From efa71c532e4778433263626bfff1a40e48f6bdb4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 9 Mar 2024 13:58:29 +0000 Subject: [PATCH 001/108] uboot-mediatek: add 'rootwait' to bootargs where needed Probing of the fitblk driver in some situations happens after Linux attempts to mount rootfs, which then fails. Always use 'rootwait' kernel parameter when using fitblk for rootfs. Signed-off-by: Daniel Golle --- .../patches/404-add-bananapi_bpi-r64_defconfigs.patch | 6 +++--- package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch | 8 ++++---- .../boot/uboot-mediatek/patches/442-add-bpi-r3-mini.patch | 4 ++-- package/boot/uboot-mediatek/patches/450-add-bpi-r4.patch | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch b/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch index 04411d79bc..6ee8729674 100644 --- a/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch +++ b/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch @@ -171,7 +171,7 @@ +ipaddr=192.168.1.1 +serverip=192.168.1.254 +loadaddr=0x48000000 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_sdmmc ; fi +bootconf=config-1#mt7622-bananapi-bpi-r64-pcie1 +bootconf_pcie=config-1#mt7622-bananapi-bpi-r64-pcie1 @@ -411,7 +411,7 @@ +serverip=192.168.1.254 +loadaddr=0x48000000 +bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootconf=config-1#mt7622-bananapi-bpi-r64-pcie1 +bootconf_pcie=config-1#mt7622-bananapi-bpi-r64-pcie1 +bootconf_sata=config-1#mt7622-bananapi-bpi-r64-sata @@ -617,7 +617,7 @@ +ipaddr=192.168.1.1 +serverip=192.168.1.254 +loadaddr=0x48000000 -+bootargs=ubi.block=0,fit root=/dev/fit0 ++bootargs=ubi.block=0,fit root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi +bootconf=config-1#mt7622-bananapi-bpi-r64-pcie1 +bootconf_pcie=config-1#mt7622-bananapi-bpi-r64-pcie1 diff --git a/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch b/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch index c48a934b74..cbcda89119 100644 --- a/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch +++ b/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch @@ -802,7 +802,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_sdmmc ; fi +bootconf=config-mt7986a-bananapi-bpi-r3 +bootconf_base=config-mt7986a-bananapi-bpi-r3 @@ -886,7 +886,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_nor ; fi +bootconf=config-mt7986a-bananapi-bpi-r3 +bootconf_base=config-mt7986a-bananapi-bpi-r3 @@ -949,7 +949,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootconf=config-mt7986a-bananapi-bpi-r3 +bootconf_base=config-mt7986a-bananapi-bpi-r3 +bootconf_nor=mt7986a-bananapi-bpi-r3-nor @@ -1025,7 +1025,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi +bootconf=config-mt7986a-bananapi-bpi-r3 +bootconf_base=config-mt7986a-bananapi-bpi-r3 diff --git a/package/boot/uboot-mediatek/patches/442-add-bpi-r3-mini.patch b/package/boot/uboot-mediatek/patches/442-add-bpi-r3-mini.patch index 667b7570ac..5409f7fa0d 100644 --- a/package/boot/uboot-mediatek/patches/442-add-bpi-r3-mini.patch +++ b/package/boot/uboot-mediatek/patches/442-add-bpi-r3-mini.patch @@ -417,7 +417,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=ubi.block=0,fit root=/dev/fit0 ++bootargs=root=ubi.block=0,fit root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi +bootconf=config-mt7986a-bananapi-bpi-r3-mini +bootdelay=0 @@ -481,7 +481,7 @@ +serverip=192.168.1.254 +loadaddr=0x46000000 +console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 -+bootargs=root=/dev/fit0 ++bootargs=root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi +bootconf=config-mt7986a-bananapi-bpi-r3-mini +bootdelay=0 diff --git a/package/boot/uboot-mediatek/patches/450-add-bpi-r4.patch b/package/boot/uboot-mediatek/patches/450-add-bpi-r4.patch index c3c21fe2f5..5fb956a2e3 100644 --- a/package/boot/uboot-mediatek/patches/450-add-bpi-r4.patch +++ b/package/boot/uboot-mediatek/patches/450-add-bpi-r4.patch @@ -555,7 +555,7 @@ +ipaddr=192.168.1.1 +serverip=192.168.1.254 +loadaddr=0x50000000 -+bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 ++bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_sdmmc ; fi +bootconf=config-mt7988a-bananapi-bpi-r4 +bootconf_sd=mt7988a-bananapi-bpi-r4-sd @@ -624,7 +624,7 @@ +ipaddr=192.168.1.1 +serverip=192.168.1.254 +loadaddr=0x50000000 -+bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 ubi.block=0,fit ++bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 rootwait ubi.block=0,fit +bootconf=config-mt7988a-bananapi-bpi-r4 +bootconf_extra=mt7988a-bananapi-bpi-r4-emmc +bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi @@ -694,7 +694,7 @@ +ipaddr=192.168.1.1 +serverip=192.168.1.254 +loadaddr=0x50000000 -+bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 ++bootargs=console=ttyS0,115200n1 pci=pcie_bus_perf root=/dev/fit0 rootwait +bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi +bootconf=config-mt7988a-bananapi-bpi-r4 +bootconf_base=config-mt7988a-bananapi-bpi-r4 From cd4de3251c1ffd572a563e6567598a875068acc2 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 9 Mar 2024 13:48:03 +0000 Subject: [PATCH 002/108] mediatek: wait for fitblk rootfs Probing of the fitblk driver in some situations happens after the kernel attempts to mount rootfs, which then fails. Always use 'rootwait' when using fitblk for rootfs. Signed-off-by: Daniel Golle --- target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts | 2 +- .../linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts | 2 +- .../linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts | 2 +- .../linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts | 2 +- target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts | 2 +- .../dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts | 1 + .../arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts | 2 +- .../patches-6.1/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts b/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts index e2b7268e85..88538c8b0a 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts @@ -13,7 +13,7 @@ chosen { rootdisk = <&ubi_rootfs>; - bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512 ubi.block=0,fit root=/dev/fit0"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512 ubi.block=0,fit root=/dev/fit0 rootwait"; }; }; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts index 5f62ed1a45..6e310d40bf 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts @@ -8,7 +8,7 @@ chosen { rootdisk = <&rootdisk>; - bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; }; }; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts index 96effb8aab..501e09a690 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts @@ -8,7 +8,7 @@ chosen { rootdisk = <&rootdisk>; - bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; }; }; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts index ec98dd262c..8c90c734d9 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts @@ -8,7 +8,7 @@ chosen { rootdisk = <&rootdisk>; - bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; }; }; diff --git a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts index 75ee0723ec..2dbb98e230 100644 --- a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts +++ b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts @@ -12,7 +12,7 @@ chosen { stdout-path = "serial0:115200n8"; - bootargs = "earlycon=uart8250,mmio32,0x11004000 root=/dev/fit0"; + bootargs = "earlycon=uart8250,mmio32,0x11004000 root=/dev/fit0 rootwait"; rootdisk = <&emmc_rootdisk>; }; }; diff --git a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts index a296c768f0..f26ab1a88e 100644 --- a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts @@ -10,6 +10,7 @@ &chosen { rootdisk = <&ubi_rootdisk>; + bootargs-append = " root=/dev/fit0 rootwait"; }; &partitions { diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts index 416958428f..f5c0c7ee2f 100644 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +++ b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts @@ -26,7 +26,7 @@ chosen { stdout-path = &uart0; - bootargs = "console=ttyS0,115200n1 loglevel=8 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0"; + bootargs = "console=ttyS0,115200n1 loglevel=8 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0 rootwait"; rootdisk-spim-nand = <&ubi_rootfs>; }; diff --git a/target/linux/mediatek/patches-6.1/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch b/target/linux/mediatek/patches-6.1/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch index 2675aa2589..f617211c9a 100644 --- a/target/linux/mediatek/patches-6.1/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch +++ b/target/linux/mediatek/patches-6.1/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch @@ -5,7 +5,7 @@ chosen { stdout-path = "serial2:115200n8"; - bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; -+ bootargs = "root=/dev/fit0 earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; ++ bootargs = "root=/dev/fit0 rootwait earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; + rootdisk-emmc = <&emmc_rootdisk>; + rootdisk-sd = <&sd_rootdisk>; }; From 330316f0566b67153f72f68635233023af4323be Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 9 Mar 2024 13:50:40 +0000 Subject: [PATCH 003/108] mediatek: linksys-e8450: improve compat warning Include a statement about having to run the installer in the sysupgrade compat warning for the Linksys E8450 (UBI). Signed-off-by: Daniel Golle --- target/linux/mediatek/image/mt7622.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index f06175041e..ab2bde0836 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -273,7 +273,7 @@ define Device/linksys_e8450-ubi ARTIFACT/preloader.bin := bl2 snand-ubi-1ddr ARTIFACT/bl31-uboot.fip := bl31-uboot linksys_e8450 DEVICE_COMPAT_VERSION := 2.0 - DEVICE_COMPAT_MESSAGE := SPI-NAND flash layout changes require bootloader update + DEVICE_COMPAT_MESSAGE := SPI-NAND flash layout changes require bootloader update. Please run the UBI installer version 1.1.0+ (unsigned) first. endef TARGET_DEVICES += linksys_e8450-ubi From 0671803bc55853fda25bb134742040d6c19c0797 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 8 Mar 2024 21:12:45 +0100 Subject: [PATCH 004/108] Revert "ipq-wifi: fix upstream board-2.bin ZTE M289F snafu" This reverts commit 75505c5ec724b9b961dcb411bac1d4b9aede3e1d. The issue has been fixed upstream. Signed-off-by: Christian Lamparter --- package/firmware/ipq-wifi/Makefile | 4 +--- target/linux/ipq40xx/image/generic.mk | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index b6c1a34bde..ed4b26af3a 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/version.mk PKG_NAME:=ipq-wifi -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git @@ -53,7 +53,6 @@ ALLWIFIBOARDS:= \ yyets_le1 \ yuncore_ax880 \ zte_mf269 \ - zte_mf289f \ zte_mf287 \ zte_mf287plus \ zyxel_nbg7815 @@ -171,7 +170,6 @@ $(eval $(call generate-ipq-wifi-package,xiaomi_ax9000,Xiaomi AX9000)) $(eval $(call generate-ipq-wifi-package,yyets_le1,YYeTs LE1)) $(eval $(call generate-ipq-wifi-package,yuncore_ax880,Yuncore AX880)) $(eval $(call generate-ipq-wifi-package,zte_mf269,ZTE MF269)) -$(eval $(call generate-ipq-wifi-package,zte_mf289f,ZTE MF289F)) $(eval $(call generate-ipq-wifi-package,zte_mf287,ZTE MF287)) $(eval $(call generate-ipq-wifi-package,zte_mf287plus,ZTE MF287Plus)) $(eval $(call generate-ipq-wifi-package,zyxel_nbg7815,Zyxel NBG7815)) diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index 8a83e27f54..3b6d111905 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -1253,7 +1253,7 @@ TARGET_DEVICES += zte_mf287pro define Device/zte_mf289f $(call Device/zte_mf28x_common) DEVICE_MODEL := MF289F - DEVICE_PACKAGES += ipq-wifi-zte_mf289f ath10k-firmware-qca9984-ct + DEVICE_PACKAGES += ath10k-firmware-qca9984-ct endef TARGET_DEVICES += zte_mf289f From 7241a91c948066e9062729a043944fd313826753 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 8 Mar 2024 21:16:44 +0100 Subject: [PATCH 005/108] firmware: intel-microcode: update to 20231114 Debian changelog: intel-microcode (3.20231114.1) unstable; urgency=medium * New upstream microcode datafile 20231114 (closes: #1055962) Mitigations for "reptar", INTEL-SA-00950 (CVE-2023-23583) Sequence of processor instructions leads to unexpected behavior for some Intel(R) Processors, may allow an authenticated user to potentially enable escalation of privilege and/or information disclosure and/or denial of service via local access. Note: "retvar" on 4th gen Xeon Scalable (sig 0x806f8 pfm 0x87), 12th gen Core mobile (sig 0x906a4 pfm 0x80), 13th gen Core desktop (sig 0xb0671 pfm 0x01) were already mitigated by a previous microcode update. * Fixes for unspecified functional issues * Updated microcodes: sig 0x000606a6, pf_mask 0x87, 2023-09-01, rev 0xd0003b9, size 299008 sig 0x000606c1, pf_mask 0x10, 2023-09-08, rev 0x1000268, size 290816 sig 0x000706e5, pf_mask 0x80, 2023-09-03, rev 0x00c2, size 113664 sig 0x000806c1, pf_mask 0x80, 2023-09-07, rev 0x00b4, size 111616 sig 0x000806c2, pf_mask 0xc2, 2023-09-07, rev 0x0034, size 98304 sig 0x000806d1, pf_mask 0xc2, 2023-09-07, rev 0x004e, size 104448 sig 0x000806f8, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0, size 572416 sig 0x000806f8, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0 sig 0x000806f7, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0 sig 0x000806f6, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0 sig 0x000806f5, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0 sig 0x000806f4, pf_mask 0x87, 2023-06-16, rev 0x2b0004d0 sig 0x000806f8, pf_mask 0x10, 2023-06-26, rev 0x2c000290, size 605184 sig 0x000806f8, pf_mask 0x10, 2023-06-26, rev 0x2c000290 sig 0x000806f6, pf_mask 0x10, 2023-06-26, rev 0x2c000290 sig 0x000806f5, pf_mask 0x10, 2023-06-26, rev 0x2c000290 sig 0x000806f4, pf_mask 0x10, 2023-06-26, rev 0x2c000290 sig 0x00090672, pf_mask 0x07, 2023-06-07, rev 0x0032, size 222208 sig 0x00090672, pf_mask 0x07, 2023-06-07, rev 0x0032 sig 0x00090675, pf_mask 0x07, 2023-06-07, rev 0x0032 sig 0x000b06f2, pf_mask 0x07, 2023-06-07, rev 0x0032 sig 0x000b06f5, pf_mask 0x07, 2023-06-07, rev 0x0032 sig 0x000906a3, pf_mask 0x80, 2023-06-07, rev 0x0430, size 220160 sig 0x000906a3, pf_mask 0x80, 2023-06-07, rev 0x0430 sig 0x000906a4, pf_mask 0x80, 2023-06-07, rev 0x0430 sig 0x000906a4, pf_mask 0x40, 2023-05-05, rev 0x0005, size 117760 sig 0x000a0671, pf_mask 0x02, 2023-09-03, rev 0x005d, size 104448 sig 0x000b0671, pf_mask 0x32, 2023-08-29, rev 0x011d, size 210944 sig 0x000b06a2, pf_mask 0xe0, 2023-08-30, rev 0x411c, size 216064 sig 0x000b06a2, pf_mask 0xe0, 2023-08-30, rev 0x411c sig 0x000b06a3, pf_mask 0xe0, 2023-08-30, rev 0x411c sig 0x000b06e0, pf_mask 0x11, 2023-06-26, rev 0x0012, size 136192 * Updated 2023-08-08 changelog entry: Mitigations for "retvar" on a few processors, refer to the 2023-11-14 entry for details. This information was disclosed in 2023-11-14. * source: update symlinks to reflect id of the latest release, 20231114 -- Henrique de Moraes Holschuh Thu, 16 Nov 2023 08:09:43 -0300 Signed-off-by: Christian Lamparter --- package/firmware/intel-microcode/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/firmware/intel-microcode/Makefile b/package/firmware/intel-microcode/Makefile index 9e87dccc12..d9b527a61f 100644 --- a/package/firmware/intel-microcode/Makefile +++ b/package/firmware/intel-microcode/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=intel-microcode -PKG_VERSION:=20230808 +PKG_VERSION:=20231114 PKG_RELEASE:=1 PKG_SOURCE:=intel-microcode_3.$(PKG_VERSION).1.tar.xz PKG_SOURCE_URL:=@DEBIAN/pool/non-free-firmware/i/intel-microcode/ -PKG_HASH:=29e77c275b3f60a691832c0844f70effbd94a4594d04af21e0c2e6e0c1ac1894 +PKG_HASH:=637ac30d3fc36eb51d3ed71909f09f7408797f4527c20e58d3b0ad4eafc20869 PKG_BUILD_DIR:=$(BUILD_DIR)/intel-microcode-3.$(PKG_VERSION).1 PKG_CPE_ID:=cpe:/a:intel:microcode From 6fa2ae30bbfa0fb0919fcd0dd3b96b185594c7f1 Mon Sep 17 00:00:00 2001 From: Sebastian Schaper Date: Sun, 11 Feb 2024 18:53:07 +0100 Subject: [PATCH 006/108] ath79: split dtsi for D-Link COVR-P2500 in preparation of adding COVR-C1200 Signed-off-by: Sebastian Schaper --- .../ath79/dts/qca9563_dlink_covr-p2500-a1.dts | 163 +---------------- .../linux/ath79/dts/qca9563_dlink_covr.dtsi | 168 ++++++++++++++++++ target/linux/ath79/image/generic.mk | 12 +- 3 files changed, 177 insertions(+), 166 deletions(-) create mode 100644 target/linux/ath79/dts/qca9563_dlink_covr.dtsi diff --git a/target/linux/ath79/dts/qca9563_dlink_covr-p2500-a1.dts b/target/linux/ath79/dts/qca9563_dlink_covr-p2500-a1.dts index 3b0c2afb50..19bf874b64 100644 --- a/target/linux/ath79/dts/qca9563_dlink_covr-p2500-a1.dts +++ b/target/linux/ath79/dts/qca9563_dlink_covr-p2500-a1.dts @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "qca956x.dtsi" - -#include -#include -#include -#include +#include "qca9563_dlink_covr.dtsi" / { compatible = "dlink,covr-p2500-a1", "qca,qca9563"; @@ -18,22 +13,6 @@ led-upgrade = &led_power_red; }; - keys { - compatible = "gpio-keys"; - - wps { - label = "wps"; - linux,code = ; - gpios = <&gpio 1 GPIO_ACTIVE_LOW>; - }; - - reset { - label = "reset"; - linux,code = ; - gpios = <&gpio 2 GPIO_ACTIVE_LOW>; - }; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -70,144 +49,4 @@ linux,default-trigger = "phy1radio"; }; }; - - virtual_flash { - compatible = "mtd-concat"; - - devices = <&fwconcat0 &fwconcat1>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x68737173>; - label = "firmware"; - reg = <0x0 0x0>; - }; - }; - }; -}; - -&spi { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0 0x40000>; - read-only; - }; - - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x10000>; - read-only; - }; - - fwconcat0: partition@50000 { - label = "fwconcat0"; - reg = <0x50000 0xe30000>; - }; - - partition@e80000 { - label = "loader"; - reg = <0xe80000 0x10000>; - read-only; - }; - - fwconcat1: partition@e90000 { - label = "fwconcat1"; - reg = <0xe90000 0x160000>; - }; - - art: partition@ff0000 { - label = "art"; - reg = <0xff0000 0x10000>; - read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - calibration_ath9k: calibration@1000 { - reg = <0x1000 0x440>; - }; - - precalibration_ath10k: pre-calibration@5000 { - reg = <0x5000 0x2f20>; - }; - }; - }; - }; - }; -}; - -&pcie { - status = "okay"; - - wifi@0,0 { - compatible = "qcom,ath10k"; - reg = <0 0 0 0 0>; - - nvmem-cells = <&precalibration_ath10k>; - nvmem-cell-names = "pre-calibration"; - }; -}; - -&gpio { - phy-reset { - gpio-hog; - gpios = <11 GPIO_ACTIVE_LOW>; - output-low; - line-name = "phy-reset"; - }; -}; - -&mdio0 { - status = "okay"; - - phy0: ethernet-phy@0 { - reg = <0>; - phy-mode = "sgmii"; - qca,mib-poll-interval = <500>; - - qca,ar8327-initvals = < - 0x04 0x00080080 /* PORT0 PAD MODE CTRL */ - 0x10 0x81000080 /* POWER_ON_STRAP */ - 0x50 0xcc35cc35 /* LED_CTRL0 */ - 0x54 0xcb37cb37 /* LED_CTRL1 */ - 0x58 0x00000000 /* LED_CTRL2 */ - 0x5c 0x00f3cf00 /* LED_CTRL3 */ - 0x7c 0x0000007e /* PORT0_STATUS */ - >; - }; -}; - -ð0 { - status = "okay"; - - pll-data = <0x03000101 0x00000101 0x00001919>; - - phy-mode = "sgmii"; - phy-handle = <&phy0>; -}; - -&wmac { - status = "okay"; - - nvmem-cells = <&calibration_ath9k>; - nvmem-cell-names = "calibration"; }; diff --git a/target/linux/ath79/dts/qca9563_dlink_covr.dtsi b/target/linux/ath79/dts/qca9563_dlink_covr.dtsi new file mode 100644 index 0000000000..5138cbc796 --- /dev/null +++ b/target/linux/ath79/dts/qca9563_dlink_covr.dtsi @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca956x.dtsi" + +#include +#include +#include +#include + +/ { + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + }; + }; + + virtual_flash { + compatible = "mtd-concat"; + + devices = <&fwconcat0 &fwconcat1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x68737173>; + label = "firmware"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +&spi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + fwconcat0: partition@50000 { + label = "fwconcat0"; + reg = <0x50000 0xe30000>; + }; + + partition@e80000 { + label = "loader"; + reg = <0xe80000 0x10000>; + read-only; + }; + + fwconcat1: partition@e90000 { + label = "fwconcat1"; + reg = <0xe90000 0x160000>; + }; + + art: partition@ff0000 { + label = "art"; + reg = <0xff0000 0x10000>; + read-only; + + compatible = "nvmem-cells"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + calibration_ath9k: calibration@1000 { + reg = <0x1000 0x440>; + }; + + precalibration_ath10k: pre-calibration@5000 { + reg = <0x5000 0x2f20>; + }; + }; + }; + }; + }; +}; + +&pcie { + status = "okay"; + + wifi0: wifi@0,0 { + compatible = "qcom,ath10k"; + reg = <0 0 0 0 0>; + + nvmem-cells = <&precalibration_ath10k>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&gpio { + phy-reset { + gpio-hog; + gpios = <11 GPIO_ACTIVE_LOW>; + output-low; + line-name = "phy-reset"; + }; +}; + +&mdio0 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "sgmii"; + qca,mib-poll-interval = <500>; + + qca,ar8327-initvals = < + 0x04 0x00080080 /* PORT0 PAD MODE CTRL */ + 0x10 0x81000080 /* POWER_ON_STRAP */ + 0x50 0xcc35cc35 /* LED_CTRL0 */ + 0x54 0xcb37cb37 /* LED_CTRL1 */ + 0x58 0x00000000 /* LED_CTRL2 */ + 0x5c 0x00f3cf00 /* LED_CTRL3 */ + 0x7c 0x0000007e /* PORT0_STATUS */ + >; + }; +}; + +ð0 { + status = "okay"; + + pll-data = <0x03000101 0x00000101 0x00001919>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; +}; + +&wmac { + status = "okay"; + + nvmem-cells = <&calibration_ath9k>; + nvmem-cell-names = "calibration"; +}; diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk index 3bdc043738..d5d8aa5592 100644 --- a/target/linux/ath79/image/generic.mk +++ b/target/linux/ath79/image/generic.mk @@ -1007,21 +1007,25 @@ define Device/devolo_magic-2-wifi endef TARGET_DEVICES += devolo_magic-2-wifi -define Device/dlink_covr-p2500-a1 +define Device/dlink_covr $(Device/loader-okli-uimage) SOC := qca9563 DEVICE_VENDOR := D-Link - DEVICE_MODEL := COVR-P2500 - DEVICE_VARIANT := A1 DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct LOADER_FLASH_OFFS := 0x050000 LOADER_KERNEL_MAGIC := 0x68737173 KERNEL := kernel-bin | append-dtb | lzma | uImage lzma -M 0x68737173 IMAGE_SIZE := 14528k - IMAGES += factory.bin recovery.bin IMAGE/recovery.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ append-rootfs | pad-rootfs | check-size | pad-to 14528k | \ append-loader-okli-uimage $(1) | pad-to 15616k +endef + +define Device/dlink_covr-p2500-a1 + $(Device/dlink_covr) + DEVICE_MODEL := COVR-P2500 + DEVICE_VARIANT := A1 + IMAGES += factory.bin recovery.bin IMAGE/factory.bin := $$(IMAGE/recovery.bin) | \ dlink-sge-image COVR-P2500 | dlink-sge-signature COVR-P2500 endef From ee69f81ca5032f13e39ce7c2515ae9c5ee0a78f1 Mon Sep 17 00:00:00 2001 From: Sebastian Schaper Date: Sun, 11 Feb 2024 18:55:43 +0100 Subject: [PATCH 007/108] ath79: add support for D-Link COVR-C1200 A1 The COVR-C1200 devices are sold as "Whole Home Mesh Wi-Fi" sets in packs of two (COVR-C1202) and three (COVR-C1203). Specifications: * QCA9563, 16 MiB flash, 128 MiB RAM, 2x3:2 802.11n * QCA9886 2x2:2 801.11ac Wave 2 * AR8337, 2 Gigabit ports (1: WAN; 2: LAN) * USB Type-C power connector (5V, 3A) Installation COVR Point A: * In factory reset state: OEM Web UI is at 192.168.0.50 no DHCP, skip wizard by directly accessing: http://192.168.0.50/UpdateFirmware_Simple.html * After completing setup wizard: Web UI is at 192.168.0.1 DHCP enabled, login with empty password * Flash factory.bin * Perform a factory reset to restore OpenWrt UCI defaults Installation COVR Points B: * OEM Web UI is at 192.168.0.50, no DHCP, empty password * Flash factory.bin * Perform a factory reset to restore OpenWrt UCI defaults Recovery: * Keep reset button pressed during power on * Recovery Web UI is at 192.168.0.50, no DHCP * Flash factory.bin used to work best with Chromium-based browsers or curl: curl -F firmware=@factory.bin \ http://192.168.0.50/upgrade.cgi since this fails to work on modern Linux systems, there is also a script dlink_recovery_upload.py Signed-off-by: Sebastian Schaper --- .../ath79/dts/qca9563_dlink_covr-c1200-a1.dts | 40 +++++++++++++++++++ .../generic/base-files/etc/board.d/02_network | 9 +++++ .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 1 + target/linux/ath79/image/generic.mk | 10 +++++ 4 files changed, 60 insertions(+) create mode 100644 target/linux/ath79/dts/qca9563_dlink_covr-c1200-a1.dts diff --git a/target/linux/ath79/dts/qca9563_dlink_covr-c1200-a1.dts b/target/linux/ath79/dts/qca9563_dlink_covr-c1200-a1.dts new file mode 100644 index 0000000000..b4f0bb3b64 --- /dev/null +++ b/target/linux/ath79/dts/qca9563_dlink_covr-c1200-a1.dts @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca9563_dlink_covr.dtsi" + +/ { + compatible = "dlink,covr-c1200-a1", "qca,qca9563"; + model = "D-Link COVR-C1200 A1"; + + aliases { + led-boot = &led_power_orange; + led-failsafe = &led_power_red; + led-running = &led_power_white; + led-upgrade = &led_power_red; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&jtag_disable_pins>; + + led_power_red: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 6 GPIO_ACTIVE_HIGH>; + }; + + led_power_white: power_white { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; + }; + + led_power_orange: power_orange { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index 4e08860cfa..6c1cb86235 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -292,6 +292,10 @@ ath79_setup_interfaces() ucidef_add_switch "switch0" \ "0@eth0" "2:wan" "3:lan" "4:lan" ;; + dlink,covr-c1200-a1) + ucidef_add_switch "switch0" \ + "0@eth0" "1:wan" "2:lan" + ;; dlink,covr-p2500-a1) ucidef_add_switch "switch0" \ "0@eth0" "1:lan" "2:lan" "3:wan" "4:plc" @@ -644,6 +648,11 @@ ath79_setup_macs() devolo,magic-2-wifi) label_mac=$(macaddr_add "$(mtd_get_mac_binary art 0x1002)" 3) ;; + dlink,covr-c1200-a1) + lan_mac=$(mtd_get_mac_ascii art "protest_lan_mac") + wan_mac=$(mtd_get_mac_ascii art "protest_wan_mac") + label_mac=$lan_mac + ;; dlink,covr-p2500-a1) lan_mac=$(mtd_get_mac_ascii art "protest_lan_mac") wan_mac=$(mtd_get_mac_ascii art "protest_lan_mac") diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ath79/generic/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac index 9574d8a17d..b90e382223 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -17,6 +17,7 @@ case "$board" in adtran,bsap1840) macaddr_add "$(mtd_get_mac_binary 'Board data' 2)" $(($PHYNBR * 8 + 1)) > /sys${DEVPATH}/macaddress ;; + dlink,covr-c1200-a1|\ dlink,covr-p2500-a1) [ "$PHYNBR" -eq 0 ] && \ mtd_get_mac_ascii art "protest_ath1_mac" > /sys${DEVPATH}/macaddress diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk index d5d8aa5592..e7960efbaa 100644 --- a/target/linux/ath79/image/generic.mk +++ b/target/linux/ath79/image/generic.mk @@ -1021,6 +1021,16 @@ define Device/dlink_covr append-loader-okli-uimage $(1) | pad-to 15616k endef +define Device/dlink_covr-c1200-a1 + $(Device/dlink_covr) + DEVICE_MODEL := COVR-C1200 + DEVICE_VARIANT := A1 + IMAGES += factory.bin + IMAGE/factory.bin := $$(IMAGE/recovery.bin) | \ + dlink-sge-signature COVR-C1200 | dlink-sge-image COVR-C1200 +endef +TARGET_DEVICES += dlink_covr-c1200-a1 + define Device/dlink_covr-p2500-a1 $(Device/dlink_covr) DEVICE_MODEL := COVR-P2500 From 860dd27617812bc25627d716436b88cf3f1cbe9d Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Thu, 22 Feb 2024 09:56:36 +0800 Subject: [PATCH 008/108] firmware: add firmware package for Realtek RTL8188FU Realtek RTL8188F is an 802.11n 1x1 USB Wi-Fi adapter. It has been supported by the upstream rtl8xxxu driver since Linux 6.2 kernel. Signed-off-by: Shiji Yang --- package/firmware/linux-firmware/realtek.mk | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/package/firmware/linux-firmware/realtek.mk b/package/firmware/linux-firmware/realtek.mk index b4880b6a7f..81e91ba085 100644 --- a/package/firmware/linux-firmware/realtek.mk +++ b/package/firmware/linux-firmware/realtek.mk @@ -29,6 +29,15 @@ define Package/rtl8188eu-firmware/install endef $(eval $(call BuildPackage,rtl8188eu-firmware)) +Package/rtl8188fu-firmware = $(call Package/firmware-default,RealTek RTL8188FU firmware) +define Package/rtl8188fu-firmware/install + $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi + $(CP) \ + $(PKG_BUILD_DIR)/rtlwifi/rtl8188fufw.bin \ + $(1)/lib/firmware/rtlwifi +endef +$(eval $(call BuildPackage,rtl8188fu-firmware)) + Package/rtl8192ce-firmware = $(call Package/firmware-default,RealTek RTL8192CE firmware) define Package/rtl8192ce-firmware/install $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi From 97f542238a23a1c8461b40dfb26d9213826d8e78 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Fri, 23 Feb 2024 05:36:50 +0800 Subject: [PATCH 009/108] mac80211: rtl8xxxu: sync with linux-next 20240229 Backporting upstream patches to improve RTL8188F support. Signed-off-by: Shiji Yang --- ...move-assignment-of-priv-vif-in-rtl8x.patch | 27 ++ ...epare-supporting-two-virtual-interfa.patch | 61 +++ ...pport-setting-linktype-for-both-inte.patch | 102 +++++ ...88e-convert-usage-of-priv-vif-to-pri.patch | 28 ++ ...pport-setting-mac-address-register-f.patch | 72 +++ ...tend-wifi-connected-check-to-both-in.patch | 75 ++++ ...tend-check-for-matching-bssid-to-bot.patch | 70 +++ ...n-t-parse-CFO-if-both-interfaces-are.patch | 51 +++ ...pport-setting-bssid-register-for-mul.patch | 67 +++ ...pport-multiple-interfaces-in-set_aif.patch | 44 ++ ...pport-multiple-interfaces-in-update_.patch | 28 ++ ...pport-multiple-interfaces-in-configu.patch | 33 ++ ...pport-multiple-interfaces-in-watchdo.patch | 66 +++ ...pport-multiple-interfaces-in-add-rem.patch | 137 ++++++ ...pport-multiple-interfaces-in-bss_inf.patch | 57 +++ ...pport-multiple-interface-in-start_ap.patch | 32 ++ ...ifi-rtl8xxxu-add-macids-for-STA-mode.patch | 82 ++++ ...fi-rtl8xxxu-remove-obsolete-priv-vif.patch | 49 +++ ...xu-add-hw-crypto-support-for-AP-mode.patch | 226 ++++++++++ ...ke-supporting-AP-mode-only-on-port-0.patch | 130 ++++++ ...clare-concurrent-mode-support-for-81.patch | 76 ++++ ...xu-Fix-LED-control-code-of-RTL8192FU.patch | 98 +++++ ...xxxu-Fix-off-by-one-initial-RTS-rate.patch | 36 ++ ...add-cancel_work_sync-for-c2hcmd_work.patch | 27 ++ ...l8xxxu-enable-channel-switch-support.patch | 100 +++++ ...nvert-EN_DESC_ID-of-TX-descriptor-to.patch | 31 ++ ...ke-instances-of-iface-limit-and-comb.patch | 36 ++ ...d-missing-number-of-sec-cam-entries-.patch | 100 +++++ ...6.9-wifi-rtl8xxxu-fix-error-messages.patch | 37 ++ ...fi-rtl8xxxu-Add-TP-Link-TL-WN823N-V2.patch | 36 ++ ...fi-rtl8xxxu-update-rate-mask-per-sta.patch | 411 ++++++++++++++++++ ...heck-vif-before-using-in-rtl8xxxu_tx.patch | 40 ++ ...x-mixed-declarations-and-code-warnin.patch | 34 ++ 33 files changed, 2499 insertions(+) create mode 100644 package/kernel/mac80211/patches/rtl/001-01-v6.9-wifi-rtl8xxxu-remove-assignment-of-priv-vif-in-rtl8x.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-02-v6.9-wifi-rtl8xxxu-prepare-supporting-two-virtual-interfa.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-03-v6.9-wifi-rtl8xxxu-support-setting-linktype-for-both-inte.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-04-v6.9-wifi-rtl8xxxu-8188e-convert-usage-of-priv-vif-to-pri.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-05-v6.9-wifi-rtl8xxxu-support-setting-mac-address-register-f.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-06-v6.9-wifi-rtl8xxxu-extend-wifi-connected-check-to-both-in.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-07-v6.9-wifi-rtl8xxxu-extend-check-for-matching-bssid-to-bot.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-08-v6.9-wifi-rtl8xxxu-don-t-parse-CFO-if-both-interfaces-are.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-09-v6.9-wifi-rtl8xxxu-support-setting-bssid-register-for-mul.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-10-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-set_aif.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-11-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-update_.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-12-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-configu.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-13-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-watchdo.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-14-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-add-rem.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-15-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-bss_inf.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-16-v6.9-wifi-rtl8xxxu-support-multiple-interface-in-start_ap.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-17-v6.9-wifi-rtl8xxxu-add-macids-for-STA-mode.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-18-v6.9-wifi-rtl8xxxu-remove-obsolete-priv-vif.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-19-v6.9-wifi-rtl8xxxu-add-hw-crypto-support-for-AP-mode.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-20-v6.9-wifi-rtl8xxxu-make-supporting-AP-mode-only-on-port-0.patch create mode 100644 package/kernel/mac80211/patches/rtl/001-21-v6.9-wifi-rtl8xxxu-declare-concurrent-mode-support-for-81.patch create mode 100644 package/kernel/mac80211/patches/rtl/002-01-v6.9-wifi-rtl8xxxu-Fix-LED-control-code-of-RTL8192FU.patch create mode 100644 package/kernel/mac80211/patches/rtl/002-02-v6.9-wifi-rtl8xxxu-Fix-off-by-one-initial-RTS-rate.patch create mode 100644 package/kernel/mac80211/patches/rtl/003-01-v6.9-wifi-rtl8xxxu-add-cancel_work_sync-for-c2hcmd_work.patch create mode 100644 package/kernel/mac80211/patches/rtl/003-02-v6.9-wifi-rtl8xxxu-enable-channel-switch-support.patch create mode 100644 package/kernel/mac80211/patches/rtl/004-01-v6.9-wifi-rtl8xxxu-convert-EN_DESC_ID-of-TX-descriptor-to.patch create mode 100644 package/kernel/mac80211/patches/rtl/004-02-v6.9-wifi-rtl8xxxu-make-instances-of-iface-limit-and-comb.patch create mode 100644 package/kernel/mac80211/patches/rtl/005-v6.9-wifi-rtl8xxxu-add-missing-number-of-sec-cam-entries-.patch create mode 100644 package/kernel/mac80211/patches/rtl/006-v6.9-wifi-rtl8xxxu-fix-error-messages.patch create mode 100644 package/kernel/mac80211/patches/rtl/007-v6.9-wifi-rtl8xxxu-Add-TP-Link-TL-WN823N-V2.patch create mode 100644 package/kernel/mac80211/patches/rtl/008-v6.9-wifi-rtl8xxxu-update-rate-mask-per-sta.patch create mode 100644 package/kernel/mac80211/patches/rtl/009-v6.9-wifi-rtl8xxxu-check-vif-before-using-in-rtl8xxxu_tx.patch create mode 100644 package/kernel/mac80211/patches/rtl/010-v6.9-wifi-rtl8xxxu-fix-mixed-declarations-and-code-warnin.patch diff --git a/package/kernel/mac80211/patches/rtl/001-01-v6.9-wifi-rtl8xxxu-remove-assignment-of-priv-vif-in-rtl8x.patch b/package/kernel/mac80211/patches/rtl/001-01-v6.9-wifi-rtl8xxxu-remove-assignment-of-priv-vif-in-rtl8x.patch new file mode 100644 index 0000000000..e0a01a8120 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-01-v6.9-wifi-rtl8xxxu-remove-assignment-of-priv-vif-in-rtl8x.patch @@ -0,0 +1,27 @@ +From d55cb6d8a99441aff55cb9ce663a07f7f1667e83 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:22 +0100 +Subject: [PATCH 01/21] wifi: rtl8xxxu: remove assignment of priv->vif in + rtl8xxxu_bss_info_changed() + +priv->vif gets already set in rtl8xxxu_add_interface, there is no need +to set it also in rtl8xxxu_bss_info_changed(). + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-2-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5004,7 +5004,6 @@ rtl8xxxu_bss_info_changed(struct ieee802 + + rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw); + +- priv->vif = vif; + priv->rssi_level = RTL8XXXU_RATR_STA_INIT; + + priv->fops->update_rate_mask(priv, ramask, 0, sgi, diff --git a/package/kernel/mac80211/patches/rtl/001-02-v6.9-wifi-rtl8xxxu-prepare-supporting-two-virtual-interfa.patch b/package/kernel/mac80211/patches/rtl/001-02-v6.9-wifi-rtl8xxxu-prepare-supporting-two-virtual-interfa.patch new file mode 100644 index 0000000000..b1948bb7c2 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-02-v6.9-wifi-rtl8xxxu-prepare-supporting-two-virtual-interfa.patch @@ -0,0 +1,61 @@ +From 2bbd7d584046038ce655e476628bb15e1460fac6 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:23 +0100 +Subject: [PATCH 02/21] wifi: rtl8xxxu: prepare supporting two virtual + interfaces + +To prepare for concurrent mode, add an array ("vifs") to rtl8xxxu_priv +to keep track of both interfaces. + +Keep the old priv->vif as long there are still users of it and let +priv->vifs[0] point to the same location. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-3-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 ++ + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1897,6 +1897,8 @@ struct rtl8xxxu_priv { + * is supported and no iface_combinations are provided. + */ + struct ieee80211_vif *vif; ++ ++ struct ieee80211_vif *vifs[2]; + struct delayed_work ra_watchdog; + struct work_struct c2hcmd_work; + struct sk_buff_head c2hcmd_queue; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6569,10 +6569,12 @@ static int rtl8xxxu_add_interface(struct + int ret; + u8 val8; + +- if (!priv->vif) ++ if (!priv->vif) { + priv->vif = vif; +- else ++ priv->vifs[0] = vif; ++ } else { + return -EOPNOTSUPP; ++ } + + switch (vif->type) { + case NL80211_IFTYPE_STATION: +@@ -6622,8 +6624,10 @@ static void rtl8xxxu_remove_interface(st + + dev_dbg(&priv->udev->dev, "%s\n", __func__); + +- if (priv->vif) ++ if (priv->vif) { + priv->vif = NULL; ++ priv->vifs[0] = NULL; ++ } + } + + static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) diff --git a/package/kernel/mac80211/patches/rtl/001-03-v6.9-wifi-rtl8xxxu-support-setting-linktype-for-both-inte.patch b/package/kernel/mac80211/patches/rtl/001-03-v6.9-wifi-rtl8xxxu-support-setting-linktype-for-both-inte.patch new file mode 100644 index 0000000000..f473fad118 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-03-v6.9-wifi-rtl8xxxu-support-setting-linktype-for-both-inte.patch @@ -0,0 +1,102 @@ +From 7f444692cde83c1455682c2d0d2c9a666422b867 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:24 +0100 +Subject: [PATCH 03/21] wifi: rtl8xxxu: support setting linktype for both + interfaces + +To prepare for concurrent mode, enhance the set_linktype function to be +able to set the linktype in the MSR register for both hardware ports. + +Until the users of set_linktype can handle multiple interfaces, use +port_num = 0. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-4-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 37 +++++++++++-------- + 1 file changed, 22 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -1633,33 +1633,41 @@ rtl8xxxu_gen1_set_tx_power(struct rtl8xx + } + + static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, +- enum nl80211_iftype linktype) ++ enum nl80211_iftype linktype, int port_num) + { +- u8 val8; +- +- val8 = rtl8xxxu_read8(priv, REG_MSR); +- val8 &= ~MSR_LINKTYPE_MASK; ++ u8 val8, type; + + switch (linktype) { + case NL80211_IFTYPE_UNSPECIFIED: +- val8 |= MSR_LINKTYPE_NONE; ++ type = MSR_LINKTYPE_NONE; + break; + case NL80211_IFTYPE_ADHOC: +- val8 |= MSR_LINKTYPE_ADHOC; ++ type = MSR_LINKTYPE_ADHOC; + break; + case NL80211_IFTYPE_STATION: +- val8 |= MSR_LINKTYPE_STATION; ++ type = MSR_LINKTYPE_STATION; + break; + case NL80211_IFTYPE_AP: +- val8 |= MSR_LINKTYPE_AP; ++ type = MSR_LINKTYPE_AP; + break; + default: +- goto out; ++ return; ++ } ++ ++ switch (port_num) { ++ case 0: ++ val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x0c; ++ val8 |= type; ++ break; ++ case 1: ++ val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x03; ++ val8 |= type << 2; ++ break; ++ default: ++ return; + } + + rtl8xxxu_write8(priv, REG_MSR, val8); +-out: +- return; + } + + static void +@@ -4236,7 +4244,6 @@ static int rtl8xxxu_init_device(struct i + } + + rtl8xxxu_set_mac(priv); +- rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION); + + /* + * Configure initial WMAC settings +@@ -4964,7 +4971,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + if (changed & BSS_CHANGED_ASSOC) { + dev_dbg(dev, "Changed ASSOC: %i!\n", vif->cfg.assoc); + +- rtl8xxxu_set_linktype(priv, vif->type); ++ rtl8xxxu_set_linktype(priv, vif->type, 0); + + if (vif->cfg.assoc) { + u32 ramask; +@@ -6610,7 +6617,7 @@ static int rtl8xxxu_add_interface(struct + ret = -EOPNOTSUPP; + } + +- rtl8xxxu_set_linktype(priv, vif->type); ++ rtl8xxxu_set_linktype(priv, vif->type, 0); + ether_addr_copy(priv->mac_addr, vif->addr); + rtl8xxxu_set_mac(priv); + diff --git a/package/kernel/mac80211/patches/rtl/001-04-v6.9-wifi-rtl8xxxu-8188e-convert-usage-of-priv-vif-to-pri.patch b/package/kernel/mac80211/patches/rtl/001-04-v6.9-wifi-rtl8xxxu-8188e-convert-usage-of-priv-vif-to-pri.patch new file mode 100644 index 0000000000..160a71adc7 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-04-v6.9-wifi-rtl8xxxu-8188e-convert-usage-of-priv-vif-to-pri.patch @@ -0,0 +1,28 @@ +From a047e46a7b98de384a158b25a05dc09aa7d70c5f Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:25 +0100 +Subject: [PATCH 04/21] wifi: rtl8xxxu: 8188e: convert usage of priv->vif to + priv->vifs[0] + +The driver currently does not support AP or concurrent mode for 8188e, +so just use priv->vifs[0] instead of priv->vif for now. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-5-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c +@@ -1699,7 +1699,7 @@ void rtl8188e_handle_ra_tx_report2(struc + /* We only use macid 0, so only the first item is relevant. + * AP mode will use more of them if it's ever implemented. + */ +- if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION) ++ if (!priv->vifs[0] || priv->vifs[0]->type == NL80211_IFTYPE_STATION) + items = 1; + + for (macid = 0; macid < items; macid++) { diff --git a/package/kernel/mac80211/patches/rtl/001-05-v6.9-wifi-rtl8xxxu-support-setting-mac-address-register-f.patch b/package/kernel/mac80211/patches/rtl/001-05-v6.9-wifi-rtl8xxxu-support-setting-mac-address-register-f.patch new file mode 100644 index 0000000000..c3e3fea450 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-05-v6.9-wifi-rtl8xxxu-support-setting-mac-address-register-f.patch @@ -0,0 +1,72 @@ +From 00add60cad3c9690ac0f9d4f6685f96ccd607670 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:26 +0100 +Subject: [PATCH 05/21] wifi: rtl8xxxu: support setting mac address register + for both interfaces + +To prepare for concurrent mode, enhance rtl8xxxu_set_mac() to write the +mac address of the respective interface to REG_MACID or REG_MACID1. + +Remove the call to rtl8xxxu_set_mac() from the init function as we set +it in rtl8xxxu_add_interface() later anyway. + +Until rtl8xxxu_add_interface() can handle both interfaces, call +rtl8xxxu_set_mac() with port_num = 0. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-6-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 20 +++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -3580,15 +3580,25 @@ void rtl8723a_phy_lc_calibrate(struct rt + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); + } + +-static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv) ++static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv, int port_num) + { + int i; + u16 reg; + +- reg = REG_MACID; ++ switch (port_num) { ++ case 0: ++ reg = REG_MACID; ++ break; ++ case 1: ++ reg = REG_MACID1; ++ break; ++ default: ++ WARN_ONCE("%s: invalid port_num\n", __func__); ++ return -EINVAL; ++ } + + for (i = 0; i < ETH_ALEN; i++) +- rtl8xxxu_write8(priv, reg + i, priv->mac_addr[i]); ++ rtl8xxxu_write8(priv, reg + i, priv->vifs[port_num]->addr[i]); + + return 0; + } +@@ -4243,8 +4253,6 @@ static int rtl8xxxu_init_device(struct i + rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + } + +- rtl8xxxu_set_mac(priv); +- + /* + * Configure initial WMAC settings + */ +@@ -6619,7 +6627,7 @@ static int rtl8xxxu_add_interface(struct + + rtl8xxxu_set_linktype(priv, vif->type, 0); + ether_addr_copy(priv->mac_addr, vif->addr); +- rtl8xxxu_set_mac(priv); ++ rtl8xxxu_set_mac(priv, 0); + + return ret; + } diff --git a/package/kernel/mac80211/patches/rtl/001-06-v6.9-wifi-rtl8xxxu-extend-wifi-connected-check-to-both-in.patch b/package/kernel/mac80211/patches/rtl/001-06-v6.9-wifi-rtl8xxxu-extend-wifi-connected-check-to-both-in.patch new file mode 100644 index 0000000000..70879f861f --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-06-v6.9-wifi-rtl8xxxu-extend-wifi-connected-check-to-both-in.patch @@ -0,0 +1,75 @@ +From 9aa776209ca31695bead52674ad943848ccc97d5 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:27 +0100 +Subject: [PATCH 06/21] wifi: rtl8xxxu: extend wifi connected check to both + interfaces + +There are multiple places in the code where the current connection +status of wifi is checked. The driver will support two interfaces soon +and either one of them (or both) could be connected. + +Convert all uses of (vif && vif->cfg.assoc) to a new helper +function rtl8xxxu_is_assoc() which checks both interfaces. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-7-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 20 +++++++++---------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6043,18 +6043,20 @@ void rtl8723bu_update_bt_link_info(struc + btcoex->bt_busy = false; + } + ++static inline bool rtl8xxxu_is_assoc(struct rtl8xxxu_priv *priv) ++{ ++ return (priv->vifs[0] && priv->vifs[0]->cfg.assoc) || ++ (priv->vifs[1] && priv->vifs[1]->cfg.assoc); ++} ++ + static + void rtl8723bu_handle_bt_inquiry(struct rtl8xxxu_priv *priv) + { +- struct ieee80211_vif *vif; + struct rtl8xxxu_btcoex *btcoex; +- bool wifi_connected; + +- vif = priv->vif; + btcoex = &priv->bt_coex; +- wifi_connected = (vif && vif->cfg.assoc); + +- if (!wifi_connected) { ++ if (!rtl8xxxu_is_assoc(priv)) { + rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0); + rtl8723bu_set_coex_with_type(priv, 0); + } else if (btcoex->has_sco || btcoex->has_hid || btcoex->has_a2dp) { +@@ -6072,15 +6074,11 @@ void rtl8723bu_handle_bt_inquiry(struct + static + void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv) + { +- struct ieee80211_vif *vif; + struct rtl8xxxu_btcoex *btcoex; +- bool wifi_connected; + +- vif = priv->vif; + btcoex = &priv->bt_coex; +- wifi_connected = (vif && vif->cfg.assoc); + +- if (wifi_connected) { ++ if (rtl8xxxu_is_assoc(priv)) { + u32 val32 = 0; + u32 high_prio_tx = 0, high_prio_rx = 0; + +@@ -7103,7 +7101,7 @@ static void rtl8xxxu_track_cfo(struct rt + int cfo_khz_a, cfo_khz_b, cfo_average; + int crystal_cap; + +- if (!priv->vif || !priv->vif->cfg.assoc) { ++ if (!rtl8xxxu_is_assoc(priv)) { + /* Reset */ + cfo->adjust = true; + diff --git a/package/kernel/mac80211/patches/rtl/001-07-v6.9-wifi-rtl8xxxu-extend-check-for-matching-bssid-to-bot.patch b/package/kernel/mac80211/patches/rtl/001-07-v6.9-wifi-rtl8xxxu-extend-check-for-matching-bssid-to-bot.patch new file mode 100644 index 0000000000..2c53aded28 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-07-v6.9-wifi-rtl8xxxu-extend-check-for-matching-bssid-to-bot.patch @@ -0,0 +1,70 @@ +From 80fd8687db41b1e04f78c37137d090f2165cca6e Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:28 +0100 +Subject: [PATCH 07/21] wifi: rtl8xxxu: extend check for matching bssid to both + interfaces + +The driver will support two interfaces soon, which both can be in +station mode, so extend the check, whether cfo information should be +parsed, to cover both interfaces. + +For better code readability put the lines with priv->vifs[port_num] in a +separate function. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-8-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 22 ++++++++++++------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5706,6 +5706,16 @@ static void rtl8xxxu_update_beacon_work_ + rtl8xxxu_send_beacon_frame(hw, vif); + } + ++static inline bool rtl8xxxu_is_packet_match_bssid(struct rtl8xxxu_priv *priv, ++ struct ieee80211_hdr *hdr, ++ int port_num) ++{ ++ return priv->vifs[port_num] && ++ priv->vifs[port_num]->type == NL80211_IFTYPE_STATION && ++ priv->vifs[port_num]->cfg.assoc && ++ ether_addr_equal(priv->vifs[port_num]->bss_conf.bssid, hdr->addr2); ++} ++ + void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv, + struct ieee80211_rx_status *rx_status, + struct rtl8723au_phy_stats *phy_stats, +@@ -5722,12 +5732,10 @@ void rtl8723au_rx_parse_phystats(struct + rx_status->signal = priv->fops->cck_rssi(priv, phy_stats); + } else { + bool parse_cfo = priv->fops->set_crystal_cap && +- priv->vif && +- priv->vif->type == NL80211_IFTYPE_STATION && +- priv->vif->cfg.assoc && + !crc_icv_err && + !ieee80211_is_ctl(hdr->frame_control) && +- ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2); ++ (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) || ++ rtl8xxxu_is_packet_match_bssid(priv, hdr, 1)); + + if (parse_cfo) { + priv->cfo_tracking.cfo_tail[0] = phy_stats->path_cfotail[0]; +@@ -5762,12 +5770,10 @@ static void jaguar2_rx_parse_phystats_ty + bool crc_icv_err) + { + bool parse_cfo = priv->fops->set_crystal_cap && +- priv->vif && +- priv->vif->type == NL80211_IFTYPE_STATION && +- priv->vif->cfg.assoc && + !crc_icv_err && + !ieee80211_is_ctl(hdr->frame_control) && +- ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2); ++ (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) || ++ rtl8xxxu_is_packet_match_bssid(priv, hdr, 1)); + u8 pwdb_max = 0; + int rx_path; + diff --git a/package/kernel/mac80211/patches/rtl/001-08-v6.9-wifi-rtl8xxxu-don-t-parse-CFO-if-both-interfaces-are.patch b/package/kernel/mac80211/patches/rtl/001-08-v6.9-wifi-rtl8xxxu-don-t-parse-CFO-if-both-interfaces-are.patch new file mode 100644 index 0000000000..bad1c3cb27 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-08-v6.9-wifi-rtl8xxxu-don-t-parse-CFO-if-both-interfaces-are.patch @@ -0,0 +1,51 @@ +From f86dd8eaf8da84ee5b803d90b8c311d7e2725d0b Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:29 +0100 +Subject: [PATCH 08/21] wifi: rtl8xxxu: don't parse CFO, if both interfaces are + connected in STA mode + +If both interfaces are in STATION mode and both are connected to an AP, +there might be conflicting CFO values for the two connections. Ignore +the CFO information in this case. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-9-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5716,6 +5716,14 @@ static inline bool rtl8xxxu_is_packet_ma + ether_addr_equal(priv->vifs[port_num]->bss_conf.bssid, hdr->addr2); + } + ++static inline bool rtl8xxxu_is_sta_sta(struct rtl8xxxu_priv *priv) ++{ ++ return (priv->vifs[0] && priv->vifs[0]->cfg.assoc && ++ priv->vifs[0]->type == NL80211_IFTYPE_STATION) && ++ (priv->vifs[1] && priv->vifs[1]->cfg.assoc && ++ priv->vifs[1]->type == NL80211_IFTYPE_STATION); ++} ++ + void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv, + struct ieee80211_rx_status *rx_status, + struct rtl8723au_phy_stats *phy_stats, +@@ -5734,6 +5742,7 @@ void rtl8723au_rx_parse_phystats(struct + bool parse_cfo = priv->fops->set_crystal_cap && + !crc_icv_err && + !ieee80211_is_ctl(hdr->frame_control) && ++ !rtl8xxxu_is_sta_sta(priv) && + (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) || + rtl8xxxu_is_packet_match_bssid(priv, hdr, 1)); + +@@ -5772,6 +5781,7 @@ static void jaguar2_rx_parse_phystats_ty + bool parse_cfo = priv->fops->set_crystal_cap && + !crc_icv_err && + !ieee80211_is_ctl(hdr->frame_control) && ++ !rtl8xxxu_is_sta_sta(priv) && + (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) || + rtl8xxxu_is_packet_match_bssid(priv, hdr, 1)); + u8 pwdb_max = 0; diff --git a/package/kernel/mac80211/patches/rtl/001-09-v6.9-wifi-rtl8xxxu-support-setting-bssid-register-for-mul.patch b/package/kernel/mac80211/patches/rtl/001-09-v6.9-wifi-rtl8xxxu-support-setting-bssid-register-for-mul.patch new file mode 100644 index 0000000000..def70343b0 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-09-v6.9-wifi-rtl8xxxu-support-setting-bssid-register-for-mul.patch @@ -0,0 +1,67 @@ +From 3ff7a05996f901a7a10068b42e9dc8435f908a4c Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:30 +0100 +Subject: [PATCH 09/21] wifi: rtl8xxxu: support setting bssid register for + multiple interfaces + +To prepare for concurrent mode, enhance rtl8xxxu_set_bssid() to write the +BSSID of the respective interface to REG_BSSID or REG_BSSID1. + +Like done with rtl8xxxu_set_mac(), call rtl8xxxu_set_bssid() with +port_num = 0, until the callers also support multiple interfaces. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-10-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -3603,14 +3603,24 @@ static int rtl8xxxu_set_mac(struct rtl8x + return 0; + } + +-static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid) ++static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid, int port_num) + { + int i; + u16 reg; + + dev_dbg(&priv->udev->dev, "%s: (%pM)\n", __func__, bssid); + +- reg = REG_BSSID; ++ switch (port_num) { ++ case 0: ++ reg = REG_BSSID; ++ break; ++ case 1: ++ reg = REG_BSSID1; ++ break; ++ default: ++ WARN_ONCE("%s: invalid port_num\n", __func__); ++ return -EINVAL; ++ } + + for (i = 0; i < ETH_ALEN; i++) + rtl8xxxu_write8(priv, reg + i, bssid[i]); +@@ -5068,7 +5078,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + + if (changed & BSS_CHANGED_BSSID) { + dev_dbg(dev, "Changed BSSID!\n"); +- rtl8xxxu_set_bssid(priv, bss_conf->bssid); ++ rtl8xxxu_set_bssid(priv, bss_conf->bssid, 0); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { +@@ -5097,7 +5107,7 @@ static int rtl8xxxu_start_ap(struct ieee + struct device *dev = &priv->udev->dev; + + dev_dbg(dev, "Start AP mode\n"); +- rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid); ++ rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, 0); + rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int); + priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true); + diff --git a/package/kernel/mac80211/patches/rtl/001-10-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-set_aif.patch b/package/kernel/mac80211/patches/rtl/001-10-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-set_aif.patch new file mode 100644 index 0000000000..b8cb66dd92 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-10-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-set_aif.patch @@ -0,0 +1,44 @@ +From 43532c050f8eec4056a21978fdb5b958e1477553 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:31 +0100 +Subject: [PATCH 10/21] wifi: rtl8xxxu: support multiple interfaces in + set_aifs() + +In concurrent mode supported by this driver, both interfaces will use +the same channel and same wireless mode. +It is therefore possible to get the wireless mode by checking the first +connected interface. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-11-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4913,14 +4913,20 @@ static void rtl8xxxu_set_aifs(struct rtl + u8 aifs, aifsn, sifs; + int i; + +- if (priv->vif) { ++ for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) { ++ if (!priv->vifs[i]) ++ continue; ++ + struct ieee80211_sta *sta; + + rcu_read_lock(); +- sta = ieee80211_find_sta(priv->vif, priv->vif->bss_conf.bssid); ++ sta = ieee80211_find_sta(priv->vifs[i], priv->vifs[i]->bss_conf.bssid); + if (sta) + wireless_mode = rtl8xxxu_wireless_mode(priv->hw, sta); + rcu_read_unlock(); ++ ++ if (wireless_mode) ++ break; + } + + if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ || diff --git a/package/kernel/mac80211/patches/rtl/001-11-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-update_.patch b/package/kernel/mac80211/patches/rtl/001-11-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-update_.patch new file mode 100644 index 0000000000..63960e7ae7 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-11-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-update_.patch @@ -0,0 +1,28 @@ +From 05b22e9b7d84253f765cde01cb09d144094b61c9 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:32 +0100 +Subject: [PATCH 11/21] wifi: rtl8xxxu: support multiple interfaces in + update_beacon_work_callback() + +As we only want to support AP mode/sending beacons on port 0, it is +enough to replace priv->vif with priv->vifs[0]. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-12-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5712,7 +5712,7 @@ static void rtl8xxxu_update_beacon_work_ + struct rtl8xxxu_priv *priv = + container_of(work, struct rtl8xxxu_priv, update_beacon_work); + struct ieee80211_hw *hw = priv->hw; +- struct ieee80211_vif *vif = priv->vif; ++ struct ieee80211_vif *vif = priv->vifs[0]; + + if (!vif) { + WARN_ONCE(true, "no vif to update beacon\n"); diff --git a/package/kernel/mac80211/patches/rtl/001-12-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-configu.patch b/package/kernel/mac80211/patches/rtl/001-12-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-configu.patch new file mode 100644 index 0000000000..707236b7dc --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-12-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-configu.patch @@ -0,0 +1,33 @@ +From 6b76638287055791e74b32c401a39ea1b91e7158 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:33 +0100 +Subject: [PATCH 12/21] wifi: rtl8xxxu: support multiple interfaces in + configure_filter() + +As we only want to support AP mode/sending beacons on port 0, change +from priv->vif to priv->vifs[0] in the check for AP mode. +Additionally, if we are in AP mode, don't filter RX beacon and probe +response frames to still allow working STATION mode on the other +interface. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-13-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6794,8 +6794,8 @@ static void rtl8xxxu_configure_filter(st + else + rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH; + +- if (priv->vif && priv->vif->type == NL80211_IFTYPE_AP) +- rcr &= ~RCR_CHECK_BSSID_MATCH; ++ if (priv->vifs[0] && priv->vifs[0]->type == NL80211_IFTYPE_AP) ++ rcr &= ~(RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON); + + if (*total_flags & FIF_CONTROL) + rcr |= RCR_ACCEPT_CTRL_FRAME; diff --git a/package/kernel/mac80211/patches/rtl/001-13-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-watchdo.patch b/package/kernel/mac80211/patches/rtl/001-13-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-watchdo.patch new file mode 100644 index 0000000000..b174b704d7 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-13-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-watchdo.patch @@ -0,0 +1,66 @@ +From 3f9baa99f8429ea6f56e7cc8d881c027518e9573 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:34 +0100 +Subject: [PATCH 13/21] wifi: rtl8xxxu: support multiple interfaces in + watchdog_callback() + +Check first whether priv->vifs[0] exists and is of type STATION, then go +to priv->vifs[1]. Make sure to call refresh_rate_mask for both +interfaces. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-14-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -7200,11 +7200,15 @@ static void rtl8xxxu_watchdog_callback(s + { + struct ieee80211_vif *vif; + struct rtl8xxxu_priv *priv; ++ int i; + + priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work); +- vif = priv->vif; ++ for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) { ++ vif = priv->vifs[i]; ++ ++ if (!vif || vif->type != NL80211_IFTYPE_STATION) ++ continue; + +- if (vif && vif->type == NL80211_IFTYPE_STATION) { + int signal; + struct ieee80211_sta *sta; + +@@ -7215,22 +7219,21 @@ static void rtl8xxxu_watchdog_callback(s + + dev_dbg(dev, "%s: no sta found\n", __func__); + rcu_read_unlock(); +- goto out; ++ continue; + } + rcu_read_unlock(); + + signal = ieee80211_ave_rssi(vif); + +- priv->fops->report_rssi(priv, 0, ++ priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta), + rtl8xxxu_signal_to_snr(signal)); + +- if (priv->fops->set_crystal_cap) +- rtl8xxxu_track_cfo(priv); +- + rtl8xxxu_refresh_rate_mask(priv, signal, sta, false); + } + +-out: ++ if (priv->fops->set_crystal_cap) ++ rtl8xxxu_track_cfo(priv); ++ + schedule_delayed_work(&priv->ra_watchdog, 2 * HZ); + } + diff --git a/package/kernel/mac80211/patches/rtl/001-14-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-add-rem.patch b/package/kernel/mac80211/patches/rtl/001-14-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-add-rem.patch new file mode 100644 index 0000000000..7fcbb02afe --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-14-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-add-rem.patch @@ -0,0 +1,137 @@ +From eef55f1545c92c7181d5083453dee1296298ad3e Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:35 +0100 +Subject: [PATCH 14/21] wifi: rtl8xxxu: support multiple interfaces in + {add,remove}_interface() + +Add a custom struct to store in vif->drv_priv with a reference to +port_num and fill it when a new interface is added. Choose a free +port_num for the newly added interface. + +As we only want to support AP mode/sending beacons on port 0, only change +the beacon settings if a new interface is actually assigned to port 0. + +Call set_linktype() and set_mac() with the appropriate port_num. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-15-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 4 ++ + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 52 +++++++++++-------- + 2 files changed, 34 insertions(+), 22 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1921,6 +1921,10 @@ struct rtl8xxxu_sta_info { + u8 macid; + }; + ++struct rtl8xxxu_vif { ++ int port_num; ++}; ++ + struct rtl8xxxu_rx_urb { + struct urb urb; + struct ieee80211_hw *hw; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6610,28 +6610,33 @@ error: + static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; +- int ret; ++ int port_num; + u8 val8; + +- if (!priv->vif) { +- priv->vif = vif; +- priv->vifs[0] = vif; +- } else { ++ if (!priv->vifs[0]) ++ port_num = 0; ++ else if (!priv->vifs[1]) ++ port_num = 1; ++ else + return -EOPNOTSUPP; +- } + + switch (vif->type) { + case NL80211_IFTYPE_STATION: +- rtl8xxxu_stop_tx_beacon(priv); ++ if (port_num == 0) { ++ rtl8xxxu_stop_tx_beacon(priv); + +- val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); +- val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | +- BEACON_DISABLE_TSF_UPDATE; +- rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); +- ret = 0; ++ val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); ++ val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | ++ BEACON_DISABLE_TSF_UPDATE; ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); ++ } + break; + case NL80211_IFTYPE_AP: ++ if (port_num == 1) ++ return -EOPNOTSUPP; ++ + rtl8xxxu_write8(priv, REG_BEACON_CTRL, + BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID); + rtl8xxxu_write8(priv, REG_ATIMWND, 0x0c); /* 12ms */ +@@ -6648,31 +6653,32 @@ static int rtl8xxxu_add_interface(struct + val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK); + val8 &= ~BIT_BCN_PORT_SEL; + rtl8xxxu_write8(priv, REG_CCK_CHECK, val8); +- +- ret = 0; + break; + default: +- ret = -EOPNOTSUPP; ++ return -EOPNOTSUPP; + } + +- rtl8xxxu_set_linktype(priv, vif->type, 0); ++ priv->vifs[port_num] = vif; ++ priv->vif = vif; ++ rtlvif->port_num = port_num; ++ ++ rtl8xxxu_set_linktype(priv, vif->type, port_num); + ether_addr_copy(priv->mac_addr, vif->addr); +- rtl8xxxu_set_mac(priv, 0); ++ rtl8xxxu_set_mac(priv, port_num); + +- return ret; ++ return 0; + } + + static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + + dev_dbg(&priv->udev->dev, "%s\n", __func__); + +- if (priv->vif) { +- priv->vif = NULL; +- priv->vifs[0] = NULL; +- } ++ priv->vif = NULL; ++ priv->vifs[rtlvif->port_num] = NULL; + } + + static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) +@@ -7661,6 +7667,8 @@ static int rtl8xxxu_probe(struct usb_int + if (ret) + goto err_set_intfdata; + ++ hw->vif_data_size = sizeof(struct rtl8xxxu_vif); ++ + hw->wiphy->max_scan_ssids = 1; + hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + if (priv->fops->max_macid_num) diff --git a/package/kernel/mac80211/patches/rtl/001-15-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-bss_inf.patch b/package/kernel/mac80211/patches/rtl/001-15-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-bss_inf.patch new file mode 100644 index 0000000000..5c5c1948d3 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-15-v6.9-wifi-rtl8xxxu-support-multiple-interfaces-in-bss_inf.patch @@ -0,0 +1,57 @@ +From 073401c3b6b9eaea027240baf07f2b84dd2d2d26 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:36 +0100 +Subject: [PATCH 15/21] wifi: rtl8xxxu: support multiple interfaces in + bss_info_changed() + +Call set_linktype and set_bssid now with correct port_num. Call +stop_tx_beacon only for port 0, as we don't support beacons on port 1. +Explicit changes to BEACON will only happen for AP type interfaces, so +we don't need an additional check there. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-16-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4983,6 +4983,7 @@ static void + rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u64 changed) + { ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + struct ieee80211_sta *sta; +@@ -4995,7 +4996,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + if (changed & BSS_CHANGED_ASSOC) { + dev_dbg(dev, "Changed ASSOC: %i!\n", vif->cfg.assoc); + +- rtl8xxxu_set_linktype(priv, vif->type, 0); ++ rtl8xxxu_set_linktype(priv, vif->type, rtlvif->port_num); + + if (vif->cfg.assoc) { + u32 ramask; +@@ -5042,7 +5043,8 @@ rtl8xxxu_bss_info_changed(struct ieee802 + + rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); + +- rtl8xxxu_stop_tx_beacon(priv); ++ if (rtlvif->port_num == 0) ++ rtl8xxxu_stop_tx_beacon(priv); + + /* joinbss sequence */ + rtl8xxxu_write16(priv, REG_BCN_PSR_RPT, +@@ -5084,7 +5086,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + + if (changed & BSS_CHANGED_BSSID) { + dev_dbg(dev, "Changed BSSID!\n"); +- rtl8xxxu_set_bssid(priv, bss_conf->bssid, 0); ++ rtl8xxxu_set_bssid(priv, bss_conf->bssid, rtlvif->port_num); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { diff --git a/package/kernel/mac80211/patches/rtl/001-16-v6.9-wifi-rtl8xxxu-support-multiple-interface-in-start_ap.patch b/package/kernel/mac80211/patches/rtl/001-16-v6.9-wifi-rtl8xxxu-support-multiple-interface-in-start_ap.patch new file mode 100644 index 0000000000..25d0238461 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-16-v6.9-wifi-rtl8xxxu-support-multiple-interface-in-start_ap.patch @@ -0,0 +1,32 @@ +From 61fdbd9e2a9d74c716bf4d9684653de5efdee691 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:37 +0100 +Subject: [PATCH 16/21] wifi: rtl8xxxu: support multiple interface in + start_ap() + +Call set_bssid() with the correct port_num now. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-17-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5111,11 +5111,12 @@ error: + static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) + { ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + + dev_dbg(dev, "Start AP mode\n"); +- rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, 0); ++ rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, rtlvif->port_num); + rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int); + priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true); + diff --git a/package/kernel/mac80211/patches/rtl/001-17-v6.9-wifi-rtl8xxxu-add-macids-for-STA-mode.patch b/package/kernel/mac80211/patches/rtl/001-17-v6.9-wifi-rtl8xxxu-add-macids-for-STA-mode.patch new file mode 100644 index 0000000000..9f8d0a3aaf --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-17-v6.9-wifi-rtl8xxxu-add-macids-for-STA-mode.patch @@ -0,0 +1,82 @@ +From 5ce0d7e8aee03e73b35f0fe1f1ebbdd4e45776f3 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:38 +0100 +Subject: [PATCH 17/21] wifi: rtl8xxxu: add macids for STA mode + +Until now, the driver only assigned a dedicated macid for connections +made in AP mode, in STA mode the return value of rtl8xxxu_get_macid() +was simply 0. +To differentiate between port 0 and 1, when both are in STA mode, +allocate a second macid (with value 1) and set sta_info->macid according +to the used port_num in rtl8xxxu_sta_add(). + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-18-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 18 +++++++++++++++++- + 2 files changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1774,6 +1774,7 @@ struct rtl8xxxu_cfo_tracking { + #define RTL8XXXU_HW_LED_CONTROL 2 + #define RTL8XXXU_MAX_MAC_ID_NUM 128 + #define RTL8XXXU_BC_MC_MACID 0 ++#define RTL8XXXU_BC_MC_MACID1 1 + + struct rtl8xxxu_priv { + struct ieee80211_hw *hw; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4053,10 +4053,13 @@ static inline u8 rtl8xxxu_get_macid(stru + { + struct rtl8xxxu_sta_info *sta_info; + +- if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION || !sta) ++ if (!sta) + return 0; + + sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; ++ if (!sta_info) ++ return 0; ++ + return sta_info->macid; + } + +@@ -4536,6 +4539,7 @@ static int rtl8xxxu_init_device(struct i + rtl8188e_ra_info_init_all(&priv->ra_info); + + set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map); ++ set_bit(RTL8XXXU_BC_MC_MACID1, priv->mac_id_map); + + exit: + return ret; +@@ -7375,6 +7379,7 @@ static int rtl8xxxu_sta_add(struct ieee8 + struct ieee80211_sta *sta) + { + struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + + if (vif->type == NL80211_IFTYPE_AP) { +@@ -7384,6 +7389,17 @@ static int rtl8xxxu_sta_add(struct ieee8 + + rtl8xxxu_refresh_rate_mask(priv, 0, sta, true); + priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true); ++ } else { ++ switch (rtlvif->port_num) { ++ case 0: ++ sta_info->macid = RTL8XXXU_BC_MC_MACID; ++ break; ++ case 1: ++ sta_info->macid = RTL8XXXU_BC_MC_MACID1; ++ break; ++ default: ++ break; ++ } + } + + return 0; diff --git a/package/kernel/mac80211/patches/rtl/001-18-v6.9-wifi-rtl8xxxu-remove-obsolete-priv-vif.patch b/package/kernel/mac80211/patches/rtl/001-18-v6.9-wifi-rtl8xxxu-remove-obsolete-priv-vif.patch new file mode 100644 index 0000000000..5cf65eb519 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-18-v6.9-wifi-rtl8xxxu-remove-obsolete-priv-vif.patch @@ -0,0 +1,49 @@ +From f232e9d91bb84817c60c051a3e3b56dd2721a7b3 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:39 +0100 +Subject: [PATCH 18/21] wifi: rtl8xxxu: remove obsolete priv->vif + +Now that all uses of priv->vif have been converted to priv->vifs[] +remove the old attribute. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-19-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ----- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 -- + 2 files changed, 7 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1893,11 +1893,6 @@ struct rtl8xxxu_priv { + u8 rssi_level; + DECLARE_BITMAP(tx_aggr_started, IEEE80211_NUM_TIDS); + DECLARE_BITMAP(tid_tx_operational, IEEE80211_NUM_TIDS); +- /* +- * Only one virtual interface permitted because only STA mode +- * is supported and no iface_combinations are provided. +- */ +- struct ieee80211_vif *vif; + + struct ieee80211_vif *vifs[2]; + struct delayed_work ra_watchdog; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6666,7 +6666,6 @@ static int rtl8xxxu_add_interface(struct + } + + priv->vifs[port_num] = vif; +- priv->vif = vif; + rtlvif->port_num = port_num; + + rtl8xxxu_set_linktype(priv, vif->type, port_num); +@@ -6684,7 +6683,6 @@ static void rtl8xxxu_remove_interface(st + + dev_dbg(&priv->udev->dev, "%s\n", __func__); + +- priv->vif = NULL; + priv->vifs[rtlvif->port_num] = NULL; + } + diff --git a/package/kernel/mac80211/patches/rtl/001-19-v6.9-wifi-rtl8xxxu-add-hw-crypto-support-for-AP-mode.patch b/package/kernel/mac80211/patches/rtl/001-19-v6.9-wifi-rtl8xxxu-add-hw-crypto-support-for-AP-mode.patch new file mode 100644 index 0000000000..b5f9307496 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-19-v6.9-wifi-rtl8xxxu-add-hw-crypto-support-for-AP-mode.patch @@ -0,0 +1,226 @@ +From b837f78fbffa5f8e7e7c59879db54793abf161ec Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:40 +0100 +Subject: [PATCH 19/21] wifi: rtl8xxxu: add hw crypto support for AP mode + +Add a custom function for allocating entries in the sec cam. This allows +us to store multiple keys with the same keyidx. + +The maximum number of sec cam entries for 8188f is 16 according to the +vendor driver. Add the number to rtl8xxxu_fileops, so that other chips +which might support more entries, can set a different number there. + +Set the bssid as mac address for group keys instead of just using the +ethernet broadcast address and use BIT(6) in the sec cam ctrl entry +for differentiating them from pairwise keys like in the vendor driver. + +Add the TXDESC_EN_DESC_ID bit and the hw_key_idx to tx +broadcast/multicast packets in AP mode. + +Finally, allow the usage of rtl8xxxu_set_key() for AP mode. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-20-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ++ + .../realtek/rtl8xxxu/rtl8xxxu_8188f.c | 1 + + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 48 +++++++++++++++---- + 3 files changed, 44 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -498,6 +498,7 @@ struct rtl8xxxu_txdesc40 { + #define DESC_RATE_ID_SHIFT 16 + #define DESC_RATE_ID_MASK 0xf + #define TXDESC_NAVUSEHDR BIT(20) ++#define TXDESC_EN_DESC_ID BIT(21) + #define TXDESC_SEC_RC4 0x00400000 + #define TXDESC_SEC_AES 0x00c00000 + #define TXDESC_PKT_OFFSET_SHIFT 26 +@@ -1775,6 +1776,7 @@ struct rtl8xxxu_cfo_tracking { + #define RTL8XXXU_MAX_MAC_ID_NUM 128 + #define RTL8XXXU_BC_MC_MACID 0 + #define RTL8XXXU_BC_MC_MACID1 1 ++#define RTL8XXXU_MAX_SEC_CAM_NUM 64 + + struct rtl8xxxu_priv { + struct ieee80211_hw *hw; +@@ -1908,6 +1910,7 @@ struct rtl8xxxu_priv { + char led_name[32]; + struct led_classdev led_cdev; + DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM); ++ DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM); + }; + + struct rtl8xxxu_sta_info { +@@ -1919,6 +1922,7 @@ struct rtl8xxxu_sta_info { + + struct rtl8xxxu_vif { + int port_num; ++ u8 hw_key_idx; + }; + + struct rtl8xxxu_rx_urb { +@@ -1993,6 +1997,7 @@ struct rtl8xxxu_fileops { + u16 max_aggr_num; + u8 supports_ap:1; + u16 max_macid_num; ++ u16 max_sec_cam_num; + u32 adda_1t_init; + u32 adda_1t_path_on; + u32 adda_2t_path_on_a; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +@@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = + .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 16, ++ .max_sec_cam_num = 16, + .adda_1t_init = 0x03c00014, + .adda_1t_path_on = 0x03c00014, + .trxff_boundary = 0x3f7f, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4559,8 +4559,10 @@ static void rtl8xxxu_cam_write(struct rt + * This is a bit of a hack - the lower bits of the cipher + * suite selector happens to match the cipher index in the CAM + */ +- addr = key->keyidx << CAM_CMD_KEY_SHIFT; ++ addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT; + ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID; ++ if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ ctrl |= BIT(6); + + for (j = 5; j >= 0; j--) { + switch (j) { +@@ -5546,13 +5548,14 @@ static void rtl8xxxu_tx(struct ieee80211 + struct rtl8xxxu_tx_urb *tx_urb; + struct ieee80211_sta *sta = NULL; + struct ieee80211_vif *vif = tx_info->control.vif; ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct device *dev = &priv->udev->dev; + u32 queue, rts_rate; + u16 pktlen = skb->len; + int tx_desc_size = priv->fops->tx_desc_size; + u8 macid; + int ret; +- bool ampdu_enable, sgi = false, short_preamble = false; ++ bool ampdu_enable, sgi = false, short_preamble = false, bmc = false; + + if (skb_headroom(skb) < tx_desc_size) { + dev_warn(dev, +@@ -5594,10 +5597,14 @@ static void rtl8xxxu_tx(struct ieee80211 + tx_desc->txdw0 = + TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || +- is_broadcast_ether_addr(ieee80211_get_DA(hdr))) ++ is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + tx_desc->txdw0 |= TXDESC_BROADMULTICAST; ++ bmc = true; ++ } ++ + + tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); ++ macid = rtl8xxxu_get_macid(priv, sta); + + if (tx_info->control.hw_key) { + switch (tx_info->control.hw_key->cipher) { +@@ -5612,6 +5619,10 @@ static void rtl8xxxu_tx(struct ieee80211 + default: + break; + } ++ if (bmc && rtlvif->hw_key_idx != 0xff) { ++ tx_desc->txdw1 |= TXDESC_EN_DESC_ID; ++ macid = rtlvif->hw_key_idx; ++ } + } + + /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */ +@@ -5655,7 +5666,6 @@ static void rtl8xxxu_tx(struct ieee80211 + else + rts_rate = 0; + +- macid = rtl8xxxu_get_macid(priv, sta); + priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, + ampdu_enable, rts_rate, macid); + +@@ -6667,6 +6677,7 @@ static int rtl8xxxu_add_interface(struct + + priv->vifs[port_num] = vif; + rtlvif->port_num = port_num; ++ rtlvif->hw_key_idx = 0xff; + + rtl8xxxu_set_linktype(priv, vif->type, port_num); + ether_addr_copy(priv->mac_addr, vif->addr); +@@ -6843,11 +6854,19 @@ static int rtl8xxxu_set_rts_threshold(st + return 0; + } + ++static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw) ++{ ++ struct rtl8xxxu_priv *priv = hw->priv; ++ ++ return find_first_zero_bit(priv->cam_map, priv->fops->max_sec_cam_num); ++} ++ + static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) + { ++ struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u8 mac_addr[ETH_ALEN]; +@@ -6859,9 +6878,6 @@ static int rtl8xxxu_set_key(struct ieee8 + dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n", + __func__, cmd, key->cipher, key->keyidx); + +- if (vif->type != NL80211_IFTYPE_STATION) +- return -EOPNOTSUPP; +- + if (key->keyidx > 3) + return -EOPNOTSUPP; + +@@ -6885,7 +6901,7 @@ static int rtl8xxxu_set_key(struct ieee8 + ether_addr_copy(mac_addr, sta->addr); + } else { + dev_dbg(dev, "%s: group key\n", __func__); +- eth_broadcast_addr(mac_addr); ++ ether_addr_copy(mac_addr, vif->bss_conf.bssid); + } + + val16 = rtl8xxxu_read16(priv, REG_CR); +@@ -6899,16 +6915,28 @@ static int rtl8xxxu_set_key(struct ieee8 + + switch (cmd) { + case SET_KEY: +- key->hw_key_idx = key->keyidx; ++ ++ retval = rtl8xxxu_get_free_sec_cam(hw); ++ if (retval < 0) ++ return -EOPNOTSUPP; ++ ++ key->hw_key_idx = retval; ++ ++ if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ rtlvif->hw_key_idx = key->hw_key_idx; ++ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + rtl8xxxu_cam_write(priv, key, mac_addr); ++ set_bit(key->hw_key_idx, priv->cam_map); + retval = 0; + break; + case DISABLE_KEY: + rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000); + val32 = CAM_CMD_POLLING | CAM_CMD_WRITE | +- key->keyidx << CAM_CMD_KEY_SHIFT; ++ key->hw_key_idx << CAM_CMD_KEY_SHIFT; + rtl8xxxu_write32(priv, REG_CAM_CMD, val32); ++ rtlvif->hw_key_idx = 0xff; ++ clear_bit(key->hw_key_idx, priv->cam_map); + retval = 0; + break; + default: diff --git a/package/kernel/mac80211/patches/rtl/001-20-v6.9-wifi-rtl8xxxu-make-supporting-AP-mode-only-on-port-0.patch b/package/kernel/mac80211/patches/rtl/001-20-v6.9-wifi-rtl8xxxu-make-supporting-AP-mode-only-on-port-0.patch new file mode 100644 index 0000000000..4b55b0ede7 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-20-v6.9-wifi-rtl8xxxu-make-supporting-AP-mode-only-on-port-0.patch @@ -0,0 +1,130 @@ +From 69abad618efd17e50bc6f880332ab36b660b0b34 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:41 +0100 +Subject: [PATCH 20/21] wifi: rtl8xxxu: make supporting AP mode only on port 0 + transparent + +When the driver is used for concurrent mode, both virtual interfaces can +be set to station or AP mode, though only one can be in AP mode at the +same time. + +In order to keep the code simple, use only hw port 0 for AP mode. When +an interface is added in AP mode which would be assigned to port 1, use +a switch_port function to transparently swap the mapping between virtual +interface and hw port. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-21-martin.kaistra@linutronix.de +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 91 ++++++++++++++++++- + 1 file changed, 89 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6624,6 +6624,91 @@ error: + return ret; + } + ++static void rtl8xxxu_switch_ports(struct rtl8xxxu_priv *priv) ++{ ++ u8 macid[ETH_ALEN], bssid[ETH_ALEN], macid_1[ETH_ALEN], bssid_1[ETH_ALEN]; ++ u8 msr, bcn_ctrl, bcn_ctrl_1, atimwnd[2], atimwnd_1[2]; ++ struct rtl8xxxu_vif *rtlvif; ++ struct ieee80211_vif *vif; ++ u8 tsftr[8], tsftr_1[8]; ++ int i; ++ ++ msr = rtl8xxxu_read8(priv, REG_MSR); ++ bcn_ctrl = rtl8xxxu_read8(priv, REG_BEACON_CTRL); ++ bcn_ctrl_1 = rtl8xxxu_read8(priv, REG_BEACON_CTRL_1); ++ ++ for (i = 0; i < ARRAY_SIZE(atimwnd); i++) ++ atimwnd[i] = rtl8xxxu_read8(priv, REG_ATIMWND + i); ++ for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++) ++ atimwnd_1[i] = rtl8xxxu_read8(priv, REG_ATIMWND_1 + i); ++ ++ for (i = 0; i < ARRAY_SIZE(tsftr); i++) ++ tsftr[i] = rtl8xxxu_read8(priv, REG_TSFTR + i); ++ for (i = 0; i < ARRAY_SIZE(tsftr); i++) ++ tsftr_1[i] = rtl8xxxu_read8(priv, REG_TSFTR1 + i); ++ ++ for (i = 0; i < ARRAY_SIZE(macid); i++) ++ macid[i] = rtl8xxxu_read8(priv, REG_MACID + i); ++ ++ for (i = 0; i < ARRAY_SIZE(bssid); i++) ++ bssid[i] = rtl8xxxu_read8(priv, REG_BSSID + i); ++ ++ for (i = 0; i < ARRAY_SIZE(macid_1); i++) ++ macid_1[i] = rtl8xxxu_read8(priv, REG_MACID1 + i); ++ ++ for (i = 0; i < ARRAY_SIZE(bssid_1); i++) ++ bssid_1[i] = rtl8xxxu_read8(priv, REG_BSSID1 + i); ++ ++ /* disable bcn function, disable update TSF */ ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL, (bcn_ctrl & ++ (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE); ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, (bcn_ctrl_1 & ++ (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE); ++ ++ /* switch msr */ ++ msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2); ++ rtl8xxxu_write8(priv, REG_MSR, msr); ++ ++ /* write port0 */ ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1 & ~BEACON_FUNCTION_ENABLE); ++ for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++) ++ rtl8xxxu_write8(priv, REG_ATIMWND + i, atimwnd_1[i]); ++ for (i = 0; i < ARRAY_SIZE(tsftr_1); i++) ++ rtl8xxxu_write8(priv, REG_TSFTR + i, tsftr_1[i]); ++ for (i = 0; i < ARRAY_SIZE(macid_1); i++) ++ rtl8xxxu_write8(priv, REG_MACID + i, macid_1[i]); ++ for (i = 0; i < ARRAY_SIZE(bssid_1); i++) ++ rtl8xxxu_write8(priv, REG_BSSID + i, bssid_1[i]); ++ ++ /* write port1 */ ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl & ~BEACON_FUNCTION_ENABLE); ++ for (i = 0; i < ARRAY_SIZE(atimwnd); i++) ++ rtl8xxxu_write8(priv, REG_ATIMWND_1 + i, atimwnd[i]); ++ for (i = 0; i < ARRAY_SIZE(tsftr); i++) ++ rtl8xxxu_write8(priv, REG_TSFTR1 + i, tsftr[i]); ++ for (i = 0; i < ARRAY_SIZE(macid); i++) ++ rtl8xxxu_write8(priv, REG_MACID1 + i, macid[i]); ++ for (i = 0; i < ARRAY_SIZE(bssid); i++) ++ rtl8xxxu_write8(priv, REG_BSSID1 + i, bssid[i]); ++ ++ /* write bcn ctl */ ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1); ++ rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl); ++ ++ vif = priv->vifs[0]; ++ priv->vifs[0] = priv->vifs[1]; ++ priv->vifs[1] = vif; ++ ++ /* priv->vifs[0] is NULL here, based on how this function is currently ++ * called from rtl8xxxu_add_interface(). ++ * When this function will be used in the future for a different ++ * scenario, please check whether vifs[0] or vifs[1] can be NULL and if ++ * necessary add code to set port_num = 1. ++ */ ++ rtlvif = (struct rtl8xxxu_vif *)priv->vifs[1]->drv_priv; ++ rtlvif->port_num = 1; ++} ++ + static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6651,8 +6736,10 @@ static int rtl8xxxu_add_interface(struct + } + break; + case NL80211_IFTYPE_AP: +- if (port_num == 1) +- return -EOPNOTSUPP; ++ if (port_num == 1) { ++ rtl8xxxu_switch_ports(priv); ++ port_num = 0; ++ } + + rtl8xxxu_write8(priv, REG_BEACON_CTRL, + BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID); diff --git a/package/kernel/mac80211/patches/rtl/001-21-v6.9-wifi-rtl8xxxu-declare-concurrent-mode-support-for-81.patch b/package/kernel/mac80211/patches/rtl/001-21-v6.9-wifi-rtl8xxxu-declare-concurrent-mode-support-for-81.patch new file mode 100644 index 0000000000..6322541434 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/001-21-v6.9-wifi-rtl8xxxu-declare-concurrent-mode-support-for-81.patch @@ -0,0 +1,76 @@ +From 1cd165adf314f6bf25cde58f02f4ff51d01730b0 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Fri, 22 Dec 2023 11:14:42 +0100 +Subject: [PATCH 21/21] wifi: rtl8xxxu: declare concurrent mode support for + 8188f + +Everything is in place now for concurrent mode, we can tell the system +that we support it. +We will allow a maximum of 2 virtual interfaces, one of them can be in +AP mode. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20231222101442.626837-22-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + + .../realtek/rtl8xxxu/rtl8xxxu_8188f.c | 1 + + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++++++++++ + 3 files changed, 21 insertions(+) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1992,6 +1992,7 @@ struct rtl8xxxu_fileops { + u8 init_reg_rxfltmap:1; + u8 init_reg_pkt_life_time:1; + u8 init_reg_hmtfr:1; ++ u8 supports_concurrent:1; + u8 ampdu_max_time; + u8 ustime_tsf_edca; + u16 max_aggr_num; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +@@ -1752,6 +1752,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = + .supports_ap = 1, + .max_macid_num = 16, + .max_sec_cam_num = 16, ++ .supports_concurrent = 1, + .adda_1t_init = 0x03c00014, + .adda_1t_path_on = 0x03c00014, + .trxff_boundary = 0x3f7f, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -7665,6 +7665,20 @@ static void rtl8xxxu_deinit_led(struct r + led_classdev_unregister(led); + } + ++struct ieee80211_iface_limit rtl8xxxu_limits[] = { ++ { .max = 2, .types = BIT(NL80211_IFTYPE_STATION), }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_AP), }, ++}; ++ ++struct ieee80211_iface_combination rtl8xxxu_combinations[] = { ++ { ++ .limits = rtl8xxxu_limits, ++ .n_limits = ARRAY_SIZE(rtl8xxxu_limits), ++ .max_interfaces = 2, ++ .num_different_channels = 1, ++ }, ++}; ++ + static int rtl8xxxu_probe(struct usb_interface *interface, + const struct usb_device_id *id) + { +@@ -7810,6 +7824,11 @@ static int rtl8xxxu_probe(struct usb_int + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); + hw->queues = 4; + ++ if (priv->fops->supports_concurrent) { ++ hw->wiphy->iface_combinations = rtl8xxxu_combinations; ++ hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtl8xxxu_combinations); ++ } ++ + sband = &rtl8xxxu_supported_band; + sband->ht_cap.ht_supported = true; + sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; diff --git a/package/kernel/mac80211/patches/rtl/002-01-v6.9-wifi-rtl8xxxu-Fix-LED-control-code-of-RTL8192FU.patch b/package/kernel/mac80211/patches/rtl/002-01-v6.9-wifi-rtl8xxxu-Fix-LED-control-code-of-RTL8192FU.patch new file mode 100644 index 0000000000..d1a480d53f --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/002-01-v6.9-wifi-rtl8xxxu-Fix-LED-control-code-of-RTL8192FU.patch @@ -0,0 +1,98 @@ +From 9475cc7ac31503521af95e38151e9d856e8ff30b Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Sun, 31 Dec 2023 00:45:54 +0200 +Subject: [PATCH 1/2] wifi: rtl8xxxu: Fix LED control code of RTL8192FU + +Some devices, like the Comfast CF-826F, use LED1, which already works. +Others, like Asus USB-N13 C1, use LED0, which doesn't work correctly. + +Write the right values to the LED control registers to make LED0 work +as well. + +This is unfortunately tested only with the Comfast CF-826F. + +Signed-off-by: Bitterblue Smith +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/7a2c3158-3a45-4466-b11e-fc09802b20e2@gmail.com +--- + .../realtek/rtl8xxxu/rtl8xxxu_8192f.c | 32 +++++++++++++------ + .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 15 +++++++++ + 2 files changed, 38 insertions(+), 9 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c +@@ -2014,26 +2014,40 @@ static int rtl8192fu_led_brightness_set( + struct rtl8xxxu_priv *priv = container_of(led_cdev, + struct rtl8xxxu_priv, + led_cdev); +- u16 ledcfg; ++ u32 ledcfg; + + /* Values obtained by observing the USB traffic from the Windows driver. */ + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080); + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000); + +- ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0); ++ ledcfg = rtl8xxxu_read32(priv, REG_LEDCFG0); ++ ++ /* Comfast CF-826F uses LED1. Asus USB-N13 C1 uses LED0. Set both. */ ++ ++ u32p_replace_bits(&ledcfg, LED_GPIO_ENABLE, LEDCFG0_LED2EN); ++ u32p_replace_bits(&ledcfg, LED_IO_MODE_OUTPUT, LEDCFG0_LED0_IO_MODE); ++ u32p_replace_bits(&ledcfg, LED_IO_MODE_OUTPUT, LEDCFG0_LED1_IO_MODE); + + if (brightness == LED_OFF) { +- /* Value obtained like above. */ +- ledcfg = BIT(1) | BIT(7); ++ u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED0CM); ++ u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED0SV); ++ u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED1CM); ++ u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED1SV); + } else if (brightness == LED_ON) { +- /* Value obtained like above. */ +- ledcfg = BIT(1) | BIT(7) | BIT(11); ++ u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED0CM); ++ u32p_replace_bits(&ledcfg, LED_SW_ON, LEDCFG0_LED0SV); ++ u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED1CM); ++ u32p_replace_bits(&ledcfg, LED_SW_ON, LEDCFG0_LED1SV); + } else if (brightness == RTL8XXXU_HW_LED_CONTROL) { +- /* Value obtained by brute force. */ +- ledcfg = BIT(8) | BIT(9); ++ u32p_replace_bits(&ledcfg, LED_MODE_TX_OR_RX_EVENTS, ++ LEDCFG0_LED0CM); ++ u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED0SV); ++ u32p_replace_bits(&ledcfg, LED_MODE_TX_OR_RX_EVENTS, ++ LEDCFG0_LED1CM); ++ u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED1SV); + } + +- rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg); ++ rtl8xxxu_write32(priv, REG_LEDCFG0, ledcfg); + + return 0; + } +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +@@ -146,6 +146,21 @@ + #define GPIO_INTM_EDGE_TRIG_IRQ BIT(9) + + #define REG_LEDCFG0 0x004c ++#define LEDCFG0_LED0CM GENMASK(2, 0) ++#define LEDCFG0_LED1CM GENMASK(10, 8) ++#define LED_MODE_SW_CTRL 0x0 ++#define LED_MODE_TX_OR_RX_EVENTS 0x3 ++#define LEDCFG0_LED0SV BIT(3) ++#define LEDCFG0_LED1SV BIT(11) ++#define LED_SW_OFF 0x0 ++#define LED_SW_ON 0x1 ++#define LEDCFG0_LED0_IO_MODE BIT(7) ++#define LEDCFG0_LED1_IO_MODE BIT(15) ++#define LED_IO_MODE_OUTPUT 0x0 ++#define LED_IO_MODE_INPUT 0x1 ++#define LEDCFG0_LED2EN BIT(21) ++#define LED_GPIO_DISABLE 0x0 ++#define LED_GPIO_ENABLE 0x1 + #define LEDCFG0_DPDT_SELECT BIT(23) + #define REG_LEDCFG1 0x004d + #define LEDCFG1_HW_LED_CONTROL BIT(1) diff --git a/package/kernel/mac80211/patches/rtl/002-02-v6.9-wifi-rtl8xxxu-Fix-off-by-one-initial-RTS-rate.patch b/package/kernel/mac80211/patches/rtl/002-02-v6.9-wifi-rtl8xxxu-Fix-off-by-one-initial-RTS-rate.patch new file mode 100644 index 0000000000..7d1c67f2e0 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/002-02-v6.9-wifi-rtl8xxxu-Fix-off-by-one-initial-RTS-rate.patch @@ -0,0 +1,36 @@ +From 80850ca041f2c7ee28fa5e47c5c1b106415f099f Mon Sep 17 00:00:00 2001 +From: Bitterblue Smith +Date: Tue, 2 Jan 2024 21:33:07 +0200 +Subject: [PATCH 2/2] wifi: rtl8xxxu: Fix off by one initial RTS rate + +rtl8xxxu_set_basic_rates() sets the wrong initial RTS rate. It sets the +next higher rate than the one it should set, e.g. 36M instead of 24M. + +The while loop was supposed to find the index of the most significant +bit which is 1, but it was copied incorrectly from the vendor driver. +Use __fls() instead. + +Signed-off-by: Bitterblue Smith +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/761e6836-6cd6-4930-91b6-0446834655c5@gmail.com +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4870,10 +4870,9 @@ static void rtl8xxxu_set_basic_rates(str + + dev_dbg(&priv->udev->dev, "%s: rates %08x\n", __func__, rate_cfg); + +- while (rate_cfg) { +- rate_cfg = (rate_cfg >> 1); +- rate_idx++; +- } ++ if (rate_cfg) ++ rate_idx = __fls(rate_cfg); ++ + rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx); + } + diff --git a/package/kernel/mac80211/patches/rtl/003-01-v6.9-wifi-rtl8xxxu-add-cancel_work_sync-for-c2hcmd_work.patch b/package/kernel/mac80211/patches/rtl/003-01-v6.9-wifi-rtl8xxxu-add-cancel_work_sync-for-c2hcmd_work.patch new file mode 100644 index 0000000000..612b5f8738 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/003-01-v6.9-wifi-rtl8xxxu-add-cancel_work_sync-for-c2hcmd_work.patch @@ -0,0 +1,27 @@ +From 1213acb478a7181cd73eeaf00db430f1e45b1361 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Thu, 11 Jan 2024 17:36:27 +0100 +Subject: [PATCH 1/2] wifi: rtl8xxxu: add cancel_work_sync() for c2hcmd_work + +The workqueue might still be running, when the driver is stopped. To +avoid a use-after-free, call cancel_work_sync() in rtl8xxxu_stop(). + +Fixes: e542e66b7c2e ("rtl8xxxu: add bluetooth co-existence support for single antenna") +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240111163628.320697-2-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -7480,6 +7480,7 @@ static void rtl8xxxu_stop(struct ieee802 + if (priv->usb_interrupts) + rtl8xxxu_write32(priv, REG_USB_HIMR, 0); + ++ cancel_work_sync(&priv->c2hcmd_work); + cancel_delayed_work_sync(&priv->ra_watchdog); + + rtl8xxxu_free_rx_resources(priv); diff --git a/package/kernel/mac80211/patches/rtl/003-02-v6.9-wifi-rtl8xxxu-enable-channel-switch-support.patch b/package/kernel/mac80211/patches/rtl/003-02-v6.9-wifi-rtl8xxxu-enable-channel-switch-support.patch new file mode 100644 index 0000000000..6c78d3901b --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/003-02-v6.9-wifi-rtl8xxxu-enable-channel-switch-support.patch @@ -0,0 +1,100 @@ +From ece90a8622320bf5a24d3326da1f8e109891573c Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Thu, 11 Jan 2024 17:36:28 +0100 +Subject: [PATCH 2/2] wifi: rtl8xxxu: enable channel switch support + +The CSA countdown in the beacon frames, which are sent out by firmware, +needs to get updated by the driver. To achieve this, convert +update_beacon_work to delayed_work and schedule it with the beacon +interval in case CSA is active and the countdown is not complete. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240111163628.320697-3-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++++++---- + 2 files changed, 16 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1900,7 +1900,7 @@ struct rtl8xxxu_priv { + struct delayed_work ra_watchdog; + struct work_struct c2hcmd_work; + struct sk_buff_head c2hcmd_queue; +- struct work_struct update_beacon_work; ++ struct delayed_work update_beacon_work; + struct rtl8xxxu_btcoex bt_coex; + struct rtl8xxxu_ra_report ra_report; + struct rtl8xxxu_cfo_tracking cfo_tracking; +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4605,7 +4605,7 @@ static int rtl8xxxu_set_tim(struct ieee8 + { + struct rtl8xxxu_priv *priv = hw->priv; + +- schedule_work(&priv->update_beacon_work); ++ schedule_delayed_work(&priv->update_beacon_work, 0); + + return 0; + } +@@ -5107,7 +5107,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + } + + if (changed & BSS_CHANGED_BEACON) +- schedule_work(&priv->update_beacon_work); ++ schedule_delayed_work(&priv->update_beacon_work, 0); + + error: + return; +@@ -5726,7 +5726,7 @@ static void rtl8xxxu_send_beacon_frame(s + static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work) + { + struct rtl8xxxu_priv *priv = +- container_of(work, struct rtl8xxxu_priv, update_beacon_work); ++ container_of(work, struct rtl8xxxu_priv, update_beacon_work.work); + struct ieee80211_hw *hw = priv->hw; + struct ieee80211_vif *vif = priv->vifs[0]; + +@@ -5735,6 +5735,14 @@ static void rtl8xxxu_update_beacon_work_ + return; + } + ++ if (vif->bss_conf.csa_active) { ++ if (ieee80211_beacon_cntdwn_is_complete(vif)) { ++ ieee80211_csa_finish(vif); ++ return; ++ } ++ schedule_delayed_work(&priv->update_beacon_work, ++ msecs_to_jiffies(vif->bss_conf.beacon_int)); ++ } + rtl8xxxu_send_beacon_frame(hw, vif); + } + +@@ -7482,6 +7490,7 @@ static void rtl8xxxu_stop(struct ieee802 + + cancel_work_sync(&priv->c2hcmd_work); + cancel_delayed_work_sync(&priv->ra_watchdog); ++ cancel_delayed_work_sync(&priv->update_beacon_work); + + rtl8xxxu_free_rx_resources(priv); + rtl8xxxu_free_tx_resources(priv); +@@ -7763,7 +7772,7 @@ static int rtl8xxxu_probe(struct usb_int + spin_lock_init(&priv->rx_urb_lock); + INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); + INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); +- INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback); ++ INIT_DELAYED_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback); + skb_queue_head_init(&priv->c2hcmd_queue); + + usb_set_intfdata(interface, hw); +@@ -7824,6 +7833,8 @@ static int rtl8xxxu_probe(struct usb_int + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); + hw->queues = 4; + ++ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; ++ + if (priv->fops->supports_concurrent) { + hw->wiphy->iface_combinations = rtl8xxxu_combinations; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtl8xxxu_combinations); diff --git a/package/kernel/mac80211/patches/rtl/004-01-v6.9-wifi-rtl8xxxu-convert-EN_DESC_ID-of-TX-descriptor-to.patch b/package/kernel/mac80211/patches/rtl/004-01-v6.9-wifi-rtl8xxxu-convert-EN_DESC_ID-of-TX-descriptor-to.patch new file mode 100644 index 0000000000..a88a52231d --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/004-01-v6.9-wifi-rtl8xxxu-convert-EN_DESC_ID-of-TX-descriptor-to.patch @@ -0,0 +1,31 @@ +From 426e7b4773921d07ab4ab8ba16fbad396d6c9971 Mon Sep 17 00:00:00 2001 +From: Ping-Ke Shih +Date: Tue, 16 Jan 2024 16:09:44 +0800 +Subject: [PATCH 1/2] wifi: rtl8xxxu: convert EN_DESC_ID of TX descriptor to + le32 type + +Fields of TX descriptor are little-endian order, so correct EN_DESC_ID +field to le32 type. + +Fixes: b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP mode") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202401161318.YtXoCkjU-lkp@intel.com/ +Cc: Martin Kaistra +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240116080945.20172-1-pkshih@realtek.com +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5619,7 +5619,7 @@ static void rtl8xxxu_tx(struct ieee80211 + break; + } + if (bmc && rtlvif->hw_key_idx != 0xff) { +- tx_desc->txdw1 |= TXDESC_EN_DESC_ID; ++ tx_desc->txdw1 |= cpu_to_le32(TXDESC_EN_DESC_ID); + macid = rtlvif->hw_key_idx; + } + } diff --git a/package/kernel/mac80211/patches/rtl/004-02-v6.9-wifi-rtl8xxxu-make-instances-of-iface-limit-and-comb.patch b/package/kernel/mac80211/patches/rtl/004-02-v6.9-wifi-rtl8xxxu-make-instances-of-iface-limit-and-comb.patch new file mode 100644 index 0000000000..68848e28e0 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/004-02-v6.9-wifi-rtl8xxxu-make-instances-of-iface-limit-and-comb.patch @@ -0,0 +1,36 @@ +From 92c7428f942da7dfcdc629b05b5114f80822d7a4 Mon Sep 17 00:00:00 2001 +From: Ping-Ke Shih +Date: Tue, 16 Jan 2024 16:09:45 +0800 +Subject: [PATCH 2/2] wifi: rtl8xxxu: make instances of iface limit and + combination to be static const + +rtl8xxxu_limits and rtl8xxxu_combinations can be static const, so add +modifiers as desire. Otherwise, Sparse reports warnings + +rtl8xxxu_core.c:7677:30: warning: symbol 'rtl8xxxu_limits' was not declared. Should it be static? +rtl8xxxu_core.c:7682:36: warning: symbol 'rtl8xxxu_combinations' was not declared. Should it be static? + +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240116080945.20172-2-pkshih@realtek.com +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -7674,12 +7674,12 @@ static void rtl8xxxu_deinit_led(struct r + led_classdev_unregister(led); + } + +-struct ieee80211_iface_limit rtl8xxxu_limits[] = { ++static const struct ieee80211_iface_limit rtl8xxxu_limits[] = { + { .max = 2, .types = BIT(NL80211_IFTYPE_STATION), }, + { .max = 1, .types = BIT(NL80211_IFTYPE_AP), }, + }; + +-struct ieee80211_iface_combination rtl8xxxu_combinations[] = { ++static const struct ieee80211_iface_combination rtl8xxxu_combinations[] = { + { + .limits = rtl8xxxu_limits, + .n_limits = ARRAY_SIZE(rtl8xxxu_limits), diff --git a/package/kernel/mac80211/patches/rtl/005-v6.9-wifi-rtl8xxxu-add-missing-number-of-sec-cam-entries-.patch b/package/kernel/mac80211/patches/rtl/005-v6.9-wifi-rtl8xxxu-add-missing-number-of-sec-cam-entries-.patch new file mode 100644 index 0000000000..9fba6befef --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/005-v6.9-wifi-rtl8xxxu-add-missing-number-of-sec-cam-entries-.patch @@ -0,0 +1,100 @@ +From 563d5025cf3b51c7bf20e6966af433ed5f838875 Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Tue, 16 Jan 2024 10:50:01 +0100 +Subject: [PATCH] wifi: rtl8xxxu: add missing number of sec cam entries for all + variants + +Commit b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP +mode") introduced max_sec_cam_num as a member of rtl8xxxu_fileops. +It was missed to set this number for all variants except 8188f, which +caused rtl8xxxu_get_free_sec_cam() to always return 0 and therefore breaking +encrypted traffic. + +Fix it by adding the numbers for all variants. The values are taken from +the vendor drivers and rtlwifi. + +Link: https://lore.kernel.org/linux-wireless/20240111163603.2325-1-zenmchen@gmail.com/ +Fixes: b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP mode") +Signed-off-by: Martin Kaistra +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240116095001.399500-1-martin.kaistra@linutronix.de +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c | 1 + + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c | 1 + + 7 files changed, 7 insertions(+) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c +@@ -1882,6 +1882,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = + .has_tx_report = 1, + .init_reg_pkt_life_time = 1, + .gen2_thermal_meter = 1, ++ .max_sec_cam_num = 32, + .adda_1t_init = 0x0b1b25a0, + .adda_1t_path_on = 0x0bdb25a0, + /* +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c +@@ -613,6 +613,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = + .rx_agg_buf_size = 16000, + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), ++ .max_sec_cam_num = 32, + .adda_1t_init = 0x0b1b25a0, + .adda_1t_path_on = 0x0bdb25a0, + .adda_2t_path_on_a = 0x04db25a4, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +@@ -1769,6 +1769,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = + .needs_full_init = 1, + .supports_ap = 1, + .max_macid_num = 128, ++ .max_sec_cam_num = 64, + .adda_1t_init = 0x0fc01616, + .adda_1t_path_on = 0x0fc01616, + .adda_2t_path_on_a = 0x0fc01616, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c +@@ -2095,6 +2095,7 @@ struct rtl8xxxu_fileops rtl8192fu_fops = + .max_aggr_num = 0x1f1f, + .supports_ap = 1, + .max_macid_num = 128, ++ .max_sec_cam_num = 64, + .trxff_boundary = 0x3f3f, + .pbp_rx = PBP_PAGE_SIZE_256, + .pbp_tx = PBP_PAGE_SIZE_256, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c +@@ -1877,6 +1877,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = + .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 16, ++ .max_sec_cam_num = 32, + .adda_1t_init = 0x03c00016, + .adda_1t_path_on = 0x03c00016, + .trxff_boundary = 0x3f7f, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c +@@ -510,6 +510,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = + .rx_agg_buf_size = 16000, + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), ++ .max_sec_cam_num = 32, + .adda_1t_init = 0x0b1b25a0, + .adda_1t_path_on = 0x0bdb25a0, + .adda_2t_path_on_a = 0x04db25a4, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +@@ -1744,6 +1744,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = + .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 128, ++ .max_sec_cam_num = 64, + .adda_1t_init = 0x01c00014, + .adda_1t_path_on = 0x01c00014, + .adda_2t_path_on_a = 0x01c00014, diff --git a/package/kernel/mac80211/patches/rtl/006-v6.9-wifi-rtl8xxxu-fix-error-messages.patch b/package/kernel/mac80211/patches/rtl/006-v6.9-wifi-rtl8xxxu-fix-error-messages.patch new file mode 100644 index 0000000000..961f613161 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/006-v6.9-wifi-rtl8xxxu-fix-error-messages.patch @@ -0,0 +1,37 @@ +From 17903a283593c1dbf9da041f836004163ca30f7b Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 31 Jan 2024 10:10:07 +0300 +Subject: [PATCH] wifi: rtl8xxxu: fix error messages + +The first parameter of WARN_ONCE() is a condition so this code will end +up printing the function name instead of the proper message. + +Fixes: 3ff7a05996f9 ("wifi: rtl8xxxu: support setting bssid register for multiple interfaces") +Signed-off-by: Dan Carpenter +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/7b144531-a8da-4725-8911-9b614a525a35@moroto.mountain +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -3593,7 +3593,7 @@ static int rtl8xxxu_set_mac(struct rtl8x + reg = REG_MACID1; + break; + default: +- WARN_ONCE("%s: invalid port_num\n", __func__); ++ WARN_ONCE(1, "%s: invalid port_num\n", __func__); + return -EINVAL; + } + +@@ -3618,7 +3618,7 @@ static int rtl8xxxu_set_bssid(struct rtl + reg = REG_BSSID1; + break; + default: +- WARN_ONCE("%s: invalid port_num\n", __func__); ++ WARN_ONCE(1, "%s: invalid port_num\n", __func__); + return -EINVAL; + } + diff --git a/package/kernel/mac80211/patches/rtl/007-v6.9-wifi-rtl8xxxu-Add-TP-Link-TL-WN823N-V2.patch b/package/kernel/mac80211/patches/rtl/007-v6.9-wifi-rtl8xxxu-Add-TP-Link-TL-WN823N-V2.patch new file mode 100644 index 0000000000..7ccc08c28d --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/007-v6.9-wifi-rtl8xxxu-Add-TP-Link-TL-WN823N-V2.patch @@ -0,0 +1,36 @@ +From 1209f487d452ff7e822dec30661fd6b5163fb8cf Mon Sep 17 00:00:00 2001 +From: Chun Qiu +Date: Mon, 29 Jan 2024 13:30:30 +0800 +Subject: [PATCH] wifi: rtl8xxxu: Add TP-Link TL-WN823N V2 + +TP-Link TL-WN823N V2 (2357:0135) is based on rtl8192fu and has been +tested to work with the rtl8xxxu driver. + +Signed-off-by: Chun Qiu +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240129053030.16369-1-cqca@cock.lu +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -7733,7 +7733,7 @@ static int rtl8xxxu_probe(struct usb_int + untested = 0; + break; + case 0x2357: +- if (id->idProduct == 0x0109) ++ if (id->idProduct == 0x0109 || id->idProduct == 0x0135) + untested = 0; + break; + case 0x0b05: +@@ -8025,6 +8025,9 @@ static const struct usb_device_id dev_ta + .driver_info = (unsigned long)&rtl8192fu_fops}, + {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, ++/* TP-Link TL-WN823N V2 */ ++{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff), ++ .driver_info = (unsigned long)&rtl8192fu_fops}, + #ifdef CPTCFG_RTL8XXXU_UNTESTED + /* Still supported by rtlwifi */ + {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), diff --git a/package/kernel/mac80211/patches/rtl/008-v6.9-wifi-rtl8xxxu-update-rate-mask-per-sta.patch b/package/kernel/mac80211/patches/rtl/008-v6.9-wifi-rtl8xxxu-update-rate-mask-per-sta.patch new file mode 100644 index 0000000000..66cd70c6b1 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/008-v6.9-wifi-rtl8xxxu-update-rate-mask-per-sta.patch @@ -0,0 +1,411 @@ +From 94dd7ce1885e530a7b10bbe50d5d68ba1bb99e6e Mon Sep 17 00:00:00 2001 +From: Martin Kaistra +Date: Mon, 5 Feb 2024 10:30:40 +0100 +Subject: [PATCH] wifi: rtl8xxxu: update rate mask per sta + +Until now, rtl8xxxu_watchdog_callback() only fetches RSSI and updates +the rate mask in station mode. This means, in AP mode only the default +rate mask is used. + +In order to have the rate mask reflect the actual connection quality, +extend rtl8xxxu_watchdog_callback() to iterate over every sta. Like in +the rtw88 driver, add a function to collect all currently present stas +and then iterate over a list of copies to ensure no RCU lock problems +for register access via USB. Remove the existing RCU lock in +rtl8xxxu_refresh_rate_mask(). + +Since the currently used ieee80211_ave_rssi() is only for 'vif', add +driver-level tracking of RSSI per sta. + +Signed-off-by: Martin Kaistra +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240205093040.1941140-1-martin.kaistra@linutronix.de +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 8 +- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 188 ++++++++++++++---- + 2 files changed, 158 insertions(+), 38 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -6,6 +6,7 @@ + */ + + #include ++#include + + #define RTL8XXXU_DEBUG_REG_WRITE 0x01 + #define RTL8XXXU_DEBUG_REG_READ 0x02 +@@ -1858,6 +1859,8 @@ struct rtl8xxxu_priv { + int next_mbox; + int nr_out_eps; + ++ /* Ensure no added or deleted stas while iterating */ ++ struct mutex sta_mutex; + struct mutex h2c_mutex; + /* Protect the indirect register accesses of RTL8710BU. */ + struct mutex syson_indirect_access_mutex; +@@ -1892,7 +1895,6 @@ struct rtl8xxxu_priv { + u8 pi_enabled:1; + u8 no_pape:1; + u8 int_buf[USB_INTR_CONTENT_LENGTH]; +- u8 rssi_level; + DECLARE_BITMAP(tx_aggr_started, IEEE80211_NUM_TIDS); + DECLARE_BITMAP(tid_tx_operational, IEEE80211_NUM_TIDS); + +@@ -1913,11 +1915,15 @@ struct rtl8xxxu_priv { + DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM); + }; + ++DECLARE_EWMA(rssi, 10, 16); ++ + struct rtl8xxxu_sta_info { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + + u8 macid; ++ struct ewma_rssi avg_rssi; ++ u8 rssi_level; + }; + + struct rtl8xxxu_vif { +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4991,10 +4991,11 @@ rtl8xxxu_bss_info_changed(struct ieee802 + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; ++ struct rtl8xxxu_sta_info *sta_info; + struct ieee80211_sta *sta; + struct rtl8xxxu_ra_report *rarpt; ++ u8 val8, macid; + u32 val32; +- u8 val8; + + rarpt = &priv->ra_report; + +@@ -5017,6 +5018,7 @@ rtl8xxxu_bss_info_changed(struct ieee802 + rcu_read_unlock(); + goto error; + } ++ macid = rtl8xxxu_get_macid(priv, sta); + + if (sta->deflink.ht_cap.ht_supported) + dev_info(dev, "%s: HT supported\n", __func__); +@@ -5037,14 +5039,15 @@ rtl8xxxu_bss_info_changed(struct ieee802 + bw = RATE_INFO_BW_40; + else + bw = RATE_INFO_BW_20; ++ ++ sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; ++ sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT; + rcu_read_unlock(); + + rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw); + +- priv->rssi_level = RTL8XXXU_RATR_STA_INIT; +- + priv->fops->update_rate_mask(priv, ramask, 0, sgi, +- bw == RATE_INFO_BW_40, 0); ++ bw == RATE_INFO_BW_40, macid); + + rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); + +@@ -6317,6 +6320,76 @@ static void rtl8188e_c2hcmd_callback(str + } + } + ++#define rtl8xxxu_iterate_vifs_atomic(priv, iterator, data) \ ++ ieee80211_iterate_active_interfaces_atomic((priv)->hw, \ ++ IEEE80211_IFACE_ITER_NORMAL, iterator, data) ++ ++struct rtl8xxxu_rx_update_rssi_data { ++ struct rtl8xxxu_priv *priv; ++ struct ieee80211_hdr *hdr; ++ struct ieee80211_rx_status *rx_status; ++ u8 *bssid; ++}; ++ ++static void rtl8xxxu_rx_update_rssi_iter(void *data, u8 *mac, ++ struct ieee80211_vif *vif) ++{ ++ struct rtl8xxxu_rx_update_rssi_data *iter_data = data; ++ struct ieee80211_sta *sta; ++ struct ieee80211_hdr *hdr = iter_data->hdr; ++ struct rtl8xxxu_priv *priv = iter_data->priv; ++ struct rtl8xxxu_sta_info *sta_info; ++ struct ieee80211_rx_status *rx_status = iter_data->rx_status; ++ u8 *bssid = iter_data->bssid; ++ ++ if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) ++ return; ++ ++ if (!(ether_addr_equal(vif->addr, hdr->addr1) || ++ ieee80211_is_beacon(hdr->frame_control))) ++ return; ++ ++ sta = ieee80211_find_sta_by_ifaddr(priv->hw, hdr->addr2, ++ vif->addr); ++ if (!sta) ++ return; ++ ++ sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; ++ ewma_rssi_add(&sta_info->avg_rssi, -rx_status->signal); ++} ++ ++static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) ++{ ++ __le16 fc = hdr->frame_control; ++ u8 *bssid; ++ ++ if (ieee80211_has_tods(fc)) ++ bssid = hdr->addr1; ++ else if (ieee80211_has_fromds(fc)) ++ bssid = hdr->addr2; ++ else ++ bssid = hdr->addr3; ++ ++ return bssid; ++} ++ ++static void rtl8xxxu_rx_update_rssi(struct rtl8xxxu_priv *priv, ++ struct ieee80211_rx_status *rx_status, ++ struct ieee80211_hdr *hdr) ++{ ++ struct rtl8xxxu_rx_update_rssi_data data = {}; ++ ++ if (ieee80211_is_ctl(hdr->frame_control)) ++ return; ++ ++ data.priv = priv; ++ data.hdr = hdr; ++ data.rx_status = rx_status; ++ data.bssid = get_hdr_bssid(hdr); ++ ++ rtl8xxxu_iterate_vifs_atomic(priv, rtl8xxxu_rx_update_rssi_iter, &data); ++} ++ + int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) + { + struct ieee80211_hw *hw = priv->hw; +@@ -6376,18 +6449,26 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8x + skb_queue_tail(&priv->c2hcmd_queue, skb); + schedule_work(&priv->c2hcmd_work); + } else { ++ struct ieee80211_hdr *hdr; ++ + phy_stats = (struct rtl8723au_phy_stats *)skb->data; + + skb_pull(skb, drvinfo_sz + desc_shift); + + skb_trim(skb, pkt_len); + +- if (rx_desc->phy_stats) ++ hdr = (struct ieee80211_hdr *)skb->data; ++ if (rx_desc->phy_stats) { + priv->fops->parse_phystats( + priv, rx_status, phy_stats, + rx_desc->rxmcs, +- (struct ieee80211_hdr *)skb->data, ++ hdr, + rx_desc->crc32 || rx_desc->icverr); ++ if (!rx_desc->crc32 && !rx_desc->icverr) ++ rtl8xxxu_rx_update_rssi(priv, ++ rx_status, ++ hdr); ++ } + + rx_status->mactime = rx_desc->tsfl; + rx_status->flag |= RX_FLAG_MACTIME_START; +@@ -6484,10 +6565,15 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8x + } else { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + +- if (rx_desc->phy_stats) ++ if (rx_desc->phy_stats) { + priv->fops->parse_phystats(priv, rx_status, phy_stats, + rx_desc->rxmcs, hdr, + rx_desc->crc32 || rx_desc->icverr); ++ if (!rx_desc->crc32 && !rx_desc->icverr) ++ rtl8xxxu_rx_update_rssi(priv, ++ rx_status, ++ hdr); ++ } + + rx_status->mactime = rx_desc->tsfl; + rx_status->flag |= RX_FLAG_MACTIME_START; +@@ -7111,6 +7197,7 @@ static void rtl8xxxu_refresh_rate_mask(s + int signal, struct ieee80211_sta *sta, + bool force) + { ++ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; + struct ieee80211_hw *hw = priv->hw; + u16 wireless_mode; + u8 rssi_level, ratr_idx; +@@ -7119,7 +7206,7 @@ static void rtl8xxxu_refresh_rate_mask(s + u8 go_up_gap = 5; + u8 macid = rtl8xxxu_get_macid(priv, sta); + +- rssi_level = priv->rssi_level; ++ rssi_level = sta_info->rssi_level; + snr = rtl8xxxu_signal_to_snr(signal); + snr_thresh_high = RTL8XXXU_SNR_THRESH_HIGH; + snr_thresh_low = RTL8XXXU_SNR_THRESH_LOW; +@@ -7144,18 +7231,16 @@ static void rtl8xxxu_refresh_rate_mask(s + else + rssi_level = RTL8XXXU_RATR_STA_LOW; + +- if (rssi_level != priv->rssi_level || force) { ++ if (rssi_level != sta_info->rssi_level || force) { + int sgi = 0; + u32 rate_bitmap = 0; + +- rcu_read_lock(); + rate_bitmap = (sta->deflink.supp_rates[0] & 0xfff) | + (sta->deflink.ht_cap.mcs.rx_mask[0] << 12) | + (sta->deflink.ht_cap.mcs.rx_mask[1] << 20); + if (sta->deflink.ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) + sgi = 1; +- rcu_read_unlock(); + + wireless_mode = rtl8xxxu_wireless_mode(hw, sta); + switch (wireless_mode) { +@@ -7236,7 +7321,7 @@ static void rtl8xxxu_refresh_rate_mask(s + break; + } + +- priv->rssi_level = rssi_level; ++ sta_info->rssi_level = rssi_level; + priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid); + } + } +@@ -7329,40 +7414,60 @@ static void rtl8xxxu_track_cfo(struct rt + rtl8xxxu_set_atc_status(priv, abs(cfo_average) >= CFO_TH_ATC); + } + +-static void rtl8xxxu_watchdog_callback(struct work_struct *work) ++static void rtl8xxxu_ra_iter(void *data, struct ieee80211_sta *sta) + { +- struct ieee80211_vif *vif; +- struct rtl8xxxu_priv *priv; +- int i; ++ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; ++ struct rtl8xxxu_priv *priv = data; ++ int signal = -ewma_rssi_read(&sta_info->avg_rssi); + +- priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work); +- for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) { +- vif = priv->vifs[i]; ++ priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta), ++ rtl8xxxu_signal_to_snr(signal)); ++ rtl8xxxu_refresh_rate_mask(priv, signal, sta, false); ++} ++ ++struct rtl8xxxu_stas_entry { ++ struct list_head list; ++ struct ieee80211_sta *sta; ++}; + +- if (!vif || vif->type != NL80211_IFTYPE_STATION) +- continue; ++struct rtl8xxxu_iter_stas_data { ++ struct rtl8xxxu_priv *priv; ++ struct list_head list; ++}; + +- int signal; +- struct ieee80211_sta *sta; ++static void rtl8xxxu_collect_sta_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtl8xxxu_iter_stas_data *iter_stas = data; ++ struct rtl8xxxu_stas_entry *stas_entry; + +- rcu_read_lock(); +- sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); +- if (!sta) { +- struct device *dev = &priv->udev->dev; ++ stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC); ++ if (!stas_entry) ++ return; + +- dev_dbg(dev, "%s: no sta found\n", __func__); +- rcu_read_unlock(); +- continue; +- } +- rcu_read_unlock(); ++ stas_entry->sta = sta; ++ list_add_tail(&stas_entry->list, &iter_stas->list); ++} + +- signal = ieee80211_ave_rssi(vif); ++static void rtl8xxxu_watchdog_callback(struct work_struct *work) ++{ + +- priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta), +- rtl8xxxu_signal_to_snr(signal)); ++ struct rtl8xxxu_iter_stas_data iter_data; ++ struct rtl8xxxu_stas_entry *sta_entry, *tmp; ++ struct rtl8xxxu_priv *priv; + +- rtl8xxxu_refresh_rate_mask(priv, signal, sta, false); ++ priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work); ++ iter_data.priv = priv; ++ INIT_LIST_HEAD(&iter_data.list); ++ ++ mutex_lock(&priv->sta_mutex); ++ ieee80211_iterate_stations_atomic(priv->hw, rtl8xxxu_collect_sta_iter, ++ &iter_data); ++ list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, list) { ++ list_del_init(&sta_entry->list); ++ rtl8xxxu_ra_iter(priv, sta_entry->sta); ++ kfree(sta_entry); + } ++ mutex_unlock(&priv->sta_mutex); + + if (priv->fops->set_crystal_cap) + rtl8xxxu_track_cfo(priv); +@@ -7504,10 +7609,15 @@ static int rtl8xxxu_sta_add(struct ieee8 + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + ++ mutex_lock(&priv->sta_mutex); ++ ewma_rssi_init(&sta_info->avg_rssi); + if (vif->type == NL80211_IFTYPE_AP) { ++ sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT; + sta_info->macid = rtl8xxxu_acquire_macid(priv); +- if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM) ++ if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM) { ++ mutex_unlock(&priv->sta_mutex); + return -ENOSPC; ++ } + + rtl8xxxu_refresh_rate_mask(priv, 0, sta, true); + priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true); +@@ -7523,6 +7633,7 @@ static int rtl8xxxu_sta_add(struct ieee8 + break; + } + } ++ mutex_unlock(&priv->sta_mutex); + + return 0; + } +@@ -7534,8 +7645,10 @@ static int rtl8xxxu_sta_remove(struct ie + struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + ++ mutex_lock(&priv->sta_mutex); + if (vif->type == NL80211_IFTYPE_AP) + rtl8xxxu_release_macid(priv, sta_info->macid); ++ mutex_unlock(&priv->sta_mutex); + + return 0; + } +@@ -7766,6 +7879,7 @@ static int rtl8xxxu_probe(struct usb_int + mutex_init(&priv->usb_buf_mutex); + mutex_init(&priv->syson_indirect_access_mutex); + mutex_init(&priv->h2c_mutex); ++ mutex_init(&priv->sta_mutex); + INIT_LIST_HEAD(&priv->tx_urb_free_list); + spin_lock_init(&priv->tx_urb_lock); + INIT_LIST_HEAD(&priv->rx_urb_pending_list); diff --git a/package/kernel/mac80211/patches/rtl/009-v6.9-wifi-rtl8xxxu-check-vif-before-using-in-rtl8xxxu_tx.patch b/package/kernel/mac80211/patches/rtl/009-v6.9-wifi-rtl8xxxu-check-vif-before-using-in-rtl8xxxu_tx.patch new file mode 100644 index 0000000000..600f7c37df --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/009-v6.9-wifi-rtl8xxxu-check-vif-before-using-in-rtl8xxxu_tx.patch @@ -0,0 +1,40 @@ +From 513c559ca9f05394da79fbf20a8f89eec5f53dce Mon Sep 17 00:00:00 2001 +From: Ping-Ke Shih +Date: Fri, 16 Feb 2024 11:39:23 +0800 +Subject: [PATCH] wifi: rtl8xxxu: check vif before using in rtl8xxxu_tx() + +The 'vif' is from tx_info of SKB, and other codes check 'vif' before using, +which raises smatch warnings: + +drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:5656 rtl8xxxu_tx() + warn: variable dereferenced before check 'vif' (see line 5553) + +Compile tested only. + +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240216033923.34683-1-pkshih@realtek.com +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5550,7 +5550,7 @@ static void rtl8xxxu_tx(struct ieee80211 + struct rtl8xxxu_tx_urb *tx_urb; + struct ieee80211_sta *sta = NULL; + struct ieee80211_vif *vif = tx_info->control.vif; +- struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; ++ struct rtl8xxxu_vif *rtlvif = vif ? (struct rtl8xxxu_vif *)vif->drv_priv : NULL; + struct device *dev = &priv->udev->dev; + u32 queue, rts_rate; + u16 pktlen = skb->len; +@@ -5621,7 +5621,7 @@ static void rtl8xxxu_tx(struct ieee80211 + default: + break; + } +- if (bmc && rtlvif->hw_key_idx != 0xff) { ++ if (bmc && rtlvif && rtlvif->hw_key_idx != 0xff) { + tx_desc->txdw1 |= cpu_to_le32(TXDESC_EN_DESC_ID); + macid = rtlvif->hw_key_idx; + } diff --git a/package/kernel/mac80211/patches/rtl/010-v6.9-wifi-rtl8xxxu-fix-mixed-declarations-and-code-warnin.patch b/package/kernel/mac80211/patches/rtl/010-v6.9-wifi-rtl8xxxu-fix-mixed-declarations-and-code-warnin.patch new file mode 100644 index 0000000000..e1de784b09 --- /dev/null +++ b/package/kernel/mac80211/patches/rtl/010-v6.9-wifi-rtl8xxxu-fix-mixed-declarations-and-code-warnin.patch @@ -0,0 +1,34 @@ +From a7e178259c5bc900da762b33d3a20b7ee1206f07 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Fri, 23 Feb 2024 21:34:32 +0800 +Subject: [PATCH] wifi: rtl8xxxu: fix mixed declarations in rtl8xxxu_set_aifs() + +Moving struct ieee80211_sta *sta variable definition to the front +of the code to fix the ISO C90 forbids mixed declarations and code +warning. + +Fixes: 43532c050f8e ("wifi: rtl8xxxu: support multiple interfaces in set_aifs()") +Signed-off-by: Shiji Yang +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://msgid.link/TYAP286MB03157A408E0D69F2F6FBD88ABC552@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4919,11 +4919,11 @@ static void rtl8xxxu_set_aifs(struct rtl + int i; + + for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) { ++ struct ieee80211_sta *sta; ++ + if (!priv->vifs[i]) + continue; + +- struct ieee80211_sta *sta; +- + rcu_read_lock(); + sta = ieee80211_find_sta(priv->vifs[i], priv->vifs[i]->bss_conf.bssid); + if (sta) From 7e04a611bc798c27a0dc584959d2c2bdf64da05f Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Mon, 18 Dec 2023 01:06:21 +0900 Subject: [PATCH 010/108] ramips: add NMBM support for ipTIME AX2004M AX2004M uses NMBM on its NAND flash, but it was not enabled in DTS as the device support [1] had been added before NMBM feature in mtk_bmt driver [2]. Let's enable it now. With this change, there is a low possibility of boot failure after sysupgrade from older versions. As AX2004M already has gone through two stable releases in the meantime, it would be safe to warn users by bumping DEVICE_COMPAT_VERSION. [1] 37753f34ac68 ("ramips: add support for ipTIME AX2004M") [2] 06382d1af7b2 ("kernel: add support for mediatek NMBM flash mapping support") Signed-off-by: Sungbo Eo --- target/linux/ramips/dts/mt7621_iptime_ax2004m.dts | 7 +++++++ target/linux/ramips/image/mt7621.mk | 4 ++++ .../ramips/mt7621/base-files/etc/board.d/05_compat-version | 3 +++ 3 files changed, 14 insertions(+) diff --git a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts index 51be0d4939..7237bf822f 100644 --- a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts @@ -57,6 +57,11 @@ &nand { status = "okay"; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + mediatek,bmt-remap-range = <0x000000 0x580000>; + partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -118,6 +123,8 @@ reg = <0x400000 0x7280000>; }; }; + + /* last 8 MiB is reserved for NMBM bad block table */ }; }; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index ab1b829ba0..7b7266b73e 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1461,6 +1461,10 @@ define Device/iptime_ax2004m DEVICE_VENDOR := ipTIME DEVICE_MODEL := AX2004M DEVICE_PACKAGES := kmod-mt7915-firmware kmod-usb3 -uboot-envtools + DEVICE_COMPAT_VERSION := 2.0 + DEVICE_COMPAT_MESSAGE := NMBM has been newly enabled, and its flash block \ + mapping might be incompatible with existing installation. \ + New installation via recovery mode is recommended. endef TARGET_DEVICES += iptime_ax2004m diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/05_compat-version b/target/linux/ramips/mt7621/base-files/etc/board.d/05_compat-version index 45bef9385b..c510dfd81a 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/05_compat-version +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/05_compat-version @@ -8,6 +8,9 @@ board_config_update case "$(board_name)" in + iptime,ax2004m) + ucidef_set_compat_version "2.0" + ;; *) ucidef_set_compat_version "1.1" ;; From ec45f2f246363a4c2a84e51d0014848bf8c52e9f Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Sun, 4 Feb 2024 21:46:14 +0900 Subject: [PATCH 011/108] ramips: rename mtd partition of ipTIME NAND devices Contrary to common ipTIME NOR devices, the "Config" partition of T5004 and AX2004M contain normal U-Boot environment variables. Renaming the partition into "u-boot-env" serves for better description, and it also conforms to common naming practice in OpenWrt. This patch might also be extended to A3004T, but its u-boot-env partition layout has not been confirmed yet. Signed-off-by: Sungbo Eo --- package/boot/uboot-envtools/files/ramips | 2 ++ target/linux/ramips/dts/mt7621_iptime_ax2004m.dts | 3 +-- target/linux/ramips/dts/mt7621_iptime_t5004.dts | 3 +-- target/linux/ramips/image/mt7621.mk | 4 ++-- target/linux/ramips/mt7621/base-files/etc/board.d/02_network | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package/boot/uboot-envtools/files/ramips b/package/boot/uboot-envtools/files/ramips index 30bf635b6d..317121f2be 100644 --- a/package/boot/uboot-envtools/files/ramips +++ b/package/boot/uboot-envtools/files/ramips @@ -73,6 +73,7 @@ belkin,rt1800|\ h3c,tx1800-plus|\ h3c,tx1801-plus|\ h3c,tx1806|\ +iptime,ax2004m|\ jcg,q20|\ linksys,e7350|\ netgear,eax12|\ @@ -92,6 +93,7 @@ ravpower,rp-wd03) ubootenv_add_uci_config "/dev/mtd$idx" "0x4000" "0x1000" "0x1000" ;; beeline,smartbox-flash|\ +iptime,t5004|\ linksys,ea6350-v4|\ linksys,ea7300-v1|\ linksys,ea7300-v2|\ diff --git a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts index 7237bf822f..88067a4fa5 100644 --- a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts @@ -74,9 +74,8 @@ }; partition@80000 { - label = "config"; + label = "u-boot-env"; reg = <0x80000 0x80000>; - read-only; }; partition@100000 { diff --git a/target/linux/ramips/dts/mt7621_iptime_t5004.dts b/target/linux/ramips/dts/mt7621_iptime_t5004.dts index bba039a63c..f7a5e8ca17 100644 --- a/target/linux/ramips/dts/mt7621_iptime_t5004.dts +++ b/target/linux/ramips/dts/mt7621_iptime_t5004.dts @@ -53,9 +53,8 @@ }; partition@80000 { - label = "config"; + label = "u-boot-env"; reg = <0x80000 0xc0000>; - read-only; }; partition@140000 { diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 7b7266b73e..23e328a090 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1460,7 +1460,7 @@ define Device/iptime_ax2004m check-size | iptime-crc32 ax2004m DEVICE_VENDOR := ipTIME DEVICE_MODEL := AX2004M - DEVICE_PACKAGES := kmod-mt7915-firmware kmod-usb3 -uboot-envtools + DEVICE_PACKAGES := kmod-mt7915-firmware kmod-usb3 DEVICE_COMPAT_VERSION := 2.0 DEVICE_COMPAT_MESSAGE := NMBM has been newly enabled, and its flash block \ mapping might be incompatible with existing installation. \ @@ -1474,7 +1474,7 @@ define Device/iptime_t5004 UIMAGE_NAME := t5004 DEVICE_VENDOR := ipTIME DEVICE_MODEL := T5004 - DEVICE_PACKAGES := -wpad-basic-mbedtls -uboot-envtools + DEVICE_PACKAGES := -wpad-basic-mbedtls endef TARGET_DEVICES += iptime_t5004 diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index ae29da4adc..d0481b78e9 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -260,7 +260,7 @@ ramips_setup_macs() label_mac=$wan_mac ;; iptime,t5004) - lan_mac=$(mtd_get_mac_ascii config ethaddr) + lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) wan_mac=$(macaddr_add "$lan_mac" 1) ;; linksys,e5600|\ From b94ea518193778312f9f8f88f120b5104cf2327e Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Sun, 4 Feb 2024 22:10:29 +0900 Subject: [PATCH 012/108] ramips: mt7621: use variable for relocate-kernel argument The "0x80001000" address logically comes from "loadaddr-y" variable for mt7621 subtarget. Let's replace the hardcoded value with the predefined variable. This change is purely cosmetic. Signed-off-by: Sungbo Eo --- target/linux/ramips/image/mt7621.mk | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 23e328a090..b644d52708 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -497,7 +497,7 @@ define Device/belkin_rt1800 DEVICE_MODEL := RT1800 DEVICE_PACKAGES := kmod-mt7915-firmware kmod-usb3 KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | \ append-squashfs4-fakeroot IMAGES += factory.bin @@ -673,7 +673,7 @@ define Device/dlink_covr-x1860-a1 DEVICE_PACKAGES := kmod-mt7915-firmware UBINIZE_OPTS := -E 5 KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | \ append-squashfs4-fakeroot IMAGES += factory.bin recovery.bin @@ -712,7 +712,7 @@ define Device/dlink_dap-x1860-a1 DEVICE_VARIANT := A1 KERNEL_SIZE := 8192k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGES += factory.bin IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | \ @@ -1166,7 +1166,7 @@ define Device/h3c_tx180x KERNEL_SIZE := 8192k IMAGE_SIZE := 120832k KERNEL_LOADADDR := 0x82000000 - KERNEL_INITRAMFS := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL_INITRAMFS := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb KERNEL := $$(KERNEL_INITRAMFS) | h3c-blank-header DEVICE_VENDOR := H3C @@ -1195,7 +1195,7 @@ define Device/haier-sim_wr1800k $(Device/nand) IMAGE_SIZE := 125440k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) ARTIFACTS := initramfs-factory.bin @@ -1321,7 +1321,7 @@ define Device/iodata_wn-deax1800gr IMAGE_SIZE := 47104k UBINIZE_OPTS := -E 5 KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata ARTIFACTS := initramfs-factory.bin @@ -1453,7 +1453,7 @@ define Device/iptime_ax2004m $(Device/nand) IMAGE_SIZE := 121344k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGES += recovery.bin IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | \ @@ -1798,7 +1798,7 @@ define Device/netgear_eax12 NETGEAR_ENC_MODEL_LIST := EAX12;EAX11v2;EAX15v2 IMAGE_SIZE := 57344k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | \ append-squashfs4-fakeroot IMAGES += factory.img @@ -1985,7 +1985,7 @@ define Device/netgear_wax202 NETGEAR_ENC_REGION := US IMAGE_SIZE := 38912k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb | \ append-squashfs4-fakeroot IMAGES += factory.img @@ -2395,7 +2395,8 @@ define Device/tplink_er605-v2 DEVICE_PACKAGES := -wpad-basic-mbedtls kmod-usb3 -uboot-envtools KERNEL_IN_UBI := 1 KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGES += sysupgrade.tar IMAGE_SIZE := 127744k endef @@ -2409,7 +2410,7 @@ define Device/tplink_ex220-v1 DEVICE_PACKAGES := kmod-mt7915-firmware -uboot-envtools TPLINK_BOARD_ID := EX220-V1 KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGE_SIZE := 15744k endef @@ -2642,7 +2643,7 @@ define Device/wavlink_ws-wn572hp3-4g DEVICE_VARIANT := 4G IMAGE_SIZE := 15040k KERNEL_LOADADDR := 0x82000000 - KERNEL := kernel-bin | relocate-kernel 0x80001000 | lzma | \ + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ append-rootfs | pad-rootfs | check-size | append-metadata From 85a8f58483b223951515219ca9b21c31c36f87c8 Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Mon, 5 Feb 2024 03:57:27 +0900 Subject: [PATCH 013/108] ramips: add factory image for ipTIME AX2004M Unlike the recovery image, this initramfs-factory image can be flashed using the stock firmware web interface (from any active boot partition), as well as the bootloader recovery web page. Drop the recovery image in favor of the factory image. Installation via stock/recovery web interface: 1. Flash **initramfs-factory** image through the web page. 2. Boot into OpenWrt and perform sysupgrade with sysupgrade image. Signed-off-by: Sungbo Eo --- target/linux/ramips/image/mt7621.mk | 6 +++--- .../linux/ramips/mt7621/base-files/lib/upgrade/platform.sh | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index b644d52708..2ab687fd02 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1455,8 +1455,8 @@ define Device/iptime_ax2004m KERNEL_LOADADDR := 0x82000000 KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb - IMAGES += recovery.bin - IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | \ + ARTIFACTS := initramfs-factory.bin + ARTIFACT/initramfs-factory.bin := append-image-stage initramfs-kernel.bin | \ check-size | iptime-crc32 ax2004m DEVICE_VENDOR := ipTIME DEVICE_MODEL := AX2004M @@ -1464,7 +1464,7 @@ define Device/iptime_ax2004m DEVICE_COMPAT_VERSION := 2.0 DEVICE_COMPAT_MESSAGE := NMBM has been newly enabled, and its flash block \ mapping might be incompatible with existing installation. \ - New installation via recovery mode is recommended. + New installation with factory image via recovery mode is recommended. endef TARGET_DEVICES += iptime_ax2004m diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh index 40a2fb61db..6151714145 100755 --- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh @@ -33,6 +33,11 @@ platform_do_upgrade() { fw_setenv --lock / bootImage 0 || exit 1 fi ;; + iptime,ax2004m) + if [ "$(fw_printenv -n boot_from 2>/dev/null)" != "firmware1" ]; then + fw_setenv boot_from firmware1 || exit 1 + fi + ;; mikrotik,ltap-2hnd|\ mikrotik,routerboard-750gr3|\ mikrotik,routerboard-760igs|\ From 261876a067fbf753d50459e3a88354ff873af422 Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Sun, 10 Mar 2024 13:55:24 +0900 Subject: [PATCH 014/108] ramips: improve support for STORYLiNK SAP-G3200U3 * Increase flash SPI frequency to 50MHz The maximum SPI frequency of MX25L6406EM2I is 86 MHz, but in this patch 50 MHz was chosen as a safe value. * Update Ethernet MAC addresses Till now LAN/WAN MAC addresses were flipped compared to stock firmware. * Fix Wi-Fi LEDs by adding mt76 led nodes * Fix LAN port order LAN ports are in reverse order of switch ports. * Fix the well-known "LZMA ERROR 1" error by using lzma-loader * Set uImage name, which enables installation via stock web interface: 1. Upload **initramfs** image file to the web page. 2. Boot into OpenWrt and perform sysupgrade with sysupgrade image. Signed-off-by: Sungbo Eo --- .../dts/mt7621_storylink_sap-g3200u3.dts | 37 +++++++++++++------ target/linux/ramips/image/mt7621.mk | 2 + 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts index 7b89ee6727..3448db5f03 100644 --- a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts +++ b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts @@ -43,7 +43,8 @@ flash@0 { compatible = "jedec,spi-nor"; reg = <0>; - spi-max-frequency = <10000000>; + spi-max-frequency = <50000000>; + m25p,fast-read; partitions { compatible = "fixed-partitions"; @@ -86,10 +87,12 @@ reg = <0x8000 0x200>; }; + macaddr_factory_e000: macaddr@e000 { + reg = <0xe000 0x6>; + }; + macaddr_factory_e006: macaddr@e006 { - compatible = "mac-base"; reg = <0xe006 0x6>; - #nvmem-cell-cells = <1>; }; }; }; @@ -108,25 +111,37 @@ }; &pcie0 { - mt76@0,0 { + wifi@0,0 { + compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_8000>; nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; + + led { + led-sources = <2>; + led-active-low; + }; }; }; &pcie1 { - mt76@0,0 { + wifi@0,0 { + compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_0>; nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; + + led { + led-sources = <2>; + led-active-low; + }; }; }; &gmac0 { - nvmem-cells = <&macaddr_factory_e006 0>; + nvmem-cells = <&macaddr_factory_e000>; nvmem-cell-names = "mac-address"; }; @@ -135,7 +150,7 @@ label = "wan"; phy-handle = <ðphy4>; - nvmem-cells = <&macaddr_factory_e006 1>; + nvmem-cells = <&macaddr_factory_e006>; nvmem-cell-names = "mac-address"; }; @@ -149,22 +164,22 @@ ports { port@0 { status = "okay"; - label = "lan1"; + label = "lan4"; }; port@1 { status = "okay"; - label = "lan2"; + label = "lan3"; }; port@2 { status = "okay"; - label = "lan3"; + label = "lan2"; }; port@3 { status = "okay"; - label = "lan4"; + label = "lan1"; }; }; }; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 2ab687fd02..a46ea39d59 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -2190,7 +2190,9 @@ TARGET_DEVICES += snr_snr-cpe-me2-sfp define Device/storylink_sap-g3200u3 $(Device/dsa-migration) + $(Device/uimage-lzma-loader) IMAGE_SIZE := 7872k + UIMAGE_NAME := SAP-G3200 DEVICE_VENDOR := STORYLiNK DEVICE_MODEL := SAP-G3200U3 DEVICE_PACKAGES := kmod-mt76x2 kmod-usb3 kmod-usb-ledtrig-usbport \ From db0d7cf6a19f909a3cce958c5a8457511c1179e8 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Mon, 1 Jan 2024 13:50:46 +0100 Subject: [PATCH 015/108] usb: add cdns3 support CDNS3 is a SuperSpeed (SS) USB 3.0 Dual-Role-Device (DRD) controller from Cadence. Add support for this device, and add the required symbols into the generic configs. Compile-tested: apm821xx, bcm4908, imx, mpc85xx, pistachio, starfive Signed-off-by: Zoltan HERPAI --- package/kernel/linux/modules/usb.mk | 38 +++++++++++++++++++++++++++++ target/linux/generic/config-5.15 | 3 +++ target/linux/generic/config-6.1 | 3 +++ 3 files changed, 44 insertions(+) diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk index 7f9e627fdb..f4a2113e17 100644 --- a/package/kernel/linux/modules/usb.mk +++ b/package/kernel/linux/modules/usb.mk @@ -459,6 +459,44 @@ endef $(eval $(call KernelPackage,usb-dwc2-pci)) +define KernelPackage/usb-cdns + TITLE:=Cadence USB USB controller driver + DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget +kmod-usb-roles + KCONFIG:= \ + CONFIG_USB_CDNS_SUPPORT + FILES:= $(LINUX_DIR)/drivers/usb/cdns3/cdns-usb-common.ko + AUTOLOAD:=$(call AutoLoad,50,cdns-usb-common,1) + $(call AddDepends/usb) +endef + +define KernelPackage/usb-cdns/description + This driver provides USB Device Controller support for the + Cadence USB Core +endef + +$(eval $(call KernelPackage,usb-cdns)) + + +define KernelPackage/usb-cdns3 + TITLE:=Cadence USB3 USB controller driver + DEPENDS:=+kmod-usb-cdns + KCONFIG:= \ + CONFIG_USB_CDNS3 \ + CONFIG_USB_CDNS3_GADGET=y \ + CONFIG_USB_CDNS3_HOST=y + FILES:= $(LINUX_DIR)/drivers/usb/cdns3/cdns3.ko + AUTOLOAD:=$(call AutoLoad,54,cdns3,1) + $(call AddDepends/usb) +endef + +define KernelPackage/usb-cdns3/description + This driver provides support for the Dual Role SuperSpeed + USB Controller based on the Cadence USB3 IP Core +endef + +$(eval $(call KernelPackage,usb-cdns3)) + + define KernelPackage/usb-dwc3 TITLE:=DWC3 USB controller driver KCONFIG:= \ diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 6070000dd4..8f6ccad216 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -6833,7 +6833,10 @@ CONFIG_USB_BELKIN=y # CONFIG_USB_CATC is not set # CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_IMX is not set +# CONFIG_USB_CDNS3_PCI_WRAP is not set # CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNSP_PCI is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_CHIPIDEA_GENERIC is not set diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 34a6503ce0..deecb62ba8 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -7117,7 +7117,10 @@ CONFIG_USB_BELKIN=y # CONFIG_USB_CATC is not set # CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_IMX is not set +# CONFIG_USB_CDNS3_PCI_WRAP is not set # CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNSP_PCI is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_CHIPIDEA_GENERIC is not set From 4070e2a64c524b1de38573700ba1c4fcc79de1bf Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 28 May 2023 15:14:02 +0200 Subject: [PATCH 016/108] starfive: add new target for StarFive JH7100/7110 SoC This target adds support for the StarFive JH7100 and JH7110 SoCs, based on 6.1, as well as a couple boards equipped with these. Specifications: SoCs: JH7100: - StarFive JH7100 dual-core RISC-V (U74, RC64GC) - additional monitoring (S7) and control (E24) cores - 2Mb L2 cache JH7110: - StarFive JH7110 quad-core RISC-V (U74, RV64GC) - additional monitoring (S7) and control (E24) cores - 2Mb L2 cache Boards: VisionFive1: - JH7100 @ 1GHz - Memory: 8Gb LPDDR4 - 4x USB3.0 - 1x GBit ethernet - AMPak 6236 wifi / bluetooth - audio - powered via USB-C VisionFive2: - JH7110 @ 1.5GHz - Memory: 2/4/8Gb DDR4 - 2x Gbit ethernet - 2x USB3.0 / 2x USB2.0 - eMMC / SDIO - various multimedia input/outputs (MIPI CSI, HDMI, audio) - M.2 key M slot - PoE support - powered via USB-C Installation: Standard SD-card installation via dd-ing the generated image to an SD-card of at least 256Mb. Signed-off-by: Zoltan HERPAI --- target/linux/starfive/Makefile | 21 + .../base-files/etc/board.d/02_network | 22 + target/linux/starfive/base-files/etc/inittab | 4 + .../lib/firmware/brcm/brcmfmac43430-sdio.txt | 53 + .../firmware/brcm/brcmfmac43430a0-sdio.txt | 1 + target/linux/starfive/config-6.1 | 555 ++++++ target/linux/starfive/generic/target.mk | 1 + target/linux/starfive/image/Config.in | 5 + target/linux/starfive/image/Makefile | 85 + .../starfive/image/gen_starfive_sdcard_img.sh | 24 + .../starfive/image/mmc.bootscript.jh7100 | 4 + .../starfive/image/mmc.bootscript.jh7110 | 5 + target/linux/starfive/modules.mk | 31 + ...k-Add-StarFive-JH7110-system-clock-a.patch | 482 +++++ ...k-Add-StarFive-JH7110-always-on-cloc.patch | 176 ++ ...lace-SOC_STARFIVE-with-ARCH_STARFIVE.patch | 53 + ...tor-out-common-JH7100-and-JH7110-cod.patch | 749 ++++++++ ...ame-clk-starfive-jh7100.h-to-clk-sta.patch | 290 +++ ...ame-jh7100-to-jh71x0-for-the-common-.patch | 1249 ++++++++++++ ...eplace-SOC_STARFIVE-with-ARCH_STARFI.patch | 30 + ...te-subdirectory-for-StarFive-drivers.patch | 436 +++++ ...-Factor-out-common-JH71X0-reset-code.patch | 390 ++++ ...Extract-the-common-JH71X0-reset-code.patch | 215 +++ ...ename-jh7100-to-jh71x0-for-the-commo.patch | 167 ++ ...h71x0-Use-32bit-I-O-on-32bit-registe.patch | 146 ++ ...-StarFive-JH7110-system-clock-driver.patch | 557 ++++++ ...-StarFive-JH7110-always-on-clock-dri.patch | 206 ++ ...ive-Add-StarFive-JH7110-reset-driver.patch | 113 ++ ...eneralise-StarFive-clk-reset-entries.patch | 50 + ...tarfive-Avoid-casting-iomem-pointers.patch | 128 ++ ...ings-timer-Add-StarFive-JH7110-clint.patch | 27 + ...rrupt-controller-Add-StarFive-JH7110.patch | 28 + ...dings-riscv-Add-SiFive-S7-compatible.patch | 27 + ...ve-Add-initial-StarFive-JH7110-devic.patch | 549 ++++++ ...ve-Add-StarFive-JH7110-pin-function-.patch | 331 ++++ ...ve-Add-StarFive-JH7110-VisionFive-2-.patch | 290 +++ ...ve-Add-StarFive-VisionFive-V1-device.patch | 43 + ...ve-Add-common-DT-for-JH7100-based-bo.patch | 349 ++++ ...ctrl-Add-StarFive-JH7110-sys-pinctrl.patch | 303 +++ ...ctrl-Add-StarFive-JH7110-aon-pinctrl.patch | 176 ++ ...-Add-StarFive-JH7110-sys-controller-.patch | 1581 +++++++++++++++ ...-Add-StarFive-JH7110-aon-controller-.patch | 224 +++ ...g-add-jh7110-defconfig-for-test-mini.patch | 228 +++ ...k-Add-StarFive-JH7110-PLL-clock-gene.patch | 80 + ...Add-StarFive-JH7110-PLL-clock-driver.patch | 786 ++++++++ ...k-jh7110-syscrg-Add-PLL-clock-inputs.patch | 75 + ...-jh7110-sys-Modify-PLL-clocks-source.patch | 71 + ...ndings-power-Add-starfive-jh7110-pmu.patch | 86 + ...rfive-Add-StarFive-JH71XX-pmu-driver.patch | 478 +++++ ...-starfive-Add-StarFive-syscon-module.patch | 98 + ...dts-starfive-jh7110-Add-syscon-nodes.patch | 52 + ...ve-jh7110-Add-PLL-clock-node-and-mod.patch | 48 + ...et-snps-dwmac-Add-dwmac-5.20-version.patch | 49 + ...orm-Add-snps-dwmac-5.20-IP-compatibl.patch | 29 + ...-snps-dwmac-Add-ahb-reset-reset-name.patch | 46 + ...dings-net-Add-support-StarFive-dwmac.patch | 190 ++ ...d-glue-layer-for-StarFive-JH7110-SoC.patch | 187 ++ ...-starfive-Add-phy-interface-settings.patch | 93 + ...ive-jh7110-Add-ethernet-device-nodes.patch | 101 + ...ve-visionfive-2-Add-configuration-of.patch | 128 ++ ...et-Add-Motorcomm-yt8xxx-ethernet-phy.patch | 147 ++ ...motorcomm-Add-pad-driver-strength-cf.patch | 34 + ...ve-visionfive-2-v1.3B-Set-the-driver.patch | 34 + ...k-Add-StarFive-JH7110-System-Top-Gro.patch | 193 ++ ...-StarFive-JH7110-System-Top-Group-cl.patch | 218 +++ ...k-Add-StarFive-JH7110-Image-Signal-P.patch | 156 ++ ...-StarFive-JH7110-Image-Signal-Proces.patch | 293 +++ ...k-Add-StarFive-JH7110-Video-Output-c.patch | 163 ++ ...-StarFive-JH7110-Video-Output-clock-.patch | 284 +++ ...h7110-Add-StarFive-STG-ISP-VOUT-rese.patch | 61 + ...rfive-update-jh7110-PLL-clock-driver.patch | 819 ++++++++ ...er-Add-timer-for-StarFive-JH7110-SoC.patch | 113 ++ ...locksource-Add-StarFive-timer-driver.patch | 540 ++++++ ...motorcomm-Add-pad-driver-strength-cf.patch | 36 + ...bindings-PWM-Add-StarFive-PWM-module.patch | 71 + ...-pwm-starfive-Add-PWM-driver-support.patch | 294 +++ ...gs-crypto-Add-StarFive-crypto-module.patch | 90 + ...o-starfive-Add-crypto-engine-support.patch | 337 ++++ ...pto-starfive-Fix-driver-dependencies.patch | 29 + ...-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch | 23 + ...-Add-TDM-controller-bindings-for-Sta.patch | 117 ++ ...-ASoC-starfive-Add-JH7110-TDM-driver.patch | 744 ++++++++ ...r-Add-power-domain-header-for-JH7110.patch | 32 + ...lace-SOC_STARFIVE-with-ARCH_STARFIVE.patch | 28 + ...xtract-JH7110-pmu-private-operations.patch | 175 ++ ...-starfive-Add-JH7110-AON-PMU-support.patch | 119 ++ ...ings-phy-Add-starfive-jh7110-dphy-rx.patch | 88 + ...hy-starfive-Add-mipi-dphy-rx-support.patch | 365 ++++ ...s-cadence-csi2rx-Convert-to-DT-schem.patch | 306 +++ ...s-cadence-csi2rx-Add-resets-property.patch | 55 + ...media-cadence-Add-operation-on-reset.patch | 129 ++ ...adence-Add-support-for-external-dphy.patch | 141 ++ ...a-cadence-Add-support-for-JH7110-SoC.patch | 23 + ...bindings-Add-JH7110-Camera-Subsystem.patch | 197 ++ ...e-Add-starfive_camss.rst-for-Starfiv.patch | 106 ++ ...0083-media-starfive-Add-basic-driver.patch | 630 ++++++ ...0084-media-starfive-Add-video-driver.patch | 992 ++++++++++ .../0085-media-starfive-Add-ISP-driver.patch | 1667 ++++++++++++++++ .../0086-media-starfive-Add-VIN-driver.patch | 1694 +++++++++++++++++ ...ings-phy-Add-StarFive-JH7110-USB-PHY.patch | 68 + ...ngs-phy-Add-StarFive-JH7110-PCIe-PHY.patch | 77 + ...arfive-Add-JH7110-USB-2.0-PHY-driver.patch | 192 ++ ...rfive-Add-JH7110-PCIE-2.0-PHY-driver.patch | 250 +++ ...b-Add-StarFive-JH7110-USB-controller.patch | 135 ++ ...-cdns-qspi-nor-constrain-minItems-ma.patch | 78 + ...cdns3-Add-StarFive-JH7110-USB-driver.patch | 298 +++ ...add-JH7110-PCIe-dt-binding-documents.patch | 181 ++ ...spi-Add-support-for-StarFive-JH7110-.patch | 79 + ...five-add-StarFive-JH7110-PCIe-driver.patch | 1004 ++++++++++ ...tdev-Add-JH7110-SOC-to-the-allowlist.patch | 24 + ...ve-Add-full-support-for-JH7110-and-V.patch | 1034 ++++++++++ ...099-update-jh7110_defconfig-for-test.patch | 48 + .../patches-6.1/0100-Add-readme.patch | 75 + ...indings-rng-Add-StarFive-TRNG-module.patch | 76 + ...ive-Add-TRNG-driver-for-StarFive-SoC.patch | 457 +++++ ...wrng-starfive-Enable-compile-testing.patch | 28 + ...hdog-Add-watchdog-for-StarFive-JH710.patch | 91 + ...atchdog-Add-StarFive-Watchdog-driver.patch | 675 +++++++ ...ts-starfive-jh7100-Add-watchdog-node.patch | 31 + ...bindings-mmc-Add-StarFive-MMC-module.patch | 95 + ...tarfive-Add-sdio-emmc-driver-support.patch | 250 +++ ...dings-hwmon-Add-starfive-jh71x0-temp.patch | 89 + ...d-StarFive-JH71x0-temperature-sensor.patch | 451 +++++ ...snps-dw-axi-dmac-constrain-the-items.patch | 62 + ...-dmac-Add-support-for-StarFive-JH711.patch | 122 ++ ...-dmac-Increase-polling-time-to-DMA-t.patch | 29 + ...spend_save_csrs-and-suspend_restore_.patch | 50 + ...ut-common-code-of-__cpu_resume_enter.patch | 136 ++ ...functions-to-support-hibernation-sus.patch | 673 +++++++ ...-mfd-axp20x-Add-support-for-AXP15060.patch | 1014 ++++++++++ ...ator-axp20x-Support-AXP15060-variant.patch | 434 +++++ ...iscv-dts-visionfive2-add-EEPROM-node.patch | 25 + ...iscv-dts-visionfive2-add-mmc-aliases.patch | 21 + ...rs-include-cpufreq-Kconfig-for-riscv.patch | 21 + ...110-sys-Fix-lower-rate-of-CPUfreq-by.patch | 92 + ...ac-dwmac-starfive-Add-JH7100-support.patch | 63 + ...syscon-Add-StarFive-JH7100-sysmain-c.patch | 23 + ...dd-starfive-jh7100-hsuart-compatible.patch | 25 + ...ve-Group-tuples-in-interrupt-propert.patch | 40 + ...Add-StarFive-JH7100-audio-clock-node.patch | 32 + ...Five-JH7100-as-having-non-coherent-D.patch | 21 + ...serial-8250-update-driver-for-JH7100.patch | 28 + ...-dmac-Handle-xfer-start-while-non-id.patch | 55 + ...axi-dmac-Add-StarFive-JH7100-support.patch | 64 + ...nctrl-starfive-Reset-pinmux-settings.patch | 127 ++ ...-flags-argument-to-JH71X0__MUX-macro.patch | 302 +++ ...100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch | 25 + ...arfive-jh7100-Keep-more-clocks-alive.patch | 94 + .../1013-net-stmmac-use-GFP_DMA32.patch | 30 + ...ve-JH7100-Random-Number-Generator-dr.patch | 477 +++++ ...sifive-ptc-Add-SiFive-PWM-PTC-driver.patch | 309 +++ ...non-coherent-DMA-support-via-SiFive-.patch | 105 + ...v-sifive-ccache-Add-uncached-offset-.patch | 30 + ...e-ccache-Add-StarFive-JH71x0-support.patch | 77 + ...ccache-Add-non-coherent-DMA-handling.patch | 159 ++ ...t-Add-StarFive-JH7100-audio-reset-de.patch | 48 + ...t-Add-starfive-jh7100-audrst-binding.patch | 56 + ...arfive-Add-JH7100-audio-reset-driver.patch | 144 ++ ...Add-StarFive-JH7100-audio-reset-node.patch | 28 + ...ll-JH7100-Starlight-and-VisionFive-s.patch | 1265 ++++++++++++ ...25-riscv-dts-visionfive1-enable-QSPI.patch | 20 + 161 files changed, 36656 insertions(+) create mode 100644 target/linux/starfive/Makefile create mode 100644 target/linux/starfive/base-files/etc/board.d/02_network create mode 100644 target/linux/starfive/base-files/etc/inittab create mode 100644 target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt create mode 120000 target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt create mode 100644 target/linux/starfive/config-6.1 create mode 100644 target/linux/starfive/generic/target.mk create mode 100644 target/linux/starfive/image/Config.in create mode 100644 target/linux/starfive/image/Makefile create mode 100755 target/linux/starfive/image/gen_starfive_sdcard_img.sh create mode 100644 target/linux/starfive/image/mmc.bootscript.jh7100 create mode 100644 target/linux/starfive/image/mmc.bootscript.jh7110 create mode 100644 target/linux/starfive/modules.mk create mode 100644 target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch create mode 100644 target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch create mode 100644 target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch create mode 100644 target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch create mode 100644 target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch create mode 100644 target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch create mode 100644 target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch create mode 100644 target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch create mode 100644 target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch create mode 100644 target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch create mode 100644 target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch create mode 100644 target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch create mode 100644 target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch create mode 100644 target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch create mode 100644 target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch create mode 100644 target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch create mode 100644 target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch create mode 100644 target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch create mode 100644 target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch create mode 100644 target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch create mode 100644 target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch create mode 100644 target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch create mode 100644 target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch create mode 100644 target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch create mode 100644 target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch create mode 100644 target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch create mode 100644 target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch create mode 100644 target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch create mode 100644 target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch create mode 100644 target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch create mode 100644 target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch create mode 100644 target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch create mode 100644 target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch create mode 100644 target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch create mode 100644 target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch create mode 100644 target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch create mode 100644 target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch create mode 100644 target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch create mode 100644 target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch create mode 100644 target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch create mode 100644 target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch create mode 100644 target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch create mode 100644 target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch create mode 100644 target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch create mode 100644 target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch create mode 100644 target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch create mode 100644 target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch create mode 100644 target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch create mode 100644 target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch create mode 100644 target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch create mode 100644 target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch create mode 100644 target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch create mode 100644 target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch create mode 100644 target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch create mode 100644 target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch create mode 100644 target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch create mode 100644 target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch create mode 100644 target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch create mode 100644 target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch create mode 100644 target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch create mode 100644 target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch create mode 100644 target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch create mode 100644 target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch create mode 100644 target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch create mode 100644 target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch create mode 100644 target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch create mode 100644 target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch create mode 100644 target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch create mode 100644 target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch create mode 100644 target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch create mode 100644 target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch create mode 100644 target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch create mode 100644 target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch create mode 100644 target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch create mode 100644 target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch create mode 100644 target/linux/starfive/patches-6.1/0088-dt-bindings-phy-Add-StarFive-JH7110-PCIe-PHY.patch create mode 100644 target/linux/starfive/patches-6.1/0089-phy-starfive-Add-JH7110-USB-2.0-PHY-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0090-phy-starfive-Add-JH7110-PCIE-2.0-PHY-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0091-dt-bindings-usb-Add-StarFive-JH7110-USB-controller.patch create mode 100644 target/linux/starfive/patches-6.1/0092-dt-bindings-qspi-cdns-qspi-nor-constrain-minItems-ma.patch create mode 100644 target/linux/starfive/patches-6.1/0093-usb-cdns3-Add-StarFive-JH7110-USB-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0094-dt-binding-pci-add-JH7110-PCIe-dt-binding-documents.patch create mode 100644 target/linux/starfive/patches-6.1/0095-spi-cadence-quadspi-Add-support-for-StarFive-JH7110-.patch create mode 100644 target/linux/starfive/patches-6.1/0096-pcie-starfive-add-StarFive-JH7110-PCIe-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0097-cpufreq-dt-platdev-Add-JH7110-SOC-to-the-allowlist.patch create mode 100644 target/linux/starfive/patches-6.1/0098-riscv-dts-starfive-Add-full-support-for-JH7110-and-V.patch create mode 100644 target/linux/starfive/patches-6.1/0099-update-jh7110_defconfig-for-test.patch create mode 100644 target/linux/starfive/patches-6.1/0100-Add-readme.patch create mode 100644 target/linux/starfive/patches-6.1/0101-dt-bindings-rng-Add-StarFive-TRNG-module.patch create mode 100644 target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch create mode 100644 target/linux/starfive/patches-6.1/0103-hwrng-starfive-Enable-compile-testing.patch create mode 100644 target/linux/starfive/patches-6.1/0104-dt-bindings-watchdog-Add-watchdog-for-StarFive-JH710.patch create mode 100644 target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch create mode 100644 target/linux/starfive/patches-6.1/0106-riscv-dts-starfive-jh7100-Add-watchdog-node.patch create mode 100644 target/linux/starfive/patches-6.1/0107-dt-bindings-mmc-Add-StarFive-MMC-module.patch create mode 100644 target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch create mode 100644 target/linux/starfive/patches-6.1/0109-dt-bindings-hwmon-Add-starfive-jh71x0-temp.patch create mode 100644 target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch create mode 100644 target/linux/starfive/patches-6.1/0111-dt-bindings-dma-snps-dw-axi-dmac-constrain-the-items.patch create mode 100644 target/linux/starfive/patches-6.1/0112-dmaengine-dw-axi-dmac-Add-support-for-StarFive-JH711.patch create mode 100644 target/linux/starfive/patches-6.1/0113-dmaengine-dw-axi-dmac-Increase-polling-time-to-DMA-t.patch create mode 100644 target/linux/starfive/patches-6.1/0114-RISC-V-Change-suspend_save_csrs-and-suspend_restore_.patch create mode 100644 target/linux/starfive/patches-6.1/0115-RISC-V-Factor-out-common-code-of-__cpu_resume_enter.patch create mode 100644 target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch create mode 100644 target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch create mode 100644 target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch create mode 100644 target/linux/starfive/patches-6.1/0119-riscv-dts-visionfive2-add-EEPROM-node.patch create mode 100644 target/linux/starfive/patches-6.1/0120-riscv-dts-visionfive2-add-mmc-aliases.patch create mode 100644 target/linux/starfive/patches-6.1/0121-drivers-include-cpufreq-Kconfig-for-riscv.patch create mode 100644 target/linux/starfive/patches-6.1/0126-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch create mode 100644 target/linux/starfive/patches-6.1/1000-net-stmmac-dwmac-starfive-Add-JH7100-support.patch create mode 100644 target/linux/starfive/patches-6.1/1001-dt-bindings-mfd-syscon-Add-StarFive-JH7100-sysmain-c.patch create mode 100644 target/linux/starfive/patches-6.1/1002-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch create mode 100644 target/linux/starfive/patches-6.1/1003-riscv-dts-starfive-Group-tuples-in-interrupt-propert.patch create mode 100644 target/linux/starfive/patches-6.1/1004-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch create mode 100644 target/linux/starfive/patches-6.1/1005-RISC-V-Mark-StarFive-JH7100-as-having-non-coherent-D.patch create mode 100644 target/linux/starfive/patches-6.1/1006-drivers-tty-serial-8250-update-driver-for-JH7100.patch create mode 100644 target/linux/starfive/patches-6.1/1007-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch create mode 100644 target/linux/starfive/patches-6.1/1008-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch create mode 100644 target/linux/starfive/patches-6.1/1009-pinctrl-starfive-Reset-pinmux-settings.patch create mode 100644 target/linux/starfive/patches-6.1/1010-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch create mode 100644 target/linux/starfive/patches-6.1/1011-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch create mode 100644 target/linux/starfive/patches-6.1/1012-clk-starfive-jh7100-Keep-more-clocks-alive.patch create mode 100644 target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch create mode 100644 target/linux/starfive/patches-6.1/1014-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch create mode 100644 target/linux/starfive/patches-6.1/1015-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch create mode 100644 target/linux/starfive/patches-6.1/1016-riscv-Implement-non-coherent-DMA-support-via-SiFive-.patch create mode 100644 target/linux/starfive/patches-6.1/1017-dt-bindings-riscv-sifive-ccache-Add-uncached-offset-.patch create mode 100644 target/linux/starfive/patches-6.1/1018-soc-sifive-ccache-Add-StarFive-JH71x0-support.patch create mode 100644 target/linux/starfive/patches-6.1/1019-soc-sifive-ccache-Add-non-coherent-DMA-handling.patch create mode 100644 target/linux/starfive/patches-6.1/1020-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch create mode 100644 target/linux/starfive/patches-6.1/1021-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch create mode 100644 target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch create mode 100644 target/linux/starfive/patches-6.1/1023-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch create mode 100644 target/linux/starfive/patches-6.1/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch create mode 100644 target/linux/starfive/patches-6.1/1025-riscv-dts-visionfive1-enable-QSPI.patch diff --git a/target/linux/starfive/Makefile b/target/linux/starfive/Makefile new file mode 100644 index 0000000000..f71f57e7f7 --- /dev/null +++ b/target/linux/starfive/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2024 Toco Technologies +# +include $(TOPDIR)/rules.mk + +ARCH:=riscv64 +BOARD:=starfive +BOARDNAME:=StarFive JH71x0 (7100/7110) +FEATURES:=ext4 +KERNELNAME:=Image dtbs + +KERNEL_PATCHVER:=6.1 + +include $(INCLUDE_DIR)/target.mk + +define Target/Description + Build firmware images for the StarFive JH71x0-based boards +endef + +$(eval $(call BuildTarget)) diff --git a/target/linux/starfive/base-files/etc/board.d/02_network b/target/linux/starfive/base-files/etc/board.d/02_network new file mode 100644 index 0000000000..bd9947ad49 --- /dev/null +++ b/target/linux/starfive/base-files/etc/board.d/02_network @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2022 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh + +board_config_update + +case "$(board_name)" in +starfive,visionfive-2-v1.3b|\ +starfive,visionfive-2-v1.2a) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ;; +*) + ucidef_set_interface_lan 'eth0' + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/starfive/base-files/etc/inittab b/target/linux/starfive/base-files/etc/inittab new file mode 100644 index 0000000000..d1b5a0fa22 --- /dev/null +++ b/target/linux/starfive/base-files/etc/inittab @@ -0,0 +1,4 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +ttyS0::askfirst:/usr/libexec/login.sh +tty1::askfirst:/usr/libexec/login.sh diff --git a/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt b/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt new file mode 100644 index 0000000000..9baa5c33bf --- /dev/null +++ b/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt @@ -0,0 +1,53 @@ +#AP6212_NVRAM_V1.0_20140603 +# 2.4 GHz, 20 MHz BW mode + +# The following parameter values are just placeholders, need to be updated. +manfid=0x2d0 +prodid=0x0726 +vendid=0x14e4 +devid=0x43e2 +boardtype=0x0726 +boardrev=0x1101 +boardnum=22 +macaddr=00:90:4c:c5:12:38 +sromrev=11 +boardflags=0x00404201 +xtalfreq=26000 +nocrc=1 +ag0=255 +aa2g=1 +ccode=ALL + +pa0itssit=0x20 +extpagain2g=0 + +#PA parameters for 2.4GHz, measured at CHIP OUTPUT +pa2ga0=-168,7161,-820 +AvVmid_c0=0x0,0xc8 +cckpwroffset0=5 + +# PPR params +maxp2ga0=90 +txpwrbckof=6 +cckbw202gpo=0x5555 +legofdmbw202gpo=0x77777777 +mcsbw202gpo=0xaaaaaaaa + +# OFDM IIR : +ofdmdigfilttype=7 +# PAPD mode: +papdmode=2 + +il0macaddr=00:90:4c:c5:12:38 +wl0id=0x431b + +#OOB parameters +hostwake=0x40 +hostrdy=0x41 +usbrdy=0x03 +usbrdydelay=100 +deadman_to=0xffffffff +# muxenab: 0x1 for UART enable, 0x10 for Host awake +muxenab=0x10 +# CLDO PWM voltage settings - 0x4 - 1.1 volt +#cldo_pwm=0x4 diff --git a/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt b/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt new file mode 120000 index 0000000000..2ed6689828 --- /dev/null +++ b/target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt @@ -0,0 +1 @@ +brcmfmac43430-sdio.txt \ No newline at end of file diff --git a/target/linux/starfive/config-6.1 b/target/linux/starfive/config-6.1 new file mode 100644 index 0000000000..6da229ddb5 --- /dev/null +++ b/target/linux/starfive/config-6.1 @@ -0,0 +1,555 @@ +CONFIG_64BIT=y +CONFIG_AMBA_PL08X=y +CONFIG_ARCH_CLOCKSOURCE_INIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_RV64I=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SIFIVE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_STARFIVE=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM_AMBA=y +# CONFIG_ARM_MHU_V2 is not set +CONFIG_ASN1=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_AUXILIARY_BUS=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y +CONFIG_CLK_SIFIVE=y +CONFIG_CLK_SIFIVE_PRCI=y +CONFIG_CLK_STARFIVE_JH7100=y +CONFIG_CLK_STARFIVE_JH7100_AUDIO=y +CONFIG_CLK_STARFIVE_JH7110_AON=y +CONFIG_CLK_STARFIVE_JH7110_ISP=y +CONFIG_CLK_STARFIVE_JH7110_PLL=y +CONFIG_CLK_STARFIVE_JH7110_STG=y +CONFIG_CLK_STARFIVE_JH7110_SYS=y +CONFIG_CLK_STARFIVE_JH7110_VOUT=y +CONFIG_CLK_STARFIVE_JH71X0=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CLZ_TAB=y +CONFIG_CMODEL_MEDANY=y +# CONFIG_CMODEL_MEDLOW is not set +CONFIG_COMMON_CLK=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONFIGFS_FS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CRASH_CORE=y +CONFIG_CRC16=y +CONFIG_CRC7=y +CONFIG_CRC_ITU_T=y +CONFIG_CRYPTO_BLAKE2B=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEV_JH7110=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_ENGINE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SM3=y +CONFIG_CRYPTO_SM3_GENERIC=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_RNG=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_XXHASH=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_GPIO=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DEBUG_RODATA_TEST=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_TIMEKEEPING=y +CONFIG_DEBUG_WX=y +CONFIG_DECOMPRESS_GZIP=y +# CONFIG_DEVFREQ_GOV_PASSIVE is not set +# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set +# CONFIG_DEVFREQ_GOV_POWERSAVE is not set +# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set +# CONFIG_DEVFREQ_GOV_USERSPACE is not set +# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_DEVTMPFS_SAFE is not set +CONFIG_DMADEVICES=y +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +# CONFIG_DPM_WATCHDOG is not set +CONFIG_DTC=y +CONFIG_DT_IDLE_GENPD=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DWMAC_DWC_QOS_ETH=y +# CONFIG_DWMAC_GENERIC is not set +CONFIG_DWMAC_STARFIVE=y +CONFIG_DW_AXI_DMAC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_EFI=y +CONFIG_EFIVAR_FS=y +# CONFIG_EFI_BOOTLOADER_CONTROL is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_COCO_SECRET is not set +# CONFIG_EFI_DISABLE_PCI_DMA is not set +CONFIG_EFI_DISABLE_RUNTIME=y +CONFIG_EFI_EARLYCON=y +CONFIG_EFI_ESRT=y +CONFIG_EFI_GENERIC_STUB=y +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_STUB=y +# CONFIG_EFI_TEST is not set +# CONFIG_EFI_ZBOOT is not set +CONFIG_ERRATA_SIFIVE=y +CONFIG_ERRATA_SIFIVE_CIP_1200=y +CONFIG_ERRATA_SIFIVE_CIP_453=y +# CONFIG_ERRATA_THEAD is not set +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXTCON=y +CONFIG_FAILOVER=y +CONFIG_FANOTIFY=y +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15" +CONFIG_FAT_DEFAULT_UTF8=y +CONFIG_FAT_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_AUTOSELECT=y +CONFIG_FONT_SUPPORT=y +CONFIG_FPU=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PHY_MIPI_DPHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=128 +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_TPS65086=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HVC_DRIVER=y +CONFIG_HVC_RISCV_SBI=y +CONFIG_HWMON=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_JH7110=y +CONFIG_HW_RANDOM_STARFIVE_VIC=y +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JH71XX_PMU=y +CONFIG_JUMP_LABEL=y +CONFIG_LIBFDT=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LSM="" +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MEMTEST=y +CONFIG_MFD_AXP20X=y +CONFIG_MFD_AXP20X_I2C=y +CONFIG_MFD_CORE=y +CONFIG_MFD_SYSCON=y +CONFIG_MFD_TPS65086=y +CONFIG_MICREL_PHY=y +CONFIG_MICROCHIP_PHY=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_DW_PCI is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_STARFIVE=y +CONFIG_MMIOWB=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MODULE_SECTIONS=y +CONFIG_MOTORCOMM_PHY=y +CONFIG_MPILIB=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NAMESPACES=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_NS=y +CONFIG_NET_SELFTESTS=y +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_DEFAULT="iso8859-15" +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +# CONFIG_NONPORTABLE is not set +CONFIG_NR_CPUS=8 +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVME_CORE=y +CONFIG_NVME_HWMON=y +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DMA_DEFAULT_COHERENT=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_OID_REGISTRY=y +CONFIG_OVERLAY_FS_INDEX=y +CONFIG_OVERLAY_FS_METACOPY=y +CONFIG_OVERLAY_FS_REDIRECT_DIR=y +CONFIG_PADATA=y +CONFIG_PAGE_EXTENSION=y +CONFIG_PAGE_OFFSET=0xff60000000000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_REPORTING=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIE_CADENCE=y +CONFIG_PCIE_CADENCE_HOST=y +CONFIG_PCIE_CADENCE_PLAT=y +CONFIG_PCIE_CADENCE_PLAT_HOST=y +# CONFIG_PCIE_FU740 is not set +# CONFIG_PCIE_STARFIVE is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCS_XPCS=y +CONFIG_PERF_EVENTS=y +CONFIG_PGTABLE_LEVELS=5 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_STARFIVE_DPHY_RX=y +CONFIG_PHY_STARFIVE_JH7110_PCIE=y +CONFIG_PHY_STARFIVE_JH7110_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_STARFIVE_JH7100=y +CONFIG_PINCTRL_STARFIVE_JH7110=y +CONFIG_PINCTRL_STARFIVE_JH7110_AON=y +CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y +CONFIG_PM=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_PM_CLK=y +CONFIG_PM_DEBUG=y +CONFIG_PM_DEVFREQ=y +# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_PORTABLE=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +# CONFIG_POWER_RESET_TPS65086 is not set +CONFIG_PPS=y +CONFIG_PREEMPT_COUNT=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PROC_CHILDREN=y +CONFIG_PROC_KCORE=y +CONFIG_PTDUMP_CORE=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +# CONFIG_PWM_SIFIVE is not set +CONFIG_PWM_SIFIVE_PTC=y +CONFIG_PWM_STARFIVE_PTC=y +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_RCU_EQS_DEBUG=y +CONFIG_RD_GZIP=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_AXP20X=y +CONFIG_REGULATOR_TPS65086=y +# CONFIG_RESET_ATTACK_MITIGATION is not set +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_SIMPLE=y +CONFIG_RESET_STARFIVE_JH7100=y +CONFIG_RESET_STARFIVE_JH7100_AUDIO=y +CONFIG_RESET_STARFIVE_JH7110=y +CONFIG_RESET_STARFIVE_JH71X0=y +CONFIG_RFS_ACCEL=y +CONFIG_RISCV=y +CONFIG_RISCV_ALTERNATIVE=y +CONFIG_RISCV_BOOT_SPINWAIT=y +CONFIG_RISCV_DMA_NONCOHERENT=y +CONFIG_RISCV_INTC=y +CONFIG_RISCV_ISA_C=y +# CONFIG_RISCV_ISA_SVPBMT is not set +CONFIG_RISCV_ISA_ZICBOM=y +CONFIG_RISCV_PMU=y +CONFIG_RISCV_PMU_LEGACY=y +CONFIG_RISCV_PMU_SBI=y +CONFIG_RISCV_SBI=y +CONFIG_RISCV_SBI_CPUIDLE=y +CONFIG_RISCV_SBI_V01=y +CONFIG_RISCV_TIMER=y +CONFIG_RPMSG=y +CONFIG_RPMSG_CHAR=y +# CONFIG_RPMSG_CTRL is not set +CONFIG_RPMSG_NS=y +# CONFIG_RPMSG_TTY is not set +CONFIG_RPMSG_VIRTIO=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_EFI is not set +CONFIG_RTC_DRV_GOLDFISH=y +CONFIG_RTC_DRV_HYM8563=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SCSI_VIRTIO=y +CONFIG_SENSORS_SFCTEMP=y +# CONFIG_SERIAL_8250_16550A_VARIANTS is not set +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_RUNTIME_UARTS=6 +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_SIFIVE=y +CONFIG_SERIAL_SIFIVE_CONSOLE=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SIFIVE_CCACHE=y +CONFIG_SIFIVE_PLIC=y +CONFIG_SMP=y +# CONFIG_SND_SOC_STARFIVE is not set +CONFIG_SOCK_DIAG=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +# CONFIG_SOC_MICROCHIP_POLARFIRE is not set +CONFIG_SOC_SIFIVE=y +CONFIG_SOC_STARFIVE=y +# CONFIG_SOC_VIRT is not set +CONFIG_SOFTLOCKUP_DETECTOR=y +CONFIG_SOUND=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_CADENCE_QUADSPI=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_SPIDEV=y +CONFIG_SRCU=y +CONFIG_STARFIVE_TIMER=y +CONFIG_STARFIVE_WATCHDOG=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y +CONFIG_STMMAC_SELFTESTS=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYNC_FILE=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_SYSFB_SIMPLEFB is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TOOLCHAIN_HAS_ZICBOM=y +CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y +CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_TTY_PRINTK=y +CONFIG_TTY_PRINTK_LEVEL=6 +CONFIG_TUNE_GENERIC=y +CONFIG_UCS2_STRING=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_CONFIGFS=y +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_EEM is not set +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_UVC is not set +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_SERIAL is not set +CONFIG_USB_F_FS=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_PCI=y +CONFIG_USB_PHY=y +CONFIG_USB_ROLE_SWITCH=y +CONFIG_USB_SUPPORT=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USELIB=y +CONFIG_USER_NS=y +CONFIG_VFAT_FS=y +# CONFIG_VIRTIO_BLK is not set +# CONFIG_VIRTIO_NET is not set +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_SYSFS=y +CONFIG_WERROR=y +CONFIG_WQ_WATCHDOG=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/starfive/generic/target.mk b/target/linux/starfive/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/starfive/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/starfive/image/Config.in b/target/linux/starfive/image/Config.in new file mode 100644 index 0000000000..e8e44e066e --- /dev/null +++ b/target/linux/starfive/image/Config.in @@ -0,0 +1,5 @@ +config STARFIVE_SD_BOOT_PARTSIZE + int "Boot (SD Card) filesystem partition size (in MB)" + depends on TARGET_starfive + default 32 + diff --git a/target/linux/starfive/image/Makefile b/target/linux/starfive/image/Makefile new file mode 100644 index 0000000000..51bc9c3cc6 --- /dev/null +++ b/target/linux/starfive/image/Makefile @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 Toco Technologies +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +FAT32_BLOCK_SIZE=1024 +FAT32_BLOCKS=$(shell echo $$(($(CONFIG_STARFIVE_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE)))) + +define Build/boot-scr-jh7110 + rm -f $@-boot.scr + mkimage -A riscv -O linux -T script -C none -a 0 -e 0 -d mmc.bootscript.jh7110 $@-boot.scr +endef + +define Build/boot-scr-jh7100 + rm -f $@-boot.scr + mkimage -A riscv -O linux -T script -C none -a 0 -e 0 -d mmc.bootscript.jh7100 $@-boot.scr +endef + +define Build/riscv-sdcard + rm -f $@.boot #$(KDIR_TMP)/$(IMG_PREFIX)-$(PROFILE)-boot.img + mkfs.fat $@.boot -C $(FAT32_BLOCKS) + mcopy -i $@.boot $(LINUX_DIR)/arch/riscv/boot/dts/$(DEVICE_DTS).dtb ::dtb + mcopy -i $@.boot $@-boot.scr ::boot.scr.uimg + mcopy -i $@.boot $(IMAGE_KERNEL) ::Image + ./gen_starfive_sdcard_img.sh \ + $@ \ + $@.boot \ + $(IMAGE_ROOTFS) \ + $(CONFIG_STARFIVE_SD_BOOT_PARTSIZE) \ + $(CONFIG_TARGET_ROOTFS_PARTSIZE) +endef + +define Device/Default + PROFILES := Default + KERNEL_NAME := Image + KERNEL := kernel-bin + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr-jh7110 | riscv-sdcard | append-metadata | gzip +endef + +define Device/JH7100 + PROFILES := Default + KERNEL_NAME := Image + KERNEL := kernel-bin + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr-jh7100 | riscv-sdcard | append-metadata | gzip +endef + +define Device/visionfive2-v1.2a + DEVICE_VENDOR := StarFive + DEVICE_MODEL := VisionFive2 v1.2a + DEVICE_DTS := starfive/jh7110-starfive-visionfive-2-v1.2a + DEVICE_PACKAGES := kmod-eeprom-at24 kmod-pcie-starfive kmod-usb3 kmod-usb-cdns3-starfive +endef +TARGET_DEVICES += visionfive2-v1.2a + +define Device/visionfive2-v1.3b + DEVICE_VENDOR := StarFive + DEVICE_MODEL := VisionFive2 v1.3b + DEVICE_DTS := starfive/jh7110-starfive-visionfive-2-v1.3b + DEVICE_PACKAGES := kmod-eeprom-at24 kmod-pcie-starfive kmod-usb3 kmod-usb-cdns3-starfive +endef +TARGET_DEVICES += visionfive2-v1.3b + +define Device/beaglev-starlight + $(call Device/JH7100) + DEVICE_VENDOR := BeagleV + DEVICE_MODEL := Starlight + DEVICE_DTS := starfive/jh7100-beaglev-starlight +endef +TARGET_DEVICES += beaglev-starlight + +define Device/visionfive-v1 + $(call Device/JH7100) + DEVICE_VENDOR := StarFive + DEVICE_MODEL := VisionFive v1 + DEVICE_DTS := starfive/jh7100-starfive-visionfive-v1 + DEVICE_PACKAGES := kmod-eeprom-at24 kmod-brcmfmac cypress-firmware-43430-sdio wpad-basic-mbedtls \ + kmod-usb3 kmod-usb-cdns3-starfive +endef +TARGET_DEVICES += visionfive-v1 + +$(eval $(call BuildImage)) diff --git a/target/linux/starfive/image/gen_starfive_sdcard_img.sh b/target/linux/starfive/image/gen_starfive_sdcard_img.sh new file mode 100755 index 0000000000..ac0c30c5d9 --- /dev/null +++ b/target/linux/starfive/image/gen_starfive_sdcard_img.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2023 OpenWrt.org +# + +set -ex +[ $# -eq 5 ] || { + echo "SYNTAX: $0 " + exit 1 +} + +OUTPUT="$1" +BOOTFS="$2" +ROOTFS="$3" +BOOTFSSIZE="$4" +ROOTFSSIZE="$5" + +set $(ptgen -o $OUTPUT -v -g -T sifiveu_spl -N loader1 -p 1024 -T sifiveu_uboot -N loader2 -p 4096 -t ef -N boot -p ${BOOTFSSIZE}M -N rootfs -p ${ROOTFSSIZE}M) + +ROOTFSOFFSET=$(($7 / 512)) + +dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=10274 conv=notrunc +dd bs=512 if="$ROOTFS" of="$OUTPUT" seek=${ROOTFSOFFSET} conv=notrunc diff --git a/target/linux/starfive/image/mmc.bootscript.jh7100 b/target/linux/starfive/image/mmc.bootscript.jh7100 new file mode 100644 index 0000000000..a6f19ae22e --- /dev/null +++ b/target/linux/starfive/image/mmc.bootscript.jh7100 @@ -0,0 +1,4 @@ +fatload mmc 0:3 0x84000000 Image +fatload mmc 0:3 0x88000000 dtb +setenv bootargs "earlyprintk console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/mmcblk0p4" +booti 0x84000000 - 0x88000000 diff --git a/target/linux/starfive/image/mmc.bootscript.jh7110 b/target/linux/starfive/image/mmc.bootscript.jh7110 new file mode 100644 index 0000000000..aeb2e82275 --- /dev/null +++ b/target/linux/starfive/image/mmc.bootscript.jh7110 @@ -0,0 +1,5 @@ +fatload mmc 1:3 0xa0000000 Image +fatload mmc 1:3 0x46000000 dtb +run chipa_set_linux +setenv bootargs "earlyprintk console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/mmcblk1p4" +booti 0xa0000000 - 0x46000000 diff --git a/target/linux/starfive/modules.mk b/target/linux/starfive/modules.mk new file mode 100644 index 0000000000..7aa559b9e5 --- /dev/null +++ b/target/linux/starfive/modules.mk @@ -0,0 +1,31 @@ +define KernelPackage/pcie-starfive + SUBMENU:=$(OTHER_MENU) + TITLE:=JH7110 PCIe controller support + DEPENDS:=@TARGET_starfive + KCONFIG:=CONFIG_PCIE_STARFIVE + FILES:=$(LINUX_DIR)/drivers/pci/controller/pcie-starfive.ko + AUTOLOAD:=$(call AutoLoad,41,pcie-starfive,1) +endef + +define KernelPackage/pcie-starfive/description + PCIe support for JH7110 +endef + +$(eval $(call KernelPackage,pcie-starfive)) + + +define KernelPackage/usb-cdns3-starfive + TITLE:=Cadence USB3 StarFive USB driver + DEPENDS:=@TARGET_starfive +kmod-usb-cdns3 + KCONFIG:= CONFIG_USB_CDNS3_STARFIVE + FILES:= $(LINUX_DIR)/drivers/usb/cdns3/cdns3-starfive.ko + AUTOLOAD:=$(call AutoLoad,53,cdns3-starfive,1) + $(call AddDepends/usb) +endef + +define KernelPackage/usb-cdns3-starfive/description + Add support for the Cadence USB3 controller found in StarFive SoCs. +endef + + +$(eval $(call KernelPackage,usb-cdns3-starfive)) diff --git a/target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch b/target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch new file mode 100644 index 0000000000..3e06d5a681 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch @@ -0,0 +1,482 @@ +From c960c73ee9fdaae51fcd8a14d44d576b1cf522b7 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:13 +0800 +Subject: [PATCH 001/122] dt-bindings: clock: Add StarFive JH7110 system clock + and reset generator + +Add bindings for the system clock and reset generator (SYSCRG) on the +JH7110 RISC-V SoC by StarFive Ltd. + +Reviewed-by: Conor Dooley +Reviewed-by: Rob Herring +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../clock/starfive,jh7110-syscrg.yaml | 104 +++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 203 ++++++++++++++++++ + .../dt-bindings/reset/starfive,jh7110-crg.h | 142 ++++++++++++ + 3 files changed, 449 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml + create mode 100644 include/dt-bindings/clock/starfive,jh7110-crg.h + create mode 100644 include/dt-bindings/reset/starfive,jh7110-crg.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml +@@ -0,0 +1,104 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-syscrg.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 System Clock and Reset Generator ++ ++maintainers: ++ - Emil Renner Berthing ++ ++properties: ++ compatible: ++ const: starfive,jh7110-syscrg ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ oneOf: ++ - items: ++ - description: Main Oscillator (24 MHz) ++ - description: GMAC1 RMII reference or GMAC1 RGMII RX ++ - description: External I2S TX bit clock ++ - description: External I2S TX left/right channel clock ++ - description: External I2S RX bit clock ++ - description: External I2S RX left/right channel clock ++ - description: External TDM clock ++ - description: External audio master clock ++ ++ - items: ++ - description: Main Oscillator (24 MHz) ++ - description: GMAC1 RMII reference ++ - description: GMAC1 RGMII RX ++ - description: External I2S TX bit clock ++ - description: External I2S TX left/right channel clock ++ - description: External I2S RX bit clock ++ - description: External I2S RX left/right channel clock ++ - description: External TDM clock ++ - description: External audio master clock ++ ++ clock-names: ++ oneOf: ++ - items: ++ - const: osc ++ - enum: ++ - gmac1_rmii_refin ++ - gmac1_rgmii_rxin ++ - const: i2stx_bclk_ext ++ - const: i2stx_lrck_ext ++ - const: i2srx_bclk_ext ++ - const: i2srx_lrck_ext ++ - const: tdm_ext ++ - const: mclk_ext ++ ++ - items: ++ - const: osc ++ - const: gmac1_rmii_refin ++ - const: gmac1_rgmii_rxin ++ - const: i2stx_bclk_ext ++ - const: i2stx_lrck_ext ++ - const: i2srx_bclk_ext ++ - const: i2srx_lrck_ext ++ - const: tdm_ext ++ - const: mclk_ext ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ '#reset-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - '#clock-cells' ++ - '#reset-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ clock-controller@13020000 { ++ compatible = "starfive,jh7110-syscrg"; ++ reg = <0x13020000 0x10000>; ++ clocks = <&osc>, <&gmac1_rmii_refin>, ++ <&gmac1_rgmii_rxin>, ++ <&i2stx_bclk_ext>, <&i2stx_lrck_ext>, ++ <&i2srx_bclk_ext>, <&i2srx_lrck_ext>, ++ <&tdm_ext>, <&mclk_ext>; ++ clock-names = "osc", "gmac1_rmii_refin", ++ "gmac1_rgmii_rxin", ++ "i2stx_bclk_ext", "i2stx_lrck_ext", ++ "i2srx_bclk_ext", "i2srx_lrck_ext", ++ "tdm_ext", "mclk_ext"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; +--- /dev/null ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -0,0 +1,203 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright 2022 Emil Renner Berthing ++ */ ++ ++#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ ++#define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ ++ ++/* SYSCRG clocks */ ++#define JH7110_SYSCLK_CPU_ROOT 0 ++#define JH7110_SYSCLK_CPU_CORE 1 ++#define JH7110_SYSCLK_CPU_BUS 2 ++#define JH7110_SYSCLK_GPU_ROOT 3 ++#define JH7110_SYSCLK_PERH_ROOT 4 ++#define JH7110_SYSCLK_BUS_ROOT 5 ++#define JH7110_SYSCLK_NOCSTG_BUS 6 ++#define JH7110_SYSCLK_AXI_CFG0 7 ++#define JH7110_SYSCLK_STG_AXIAHB 8 ++#define JH7110_SYSCLK_AHB0 9 ++#define JH7110_SYSCLK_AHB1 10 ++#define JH7110_SYSCLK_APB_BUS 11 ++#define JH7110_SYSCLK_APB0 12 ++#define JH7110_SYSCLK_PLL0_DIV2 13 ++#define JH7110_SYSCLK_PLL1_DIV2 14 ++#define JH7110_SYSCLK_PLL2_DIV2 15 ++#define JH7110_SYSCLK_AUDIO_ROOT 16 ++#define JH7110_SYSCLK_MCLK_INNER 17 ++#define JH7110_SYSCLK_MCLK 18 ++#define JH7110_SYSCLK_MCLK_OUT 19 ++#define JH7110_SYSCLK_ISP_2X 20 ++#define JH7110_SYSCLK_ISP_AXI 21 ++#define JH7110_SYSCLK_GCLK0 22 ++#define JH7110_SYSCLK_GCLK1 23 ++#define JH7110_SYSCLK_GCLK2 24 ++#define JH7110_SYSCLK_CORE 25 ++#define JH7110_SYSCLK_CORE1 26 ++#define JH7110_SYSCLK_CORE2 27 ++#define JH7110_SYSCLK_CORE3 28 ++#define JH7110_SYSCLK_CORE4 29 ++#define JH7110_SYSCLK_DEBUG 30 ++#define JH7110_SYSCLK_RTC_TOGGLE 31 ++#define JH7110_SYSCLK_TRACE0 32 ++#define JH7110_SYSCLK_TRACE1 33 ++#define JH7110_SYSCLK_TRACE2 34 ++#define JH7110_SYSCLK_TRACE3 35 ++#define JH7110_SYSCLK_TRACE4 36 ++#define JH7110_SYSCLK_TRACE_COM 37 ++#define JH7110_SYSCLK_NOC_BUS_CPU_AXI 38 ++#define JH7110_SYSCLK_NOC_BUS_AXICFG0_AXI 39 ++#define JH7110_SYSCLK_OSC_DIV2 40 ++#define JH7110_SYSCLK_PLL1_DIV4 41 ++#define JH7110_SYSCLK_PLL1_DIV8 42 ++#define JH7110_SYSCLK_DDR_BUS 43 ++#define JH7110_SYSCLK_DDR_AXI 44 ++#define JH7110_SYSCLK_GPU_CORE 45 ++#define JH7110_SYSCLK_GPU_CORE_CLK 46 ++#define JH7110_SYSCLK_GPU_SYS_CLK 47 ++#define JH7110_SYSCLK_GPU_APB 48 ++#define JH7110_SYSCLK_GPU_RTC_TOGGLE 49 ++#define JH7110_SYSCLK_NOC_BUS_GPU_AXI 50 ++#define JH7110_SYSCLK_ISP_TOP_CORE 51 ++#define JH7110_SYSCLK_ISP_TOP_AXI 52 ++#define JH7110_SYSCLK_NOC_BUS_ISP_AXI 53 ++#define JH7110_SYSCLK_HIFI4_CORE 54 ++#define JH7110_SYSCLK_HIFI4_AXI 55 ++#define JH7110_SYSCLK_AXI_CFG1_MAIN 56 ++#define JH7110_SYSCLK_AXI_CFG1_AHB 57 ++#define JH7110_SYSCLK_VOUT_SRC 58 ++#define JH7110_SYSCLK_VOUT_AXI 59 ++#define JH7110_SYSCLK_NOC_BUS_DISP_AXI 60 ++#define JH7110_SYSCLK_VOUT_TOP_AHB 61 ++#define JH7110_SYSCLK_VOUT_TOP_AXI 62 ++#define JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK 63 ++#define JH7110_SYSCLK_VOUT_TOP_MIPIPHY_REF 64 ++#define JH7110_SYSCLK_JPEGC_AXI 65 ++#define JH7110_SYSCLK_CODAJ12_AXI 66 ++#define JH7110_SYSCLK_CODAJ12_CORE 67 ++#define JH7110_SYSCLK_CODAJ12_APB 68 ++#define JH7110_SYSCLK_VDEC_AXI 69 ++#define JH7110_SYSCLK_WAVE511_AXI 70 ++#define JH7110_SYSCLK_WAVE511_BPU 71 ++#define JH7110_SYSCLK_WAVE511_VCE 72 ++#define JH7110_SYSCLK_WAVE511_APB 73 ++#define JH7110_SYSCLK_VDEC_JPG 74 ++#define JH7110_SYSCLK_VDEC_MAIN 75 ++#define JH7110_SYSCLK_NOC_BUS_VDEC_AXI 76 ++#define JH7110_SYSCLK_VENC_AXI 77 ++#define JH7110_SYSCLK_WAVE420L_AXI 78 ++#define JH7110_SYSCLK_WAVE420L_BPU 79 ++#define JH7110_SYSCLK_WAVE420L_VCE 80 ++#define JH7110_SYSCLK_WAVE420L_APB 81 ++#define JH7110_SYSCLK_NOC_BUS_VENC_AXI 82 ++#define JH7110_SYSCLK_AXI_CFG0_MAIN_DIV 83 ++#define JH7110_SYSCLK_AXI_CFG0_MAIN 84 ++#define JH7110_SYSCLK_AXI_CFG0_HIFI4 85 ++#define JH7110_SYSCLK_AXIMEM2_AXI 86 ++#define JH7110_SYSCLK_QSPI_AHB 87 ++#define JH7110_SYSCLK_QSPI_APB 88 ++#define JH7110_SYSCLK_QSPI_REF_SRC 89 ++#define JH7110_SYSCLK_QSPI_REF 90 ++#define JH7110_SYSCLK_SDIO0_AHB 91 ++#define JH7110_SYSCLK_SDIO1_AHB 92 ++#define JH7110_SYSCLK_SDIO0_SDCARD 93 ++#define JH7110_SYSCLK_SDIO1_SDCARD 94 ++#define JH7110_SYSCLK_USB_125M 95 ++#define JH7110_SYSCLK_NOC_BUS_STG_AXI 96 ++#define JH7110_SYSCLK_GMAC1_AHB 97 ++#define JH7110_SYSCLK_GMAC1_AXI 98 ++#define JH7110_SYSCLK_GMAC_SRC 99 ++#define JH7110_SYSCLK_GMAC1_GTXCLK 100 ++#define JH7110_SYSCLK_GMAC1_RMII_RTX 101 ++#define JH7110_SYSCLK_GMAC1_PTP 102 ++#define JH7110_SYSCLK_GMAC1_RX 103 ++#define JH7110_SYSCLK_GMAC1_RX_INV 104 ++#define JH7110_SYSCLK_GMAC1_TX 105 ++#define JH7110_SYSCLK_GMAC1_TX_INV 106 ++#define JH7110_SYSCLK_GMAC1_GTXC 107 ++#define JH7110_SYSCLK_GMAC0_GTXCLK 108 ++#define JH7110_SYSCLK_GMAC0_PTP 109 ++#define JH7110_SYSCLK_GMAC_PHY 110 ++#define JH7110_SYSCLK_GMAC0_GTXC 111 ++#define JH7110_SYSCLK_IOMUX_APB 112 ++#define JH7110_SYSCLK_MAILBOX_APB 113 ++#define JH7110_SYSCLK_INT_CTRL_APB 114 ++#define JH7110_SYSCLK_CAN0_APB 115 ++#define JH7110_SYSCLK_CAN0_TIMER 116 ++#define JH7110_SYSCLK_CAN0_CAN 117 ++#define JH7110_SYSCLK_CAN1_APB 118 ++#define JH7110_SYSCLK_CAN1_TIMER 119 ++#define JH7110_SYSCLK_CAN1_CAN 120 ++#define JH7110_SYSCLK_PWM_APB 121 ++#define JH7110_SYSCLK_WDT_APB 122 ++#define JH7110_SYSCLK_WDT_CORE 123 ++#define JH7110_SYSCLK_TIMER_APB 124 ++#define JH7110_SYSCLK_TIMER0 125 ++#define JH7110_SYSCLK_TIMER1 126 ++#define JH7110_SYSCLK_TIMER2 127 ++#define JH7110_SYSCLK_TIMER3 128 ++#define JH7110_SYSCLK_TEMP_APB 129 ++#define JH7110_SYSCLK_TEMP_CORE 130 ++#define JH7110_SYSCLK_SPI0_APB 131 ++#define JH7110_SYSCLK_SPI1_APB 132 ++#define JH7110_SYSCLK_SPI2_APB 133 ++#define JH7110_SYSCLK_SPI3_APB 134 ++#define JH7110_SYSCLK_SPI4_APB 135 ++#define JH7110_SYSCLK_SPI5_APB 136 ++#define JH7110_SYSCLK_SPI6_APB 137 ++#define JH7110_SYSCLK_I2C0_APB 138 ++#define JH7110_SYSCLK_I2C1_APB 139 ++#define JH7110_SYSCLK_I2C2_APB 140 ++#define JH7110_SYSCLK_I2C3_APB 141 ++#define JH7110_SYSCLK_I2C4_APB 142 ++#define JH7110_SYSCLK_I2C5_APB 143 ++#define JH7110_SYSCLK_I2C6_APB 144 ++#define JH7110_SYSCLK_UART0_APB 145 ++#define JH7110_SYSCLK_UART0_CORE 146 ++#define JH7110_SYSCLK_UART1_APB 147 ++#define JH7110_SYSCLK_UART1_CORE 148 ++#define JH7110_SYSCLK_UART2_APB 149 ++#define JH7110_SYSCLK_UART2_CORE 150 ++#define JH7110_SYSCLK_UART3_APB 151 ++#define JH7110_SYSCLK_UART3_CORE 152 ++#define JH7110_SYSCLK_UART4_APB 153 ++#define JH7110_SYSCLK_UART4_CORE 154 ++#define JH7110_SYSCLK_UART5_APB 155 ++#define JH7110_SYSCLK_UART5_CORE 156 ++#define JH7110_SYSCLK_PWMDAC_APB 157 ++#define JH7110_SYSCLK_PWMDAC_CORE 158 ++#define JH7110_SYSCLK_SPDIF_APB 159 ++#define JH7110_SYSCLK_SPDIF_CORE 160 ++#define JH7110_SYSCLK_I2STX0_APB 161 ++#define JH7110_SYSCLK_I2STX0_BCLK_MST 162 ++#define JH7110_SYSCLK_I2STX0_BCLK_MST_INV 163 ++#define JH7110_SYSCLK_I2STX0_LRCK_MST 164 ++#define JH7110_SYSCLK_I2STX0_BCLK 165 ++#define JH7110_SYSCLK_I2STX0_BCLK_INV 166 ++#define JH7110_SYSCLK_I2STX0_LRCK 167 ++#define JH7110_SYSCLK_I2STX1_APB 168 ++#define JH7110_SYSCLK_I2STX1_BCLK_MST 169 ++#define JH7110_SYSCLK_I2STX1_BCLK_MST_INV 170 ++#define JH7110_SYSCLK_I2STX1_LRCK_MST 171 ++#define JH7110_SYSCLK_I2STX1_BCLK 172 ++#define JH7110_SYSCLK_I2STX1_BCLK_INV 173 ++#define JH7110_SYSCLK_I2STX1_LRCK 174 ++#define JH7110_SYSCLK_I2SRX_APB 175 ++#define JH7110_SYSCLK_I2SRX_BCLK_MST 176 ++#define JH7110_SYSCLK_I2SRX_BCLK_MST_INV 177 ++#define JH7110_SYSCLK_I2SRX_LRCK_MST 178 ++#define JH7110_SYSCLK_I2SRX_BCLK 179 ++#define JH7110_SYSCLK_I2SRX_BCLK_INV 180 ++#define JH7110_SYSCLK_I2SRX_LRCK 181 ++#define JH7110_SYSCLK_PDM_DMIC 182 ++#define JH7110_SYSCLK_PDM_APB 183 ++#define JH7110_SYSCLK_TDM_AHB 184 ++#define JH7110_SYSCLK_TDM_APB 185 ++#define JH7110_SYSCLK_TDM_INTERNAL 186 ++#define JH7110_SYSCLK_TDM_TDM 187 ++#define JH7110_SYSCLK_TDM_TDM_INV 188 ++#define JH7110_SYSCLK_JTAG_CERTIFICATION_TRNG 189 ++ ++#define JH7110_SYSCLK_END 190 ++ ++#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */ +--- /dev/null ++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h +@@ -0,0 +1,142 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright (C) 2022 Emil Renner Berthing ++ */ ++ ++#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ ++#define __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ ++ ++/* SYSCRG resets */ ++#define JH7110_SYSRST_JTAG_APB 0 ++#define JH7110_SYSRST_SYSCON_APB 1 ++#define JH7110_SYSRST_IOMUX_APB 2 ++#define JH7110_SYSRST_BUS 3 ++#define JH7110_SYSRST_DEBUG 4 ++#define JH7110_SYSRST_CORE0 5 ++#define JH7110_SYSRST_CORE1 6 ++#define JH7110_SYSRST_CORE2 7 ++#define JH7110_SYSRST_CORE3 8 ++#define JH7110_SYSRST_CORE4 9 ++#define JH7110_SYSRST_CORE0_ST 10 ++#define JH7110_SYSRST_CORE1_ST 11 ++#define JH7110_SYSRST_CORE2_ST 12 ++#define JH7110_SYSRST_CORE3_ST 13 ++#define JH7110_SYSRST_CORE4_ST 14 ++#define JH7110_SYSRST_TRACE0 15 ++#define JH7110_SYSRST_TRACE1 16 ++#define JH7110_SYSRST_TRACE2 17 ++#define JH7110_SYSRST_TRACE3 18 ++#define JH7110_SYSRST_TRACE4 19 ++#define JH7110_SYSRST_TRACE_COM 20 ++#define JH7110_SYSRST_GPU_APB 21 ++#define JH7110_SYSRST_GPU_DOMA 22 ++#define JH7110_SYSRST_NOC_BUS_APB 23 ++#define JH7110_SYSRST_NOC_BUS_AXICFG0_AXI 24 ++#define JH7110_SYSRST_NOC_BUS_CPU_AXI 25 ++#define JH7110_SYSRST_NOC_BUS_DISP_AXI 26 ++#define JH7110_SYSRST_NOC_BUS_GPU_AXI 27 ++#define JH7110_SYSRST_NOC_BUS_ISP_AXI 28 ++#define JH7110_SYSRST_NOC_BUS_DDRC 29 ++#define JH7110_SYSRST_NOC_BUS_STG_AXI 30 ++#define JH7110_SYSRST_NOC_BUS_VDEC_AXI 31 ++ ++#define JH7110_SYSRST_NOC_BUS_VENC_AXI 32 ++#define JH7110_SYSRST_AXI_CFG1_AHB 33 ++#define JH7110_SYSRST_AXI_CFG1_MAIN 34 ++#define JH7110_SYSRST_AXI_CFG0_MAIN 35 ++#define JH7110_SYSRST_AXI_CFG0_MAIN_DIV 36 ++#define JH7110_SYSRST_AXI_CFG0_HIFI4 37 ++#define JH7110_SYSRST_DDR_AXI 38 ++#define JH7110_SYSRST_DDR_OSC 39 ++#define JH7110_SYSRST_DDR_APB 40 ++#define JH7110_SYSRST_ISP_TOP 41 ++#define JH7110_SYSRST_ISP_TOP_AXI 42 ++#define JH7110_SYSRST_VOUT_TOP_SRC 43 ++#define JH7110_SYSRST_CODAJ12_AXI 44 ++#define JH7110_SYSRST_CODAJ12_CORE 45 ++#define JH7110_SYSRST_CODAJ12_APB 46 ++#define JH7110_SYSRST_WAVE511_AXI 47 ++#define JH7110_SYSRST_WAVE511_BPU 48 ++#define JH7110_SYSRST_WAVE511_VCE 49 ++#define JH7110_SYSRST_WAVE511_APB 50 ++#define JH7110_SYSRST_VDEC_JPG 51 ++#define JH7110_SYSRST_VDEC_MAIN 52 ++#define JH7110_SYSRST_AXIMEM0_AXI 53 ++#define JH7110_SYSRST_WAVE420L_AXI 54 ++#define JH7110_SYSRST_WAVE420L_BPU 55 ++#define JH7110_SYSRST_WAVE420L_VCE 56 ++#define JH7110_SYSRST_WAVE420L_APB 57 ++#define JH7110_SYSRST_AXIMEM1_AXI 58 ++#define JH7110_SYSRST_AXIMEM2_AXI 59 ++#define JH7110_SYSRST_INTMEM 60 ++#define JH7110_SYSRST_QSPI_AHB 61 ++#define JH7110_SYSRST_QSPI_APB 62 ++#define JH7110_SYSRST_QSPI_REF 63 ++ ++#define JH7110_SYSRST_SDIO0_AHB 64 ++#define JH7110_SYSRST_SDIO1_AHB 65 ++#define JH7110_SYSRST_GMAC1_AXI 66 ++#define JH7110_SYSRST_GMAC1_AHB 67 ++#define JH7110_SYSRST_MAILBOX_APB 68 ++#define JH7110_SYSRST_SPI0_APB 69 ++#define JH7110_SYSRST_SPI1_APB 70 ++#define JH7110_SYSRST_SPI2_APB 71 ++#define JH7110_SYSRST_SPI3_APB 72 ++#define JH7110_SYSRST_SPI4_APB 73 ++#define JH7110_SYSRST_SPI5_APB 74 ++#define JH7110_SYSRST_SPI6_APB 75 ++#define JH7110_SYSRST_I2C0_APB 76 ++#define JH7110_SYSRST_I2C1_APB 77 ++#define JH7110_SYSRST_I2C2_APB 78 ++#define JH7110_SYSRST_I2C3_APB 79 ++#define JH7110_SYSRST_I2C4_APB 80 ++#define JH7110_SYSRST_I2C5_APB 81 ++#define JH7110_SYSRST_I2C6_APB 82 ++#define JH7110_SYSRST_UART0_APB 83 ++#define JH7110_SYSRST_UART0_CORE 84 ++#define JH7110_SYSRST_UART1_APB 85 ++#define JH7110_SYSRST_UART1_CORE 86 ++#define JH7110_SYSRST_UART2_APB 87 ++#define JH7110_SYSRST_UART2_CORE 88 ++#define JH7110_SYSRST_UART3_APB 89 ++#define JH7110_SYSRST_UART3_CORE 90 ++#define JH7110_SYSRST_UART4_APB 91 ++#define JH7110_SYSRST_UART4_CORE 92 ++#define JH7110_SYSRST_UART5_APB 93 ++#define JH7110_SYSRST_UART5_CORE 94 ++#define JH7110_SYSRST_SPDIF_APB 95 ++ ++#define JH7110_SYSRST_PWMDAC_APB 96 ++#define JH7110_SYSRST_PDM_DMIC 97 ++#define JH7110_SYSRST_PDM_APB 98 ++#define JH7110_SYSRST_I2SRX_APB 99 ++#define JH7110_SYSRST_I2SRX_BCLK 100 ++#define JH7110_SYSRST_I2STX0_APB 101 ++#define JH7110_SYSRST_I2STX0_BCLK 102 ++#define JH7110_SYSRST_I2STX1_APB 103 ++#define JH7110_SYSRST_I2STX1_BCLK 104 ++#define JH7110_SYSRST_TDM_AHB 105 ++#define JH7110_SYSRST_TDM_CORE 106 ++#define JH7110_SYSRST_TDM_APB 107 ++#define JH7110_SYSRST_PWM_APB 108 ++#define JH7110_SYSRST_WDT_APB 109 ++#define JH7110_SYSRST_WDT_CORE 110 ++#define JH7110_SYSRST_CAN0_APB 111 ++#define JH7110_SYSRST_CAN0_CORE 112 ++#define JH7110_SYSRST_CAN0_TIMER 113 ++#define JH7110_SYSRST_CAN1_APB 114 ++#define JH7110_SYSRST_CAN1_CORE 115 ++#define JH7110_SYSRST_CAN1_TIMER 116 ++#define JH7110_SYSRST_TIMER_APB 117 ++#define JH7110_SYSRST_TIMER0 118 ++#define JH7110_SYSRST_TIMER1 119 ++#define JH7110_SYSRST_TIMER2 120 ++#define JH7110_SYSRST_TIMER3 121 ++#define JH7110_SYSRST_INT_CTRL_APB 122 ++#define JH7110_SYSRST_TEMP_APB 123 ++#define JH7110_SYSRST_TEMP_CORE 124 ++#define JH7110_SYSRST_JTAG_CERTIFICATION 125 ++ ++#define JH7110_SYSRST_END 126 ++ ++#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */ diff --git a/target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch b/target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch new file mode 100644 index 0000000000..94cb575a71 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch @@ -0,0 +1,176 @@ +From cd833f484009f37be57a2aa09257af6e8c1b25b6 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:14 +0800 +Subject: [PATCH 002/122] dt-bindings: clock: Add StarFive JH7110 always-on + clock and reset generator + +Add bindings for the always-on clock and reset generator (AONCRG) on the +JH7110 RISC-V SoC by StarFive Ltd. + +Reviewed-by: Conor Dooley +Reviewed-by: Rob Herring +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../clock/starfive,jh7110-aoncrg.yaml | 107 ++++++++++++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 18 +++ + .../dt-bindings/reset/starfive,jh7110-crg.h | 12 ++ + 3 files changed, 137 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-aoncrg.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-aoncrg.yaml +@@ -0,0 +1,107 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-aoncrg.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 Always-On Clock and Reset Generator ++ ++maintainers: ++ - Emil Renner Berthing ++ ++properties: ++ compatible: ++ const: starfive,jh7110-aoncrg ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ oneOf: ++ - items: ++ - description: Main Oscillator (24 MHz) ++ - description: GMAC0 RMII reference or GMAC0 RGMII RX ++ - description: STG AXI/AHB ++ - description: APB Bus ++ - description: GMAC0 GTX ++ ++ - items: ++ - description: Main Oscillator (24 MHz) ++ - description: GMAC0 RMII reference or GMAC0 RGMII RX ++ - description: STG AXI/AHB or GMAC0 RGMII RX ++ - description: APB Bus or STG AXI/AHB ++ - description: GMAC0 GTX or APB Bus ++ - description: RTC Oscillator (32.768 kHz) or GMAC0 GTX ++ ++ - items: ++ - description: Main Oscillator (24 MHz) ++ - description: GMAC0 RMII reference ++ - description: GMAC0 RGMII RX ++ - description: STG AXI/AHB ++ - description: APB Bus ++ - description: GMAC0 GTX ++ - description: RTC Oscillator (32.768 kHz) ++ ++ clock-names: ++ oneOf: ++ - minItems: 5 ++ items: ++ - const: osc ++ - enum: ++ - gmac0_rmii_refin ++ - gmac0_rgmii_rxin ++ - const: stg_axiahb ++ - const: apb_bus ++ - const: gmac0_gtxclk ++ - const: rtc_osc ++ ++ - minItems: 6 ++ items: ++ - const: osc ++ - const: gmac0_rmii_refin ++ - const: gmac0_rgmii_rxin ++ - const: stg_axiahb ++ - const: apb_bus ++ - const: gmac0_gtxclk ++ - const: rtc_osc ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ '#reset-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - '#clock-cells' ++ - '#reset-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ clock-controller@17000000 { ++ compatible = "starfive,jh7110-aoncrg"; ++ reg = <0x17000000 0x10000>; ++ clocks = <&osc>, <&gmac0_rmii_refin>, ++ <&gmac0_rgmii_rxin>, ++ <&syscrg JH7110_SYSCLK_STG_AXIAHB>, ++ <&syscrg JH7110_SYSCLK_APB_BUS>, ++ <&syscrg JH7110_SYSCLK_GMAC0_GTXCLK>, ++ <&rtc_osc>; ++ clock-names = "osc", "gmac0_rmii_refin", ++ "gmac0_rgmii_rxin", "stg_axiahb", ++ "apb_bus", "gmac0_gtxclk", ++ "rtc_osc"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; +--- a/include/dt-bindings/clock/starfive,jh7110-crg.h ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -200,4 +200,22 @@ + + #define JH7110_SYSCLK_END 190 + ++/* AONCRG clocks */ ++#define JH7110_AONCLK_OSC_DIV4 0 ++#define JH7110_AONCLK_APB_FUNC 1 ++#define JH7110_AONCLK_GMAC0_AHB 2 ++#define JH7110_AONCLK_GMAC0_AXI 3 ++#define JH7110_AONCLK_GMAC0_RMII_RTX 4 ++#define JH7110_AONCLK_GMAC0_TX 5 ++#define JH7110_AONCLK_GMAC0_TX_INV 6 ++#define JH7110_AONCLK_GMAC0_RX 7 ++#define JH7110_AONCLK_GMAC0_RX_INV 8 ++#define JH7110_AONCLK_OTPC_APB 9 ++#define JH7110_AONCLK_RTC_APB 10 ++#define JH7110_AONCLK_RTC_INTERNAL 11 ++#define JH7110_AONCLK_RTC_32K 12 ++#define JH7110_AONCLK_RTC_CAL 13 ++ ++#define JH7110_AONCLK_END 14 ++ + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */ +--- a/include/dt-bindings/reset/starfive,jh7110-crg.h ++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h +@@ -139,4 +139,16 @@ + + #define JH7110_SYSRST_END 126 + ++/* AONCRG resets */ ++#define JH7110_AONRST_GMAC0_AXI 0 ++#define JH7110_AONRST_GMAC0_AHB 1 ++#define JH7110_AONRST_IOMUX 2 ++#define JH7110_AONRST_PMU_APB 3 ++#define JH7110_AONRST_PMU_WKUP 4 ++#define JH7110_AONRST_RTC_APB 5 ++#define JH7110_AONRST_RTC_CAL 6 ++#define JH7110_AONRST_RTC_32K 7 ++ ++#define JH7110_AONRST_END 8 ++ + #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */ diff --git a/target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch b/target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch new file mode 100644 index 0000000000..1cedd313d9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch @@ -0,0 +1,53 @@ +From 124f322d1c42232e439ea9a356d68caf1d0656f3 Mon Sep 17 00:00:00 2001 +From: Hal Feng +Date: Sat, 1 Apr 2023 19:19:15 +0800 +Subject: [PATCH 003/122] clk: starfive: Replace SOC_STARFIVE with + ARCH_STARFIVE + +Using ARCH_FOO symbol is preferred than SOC_FOO. +Set obj-y for starfive/ in Makefile, so the StarFive drivers +can be compiled with COMPILE_TEST=y but ARCH_STARFIVE=n. + +Reviewed-by: Conor Dooley +Reviewed-by: Heiko Stuebner +Reviewed-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/clk/Makefile | 2 +- + drivers/clk/starfive/Kconfig | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -117,7 +117,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/ + obj-y += sprd/ + obj-$(CONFIG_ARCH_STI) += st/ + obj-$(CONFIG_ARCH_STM32) += stm32/ +-obj-$(CONFIG_SOC_STARFIVE) += starfive/ ++obj-y += starfive/ + obj-$(CONFIG_ARCH_SUNXI) += sunxi/ + obj-y += sunxi-ng/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -2,8 +2,8 @@ + + config CLK_STARFIVE_JH7100 + bool "StarFive JH7100 clock support" +- depends on SOC_STARFIVE || COMPILE_TEST +- default SOC_STARFIVE ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ default ARCH_STARFIVE + help + Say yes here to support the clock controller on the StarFive JH7100 + SoC. +@@ -11,7 +11,7 @@ config CLK_STARFIVE_JH7100 + config CLK_STARFIVE_JH7100_AUDIO + tristate "StarFive JH7100 audio clock support" + depends on CLK_STARFIVE_JH7100 +- default m if SOC_STARFIVE ++ default m if ARCH_STARFIVE + help + Say Y or M here to support the audio clocks on the StarFive JH7100 + SoC. diff --git a/target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch b/target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch new file mode 100644 index 0000000000..72375bb0d9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch @@ -0,0 +1,749 @@ +From 6f14eb919e5b92076e17aec5388655348963eef7 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:16 +0800 +Subject: [PATCH 004/122] clk: starfive: Factor out common JH7100 and JH7110 + code + +The clock control registers on the StarFive JH7100 and JH7110 work +identically, so factor out the code then drivers for the two SoCs +can share it without depending on each other. No functional change. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/clk/starfive/Kconfig | 5 + + drivers/clk/starfive/Makefile | 3 +- + drivers/clk/starfive/clk-starfive-jh7100.c | 325 -------------------- + drivers/clk/starfive/clk-starfive-jh7100.h | 2 + + drivers/clk/starfive/clk-starfive-jh71x0.c | 333 +++++++++++++++++++++ + 5 files changed, 342 insertions(+), 326 deletions(-) + create mode 100644 drivers/clk/starfive/clk-starfive-jh71x0.c + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -1,8 +1,12 @@ + # SPDX-License-Identifier: GPL-2.0 + ++config CLK_STARFIVE_JH71X0 ++ bool ++ + config CLK_STARFIVE_JH7100 + bool "StarFive JH7100 clock support" + depends on ARCH_STARFIVE || COMPILE_TEST ++ select CLK_STARFIVE_JH71X0 + default ARCH_STARFIVE + help + Say yes here to support the clock controller on the StarFive JH7100 +@@ -11,6 +15,7 @@ config CLK_STARFIVE_JH7100 + config CLK_STARFIVE_JH7100_AUDIO + tristate "StarFive JH7100 audio clock support" + depends on CLK_STARFIVE_JH7100 ++ select CLK_STARFIVE_JH71X0 + default m if ARCH_STARFIVE + help + Say Y or M here to support the audio clocks on the StarFive JH7100 +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-# StarFive Clock ++obj-$(CONFIG_CLK_STARFIVE_JH71X0) += clk-starfive-jh71x0.o ++ + obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk-starfive-jh7100.o + obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) += clk-starfive-jh7100-audio.o +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -7,15 +7,10 @@ + * Copyright (C) 2021 Emil Renner Berthing + */ + +-#include + #include +-#include + #include + #include +-#include +-#include + #include +-#include + #include + + #include +@@ -269,326 +264,6 @@ static const struct jh7100_clk_data jh71 + JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS), + }; + +-static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw) +-{ +- return container_of(hw, struct jh7100_clk, hw); +-} +- +-static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk) +-{ +- return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]); +-} +- +-static u32 jh7100_clk_reg_get(struct jh7100_clk *clk) +-{ +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); +- void __iomem *reg = priv->base + 4 * clk->idx; +- +- return readl_relaxed(reg); +-} +- +-static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value) +-{ +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); +- void __iomem *reg = priv->base + 4 * clk->idx; +- unsigned long flags; +- +- spin_lock_irqsave(&priv->rmw_lock, flags); +- value |= readl_relaxed(reg) & ~mask; +- writel_relaxed(value, reg); +- spin_unlock_irqrestore(&priv->rmw_lock, flags); +-} +- +-static int jh7100_clk_enable(struct clk_hw *hw) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE); +- return 0; +-} +- +-static void jh7100_clk_disable(struct clk_hw *hw) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0); +-} +- +-static int jh7100_clk_is_enabled(struct clk_hw *hw) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- +- return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE); +-} +- +-static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw, +- unsigned long parent_rate) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK; +- +- return div ? parent_rate / div : 0; +-} +- +-static int jh7100_clk_determine_rate(struct clk_hw *hw, +- struct clk_rate_request *req) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- unsigned long parent = req->best_parent_rate; +- unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); +- unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div); +- unsigned long result = parent / div; +- +- /* +- * we want the result clamped by min_rate and max_rate if possible: +- * case 1: div hits the max divider value, which means it's less than +- * parent / rate, so the result is greater than rate and min_rate in +- * particular. we can't do anything about result > max_rate because the +- * divider doesn't go any further. +- * case 2: div = DIV_ROUND_UP(parent, rate) which means the result is +- * always lower or equal to rate and max_rate. however the result may +- * turn out lower than min_rate, but then the next higher rate is fine: +- * div - 1 = ceil(parent / rate) - 1 < parent / rate +- * and thus +- * min_rate <= rate < parent / (div - 1) +- */ +- if (result < req->min_rate && div > 1) +- result = parent / (div - 1); +- +- req->rate = result; +- return 0; +-} +- +-static int jh7100_clk_set_rate(struct clk_hw *hw, +- unsigned long rate, +- unsigned long parent_rate) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate), +- 1UL, (unsigned long)clk->max_div); +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div); +- return 0; +-} +- +-static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw, +- unsigned long parent_rate) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 reg = jh7100_clk_reg_get(clk); +- unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) + +- ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT); +- +- return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; +-} +- +-static int jh7100_clk_frac_determine_rate(struct clk_hw *hw, +- struct clk_rate_request *req) +-{ +- unsigned long parent100 = 100 * req->best_parent_rate; +- unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); +- unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate), +- JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); +- unsigned long result = parent100 / div100; +- +- /* clamp the result as in jh7100_clk_determine_rate() above */ +- if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX) +- result = parent100 / (div100 + 1); +- if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN) +- result = parent100 / (div100 - 1); +- +- req->rate = result; +- return 0; +-} +- +-static int jh7100_clk_frac_set_rate(struct clk_hw *hw, +- unsigned long rate, +- unsigned long parent_rate) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate), +- JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); +- u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100); +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value); +- return 0; +-} +- +-static u8 jh7100_clk_get_parent(struct clk_hw *hw) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = jh7100_clk_reg_get(clk); +- +- return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT; +-} +- +-static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = (u32)index << JH7100_CLK_MUX_SHIFT; +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value); +- return 0; +-} +- +-static int jh7100_clk_mux_determine_rate(struct clk_hw *hw, +- struct clk_rate_request *req) +-{ +- return clk_mux_determine_rate_flags(hw, req, 0); +-} +- +-static int jh7100_clk_get_phase(struct clk_hw *hw) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = jh7100_clk_reg_get(clk); +- +- return (value & JH7100_CLK_INVERT) ? 180 : 0; +-} +- +-static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees) +-{ +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value; +- +- if (degrees == 0) +- value = 0; +- else if (degrees == 180) +- value = JH7100_CLK_INVERT; +- else +- return -EINVAL; +- +- jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value); +- return 0; +-} +- +-#ifdef CONFIG_DEBUG_FS +-static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) +-{ +- static const struct debugfs_reg32 jh7100_clk_reg = { +- .name = "CTRL", +- .offset = 0, +- }; +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); +- struct debugfs_regset32 *regset; +- +- regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL); +- if (!regset) +- return; +- +- regset->regs = &jh7100_clk_reg; +- regset->nregs = 1; +- regset->base = priv->base + 4 * clk->idx; +- +- debugfs_create_regset32("registers", 0400, dentry, regset); +-} +-#else +-#define jh7100_clk_debug_init NULL +-#endif +- +-static const struct clk_ops jh7100_clk_gate_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_div_ops = { +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_fdiv_ops = { +- .recalc_rate = jh7100_clk_frac_recalc_rate, +- .determine_rate = jh7100_clk_frac_determine_rate, +- .set_rate = jh7100_clk_frac_set_rate, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_gdiv_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_mux_ops = { +- .determine_rate = jh7100_clk_mux_determine_rate, +- .set_parent = jh7100_clk_set_parent, +- .get_parent = jh7100_clk_get_parent, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_gmux_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .determine_rate = jh7100_clk_mux_determine_rate, +- .set_parent = jh7100_clk_set_parent, +- .get_parent = jh7100_clk_get_parent, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_mdiv_ops = { +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .get_parent = jh7100_clk_get_parent, +- .set_parent = jh7100_clk_set_parent, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_gmd_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .get_parent = jh7100_clk_get_parent, +- .set_parent = jh7100_clk_set_parent, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-static const struct clk_ops jh7100_clk_inv_ops = { +- .get_phase = jh7100_clk_get_phase, +- .set_phase = jh7100_clk_set_phase, +- .debug_init = jh7100_clk_debug_init, +-}; +- +-const struct clk_ops *starfive_jh7100_clk_ops(u32 max) +-{ +- if (max & JH7100_CLK_DIV_MASK) { +- if (max & JH7100_CLK_MUX_MASK) { +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gmd_ops; +- return &jh7100_clk_mdiv_ops; +- } +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gdiv_ops; +- if (max == JH7100_CLK_FRAC_MAX) +- return &jh7100_clk_fdiv_ops; +- return &jh7100_clk_div_ops; +- } +- +- if (max & JH7100_CLK_MUX_MASK) { +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gmux_ops; +- return &jh7100_clk_mux_ops; +- } +- +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gate_ops; +- +- return &jh7100_clk_inv_ops; +-} +-EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops); +- + static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data) + { + struct jh7100_clk_priv *priv = data; +--- a/drivers/clk/starfive/clk-starfive-jh7100.h ++++ b/drivers/clk/starfive/clk-starfive-jh7100.h +@@ -4,6 +4,8 @@ + + #include + #include ++#include ++#include + + /* register fields */ + #define JH7100_CLK_ENABLE BIT(31) +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c +@@ -0,0 +1,333 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7100 Clock Generator Driver ++ * ++ * Copyright (C) 2021-2022 Emil Renner Berthing ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "clk-starfive-jh7100.h" ++ ++static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw) ++{ ++ return container_of(hw, struct jh7100_clk, hw); ++} ++ ++static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk) ++{ ++ return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]); ++} ++ ++static u32 jh7100_clk_reg_get(struct jh7100_clk *clk) ++{ ++ struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ void __iomem *reg = priv->base + 4 * clk->idx; ++ ++ return readl_relaxed(reg); ++} ++ ++static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value) ++{ ++ struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ void __iomem *reg = priv->base + 4 * clk->idx; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->rmw_lock, flags); ++ value |= readl_relaxed(reg) & ~mask; ++ writel_relaxed(value, reg); ++ spin_unlock_irqrestore(&priv->rmw_lock, flags); ++} ++ ++static int jh7100_clk_enable(struct clk_hw *hw) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE); ++ return 0; ++} ++ ++static void jh7100_clk_disable(struct clk_hw *hw) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0); ++} ++ ++static int jh7100_clk_is_enabled(struct clk_hw *hw) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ ++ return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE); ++} ++ ++static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK; ++ ++ return div ? parent_rate / div : 0; ++} ++ ++static int jh7100_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ unsigned long parent = req->best_parent_rate; ++ unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); ++ unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div); ++ unsigned long result = parent / div; ++ ++ /* ++ * we want the result clamped by min_rate and max_rate if possible: ++ * case 1: div hits the max divider value, which means it's less than ++ * parent / rate, so the result is greater than rate and min_rate in ++ * particular. we can't do anything about result > max_rate because the ++ * divider doesn't go any further. ++ * case 2: div = DIV_ROUND_UP(parent, rate) which means the result is ++ * always lower or equal to rate and max_rate. however the result may ++ * turn out lower than min_rate, but then the next higher rate is fine: ++ * div - 1 = ceil(parent / rate) - 1 < parent / rate ++ * and thus ++ * min_rate <= rate < parent / (div - 1) ++ */ ++ if (result < req->min_rate && div > 1) ++ result = parent / (div - 1); ++ ++ req->rate = result; ++ return 0; ++} ++ ++static int jh7100_clk_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate), ++ 1UL, (unsigned long)clk->max_div); ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div); ++ return 0; ++} ++ ++static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 reg = jh7100_clk_reg_get(clk); ++ unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) + ++ ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT); ++ ++ return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; ++} ++ ++static int jh7100_clk_frac_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ unsigned long parent100 = 100 * req->best_parent_rate; ++ unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); ++ unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate), ++ JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); ++ unsigned long result = parent100 / div100; ++ ++ /* clamp the result as in jh7100_clk_determine_rate() above */ ++ if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX) ++ result = parent100 / (div100 + 1); ++ if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN) ++ result = parent100 / (div100 - 1); ++ ++ req->rate = result; ++ return 0; ++} ++ ++static int jh7100_clk_frac_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate), ++ JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); ++ u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100); ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value); ++ return 0; ++} ++ ++static u8 jh7100_clk_get_parent(struct clk_hw *hw) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 value = jh7100_clk_reg_get(clk); ++ ++ return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT; ++} ++ ++static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 value = (u32)index << JH7100_CLK_MUX_SHIFT; ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value); ++ return 0; ++} ++ ++static int jh7100_clk_mux_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ return clk_mux_determine_rate_flags(hw, req, 0); ++} ++ ++static int jh7100_clk_get_phase(struct clk_hw *hw) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 value = jh7100_clk_reg_get(clk); ++ ++ return (value & JH7100_CLK_INVERT) ? 180 : 0; ++} ++ ++static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees) ++{ ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ u32 value; ++ ++ if (degrees == 0) ++ value = 0; ++ else if (degrees == 180) ++ value = JH7100_CLK_INVERT; ++ else ++ return -EINVAL; ++ ++ jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value); ++ return 0; ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ static const struct debugfs_reg32 jh7100_clk_reg = { ++ .name = "CTRL", ++ .offset = 0, ++ }; ++ struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ struct debugfs_regset32 *regset; ++ ++ regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ return; ++ ++ regset->regs = &jh7100_clk_reg; ++ regset->nregs = 1; ++ regset->base = priv->base + 4 * clk->idx; ++ ++ debugfs_create_regset32("registers", 0400, dentry, regset); ++} ++#else ++#define jh7100_clk_debug_init NULL ++#endif ++ ++static const struct clk_ops jh7100_clk_gate_ops = { ++ .enable = jh7100_clk_enable, ++ .disable = jh7100_clk_disable, ++ .is_enabled = jh7100_clk_is_enabled, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_div_ops = { ++ .recalc_rate = jh7100_clk_recalc_rate, ++ .determine_rate = jh7100_clk_determine_rate, ++ .set_rate = jh7100_clk_set_rate, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_fdiv_ops = { ++ .recalc_rate = jh7100_clk_frac_recalc_rate, ++ .determine_rate = jh7100_clk_frac_determine_rate, ++ .set_rate = jh7100_clk_frac_set_rate, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_gdiv_ops = { ++ .enable = jh7100_clk_enable, ++ .disable = jh7100_clk_disable, ++ .is_enabled = jh7100_clk_is_enabled, ++ .recalc_rate = jh7100_clk_recalc_rate, ++ .determine_rate = jh7100_clk_determine_rate, ++ .set_rate = jh7100_clk_set_rate, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_mux_ops = { ++ .determine_rate = jh7100_clk_mux_determine_rate, ++ .set_parent = jh7100_clk_set_parent, ++ .get_parent = jh7100_clk_get_parent, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_gmux_ops = { ++ .enable = jh7100_clk_enable, ++ .disable = jh7100_clk_disable, ++ .is_enabled = jh7100_clk_is_enabled, ++ .determine_rate = jh7100_clk_mux_determine_rate, ++ .set_parent = jh7100_clk_set_parent, ++ .get_parent = jh7100_clk_get_parent, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_mdiv_ops = { ++ .recalc_rate = jh7100_clk_recalc_rate, ++ .determine_rate = jh7100_clk_determine_rate, ++ .get_parent = jh7100_clk_get_parent, ++ .set_parent = jh7100_clk_set_parent, ++ .set_rate = jh7100_clk_set_rate, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_gmd_ops = { ++ .enable = jh7100_clk_enable, ++ .disable = jh7100_clk_disable, ++ .is_enabled = jh7100_clk_is_enabled, ++ .recalc_rate = jh7100_clk_recalc_rate, ++ .determine_rate = jh7100_clk_determine_rate, ++ .get_parent = jh7100_clk_get_parent, ++ .set_parent = jh7100_clk_set_parent, ++ .set_rate = jh7100_clk_set_rate, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++static const struct clk_ops jh7100_clk_inv_ops = { ++ .get_phase = jh7100_clk_get_phase, ++ .set_phase = jh7100_clk_set_phase, ++ .debug_init = jh7100_clk_debug_init, ++}; ++ ++const struct clk_ops *starfive_jh7100_clk_ops(u32 max) ++{ ++ if (max & JH7100_CLK_DIV_MASK) { ++ if (max & JH7100_CLK_MUX_MASK) { ++ if (max & JH7100_CLK_ENABLE) ++ return &jh7100_clk_gmd_ops; ++ return &jh7100_clk_mdiv_ops; ++ } ++ if (max & JH7100_CLK_ENABLE) ++ return &jh7100_clk_gdiv_ops; ++ if (max == JH7100_CLK_FRAC_MAX) ++ return &jh7100_clk_fdiv_ops; ++ return &jh7100_clk_div_ops; ++ } ++ ++ if (max & JH7100_CLK_MUX_MASK) { ++ if (max & JH7100_CLK_ENABLE) ++ return &jh7100_clk_gmux_ops; ++ return &jh7100_clk_mux_ops; ++ } ++ ++ if (max & JH7100_CLK_ENABLE) ++ return &jh7100_clk_gate_ops; ++ ++ return &jh7100_clk_inv_ops; ++} ++EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops); diff --git a/target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch b/target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch new file mode 100644 index 0000000000..e9d0e7a71f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch @@ -0,0 +1,290 @@ +From 8daa4c812f3b32a4d56ab48945e552a137fca9b7 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:17 +0800 +Subject: [PATCH 005/122] clk: starfive: Rename clk-starfive-jh7100.h to + clk-starfive-jh71x0.h + +Rename clk-starfive-jh7100.h to clk-starfive-jh71x0.h for making +the code to be common. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/clk/starfive/clk-starfive-jh7100-audio.c | 2 +- + drivers/clk/starfive/clk-starfive-jh7100.c | 2 +- + drivers/clk/starfive/clk-starfive-jh71x0.c | 2 +- + .../starfive/{clk-starfive-jh7100.h => clk-starfive-jh71x0.h} | 0 + 4 files changed, 3 insertions(+), 3 deletions(-) + rename drivers/clk/starfive/{clk-starfive-jh7100.h => clk-starfive-jh71x0.h} (100%) + +--- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c +@@ -16,7 +16,7 @@ + + #include + +-#include "clk-starfive-jh7100.h" ++#include "clk-starfive-jh71x0.h" + + /* external clocks */ + #define JH7100_AUDCLK_AUDIO_SRC (JH7100_AUDCLK_END + 0) +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -15,7 +15,7 @@ + + #include + +-#include "clk-starfive-jh7100.h" ++#include "clk-starfive-jh71x0.h" + + /* external clocks */ + #define JH7100_CLK_OSC_SYS (JH7100_CLK_END + 0) +--- a/drivers/clk/starfive/clk-starfive-jh71x0.c ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c +@@ -10,7 +10,7 @@ + #include + #include + +-#include "clk-starfive-jh7100.h" ++#include "clk-starfive-jh71x0.h" + + static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw) + { +--- a/drivers/clk/starfive/clk-starfive-jh7100.h ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-#ifndef __CLK_STARFIVE_JH7100_H +-#define __CLK_STARFIVE_JH7100_H +- +-#include +-#include +-#include +-#include +- +-/* register fields */ +-#define JH7100_CLK_ENABLE BIT(31) +-#define JH7100_CLK_INVERT BIT(30) +-#define JH7100_CLK_MUX_MASK GENMASK(27, 24) +-#define JH7100_CLK_MUX_SHIFT 24 +-#define JH7100_CLK_DIV_MASK GENMASK(23, 0) +-#define JH7100_CLK_FRAC_MASK GENMASK(15, 8) +-#define JH7100_CLK_FRAC_SHIFT 8 +-#define JH7100_CLK_INT_MASK GENMASK(7, 0) +- +-/* fractional divider min/max */ +-#define JH7100_CLK_FRAC_MIN 100UL +-#define JH7100_CLK_FRAC_MAX 25599UL +- +-/* clock data */ +-struct jh7100_clk_data { +- const char *name; +- unsigned long flags; +- u32 max; +- u8 parents[4]; +-}; +- +-#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \ +- .name = _name, \ +- .flags = CLK_SET_RATE_PARENT | (_flags), \ +- .max = JH7100_CLK_ENABLE, \ +- .parents = { [0] = _parent }, \ +-} +- +-#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \ +- .name = _name, \ +- .flags = 0, \ +- .max = _max, \ +- .parents = { [0] = _parent }, \ +-} +- +-#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \ +- .name = _name, \ +- .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | (_max), \ +- .parents = { [0] = _parent }, \ +-} +- +-#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \ +- .name = _name, \ +- .flags = 0, \ +- .max = JH7100_CLK_FRAC_MAX, \ +- .parents = { [0] = _parent }, \ +-} +- +-#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \ +- .name = _name, \ +- .flags = 0, \ +- .max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \ +- .parents = { __VA_ARGS__ }, \ +-} +- +-#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \ +- .name = _name, \ +- .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | \ +- (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \ +- .parents = { __VA_ARGS__ }, \ +-} +- +-#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = { \ +- .name = _name, \ +- .flags = 0, \ +- .max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ +- .parents = { __VA_ARGS__ }, \ +-} +- +-#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = { \ +- .name = _name, \ +- .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | \ +- (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ +- .parents = { __VA_ARGS__ }, \ +-} +- +-#define JH7100__INV(_idx, _name, _parent) [_idx] = { \ +- .name = _name, \ +- .flags = CLK_SET_RATE_PARENT, \ +- .max = JH7100_CLK_INVERT, \ +- .parents = { [0] = _parent }, \ +-} +- +-struct jh7100_clk { +- struct clk_hw hw; +- unsigned int idx; +- unsigned int max_div; +-}; +- +-struct jh7100_clk_priv { +- /* protect clk enable and set rate/parent from happening at the same time */ +- spinlock_t rmw_lock; +- struct device *dev; +- void __iomem *base; +- struct clk_hw *pll[3]; +- struct jh7100_clk reg[]; +-}; +- +-const struct clk_ops *starfive_jh7100_clk_ops(u32 max); +- +-#endif +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.h +@@ -0,0 +1,114 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __CLK_STARFIVE_JH7100_H ++#define __CLK_STARFIVE_JH7100_H ++ ++#include ++#include ++#include ++#include ++ ++/* register fields */ ++#define JH7100_CLK_ENABLE BIT(31) ++#define JH7100_CLK_INVERT BIT(30) ++#define JH7100_CLK_MUX_MASK GENMASK(27, 24) ++#define JH7100_CLK_MUX_SHIFT 24 ++#define JH7100_CLK_DIV_MASK GENMASK(23, 0) ++#define JH7100_CLK_FRAC_MASK GENMASK(15, 8) ++#define JH7100_CLK_FRAC_SHIFT 8 ++#define JH7100_CLK_INT_MASK GENMASK(7, 0) ++ ++/* fractional divider min/max */ ++#define JH7100_CLK_FRAC_MIN 100UL ++#define JH7100_CLK_FRAC_MAX 25599UL ++ ++/* clock data */ ++struct jh7100_clk_data { ++ const char *name; ++ unsigned long flags; ++ u32 max; ++ u8 parents[4]; ++}; ++ ++#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \ ++ .name = _name, \ ++ .flags = CLK_SET_RATE_PARENT | (_flags), \ ++ .max = JH7100_CLK_ENABLE, \ ++ .parents = { [0] = _parent }, \ ++} ++ ++#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \ ++ .name = _name, \ ++ .flags = 0, \ ++ .max = _max, \ ++ .parents = { [0] = _parent }, \ ++} ++ ++#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \ ++ .name = _name, \ ++ .flags = _flags, \ ++ .max = JH7100_CLK_ENABLE | (_max), \ ++ .parents = { [0] = _parent }, \ ++} ++ ++#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \ ++ .name = _name, \ ++ .flags = 0, \ ++ .max = JH7100_CLK_FRAC_MAX, \ ++ .parents = { [0] = _parent }, \ ++} ++ ++#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \ ++ .name = _name, \ ++ .flags = 0, \ ++ .max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \ ++ .parents = { __VA_ARGS__ }, \ ++} ++ ++#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \ ++ .name = _name, \ ++ .flags = _flags, \ ++ .max = JH7100_CLK_ENABLE | \ ++ (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \ ++ .parents = { __VA_ARGS__ }, \ ++} ++ ++#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = { \ ++ .name = _name, \ ++ .flags = 0, \ ++ .max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ ++ .parents = { __VA_ARGS__ }, \ ++} ++ ++#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = { \ ++ .name = _name, \ ++ .flags = _flags, \ ++ .max = JH7100_CLK_ENABLE | \ ++ (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ ++ .parents = { __VA_ARGS__ }, \ ++} ++ ++#define JH7100__INV(_idx, _name, _parent) [_idx] = { \ ++ .name = _name, \ ++ .flags = CLK_SET_RATE_PARENT, \ ++ .max = JH7100_CLK_INVERT, \ ++ .parents = { [0] = _parent }, \ ++} ++ ++struct jh7100_clk { ++ struct clk_hw hw; ++ unsigned int idx; ++ unsigned int max_div; ++}; ++ ++struct jh7100_clk_priv { ++ /* protect clk enable and set rate/parent from happening at the same time */ ++ spinlock_t rmw_lock; ++ struct device *dev; ++ void __iomem *base; ++ struct clk_hw *pll[3]; ++ struct jh7100_clk reg[]; ++}; ++ ++const struct clk_ops *starfive_jh7100_clk_ops(u32 max); ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch b/target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch new file mode 100644 index 0000000000..60ebf2cc0a --- /dev/null +++ b/target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch @@ -0,0 +1,1249 @@ +From 674fa25b207e4bef6c27af2acfbca3a0d765a45b Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:18 +0800 +Subject: [PATCH 006/122] clk: starfive: Rename "jh7100" to "jh71x0" for the + common code + +Rename some variables from "jh7100" or "JH7100" to "jh71x0" +or "JH71X0". + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../clk/starfive/clk-starfive-jh7100-audio.c | 72 ++-- + drivers/clk/starfive/clk-starfive-jh7100.c | 389 +++++++++--------- + drivers/clk/starfive/clk-starfive-jh71x0.c | 282 ++++++------- + drivers/clk/starfive/clk-starfive-jh71x0.h | 81 ++-- + 4 files changed, 418 insertions(+), 406 deletions(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c +@@ -28,66 +28,66 @@ + #define JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD (JH7100_AUDCLK_END + 6) + #define JH7100_AUDCLK_VAD_INTMEM (JH7100_AUDCLK_END + 7) + +-static const struct jh7100_clk_data jh7100_audclk_data[] = { +- JH7100__GMD(JH7100_AUDCLK_ADC_MCLK, "adc_mclk", 0, 15, 2, ++static const struct jh71x0_clk_data jh7100_audclk_data[] = { ++ JH71X0__GMD(JH7100_AUDCLK_ADC_MCLK, "adc_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), +- JH7100__GMD(JH7100_AUDCLK_I2S1_MCLK, "i2s1_mclk", 0, 15, 2, ++ JH71X0__GMD(JH7100_AUDCLK_I2S1_MCLK, "i2s1_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), +- JH7100_GATE(JH7100_AUDCLK_I2SADC_APB, "i2sadc_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100_MDIV(JH7100_AUDCLK_I2SADC_BCLK, "i2sadc_bclk", 31, 2, ++ JH71X0_GATE(JH7100_AUDCLK_I2SADC_APB, "i2sadc_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0_MDIV(JH7100_AUDCLK_I2SADC_BCLK, "i2sadc_bclk", 31, 2, + JH7100_AUDCLK_ADC_MCLK, + JH7100_AUDCLK_I2SADC_BCLK_IOPAD), +- JH7100__INV(JH7100_AUDCLK_I2SADC_BCLK_N, "i2sadc_bclk_n", JH7100_AUDCLK_I2SADC_BCLK), +- JH7100_MDIV(JH7100_AUDCLK_I2SADC_LRCLK, "i2sadc_lrclk", 63, 3, ++ JH71X0__INV(JH7100_AUDCLK_I2SADC_BCLK_N, "i2sadc_bclk_n", JH7100_AUDCLK_I2SADC_BCLK), ++ JH71X0_MDIV(JH7100_AUDCLK_I2SADC_LRCLK, "i2sadc_lrclk", 63, 3, + JH7100_AUDCLK_I2SADC_BCLK_N, + JH7100_AUDCLK_I2SADC_LRCLK_IOPAD, + JH7100_AUDCLK_I2SADC_BCLK), +- JH7100_GATE(JH7100_AUDCLK_PDM_APB, "pdm_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100__GMD(JH7100_AUDCLK_PDM_MCLK, "pdm_mclk", 0, 15, 2, ++ JH71X0_GATE(JH7100_AUDCLK_PDM_APB, "pdm_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0__GMD(JH7100_AUDCLK_PDM_MCLK, "pdm_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), +- JH7100_GATE(JH7100_AUDCLK_I2SVAD_APB, "i2svad_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100__GMD(JH7100_AUDCLK_SPDIF, "spdif", 0, 15, 2, ++ JH71X0_GATE(JH7100_AUDCLK_I2SVAD_APB, "i2svad_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0__GMD(JH7100_AUDCLK_SPDIF, "spdif", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), +- JH7100_GATE(JH7100_AUDCLK_SPDIF_APB, "spdif_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100_GATE(JH7100_AUDCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100__GMD(JH7100_AUDCLK_DAC_MCLK, "dac_mclk", 0, 15, 2, ++ JH71X0_GATE(JH7100_AUDCLK_SPDIF_APB, "spdif_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0_GATE(JH7100_AUDCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0__GMD(JH7100_AUDCLK_DAC_MCLK, "dac_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), +- JH7100_GATE(JH7100_AUDCLK_I2SDAC_APB, "i2sdac_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100_MDIV(JH7100_AUDCLK_I2SDAC_BCLK, "i2sdac_bclk", 31, 2, ++ JH71X0_GATE(JH7100_AUDCLK_I2SDAC_APB, "i2sdac_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0_MDIV(JH7100_AUDCLK_I2SDAC_BCLK, "i2sdac_bclk", 31, 2, + JH7100_AUDCLK_DAC_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), +- JH7100__INV(JH7100_AUDCLK_I2SDAC_BCLK_N, "i2sdac_bclk_n", JH7100_AUDCLK_I2SDAC_BCLK), +- JH7100_MDIV(JH7100_AUDCLK_I2SDAC_LRCLK, "i2sdac_lrclk", 31, 2, ++ JH71X0__INV(JH7100_AUDCLK_I2SDAC_BCLK_N, "i2sdac_bclk_n", JH7100_AUDCLK_I2SDAC_BCLK), ++ JH71X0_MDIV(JH7100_AUDCLK_I2SDAC_LRCLK, "i2sdac_lrclk", 31, 2, + JH7100_AUDCLK_I2S1_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), +- JH7100_GATE(JH7100_AUDCLK_I2S1_APB, "i2s1_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100_MDIV(JH7100_AUDCLK_I2S1_BCLK, "i2s1_bclk", 31, 2, ++ JH71X0_GATE(JH7100_AUDCLK_I2S1_APB, "i2s1_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0_MDIV(JH7100_AUDCLK_I2S1_BCLK, "i2s1_bclk", 31, 2, + JH7100_AUDCLK_I2S1_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), +- JH7100__INV(JH7100_AUDCLK_I2S1_BCLK_N, "i2s1_bclk_n", JH7100_AUDCLK_I2S1_BCLK), +- JH7100_MDIV(JH7100_AUDCLK_I2S1_LRCLK, "i2s1_lrclk", 63, 3, ++ JH71X0__INV(JH7100_AUDCLK_I2S1_BCLK_N, "i2s1_bclk_n", JH7100_AUDCLK_I2S1_BCLK), ++ JH71X0_MDIV(JH7100_AUDCLK_I2S1_LRCLK, "i2s1_lrclk", 63, 3, + JH7100_AUDCLK_I2S1_BCLK_N, + JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD), +- JH7100_GATE(JH7100_AUDCLK_I2SDAC16K_APB, "i2s1dac16k_apb", 0, JH7100_AUDCLK_APB0_BUS), +- JH7100__DIV(JH7100_AUDCLK_APB0_BUS, "apb0_bus", 8, JH7100_AUDCLK_DOM7AHB_BUS), +- JH7100_GATE(JH7100_AUDCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7100_AUDCLK_DOM7AHB_BUS), +- JH7100_GATE(JH7100_AUDCLK_USB_APB, "usb_apb", CLK_IGNORE_UNUSED, JH7100_AUDCLK_APB_EN), +- JH7100_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB), +- JH7100_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB), +- JH7100__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS), +- JH7100__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2, ++ JH71X0_GATE(JH7100_AUDCLK_I2SDAC16K_APB, "i2s1dac16k_apb", 0, JH7100_AUDCLK_APB0_BUS), ++ JH71X0__DIV(JH7100_AUDCLK_APB0_BUS, "apb0_bus", 8, JH7100_AUDCLK_DOM7AHB_BUS), ++ JH71X0_GATE(JH7100_AUDCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7100_AUDCLK_DOM7AHB_BUS), ++ JH71X0_GATE(JH7100_AUDCLK_USB_APB, "usb_apb", CLK_IGNORE_UNUSED, JH7100_AUDCLK_APB_EN), ++ JH71X0_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB), ++ JH71X0_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB), ++ JH71X0__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS), ++ JH71X0__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2, + JH7100_AUDCLK_VAD_INTMEM, + JH7100_AUDCLK_AUDIO_12288), + }; + + static struct clk_hw *jh7100_audclk_get(struct of_phandle_args *clkspec, void *data) + { +- struct jh7100_clk_priv *priv = data; ++ struct jh71x0_clk_priv *priv = data; + unsigned int idx = clkspec->args[0]; + + if (idx < JH7100_AUDCLK_END) +@@ -98,7 +98,7 @@ static struct clk_hw *jh7100_audclk_get( + + static int jh7100_audclk_probe(struct platform_device *pdev) + { +- struct jh7100_clk_priv *priv; ++ struct jh71x0_clk_priv *priv; + unsigned int idx; + int ret; + +@@ -117,12 +117,12 @@ static int jh7100_audclk_probe(struct pl + struct clk_parent_data parents[4] = {}; + struct clk_init_data init = { + .name = jh7100_audclk_data[idx].name, +- .ops = starfive_jh7100_clk_ops(max), ++ .ops = starfive_jh71x0_clk_ops(max), + .parent_data = parents, +- .num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1, ++ .num_parents = ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, + .flags = jh7100_audclk_data[idx].flags, + }; +- struct jh7100_clk *clk = &priv->reg[idx]; ++ struct jh71x0_clk *clk = &priv->reg[idx]; + unsigned int i; + + for (i = 0; i < init.num_parents; i++) { +@@ -140,7 +140,7 @@ static int jh7100_audclk_probe(struct pl + + clk->hw.init = &init; + clk->idx = idx; +- clk->max_div = max & JH7100_CLK_DIV_MASK; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; + + ret = devm_clk_hw_register(priv->dev, &clk->hw); + if (ret) +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -23,250 +23,253 @@ + #define JH7100_CLK_GMAC_RMII_REF (JH7100_CLK_END + 2) + #define JH7100_CLK_GMAC_GR_MII_RX (JH7100_CLK_END + 3) + +-static const struct jh7100_clk_data jh7100_clk_data[] __initconst = { +- JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4, ++static const struct jh71x0_clk_data jh7100_clk_data[] __initconst = { ++ JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3, ++ JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4, ++ JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3, ++ JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2, ++ JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT), +- JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2, ++ JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3, ++ JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3, ++ JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3, + JH7100_CLK_OSC_AUD, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT), +- JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3, ++ JH71X0_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT), ++ JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3, ++ JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT), +- JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3, ++ JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3, + JH7100_CLK_OSC_AUD, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), +- JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", 2, JH7100_CLK_CPUNDBUS_ROOT), +- JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", 4, JH7100_CLK_DSP_ROOT), +- JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", 4, JH7100_CLK_PERH0_ROOT), +- JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", 4, JH7100_CLK_PERH1_ROOT), +- JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", 0, 31, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", 0, 31, JH7100_CLK_DLA_ROOT), +- JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", 0, 31, JH7100_CLK_PERH1_SRC), +- JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 2, ++ JH71X0__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", 2, JH7100_CLK_CPUNDBUS_ROOT), ++ JH71X0__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", 4, JH7100_CLK_DSP_ROOT), ++ JH71X0__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", 4, JH7100_CLK_PERH0_ROOT), ++ JH71X0__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", 4, JH7100_CLK_PERH1_ROOT), ++ JH71X0_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", 0, 31, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", 0, 31, JH7100_CLK_DLA_ROOT), ++ JH71X0_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", 0, 31, JH7100_CLK_PERH1_SRC), ++ JH71X0__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_OSC_AUD), +- JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", 8, JH7100_CLK_CPU_CORE), +- JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", 8, JH7100_CLK_AHB_BUS), +- JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", 8, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", CLK_IS_CRITICAL, JH7100_CLK_CPU_CORE), +- JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", CLK_IS_CRITICAL, 8, JH7100_CLK_CPU_CORE), +- JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", CLK_IS_CRITICAL, JH7100_CLK_CPU_AXI), +- JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", CLK_IS_CRITICAL, JH7100_CLK_OSC_SYS), +- JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", 0, JH7100_CLK_CPU_AXI), +- JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI), +- JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT), +- JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS), +- JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS), +- JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV), +- JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT), +- JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC), +- JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", 4, JH7100_CLK_CDECHIFI4_ROOT), +- JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", 8, JH7100_CLK_VCDECBUS_SRC), +- JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", 0, JH7100_CLK_VDEC_BUS), +- JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", 0, JH7100_CLK_VDEC_BUS), +- JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC), +- JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", 0, 8, JH7100_CLK_CDEC_ROOT), +- JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", 0, 8, JH7100_CLK_CDECHIFI4_ROOT), +- JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", 8, JH7100_CLK_VCDECBUS_SRC), +- JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", 0, JH7100_CLK_JPCGC300_AXIBUS), +- JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", 0, JH7100_CLK_JPCGC300_AXIBUS), +- JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", 8, JH7100_CLK_VCDECBUS_SRC), +- JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", 0, JH7100_CLK_VENC_BUS), +- JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", 0, JH7100_CLK_VENC_BUS), +- JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC), +- JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", 0, 8, JH7100_CLK_CDEC_ROOT), +- JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_PLL1_OUT), +- JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", CLK_IS_CRITICAL, 2, JH7100_CLK_DDRPLL_DIV2), +- JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", CLK_IS_CRITICAL, 2, JH7100_CLK_DDRPLL_DIV4), +- JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_OSC_SYS), +- JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", CLK_IS_CRITICAL, 4, ++ JH71X0__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", 8, JH7100_CLK_CPU_CORE), ++ JH71X0__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", 8, JH7100_CLK_AHB_BUS), ++ JH71X0__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", 8, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_U74_CORE0, "u74_core0", CLK_IS_CRITICAL, JH7100_CLK_CPU_CORE), ++ JH71X0_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", CLK_IS_CRITICAL, 8, JH7100_CLK_CPU_CORE), ++ JH71X0_GATE(JH7100_CLK_U74_AXI, "u74_axi", CLK_IS_CRITICAL, JH7100_CLK_CPU_AXI), ++ JH71X0_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", CLK_IS_CRITICAL, JH7100_CLK_OSC_SYS), ++ JH71X0_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", 0, JH7100_CLK_CPU_AXI), ++ JH71X0_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI), ++ JH71X0_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT), ++ JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS), ++ JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS), ++ JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV), ++ JH71X0__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT), ++ JH71X0_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC), ++ JH71X0__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", 4, JH7100_CLK_CDECHIFI4_ROOT), ++ JH71X0__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", 8, JH7100_CLK_VCDECBUS_SRC), ++ JH71X0_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", 0, JH7100_CLK_VDEC_BUS), ++ JH71X0_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", 0, JH7100_CLK_VDEC_BUS), ++ JH71X0_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC), ++ JH71X0_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", 0, 8, JH7100_CLK_CDEC_ROOT), ++ JH71X0_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", 0, 8, JH7100_CLK_CDECHIFI4_ROOT), ++ JH71X0_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", 8, JH7100_CLK_VCDECBUS_SRC), ++ JH71X0_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", 0, JH7100_CLK_JPCGC300_AXIBUS), ++ JH71X0_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", 0, JH7100_CLK_JPCGC300_AXIBUS), ++ JH71X0__DIV(JH7100_CLK_VENC_BUS, "venc_bus", 8, JH7100_CLK_VCDECBUS_SRC), ++ JH71X0_GATE(JH7100_CLK_VENC_AXI, "venc_axi", 0, JH7100_CLK_VENC_BUS), ++ JH71X0_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", 0, JH7100_CLK_VENC_BUS), ++ JH71X0_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC), ++ JH71X0_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", 0, 8, JH7100_CLK_CDEC_ROOT), ++ JH71X0_GATE(JH7100_CLK_VENC_APB, "venc_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_PLL1_OUT), ++ JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", CLK_IS_CRITICAL, 2, ++ JH7100_CLK_DDRPLL_DIV2), ++ JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", CLK_IS_CRITICAL, 2, ++ JH7100_CLK_DDRPLL_DIV4), ++ JH71X0_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_OSC_SYS), ++ JH71X0_GMUX(JH7100_CLK_DDRC0, "ddrc0", CLK_IS_CRITICAL, 4, + JH7100_CLK_DDROSC_DIV2, + JH7100_CLK_DDRPLL_DIV2, + JH7100_CLK_DDRPLL_DIV4, + JH7100_CLK_DDRPLL_DIV8), +- JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", CLK_IS_CRITICAL, 4, ++ JH71X0_GMUX(JH7100_CLK_DDRC1, "ddrc1", CLK_IS_CRITICAL, 4, + JH7100_CLK_DDROSC_DIV2, + JH7100_CLK_DDRPLL_DIV2, + JH7100_CLK_DDRPLL_DIV4, + JH7100_CLK_DDRPLL_DIV8), +- JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", 8, JH7100_CLK_DLA_ROOT), +- JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", 4, JH7100_CLK_DSP_ROOT), +- JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 2, ++ JH71X0_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0__DIV(JH7100_CLK_NOC_ROB, "noc_rob", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0__DIV(JH7100_CLK_NOC_COG, "noc_cog", 8, JH7100_CLK_DLA_ROOT), ++ JH71X0_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", 4, JH7100_CLK_DSP_ROOT), ++ JH71X0__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 2, + JH7100_CLK_CPU_AXI, + JH7100_CLK_NNEBUS_SRC1), +- JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS), +- JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", 0, JH7100_CLK_NNE_BUS), +- JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", 0, JH7100_CLK_NNE_BUS), +- JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", CLK_IS_CRITICAL, JH7100_CLK_NNE_BUS), +- JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", 4, JH7100_CLK_CDECHIFI4_ROOT), +- JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", 8, JH7100_CLK_HIFI4_SRC), +- JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", 0, JH7100_CLK_HIFI4_COREFREE), +- JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", 8, JH7100_CLK_HIFI4_COREFREE), +- JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", 0, JH7100_CLK_HIFI4_BUS), +- JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", 0, JH7100_CLK_HIFI4_BUS), +- JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS), +- JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS), +- JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", CLK_IS_CRITICAL, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS), +- JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS), +- JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT), +- JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV), +- JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32, JH7100_CLK_USBPHY_ROOTDIV), +- JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2, ++ JH71X0_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS), ++ JH71X0_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", 0, JH7100_CLK_NNE_BUS), ++ JH71X0_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", 0, JH7100_CLK_NNE_BUS), ++ JH71X0_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", CLK_IS_CRITICAL, JH7100_CLK_NNE_BUS), ++ JH71X0__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", 4, JH7100_CLK_CDECHIFI4_ROOT), ++ JH71X0__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", 8, JH7100_CLK_HIFI4_SRC), ++ JH71X0_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", 0, JH7100_CLK_HIFI4_COREFREE), ++ JH71X0__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", 8, JH7100_CLK_HIFI4_COREFREE), ++ JH71X0_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", 0, JH7100_CLK_HIFI4_BUS), ++ JH71X0_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", 0, JH7100_CLK_HIFI4_BUS), ++ JH71X0__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS), ++ JH71X0_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS), ++ JH71X0_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", CLK_IS_CRITICAL, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0__DIV(JH7100_CLK_USB_BUS, "usb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), ++ JH71X0_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS), ++ JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS), ++ JH71X0__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT), ++ JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV), ++ JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32, ++ JH7100_CLK_USBPHY_ROOTDIV), ++ JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_USBPHY_PLLDIV25M), +- JH7100_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT), +- JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV), +- JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD), +- JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT), +- JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", 8, JH7100_CLK_VIN_SRC), +- JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", 0, JH7100_CLK_ISP0_BUS), +- JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", 0, JH7100_CLK_ISP0_BUS), +- JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", 0, JH7100_CLK_ISP0_BUS), +- JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", 8, JH7100_CLK_VIN_SRC), +- JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", 0, JH7100_CLK_ISP1_BUS), +- JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", 0, JH7100_CLK_ISP1_BUS), +- JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC), +- JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS), +- JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS), +- JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT), +- JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT), +- JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC), +- JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS), +- JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS), +- JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC), +- JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT), +- JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", 0, 24, JH7100_CLK_PERH1_SRC), +- JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", JH7100_CLK_SDIO1_CCLKINT), +- JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", 8, JH7100_CLK_GMACUSB_ROOT), +- JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", 0, 31, JH7100_CLK_GMAC_ROOT_DIV), +- JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV), +- JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), +- JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), +- JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 3, ++ JH71X0_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT), ++ JH71X0_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV), ++ JH71X0_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD), ++ JH71X0_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT), ++ JH71X0__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", 8, JH7100_CLK_VIN_SRC), ++ JH71X0_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", 0, JH7100_CLK_ISP0_BUS), ++ JH71X0_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", 0, JH7100_CLK_ISP0_BUS), ++ JH71X0_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", 0, JH7100_CLK_ISP0_BUS), ++ JH71X0__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", 8, JH7100_CLK_VIN_SRC), ++ JH71X0_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", 0, JH7100_CLK_ISP1_BUS), ++ JH71X0_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", 0, JH7100_CLK_ISP1_BUS), ++ JH71X0__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC), ++ JH71X0_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS), ++ JH71X0_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS), ++ JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT), ++ JH71X0__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT), ++ JH71X0__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC), ++ JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS), ++ JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS), ++ JH71X0_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC), ++ JH71X0__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT), ++ JH71X0_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", 0, 24, JH7100_CLK_PERH1_SRC), ++ JH71X0__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", JH7100_CLK_SDIO1_CCLKINT), ++ JH71X0_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", 8, JH7100_CLK_GMACUSB_ROOT), ++ JH71X0_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", 0, 31, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 3, + JH7100_CLK_GMAC_GTX, + JH7100_CLK_GMAC_TX_INV, + JH7100_CLK_GMAC_RMII_TX), +- JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", JH7100_CLK_GMAC_TX), +- JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 2, ++ JH71X0__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", JH7100_CLK_GMAC_TX), ++ JH71X0__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 2, + JH7100_CLK_GMAC_GR_MII_RX, + JH7100_CLK_GMAC_RMII_RX), +- JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE), +- JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", 0, JH7100_CLK_GMAC_RMII_REF), +- JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", 0, 127, JH7100_CLK_GMAC_ROOT_DIV), +- JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", 0, 31, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", 0, JH7100_CLK_OSC_SYS), +- JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", 0, 31, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", 0, JH7100_CLK_AHB_BUS), +- JH7100_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB), +- JH7100_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB), +- JH7100_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB), +- JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", 0, 63, JH7100_CLK_PERH1_SRC), +- JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", 0, JH7100_CLK_APB1_BUS), +- JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), +- JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", 0, JH7100_CLK_APB2_BUS), +- JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", 0, 31, JH7100_CLK_OSC_SYS), +- JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE), ++ JH71X0_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", 0, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", 0, 127, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", 0, 31, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_E24_AHB, "e24_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", 0, JH7100_CLK_OSC_SYS), ++ JH71X0_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", 0, 31, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB), ++ JH71X0_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB), ++ JH71X0_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB), ++ JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_UART1_APB, "uart1_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", 0, 63, JH7100_CLK_PERH1_SRC), ++ JH71X0_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GATE(JH7100_CLK_UART2_APB, "uart2_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_UART3_APB, "uart3_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", 0, 63, JH7100_CLK_PERH0_SRC), ++ JH71X0_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GATE(JH7100_CLK_PWM_APB, "pwm_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GATE(JH7100_CLK_MSI_APB, "msi_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GATE(JH7100_CLK_TEMP_APB, "temp_apb", 0, JH7100_CLK_APB2_BUS), ++ JH71X0_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", 0, 31, JH7100_CLK_OSC_SYS), ++ JH71X0_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS), + }; + + static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data) + { +- struct jh7100_clk_priv *priv = data; ++ struct jh71x0_clk_priv *priv = data; + unsigned int idx = clkspec->args[0]; + + if (idx < JH7100_CLK_PLL0_OUT) +@@ -280,7 +283,7 @@ static struct clk_hw *jh7100_clk_get(str + + static int __init clk_starfive_jh7100_probe(struct platform_device *pdev) + { +- struct jh7100_clk_priv *priv; ++ struct jh71x0_clk_priv *priv; + unsigned int idx; + int ret; + +@@ -314,12 +317,12 @@ static int __init clk_starfive_jh7100_pr + struct clk_parent_data parents[4] = {}; + struct clk_init_data init = { + .name = jh7100_clk_data[idx].name, +- .ops = starfive_jh7100_clk_ops(max), ++ .ops = starfive_jh71x0_clk_ops(max), + .parent_data = parents, +- .num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1, ++ .num_parents = ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, + .flags = jh7100_clk_data[idx].flags, + }; +- struct jh7100_clk *clk = &priv->reg[idx]; ++ struct jh71x0_clk *clk = &priv->reg[idx]; + unsigned int i; + + for (i = 0; i < init.num_parents; i++) { +@@ -341,7 +344,7 @@ static int __init clk_starfive_jh7100_pr + + clk->hw.init = &init; + clk->idx = idx; +- clk->max_div = max & JH7100_CLK_DIV_MASK; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; + + ret = devm_clk_hw_register(priv->dev, &clk->hw); + if (ret) +--- a/drivers/clk/starfive/clk-starfive-jh71x0.c ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * StarFive JH7100 Clock Generator Driver ++ * StarFive JH71X0 Clock Generator Driver + * + * Copyright (C) 2021-2022 Emil Renner Berthing + */ +@@ -12,27 +12,27 @@ + + #include "clk-starfive-jh71x0.h" + +-static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw) ++static struct jh71x0_clk *jh71x0_clk_from(struct clk_hw *hw) + { +- return container_of(hw, struct jh7100_clk, hw); ++ return container_of(hw, struct jh71x0_clk, hw); + } + +-static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk) ++static struct jh71x0_clk_priv *jh71x0_priv_from(struct jh71x0_clk *clk) + { +- return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]); ++ return container_of(clk, struct jh71x0_clk_priv, reg[clk->idx]); + } + +-static u32 jh7100_clk_reg_get(struct jh7100_clk *clk) ++static u32 jh71x0_clk_reg_get(struct jh71x0_clk *clk) + { +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); + void __iomem *reg = priv->base + 4 * clk->idx; + + return readl_relaxed(reg); + } + +-static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value) ++static void jh71x0_clk_reg_rmw(struct jh71x0_clk *clk, u32 mask, u32 value) + { +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); + void __iomem *reg = priv->base + 4 * clk->idx; + unsigned long flags; + +@@ -42,41 +42,41 @@ static void jh7100_clk_reg_rmw(struct jh + spin_unlock_irqrestore(&priv->rmw_lock, flags); + } + +-static int jh7100_clk_enable(struct clk_hw *hw) ++static int jh71x0_clk_enable(struct clk_hw *hw) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, JH71X0_CLK_ENABLE); + return 0; + } + +-static void jh7100_clk_disable(struct clk_hw *hw) ++static void jh71x0_clk_disable(struct clk_hw *hw) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, 0); + } + +-static int jh7100_clk_is_enabled(struct clk_hw *hw) ++static int jh71x0_clk_is_enabled(struct clk_hw *hw) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + +- return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE); ++ return !!(jh71x0_clk_reg_get(clk) & JH71X0_CLK_ENABLE); + } + +-static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw, ++static unsigned long jh71x0_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK; ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ u32 div = jh71x0_clk_reg_get(clk) & JH71X0_CLK_DIV_MASK; + + return div ? parent_rate / div : 0; + } + +-static int jh7100_clk_determine_rate(struct clk_hw *hw, ++static int jh71x0_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + unsigned long parent = req->best_parent_rate; + unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); + unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div); +@@ -102,232 +102,232 @@ static int jh7100_clk_determine_rate(str + return 0; + } + +-static int jh7100_clk_set_rate(struct clk_hw *hw, ++static int jh71x0_clk_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate), + 1UL, (unsigned long)clk->max_div); + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, div); + return 0; + } + +-static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw, ++static unsigned long jh71x0_clk_frac_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 reg = jh7100_clk_reg_get(clk); +- unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) + +- ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ u32 reg = jh71x0_clk_reg_get(clk); ++ unsigned long div100 = 100 * (reg & JH71X0_CLK_INT_MASK) + ++ ((reg & JH71X0_CLK_FRAC_MASK) >> JH71X0_CLK_FRAC_SHIFT); + +- return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; ++ return (div100 >= JH71X0_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; + } + +-static int jh7100_clk_frac_determine_rate(struct clk_hw *hw, ++static int jh71x0_clk_frac_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) + { + unsigned long parent100 = 100 * req->best_parent_rate; + unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); + unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate), +- JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); ++ JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX); + unsigned long result = parent100 / div100; + +- /* clamp the result as in jh7100_clk_determine_rate() above */ +- if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX) ++ /* clamp the result as in jh71x0_clk_determine_rate() above */ ++ if (result > req->max_rate && div100 < JH71X0_CLK_FRAC_MAX) + result = parent100 / (div100 + 1); +- if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN) ++ if (result < req->min_rate && div100 > JH71X0_CLK_FRAC_MIN) + result = parent100 / (div100 - 1); + + req->rate = result; + return 0; + } + +-static int jh7100_clk_frac_set_rate(struct clk_hw *hw, ++static int jh71x0_clk_frac_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate), +- JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); +- u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100); ++ JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX); ++ u32 value = ((div100 % 100) << JH71X0_CLK_FRAC_SHIFT) | (div100 / 100); + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, value); + return 0; + } + +-static u8 jh7100_clk_get_parent(struct clk_hw *hw) ++static u8 jh71x0_clk_get_parent(struct clk_hw *hw) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = jh7100_clk_reg_get(clk); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ u32 value = jh71x0_clk_reg_get(clk); + +- return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT; ++ return (value & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT; + } + +-static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index) ++static int jh71x0_clk_set_parent(struct clk_hw *hw, u8 index) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = (u32)index << JH7100_CLK_MUX_SHIFT; ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ u32 value = (u32)index << JH71X0_CLK_MUX_SHIFT; + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_MUX_MASK, value); + return 0; + } + +-static int jh7100_clk_mux_determine_rate(struct clk_hw *hw, ++static int jh71x0_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) + { + return clk_mux_determine_rate_flags(hw, req, 0); + } + +-static int jh7100_clk_get_phase(struct clk_hw *hw) ++static int jh71x0_clk_get_phase(struct clk_hw *hw) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- u32 value = jh7100_clk_reg_get(clk); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ u32 value = jh71x0_clk_reg_get(clk); + +- return (value & JH7100_CLK_INVERT) ? 180 : 0; ++ return (value & JH71X0_CLK_INVERT) ? 180 : 0; + } + +-static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees) ++static int jh71x0_clk_set_phase(struct clk_hw *hw, int degrees) + { +- struct jh7100_clk *clk = jh7100_clk_from(hw); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); + u32 value; + + if (degrees == 0) + value = 0; + else if (degrees == 180) +- value = JH7100_CLK_INVERT; ++ value = JH71X0_CLK_INVERT; + else + return -EINVAL; + +- jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value); ++ jh71x0_clk_reg_rmw(clk, JH71X0_CLK_INVERT, value); + return 0; + } + + #ifdef CONFIG_DEBUG_FS +-static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) ++static void jh71x0_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) + { +- static const struct debugfs_reg32 jh7100_clk_reg = { ++ static const struct debugfs_reg32 jh71x0_clk_reg = { + .name = "CTRL", + .offset = 0, + }; +- struct jh7100_clk *clk = jh7100_clk_from(hw); +- struct jh7100_clk_priv *priv = jh7100_priv_from(clk); ++ struct jh71x0_clk *clk = jh71x0_clk_from(hw); ++ struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); + struct debugfs_regset32 *regset; + + regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL); + if (!regset) + return; + +- regset->regs = &jh7100_clk_reg; ++ regset->regs = &jh71x0_clk_reg; + regset->nregs = 1; + regset->base = priv->base + 4 * clk->idx; + + debugfs_create_regset32("registers", 0400, dentry, regset); + } + #else +-#define jh7100_clk_debug_init NULL ++#define jh71x0_clk_debug_init NULL + #endif + +-static const struct clk_ops jh7100_clk_gate_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_gate_ops = { ++ .enable = jh71x0_clk_enable, ++ .disable = jh71x0_clk_disable, ++ .is_enabled = jh71x0_clk_is_enabled, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_div_ops = { +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_div_ops = { ++ .recalc_rate = jh71x0_clk_recalc_rate, ++ .determine_rate = jh71x0_clk_determine_rate, ++ .set_rate = jh71x0_clk_set_rate, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_fdiv_ops = { +- .recalc_rate = jh7100_clk_frac_recalc_rate, +- .determine_rate = jh7100_clk_frac_determine_rate, +- .set_rate = jh7100_clk_frac_set_rate, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_fdiv_ops = { ++ .recalc_rate = jh71x0_clk_frac_recalc_rate, ++ .determine_rate = jh71x0_clk_frac_determine_rate, ++ .set_rate = jh71x0_clk_frac_set_rate, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_gdiv_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_gdiv_ops = { ++ .enable = jh71x0_clk_enable, ++ .disable = jh71x0_clk_disable, ++ .is_enabled = jh71x0_clk_is_enabled, ++ .recalc_rate = jh71x0_clk_recalc_rate, ++ .determine_rate = jh71x0_clk_determine_rate, ++ .set_rate = jh71x0_clk_set_rate, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_mux_ops = { +- .determine_rate = jh7100_clk_mux_determine_rate, +- .set_parent = jh7100_clk_set_parent, +- .get_parent = jh7100_clk_get_parent, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_mux_ops = { ++ .determine_rate = jh71x0_clk_mux_determine_rate, ++ .set_parent = jh71x0_clk_set_parent, ++ .get_parent = jh71x0_clk_get_parent, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_gmux_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .determine_rate = jh7100_clk_mux_determine_rate, +- .set_parent = jh7100_clk_set_parent, +- .get_parent = jh7100_clk_get_parent, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_gmux_ops = { ++ .enable = jh71x0_clk_enable, ++ .disable = jh71x0_clk_disable, ++ .is_enabled = jh71x0_clk_is_enabled, ++ .determine_rate = jh71x0_clk_mux_determine_rate, ++ .set_parent = jh71x0_clk_set_parent, ++ .get_parent = jh71x0_clk_get_parent, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_mdiv_ops = { +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .get_parent = jh7100_clk_get_parent, +- .set_parent = jh7100_clk_set_parent, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_mdiv_ops = { ++ .recalc_rate = jh71x0_clk_recalc_rate, ++ .determine_rate = jh71x0_clk_determine_rate, ++ .get_parent = jh71x0_clk_get_parent, ++ .set_parent = jh71x0_clk_set_parent, ++ .set_rate = jh71x0_clk_set_rate, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_gmd_ops = { +- .enable = jh7100_clk_enable, +- .disable = jh7100_clk_disable, +- .is_enabled = jh7100_clk_is_enabled, +- .recalc_rate = jh7100_clk_recalc_rate, +- .determine_rate = jh7100_clk_determine_rate, +- .get_parent = jh7100_clk_get_parent, +- .set_parent = jh7100_clk_set_parent, +- .set_rate = jh7100_clk_set_rate, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_gmd_ops = { ++ .enable = jh71x0_clk_enable, ++ .disable = jh71x0_clk_disable, ++ .is_enabled = jh71x0_clk_is_enabled, ++ .recalc_rate = jh71x0_clk_recalc_rate, ++ .determine_rate = jh71x0_clk_determine_rate, ++ .get_parent = jh71x0_clk_get_parent, ++ .set_parent = jh71x0_clk_set_parent, ++ .set_rate = jh71x0_clk_set_rate, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-static const struct clk_ops jh7100_clk_inv_ops = { +- .get_phase = jh7100_clk_get_phase, +- .set_phase = jh7100_clk_set_phase, +- .debug_init = jh7100_clk_debug_init, ++static const struct clk_ops jh71x0_clk_inv_ops = { ++ .get_phase = jh71x0_clk_get_phase, ++ .set_phase = jh71x0_clk_set_phase, ++ .debug_init = jh71x0_clk_debug_init, + }; + +-const struct clk_ops *starfive_jh7100_clk_ops(u32 max) ++const struct clk_ops *starfive_jh71x0_clk_ops(u32 max) + { +- if (max & JH7100_CLK_DIV_MASK) { +- if (max & JH7100_CLK_MUX_MASK) { +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gmd_ops; +- return &jh7100_clk_mdiv_ops; ++ if (max & JH71X0_CLK_DIV_MASK) { ++ if (max & JH71X0_CLK_MUX_MASK) { ++ if (max & JH71X0_CLK_ENABLE) ++ return &jh71x0_clk_gmd_ops; ++ return &jh71x0_clk_mdiv_ops; + } +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gdiv_ops; +- if (max == JH7100_CLK_FRAC_MAX) +- return &jh7100_clk_fdiv_ops; +- return &jh7100_clk_div_ops; ++ if (max & JH71X0_CLK_ENABLE) ++ return &jh71x0_clk_gdiv_ops; ++ if (max == JH71X0_CLK_FRAC_MAX) ++ return &jh71x0_clk_fdiv_ops; ++ return &jh71x0_clk_div_ops; + } + +- if (max & JH7100_CLK_MUX_MASK) { +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gmux_ops; +- return &jh7100_clk_mux_ops; ++ if (max & JH71X0_CLK_MUX_MASK) { ++ if (max & JH71X0_CLK_ENABLE) ++ return &jh71x0_clk_gmux_ops; ++ return &jh71x0_clk_mux_ops; + } + +- if (max & JH7100_CLK_ENABLE) +- return &jh7100_clk_gate_ops; ++ if (max & JH71X0_CLK_ENABLE) ++ return &jh71x0_clk_gate_ops; + +- return &jh7100_clk_inv_ops; ++ return &jh71x0_clk_inv_ops; + } +-EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops); ++EXPORT_SYMBOL_GPL(starfive_jh71x0_clk_ops); +--- a/drivers/clk/starfive/clk-starfive-jh71x0.h ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 */ +-#ifndef __CLK_STARFIVE_JH7100_H +-#define __CLK_STARFIVE_JH7100_H ++#ifndef __CLK_STARFIVE_JH71X0_H ++#define __CLK_STARFIVE_JH71X0_H + + #include + #include +@@ -8,107 +8,116 @@ + #include + + /* register fields */ +-#define JH7100_CLK_ENABLE BIT(31) +-#define JH7100_CLK_INVERT BIT(30) +-#define JH7100_CLK_MUX_MASK GENMASK(27, 24) +-#define JH7100_CLK_MUX_SHIFT 24 +-#define JH7100_CLK_DIV_MASK GENMASK(23, 0) +-#define JH7100_CLK_FRAC_MASK GENMASK(15, 8) +-#define JH7100_CLK_FRAC_SHIFT 8 +-#define JH7100_CLK_INT_MASK GENMASK(7, 0) ++#define JH71X0_CLK_ENABLE BIT(31) ++#define JH71X0_CLK_INVERT BIT(30) ++#define JH71X0_CLK_MUX_MASK GENMASK(27, 24) ++#define JH71X0_CLK_MUX_SHIFT 24 ++#define JH71X0_CLK_DIV_MASK GENMASK(23, 0) ++#define JH71X0_CLK_FRAC_MASK GENMASK(15, 8) ++#define JH71X0_CLK_FRAC_SHIFT 8 ++#define JH71X0_CLK_INT_MASK GENMASK(7, 0) + + /* fractional divider min/max */ +-#define JH7100_CLK_FRAC_MIN 100UL +-#define JH7100_CLK_FRAC_MAX 25599UL ++#define JH71X0_CLK_FRAC_MIN 100UL ++#define JH71X0_CLK_FRAC_MAX 25599UL + + /* clock data */ +-struct jh7100_clk_data { ++struct jh71x0_clk_data { + const char *name; + unsigned long flags; + u32 max; + u8 parents[4]; + }; + +-#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \ ++#define JH71X0_GATE(_idx, _name, _flags, _parent) \ ++[_idx] = { \ + .name = _name, \ + .flags = CLK_SET_RATE_PARENT | (_flags), \ +- .max = JH7100_CLK_ENABLE, \ ++ .max = JH71X0_CLK_ENABLE, \ + .parents = { [0] = _parent }, \ + } + +-#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \ ++#define JH71X0__DIV(_idx, _name, _max, _parent) \ ++[_idx] = { \ + .name = _name, \ + .flags = 0, \ + .max = _max, \ + .parents = { [0] = _parent }, \ + } + +-#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \ ++#define JH71X0_GDIV(_idx, _name, _flags, _max, _parent) \ ++[_idx] = { \ + .name = _name, \ + .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | (_max), \ ++ .max = JH71X0_CLK_ENABLE | (_max), \ + .parents = { [0] = _parent }, \ + } + +-#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \ ++#define JH71X0_FDIV(_idx, _name, _parent) \ ++[_idx] = { \ + .name = _name, \ + .flags = 0, \ +- .max = JH7100_CLK_FRAC_MAX, \ ++ .max = JH71X0_CLK_FRAC_MAX, \ + .parents = { [0] = _parent }, \ + } + +-#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \ ++#define JH71X0__MUX(_idx, _name, _nparents, ...) \ ++[_idx] = { \ + .name = _name, \ + .flags = 0, \ +- .max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \ ++ .max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT, \ + .parents = { __VA_ARGS__ }, \ + } + +-#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \ ++#define JH71X0_GMUX(_idx, _name, _flags, _nparents, ...) \ ++[_idx] = { \ + .name = _name, \ + .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | \ +- (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \ ++ .max = JH71X0_CLK_ENABLE | \ ++ (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT), \ + .parents = { __VA_ARGS__ }, \ + } + +-#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = { \ ++#define JH71X0_MDIV(_idx, _name, _max, _nparents, ...) \ ++[_idx] = { \ + .name = _name, \ + .flags = 0, \ +- .max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ ++ .max = (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max), \ + .parents = { __VA_ARGS__ }, \ + } + +-#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = { \ ++#define JH71X0__GMD(_idx, _name, _flags, _max, _nparents, ...) \ ++[_idx] = { \ + .name = _name, \ + .flags = _flags, \ +- .max = JH7100_CLK_ENABLE | \ +- (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ ++ .max = JH71X0_CLK_ENABLE | \ ++ (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max), \ + .parents = { __VA_ARGS__ }, \ + } + +-#define JH7100__INV(_idx, _name, _parent) [_idx] = { \ ++#define JH71X0__INV(_idx, _name, _parent) \ ++[_idx] = { \ + .name = _name, \ + .flags = CLK_SET_RATE_PARENT, \ +- .max = JH7100_CLK_INVERT, \ ++ .max = JH71X0_CLK_INVERT, \ + .parents = { [0] = _parent }, \ + } + +-struct jh7100_clk { ++struct jh71x0_clk { + struct clk_hw hw; + unsigned int idx; + unsigned int max_div; + }; + +-struct jh7100_clk_priv { ++struct jh71x0_clk_priv { + /* protect clk enable and set rate/parent from happening at the same time */ + spinlock_t rmw_lock; + struct device *dev; + void __iomem *base; + struct clk_hw *pll[3]; +- struct jh7100_clk reg[]; ++ struct jh71x0_clk reg[]; + }; + +-const struct clk_ops *starfive_jh7100_clk_ops(u32 max); ++const struct clk_ops *starfive_jh71x0_clk_ops(u32 max); + + #endif diff --git a/target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch b/target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch new file mode 100644 index 0000000000..e5281b85e9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch @@ -0,0 +1,30 @@ +From 0ee5a7565601fa785d7e55c57f26ff5d79473eb2 Mon Sep 17 00:00:00 2001 +From: Hal Feng +Date: Sat, 1 Apr 2023 19:19:19 +0800 +Subject: [PATCH 007/122] reset: starfive: Replace SOC_STARFIVE with + ARCH_STARFIVE + +Using ARCH_FOO symbol is preferred than SOC_FOO. + +Reviewed-by: Philipp Zabel +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/reset/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -234,8 +234,8 @@ config RESET_SOCFPGA + + config RESET_STARFIVE_JH7100 + bool "StarFive JH7100 Reset Driver" +- depends on SOC_STARFIVE || COMPILE_TEST +- default SOC_STARFIVE ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ default ARCH_STARFIVE + help + This enables the reset controller driver for the StarFive JH7100 SoC. + diff --git a/target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch b/target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch new file mode 100644 index 0000000000..2e44f38e59 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch @@ -0,0 +1,436 @@ +From ea9e5879793f9743fbfe613174900ab0c431ac0e Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:20 +0800 +Subject: [PATCH 008/122] reset: Create subdirectory for StarFive drivers + +This moves the StarFive JH7100 reset driver to a new subdirectory in +preparation for adding more StarFive reset drivers. + +Reviewed-by: Philipp Zabel +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/reset/Kconfig | 8 +------- + drivers/reset/Makefile | 2 +- + drivers/reset/starfive/Kconfig | 8 ++++++++ + drivers/reset/starfive/Makefile | 2 ++ + drivers/reset/{ => starfive}/reset-starfive-jh7100.c | 0 + 5 files changed, 12 insertions(+), 8 deletions(-) + create mode 100644 drivers/reset/starfive/Kconfig + create mode 100644 drivers/reset/starfive/Makefile + rename drivers/reset/{ => starfive}/reset-starfive-jh7100.c (100%) + +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -232,13 +232,6 @@ config RESET_SOCFPGA + This enables the reset driver for the SoCFPGA ARMv7 platforms. This + driver gets initialized early during platform init calls. + +-config RESET_STARFIVE_JH7100 +- bool "StarFive JH7100 Reset Driver" +- depends on ARCH_STARFIVE || COMPILE_TEST +- default ARCH_STARFIVE +- help +- This enables the reset controller driver for the StarFive JH7100 SoC. +- + config RESET_SUNPLUS + bool "Sunplus SoCs Reset Driver" if COMPILE_TEST + default ARCH_SUNPLUS +@@ -320,6 +313,7 @@ config RESET_ZYNQ + help + This enables the reset controller driver for Xilinx Zynq SoCs. + ++source "drivers/reset/starfive/Kconfig" + source "drivers/reset/sti/Kconfig" + source "drivers/reset/hisilicon/Kconfig" + source "drivers/reset/tegra/Kconfig" +--- a/drivers/reset/Makefile ++++ b/drivers/reset/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-y += core.o + obj-y += hisilicon/ ++obj-y += starfive/ + obj-$(CONFIG_ARCH_STI) += sti/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ + obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o +@@ -30,7 +31,6 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += + obj-$(CONFIG_RESET_SCMI) += reset-scmi.o + obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o + obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o +-obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o + obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o + obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o + obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o +--- /dev/null ++++ b/drivers/reset/starfive/Kconfig +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++config RESET_STARFIVE_JH7100 ++ bool "StarFive JH7100 Reset Driver" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ default ARCH_STARFIVE ++ help ++ This enables the reset controller driver for the StarFive JH7100 SoC. +--- /dev/null ++++ b/drivers/reset/starfive/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o +--- a/drivers/reset/reset-starfive-jh7100.c ++++ /dev/null +@@ -1,173 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Reset driver for the StarFive JH7100 SoC +- * +- * Copyright (C) 2021 Emil Renner Berthing +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-/* register offsets */ +-#define JH7100_RESET_ASSERT0 0x00 +-#define JH7100_RESET_ASSERT1 0x04 +-#define JH7100_RESET_ASSERT2 0x08 +-#define JH7100_RESET_ASSERT3 0x0c +-#define JH7100_RESET_STATUS0 0x10 +-#define JH7100_RESET_STATUS1 0x14 +-#define JH7100_RESET_STATUS2 0x18 +-#define JH7100_RESET_STATUS3 0x1c +- +-/* +- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts +- * line 32m + n, and writing a 0 deasserts the same line. +- * Most reset lines have their status inverted so a 0 bit in the STATUS +- * register means the line is asserted and a 1 means it's deasserted. A few +- * lines don't though, so store the expected value of the status registers when +- * all lines are asserted. +- */ +-static const u64 jh7100_reset_asserted[2] = { +- /* STATUS0 */ +- BIT_ULL_MASK(JH7100_RST_U74) | +- BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | +- BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | +- /* STATUS1 */ +- BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | +- BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), +- /* STATUS2 */ +- BIT_ULL_MASK(JH7100_RST_E24) | +- /* STATUS3 */ +- 0, +-}; +- +-struct jh7100_reset { +- struct reset_controller_dev rcdev; +- /* protect registers against concurrent read-modify-write */ +- spinlock_t lock; +- void __iomem *base; +-}; +- +-static inline struct jh7100_reset * +-jh7100_reset_from(struct reset_controller_dev *rcdev) +-{ +- return container_of(rcdev, struct jh7100_reset, rcdev); +-} +- +-static int jh7100_reset_update(struct reset_controller_dev *rcdev, +- unsigned long id, bool assert) +-{ +- struct jh7100_reset *data = jh7100_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); +- u64 done = jh7100_reset_asserted[offset] & mask; +- u64 value; +- unsigned long flags; +- int ret; +- +- if (!assert) +- done ^= mask; +- +- spin_lock_irqsave(&data->lock, flags); +- +- value = readq(reg_assert); +- if (assert) +- value |= mask; +- else +- value &= ~mask; +- writeq(value, reg_assert); +- +- /* if the associated clock is gated, deasserting might otherwise hang forever */ +- ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); +- +- spin_unlock_irqrestore(&data->lock, flags); +- return ret; +-} +- +-static int jh7100_reset_assert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return jh7100_reset_update(rcdev, id, true); +-} +- +-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return jh7100_reset_update(rcdev, id, false); +-} +- +-static int jh7100_reset_reset(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- int ret; +- +- ret = jh7100_reset_assert(rcdev, id); +- if (ret) +- return ret; +- +- return jh7100_reset_deassert(rcdev, id); +-} +- +-static int jh7100_reset_status(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- struct jh7100_reset *data = jh7100_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); +- u64 value = readq(reg_status); +- +- return !((value ^ jh7100_reset_asserted[offset]) & mask); +-} +- +-static const struct reset_control_ops jh7100_reset_ops = { +- .assert = jh7100_reset_assert, +- .deassert = jh7100_reset_deassert, +- .reset = jh7100_reset_reset, +- .status = jh7100_reset_status, +-}; +- +-static int __init jh7100_reset_probe(struct platform_device *pdev) +-{ +- struct jh7100_reset *data; +- +- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- +- data->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(data->base)) +- return PTR_ERR(data->base); +- +- data->rcdev.ops = &jh7100_reset_ops; +- data->rcdev.owner = THIS_MODULE; +- data->rcdev.nr_resets = JH7100_RSTN_END; +- data->rcdev.dev = &pdev->dev; +- data->rcdev.of_node = pdev->dev.of_node; +- spin_lock_init(&data->lock); +- +- return devm_reset_controller_register(&pdev->dev, &data->rcdev); +-} +- +-static const struct of_device_id jh7100_reset_dt_ids[] = { +- { .compatible = "starfive,jh7100-reset" }, +- { /* sentinel */ } +-}; +- +-static struct platform_driver jh7100_reset_driver = { +- .driver = { +- .name = "jh7100-reset", +- .of_match_table = jh7100_reset_dt_ids, +- .suppress_bind_attrs = true, +- }, +-}; +-builtin_platform_driver_probe(jh7100_reset_driver, jh7100_reset_probe); +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh7100.c +@@ -0,0 +1,173 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Reset driver for the StarFive JH7100 SoC ++ * ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* register offsets */ ++#define JH7100_RESET_ASSERT0 0x00 ++#define JH7100_RESET_ASSERT1 0x04 ++#define JH7100_RESET_ASSERT2 0x08 ++#define JH7100_RESET_ASSERT3 0x0c ++#define JH7100_RESET_STATUS0 0x10 ++#define JH7100_RESET_STATUS1 0x14 ++#define JH7100_RESET_STATUS2 0x18 ++#define JH7100_RESET_STATUS3 0x1c ++ ++/* ++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts ++ * line 32m + n, and writing a 0 deasserts the same line. ++ * Most reset lines have their status inverted so a 0 bit in the STATUS ++ * register means the line is asserted and a 1 means it's deasserted. A few ++ * lines don't though, so store the expected value of the status registers when ++ * all lines are asserted. ++ */ ++static const u64 jh7100_reset_asserted[2] = { ++ /* STATUS0 */ ++ BIT_ULL_MASK(JH7100_RST_U74) | ++ BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | ++ /* STATUS1 */ ++ BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), ++ /* STATUS2 */ ++ BIT_ULL_MASK(JH7100_RST_E24) | ++ /* STATUS3 */ ++ 0, ++}; ++ ++struct jh7100_reset { ++ struct reset_controller_dev rcdev; ++ /* protect registers against concurrent read-modify-write */ ++ spinlock_t lock; ++ void __iomem *base; ++}; ++ ++static inline struct jh7100_reset * ++jh7100_reset_from(struct reset_controller_dev *rcdev) ++{ ++ return container_of(rcdev, struct jh7100_reset, rcdev); ++} ++ ++static int jh7100_reset_update(struct reset_controller_dev *rcdev, ++ unsigned long id, bool assert) ++{ ++ struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ unsigned long offset = BIT_ULL_WORD(id); ++ u64 mask = BIT_ULL_MASK(id); ++ void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64); ++ void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); ++ u64 done = jh7100_reset_asserted[offset] & mask; ++ u64 value; ++ unsigned long flags; ++ int ret; ++ ++ if (!assert) ++ done ^= mask; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ value = readq(reg_assert); ++ if (assert) ++ value |= mask; ++ else ++ value &= ~mask; ++ writeq(value, reg_assert); ++ ++ /* if the associated clock is gated, deasserting might otherwise hang forever */ ++ ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ return ret; ++} ++ ++static int jh7100_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return jh7100_reset_update(rcdev, id, true); ++} ++ ++static int jh7100_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return jh7100_reset_update(rcdev, id, false); ++} ++ ++static int jh7100_reset_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ int ret; ++ ++ ret = jh7100_reset_assert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ return jh7100_reset_deassert(rcdev, id); ++} ++ ++static int jh7100_reset_status(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ unsigned long offset = BIT_ULL_WORD(id); ++ u64 mask = BIT_ULL_MASK(id); ++ void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); ++ u64 value = readq(reg_status); ++ ++ return !((value ^ jh7100_reset_asserted[offset]) & mask); ++} ++ ++static const struct reset_control_ops jh7100_reset_ops = { ++ .assert = jh7100_reset_assert, ++ .deassert = jh7100_reset_deassert, ++ .reset = jh7100_reset_reset, ++ .status = jh7100_reset_status, ++}; ++ ++static int __init jh7100_reset_probe(struct platform_device *pdev) ++{ ++ struct jh7100_reset *data; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(data->base)) ++ return PTR_ERR(data->base); ++ ++ data->rcdev.ops = &jh7100_reset_ops; ++ data->rcdev.owner = THIS_MODULE; ++ data->rcdev.nr_resets = JH7100_RSTN_END; ++ data->rcdev.dev = &pdev->dev; ++ data->rcdev.of_node = pdev->dev.of_node; ++ spin_lock_init(&data->lock); ++ ++ return devm_reset_controller_register(&pdev->dev, &data->rcdev); ++} ++ ++static const struct of_device_id jh7100_reset_dt_ids[] = { ++ { .compatible = "starfive,jh7100-reset" }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver jh7100_reset_driver = { ++ .driver = { ++ .name = "jh7100-reset", ++ .of_match_table = jh7100_reset_dt_ids, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver_probe(jh7100_reset_driver, jh7100_reset_probe); diff --git a/target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch b/target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch new file mode 100644 index 0000000000..cd192f80af --- /dev/null +++ b/target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch @@ -0,0 +1,390 @@ +From a8051a7daa45056f469686286886968bc62b94df Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:21 +0800 +Subject: [PATCH 009/122] reset: starfive: Factor out common JH71X0 reset code + +The StarFive JH7100 SoC has additional reset controllers for audio and +video, but the registers follow the same structure. On the JH7110 the +reset registers don't get their own memory range, but instead follow the +clock control registers. The registers still follow the same structure +though, so let's factor out the common code to handle all these cases. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/reset/starfive/Kconfig | 4 + + drivers/reset/starfive/Makefile | 2 + + .../reset/starfive/reset-starfive-jh7100.c | 150 +--------------- + .../reset/starfive/reset-starfive-jh71x0.c | 162 ++++++++++++++++++ + .../reset/starfive/reset-starfive-jh71x0.h | 11 ++ + 5 files changed, 180 insertions(+), 149 deletions(-) + create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.c + create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.h + +--- a/drivers/reset/starfive/Kconfig ++++ b/drivers/reset/starfive/Kconfig +@@ -1,8 +1,12 @@ + # SPDX-License-Identifier: GPL-2.0-only + ++config RESET_STARFIVE_JH71X0 ++ bool ++ + config RESET_STARFIVE_JH7100 + bool "StarFive JH7100 Reset Driver" + depends on ARCH_STARFIVE || COMPILE_TEST ++ select RESET_STARFIVE_JH71X0 + default ARCH_STARFIVE + help + This enables the reset controller driver for the StarFive JH7100 SoC. +--- a/drivers/reset/starfive/Makefile ++++ b/drivers/reset/starfive/Makefile +@@ -1,2 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_RESET_STARFIVE_JH71X0) += reset-starfive-jh71x0.o ++ + obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o +--- a/drivers/reset/starfive/reset-starfive-jh7100.c ++++ b/drivers/reset/starfive/reset-starfive-jh7100.c +@@ -5,158 +5,10 @@ + * Copyright (C) 2021 Emil Renner Berthing + */ + +-#include +-#include +-#include +-#include + #include + #include +-#include +-#include + +-#include +- +-/* register offsets */ +-#define JH7100_RESET_ASSERT0 0x00 +-#define JH7100_RESET_ASSERT1 0x04 +-#define JH7100_RESET_ASSERT2 0x08 +-#define JH7100_RESET_ASSERT3 0x0c +-#define JH7100_RESET_STATUS0 0x10 +-#define JH7100_RESET_STATUS1 0x14 +-#define JH7100_RESET_STATUS2 0x18 +-#define JH7100_RESET_STATUS3 0x1c +- +-/* +- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts +- * line 32m + n, and writing a 0 deasserts the same line. +- * Most reset lines have their status inverted so a 0 bit in the STATUS +- * register means the line is asserted and a 1 means it's deasserted. A few +- * lines don't though, so store the expected value of the status registers when +- * all lines are asserted. +- */ +-static const u64 jh7100_reset_asserted[2] = { +- /* STATUS0 */ +- BIT_ULL_MASK(JH7100_RST_U74) | +- BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | +- BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | +- /* STATUS1 */ +- BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | +- BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), +- /* STATUS2 */ +- BIT_ULL_MASK(JH7100_RST_E24) | +- /* STATUS3 */ +- 0, +-}; +- +-struct jh7100_reset { +- struct reset_controller_dev rcdev; +- /* protect registers against concurrent read-modify-write */ +- spinlock_t lock; +- void __iomem *base; +-}; +- +-static inline struct jh7100_reset * +-jh7100_reset_from(struct reset_controller_dev *rcdev) +-{ +- return container_of(rcdev, struct jh7100_reset, rcdev); +-} +- +-static int jh7100_reset_update(struct reset_controller_dev *rcdev, +- unsigned long id, bool assert) +-{ +- struct jh7100_reset *data = jh7100_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); +- u64 done = jh7100_reset_asserted[offset] & mask; +- u64 value; +- unsigned long flags; +- int ret; +- +- if (!assert) +- done ^= mask; +- +- spin_lock_irqsave(&data->lock, flags); +- +- value = readq(reg_assert); +- if (assert) +- value |= mask; +- else +- value &= ~mask; +- writeq(value, reg_assert); +- +- /* if the associated clock is gated, deasserting might otherwise hang forever */ +- ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); +- +- spin_unlock_irqrestore(&data->lock, flags); +- return ret; +-} +- +-static int jh7100_reset_assert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return jh7100_reset_update(rcdev, id, true); +-} +- +-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- return jh7100_reset_update(rcdev, id, false); +-} +- +-static int jh7100_reset_reset(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- int ret; +- +- ret = jh7100_reset_assert(rcdev, id); +- if (ret) +- return ret; +- +- return jh7100_reset_deassert(rcdev, id); +-} +- +-static int jh7100_reset_status(struct reset_controller_dev *rcdev, +- unsigned long id) +-{ +- struct jh7100_reset *data = jh7100_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); +- u64 value = readq(reg_status); +- +- return !((value ^ jh7100_reset_asserted[offset]) & mask); +-} +- +-static const struct reset_control_ops jh7100_reset_ops = { +- .assert = jh7100_reset_assert, +- .deassert = jh7100_reset_deassert, +- .reset = jh7100_reset_reset, +- .status = jh7100_reset_status, +-}; +- +-static int __init jh7100_reset_probe(struct platform_device *pdev) +-{ +- struct jh7100_reset *data; +- +- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- +- data->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(data->base)) +- return PTR_ERR(data->base); +- +- data->rcdev.ops = &jh7100_reset_ops; +- data->rcdev.owner = THIS_MODULE; +- data->rcdev.nr_resets = JH7100_RSTN_END; +- data->rcdev.dev = &pdev->dev; +- data->rcdev.of_node = pdev->dev.of_node; +- spin_lock_init(&data->lock); +- +- return devm_reset_controller_register(&pdev->dev, &data->rcdev); +-} ++#include "reset-starfive-jh71x0.h" + + static const struct of_device_id jh7100_reset_dt_ids[] = { + { .compatible = "starfive,jh7100-reset" }, +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c +@@ -0,0 +1,162 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Reset driver for the StarFive JH7100 SoC ++ * ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "reset-starfive-jh71x0.h" ++ ++#include ++ ++/* register offsets */ ++#define JH7100_RESET_ASSERT0 0x00 ++#define JH7100_RESET_ASSERT1 0x04 ++#define JH7100_RESET_ASSERT2 0x08 ++#define JH7100_RESET_ASSERT3 0x0c ++#define JH7100_RESET_STATUS0 0x10 ++#define JH7100_RESET_STATUS1 0x14 ++#define JH7100_RESET_STATUS2 0x18 ++#define JH7100_RESET_STATUS3 0x1c ++ ++/* ++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts ++ * line 32m + n, and writing a 0 deasserts the same line. ++ * Most reset lines have their status inverted so a 0 bit in the STATUS ++ * register means the line is asserted and a 1 means it's deasserted. A few ++ * lines don't though, so store the expected value of the status registers when ++ * all lines are asserted. ++ */ ++static const u64 jh7100_reset_asserted[2] = { ++ /* STATUS0 */ ++ BIT_ULL_MASK(JH7100_RST_U74) | ++ BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | ++ /* STATUS1 */ ++ BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), ++ /* STATUS2 */ ++ BIT_ULL_MASK(JH7100_RST_E24) | ++ /* STATUS3 */ ++ 0, ++}; ++ ++struct jh7100_reset { ++ struct reset_controller_dev rcdev; ++ /* protect registers against concurrent read-modify-write */ ++ spinlock_t lock; ++ void __iomem *base; ++}; ++ ++static inline struct jh7100_reset * ++jh7100_reset_from(struct reset_controller_dev *rcdev) ++{ ++ return container_of(rcdev, struct jh7100_reset, rcdev); ++} ++ ++static int jh7100_reset_update(struct reset_controller_dev *rcdev, ++ unsigned long id, bool assert) ++{ ++ struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ unsigned long offset = BIT_ULL_WORD(id); ++ u64 mask = BIT_ULL_MASK(id); ++ void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64); ++ void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); ++ u64 done = jh7100_reset_asserted[offset] & mask; ++ u64 value; ++ unsigned long flags; ++ int ret; ++ ++ if (!assert) ++ done ^= mask; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ value = readq(reg_assert); ++ if (assert) ++ value |= mask; ++ else ++ value &= ~mask; ++ writeq(value, reg_assert); ++ ++ /* if the associated clock is gated, deasserting might otherwise hang forever */ ++ ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ return ret; ++} ++ ++static int jh7100_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return jh7100_reset_update(rcdev, id, true); ++} ++ ++static int jh7100_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return jh7100_reset_update(rcdev, id, false); ++} ++ ++static int jh7100_reset_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ int ret; ++ ++ ret = jh7100_reset_assert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ return jh7100_reset_deassert(rcdev, id); ++} ++ ++static int jh7100_reset_status(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ unsigned long offset = BIT_ULL_WORD(id); ++ u64 mask = BIT_ULL_MASK(id); ++ void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); ++ u64 value = readq(reg_status); ++ ++ return !((value ^ jh7100_reset_asserted[offset]) & mask); ++} ++ ++static const struct reset_control_ops jh7100_reset_ops = { ++ .assert = jh7100_reset_assert, ++ .deassert = jh7100_reset_deassert, ++ .reset = jh7100_reset_reset, ++ .status = jh7100_reset_status, ++}; ++ ++int jh7100_reset_probe(struct platform_device *pdev) ++{ ++ struct jh7100_reset *data; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(data->base)) ++ return PTR_ERR(data->base); ++ ++ data->rcdev.ops = &jh7100_reset_ops; ++ data->rcdev.owner = THIS_MODULE; ++ data->rcdev.nr_resets = JH7100_RSTN_END; ++ data->rcdev.dev = &pdev->dev; ++ data->rcdev.of_node = pdev->dev.of_node; ++ spin_lock_init(&data->lock); ++ ++ return devm_reset_controller_register(&pdev->dev, &data->rcdev); ++} ++EXPORT_SYMBOL_GPL(jh7100_reset_probe); +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#ifndef __RESET_STARFIVE_JH71X0_H ++#define __RESET_STARFIVE_JH71X0_H ++ ++int jh7100_reset_probe(struct platform_device *pdev); ++ ++#endif /* __RESET_STARFIVE_JH71X0_H */ diff --git a/target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch b/target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch new file mode 100644 index 0000000000..0a932f57b2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch @@ -0,0 +1,215 @@ +From dbee38aac9811a25e3e3204f813048bf64155248 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:22 +0800 +Subject: [PATCH 010/122] reset: starfive: Extract the common JH71X0 reset code + +Extract the common JH71X0 reset code for reusing them to +support JH7110 SoC. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../reset/starfive/reset-starfive-jh7100.c | 49 ++++++++++++ + .../reset/starfive/reset-starfive-jh71x0.c | 76 ++++++------------- + .../reset/starfive/reset-starfive-jh71x0.h | 5 +- + 3 files changed, 76 insertions(+), 54 deletions(-) + +--- a/drivers/reset/starfive/reset-starfive-jh7100.c ++++ b/drivers/reset/starfive/reset-starfive-jh7100.c +@@ -10,6 +10,55 @@ + + #include "reset-starfive-jh71x0.h" + ++#include ++ ++/* register offsets */ ++#define JH7100_RESET_ASSERT0 0x00 ++#define JH7100_RESET_ASSERT1 0x04 ++#define JH7100_RESET_ASSERT2 0x08 ++#define JH7100_RESET_ASSERT3 0x0c ++#define JH7100_RESET_STATUS0 0x10 ++#define JH7100_RESET_STATUS1 0x14 ++#define JH7100_RESET_STATUS2 0x18 ++#define JH7100_RESET_STATUS3 0x1c ++ ++/* ++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts ++ * line 32m + n, and writing a 0 deasserts the same line. ++ * Most reset lines have their status inverted so a 0 bit in the STATUS ++ * register means the line is asserted and a 1 means it's deasserted. A few ++ * lines don't though, so store the expected value of the status registers when ++ * all lines are asserted. ++ */ ++static const u64 jh7100_reset_asserted[2] = { ++ /* STATUS0 */ ++ BIT_ULL_MASK(JH7100_RST_U74) | ++ BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | ++ /* STATUS1 */ ++ BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | ++ BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), ++ /* STATUS2 */ ++ BIT_ULL_MASK(JH7100_RST_E24) | ++ /* STATUS3 */ ++ 0, ++}; ++ ++static int __init jh7100_reset_probe(struct platform_device *pdev) ++{ ++ void __iomem *base = devm_platform_ioremap_resource(pdev, 0); ++ ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ return reset_starfive_jh7100_register(&pdev->dev, pdev->dev.of_node, ++ base + JH7100_RESET_ASSERT0, ++ base + JH7100_RESET_STATUS0, ++ jh7100_reset_asserted, ++ JH7100_RSTN_END, ++ THIS_MODULE); ++} ++ + static const struct of_device_id jh7100_reset_dt_ids[] = { + { .compatible = "starfive,jh7100-reset" }, + { /* sentinel */ } +--- a/drivers/reset/starfive/reset-starfive-jh71x0.c ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c +@@ -10,51 +10,18 @@ + #include + #include + #include +-#include + #include + #include + + #include "reset-starfive-jh71x0.h" + +-#include +- +-/* register offsets */ +-#define JH7100_RESET_ASSERT0 0x00 +-#define JH7100_RESET_ASSERT1 0x04 +-#define JH7100_RESET_ASSERT2 0x08 +-#define JH7100_RESET_ASSERT3 0x0c +-#define JH7100_RESET_STATUS0 0x10 +-#define JH7100_RESET_STATUS1 0x14 +-#define JH7100_RESET_STATUS2 0x18 +-#define JH7100_RESET_STATUS3 0x1c +- +-/* +- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts +- * line 32m + n, and writing a 0 deasserts the same line. +- * Most reset lines have their status inverted so a 0 bit in the STATUS +- * register means the line is asserted and a 1 means it's deasserted. A few +- * lines don't though, so store the expected value of the status registers when +- * all lines are asserted. +- */ +-static const u64 jh7100_reset_asserted[2] = { +- /* STATUS0 */ +- BIT_ULL_MASK(JH7100_RST_U74) | +- BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | +- BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | +- /* STATUS1 */ +- BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | +- BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), +- /* STATUS2 */ +- BIT_ULL_MASK(JH7100_RST_E24) | +- /* STATUS3 */ +- 0, +-}; +- + struct jh7100_reset { + struct reset_controller_dev rcdev; + /* protect registers against concurrent read-modify-write */ + spinlock_t lock; +- void __iomem *base; ++ void __iomem *assert; ++ void __iomem *status; ++ const u64 *asserted; + }; + + static inline struct jh7100_reset * +@@ -69,9 +36,9 @@ static int jh7100_reset_update(struct re + struct jh7100_reset *data = jh7100_reset_from(rcdev); + unsigned long offset = BIT_ULL_WORD(id); + u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); +- u64 done = jh7100_reset_asserted[offset] & mask; ++ void __iomem *reg_assert = data->assert + offset * sizeof(u64); ++ void __iomem *reg_status = data->status + offset * sizeof(u64); ++ u64 done = data->asserted ? data->asserted[offset] & mask : 0; + u64 value; + unsigned long flags; + int ret; +@@ -125,10 +92,10 @@ static int jh7100_reset_status(struct re + struct jh7100_reset *data = jh7100_reset_from(rcdev); + unsigned long offset = BIT_ULL_WORD(id); + u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64); ++ void __iomem *reg_status = data->status + offset * sizeof(u64); + u64 value = readq(reg_status); + +- return !((value ^ jh7100_reset_asserted[offset]) & mask); ++ return !((value ^ data->asserted[offset]) & mask); + } + + static const struct reset_control_ops jh7100_reset_ops = { +@@ -138,25 +105,28 @@ static const struct reset_control_ops jh + .status = jh7100_reset_status, + }; + +-int jh7100_reset_probe(struct platform_device *pdev) ++int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node, ++ void __iomem *assert, void __iomem *status, ++ const u64 *asserted, unsigned int nr_resets, ++ struct module *owner) + { + struct jh7100_reset *data; + +- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + +- data->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(data->base)) +- return PTR_ERR(data->base); +- + data->rcdev.ops = &jh7100_reset_ops; +- data->rcdev.owner = THIS_MODULE; +- data->rcdev.nr_resets = JH7100_RSTN_END; +- data->rcdev.dev = &pdev->dev; +- data->rcdev.of_node = pdev->dev.of_node; ++ data->rcdev.owner = owner; ++ data->rcdev.nr_resets = nr_resets; ++ data->rcdev.dev = dev; ++ data->rcdev.of_node = of_node; ++ + spin_lock_init(&data->lock); ++ data->assert = assert; ++ data->status = status; ++ data->asserted = asserted; + +- return devm_reset_controller_register(&pdev->dev, &data->rcdev); ++ return devm_reset_controller_register(dev, &data->rcdev); + } +-EXPORT_SYMBOL_GPL(jh7100_reset_probe); ++EXPORT_SYMBOL_GPL(reset_starfive_jh7100_register); +--- a/drivers/reset/starfive/reset-starfive-jh71x0.h ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h +@@ -6,6 +6,9 @@ + #ifndef __RESET_STARFIVE_JH71X0_H + #define __RESET_STARFIVE_JH71X0_H + +-int jh7100_reset_probe(struct platform_device *pdev); ++int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node, ++ void __iomem *assert, void __iomem *status, ++ const u64 *asserted, unsigned int nr_resets, ++ struct module *owner); + + #endif /* __RESET_STARFIVE_JH71X0_H */ diff --git a/target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch b/target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch new file mode 100644 index 0000000000..144d847725 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch @@ -0,0 +1,167 @@ +From 798b9b4681be53ddbf1d8db8a88ff19aaaca500f Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:23 +0800 +Subject: [PATCH 011/122] reset: starfive: Rename "jh7100" to "jh71x0" for the + common code + +For the common code will be shared with the StarFive JH7110 SoC. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../reset/starfive/reset-starfive-jh7100.c | 2 +- + .../reset/starfive/reset-starfive-jh71x0.c | 50 +++++++++---------- + .../reset/starfive/reset-starfive-jh71x0.h | 2 +- + 3 files changed, 27 insertions(+), 27 deletions(-) + +--- a/drivers/reset/starfive/reset-starfive-jh7100.c ++++ b/drivers/reset/starfive/reset-starfive-jh7100.c +@@ -51,7 +51,7 @@ static int __init jh7100_reset_probe(str + if (IS_ERR(base)) + return PTR_ERR(base); + +- return reset_starfive_jh7100_register(&pdev->dev, pdev->dev.of_node, ++ return reset_starfive_jh71x0_register(&pdev->dev, pdev->dev.of_node, + base + JH7100_RESET_ASSERT0, + base + JH7100_RESET_STATUS0, + jh7100_reset_asserted, +--- a/drivers/reset/starfive/reset-starfive-jh71x0.c ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + /* +- * Reset driver for the StarFive JH7100 SoC ++ * Reset driver for the StarFive JH71X0 SoCs + * + * Copyright (C) 2021 Emil Renner Berthing + */ +@@ -15,7 +15,7 @@ + + #include "reset-starfive-jh71x0.h" + +-struct jh7100_reset { ++struct jh71x0_reset { + struct reset_controller_dev rcdev; + /* protect registers against concurrent read-modify-write */ + spinlock_t lock; +@@ -24,16 +24,16 @@ struct jh7100_reset { + const u64 *asserted; + }; + +-static inline struct jh7100_reset * +-jh7100_reset_from(struct reset_controller_dev *rcdev) ++static inline struct jh71x0_reset * ++jh71x0_reset_from(struct reset_controller_dev *rcdev) + { +- return container_of(rcdev, struct jh7100_reset, rcdev); ++ return container_of(rcdev, struct jh71x0_reset, rcdev); + } + +-static int jh7100_reset_update(struct reset_controller_dev *rcdev, ++static int jh71x0_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +- struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ struct jh71x0_reset *data = jh71x0_reset_from(rcdev); + unsigned long offset = BIT_ULL_WORD(id); + u64 mask = BIT_ULL_MASK(id); + void __iomem *reg_assert = data->assert + offset * sizeof(u64); +@@ -62,34 +62,34 @@ static int jh7100_reset_update(struct re + return ret; + } + +-static int jh7100_reset_assert(struct reset_controller_dev *rcdev, ++static int jh71x0_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) + { +- return jh7100_reset_update(rcdev, id, true); ++ return jh71x0_reset_update(rcdev, id, true); + } + +-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev, ++static int jh71x0_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) + { +- return jh7100_reset_update(rcdev, id, false); ++ return jh71x0_reset_update(rcdev, id, false); + } + +-static int jh7100_reset_reset(struct reset_controller_dev *rcdev, ++static int jh71x0_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) + { + int ret; + +- ret = jh7100_reset_assert(rcdev, id); ++ ret = jh71x0_reset_assert(rcdev, id); + if (ret) + return ret; + +- return jh7100_reset_deassert(rcdev, id); ++ return jh71x0_reset_deassert(rcdev, id); + } + +-static int jh7100_reset_status(struct reset_controller_dev *rcdev, ++static int jh71x0_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) + { +- struct jh7100_reset *data = jh7100_reset_from(rcdev); ++ struct jh71x0_reset *data = jh71x0_reset_from(rcdev); + unsigned long offset = BIT_ULL_WORD(id); + u64 mask = BIT_ULL_MASK(id); + void __iomem *reg_status = data->status + offset * sizeof(u64); +@@ -98,25 +98,25 @@ static int jh7100_reset_status(struct re + return !((value ^ data->asserted[offset]) & mask); + } + +-static const struct reset_control_ops jh7100_reset_ops = { +- .assert = jh7100_reset_assert, +- .deassert = jh7100_reset_deassert, +- .reset = jh7100_reset_reset, +- .status = jh7100_reset_status, ++static const struct reset_control_ops jh71x0_reset_ops = { ++ .assert = jh71x0_reset_assert, ++ .deassert = jh71x0_reset_deassert, ++ .reset = jh71x0_reset_reset, ++ .status = jh71x0_reset_status, + }; + +-int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node, ++int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node, + void __iomem *assert, void __iomem *status, + const u64 *asserted, unsigned int nr_resets, + struct module *owner) + { +- struct jh7100_reset *data; ++ struct jh71x0_reset *data; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + +- data->rcdev.ops = &jh7100_reset_ops; ++ data->rcdev.ops = &jh71x0_reset_ops; + data->rcdev.owner = owner; + data->rcdev.nr_resets = nr_resets; + data->rcdev.dev = dev; +@@ -129,4 +129,4 @@ int reset_starfive_jh7100_register(struc + + return devm_reset_controller_register(dev, &data->rcdev); + } +-EXPORT_SYMBOL_GPL(reset_starfive_jh7100_register); ++EXPORT_SYMBOL_GPL(reset_starfive_jh71x0_register); +--- a/drivers/reset/starfive/reset-starfive-jh71x0.h ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h +@@ -6,7 +6,7 @@ + #ifndef __RESET_STARFIVE_JH71X0_H + #define __RESET_STARFIVE_JH71X0_H + +-int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node, ++int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node, + void __iomem *assert, void __iomem *status, + const u64 *asserted, unsigned int nr_resets, + struct module *owner); diff --git a/target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch b/target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch new file mode 100644 index 0000000000..459ac5a3b6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch @@ -0,0 +1,146 @@ +From 365bb978e5e11a16c362d9c2c64d7bf8d04999df Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:24 +0800 +Subject: [PATCH 012/122] reset: starfive: jh71x0: Use 32bit I/O on 32bit + registers + +We currently use 64bit I/O on the 32bit registers. This works because +there are an even number of assert and status registers, so they're only +ever accessed in pairs on 64bit boundaries. + +There are however other reset controllers for audio and video on the +JH7100 SoC with only one status register that isn't 64bit aligned so +64bit I/O results in an unaligned access exception. + +Switch to 32bit I/O in preparation for supporting these resets too. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../reset/starfive/reset-starfive-jh7100.c | 14 ++++----- + .../reset/starfive/reset-starfive-jh71x0.c | 31 +++++++++---------- + .../reset/starfive/reset-starfive-jh71x0.h | 2 +- + 3 files changed, 23 insertions(+), 24 deletions(-) + +--- a/drivers/reset/starfive/reset-starfive-jh7100.c ++++ b/drivers/reset/starfive/reset-starfive-jh7100.c +@@ -30,16 +30,16 @@ + * lines don't though, so store the expected value of the status registers when + * all lines are asserted. + */ +-static const u64 jh7100_reset_asserted[2] = { ++static const u32 jh7100_reset_asserted[4] = { + /* STATUS0 */ +- BIT_ULL_MASK(JH7100_RST_U74) | +- BIT_ULL_MASK(JH7100_RST_VP6_DRESET) | +- BIT_ULL_MASK(JH7100_RST_VP6_BRESET) | ++ BIT(JH7100_RST_U74 % 32) | ++ BIT(JH7100_RST_VP6_DRESET % 32) | ++ BIT(JH7100_RST_VP6_BRESET % 32), + /* STATUS1 */ +- BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) | +- BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET), ++ BIT(JH7100_RST_HIFI4_DRESET % 32) | ++ BIT(JH7100_RST_HIFI4_BRESET % 32), + /* STATUS2 */ +- BIT_ULL_MASK(JH7100_RST_E24) | ++ BIT(JH7100_RST_E24 % 32), + /* STATUS3 */ + 0, + }; +--- a/drivers/reset/starfive/reset-starfive-jh71x0.c ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c +@@ -8,7 +8,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -21,7 +20,7 @@ struct jh71x0_reset { + spinlock_t lock; + void __iomem *assert; + void __iomem *status; +- const u64 *asserted; ++ const u32 *asserted; + }; + + static inline struct jh71x0_reset * +@@ -34,12 +33,12 @@ static int jh71x0_reset_update(struct re + unsigned long id, bool assert) + { + struct jh71x0_reset *data = jh71x0_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_assert = data->assert + offset * sizeof(u64); +- void __iomem *reg_status = data->status + offset * sizeof(u64); +- u64 done = data->asserted ? data->asserted[offset] & mask : 0; +- u64 value; ++ unsigned long offset = id / 32; ++ u32 mask = BIT(id % 32); ++ void __iomem *reg_assert = data->assert + offset * sizeof(u32); ++ void __iomem *reg_status = data->status + offset * sizeof(u32); ++ u32 done = data->asserted ? data->asserted[offset] & mask : 0; ++ u32 value; + unsigned long flags; + int ret; + +@@ -48,15 +47,15 @@ static int jh71x0_reset_update(struct re + + spin_lock_irqsave(&data->lock, flags); + +- value = readq(reg_assert); ++ value = readl(reg_assert); + if (assert) + value |= mask; + else + value &= ~mask; +- writeq(value, reg_assert); ++ writel(value, reg_assert); + + /* if the associated clock is gated, deasserting might otherwise hang forever */ +- ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); ++ ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); + + spin_unlock_irqrestore(&data->lock, flags); + return ret; +@@ -90,10 +89,10 @@ static int jh71x0_reset_status(struct re + unsigned long id) + { + struct jh71x0_reset *data = jh71x0_reset_from(rcdev); +- unsigned long offset = BIT_ULL_WORD(id); +- u64 mask = BIT_ULL_MASK(id); +- void __iomem *reg_status = data->status + offset * sizeof(u64); +- u64 value = readq(reg_status); ++ unsigned long offset = id / 32; ++ u32 mask = BIT(id % 32); ++ void __iomem *reg_status = data->status + offset * sizeof(u32); ++ u32 value = readl(reg_status); + + return !((value ^ data->asserted[offset]) & mask); + } +@@ -107,7 +106,7 @@ static const struct reset_control_ops jh + + int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node, + void __iomem *assert, void __iomem *status, +- const u64 *asserted, unsigned int nr_resets, ++ const u32 *asserted, unsigned int nr_resets, + struct module *owner) + { + struct jh71x0_reset *data; +--- a/drivers/reset/starfive/reset-starfive-jh71x0.h ++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h +@@ -8,7 +8,7 @@ + + int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node, + void __iomem *assert, void __iomem *status, +- const u64 *asserted, unsigned int nr_resets, ++ const u32 *asserted, unsigned int nr_resets, + struct module *owner); + + #endif /* __RESET_STARFIVE_JH71X0_H */ diff --git a/target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch b/target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch new file mode 100644 index 0000000000..f272d5179b --- /dev/null +++ b/target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch @@ -0,0 +1,557 @@ +From eea853275c704f6c24a418a50715bc5ad68a6283 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:25 +0800 +Subject: [PATCH 013/122] clk: starfive: Add StarFive JH7110 system clock + driver + +Add driver for the StarFive JH7110 system clock controller and +register an auxiliary device for system reset controller which +is named as "rst-sys". + +Tested-by: Tommaso Merciai +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Co-developed-by: Hal Feng +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/clk/starfive/Kconfig | 11 + + drivers/clk/starfive/Makefile | 2 + + .../clk/starfive/clk-starfive-jh7110-sys.c | 490 ++++++++++++++++++ + drivers/clk/starfive/clk-starfive-jh7110.h | 11 + + 4 files changed, 514 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-sys.c + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110.h + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -20,3 +20,14 @@ config CLK_STARFIVE_JH7100_AUDIO + help + Say Y or M here to support the audio clocks on the StarFive JH7100 + SoC. ++ ++config CLK_STARFIVE_JH7110_SYS ++ bool "StarFive JH7110 system clock support" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ select AUXILIARY_BUS ++ select CLK_STARFIVE_JH71X0 ++ select RESET_STARFIVE_JH7110 ++ default ARCH_STARFIVE ++ help ++ Say yes here to support the system clock controller on the ++ StarFive JH7110 SoC. +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -3,3 +3,5 @@ obj-$(CONFIG_CLK_STARFIVE_JH71X0) += clk + + obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk-starfive-jh7100.o + obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) += clk-starfive-jh7100-audio.o ++ ++obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += clk-starfive-jh7110-sys.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c +@@ -0,0 +1,490 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 System Clock Driver ++ * ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110.h" ++ ++/* external clocks */ ++#define JH7110_SYSCLK_OSC (JH7110_SYSCLK_END + 0) ++#define JH7110_SYSCLK_GMAC1_RMII_REFIN (JH7110_SYSCLK_END + 1) ++#define JH7110_SYSCLK_GMAC1_RGMII_RXIN (JH7110_SYSCLK_END + 2) ++#define JH7110_SYSCLK_I2STX_BCLK_EXT (JH7110_SYSCLK_END + 3) ++#define JH7110_SYSCLK_I2STX_LRCK_EXT (JH7110_SYSCLK_END + 4) ++#define JH7110_SYSCLK_I2SRX_BCLK_EXT (JH7110_SYSCLK_END + 5) ++#define JH7110_SYSCLK_I2SRX_LRCK_EXT (JH7110_SYSCLK_END + 6) ++#define JH7110_SYSCLK_TDM_EXT (JH7110_SYSCLK_END + 7) ++#define JH7110_SYSCLK_MCLK_EXT (JH7110_SYSCLK_END + 8) ++#define JH7110_SYSCLK_PLL0_OUT (JH7110_SYSCLK_END + 9) ++#define JH7110_SYSCLK_PLL1_OUT (JH7110_SYSCLK_END + 10) ++#define JH7110_SYSCLK_PLL2_OUT (JH7110_SYSCLK_END + 11) ++ ++static const struct jh71x0_clk_data jh7110_sysclk_data[] __initconst = { ++ /* root */ ++ JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 2, ++ JH7110_SYSCLK_OSC, ++ JH7110_SYSCLK_PLL0_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_CPU_CORE, "cpu_core", 7, JH7110_SYSCLK_CPU_ROOT), ++ JH71X0__DIV(JH7110_SYSCLK_CPU_BUS, "cpu_bus", 2, JH7110_SYSCLK_CPU_CORE), ++ JH71X0__MUX(JH7110_SYSCLK_GPU_ROOT, "gpu_root", 2, ++ JH7110_SYSCLK_PLL2_OUT, ++ JH7110_SYSCLK_PLL1_OUT), ++ JH71X0_MDIV(JH7110_SYSCLK_PERH_ROOT, "perh_root", 2, 2, ++ JH7110_SYSCLK_PLL0_OUT, ++ JH7110_SYSCLK_PLL2_OUT), ++ JH71X0__MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", 2, ++ JH7110_SYSCLK_OSC, ++ JH7110_SYSCLK_PLL2_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_NOCSTG_BUS, "nocstg_bus", 3, JH7110_SYSCLK_BUS_ROOT), ++ JH71X0__DIV(JH7110_SYSCLK_AXI_CFG0, "axi_cfg0", 3, JH7110_SYSCLK_BUS_ROOT), ++ JH71X0__DIV(JH7110_SYSCLK_STG_AXIAHB, "stg_axiahb", 2, JH7110_SYSCLK_AXI_CFG0), ++ JH71X0_GATE(JH7110_SYSCLK_AHB0, "ahb0", CLK_IS_CRITICAL, JH7110_SYSCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_SYSCLK_AHB1, "ahb1", CLK_IS_CRITICAL, JH7110_SYSCLK_STG_AXIAHB), ++ JH71X0__DIV(JH7110_SYSCLK_APB_BUS, "apb_bus", 8, JH7110_SYSCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_SYSCLK_APB0, "apb0", CLK_IS_CRITICAL, JH7110_SYSCLK_APB_BUS), ++ JH71X0__DIV(JH7110_SYSCLK_PLL0_DIV2, "pll0_div2", 2, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV2, "pll1_div2", 2, JH7110_SYSCLK_PLL1_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_PLL2_DIV2, "pll2_div2", 2, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_AUDIO_ROOT, "audio_root", 8, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_MCLK_INNER, "mclk_inner", 64, JH7110_SYSCLK_AUDIO_ROOT), ++ JH71X0__MUX(JH7110_SYSCLK_MCLK, "mclk", 2, ++ JH7110_SYSCLK_MCLK_INNER, ++ JH7110_SYSCLK_MCLK_EXT), ++ JH71X0_GATE(JH7110_SYSCLK_MCLK_OUT, "mclk_out", 0, JH7110_SYSCLK_MCLK_INNER), ++ JH71X0_MDIV(JH7110_SYSCLK_ISP_2X, "isp_2x", 8, 2, ++ JH7110_SYSCLK_PLL2_OUT, ++ JH7110_SYSCLK_PLL1_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_ISP_AXI, "isp_axi", 4, JH7110_SYSCLK_ISP_2X), ++ JH71X0_GDIV(JH7110_SYSCLK_GCLK0, "gclk0", 0, 62, JH7110_SYSCLK_PLL0_DIV2), ++ JH71X0_GDIV(JH7110_SYSCLK_GCLK1, "gclk1", 0, 62, JH7110_SYSCLK_PLL1_DIV2), ++ JH71X0_GDIV(JH7110_SYSCLK_GCLK2, "gclk2", 0, 62, JH7110_SYSCLK_PLL2_DIV2), ++ /* cores */ ++ JH71X0_GATE(JH7110_SYSCLK_CORE, "core", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_CORE1, "core1", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_CORE2, "core2", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_CORE3, "core3", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_CORE4, "core4", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_DEBUG, "debug", 0, JH7110_SYSCLK_CPU_BUS), ++ JH71X0__DIV(JH7110_SYSCLK_RTC_TOGGLE, "rtc_toggle", 6, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE0, "trace0", 0, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE1, "trace1", 0, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE2, "trace2", 0, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE3, "trace3", 0, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE4, "trace4", 0, JH7110_SYSCLK_CPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_TRACE_COM, "trace_com", 0, JH7110_SYSCLK_CPU_BUS), ++ /* noc */ ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_CPU_AXI, "noc_bus_cpu_axi", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_CPU_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_AXICFG0_AXI, "noc_bus_axicfg0_axi", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_AXI_CFG0), ++ /* ddr */ ++ JH71X0__DIV(JH7110_SYSCLK_OSC_DIV2, "osc_div2", 2, JH7110_SYSCLK_OSC), ++ JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV4, "pll1_div4", 2, JH7110_SYSCLK_PLL1_DIV2), ++ JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV8, "pll1_div8", 2, JH7110_SYSCLK_PLL1_DIV4), ++ JH71X0__MUX(JH7110_SYSCLK_DDR_BUS, "ddr_bus", 4, ++ JH7110_SYSCLK_OSC_DIV2, ++ JH7110_SYSCLK_PLL1_DIV2, ++ JH7110_SYSCLK_PLL1_DIV4, ++ JH7110_SYSCLK_PLL1_DIV8), ++ JH71X0_GATE(JH7110_SYSCLK_DDR_AXI, "ddr_axi", CLK_IS_CRITICAL, JH7110_SYSCLK_DDR_BUS), ++ /* gpu */ ++ JH71X0__DIV(JH7110_SYSCLK_GPU_CORE, "gpu_core", 7, JH7110_SYSCLK_GPU_ROOT), ++ JH71X0_GATE(JH7110_SYSCLK_GPU_CORE_CLK, "gpu_core_clk", 0, JH7110_SYSCLK_GPU_CORE), ++ JH71X0_GATE(JH7110_SYSCLK_GPU_SYS_CLK, "gpu_sys_clk", 0, JH7110_SYSCLK_ISP_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_GPU_APB, "gpu_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GDIV(JH7110_SYSCLK_GPU_RTC_TOGGLE, "gpu_rtc_toggle", 0, 12, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_GPU_AXI, "noc_bus_gpu_axi", 0, JH7110_SYSCLK_GPU_CORE), ++ /* isp */ ++ JH71X0_GATE(JH7110_SYSCLK_ISP_TOP_CORE, "isp_top_core", 0, JH7110_SYSCLK_ISP_2X), ++ JH71X0_GATE(JH7110_SYSCLK_ISP_TOP_AXI, "isp_top_axi", 0, JH7110_SYSCLK_ISP_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_ISP_AXI, "noc_bus_isp_axi", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_ISP_AXI), ++ /* hifi4 */ ++ JH71X0__DIV(JH7110_SYSCLK_HIFI4_CORE, "hifi4_core", 15, JH7110_SYSCLK_BUS_ROOT), ++ JH71X0__DIV(JH7110_SYSCLK_HIFI4_AXI, "hifi4_axi", 2, JH7110_SYSCLK_HIFI4_CORE), ++ /* axi_cfg1 */ ++ JH71X0_GATE(JH7110_SYSCLK_AXI_CFG1_MAIN, "axi_cfg1_main", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_ISP_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_AXI_CFG1_AHB, "axi_cfg1_ahb", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_AHB0), ++ /* vout */ ++ JH71X0_GATE(JH7110_SYSCLK_VOUT_SRC, "vout_src", 0, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_VOUT_AXI, "vout_axi", 7, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_DISP_AXI, "noc_bus_disp_axi", 0, JH7110_SYSCLK_VOUT_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_AHB, "vout_top_ahb", 0, JH7110_SYSCLK_AHB1), ++ JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_AXI, "vout_top_axi", 0, JH7110_SYSCLK_VOUT_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK, "vout_top_hdmitx0_mclk", 0, ++ JH7110_SYSCLK_MCLK), ++ JH71X0__DIV(JH7110_SYSCLK_VOUT_TOP_MIPIPHY_REF, "vout_top_mipiphy_ref", 2, ++ JH7110_SYSCLK_OSC), ++ /* jpegc */ ++ JH71X0__DIV(JH7110_SYSCLK_JPEGC_AXI, "jpegc_axi", 16, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_CODAJ12_AXI, "codaj12_axi", 0, JH7110_SYSCLK_JPEGC_AXI), ++ JH71X0_GDIV(JH7110_SYSCLK_CODAJ12_CORE, "codaj12_core", 0, 16, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_CODAJ12_APB, "codaj12_apb", 0, JH7110_SYSCLK_APB_BUS), ++ /* vdec */ ++ JH71X0__DIV(JH7110_SYSCLK_VDEC_AXI, "vdec_axi", 7, JH7110_SYSCLK_BUS_ROOT), ++ JH71X0_GATE(JH7110_SYSCLK_WAVE511_AXI, "wave511_axi", 0, JH7110_SYSCLK_VDEC_AXI), ++ JH71X0_GDIV(JH7110_SYSCLK_WAVE511_BPU, "wave511_bpu", 0, 7, JH7110_SYSCLK_BUS_ROOT), ++ JH71X0_GDIV(JH7110_SYSCLK_WAVE511_VCE, "wave511_vce", 0, 7, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_WAVE511_APB, "wave511_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_VDEC_JPG, "vdec_jpg", 0, JH7110_SYSCLK_JPEGC_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_VDEC_MAIN, "vdec_main", 0, JH7110_SYSCLK_VDEC_AXI), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_VDEC_AXI, "noc_bus_vdec_axi", 0, JH7110_SYSCLK_VDEC_AXI), ++ /* venc */ ++ JH71X0__DIV(JH7110_SYSCLK_VENC_AXI, "venc_axi", 15, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_WAVE420L_AXI, "wave420l_axi", 0, JH7110_SYSCLK_VENC_AXI), ++ JH71X0_GDIV(JH7110_SYSCLK_WAVE420L_BPU, "wave420l_bpu", 0, 15, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GDIV(JH7110_SYSCLK_WAVE420L_VCE, "wave420l_vce", 0, 15, JH7110_SYSCLK_PLL2_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_WAVE420L_APB, "wave420l_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_VENC_AXI, "noc_bus_venc_axi", 0, JH7110_SYSCLK_VENC_AXI), ++ /* axi_cfg0 */ ++ JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_MAIN_DIV, "axi_cfg0_main_div", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_AHB1), ++ JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_MAIN, "axi_cfg0_main", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_AXI_CFG0), ++ JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_HIFI4, "axi_cfg0_hifi4", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_HIFI4_AXI), ++ /* intmem */ ++ JH71X0_GATE(JH7110_SYSCLK_AXIMEM2_AXI, "aximem2_axi", 0, JH7110_SYSCLK_AXI_CFG0), ++ /* qspi */ ++ JH71X0_GATE(JH7110_SYSCLK_QSPI_AHB, "qspi_ahb", 0, JH7110_SYSCLK_AHB1), ++ JH71X0_GATE(JH7110_SYSCLK_QSPI_APB, "qspi_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0__DIV(JH7110_SYSCLK_QSPI_REF_SRC, "qspi_ref_src", 16, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0_GMUX(JH7110_SYSCLK_QSPI_REF, "qspi_ref", 0, 2, ++ JH7110_SYSCLK_OSC, ++ JH7110_SYSCLK_QSPI_REF_SRC), ++ /* sdio */ ++ JH71X0_GATE(JH7110_SYSCLK_SDIO0_AHB, "sdio0_ahb", 0, JH7110_SYSCLK_AHB0), ++ JH71X0_GATE(JH7110_SYSCLK_SDIO1_AHB, "sdio1_ahb", 0, JH7110_SYSCLK_AHB0), ++ JH71X0_GDIV(JH7110_SYSCLK_SDIO0_SDCARD, "sdio0_sdcard", 0, 15, JH7110_SYSCLK_AXI_CFG0), ++ JH71X0_GDIV(JH7110_SYSCLK_SDIO1_SDCARD, "sdio1_sdcard", 0, 15, JH7110_SYSCLK_AXI_CFG0), ++ /* stg */ ++ JH71X0__DIV(JH7110_SYSCLK_USB_125M, "usb_125m", 15, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_STG_AXI, "noc_bus_stg_axi", CLK_IS_CRITICAL, ++ JH7110_SYSCLK_NOCSTG_BUS), ++ /* gmac1 */ ++ JH71X0_GATE(JH7110_SYSCLK_GMAC1_AHB, "gmac1_ahb", 0, JH7110_SYSCLK_AHB0), ++ JH71X0_GATE(JH7110_SYSCLK_GMAC1_AXI, "gmac1_axi", 0, JH7110_SYSCLK_STG_AXIAHB), ++ JH71X0__DIV(JH7110_SYSCLK_GMAC_SRC, "gmac_src", 7, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_GMAC1_GTXCLK, "gmac1_gtxclk", 15, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0__DIV(JH7110_SYSCLK_GMAC1_RMII_RTX, "gmac1_rmii_rtx", 30, ++ JH7110_SYSCLK_GMAC1_RMII_REFIN), ++ JH71X0_GDIV(JH7110_SYSCLK_GMAC1_PTP, "gmac1_ptp", 0, 31, JH7110_SYSCLK_GMAC_SRC), ++ JH71X0__MUX(JH7110_SYSCLK_GMAC1_RX, "gmac1_rx", 2, ++ JH7110_SYSCLK_GMAC1_RGMII_RXIN, ++ JH7110_SYSCLK_GMAC1_RMII_RTX), ++ JH71X0__INV(JH7110_SYSCLK_GMAC1_RX_INV, "gmac1_rx_inv", JH7110_SYSCLK_GMAC1_RX), ++ JH71X0_GMUX(JH7110_SYSCLK_GMAC1_TX, "gmac1_tx", ++ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 2, ++ JH7110_SYSCLK_GMAC1_GTXCLK, ++ JH7110_SYSCLK_GMAC1_RMII_RTX), ++ JH71X0__INV(JH7110_SYSCLK_GMAC1_TX_INV, "gmac1_tx_inv", JH7110_SYSCLK_GMAC1_TX), ++ JH71X0_GATE(JH7110_SYSCLK_GMAC1_GTXC, "gmac1_gtxc", 0, JH7110_SYSCLK_GMAC1_GTXCLK), ++ /* gmac0 */ ++ JH71X0_GDIV(JH7110_SYSCLK_GMAC0_GTXCLK, "gmac0_gtxclk", 0, 15, JH7110_SYSCLK_PLL0_OUT), ++ JH71X0_GDIV(JH7110_SYSCLK_GMAC0_PTP, "gmac0_ptp", 0, 31, JH7110_SYSCLK_GMAC_SRC), ++ JH71X0_GDIV(JH7110_SYSCLK_GMAC_PHY, "gmac_phy", 0, 31, JH7110_SYSCLK_GMAC_SRC), ++ JH71X0_GATE(JH7110_SYSCLK_GMAC0_GTXC, "gmac0_gtxc", 0, JH7110_SYSCLK_GMAC0_GTXCLK), ++ /* apb misc */ ++ JH71X0_GATE(JH7110_SYSCLK_IOMUX_APB, "iomux_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_MAILBOX_APB, "mailbox_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_INT_CTRL_APB, "int_ctrl_apb", 0, JH7110_SYSCLK_APB_BUS), ++ /* can0 */ ++ JH71X0_GATE(JH7110_SYSCLK_CAN0_APB, "can0_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GDIV(JH7110_SYSCLK_CAN0_TIMER, "can0_timer", 0, 24, JH7110_SYSCLK_OSC), ++ JH71X0_GDIV(JH7110_SYSCLK_CAN0_CAN, "can0_can", 0, 63, JH7110_SYSCLK_PERH_ROOT), ++ /* can1 */ ++ JH71X0_GATE(JH7110_SYSCLK_CAN1_APB, "can1_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GDIV(JH7110_SYSCLK_CAN1_TIMER, "can1_timer", 0, 24, JH7110_SYSCLK_OSC), ++ JH71X0_GDIV(JH7110_SYSCLK_CAN1_CAN, "can1_can", 0, 63, JH7110_SYSCLK_PERH_ROOT), ++ /* pwm */ ++ JH71X0_GATE(JH7110_SYSCLK_PWM_APB, "pwm_apb", 0, JH7110_SYSCLK_APB_BUS), ++ /* wdt */ ++ JH71X0_GATE(JH7110_SYSCLK_WDT_APB, "wdt_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_WDT_CORE, "wdt_core", 0, JH7110_SYSCLK_OSC), ++ /* timer */ ++ JH71X0_GATE(JH7110_SYSCLK_TIMER_APB, "timer_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_TIMER0, "timer0", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_TIMER1, "timer1", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_TIMER2, "timer2", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_TIMER3, "timer3", 0, JH7110_SYSCLK_OSC), ++ /* temp sensor */ ++ JH71X0_GATE(JH7110_SYSCLK_TEMP_APB, "temp_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GDIV(JH7110_SYSCLK_TEMP_CORE, "temp_core", 0, 24, JH7110_SYSCLK_OSC), ++ /* spi */ ++ JH71X0_GATE(JH7110_SYSCLK_SPI0_APB, "spi0_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_SPI1_APB, "spi1_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_SPI2_APB, "spi2_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_SPI3_APB, "spi3_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_SPI4_APB, "spi4_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_SPI5_APB, "spi5_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_SPI6_APB, "spi6_apb", 0, JH7110_SYSCLK_APB_BUS), ++ /* i2c */ ++ JH71X0_GATE(JH7110_SYSCLK_I2C0_APB, "i2c0_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_I2C1_APB, "i2c1_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_I2C2_APB, "i2c2_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_I2C3_APB, "i2c3_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_I2C4_APB, "i2c4_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_I2C5_APB, "i2c5_apb", 0, JH7110_SYSCLK_APB_BUS), ++ JH71X0_GATE(JH7110_SYSCLK_I2C6_APB, "i2c6_apb", 0, JH7110_SYSCLK_APB_BUS), ++ /* uart */ ++ JH71X0_GATE(JH7110_SYSCLK_UART0_APB, "uart0_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_UART0_CORE, "uart0_core", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_UART1_APB, "uart1_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_UART1_CORE, "uart1_core", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_UART2_APB, "uart2_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_UART2_CORE, "uart2_core", 0, JH7110_SYSCLK_OSC), ++ JH71X0_GATE(JH7110_SYSCLK_UART3_APB, "uart3_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_UART3_CORE, "uart3_core", 0, 10, JH7110_SYSCLK_PERH_ROOT), ++ JH71X0_GATE(JH7110_SYSCLK_UART4_APB, "uart4_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_UART4_CORE, "uart4_core", 0, 10, JH7110_SYSCLK_PERH_ROOT), ++ JH71X0_GATE(JH7110_SYSCLK_UART5_APB, "uart5_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_UART5_CORE, "uart5_core", 0, 10, JH7110_SYSCLK_PERH_ROOT), ++ /* pwmdac */ ++ JH71X0_GATE(JH7110_SYSCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_PWMDAC_CORE, "pwmdac_core", 0, 256, JH7110_SYSCLK_AUDIO_ROOT), ++ /* spdif */ ++ JH71X0_GATE(JH7110_SYSCLK_SPDIF_APB, "spdif_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GATE(JH7110_SYSCLK_SPDIF_CORE, "spdif_core", 0, JH7110_SYSCLK_MCLK), ++ /* i2stx0 */ ++ JH71X0_GATE(JH7110_SYSCLK_I2STX0_APB, "i2stx0_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_I2STX0_BCLK_MST, "i2stx0_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK), ++ JH71X0__INV(JH7110_SYSCLK_I2STX0_BCLK_MST_INV, "i2stx0_bclk_mst_inv", ++ JH7110_SYSCLK_I2STX0_BCLK_MST), ++ JH71X0_MDIV(JH7110_SYSCLK_I2STX0_LRCK_MST, "i2stx0_lrck_mst", 64, 2, ++ JH7110_SYSCLK_I2STX0_BCLK_MST_INV, ++ JH7110_SYSCLK_I2STX0_BCLK_MST), ++ JH71X0__MUX(JH7110_SYSCLK_I2STX0_BCLK, "i2stx0_bclk", 2, ++ JH7110_SYSCLK_I2STX0_BCLK_MST, ++ JH7110_SYSCLK_I2STX_BCLK_EXT), ++ JH71X0__INV(JH7110_SYSCLK_I2STX0_BCLK_INV, "i2stx0_bclk_inv", JH7110_SYSCLK_I2STX0_BCLK), ++ JH71X0__MUX(JH7110_SYSCLK_I2STX0_LRCK, "i2stx0_lrck", 2, ++ JH7110_SYSCLK_I2STX0_LRCK_MST, ++ JH7110_SYSCLK_I2STX_LRCK_EXT), ++ /* i2stx1 */ ++ JH71X0_GATE(JH7110_SYSCLK_I2STX1_APB, "i2stx1_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_I2STX1_BCLK_MST, "i2stx1_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK), ++ JH71X0__INV(JH7110_SYSCLK_I2STX1_BCLK_MST_INV, "i2stx1_bclk_mst_inv", ++ JH7110_SYSCLK_I2STX1_BCLK_MST), ++ JH71X0_MDIV(JH7110_SYSCLK_I2STX1_LRCK_MST, "i2stx1_lrck_mst", 64, 2, ++ JH7110_SYSCLK_I2STX1_BCLK_MST_INV, ++ JH7110_SYSCLK_I2STX1_BCLK_MST), ++ JH71X0__MUX(JH7110_SYSCLK_I2STX1_BCLK, "i2stx1_bclk", 2, ++ JH7110_SYSCLK_I2STX1_BCLK_MST, ++ JH7110_SYSCLK_I2STX_BCLK_EXT), ++ JH71X0__INV(JH7110_SYSCLK_I2STX1_BCLK_INV, "i2stx1_bclk_inv", JH7110_SYSCLK_I2STX1_BCLK), ++ JH71X0__MUX(JH7110_SYSCLK_I2STX1_LRCK, "i2stx1_lrck", 2, ++ JH7110_SYSCLK_I2STX1_LRCK_MST, ++ JH7110_SYSCLK_I2STX_LRCK_EXT), ++ /* i2srx */ ++ JH71X0_GATE(JH7110_SYSCLK_I2SRX_APB, "i2srx_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_I2SRX_BCLK_MST, "i2srx_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK), ++ JH71X0__INV(JH7110_SYSCLK_I2SRX_BCLK_MST_INV, "i2srx_bclk_mst_inv", ++ JH7110_SYSCLK_I2SRX_BCLK_MST), ++ JH71X0_MDIV(JH7110_SYSCLK_I2SRX_LRCK_MST, "i2srx_lrck_mst", 64, 2, ++ JH7110_SYSCLK_I2SRX_BCLK_MST_INV, ++ JH7110_SYSCLK_I2SRX_BCLK_MST), ++ JH71X0__MUX(JH7110_SYSCLK_I2SRX_BCLK, "i2srx_bclk", 2, ++ JH7110_SYSCLK_I2SRX_BCLK_MST, ++ JH7110_SYSCLK_I2SRX_BCLK_EXT), ++ JH71X0__INV(JH7110_SYSCLK_I2SRX_BCLK_INV, "i2srx_bclk_inv", JH7110_SYSCLK_I2SRX_BCLK), ++ JH71X0__MUX(JH7110_SYSCLK_I2SRX_LRCK, "i2srx_lrck", 2, ++ JH7110_SYSCLK_I2SRX_LRCK_MST, ++ JH7110_SYSCLK_I2SRX_LRCK_EXT), ++ /* pdm */ ++ JH71X0_GDIV(JH7110_SYSCLK_PDM_DMIC, "pdm_dmic", 0, 64, JH7110_SYSCLK_MCLK), ++ JH71X0_GATE(JH7110_SYSCLK_PDM_APB, "pdm_apb", 0, JH7110_SYSCLK_APB0), ++ /* tdm */ ++ JH71X0_GATE(JH7110_SYSCLK_TDM_AHB, "tdm_ahb", 0, JH7110_SYSCLK_AHB0), ++ JH71X0_GATE(JH7110_SYSCLK_TDM_APB, "tdm_apb", 0, JH7110_SYSCLK_APB0), ++ JH71X0_GDIV(JH7110_SYSCLK_TDM_INTERNAL, "tdm_internal", 0, 64, JH7110_SYSCLK_MCLK), ++ JH71X0__MUX(JH7110_SYSCLK_TDM_TDM, "tdm_tdm", 2, ++ JH7110_SYSCLK_TDM_INTERNAL, ++ JH7110_SYSCLK_TDM_EXT), ++ JH71X0__INV(JH7110_SYSCLK_TDM_TDM_INV, "tdm_tdm_inv", JH7110_SYSCLK_TDM_TDM), ++ /* jtag */ ++ JH71X0__DIV(JH7110_SYSCLK_JTAG_CERTIFICATION_TRNG, "jtag_certification_trng", 4, ++ JH7110_SYSCLK_OSC), ++}; ++ ++static struct clk_hw *jh7110_sysclk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh71x0_clk_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_SYSCLK_END) ++ return &priv->reg[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++static void jh7110_reset_unregister_adev(void *_adev) ++{ ++ struct auxiliary_device *adev = _adev; ++ ++ auxiliary_device_delete(adev); ++} ++ ++static void jh7110_reset_adev_release(struct device *dev) ++{ ++ struct auxiliary_device *adev = to_auxiliary_dev(dev); ++ ++ auxiliary_device_uninit(adev); ++} ++ ++int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv, ++ const char *adev_name, ++ u32 adev_id) ++{ ++ struct auxiliary_device *adev; ++ int ret; ++ ++ adev = devm_kzalloc(priv->dev, sizeof(*adev), GFP_KERNEL); ++ if (!adev) ++ return -ENOMEM; ++ ++ adev->name = adev_name; ++ adev->dev.parent = priv->dev; ++ adev->dev.release = jh7110_reset_adev_release; ++ adev->id = adev_id; ++ ++ ret = auxiliary_device_init(adev); ++ if (ret) ++ return ret; ++ ++ ret = auxiliary_device_add(adev); ++ if (ret) { ++ auxiliary_device_uninit(adev); ++ return ret; ++ } ++ ++ return devm_add_action_or_reset(priv->dev, ++ jh7110_reset_unregister_adev, adev); ++} ++EXPORT_SYMBOL_GPL(jh7110_reset_controller_register); ++ ++static int __init jh7110_syscrg_probe(struct platform_device *pdev) ++{ ++ struct jh71x0_clk_priv *priv; ++ unsigned int idx; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, ++ struct_size(priv, reg, JH7110_SYSCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->rmw_lock); ++ priv->dev = &pdev->dev; ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ dev_set_drvdata(priv->dev, (void *)(&priv->base)); ++ ++ /* ++ * These PLL clocks are not actually fixed factor clocks and can be ++ * controlled by the syscon registers of JH7110. They will be dropped ++ * and registered in the PLL clock driver instead. ++ */ ++ /* 24MHz -> 1000.0MHz */ ++ priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out", ++ "osc", 0, 125, 3); ++ if (IS_ERR(priv->pll[0])) ++ return PTR_ERR(priv->pll[0]); ++ ++ /* 24MHz -> 1066.0MHz */ ++ priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out", ++ "osc", 0, 533, 12); ++ if (IS_ERR(priv->pll[1])) ++ return PTR_ERR(priv->pll[1]); ++ ++ /* 24MHz -> 1188.0MHz */ ++ priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out", ++ "osc", 0, 99, 2); ++ if (IS_ERR(priv->pll[2])) ++ return PTR_ERR(priv->pll[2]); ++ ++ for (idx = 0; idx < JH7110_SYSCLK_END; idx++) { ++ u32 max = jh7110_sysclk_data[idx].max; ++ struct clk_parent_data parents[4] = {}; ++ struct clk_init_data init = { ++ .name = jh7110_sysclk_data[idx].name, ++ .ops = starfive_jh71x0_clk_ops(max), ++ .parent_data = parents, ++ .num_parents = ++ ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, ++ .flags = jh7110_sysclk_data[idx].flags, ++ }; ++ struct jh71x0_clk *clk = &priv->reg[idx]; ++ unsigned int i; ++ ++ for (i = 0; i < init.num_parents; i++) { ++ unsigned int pidx = jh7110_sysclk_data[idx].parents[i]; ++ ++ if (pidx < JH7110_SYSCLK_END) ++ parents[i].hw = &priv->reg[pidx].hw; ++ else if (pidx == JH7110_SYSCLK_OSC) ++ parents[i].fw_name = "osc"; ++ else if (pidx == JH7110_SYSCLK_GMAC1_RMII_REFIN) ++ parents[i].fw_name = "gmac1_rmii_refin"; ++ else if (pidx == JH7110_SYSCLK_GMAC1_RGMII_RXIN) ++ parents[i].fw_name = "gmac1_rgmii_rxin"; ++ else if (pidx == JH7110_SYSCLK_I2STX_BCLK_EXT) ++ parents[i].fw_name = "i2stx_bclk_ext"; ++ else if (pidx == JH7110_SYSCLK_I2STX_LRCK_EXT) ++ parents[i].fw_name = "i2stx_lrck_ext"; ++ else if (pidx == JH7110_SYSCLK_I2SRX_BCLK_EXT) ++ parents[i].fw_name = "i2srx_bclk_ext"; ++ else if (pidx == JH7110_SYSCLK_I2SRX_LRCK_EXT) ++ parents[i].fw_name = "i2srx_lrck_ext"; ++ else if (pidx == JH7110_SYSCLK_TDM_EXT) ++ parents[i].fw_name = "tdm_ext"; ++ else if (pidx == JH7110_SYSCLK_MCLK_EXT) ++ parents[i].fw_name = "mclk_ext"; ++ else ++ parents[i].hw = priv->pll[pidx - JH7110_SYSCLK_PLL0_OUT]; ++ } ++ ++ clk->hw.init = &init; ++ clk->idx = idx; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clk->hw); ++ if (ret) ++ return ret; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_sysclk_get, priv); ++ if (ret) ++ return ret; ++ ++ return jh7110_reset_controller_register(priv, "rst-sys", 0); ++} ++ ++static const struct of_device_id jh7110_syscrg_match[] = { ++ { .compatible = "starfive,jh7110-syscrg" }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver jh7110_syscrg_driver = { ++ .driver = { ++ .name = "clk-starfive-jh7110-sys", ++ .of_match_table = jh7110_syscrg_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver_probe(jh7110_syscrg_driver, jh7110_syscrg_probe); +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __CLK_STARFIVE_JH7110_H ++#define __CLK_STARFIVE_JH7110_H ++ ++#include "clk-starfive-jh71x0.h" ++ ++int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv, ++ const char *adev_name, ++ u32 adev_id); ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch b/target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch new file mode 100644 index 0000000000..4986c110f7 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch @@ -0,0 +1,206 @@ +From 6b9f7a65cd2e9cc4bdc2ee3c3fb46bef4568af0a Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:26 +0800 +Subject: [PATCH 014/122] clk: starfive: Add StarFive JH7110 always-on clock + driver + +Add driver for the StarFive JH7110 always-on clock controller +and register an auxiliary device for always-on reset controller +which is named as "rst-aon". + +Tested-by: Tommaso Merciai +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Co-developed-by: Hal Feng +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/clk/starfive/Kconfig | 11 ++ + drivers/clk/starfive/Makefile | 1 + + .../clk/starfive/clk-starfive-jh7110-aon.c | 156 ++++++++++++++++++ + 3 files changed, 168 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-aon.c + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -31,3 +31,14 @@ config CLK_STARFIVE_JH7110_SYS + help + Say yes here to support the system clock controller on the + StarFive JH7110 SoC. ++ ++config CLK_STARFIVE_JH7110_AON ++ tristate "StarFive JH7110 always-on clock support" ++ depends on CLK_STARFIVE_JH7110_SYS ++ select AUXILIARY_BUS ++ select CLK_STARFIVE_JH71X0 ++ select RESET_STARFIVE_JH7110 ++ default m if ARCH_STARFIVE ++ help ++ Say yes here to support the always-on clock controller on the ++ StarFive JH7110 SoC. +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -5,3 +5,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk + obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) += clk-starfive-jh7100-audio.o + + obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += clk-starfive-jh7110-sys.o ++obj-$(CONFIG_CLK_STARFIVE_JH7110_AON) += clk-starfive-jh7110-aon.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-aon.c +@@ -0,0 +1,156 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 Always-On Clock Driver ++ * ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110.h" ++ ++/* external clocks */ ++#define JH7110_AONCLK_OSC (JH7110_AONCLK_END + 0) ++#define JH7110_AONCLK_GMAC0_RMII_REFIN (JH7110_AONCLK_END + 1) ++#define JH7110_AONCLK_GMAC0_RGMII_RXIN (JH7110_AONCLK_END + 2) ++#define JH7110_AONCLK_STG_AXIAHB (JH7110_AONCLK_END + 3) ++#define JH7110_AONCLK_APB_BUS (JH7110_AONCLK_END + 4) ++#define JH7110_AONCLK_GMAC0_GTXCLK (JH7110_AONCLK_END + 5) ++#define JH7110_AONCLK_RTC_OSC (JH7110_AONCLK_END + 6) ++ ++static const struct jh71x0_clk_data jh7110_aonclk_data[] = { ++ /* source */ ++ JH71X0__DIV(JH7110_AONCLK_OSC_DIV4, "osc_div4", 4, JH7110_AONCLK_OSC), ++ JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 2, ++ JH7110_AONCLK_OSC_DIV4, ++ JH7110_AONCLK_OSC), ++ /* gmac0 */ ++ JH71X0_GATE(JH7110_AONCLK_GMAC0_AHB, "gmac0_ahb", 0, JH7110_AONCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_AONCLK_GMAC0_AXI, "gmac0_axi", 0, JH7110_AONCLK_STG_AXIAHB), ++ JH71X0__DIV(JH7110_AONCLK_GMAC0_RMII_RTX, "gmac0_rmii_rtx", 30, ++ JH7110_AONCLK_GMAC0_RMII_REFIN), ++ JH71X0_GMUX(JH7110_AONCLK_GMAC0_TX, "gmac0_tx", ++ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 2, ++ JH7110_AONCLK_GMAC0_GTXCLK, ++ JH7110_AONCLK_GMAC0_RMII_RTX), ++ JH71X0__INV(JH7110_AONCLK_GMAC0_TX_INV, "gmac0_tx_inv", JH7110_AONCLK_GMAC0_TX), ++ JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 2, ++ JH7110_AONCLK_GMAC0_RGMII_RXIN, ++ JH7110_AONCLK_GMAC0_RMII_RTX), ++ JH71X0__INV(JH7110_AONCLK_GMAC0_RX_INV, "gmac0_rx_inv", JH7110_AONCLK_GMAC0_RX), ++ /* otpc */ ++ JH71X0_GATE(JH7110_AONCLK_OTPC_APB, "otpc_apb", 0, JH7110_AONCLK_APB_BUS), ++ /* rtc */ ++ JH71X0_GATE(JH7110_AONCLK_RTC_APB, "rtc_apb", 0, JH7110_AONCLK_APB_BUS), ++ JH71X0__DIV(JH7110_AONCLK_RTC_INTERNAL, "rtc_internal", 1022, JH7110_AONCLK_OSC), ++ JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 2, ++ JH7110_AONCLK_RTC_OSC, ++ JH7110_AONCLK_RTC_INTERNAL), ++ JH71X0_GATE(JH7110_AONCLK_RTC_CAL, "rtc_cal", 0, JH7110_AONCLK_OSC), ++}; ++ ++static struct clk_hw *jh7110_aonclk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh71x0_clk_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_AONCLK_END) ++ return &priv->reg[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++static int jh7110_aoncrg_probe(struct platform_device *pdev) ++{ ++ struct jh71x0_clk_priv *priv; ++ unsigned int idx; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, ++ struct_size(priv, reg, JH7110_AONCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->rmw_lock); ++ priv->dev = &pdev->dev; ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ dev_set_drvdata(priv->dev, (void *)(&priv->base)); ++ ++ for (idx = 0; idx < JH7110_AONCLK_END; idx++) { ++ u32 max = jh7110_aonclk_data[idx].max; ++ struct clk_parent_data parents[4] = {}; ++ struct clk_init_data init = { ++ .name = jh7110_aonclk_data[idx].name, ++ .ops = starfive_jh71x0_clk_ops(max), ++ .parent_data = parents, ++ .num_parents = ++ ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, ++ .flags = jh7110_aonclk_data[idx].flags, ++ }; ++ struct jh71x0_clk *clk = &priv->reg[idx]; ++ unsigned int i; ++ ++ for (i = 0; i < init.num_parents; i++) { ++ unsigned int pidx = jh7110_aonclk_data[idx].parents[i]; ++ ++ if (pidx < JH7110_AONCLK_END) ++ parents[i].hw = &priv->reg[pidx].hw; ++ else if (pidx == JH7110_AONCLK_OSC) ++ parents[i].fw_name = "osc"; ++ else if (pidx == JH7110_AONCLK_GMAC0_RMII_REFIN) ++ parents[i].fw_name = "gmac0_rmii_refin"; ++ else if (pidx == JH7110_AONCLK_GMAC0_RGMII_RXIN) ++ parents[i].fw_name = "gmac0_rgmii_rxin"; ++ else if (pidx == JH7110_AONCLK_STG_AXIAHB) ++ parents[i].fw_name = "stg_axiahb"; ++ else if (pidx == JH7110_AONCLK_APB_BUS) ++ parents[i].fw_name = "apb_bus"; ++ else if (pidx == JH7110_AONCLK_GMAC0_GTXCLK) ++ parents[i].fw_name = "gmac0_gtxclk"; ++ else if (pidx == JH7110_AONCLK_RTC_OSC) ++ parents[i].fw_name = "rtc_osc"; ++ } ++ ++ clk->hw.init = &init; ++ clk->idx = idx; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clk->hw); ++ if (ret) ++ return ret; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_aonclk_get, priv); ++ if (ret) ++ return ret; ++ ++ return jh7110_reset_controller_register(priv, "rst-aon", 1); ++} ++ ++static const struct of_device_id jh7110_aoncrg_match[] = { ++ { .compatible = "starfive,jh7110-aoncrg" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_aoncrg_match); ++ ++static struct platform_driver jh7110_aoncrg_driver = { ++ .probe = jh7110_aoncrg_probe, ++ .driver = { ++ .name = "clk-starfive-jh7110-aon", ++ .of_match_table = jh7110_aoncrg_match, ++ }, ++}; ++module_platform_driver(jh7110_aoncrg_driver); ++ ++MODULE_AUTHOR("Emil Renner Berthing"); ++MODULE_DESCRIPTION("StarFive JH7110 always-on clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch b/target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch new file mode 100644 index 0000000000..1a2a9d9991 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch @@ -0,0 +1,113 @@ +From ea2f40c943f4a6d39a2f3ea4660266250d37c95a Mon Sep 17 00:00:00 2001 +From: Hal Feng +Date: Sat, 1 Apr 2023 19:19:27 +0800 +Subject: [PATCH 015/122] reset: starfive: Add StarFive JH7110 reset driver + +Add auxiliary driver to support StarFive JH7110 system +and always-on resets. + +Tested-by: Tommaso Merciai +Reviewed-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + drivers/reset/starfive/Kconfig | 8 +++ + drivers/reset/starfive/Makefile | 1 + + .../reset/starfive/reset-starfive-jh7110.c | 70 +++++++++++++++++++ + 3 files changed, 79 insertions(+) + create mode 100644 drivers/reset/starfive/reset-starfive-jh7110.c + +--- a/drivers/reset/starfive/Kconfig ++++ b/drivers/reset/starfive/Kconfig +@@ -10,3 +10,11 @@ config RESET_STARFIVE_JH7100 + default ARCH_STARFIVE + help + This enables the reset controller driver for the StarFive JH7100 SoC. ++ ++config RESET_STARFIVE_JH7110 ++ bool "StarFive JH7110 Reset Driver" ++ depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS ++ select RESET_STARFIVE_JH71X0 ++ default ARCH_STARFIVE ++ help ++ This enables the reset controller driver for the StarFive JH7110 SoC. +--- a/drivers/reset/starfive/Makefile ++++ b/drivers/reset/starfive/Makefile +@@ -2,3 +2,4 @@ + obj-$(CONFIG_RESET_STARFIVE_JH71X0) += reset-starfive-jh71x0.o + + obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o ++obj-$(CONFIG_RESET_STARFIVE_JH7110) += reset-starfive-jh7110.o +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh7110.c +@@ -0,0 +1,70 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Reset driver for the StarFive JH7110 SoC ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++ ++#include "reset-starfive-jh71x0.h" ++ ++#include ++ ++struct jh7110_reset_info { ++ unsigned int nr_resets; ++ unsigned int assert_offset; ++ unsigned int status_offset; ++}; ++ ++static const struct jh7110_reset_info jh7110_sys_info = { ++ .nr_resets = JH7110_SYSRST_END, ++ .assert_offset = 0x2F8, ++ .status_offset = 0x308, ++}; ++ ++static const struct jh7110_reset_info jh7110_aon_info = { ++ .nr_resets = JH7110_AONRST_END, ++ .assert_offset = 0x38, ++ .status_offset = 0x3C, ++}; ++ ++static int jh7110_reset_probe(struct auxiliary_device *adev, ++ const struct auxiliary_device_id *id) ++{ ++ struct jh7110_reset_info *info = (struct jh7110_reset_info *)(id->driver_data); ++ void __iomem **base = (void __iomem **)dev_get_drvdata(adev->dev.parent); ++ ++ if (!info || !base) ++ return -ENODEV; ++ ++ return reset_starfive_jh71x0_register(&adev->dev, adev->dev.parent->of_node, ++ *base + info->assert_offset, ++ *base + info->status_offset, ++ NULL, ++ info->nr_resets, ++ NULL); ++} ++ ++static const struct auxiliary_device_id jh7110_reset_ids[] = { ++ { ++ .name = "clk_starfive_jh7110_sys.rst-sys", ++ .driver_data = (kernel_ulong_t)&jh7110_sys_info, ++ }, ++ { ++ .name = "clk_starfive_jh7110_sys.rst-aon", ++ .driver_data = (kernel_ulong_t)&jh7110_aon_info, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(auxiliary, jh7110_reset_ids); ++ ++static struct auxiliary_driver jh7110_reset_driver = { ++ .probe = jh7110_reset_probe, ++ .id_table = jh7110_reset_ids, ++}; ++module_auxiliary_driver(jh7110_reset_driver); ++ ++MODULE_AUTHOR("Hal Feng "); ++MODULE_DESCRIPTION("StarFive JH7110 reset driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch b/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch new file mode 100644 index 0000000000..68b96fa388 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch @@ -0,0 +1,50 @@ +From 17fecb06e9de3ae5bbf7aecc4d91e14517982f5c Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Wed, 17 May 2023 20:41:51 -0700 +Subject: [PATCH 016/122] MAINTAINERS: generalise StarFive clk/reset entries + +Update the MAINTAINERS entry for StarFive's clock and reset drivers to +account for the addition of JH7110 support and Hal's role in that. + +Signed-off-by: shanlong.li +--- + MAINTAINERS | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19650,12 +19650,13 @@ M: Emil Renner Berthing ++M: Hal Feng + S: Maintained +-F: Documentation/devicetree/bindings/clock/starfive,jh7100-*.yaml +-F: drivers/clk/starfive/clk-starfive-jh7100* +-F: include/dt-bindings/clock/starfive-jh7100*.h ++F: Documentation/devicetree/bindings/clock/starfive,jh71*.yaml ++F: drivers/clk/starfive/clk-starfive-jh71* ++F: include/dt-bindings/clock/starfive?jh71*.h + + STARFIVE JH7100 PINCTRL DRIVER + M: Emil Renner Berthing +@@ -19665,12 +19666,13 @@ F: Documentation/devicetree/bindings/pin + F: drivers/pinctrl/starfive/ + F: include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h + +-STARFIVE JH7100 RESET CONTROLLER DRIVER ++STARFIVE JH71X0 RESET CONTROLLER DRIVERS + M: Emil Renner Berthing ++M: Hal Feng + S: Maintained + F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml +-F: drivers/reset/reset-starfive-jh7100.c +-F: include/dt-bindings/reset/starfive-jh7100.h ++F: drivers/reset/starfive/reset-starfive-jh71* ++F: include/dt-bindings/reset/starfive?jh71*.h + + STATIC BRANCH/CALL + M: Peter Zijlstra diff --git a/target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch b/target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch new file mode 100644 index 0000000000..9667f7256c --- /dev/null +++ b/target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch @@ -0,0 +1,128 @@ +From d9d4e0fb44a50cace195e1639cfb23e518e17e88 Mon Sep 17 00:00:00 2001 +From: Stephen Boyd +Date: Thu, 13 Apr 2023 13:55:28 -0700 +Subject: [PATCH 017/122] clk: starfive: Avoid casting iomem pointers + +Let's use a wrapper struct for the auxiliary_device made in +jh7110_reset_controller_register() so that we can stop casting iomem +pointers. The casts trip up tools like sparse, and make for some awkward +casts that are largely unnecessary. While we're here, change the +allocation from devm and actually free the auxiliary_device memory in +the release function. This avoids any use after free problems where the +parent device driver is unbound from the device but the +auxiliuary_device is still in use accessing devm freed memory. + +Cc: Tommaso Merciai +Cc: Emil Renner Berthing +Cc: Hal Feng +Cc: Conor Dooley +Cc: Xingyu Wu +Reviewed-by: Conor Dooley +Fixes: edab7204afe5 ("clk: starfive: Add StarFive JH7110 system clock driver") +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20230413205528.4044216-1-sboyd@kernel.org +--- + drivers/clk/starfive/clk-starfive-jh7110-sys.c | 15 ++++++++++++--- + drivers/reset/starfive/reset-starfive-jh7110.c | 9 ++++++--- + include/soc/starfive/reset-starfive-jh71x0.h | 17 +++++++++++++++++ + 3 files changed, 35 insertions(+), 6 deletions(-) + create mode 100644 include/soc/starfive/reset-starfive-jh71x0.h + +--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c +@@ -11,6 +11,9 @@ + #include + #include + #include ++#include ++ ++#include + + #include + +@@ -335,26 +338,32 @@ static void jh7110_reset_unregister_adev + struct auxiliary_device *adev = _adev; + + auxiliary_device_delete(adev); ++ auxiliary_device_uninit(adev); + } + + static void jh7110_reset_adev_release(struct device *dev) + { + struct auxiliary_device *adev = to_auxiliary_dev(dev); ++ struct jh71x0_reset_adev *rdev = to_jh71x0_reset_adev(adev); + +- auxiliary_device_uninit(adev); ++ kfree(rdev); + } + + int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv, + const char *adev_name, + u32 adev_id) + { ++ struct jh71x0_reset_adev *rdev; + struct auxiliary_device *adev; + int ret; + +- adev = devm_kzalloc(priv->dev, sizeof(*adev), GFP_KERNEL); +- if (!adev) ++ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); ++ if (!rdev) + return -ENOMEM; + ++ rdev->base = priv->base; ++ ++ adev = &rdev->adev; + adev->name = adev_name; + adev->dev.parent = priv->dev; + adev->dev.release = jh7110_reset_adev_release; +--- a/drivers/reset/starfive/reset-starfive-jh7110.c ++++ b/drivers/reset/starfive/reset-starfive-jh7110.c +@@ -7,6 +7,8 @@ + + #include + ++#include ++ + #include "reset-starfive-jh71x0.h" + + #include +@@ -33,14 +35,15 @@ static int jh7110_reset_probe(struct aux + const struct auxiliary_device_id *id) + { + struct jh7110_reset_info *info = (struct jh7110_reset_info *)(id->driver_data); +- void __iomem **base = (void __iomem **)dev_get_drvdata(adev->dev.parent); ++ struct jh71x0_reset_adev *rdev = to_jh71x0_reset_adev(adev); ++ void __iomem *base = rdev->base; + + if (!info || !base) + return -ENODEV; + + return reset_starfive_jh71x0_register(&adev->dev, adev->dev.parent->of_node, +- *base + info->assert_offset, +- *base + info->status_offset, ++ base + info->assert_offset, ++ base + info->status_offset, + NULL, + info->nr_resets, + NULL); +--- /dev/null ++++ b/include/soc/starfive/reset-starfive-jh71x0.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __SOC_STARFIVE_RESET_JH71X0_H ++#define __SOC_STARFIVE_RESET_JH71X0_H ++ ++#include ++#include ++#include ++ ++struct jh71x0_reset_adev { ++ void __iomem *base; ++ struct auxiliary_device adev; ++}; ++ ++#define to_jh71x0_reset_adev(_adev) \ ++ container_of((_adev), struct jh71x0_reset_adev, adev) ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch b/target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch new file mode 100644 index 0000000000..83de87edfc --- /dev/null +++ b/target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch @@ -0,0 +1,27 @@ +From f043ba93a8f22fda312574eb98217be15468b7ef Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:28 +0800 +Subject: [PATCH 018/122] dt-bindings: timer: Add StarFive JH7110 clint + +Add compatible string for the StarFive JH7110 clint. + +Reviewed-by: Conor Dooley +Acked-by: Krzysztof Kozlowski +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml ++++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml +@@ -27,6 +27,7 @@ properties: + - enum: + - sifive,fu540-c000-clint + - starfive,jh7100-clint ++ - starfive,jh7110-clint + - canaan,k210-clint + - const: sifive,clint0 + - items: diff --git a/target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch b/target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch new file mode 100644 index 0000000000..bb604fee54 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch @@ -0,0 +1,28 @@ +From dba83b8b65b4ef47e8986739b6734894f3979c52 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:29 +0800 +Subject: [PATCH 019/122] dt-bindings: interrupt-controller: Add StarFive + JH7110 plic + +Add compatible string for StarFive JH7110 plic. + +Reviewed-by: Conor Dooley +Acked-by: Krzysztof Kozlowski +Reviewed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml ++++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +@@ -60,6 +60,7 @@ properties: + - enum: + - sifive,fu540-c000-plic + - starfive,jh7100-plic ++ - starfive,jh7110-plic + - canaan,k210-plic + - const: sifive,plic-1.0.0 + - items: diff --git a/target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch b/target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch new file mode 100644 index 0000000000..c8e282e04f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch @@ -0,0 +1,27 @@ +From fccbb0c52438762999ea16c85d4ebf4cc7e2deff Mon Sep 17 00:00:00 2001 +From: Hal Feng +Date: Sat, 1 Apr 2023 19:19:30 +0800 +Subject: [PATCH 020/122] dt-bindings: riscv: Add SiFive S7 compatible + +Add a new compatible string in cpu.yaml for SiFive S7 CPU +core which is used on SiFive U74-MC core complex etc. + +Reviewed-by: Conor Dooley +Acked-by: Krzysztof Kozlowski +Reviewed-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Signed-off-by: Conor Dooley +--- + Documentation/devicetree/bindings/riscv/cpus.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/riscv/cpus.yaml ++++ b/Documentation/devicetree/bindings/riscv/cpus.yaml +@@ -33,6 +33,7 @@ properties: + - sifive,e5 + - sifive,e7 + - sifive,e71 ++ - sifive,s7 + - sifive,u74-mc + - sifive,u54 + - sifive,u74 diff --git a/target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch b/target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch new file mode 100644 index 0000000000..d1e1cfc8cd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch @@ -0,0 +1,549 @@ +From ca57ce82224c21f93ad43754474fb8de1baf5caa Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:31 +0800 +Subject: [PATCH 021/122] riscv: dts: starfive: Add initial StarFive JH7110 + device tree + +Add initial device tree for the JH7110 RISC-V SoC by StarFive +Technology Ltd. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Signed-off-by: Emil Renner Berthing +Co-developed-by: Jianlong Huang +Signed-off-by: Jianlong Huang +Co-developed-by: Hal Feng +Signed-off-by: Hal Feng +[conor: squashed in the removal of the S7's non-existent mmu] +Reviewed-by: Emil Renner Berthing +Signed-off-by: Conor Dooley +--- + arch/riscv/Kconfig.socs | 5 + + arch/riscv/boot/dts/starfive/jh7110.dtsi | 500 +++++++++++++++++++++++ + 2 files changed, 505 insertions(+) + create mode 100644 arch/riscv/boot/dts/starfive/jh7110.dtsi + +--- a/arch/riscv/Kconfig.socs ++++ b/arch/riscv/Kconfig.socs +@@ -7,6 +7,8 @@ config SOC_MICROCHIP_POLARFIRE + help + This enables support for Microchip PolarFire SoC platforms. + ++config ARCH_SIFIVE ++ def_bool SOC_SIFIVE + config SOC_SIFIVE + bool "SiFive SoCs" + select SERIAL_SIFIVE if TTY +@@ -18,6 +20,9 @@ config SOC_SIFIVE + help + This enables support for SiFive SoC platform hardware. + ++config ARCH_STARFIVE ++ def_bool SOC_STARFIVE ++ + config SOC_STARFIVE + bool "StarFive SoCs" + select PINCTRL +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi +@@ -0,0 +1,500 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include ++#include ++ ++/ { ++ compatible = "starfive,jh7110"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ S7_0: cpu@0 { ++ compatible = "sifive,s7", "riscv"; ++ reg = <0>; ++ device_type = "cpu"; ++ i-cache-block-size = <64>; ++ i-cache-sets = <64>; ++ i-cache-size = <16384>; ++ next-level-cache = <&ccache>; ++ riscv,isa = "rv64imac_zba_zbb"; ++ status = "disabled"; ++ ++ cpu0_intc: interrupt-controller { ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ U74_1: cpu@1 { ++ compatible = "sifive,u74-mc", "riscv"; ++ reg = <1>; ++ d-cache-block-size = <64>; ++ d-cache-sets = <64>; ++ d-cache-size = <32768>; ++ d-tlb-sets = <1>; ++ d-tlb-size = <40>; ++ device_type = "cpu"; ++ i-cache-block-size = <64>; ++ i-cache-sets = <64>; ++ i-cache-size = <32768>; ++ i-tlb-sets = <1>; ++ i-tlb-size = <40>; ++ mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; ++ riscv,isa = "rv64imafdc_zba_zbb"; ++ tlb-split; ++ ++ cpu1_intc: interrupt-controller { ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ U74_2: cpu@2 { ++ compatible = "sifive,u74-mc", "riscv"; ++ reg = <2>; ++ d-cache-block-size = <64>; ++ d-cache-sets = <64>; ++ d-cache-size = <32768>; ++ d-tlb-sets = <1>; ++ d-tlb-size = <40>; ++ device_type = "cpu"; ++ i-cache-block-size = <64>; ++ i-cache-sets = <64>; ++ i-cache-size = <32768>; ++ i-tlb-sets = <1>; ++ i-tlb-size = <40>; ++ mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; ++ riscv,isa = "rv64imafdc_zba_zbb"; ++ tlb-split; ++ ++ cpu2_intc: interrupt-controller { ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ U74_3: cpu@3 { ++ compatible = "sifive,u74-mc", "riscv"; ++ reg = <3>; ++ d-cache-block-size = <64>; ++ d-cache-sets = <64>; ++ d-cache-size = <32768>; ++ d-tlb-sets = <1>; ++ d-tlb-size = <40>; ++ device_type = "cpu"; ++ i-cache-block-size = <64>; ++ i-cache-sets = <64>; ++ i-cache-size = <32768>; ++ i-tlb-sets = <1>; ++ i-tlb-size = <40>; ++ mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; ++ riscv,isa = "rv64imafdc_zba_zbb"; ++ tlb-split; ++ ++ cpu3_intc: interrupt-controller { ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ U74_4: cpu@4 { ++ compatible = "sifive,u74-mc", "riscv"; ++ reg = <4>; ++ d-cache-block-size = <64>; ++ d-cache-sets = <64>; ++ d-cache-size = <32768>; ++ d-tlb-sets = <1>; ++ d-tlb-size = <40>; ++ device_type = "cpu"; ++ i-cache-block-size = <64>; ++ i-cache-sets = <64>; ++ i-cache-size = <32768>; ++ i-tlb-sets = <1>; ++ i-tlb-size = <40>; ++ mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; ++ riscv,isa = "rv64imafdc_zba_zbb"; ++ tlb-split; ++ ++ cpu4_intc: interrupt-controller { ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ cpu-map { ++ cluster0 { ++ core0 { ++ cpu = <&S7_0>; ++ }; ++ ++ core1 { ++ cpu = <&U74_1>; ++ }; ++ ++ core2 { ++ cpu = <&U74_2>; ++ }; ++ ++ core3 { ++ cpu = <&U74_3>; ++ }; ++ ++ core4 { ++ cpu = <&U74_4>; ++ }; ++ }; ++ }; ++ }; ++ ++ gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "gmac0_rgmii_rxin"; ++ #clock-cells = <0>; ++ }; ++ ++ gmac0_rmii_refin: gmac0-rmii-refin-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "gmac0_rmii_refin"; ++ #clock-cells = <0>; ++ }; ++ ++ gmac1_rgmii_rxin: gmac1-rgmii-rxin-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "gmac1_rgmii_rxin"; ++ #clock-cells = <0>; ++ }; ++ ++ gmac1_rmii_refin: gmac1-rmii-refin-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "gmac1_rmii_refin"; ++ #clock-cells = <0>; ++ }; ++ ++ i2srx_bclk_ext: i2srx-bclk-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "i2srx_bclk_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ i2srx_lrck_ext: i2srx-lrck-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "i2srx_lrck_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ i2stx_bclk_ext: i2stx-bclk-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "i2stx_bclk_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ i2stx_lrck_ext: i2stx-lrck-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "i2stx_lrck_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ mclk_ext: mclk-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "mclk_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ osc: oscillator { ++ compatible = "fixed-clock"; ++ clock-output-names = "osc"; ++ #clock-cells = <0>; ++ }; ++ ++ rtc_osc: rtc-oscillator { ++ compatible = "fixed-clock"; ++ clock-output-names = "rtc_osc"; ++ #clock-cells = <0>; ++ }; ++ ++ tdm_ext: tdm-ext-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "tdm_ext"; ++ #clock-cells = <0>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ interrupt-parent = <&plic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clint: timer@2000000 { ++ compatible = "starfive,jh7110-clint", "sifive,clint0"; ++ reg = <0x0 0x2000000 0x0 0x10000>; ++ interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, ++ <&cpu1_intc 3>, <&cpu1_intc 7>, ++ <&cpu2_intc 3>, <&cpu2_intc 7>, ++ <&cpu3_intc 3>, <&cpu3_intc 7>, ++ <&cpu4_intc 3>, <&cpu4_intc 7>; ++ }; ++ ++ ccache: cache-controller@2010000 { ++ compatible = "starfive,jh7110-ccache", "sifive,ccache0", "cache"; ++ reg = <0x0 0x2010000 0x0 0x4000>; ++ interrupts = <1>, <3>, <4>, <2>; ++ cache-block-size = <64>; ++ cache-level = <2>; ++ cache-sets = <2048>; ++ cache-size = <2097152>; ++ cache-unified; ++ }; ++ ++ plic: interrupt-controller@c000000 { ++ compatible = "starfive,jh7110-plic", "sifive,plic-1.0.0"; ++ reg = <0x0 0xc000000 0x0 0x4000000>; ++ interrupts-extended = <&cpu0_intc 11>, ++ <&cpu1_intc 11>, <&cpu1_intc 9>, ++ <&cpu2_intc 11>, <&cpu2_intc 9>, ++ <&cpu3_intc 11>, <&cpu3_intc 9>, ++ <&cpu4_intc 11>, <&cpu4_intc 9>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ #address-cells = <0>; ++ riscv,ndev = <136>; ++ }; ++ ++ uart0: serial@10000000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x10000000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>, ++ <&syscrg JH7110_SYSCLK_UART0_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART0_APB>; ++ interrupts = <32>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@10010000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x10010000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>, ++ <&syscrg JH7110_SYSCLK_UART1_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART1_APB>; ++ interrupts = <33>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@10020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x10020000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>, ++ <&syscrg JH7110_SYSCLK_UART2_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART2_APB>; ++ interrupts = <34>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@10030000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x10030000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C0_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C0_APB>; ++ interrupts = <35>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@10040000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x10040000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C1_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C1_APB>; ++ interrupts = <36>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@10050000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x10050000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C2_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C2_APB>; ++ interrupts = <37>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@12000000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x12000000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>, ++ <&syscrg JH7110_SYSCLK_UART3_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART3_APB>; ++ interrupts = <45>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@12010000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x12010000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>, ++ <&syscrg JH7110_SYSCLK_UART4_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART4_APB>; ++ interrupts = <46>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@12020000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x0 0x12020000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>, ++ <&syscrg JH7110_SYSCLK_UART5_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&syscrg JH7110_SYSRST_UART5_APB>; ++ interrupts = <47>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@12030000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x12030000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C3_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C3_APB>; ++ interrupts = <48>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@12040000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x12040000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C4_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C4_APB>; ++ interrupts = <49>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@12050000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x12050000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C5_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C5_APB>; ++ interrupts = <50>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c6: i2c@12060000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x12060000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_I2C6_APB>; ++ clock-names = "ref"; ++ resets = <&syscrg JH7110_SYSRST_I2C6_APB>; ++ interrupts = <51>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ syscrg: clock-controller@13020000 { ++ compatible = "starfive,jh7110-syscrg"; ++ reg = <0x0 0x13020000 0x0 0x10000>; ++ clocks = <&osc>, <&gmac1_rmii_refin>, ++ <&gmac1_rgmii_rxin>, ++ <&i2stx_bclk_ext>, <&i2stx_lrck_ext>, ++ <&i2srx_bclk_ext>, <&i2srx_lrck_ext>, ++ <&tdm_ext>, <&mclk_ext>; ++ clock-names = "osc", "gmac1_rmii_refin", ++ "gmac1_rgmii_rxin", ++ "i2stx_bclk_ext", "i2stx_lrck_ext", ++ "i2srx_bclk_ext", "i2srx_lrck_ext", ++ "tdm_ext", "mclk_ext"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ sysgpio: pinctrl@13040000 { ++ compatible = "starfive,jh7110-sys-pinctrl"; ++ reg = <0x0 0x13040000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_IOMUX_APB>; ++ resets = <&syscrg JH7110_SYSRST_IOMUX_APB>; ++ interrupts = <86>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ aoncrg: clock-controller@17000000 { ++ compatible = "starfive,jh7110-aoncrg"; ++ reg = <0x0 0x17000000 0x0 0x10000>; ++ clocks = <&osc>, <&gmac0_rmii_refin>, ++ <&gmac0_rgmii_rxin>, ++ <&syscrg JH7110_SYSCLK_STG_AXIAHB>, ++ <&syscrg JH7110_SYSCLK_APB_BUS>, ++ <&syscrg JH7110_SYSCLK_GMAC0_GTXCLK>, ++ <&rtc_osc>; ++ clock-names = "osc", "gmac0_rmii_refin", ++ "gmac0_rgmii_rxin", "stg_axiahb", ++ "apb_bus", "gmac0_gtxclk", ++ "rtc_osc"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ aongpio: pinctrl@17020000 { ++ compatible = "starfive,jh7110-aon-pinctrl"; ++ reg = <0x0 0x17020000 0x0 0x10000>; ++ resets = <&aoncrg JH7110_AONRST_IOMUX>; ++ interrupts = <85>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++}; diff --git a/target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch b/target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch new file mode 100644 index 0000000000..9c329d019f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch @@ -0,0 +1,331 @@ +From 878c16d22c0feb52c3af65139734b8bb45e349e1 Mon Sep 17 00:00:00 2001 +From: Jianlong Huang +Date: Sat, 1 Apr 2023 19:19:32 +0800 +Subject: [PATCH 022/122] riscv: dts: starfive: Add StarFive JH7110 pin + function definitions + +Add pin function definitions for StarFive JH7110 SoC. + +Tested-by: Tommaso Merciai +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Jianlong Huang +Signed-off-by: Hal Feng +Reviewed-by: Emil Renner Berthing +Signed-off-by: Conor Dooley +--- + arch/riscv/boot/dts/starfive/jh7110-pinfunc.h | 308 ++++++++++++++++++ + 1 file changed, 308 insertions(+) + create mode 100644 arch/riscv/boot/dts/starfive/jh7110-pinfunc.h + +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h +@@ -0,0 +1,308 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef __JH7110_PINFUNC_H__ ++#define __JH7110_PINFUNC_H__ ++ ++/* ++ * mux bits: ++ * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 | ++ * | din | dout | doen | function | gpio nr | ++ * ++ * dout: output signal ++ * doen: output enable signal ++ * din: optional input signal, 0xff = none ++ * function: function selector ++ * gpio nr: gpio number, 0 - 63 ++ */ ++#define GPIOMUX(n, dout, doen, din) ( \ ++ (((din) & 0xff) << 24) | \ ++ (((dout) & 0xff) << 16) | \ ++ (((doen) & 0x3f) << 10) | \ ++ ((n) & 0x3f)) ++ ++#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) & 0xff)) ++ ++/* sys_iomux dout */ ++#define GPOUT_LOW 0 ++#define GPOUT_HIGH 1 ++#define GPOUT_SYS_WAVE511_UART_TX 2 ++#define GPOUT_SYS_CAN0_STBY 3 ++#define GPOUT_SYS_CAN0_TST_NEXT_BIT 4 ++#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT 5 ++#define GPOUT_SYS_CAN0_TXD 6 ++#define GPOUT_SYS_USB_DRIVE_VBUS 7 ++#define GPOUT_SYS_QSPI_CS1 8 ++#define GPOUT_SYS_SPDIF 9 ++#define GPOUT_SYS_HDMI_CEC_SDA 10 ++#define GPOUT_SYS_HDMI_DDC_SCL 11 ++#define GPOUT_SYS_HDMI_DDC_SDA 12 ++#define GPOUT_SYS_WATCHDOG 13 ++#define GPOUT_SYS_I2C0_CLK 14 ++#define GPOUT_SYS_I2C0_DATA 15 ++#define GPOUT_SYS_SDIO0_BACK_END_POWER 16 ++#define GPOUT_SYS_SDIO0_CARD_POWER_EN 17 ++#define GPOUT_SYS_SDIO0_CCMD_OD_PULLUP_EN 18 ++#define GPOUT_SYS_SDIO0_RST 19 ++#define GPOUT_SYS_UART0_TX 20 ++#define GPOUT_SYS_HIFI4_JTAG_TDO 21 ++#define GPOUT_SYS_JTAG_TDO 22 ++#define GPOUT_SYS_PDM_MCLK 23 ++#define GPOUT_SYS_PWM_CHANNEL0 24 ++#define GPOUT_SYS_PWM_CHANNEL1 25 ++#define GPOUT_SYS_PWM_CHANNEL2 26 ++#define GPOUT_SYS_PWM_CHANNEL3 27 ++#define GPOUT_SYS_PWMDAC_LEFT 28 ++#define GPOUT_SYS_PWMDAC_RIGHT 29 ++#define GPOUT_SYS_SPI0_CLK 30 ++#define GPOUT_SYS_SPI0_FSS 31 ++#define GPOUT_SYS_SPI0_TXD 32 ++#define GPOUT_SYS_GMAC_PHYCLK 33 ++#define GPOUT_SYS_I2SRX_BCLK 34 ++#define GPOUT_SYS_I2SRX_LRCK 35 ++#define GPOUT_SYS_I2STX0_BCLK 36 ++#define GPOUT_SYS_I2STX0_LRCK 37 ++#define GPOUT_SYS_MCLK 38 ++#define GPOUT_SYS_TDM_CLK 39 ++#define GPOUT_SYS_TDM_SYNC 40 ++#define GPOUT_SYS_TDM_TXD 41 ++#define GPOUT_SYS_TRACE_DATA0 42 ++#define GPOUT_SYS_TRACE_DATA1 43 ++#define GPOUT_SYS_TRACE_DATA2 44 ++#define GPOUT_SYS_TRACE_DATA3 45 ++#define GPOUT_SYS_TRACE_REF 46 ++#define GPOUT_SYS_CAN1_STBY 47 ++#define GPOUT_SYS_CAN1_TST_NEXT_BIT 48 ++#define GPOUT_SYS_CAN1_TST_SAMPLE_POINT 49 ++#define GPOUT_SYS_CAN1_TXD 50 ++#define GPOUT_SYS_I2C1_CLK 51 ++#define GPOUT_SYS_I2C1_DATA 52 ++#define GPOUT_SYS_SDIO1_BACK_END_POWER 53 ++#define GPOUT_SYS_SDIO1_CARD_POWER_EN 54 ++#define GPOUT_SYS_SDIO1_CLK 55 ++#define GPOUT_SYS_SDIO1_CMD_OD_PULLUP_EN 56 ++#define GPOUT_SYS_SDIO1_CMD 57 ++#define GPOUT_SYS_SDIO1_DATA0 58 ++#define GPOUT_SYS_SDIO1_DATA1 59 ++#define GPOUT_SYS_SDIO1_DATA2 60 ++#define GPOUT_SYS_SDIO1_DATA3 61 ++#define GPOUT_SYS_SDIO1_DATA4 63 ++#define GPOUT_SYS_SDIO1_DATA5 63 ++#define GPOUT_SYS_SDIO1_DATA6 64 ++#define GPOUT_SYS_SDIO1_DATA7 65 ++#define GPOUT_SYS_SDIO1_RST 66 ++#define GPOUT_SYS_UART1_RTS 67 ++#define GPOUT_SYS_UART1_TX 68 ++#define GPOUT_SYS_I2STX1_SDO0 69 ++#define GPOUT_SYS_I2STX1_SDO1 70 ++#define GPOUT_SYS_I2STX1_SDO2 71 ++#define GPOUT_SYS_I2STX1_SDO3 72 ++#define GPOUT_SYS_SPI1_CLK 73 ++#define GPOUT_SYS_SPI1_FSS 74 ++#define GPOUT_SYS_SPI1_TXD 75 ++#define GPOUT_SYS_I2C2_CLK 76 ++#define GPOUT_SYS_I2C2_DATA 77 ++#define GPOUT_SYS_UART2_RTS 78 ++#define GPOUT_SYS_UART2_TX 79 ++#define GPOUT_SYS_SPI2_CLK 80 ++#define GPOUT_SYS_SPI2_FSS 81 ++#define GPOUT_SYS_SPI2_TXD 82 ++#define GPOUT_SYS_I2C3_CLK 83 ++#define GPOUT_SYS_I2C3_DATA 84 ++#define GPOUT_SYS_UART3_TX 85 ++#define GPOUT_SYS_SPI3_CLK 86 ++#define GPOUT_SYS_SPI3_FSS 87 ++#define GPOUT_SYS_SPI3_TXD 88 ++#define GPOUT_SYS_I2C4_CLK 89 ++#define GPOUT_SYS_I2C4_DATA 90 ++#define GPOUT_SYS_UART4_RTS 91 ++#define GPOUT_SYS_UART4_TX 92 ++#define GPOUT_SYS_SPI4_CLK 93 ++#define GPOUT_SYS_SPI4_FSS 94 ++#define GPOUT_SYS_SPI4_TXD 95 ++#define GPOUT_SYS_I2C5_CLK 96 ++#define GPOUT_SYS_I2C5_DATA 97 ++#define GPOUT_SYS_UART5_RTS 98 ++#define GPOUT_SYS_UART5_TX 99 ++#define GPOUT_SYS_SPI5_CLK 100 ++#define GPOUT_SYS_SPI5_FSS 101 ++#define GPOUT_SYS_SPI5_TXD 102 ++#define GPOUT_SYS_I2C6_CLK 103 ++#define GPOUT_SYS_I2C6_DATA 104 ++#define GPOUT_SYS_SPI6_CLK 105 ++#define GPOUT_SYS_SPI6_FSS 106 ++#define GPOUT_SYS_SPI6_TXD 107 ++ ++/* aon_iomux dout */ ++#define GPOUT_AON_CLK_32K_OUT 2 ++#define GPOUT_AON_PTC0_PWM4 3 ++#define GPOUT_AON_PTC0_PWM5 4 ++#define GPOUT_AON_PTC0_PWM6 5 ++#define GPOUT_AON_PTC0_PWM7 6 ++#define GPOUT_AON_CLK_GCLK0 7 ++#define GPOUT_AON_CLK_GCLK1 8 ++#define GPOUT_AON_CLK_GCLK2 9 ++ ++/* sys_iomux doen */ ++#define GPOEN_ENABLE 0 ++#define GPOEN_DISABLE 1 ++#define GPOEN_SYS_HDMI_CEC_SDA 2 ++#define GPOEN_SYS_HDMI_DDC_SCL 3 ++#define GPOEN_SYS_HDMI_DDC_SDA 4 ++#define GPOEN_SYS_I2C0_CLK 5 ++#define GPOEN_SYS_I2C0_DATA 6 ++#define GPOEN_SYS_HIFI4_JTAG_TDO 7 ++#define GPOEN_SYS_JTAG_TDO 8 ++#define GPOEN_SYS_PWM0_CHANNEL0 9 ++#define GPOEN_SYS_PWM0_CHANNEL1 10 ++#define GPOEN_SYS_PWM0_CHANNEL2 11 ++#define GPOEN_SYS_PWM0_CHANNEL3 12 ++#define GPOEN_SYS_SPI0_NSSPCTL 13 ++#define GPOEN_SYS_SPI0_NSSP 14 ++#define GPOEN_SYS_TDM_SYNC 15 ++#define GPOEN_SYS_TDM_TXD 16 ++#define GPOEN_SYS_I2C1_CLK 17 ++#define GPOEN_SYS_I2C1_DATA 18 ++#define GPOEN_SYS_SDIO1_CMD 19 ++#define GPOEN_SYS_SDIO1_DATA0 20 ++#define GPOEN_SYS_SDIO1_DATA1 21 ++#define GPOEN_SYS_SDIO1_DATA2 22 ++#define GPOEN_SYS_SDIO1_DATA3 23 ++#define GPOEN_SYS_SDIO1_DATA4 24 ++#define GPOEN_SYS_SDIO1_DATA5 25 ++#define GPOEN_SYS_SDIO1_DATA6 26 ++#define GPOEN_SYS_SDIO1_DATA7 27 ++#define GPOEN_SYS_SPI1_NSSPCTL 28 ++#define GPOEN_SYS_SPI1_NSSP 29 ++#define GPOEN_SYS_I2C2_CLK 30 ++#define GPOEN_SYS_I2C2_DATA 31 ++#define GPOEN_SYS_SPI2_NSSPCTL 32 ++#define GPOEN_SYS_SPI2_NSSP 33 ++#define GPOEN_SYS_I2C3_CLK 34 ++#define GPOEN_SYS_I2C3_DATA 35 ++#define GPOEN_SYS_SPI3_NSSPCTL 36 ++#define GPOEN_SYS_SPI3_NSSP 37 ++#define GPOEN_SYS_I2C4_CLK 38 ++#define GPOEN_SYS_I2C4_DATA 39 ++#define GPOEN_SYS_SPI4_NSSPCTL 40 ++#define GPOEN_SYS_SPI4_NSSP 41 ++#define GPOEN_SYS_I2C5_CLK 42 ++#define GPOEN_SYS_I2C5_DATA 43 ++#define GPOEN_SYS_SPI5_NSSPCTL 44 ++#define GPOEN_SYS_SPI5_NSSP 45 ++#define GPOEN_SYS_I2C6_CLK 46 ++#define GPOEN_SYS_I2C6_DATA 47 ++#define GPOEN_SYS_SPI6_NSSPCTL 48 ++#define GPOEN_SYS_SPI6_NSSP 49 ++ ++/* aon_iomux doen */ ++#define GPOEN_AON_PTC0_OE_N_4 2 ++#define GPOEN_AON_PTC0_OE_N_5 3 ++#define GPOEN_AON_PTC0_OE_N_6 4 ++#define GPOEN_AON_PTC0_OE_N_7 5 ++ ++/* sys_iomux gin */ ++#define GPI_NONE 255 ++ ++#define GPI_SYS_WAVE511_UART_RX 0 ++#define GPI_SYS_CAN0_RXD 1 ++#define GPI_SYS_USB_OVERCURRENT 2 ++#define GPI_SYS_SPDIF 3 ++#define GPI_SYS_JTAG_RST 4 ++#define GPI_SYS_HDMI_CEC_SDA 5 ++#define GPI_SYS_HDMI_DDC_SCL 6 ++#define GPI_SYS_HDMI_DDC_SDA 7 ++#define GPI_SYS_HDMI_HPD 8 ++#define GPI_SYS_I2C0_CLK 9 ++#define GPI_SYS_I2C0_DATA 10 ++#define GPI_SYS_SDIO0_CD 11 ++#define GPI_SYS_SDIO0_INT 12 ++#define GPI_SYS_SDIO0_WP 13 ++#define GPI_SYS_UART0_RX 14 ++#define GPI_SYS_HIFI4_JTAG_TCK 15 ++#define GPI_SYS_HIFI4_JTAG_TDI 16 ++#define GPI_SYS_HIFI4_JTAG_TMS 17 ++#define GPI_SYS_HIFI4_JTAG_RST 18 ++#define GPI_SYS_JTAG_TDI 19 ++#define GPI_SYS_JTAG_TMS 20 ++#define GPI_SYS_PDM_DMIC0 21 ++#define GPI_SYS_PDM_DMIC1 22 ++#define GPI_SYS_I2SRX_SDIN0 23 ++#define GPI_SYS_I2SRX_SDIN1 24 ++#define GPI_SYS_I2SRX_SDIN2 25 ++#define GPI_SYS_SPI0_CLK 26 ++#define GPI_SYS_SPI0_FSS 27 ++#define GPI_SYS_SPI0_RXD 28 ++#define GPI_SYS_JTAG_TCK 29 ++#define GPI_SYS_MCLK_EXT 30 ++#define GPI_SYS_I2SRX_BCLK 31 ++#define GPI_SYS_I2SRX_LRCK 32 ++#define GPI_SYS_I2STX0_BCLK 33 ++#define GPI_SYS_I2STX0_LRCK 34 ++#define GPI_SYS_TDM_CLK 35 ++#define GPI_SYS_TDM_RXD 36 ++#define GPI_SYS_TDM_SYNC 37 ++#define GPI_SYS_CAN1_RXD 38 ++#define GPI_SYS_I2C1_CLK 39 ++#define GPI_SYS_I2C1_DATA 40 ++#define GPI_SYS_SDIO1_CD 41 ++#define GPI_SYS_SDIO1_INT 42 ++#define GPI_SYS_SDIO1_WP 43 ++#define GPI_SYS_SDIO1_CMD 44 ++#define GPI_SYS_SDIO1_DATA0 45 ++#define GPI_SYS_SDIO1_DATA1 46 ++#define GPI_SYS_SDIO1_DATA2 47 ++#define GPI_SYS_SDIO1_DATA3 48 ++#define GPI_SYS_SDIO1_DATA4 49 ++#define GPI_SYS_SDIO1_DATA5 50 ++#define GPI_SYS_SDIO1_DATA6 51 ++#define GPI_SYS_SDIO1_DATA7 52 ++#define GPI_SYS_SDIO1_STRB 53 ++#define GPI_SYS_UART1_CTS 54 ++#define GPI_SYS_UART1_RX 55 ++#define GPI_SYS_SPI1_CLK 56 ++#define GPI_SYS_SPI1_FSS 57 ++#define GPI_SYS_SPI1_RXD 58 ++#define GPI_SYS_I2C2_CLK 59 ++#define GPI_SYS_I2C2_DATA 60 ++#define GPI_SYS_UART2_CTS 61 ++#define GPI_SYS_UART2_RX 62 ++#define GPI_SYS_SPI2_CLK 63 ++#define GPI_SYS_SPI2_FSS 64 ++#define GPI_SYS_SPI2_RXD 65 ++#define GPI_SYS_I2C3_CLK 66 ++#define GPI_SYS_I2C3_DATA 67 ++#define GPI_SYS_UART3_RX 68 ++#define GPI_SYS_SPI3_CLK 69 ++#define GPI_SYS_SPI3_FSS 70 ++#define GPI_SYS_SPI3_RXD 71 ++#define GPI_SYS_I2C4_CLK 72 ++#define GPI_SYS_I2C4_DATA 73 ++#define GPI_SYS_UART4_CTS 74 ++#define GPI_SYS_UART4_RX 75 ++#define GPI_SYS_SPI4_CLK 76 ++#define GPI_SYS_SPI4_FSS 77 ++#define GPI_SYS_SPI4_RXD 78 ++#define GPI_SYS_I2C5_CLK 79 ++#define GPI_SYS_I2C5_DATA 80 ++#define GPI_SYS_UART5_CTS 81 ++#define GPI_SYS_UART5_RX 82 ++#define GPI_SYS_SPI5_CLK 83 ++#define GPI_SYS_SPI5_FSS 84 ++#define GPI_SYS_SPI5_RXD 85 ++#define GPI_SYS_I2C6_CLK 86 ++#define GPI_SYS_I2C6_DATA 87 ++#define GPI_SYS_SPI6_CLK 88 ++#define GPI_SYS_SPI6_FSS 89 ++#define GPI_SYS_SPI6_RXD 90 ++ ++/* aon_iomux gin */ ++#define GPI_AON_PMU_GPIO_WAKEUP_0 0 ++#define GPI_AON_PMU_GPIO_WAKEUP_1 1 ++#define GPI_AON_PMU_GPIO_WAKEUP_2 2 ++#define GPI_AON_PMU_GPIO_WAKEUP_3 3 ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch b/target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch new file mode 100644 index 0000000000..9e311bf527 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch @@ -0,0 +1,290 @@ +From 76bc84c399f11c7d6a37fe68cbd5f182e4c18369 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 1 Apr 2023 19:19:33 +0800 +Subject: [PATCH 023/122] riscv: dts: starfive: Add StarFive JH7110 VisionFive + 2 board device tree + +Add a minimal device tree for StarFive JH7110 VisionFive 2 board +which has version A and version B. Support booting and basic +clock/reset/pinctrl/uart drivers. + +Tested-by: Tommaso Merciai +Reviewed-by: Conor Dooley +Acked-by: Conor Dooley +Signed-off-by: Emil Renner Berthing +Co-developed-by: Jianlong Huang +Signed-off-by: Jianlong Huang +Co-developed-by: Hal Feng +Signed-off-by: Hal Feng +Reviewed-by: Emil Renner Berthing +Signed-off-by: Conor Dooley +--- + arch/riscv/boot/dts/starfive/Makefile | 6 +- + .../jh7110-starfive-visionfive-2-v1.2a.dts | 13 ++ + .../jh7110-starfive-visionfive-2-v1.3b.dts | 13 ++ + .../jh7110-starfive-visionfive-2.dtsi | 215 ++++++++++++++++++ + 4 files changed, 246 insertions(+), 1 deletion(-) + create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts + create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts + create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi + +--- a/arch/riscv/boot/dts/starfive/Makefile ++++ b/arch/riscv/boot/dts/starfive/Makefile +@@ -1,2 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 +-dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb ++dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb ++dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb ++ ++dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb ++dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7110-starfive-visionfive-2.dtsi" ++ ++/ { ++ model = "StarFive VisionFive 2 v1.2A"; ++ compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110"; ++}; +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7110-starfive-visionfive-2.dtsi" ++ ++/ { ++ model = "StarFive VisionFive 2 v1.3B"; ++ compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110"; ++}; +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -0,0 +1,215 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7110.dtsi" ++#include "jh7110-pinfunc.h" ++#include ++ ++/ { ++ aliases { ++ i2c0 = &i2c0; ++ i2c2 = &i2c2; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ cpus { ++ timebase-frequency = <4000000>; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x0 0x40000000 0x1 0x0>; ++ }; ++ ++ gpio-restart { ++ compatible = "gpio-restart"; ++ gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>; ++ priority = <224>; ++ }; ++}; ++ ++&gmac0_rgmii_rxin { ++ clock-frequency = <125000000>; ++}; ++ ++&gmac0_rmii_refin { ++ clock-frequency = <50000000>; ++}; ++ ++&gmac1_rgmii_rxin { ++ clock-frequency = <125000000>; ++}; ++ ++&gmac1_rmii_refin { ++ clock-frequency = <50000000>; ++}; ++ ++&i2srx_bclk_ext { ++ clock-frequency = <12288000>; ++}; ++ ++&i2srx_lrck_ext { ++ clock-frequency = <192000>; ++}; ++ ++&i2stx_bclk_ext { ++ clock-frequency = <12288000>; ++}; ++ ++&i2stx_lrck_ext { ++ clock-frequency = <192000>; ++}; ++ ++&mclk_ext { ++ clock-frequency = <12288000>; ++}; ++ ++&osc { ++ clock-frequency = <24000000>; ++}; ++ ++&rtc_osc { ++ clock-frequency = <32768>; ++}; ++ ++&tdm_ext { ++ clock-frequency = <49152000>; ++}; ++ ++&i2c0 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <510>; ++ i2c-scl-falling-time-ns = <510>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <510>; ++ i2c-scl-falling-time-ns = <510>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++}; ++ ++&i2c5 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <510>; ++ i2c-scl-falling-time-ns = <510>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c5_pins>; ++ status = "okay"; ++}; ++ ++&i2c6 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <510>; ++ i2c-scl-falling-time-ns = <510>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c6_pins>; ++ status = "okay"; ++}; ++ ++&sysgpio { ++ i2c0_pins: i2c0-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ i2c2_pins: i2c2-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ i2c5_pins: i2c5-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ i2c6_pins: i2c6-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ uart0_pins: uart0-0 { ++ tx-pins { ++ pinmux = ; ++ bias-disable; ++ drive-strength = <12>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ ++ rx-pins { ++ pinmux = ; ++ bias-disable; /* external pull-up */ ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-enable; ++ slew-rate = <0>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ status = "okay"; ++}; diff --git a/target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch b/target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch new file mode 100644 index 0000000000..f823aff9a1 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch @@ -0,0 +1,43 @@ +From cbb348ddbc68fe4fc8ac80bed11c298149e7893f Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 18 Oct 2022 00:05:42 +0300 +Subject: [PATCH 024/122] riscv: dts: starfive: Add StarFive VisionFive V1 + device tree + +Add initial device tree for the StarFive VisionFive V1 SBC, which +is similar with the already supported BeagleV Starlight Beta board, +both being based on the StarFive JH7100 SoC. + +Link: https://github.com/starfive-tech/VisionFive +Signed-off-by: Cristian Ciocaltea +Reviewed-by: Conor Dooley +Reviewed-by: Matthias Brugger +Signed-off-by: Conor Dooley +--- + .../jh7100-starfive-visionfive-v1.dts | 20 +++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts + +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2021 StarFive Technology Co., Ltd. ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7100-common.dtsi" ++#include ++ ++/ { ++ model = "StarFive VisionFive V1"; ++ compatible = "starfive,visionfive-v1", "starfive,jh7100"; ++ ++ gpio-restart { ++ compatible = "gpio-restart"; ++ gpios = <&gpio 63 GPIO_ACTIVE_HIGH>; ++ priority = <224>; ++ }; ++}; diff --git a/target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch b/target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch new file mode 100644 index 0000000000..44b5836c34 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch @@ -0,0 +1,349 @@ +From 2101233d71b74e33de33e4cc292c6a8cf5da9d42 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 18 Oct 2022 00:05:41 +0300 +Subject: [PATCH 025/122] riscv: dts: starfive: Add common DT for JH7100 based + boards + +In preparation for adding initial device tree support for the StarFive +VisionFive board, which is similar with BeagleV Starlight, move most +of the content from jh7100-beaglev-starlight.dts to a new file, to be +shared between the two boards. + +Signed-off-by: Cristian Ciocaltea +Reviewed-by: Conor Dooley +Reviewed-by: Matthias Brugger +Signed-off-by: Conor Dooley +--- + .../dts/starfive/jh7100-beaglev-starlight.dts | 153 +---------------- + .../boot/dts/starfive/jh7100-common.dtsi | 161 ++++++++++++++++++ + 2 files changed, 162 insertions(+), 152 deletions(-) + create mode 100644 arch/riscv/boot/dts/starfive/jh7100-common.dtsi + +--- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts ++++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts +@@ -5,160 +5,9 @@ + */ + + /dts-v1/; +-#include "jh7100.dtsi" +-#include +-#include +-#include ++#include "jh7100-common.dtsi" + + / { + model = "BeagleV Starlight Beta"; + compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100"; +- +- aliases { +- serial0 = &uart3; +- }; +- +- chosen { +- stdout-path = "serial0:115200n8"; +- }; +- +- cpus { +- timebase-frequency = <6250000>; +- }; +- +- memory@80000000 { +- device_type = "memory"; +- reg = <0x0 0x80000000 0x2 0x0>; +- }; +- +- leds { +- compatible = "gpio-leds"; +- +- led-ack { +- gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; +- color = ; +- function = LED_FUNCTION_HEARTBEAT; +- linux,default-trigger = "heartbeat"; +- label = "ack"; +- }; +- }; +-}; +- +-&gpio { +- i2c0_pins: i2c0-0 { +- i2c-pins { +- pinmux = , +- ; +- bias-disable; /* external pull-up */ +- input-enable; +- input-schmitt-enable; +- }; +- }; +- +- i2c1_pins: i2c1-0 { +- i2c-pins { +- pinmux = , +- ; +- bias-pull-up; +- input-enable; +- input-schmitt-enable; +- }; +- }; +- +- i2c2_pins: i2c2-0 { +- i2c-pins { +- pinmux = , +- ; +- bias-disable; /* external pull-up */ +- input-enable; +- input-schmitt-enable; +- }; +- }; +- +- uart3_pins: uart3-0 { +- rx-pins { +- pinmux = ; +- bias-pull-up; +- drive-strength = <14>; +- input-enable; +- input-schmitt-enable; +- slew-rate = <0>; +- }; +- tx-pins { +- pinmux = ; +- bias-disable; +- drive-strength = <35>; +- input-disable; +- input-schmitt-disable; +- slew-rate = <0>; +- }; +- }; +-}; +- +-&i2c0 { +- clock-frequency = <100000>; +- i2c-sda-hold-time-ns = <300>; +- i2c-sda-falling-time-ns = <500>; +- i2c-scl-falling-time-ns = <500>; +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c0_pins>; +- status = "okay"; +- +- pmic@5e { +- compatible = "ti,tps65086"; +- reg = <0x5e>; +- gpio-controller; +- #gpio-cells = <2>; +- +- regulators { +- }; +- }; +-}; +- +-&i2c1 { +- clock-frequency = <400000>; +- i2c-sda-hold-time-ns = <300>; +- i2c-sda-falling-time-ns = <100>; +- i2c-scl-falling-time-ns = <100>; +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c1_pins>; +- status = "okay"; +-}; +- +-&i2c2 { +- clock-frequency = <100000>; +- i2c-sda-hold-time-ns = <300>; +- i2c-sda-falling-time-ns = <500>; +- i2c-scl-falling-time-ns = <500>; +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c2_pins>; +- status = "okay"; +-}; +- +-&osc_sys { +- clock-frequency = <25000000>; +-}; +- +-&osc_aud { +- clock-frequency = <27000000>; +-}; +- +-&uart3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart3_pins>; +- status = "okay"; + }; +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi +@@ -0,0 +1,161 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2021 StarFive Technology Co., Ltd. ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7100.dtsi" ++#include ++#include ++#include ++ ++/ { ++ aliases { ++ serial0 = &uart3; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ cpus { ++ timebase-frequency = <6250000>; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x0 0x80000000 0x2 0x0>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-ack { ++ gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; ++ color = ; ++ function = LED_FUNCTION_HEARTBEAT; ++ linux,default-trigger = "heartbeat"; ++ label = "ack"; ++ }; ++ }; ++}; ++ ++&gpio { ++ i2c0_pins: i2c0-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ i2c1_pins: i2c1-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-pull-up; ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ i2c2_pins: i2c2-0 { ++ i2c-pins { ++ pinmux = , ++ ; ++ bias-disable; /* external pull-up */ ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ uart3_pins: uart3-0 { ++ rx-pins { ++ pinmux = ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-enable; ++ slew-rate = <0>; ++ }; ++ tx-pins { ++ pinmux = ; ++ bias-disable; ++ drive-strength = <35>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <500>; ++ i2c-scl-falling-time-ns = <500>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ status = "okay"; ++ ++ pmic@5e { ++ compatible = "ti,tps65086"; ++ reg = <0x5e>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ regulators { ++ }; ++ }; ++}; ++ ++&i2c1 { ++ clock-frequency = <400000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <100>; ++ i2c-scl-falling-time-ns = <100>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <100000>; ++ i2c-sda-hold-time-ns = <300>; ++ i2c-sda-falling-time-ns = <500>; ++ i2c-scl-falling-time-ns = <500>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++}; ++ ++&osc_sys { ++ clock-frequency = <25000000>; ++}; ++ ++&osc_aud { ++ clock-frequency = <27000000>; ++}; ++ ++&uart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ status = "okay"; ++}; diff --git a/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch b/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch new file mode 100644 index 0000000000..eab4e6ee9f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch @@ -0,0 +1,303 @@ +From 28518a9637fee6b84464beff9d4308edc3efba72 Mon Sep 17 00:00:00 2001 +From: Jianlong Huang +Date: Thu, 9 Feb 2023 22:36:59 +0800 +Subject: [PATCH 026/122] dt-bindings: pinctrl: Add StarFive JH7110 sys pinctrl + +Add pinctrl bindings for StarFive JH7110 SoC sys pinctrl controller. + +Reviewed-by: Rob Herring +Signed-off-by: Jianlong Huang +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +--- + .../pinctrl/starfive,jh7110-sys-pinctrl.yaml | 142 ++++++++++++++++++ + MAINTAINERS | 6 +- + .../pinctrl/starfive,jh7110-pinctrl.h | 115 ++++++++++++++ + 3 files changed, 261 insertions(+), 2 deletions(-) + create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml + create mode 100644 include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml +@@ -0,0 +1,142 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/pinctrl/starfive,jh7110-sys-pinctrl.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 SYS Pin Controller ++ ++description: | ++ Bindings for the JH7110 RISC-V SoC from StarFive Technology Ltd. ++ ++ Out of the SoC's many pins only the ones named PAD_GPIO0 to PAD_GPIO63 ++ can be multiplexed and have configurable bias, drive strength, ++ schmitt trigger etc. ++ Some peripherals have their I/O go through the 64 "GPIOs". This also ++ includes a number of other UARTs, I2Cs, SPIs, PWMs etc. ++ All these peripherals are connected to all 64 GPIOs such that ++ any GPIO can be set up to be controlled by any of the peripherals. ++ ++maintainers: ++ - Jianlong Huang ++ ++properties: ++ compatible: ++ const: starfive,jh7110-sys-pinctrl ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ interrupt-controller: true ++ ++ '#interrupt-cells': ++ const: 2 ++ ++ gpio-controller: true ++ ++ '#gpio-cells': ++ const: 2 ++ ++patternProperties: ++ '-[0-9]+$': ++ type: object ++ additionalProperties: false ++ patternProperties: ++ '-pins$': ++ type: object ++ description: | ++ A pinctrl node should contain at least one subnode representing the ++ pinctrl groups available on the machine. Each subnode will list the ++ pins it needs, and how they should be configured, with regard to ++ muxer configuration, bias, input enable/disable, input schmitt ++ trigger enable/disable, slew-rate and drive strength. ++ allOf: ++ - $ref: /schemas/pinctrl/pincfg-node.yaml ++ - $ref: /schemas/pinctrl/pinmux-node.yaml ++ additionalProperties: false ++ ++ properties: ++ pinmux: ++ description: | ++ The list of GPIOs and their mux settings that properties in the ++ node apply to. This should be set using the GPIOMUX or PINMUX ++ macros. ++ ++ bias-disable: true ++ ++ bias-pull-up: ++ type: boolean ++ ++ bias-pull-down: ++ type: boolean ++ ++ drive-strength: ++ enum: [ 2, 4, 8, 12 ] ++ ++ input-enable: true ++ ++ input-disable: true ++ ++ input-schmitt-enable: true ++ ++ input-schmitt-disable: true ++ ++ slew-rate: ++ maximum: 1 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - interrupts ++ - interrupt-controller ++ - '#interrupt-cells' ++ - gpio-controller ++ - '#gpio-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pinctrl@13040000 { ++ compatible = "starfive,jh7110-sys-pinctrl"; ++ reg = <0x13040000 0x10000>; ++ clocks = <&syscrg 112>; ++ resets = <&syscrg 2>; ++ interrupts = <86>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ uart0-0 { ++ tx-pins { ++ pinmux = <0xff140005>; ++ bias-disable; ++ drive-strength = <12>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ ++ rx-pins { ++ pinmux = <0x0E000406>; ++ bias-pull-up; ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-enable; ++ slew-rate = <0>; ++ }; ++ }; ++ }; ++ ++... +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19658,13 +19658,15 @@ F: Documentation/devicetree/bindings/clo + F: drivers/clk/starfive/clk-starfive-jh71* + F: include/dt-bindings/clock/starfive?jh71*.h + +-STARFIVE JH7100 PINCTRL DRIVER ++STARFIVE JH71X0 PINCTRL DRIVERS + M: Emil Renner Berthing ++M: Jianlong Huang + L: linux-gpio@vger.kernel.org + S: Maintained +-F: Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml ++F: Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml + F: drivers/pinctrl/starfive/ + F: include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h ++F: include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h + + STARFIVE JH71X0 RESET CONTROLLER DRIVERS + M: Emil Renner Berthing +--- /dev/null ++++ b/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h +@@ -0,0 +1,115 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef __DT_BINDINGS_PINCTRL_STARFIVE_JH7110_H__ ++#define __DT_BINDINGS_PINCTRL_STARFIVE_JH7110_H__ ++ ++/* sys_iomux pins */ ++#define PAD_GPIO0 0 ++#define PAD_GPIO1 1 ++#define PAD_GPIO2 2 ++#define PAD_GPIO3 3 ++#define PAD_GPIO4 4 ++#define PAD_GPIO5 5 ++#define PAD_GPIO6 6 ++#define PAD_GPIO7 7 ++#define PAD_GPIO8 8 ++#define PAD_GPIO9 9 ++#define PAD_GPIO10 10 ++#define PAD_GPIO11 11 ++#define PAD_GPIO12 12 ++#define PAD_GPIO13 13 ++#define PAD_GPIO14 14 ++#define PAD_GPIO15 15 ++#define PAD_GPIO16 16 ++#define PAD_GPIO17 17 ++#define PAD_GPIO18 18 ++#define PAD_GPIO19 19 ++#define PAD_GPIO20 20 ++#define PAD_GPIO21 21 ++#define PAD_GPIO22 22 ++#define PAD_GPIO23 23 ++#define PAD_GPIO24 24 ++#define PAD_GPIO25 25 ++#define PAD_GPIO26 26 ++#define PAD_GPIO27 27 ++#define PAD_GPIO28 28 ++#define PAD_GPIO29 29 ++#define PAD_GPIO30 30 ++#define PAD_GPIO31 31 ++#define PAD_GPIO32 32 ++#define PAD_GPIO33 33 ++#define PAD_GPIO34 34 ++#define PAD_GPIO35 35 ++#define PAD_GPIO36 36 ++#define PAD_GPIO37 37 ++#define PAD_GPIO38 38 ++#define PAD_GPIO39 39 ++#define PAD_GPIO40 40 ++#define PAD_GPIO41 41 ++#define PAD_GPIO42 42 ++#define PAD_GPIO43 43 ++#define PAD_GPIO44 44 ++#define PAD_GPIO45 45 ++#define PAD_GPIO46 46 ++#define PAD_GPIO47 47 ++#define PAD_GPIO48 48 ++#define PAD_GPIO49 49 ++#define PAD_GPIO50 50 ++#define PAD_GPIO51 51 ++#define PAD_GPIO52 52 ++#define PAD_GPIO53 53 ++#define PAD_GPIO54 54 ++#define PAD_GPIO55 55 ++#define PAD_GPIO56 56 ++#define PAD_GPIO57 57 ++#define PAD_GPIO58 58 ++#define PAD_GPIO59 59 ++#define PAD_GPIO60 60 ++#define PAD_GPIO61 61 ++#define PAD_GPIO62 62 ++#define PAD_GPIO63 63 ++#define PAD_SD0_CLK 64 ++#define PAD_SD0_CMD 65 ++#define PAD_SD0_DATA0 66 ++#define PAD_SD0_DATA1 67 ++#define PAD_SD0_DATA2 68 ++#define PAD_SD0_DATA3 69 ++#define PAD_SD0_DATA4 70 ++#define PAD_SD0_DATA5 71 ++#define PAD_SD0_DATA6 72 ++#define PAD_SD0_DATA7 73 ++#define PAD_SD0_STRB 74 ++#define PAD_GMAC1_MDC 75 ++#define PAD_GMAC1_MDIO 76 ++#define PAD_GMAC1_RXD0 77 ++#define PAD_GMAC1_RXD1 78 ++#define PAD_GMAC1_RXD2 79 ++#define PAD_GMAC1_RXD3 80 ++#define PAD_GMAC1_RXDV 81 ++#define PAD_GMAC1_RXC 82 ++#define PAD_GMAC1_TXD0 83 ++#define PAD_GMAC1_TXD1 84 ++#define PAD_GMAC1_TXD2 85 ++#define PAD_GMAC1_TXD3 86 ++#define PAD_GMAC1_TXEN 87 ++#define PAD_GMAC1_TXC 88 ++#define PAD_QSPI_SCLK 89 ++#define PAD_QSPI_CS0 90 ++#define PAD_QSPI_DATA0 91 ++#define PAD_QSPI_DATA1 92 ++#define PAD_QSPI_DATA2 93 ++#define PAD_QSPI_DATA3 94 ++ ++#define GPOUT_LOW 0 ++#define GPOUT_HIGH 1 ++ ++#define GPOEN_ENABLE 0 ++#define GPOEN_DISABLE 1 ++ ++#define GPI_NONE 255 ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch b/target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch new file mode 100644 index 0000000000..8ef08efca1 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch @@ -0,0 +1,176 @@ +From 514cae455122c799638226f4358e8e6f5e155248 Mon Sep 17 00:00:00 2001 +From: Jianlong Huang +Date: Thu, 9 Feb 2023 22:37:00 +0800 +Subject: [PATCH 027/122] dt-bindings: pinctrl: Add StarFive JH7110 aon pinctrl + +Add pinctrl bindings for StarFive JH7110 SoC aon pinctrl controller. + +Reviewed-by: Rob Herring +Signed-off-by: Jianlong Huang +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +--- + .../pinctrl/starfive,jh7110-aon-pinctrl.yaml | 124 ++++++++++++++++++ + .../pinctrl/starfive,jh7110-pinctrl.h | 22 ++++ + 2 files changed, 146 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml +@@ -0,0 +1,124 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/pinctrl/starfive,jh7110-aon-pinctrl.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 AON Pin Controller ++ ++description: | ++ Bindings for the JH7110 RISC-V SoC from StarFive Technology Ltd. ++ ++ Out of the SoC's many pins only the ones named PAD_RGPIO0 to PAD_RGPIO3 ++ can be multiplexed and have configurable bias, drive strength, ++ schmitt trigger etc. ++ Some peripherals such as PWM have their I/O go through the 4 "GPIOs". ++ ++maintainers: ++ - Jianlong Huang ++ ++properties: ++ compatible: ++ const: starfive,jh7110-aon-pinctrl ++ ++ reg: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ interrupt-controller: true ++ ++ '#interrupt-cells': ++ const: 2 ++ ++ gpio-controller: true ++ ++ '#gpio-cells': ++ const: 2 ++ ++patternProperties: ++ '-[0-9]+$': ++ type: object ++ additionalProperties: false ++ patternProperties: ++ '-pins$': ++ type: object ++ description: | ++ A pinctrl node should contain at least one subnode representing the ++ pinctrl groups available on the machine. Each subnode will list the ++ pins it needs, and how they should be configured, with regard to ++ muxer configuration, bias, input enable/disable, input schmitt ++ trigger enable/disable, slew-rate and drive strength. ++ allOf: ++ - $ref: /schemas/pinctrl/pincfg-node.yaml ++ - $ref: /schemas/pinctrl/pinmux-node.yaml ++ additionalProperties: false ++ ++ properties: ++ pinmux: ++ description: | ++ The list of GPIOs and their mux settings that properties in the ++ node apply to. This should be set using the GPIOMUX macro. ++ ++ bias-disable: true ++ ++ bias-pull-up: ++ type: boolean ++ ++ bias-pull-down: ++ type: boolean ++ ++ drive-strength: ++ enum: [ 2, 4, 8, 12 ] ++ ++ input-enable: true ++ ++ input-disable: true ++ ++ input-schmitt-enable: true ++ ++ input-schmitt-disable: true ++ ++ slew-rate: ++ maximum: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - interrupt-controller ++ - '#interrupt-cells' ++ - gpio-controller ++ - '#gpio-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pinctrl@17020000 { ++ compatible = "starfive,jh7110-aon-pinctrl"; ++ reg = <0x17020000 0x10000>; ++ resets = <&aoncrg 2>; ++ interrupts = <85>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ pwm-0 { ++ pwm-pins { ++ pinmux = <0xff030802>; ++ bias-disable; ++ drive-strength = <12>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ }; ++ ++... +--- a/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h ++++ b/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h +@@ -104,6 +104,28 @@ + #define PAD_QSPI_DATA2 93 + #define PAD_QSPI_DATA3 94 + ++/* aon_iomux pins */ ++#define PAD_TESTEN 0 ++#define PAD_RGPIO0 1 ++#define PAD_RGPIO1 2 ++#define PAD_RGPIO2 3 ++#define PAD_RGPIO3 4 ++#define PAD_RSTN 5 ++#define PAD_GMAC0_MDC 6 ++#define PAD_GMAC0_MDIO 7 ++#define PAD_GMAC0_RXD0 8 ++#define PAD_GMAC0_RXD1 9 ++#define PAD_GMAC0_RXD2 10 ++#define PAD_GMAC0_RXD3 11 ++#define PAD_GMAC0_RXDV 12 ++#define PAD_GMAC0_RXC 13 ++#define PAD_GMAC0_TXD0 14 ++#define PAD_GMAC0_TXD1 15 ++#define PAD_GMAC0_TXD2 16 ++#define PAD_GMAC0_TXD3 17 ++#define PAD_GMAC0_TXEN 18 ++#define PAD_GMAC0_TXC 19 ++ + #define GPOUT_LOW 0 + #define GPOUT_HIGH 1 + diff --git a/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch b/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch new file mode 100644 index 0000000000..a9310aadc3 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch @@ -0,0 +1,1581 @@ +From 4dba3156173e59131d234d702388ee7283bac8a9 Mon Sep 17 00:00:00 2001 +From: Jianlong Huang +Date: Thu, 9 Feb 2023 22:37:01 +0800 +Subject: [PATCH 028/122] pinctrl: starfive: Add StarFive JH7110 sys controller + driver + +Add pinctrl driver for StarFive JH7110 SoC sys pinctrl controller. + +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Jianlong Huang +Signed-off-by: Hal Feng +--- + MAINTAINERS | 2 +- + drivers/pinctrl/starfive/Kconfig | 21 + + drivers/pinctrl/starfive/Makefile | 3 + + .../starfive/pinctrl-starfive-jh7110-sys.c | 449 ++++++++ + .../starfive/pinctrl-starfive-jh7110.c | 982 ++++++++++++++++++ + .../starfive/pinctrl-starfive-jh7110.h | 70 ++ + 6 files changed, 1526 insertions(+), 1 deletion(-) + create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c + create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c + create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19664,7 +19664,7 @@ M: Jianlong Huang ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "../core.h" ++#include "../pinctrl-utils.h" ++#include "../pinmux.h" ++#include "../pinconf.h" ++#include "pinctrl-starfive-jh7110.h" ++ ++#define JH7110_SYS_NGPIO 64 ++#define JH7110_SYS_GC_BASE 0 ++ ++/* registers */ ++#define JH7110_SYS_DOEN 0x000 ++#define JH7110_SYS_DOUT 0x040 ++#define JH7110_SYS_GPI 0x080 ++#define JH7110_SYS_GPIOIN 0x118 ++ ++#define JH7110_SYS_GPIOEN 0x0dc ++#define JH7110_SYS_GPIOIS0 0x0e0 ++#define JH7110_SYS_GPIOIS1 0x0e4 ++#define JH7110_SYS_GPIOIC0 0x0e8 ++#define JH7110_SYS_GPIOIC1 0x0ec ++#define JH7110_SYS_GPIOIBE0 0x0f0 ++#define JH7110_SYS_GPIOIBE1 0x0f4 ++#define JH7110_SYS_GPIOIEV0 0x0f8 ++#define JH7110_SYS_GPIOIEV1 0x0fc ++#define JH7110_SYS_GPIOIE0 0x100 ++#define JH7110_SYS_GPIOIE1 0x104 ++#define JH7110_SYS_GPIORIS0 0x108 ++#define JH7110_SYS_GPIORIS1 0x10c ++#define JH7110_SYS_GPIOMIS0 0x110 ++#define JH7110_SYS_GPIOMIS1 0x114 ++ ++#define JH7110_SYS_GPO_PDA_0_74_CFG 0x120 ++#define JH7110_SYS_GPO_PDA_89_94_CFG 0x284 ++ ++static const struct pinctrl_pin_desc jh7110_sys_pins[] = { ++ PINCTRL_PIN(PAD_GPIO0, "GPIO0"), ++ PINCTRL_PIN(PAD_GPIO1, "GPIO1"), ++ PINCTRL_PIN(PAD_GPIO2, "GPIO2"), ++ PINCTRL_PIN(PAD_GPIO3, "GPIO3"), ++ PINCTRL_PIN(PAD_GPIO4, "GPIO4"), ++ PINCTRL_PIN(PAD_GPIO5, "GPIO5"), ++ PINCTRL_PIN(PAD_GPIO6, "GPIO6"), ++ PINCTRL_PIN(PAD_GPIO7, "GPIO7"), ++ PINCTRL_PIN(PAD_GPIO8, "GPIO8"), ++ PINCTRL_PIN(PAD_GPIO9, "GPIO9"), ++ PINCTRL_PIN(PAD_GPIO10, "GPIO10"), ++ PINCTRL_PIN(PAD_GPIO11, "GPIO11"), ++ PINCTRL_PIN(PAD_GPIO12, "GPIO12"), ++ PINCTRL_PIN(PAD_GPIO13, "GPIO13"), ++ PINCTRL_PIN(PAD_GPIO14, "GPIO14"), ++ PINCTRL_PIN(PAD_GPIO15, "GPIO15"), ++ PINCTRL_PIN(PAD_GPIO16, "GPIO16"), ++ PINCTRL_PIN(PAD_GPIO17, "GPIO17"), ++ PINCTRL_PIN(PAD_GPIO18, "GPIO18"), ++ PINCTRL_PIN(PAD_GPIO19, "GPIO19"), ++ PINCTRL_PIN(PAD_GPIO20, "GPIO20"), ++ PINCTRL_PIN(PAD_GPIO21, "GPIO21"), ++ PINCTRL_PIN(PAD_GPIO22, "GPIO22"), ++ PINCTRL_PIN(PAD_GPIO23, "GPIO23"), ++ PINCTRL_PIN(PAD_GPIO24, "GPIO24"), ++ PINCTRL_PIN(PAD_GPIO25, "GPIO25"), ++ PINCTRL_PIN(PAD_GPIO26, "GPIO26"), ++ PINCTRL_PIN(PAD_GPIO27, "GPIO27"), ++ PINCTRL_PIN(PAD_GPIO28, "GPIO28"), ++ PINCTRL_PIN(PAD_GPIO29, "GPIO29"), ++ PINCTRL_PIN(PAD_GPIO30, "GPIO30"), ++ PINCTRL_PIN(PAD_GPIO31, "GPIO31"), ++ PINCTRL_PIN(PAD_GPIO32, "GPIO32"), ++ PINCTRL_PIN(PAD_GPIO33, "GPIO33"), ++ PINCTRL_PIN(PAD_GPIO34, "GPIO34"), ++ PINCTRL_PIN(PAD_GPIO35, "GPIO35"), ++ PINCTRL_PIN(PAD_GPIO36, "GPIO36"), ++ PINCTRL_PIN(PAD_GPIO37, "GPIO37"), ++ PINCTRL_PIN(PAD_GPIO38, "GPIO38"), ++ PINCTRL_PIN(PAD_GPIO39, "GPIO39"), ++ PINCTRL_PIN(PAD_GPIO40, "GPIO40"), ++ PINCTRL_PIN(PAD_GPIO41, "GPIO41"), ++ PINCTRL_PIN(PAD_GPIO42, "GPIO42"), ++ PINCTRL_PIN(PAD_GPIO43, "GPIO43"), ++ PINCTRL_PIN(PAD_GPIO44, "GPIO44"), ++ PINCTRL_PIN(PAD_GPIO45, "GPIO45"), ++ PINCTRL_PIN(PAD_GPIO46, "GPIO46"), ++ PINCTRL_PIN(PAD_GPIO47, "GPIO47"), ++ PINCTRL_PIN(PAD_GPIO48, "GPIO48"), ++ PINCTRL_PIN(PAD_GPIO49, "GPIO49"), ++ PINCTRL_PIN(PAD_GPIO50, "GPIO50"), ++ PINCTRL_PIN(PAD_GPIO51, "GPIO51"), ++ PINCTRL_PIN(PAD_GPIO52, "GPIO52"), ++ PINCTRL_PIN(PAD_GPIO53, "GPIO53"), ++ PINCTRL_PIN(PAD_GPIO54, "GPIO54"), ++ PINCTRL_PIN(PAD_GPIO55, "GPIO55"), ++ PINCTRL_PIN(PAD_GPIO56, "GPIO56"), ++ PINCTRL_PIN(PAD_GPIO57, "GPIO57"), ++ PINCTRL_PIN(PAD_GPIO58, "GPIO58"), ++ PINCTRL_PIN(PAD_GPIO59, "GPIO59"), ++ PINCTRL_PIN(PAD_GPIO60, "GPIO60"), ++ PINCTRL_PIN(PAD_GPIO61, "GPIO61"), ++ PINCTRL_PIN(PAD_GPIO62, "GPIO62"), ++ PINCTRL_PIN(PAD_GPIO63, "GPIO63"), ++ PINCTRL_PIN(PAD_SD0_CLK, "SD0_CLK"), ++ PINCTRL_PIN(PAD_SD0_CMD, "SD0_CMD"), ++ PINCTRL_PIN(PAD_SD0_DATA0, "SD0_DATA0"), ++ PINCTRL_PIN(PAD_SD0_DATA1, "SD0_DATA1"), ++ PINCTRL_PIN(PAD_SD0_DATA2, "SD0_DATA2"), ++ PINCTRL_PIN(PAD_SD0_DATA3, "SD0_DATA3"), ++ PINCTRL_PIN(PAD_SD0_DATA4, "SD0_DATA4"), ++ PINCTRL_PIN(PAD_SD0_DATA5, "SD0_DATA5"), ++ PINCTRL_PIN(PAD_SD0_DATA6, "SD0_DATA6"), ++ PINCTRL_PIN(PAD_SD0_DATA7, "SD0_DATA7"), ++ PINCTRL_PIN(PAD_SD0_STRB, "SD0_STRB"), ++ PINCTRL_PIN(PAD_GMAC1_MDC, "GMAC1_MDC"), ++ PINCTRL_PIN(PAD_GMAC1_MDIO, "GMAC1_MDIO"), ++ PINCTRL_PIN(PAD_GMAC1_RXD0, "GMAC1_RXD0"), ++ PINCTRL_PIN(PAD_GMAC1_RXD1, "GMAC1_RXD1"), ++ PINCTRL_PIN(PAD_GMAC1_RXD2, "GMAC1_RXD2"), ++ PINCTRL_PIN(PAD_GMAC1_RXD3, "GMAC1_RXD3"), ++ PINCTRL_PIN(PAD_GMAC1_RXDV, "GMAC1_RXDV"), ++ PINCTRL_PIN(PAD_GMAC1_RXC, "GMAC1_RXC"), ++ PINCTRL_PIN(PAD_GMAC1_TXD0, "GMAC1_TXD0"), ++ PINCTRL_PIN(PAD_GMAC1_TXD1, "GMAC1_TXD1"), ++ PINCTRL_PIN(PAD_GMAC1_TXD2, "GMAC1_TXD2"), ++ PINCTRL_PIN(PAD_GMAC1_TXD3, "GMAC1_TXD3"), ++ PINCTRL_PIN(PAD_GMAC1_TXEN, "GMAC1_TXEN"), ++ PINCTRL_PIN(PAD_GMAC1_TXC, "GMAC1_TXC"), ++ PINCTRL_PIN(PAD_QSPI_SCLK, "QSPI_SCLK"), ++ PINCTRL_PIN(PAD_QSPI_CS0, "QSPI_CS0"), ++ PINCTRL_PIN(PAD_QSPI_DATA0, "QSPI_DATA0"), ++ PINCTRL_PIN(PAD_QSPI_DATA1, "QSPI_DATA1"), ++ PINCTRL_PIN(PAD_QSPI_DATA2, "QSPI_DATA2"), ++ PINCTRL_PIN(PAD_QSPI_DATA3, "QSPI_DATA3"), ++}; ++ ++struct jh7110_func_sel { ++ u16 offset; ++ u8 shift; ++ u8 max; ++}; ++ ++static const struct jh7110_func_sel ++ jh7110_sys_func_sel[ARRAY_SIZE(jh7110_sys_pins)] = { ++ [PAD_GMAC1_RXC] = { 0x29c, 0, 1 }, ++ [PAD_GPIO10] = { 0x29c, 2, 3 }, ++ [PAD_GPIO11] = { 0x29c, 5, 3 }, ++ [PAD_GPIO12] = { 0x29c, 8, 3 }, ++ [PAD_GPIO13] = { 0x29c, 11, 3 }, ++ [PAD_GPIO14] = { 0x29c, 14, 3 }, ++ [PAD_GPIO15] = { 0x29c, 17, 3 }, ++ [PAD_GPIO16] = { 0x29c, 20, 3 }, ++ [PAD_GPIO17] = { 0x29c, 23, 3 }, ++ [PAD_GPIO18] = { 0x29c, 26, 3 }, ++ [PAD_GPIO19] = { 0x29c, 29, 3 }, ++ ++ [PAD_GPIO20] = { 0x2a0, 0, 3 }, ++ [PAD_GPIO21] = { 0x2a0, 3, 3 }, ++ [PAD_GPIO22] = { 0x2a0, 6, 3 }, ++ [PAD_GPIO23] = { 0x2a0, 9, 3 }, ++ [PAD_GPIO24] = { 0x2a0, 12, 3 }, ++ [PAD_GPIO25] = { 0x2a0, 15, 3 }, ++ [PAD_GPIO26] = { 0x2a0, 18, 3 }, ++ [PAD_GPIO27] = { 0x2a0, 21, 3 }, ++ [PAD_GPIO28] = { 0x2a0, 24, 3 }, ++ [PAD_GPIO29] = { 0x2a0, 27, 3 }, ++ ++ [PAD_GPIO30] = { 0x2a4, 0, 3 }, ++ [PAD_GPIO31] = { 0x2a4, 3, 3 }, ++ [PAD_GPIO32] = { 0x2a4, 6, 3 }, ++ [PAD_GPIO33] = { 0x2a4, 9, 3 }, ++ [PAD_GPIO34] = { 0x2a4, 12, 3 }, ++ [PAD_GPIO35] = { 0x2a4, 15, 3 }, ++ [PAD_GPIO36] = { 0x2a4, 17, 3 }, ++ [PAD_GPIO37] = { 0x2a4, 20, 3 }, ++ [PAD_GPIO38] = { 0x2a4, 23, 3 }, ++ [PAD_GPIO39] = { 0x2a4, 26, 3 }, ++ [PAD_GPIO40] = { 0x2a4, 29, 3 }, ++ ++ [PAD_GPIO41] = { 0x2a8, 0, 3 }, ++ [PAD_GPIO42] = { 0x2a8, 3, 3 }, ++ [PAD_GPIO43] = { 0x2a8, 6, 3 }, ++ [PAD_GPIO44] = { 0x2a8, 9, 3 }, ++ [PAD_GPIO45] = { 0x2a8, 12, 3 }, ++ [PAD_GPIO46] = { 0x2a8, 15, 3 }, ++ [PAD_GPIO47] = { 0x2a8, 18, 3 }, ++ [PAD_GPIO48] = { 0x2a8, 21, 3 }, ++ [PAD_GPIO49] = { 0x2a8, 24, 3 }, ++ [PAD_GPIO50] = { 0x2a8, 27, 3 }, ++ [PAD_GPIO51] = { 0x2a8, 30, 3 }, ++ ++ [PAD_GPIO52] = { 0x2ac, 0, 3 }, ++ [PAD_GPIO53] = { 0x2ac, 2, 3 }, ++ [PAD_GPIO54] = { 0x2ac, 4, 3 }, ++ [PAD_GPIO55] = { 0x2ac, 6, 3 }, ++ [PAD_GPIO56] = { 0x2ac, 9, 3 }, ++ [PAD_GPIO57] = { 0x2ac, 12, 3 }, ++ [PAD_GPIO58] = { 0x2ac, 15, 3 }, ++ [PAD_GPIO59] = { 0x2ac, 18, 3 }, ++ [PAD_GPIO60] = { 0x2ac, 21, 3 }, ++ [PAD_GPIO61] = { 0x2ac, 24, 3 }, ++ [PAD_GPIO62] = { 0x2ac, 27, 3 }, ++ [PAD_GPIO63] = { 0x2ac, 30, 3 }, ++ ++ [PAD_GPIO6] = { 0x2b0, 0, 3 }, ++ [PAD_GPIO7] = { 0x2b0, 2, 3 }, ++ [PAD_GPIO8] = { 0x2b0, 5, 3 }, ++ [PAD_GPIO9] = { 0x2b0, 8, 3 }, ++}; ++ ++struct jh7110_vin_group_sel { ++ u16 offset; ++ u8 shift; ++ u8 group; ++}; ++ ++static const struct jh7110_vin_group_sel ++ jh7110_sys_vin_group_sel[ARRAY_SIZE(jh7110_sys_pins)] = { ++ [PAD_GPIO6] = { 0x2b4, 21, 0 }, ++ [PAD_GPIO7] = { 0x2b4, 18, 0 }, ++ [PAD_GPIO8] = { 0x2b4, 15, 0 }, ++ [PAD_GPIO9] = { 0x2b0, 11, 0 }, ++ [PAD_GPIO10] = { 0x2b0, 20, 0 }, ++ [PAD_GPIO11] = { 0x2b0, 23, 0 }, ++ [PAD_GPIO12] = { 0x2b0, 26, 0 }, ++ [PAD_GPIO13] = { 0x2b0, 29, 0 }, ++ [PAD_GPIO14] = { 0x2b4, 0, 0 }, ++ [PAD_GPIO15] = { 0x2b4, 3, 0 }, ++ [PAD_GPIO16] = { 0x2b4, 6, 0 }, ++ [PAD_GPIO17] = { 0x2b4, 9, 0 }, ++ [PAD_GPIO18] = { 0x2b4, 12, 0 }, ++ [PAD_GPIO19] = { 0x2b0, 14, 0 }, ++ [PAD_GPIO20] = { 0x2b0, 17, 0 }, ++ ++ [PAD_GPIO21] = { 0x2b4, 21, 1 }, ++ [PAD_GPIO22] = { 0x2b4, 18, 1 }, ++ [PAD_GPIO23] = { 0x2b4, 15, 1 }, ++ [PAD_GPIO24] = { 0x2b0, 11, 1 }, ++ [PAD_GPIO25] = { 0x2b0, 20, 1 }, ++ [PAD_GPIO26] = { 0x2b0, 23, 1 }, ++ [PAD_GPIO27] = { 0x2b0, 26, 1 }, ++ [PAD_GPIO28] = { 0x2b0, 29, 1 }, ++ [PAD_GPIO29] = { 0x2b4, 0, 1 }, ++ [PAD_GPIO30] = { 0x2b4, 3, 1 }, ++ [PAD_GPIO31] = { 0x2b4, 6, 1 }, ++ [PAD_GPIO32] = { 0x2b4, 9, 1 }, ++ [PAD_GPIO33] = { 0x2b4, 12, 1 }, ++ [PAD_GPIO34] = { 0x2b0, 14, 1 }, ++ [PAD_GPIO35] = { 0x2b0, 17, 1 }, ++ ++ [PAD_GPIO36] = { 0x2b4, 21, 2 }, ++ [PAD_GPIO37] = { 0x2b4, 18, 2 }, ++ [PAD_GPIO38] = { 0x2b4, 15, 2 }, ++ [PAD_GPIO39] = { 0x2b0, 11, 2 }, ++ [PAD_GPIO40] = { 0x2b0, 20, 2 }, ++ [PAD_GPIO41] = { 0x2b0, 23, 2 }, ++ [PAD_GPIO42] = { 0x2b0, 26, 2 }, ++ [PAD_GPIO43] = { 0x2b0, 29, 2 }, ++ [PAD_GPIO44] = { 0x2b4, 0, 2 }, ++ [PAD_GPIO45] = { 0x2b4, 3, 2 }, ++ [PAD_GPIO46] = { 0x2b4, 6, 2 }, ++ [PAD_GPIO47] = { 0x2b4, 9, 2 }, ++ [PAD_GPIO48] = { 0x2b4, 12, 2 }, ++ [PAD_GPIO49] = { 0x2b0, 14, 2 }, ++ [PAD_GPIO50] = { 0x2b0, 17, 2 }, ++}; ++ ++static void jh7110_set_function(struct jh7110_pinctrl *sfp, ++ unsigned int pin, u32 func) ++{ ++ const struct jh7110_func_sel *fs = &jh7110_sys_func_sel[pin]; ++ unsigned long flags; ++ void __iomem *reg; ++ u32 mask; ++ ++ if (!fs->offset) ++ return; ++ ++ if (func > fs->max) ++ return; ++ ++ reg = sfp->base + fs->offset; ++ func = func << fs->shift; ++ mask = 0x3U << fs->shift; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ func |= readl_relaxed(reg) & ~mask; ++ writel_relaxed(func, reg); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static void jh7110_set_vin_group(struct jh7110_pinctrl *sfp, ++ unsigned int pin) ++{ ++ const struct jh7110_vin_group_sel *gs = &jh7110_sys_vin_group_sel[pin]; ++ unsigned long flags; ++ void __iomem *reg; ++ u32 mask; ++ u32 grp; ++ ++ if (!gs->offset) ++ return; ++ ++ reg = sfp->base + gs->offset; ++ grp = gs->group << gs->shift; ++ mask = 0x3U << gs->shift; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ grp |= readl_relaxed(reg) & ~mask; ++ writel_relaxed(grp, reg); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static int jh7110_sys_set_one_pin_mux(struct jh7110_pinctrl *sfp, ++ unsigned int pin, ++ unsigned int din, u32 dout, ++ u32 doen, u32 func) ++{ ++ if (pin < sfp->gc.ngpio && func == 0) ++ jh7110_set_gpiomux(sfp, pin, din, dout, doen); ++ ++ jh7110_set_function(sfp, pin, func); ++ ++ if (pin < sfp->gc.ngpio && func == 2) ++ jh7110_set_vin_group(sfp, pin); ++ ++ return 0; ++} ++ ++static int jh7110_sys_get_padcfg_base(struct jh7110_pinctrl *sfp, ++ unsigned int pin) ++{ ++ if (pin < PAD_GMAC1_MDC) ++ return JH7110_SYS_GPO_PDA_0_74_CFG; ++ else if (pin > PAD_GMAC1_TXC && pin <= PAD_QSPI_DATA3) ++ return JH7110_SYS_GPO_PDA_89_94_CFG; ++ else ++ return -1; ++} ++ ++static void jh7110_sys_irq_handler(struct irq_desc *desc) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ unsigned long mis; ++ unsigned int pin; ++ ++ chained_irq_enter(chip, desc); ++ ++ mis = readl_relaxed(sfp->base + JH7110_SYS_GPIOMIS0); ++ for_each_set_bit(pin, &mis, 32) ++ generic_handle_domain_irq(sfp->gc.irq.domain, pin); ++ ++ mis = readl_relaxed(sfp->base + JH7110_SYS_GPIOMIS1); ++ for_each_set_bit(pin, &mis, 32) ++ generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32); ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static int jh7110_sys_init_hw(struct gpio_chip *gc) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ ++ /* mask all GPIO interrupts */ ++ writel(0U, sfp->base + JH7110_SYS_GPIOIE0); ++ writel(0U, sfp->base + JH7110_SYS_GPIOIE1); ++ /* clear edge interrupt flags */ ++ writel(~0U, sfp->base + JH7110_SYS_GPIOIC0); ++ writel(~0U, sfp->base + JH7110_SYS_GPIOIC1); ++ /* enable GPIO interrupts */ ++ writel(1U, sfp->base + JH7110_SYS_GPIOEN); ++ return 0; ++} ++ ++static const struct jh7110_gpio_irq_reg jh7110_sys_irq_reg = { ++ .is_reg_base = JH7110_SYS_GPIOIS0, ++ .ic_reg_base = JH7110_SYS_GPIOIC0, ++ .ibe_reg_base = JH7110_SYS_GPIOIBE0, ++ .iev_reg_base = JH7110_SYS_GPIOIEV0, ++ .ie_reg_base = JH7110_SYS_GPIOIE0, ++ .ris_reg_base = JH7110_SYS_GPIORIS0, ++ .mis_reg_base = JH7110_SYS_GPIOMIS0, ++}; ++ ++static const struct jh7110_pinctrl_soc_info jh7110_sys_pinctrl_info = { ++ .pins = jh7110_sys_pins, ++ .npins = ARRAY_SIZE(jh7110_sys_pins), ++ .ngpios = JH7110_SYS_NGPIO, ++ .gc_base = JH7110_SYS_GC_BASE, ++ .dout_reg_base = JH7110_SYS_DOUT, ++ .dout_mask = GENMASK(6, 0), ++ .doen_reg_base = JH7110_SYS_DOEN, ++ .doen_mask = GENMASK(5, 0), ++ .gpi_reg_base = JH7110_SYS_GPI, ++ .gpi_mask = GENMASK(6, 0), ++ .gpioin_reg_base = JH7110_SYS_GPIOIN, ++ .irq_reg = &jh7110_sys_irq_reg, ++ .jh7110_set_one_pin_mux = jh7110_sys_set_one_pin_mux, ++ .jh7110_get_padcfg_base = jh7110_sys_get_padcfg_base, ++ .jh7110_gpio_irq_handler = jh7110_sys_irq_handler, ++ .jh7110_gpio_init_hw = jh7110_sys_init_hw, ++}; ++ ++static const struct of_device_id jh7110_sys_pinctrl_of_match[] = { ++ { ++ .compatible = "starfive,jh7110-sys-pinctrl", ++ .data = &jh7110_sys_pinctrl_info, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_sys_pinctrl_of_match); ++ ++static struct platform_driver jh7110_sys_pinctrl_driver = { ++ .probe = jh7110_pinctrl_probe, ++ .driver = { ++ .name = "starfive-jh7110-sys-pinctrl", ++ .of_match_table = jh7110_sys_pinctrl_of_match, ++ }, ++}; ++module_platform_driver(jh7110_sys_pinctrl_driver); ++ ++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC sys controller"); ++MODULE_AUTHOR("Emil Renner Berthing "); ++MODULE_AUTHOR("Jianlong Huang "); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c +@@ -0,0 +1,982 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Pinctrl / GPIO driver for StarFive JH7110 SoC ++ * ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../core.h" ++#include "../pinctrl-utils.h" ++#include "../pinmux.h" ++#include "../pinconf.h" ++#include "pinctrl-starfive-jh7110.h" ++ ++/* pad control bits */ ++#define JH7110_PADCFG_POS BIT(7) ++#define JH7110_PADCFG_SMT BIT(6) ++#define JH7110_PADCFG_SLEW BIT(5) ++#define JH7110_PADCFG_PD BIT(4) ++#define JH7110_PADCFG_PU BIT(3) ++#define JH7110_PADCFG_BIAS (JH7110_PADCFG_PD | JH7110_PADCFG_PU) ++#define JH7110_PADCFG_DS_MASK GENMASK(2, 1) ++#define JH7110_PADCFG_DS_2MA (0U << 1) ++#define JH7110_PADCFG_DS_4MA BIT(1) ++#define JH7110_PADCFG_DS_8MA (2U << 1) ++#define JH7110_PADCFG_DS_12MA (3U << 1) ++#define JH7110_PADCFG_IE BIT(0) ++ ++/* ++ * The packed pinmux values from the device tree look like this: ++ * ++ * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 | ++ * | din | dout | doen | function | pin | ++ */ ++static unsigned int jh7110_pinmux_din(u32 v) ++{ ++ return (v & GENMASK(31, 24)) >> 24; ++} ++ ++static u32 jh7110_pinmux_dout(u32 v) ++{ ++ return (v & GENMASK(23, 16)) >> 16; ++} ++ ++static u32 jh7110_pinmux_doen(u32 v) ++{ ++ return (v & GENMASK(15, 10)) >> 10; ++} ++ ++static u32 jh7110_pinmux_function(u32 v) ++{ ++ return (v & GENMASK(9, 8)) >> 8; ++} ++ ++static unsigned int jh7110_pinmux_pin(u32 v) ++{ ++ return v & GENMASK(7, 0); ++} ++ ++static struct jh7110_pinctrl *jh7110_from_irq_data(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ ++ return container_of(gc, struct jh7110_pinctrl, gc); ++} ++ ++struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc) ++{ ++ struct gpio_chip *gc = irq_desc_get_handler_data(desc); ++ ++ return container_of(gc, struct jh7110_pinctrl, gc); ++} ++EXPORT_SYMBOL_GPL(jh7110_from_irq_desc); ++ ++#ifdef CONFIG_DEBUG_FS ++static void jh7110_pin_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, unsigned int pin) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ ++ seq_printf(s, "%s", dev_name(pctldev->dev)); ++ ++ if (pin < sfp->gc.ngpio) { ++ unsigned int offset = 4 * (pin / 4); ++ unsigned int shift = 8 * (pin % 4); ++ u32 dout = readl_relaxed(sfp->base + info->dout_reg_base + offset); ++ u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset); ++ u32 gpi = readl_relaxed(sfp->base + info->gpi_reg_base + offset); ++ ++ dout = (dout >> shift) & info->dout_mask; ++ doen = (doen >> shift) & info->doen_mask; ++ gpi = ((gpi >> shift) - 2) & info->gpi_mask; ++ ++ seq_printf(s, " dout=%u doen=%u din=%u", dout, doen, gpi); ++ } ++} ++#else ++#define jh7110_pin_dbg_show NULL ++#endif ++ ++static int jh7110_dt_node_to_map(struct pinctrl_dev *pctldev, ++ struct device_node *np, ++ struct pinctrl_map **maps, ++ unsigned int *num_maps) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ struct device *dev = sfp->gc.parent; ++ struct device_node *child; ++ struct pinctrl_map *map; ++ const char **pgnames; ++ const char *grpname; ++ int ngroups; ++ int nmaps; ++ int ret; ++ ++ ngroups = 0; ++ for_each_child_of_node(np, child) ++ ngroups += 1; ++ nmaps = 2 * ngroups; ++ ++ pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL); ++ if (!pgnames) ++ return -ENOMEM; ++ ++ map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL); ++ if (!map) ++ return -ENOMEM; ++ ++ nmaps = 0; ++ ngroups = 0; ++ mutex_lock(&sfp->mutex); ++ for_each_child_of_node(np, child) { ++ int npins = of_property_count_u32_elems(child, "pinmux"); ++ int *pins; ++ u32 *pinmux; ++ int i; ++ ++ if (npins < 1) { ++ dev_err(dev, ++ "invalid pinctrl group %pOFn.%pOFn: pinmux not set\n", ++ np, child); ++ ret = -EINVAL; ++ goto put_child; ++ } ++ ++ grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", np, child); ++ if (!grpname) { ++ ret = -ENOMEM; ++ goto put_child; ++ } ++ ++ pgnames[ngroups++] = grpname; ++ ++ pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL); ++ if (!pins) { ++ ret = -ENOMEM; ++ goto put_child; ++ } ++ ++ pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL); ++ if (!pinmux) { ++ ret = -ENOMEM; ++ goto put_child; ++ } ++ ++ ret = of_property_read_u32_array(child, "pinmux", pinmux, npins); ++ if (ret) ++ goto put_child; ++ ++ for (i = 0; i < npins; i++) ++ pins[i] = jh7110_pinmux_pin(pinmux[i]); ++ ++ map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP; ++ map[nmaps].data.mux.function = np->name; ++ map[nmaps].data.mux.group = grpname; ++ nmaps += 1; ++ ++ ret = pinctrl_generic_add_group(pctldev, grpname, ++ pins, npins, pinmux); ++ if (ret < 0) { ++ dev_err(dev, "error adding group %s: %d\n", grpname, ret); ++ goto put_child; ++ } ++ ++ ret = pinconf_generic_parse_dt_config(child, pctldev, ++ &map[nmaps].data.configs.configs, ++ &map[nmaps].data.configs.num_configs); ++ if (ret) { ++ dev_err(dev, "error parsing pin config of group %s: %d\n", ++ grpname, ret); ++ goto put_child; ++ } ++ ++ /* don't create a map if there are no pinconf settings */ ++ if (map[nmaps].data.configs.num_configs == 0) ++ continue; ++ ++ map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; ++ map[nmaps].data.configs.group_or_pin = grpname; ++ nmaps += 1; ++ } ++ ++ ret = pinmux_generic_add_function(pctldev, np->name, ++ pgnames, ngroups, NULL); ++ if (ret < 0) { ++ dev_err(dev, "error adding function %s: %d\n", np->name, ret); ++ goto free_map; ++ } ++ mutex_unlock(&sfp->mutex); ++ ++ *maps = map; ++ *num_maps = nmaps; ++ return 0; ++ ++put_child: ++ of_node_put(child); ++free_map: ++ pinctrl_utils_free_map(pctldev, map, nmaps); ++ mutex_unlock(&sfp->mutex); ++ return ret; ++} ++ ++static const struct pinctrl_ops jh7110_pinctrl_ops = { ++ .get_groups_count = pinctrl_generic_get_group_count, ++ .get_group_name = pinctrl_generic_get_group_name, ++ .get_group_pins = pinctrl_generic_get_group_pins, ++ .pin_dbg_show = jh7110_pin_dbg_show, ++ .dt_node_to_map = jh7110_dt_node_to_map, ++ .dt_free_map = pinctrl_utils_free_map, ++}; ++ ++void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin, ++ unsigned int din, u32 dout, u32 doen) ++{ ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ ++ unsigned int offset = 4 * (pin / 4); ++ unsigned int shift = 8 * (pin % 4); ++ u32 dout_mask = info->dout_mask << shift; ++ u32 done_mask = info->doen_mask << shift; ++ u32 ival, imask; ++ void __iomem *reg_dout; ++ void __iomem *reg_doen; ++ void __iomem *reg_din; ++ unsigned long flags; ++ ++ reg_dout = sfp->base + info->dout_reg_base + offset; ++ reg_doen = sfp->base + info->doen_reg_base + offset; ++ dout <<= shift; ++ doen <<= shift; ++ if (din != GPI_NONE) { ++ unsigned int ioffset = 4 * (din / 4); ++ unsigned int ishift = 8 * (din % 4); ++ ++ reg_din = sfp->base + info->gpi_reg_base + ioffset; ++ ival = (pin + 2) << ishift; ++ imask = info->gpi_mask << ishift; ++ } else { ++ reg_din = NULL; ++ } ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ dout |= readl_relaxed(reg_dout) & ~dout_mask; ++ writel_relaxed(dout, reg_dout); ++ doen |= readl_relaxed(reg_doen) & ~done_mask; ++ writel_relaxed(doen, reg_doen); ++ if (reg_din) { ++ ival |= readl_relaxed(reg_din) & ~imask; ++ writel_relaxed(ival, reg_din); ++ } ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++EXPORT_SYMBOL_GPL(jh7110_set_gpiomux); ++ ++static int jh7110_set_mux(struct pinctrl_dev *pctldev, ++ unsigned int fsel, unsigned int gsel) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ const struct group_desc *group; ++ const u32 *pinmux; ++ unsigned int i; ++ ++ group = pinctrl_generic_get_group(pctldev, gsel); ++ if (!group) ++ return -EINVAL; ++ ++ pinmux = group->data; ++ for (i = 0; i < group->num_pins; i++) { ++ u32 v = pinmux[i]; ++ ++ if (info->jh7110_set_one_pin_mux) ++ info->jh7110_set_one_pin_mux(sfp, ++ jh7110_pinmux_pin(v), ++ jh7110_pinmux_din(v), ++ jh7110_pinmux_dout(v), ++ jh7110_pinmux_doen(v), ++ jh7110_pinmux_function(v)); ++ } ++ ++ return 0; ++} ++ ++static const struct pinmux_ops jh7110_pinmux_ops = { ++ .get_functions_count = pinmux_generic_get_function_count, ++ .get_function_name = pinmux_generic_get_function_name, ++ .get_function_groups = pinmux_generic_get_function_groups, ++ .set_mux = jh7110_set_mux, ++ .strict = true, ++}; ++ ++static const u8 jh7110_drive_strength_mA[4] = { 2, 4, 8, 12 }; ++ ++static u32 jh7110_padcfg_ds_to_mA(u32 padcfg) ++{ ++ return jh7110_drive_strength_mA[(padcfg >> 1) & 3U]; ++} ++ ++static u32 jh7110_padcfg_ds_from_mA(u32 v) ++{ ++ int i; ++ ++ for (i = 0; i < 3; i++) { ++ if (v <= jh7110_drive_strength_mA[i]) ++ break; ++ } ++ return i << 1; ++} ++ ++static void jh7110_padcfg_rmw(struct jh7110_pinctrl *sfp, ++ unsigned int pin, u32 mask, u32 value) ++{ ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ void __iomem *reg; ++ unsigned long flags; ++ int padcfg_base; ++ ++ if (!info->jh7110_get_padcfg_base) ++ return; ++ ++ padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); ++ if (padcfg_base < 0) ++ return; ++ ++ reg = sfp->base + padcfg_base + 4 * pin; ++ value &= mask; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ value |= readl_relaxed(reg) & ~mask; ++ writel_relaxed(value, reg); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static int jh7110_pinconf_get(struct pinctrl_dev *pctldev, ++ unsigned int pin, unsigned long *config) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ int param = pinconf_to_config_param(*config); ++ u32 padcfg, arg; ++ bool enabled; ++ int padcfg_base; ++ ++ if (!info->jh7110_get_padcfg_base) ++ return 0; ++ ++ padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); ++ if (padcfg_base < 0) ++ return 0; ++ ++ padcfg = readl_relaxed(sfp->base + padcfg_base + 4 * pin); ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ enabled = !(padcfg & JH7110_PADCFG_BIAS); ++ arg = 0; ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ enabled = padcfg & JH7110_PADCFG_PD; ++ arg = 1; ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ enabled = padcfg & JH7110_PADCFG_PU; ++ arg = 1; ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ enabled = true; ++ arg = jh7110_padcfg_ds_to_mA(padcfg); ++ break; ++ case PIN_CONFIG_INPUT_ENABLE: ++ enabled = padcfg & JH7110_PADCFG_IE; ++ arg = enabled; ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ enabled = padcfg & JH7110_PADCFG_SMT; ++ arg = enabled; ++ break; ++ case PIN_CONFIG_SLEW_RATE: ++ enabled = true; ++ arg = !!(padcfg & JH7110_PADCFG_SLEW); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ return enabled ? 0 : -EINVAL; ++} ++ ++static int jh7110_pinconf_group_get(struct pinctrl_dev *pctldev, ++ unsigned int gsel, ++ unsigned long *config) ++{ ++ const struct group_desc *group; ++ ++ group = pinctrl_generic_get_group(pctldev, gsel); ++ if (!group) ++ return -EINVAL; ++ ++ return jh7110_pinconf_get(pctldev, group->pins[0], config); ++} ++ ++static int jh7110_pinconf_group_set(struct pinctrl_dev *pctldev, ++ unsigned int gsel, ++ unsigned long *configs, ++ unsigned int num_configs) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ const struct group_desc *group; ++ u16 mask, value; ++ int i; ++ ++ group = pinctrl_generic_get_group(pctldev, gsel); ++ if (!group) ++ return -EINVAL; ++ ++ mask = 0; ++ value = 0; ++ for (i = 0; i < num_configs; i++) { ++ int param = pinconf_to_config_param(configs[i]); ++ u32 arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ mask |= JH7110_PADCFG_BIAS; ++ value &= ~JH7110_PADCFG_BIAS; ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ if (arg == 0) ++ return -ENOTSUPP; ++ mask |= JH7110_PADCFG_BIAS; ++ value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PD; ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ if (arg == 0) ++ return -ENOTSUPP; ++ mask |= JH7110_PADCFG_BIAS; ++ value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PU; ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ mask |= JH7110_PADCFG_DS_MASK; ++ value = (value & ~JH7110_PADCFG_DS_MASK) | ++ jh7110_padcfg_ds_from_mA(arg); ++ break; ++ case PIN_CONFIG_INPUT_ENABLE: ++ mask |= JH7110_PADCFG_IE; ++ if (arg) ++ value |= JH7110_PADCFG_IE; ++ else ++ value &= ~JH7110_PADCFG_IE; ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ mask |= JH7110_PADCFG_SMT; ++ if (arg) ++ value |= JH7110_PADCFG_SMT; ++ else ++ value &= ~JH7110_PADCFG_SMT; ++ break; ++ case PIN_CONFIG_SLEW_RATE: ++ mask |= JH7110_PADCFG_SLEW; ++ if (arg) ++ value |= JH7110_PADCFG_SLEW; ++ else ++ value &= ~JH7110_PADCFG_SLEW; ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ } ++ ++ for (i = 0; i < group->num_pins; i++) ++ jh7110_padcfg_rmw(sfp, group->pins[i], mask, value); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static void jh7110_pinconf_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, unsigned int pin) ++{ ++ struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ u32 value; ++ int padcfg_base; ++ ++ if (!info->jh7110_get_padcfg_base) ++ return; ++ ++ padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); ++ if (padcfg_base < 0) ++ return; ++ ++ value = readl_relaxed(sfp->base + padcfg_base + 4 * pin); ++ seq_printf(s, " (0x%02x)", value); ++} ++#else ++#define jh7110_pinconf_dbg_show NULL ++#endif ++ ++static const struct pinconf_ops jh7110_pinconf_ops = { ++ .pin_config_get = jh7110_pinconf_get, ++ .pin_config_group_get = jh7110_pinconf_group_get, ++ .pin_config_group_set = jh7110_pinconf_group_set, ++ .pin_config_dbg_show = jh7110_pinconf_dbg_show, ++ .is_generic = true, ++}; ++ ++static int jh7110_gpio_request(struct gpio_chip *gc, unsigned int gpio) ++{ ++ return pinctrl_gpio_request(gc->base + gpio); ++} ++ ++static void jh7110_gpio_free(struct gpio_chip *gc, unsigned int gpio) ++{ ++ pinctrl_gpio_free(gc->base + gpio); ++} ++ ++static int jh7110_gpio_get_direction(struct gpio_chip *gc, ++ unsigned int gpio) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ unsigned int offset = 4 * (gpio / 4); ++ unsigned int shift = 8 * (gpio % 4); ++ u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset); ++ ++ doen = (doen >> shift) & info->doen_mask; ++ ++ return doen == GPOEN_ENABLE ? ++ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; ++} ++ ++static int jh7110_gpio_direction_input(struct gpio_chip *gc, ++ unsigned int gpio) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ ++ /* enable input and schmitt trigger */ ++ jh7110_padcfg_rmw(sfp, gpio, ++ JH7110_PADCFG_IE | JH7110_PADCFG_SMT, ++ JH7110_PADCFG_IE | JH7110_PADCFG_SMT); ++ ++ if (info->jh7110_set_one_pin_mux) ++ info->jh7110_set_one_pin_mux(sfp, gpio, ++ GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0); ++ ++ return 0; ++} ++ ++static int jh7110_gpio_direction_output(struct gpio_chip *gc, ++ unsigned int gpio, int value) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ ++ if (info->jh7110_set_one_pin_mux) ++ info->jh7110_set_one_pin_mux(sfp, gpio, ++ GPI_NONE, value ? GPOUT_HIGH : GPOUT_LOW, ++ GPOEN_ENABLE, 0); ++ ++ /* disable input, schmitt trigger and bias */ ++ jh7110_padcfg_rmw(sfp, gpio, ++ JH7110_PADCFG_IE | JH7110_PADCFG_SMT | ++ JH7110_PADCFG_BIAS, 0); ++ return 0; ++} ++ ++static int jh7110_gpio_get(struct gpio_chip *gc, unsigned int gpio) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ void __iomem *reg = sfp->base + info->gpioin_reg_base ++ + 4 * (gpio / 32); ++ ++ return !!(readl_relaxed(reg) & BIT(gpio % 32)); ++} ++ ++static void jh7110_gpio_set(struct gpio_chip *gc, ++ unsigned int gpio, int value) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ const struct jh7110_pinctrl_soc_info *info = sfp->info; ++ unsigned int offset = 4 * (gpio / 4); ++ unsigned int shift = 8 * (gpio % 4); ++ void __iomem *reg_dout = sfp->base + info->dout_reg_base + offset; ++ u32 dout = (value ? GPOUT_HIGH : GPOUT_LOW) << shift; ++ u32 mask = info->dout_mask << shift; ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ dout |= readl_relaxed(reg_dout) & ~mask; ++ writel_relaxed(dout, reg_dout); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static int jh7110_gpio_set_config(struct gpio_chip *gc, ++ unsigned int gpio, unsigned long config) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ u32 arg = pinconf_to_config_argument(config); ++ u32 value; ++ u32 mask; ++ ++ switch (pinconf_to_config_param(config)) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ mask = JH7110_PADCFG_BIAS; ++ value = 0; ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ if (arg == 0) ++ return -ENOTSUPP; ++ mask = JH7110_PADCFG_BIAS; ++ value = JH7110_PADCFG_PD; ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ if (arg == 0) ++ return -ENOTSUPP; ++ mask = JH7110_PADCFG_BIAS; ++ value = JH7110_PADCFG_PU; ++ break; ++ case PIN_CONFIG_DRIVE_PUSH_PULL: ++ return 0; ++ case PIN_CONFIG_INPUT_ENABLE: ++ mask = JH7110_PADCFG_IE; ++ value = arg ? JH7110_PADCFG_IE : 0; ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ mask = JH7110_PADCFG_SMT; ++ value = arg ? JH7110_PADCFG_SMT : 0; ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ jh7110_padcfg_rmw(sfp, gpio, mask, value); ++ return 0; ++} ++ ++static int jh7110_gpio_add_pin_ranges(struct gpio_chip *gc) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ ++ sfp->gpios.name = sfp->gc.label; ++ sfp->gpios.base = sfp->gc.base; ++ sfp->gpios.pin_base = 0; ++ sfp->gpios.npins = sfp->gc.ngpio; ++ sfp->gpios.gc = &sfp->gc; ++ pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios); ++ return 0; ++} ++ ++static void jh7110_irq_ack(struct irq_data *d) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); ++ const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; ++ irq_hw_number_t gpio = irqd_to_hwirq(d); ++ void __iomem *ic = sfp->base + irq_reg->ic_reg_base ++ + 4 * (gpio / 32); ++ u32 mask = BIT(gpio % 32); ++ unsigned long flags; ++ u32 value; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ value = readl_relaxed(ic) & ~mask; ++ writel_relaxed(value, ic); ++ writel_relaxed(value | mask, ic); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static void jh7110_irq_mask(struct irq_data *d) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); ++ const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; ++ irq_hw_number_t gpio = irqd_to_hwirq(d); ++ void __iomem *ie = sfp->base + irq_reg->ie_reg_base ++ + 4 * (gpio / 32); ++ u32 mask = BIT(gpio % 32); ++ unsigned long flags; ++ u32 value; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ value = readl_relaxed(ie) & ~mask; ++ writel_relaxed(value, ie); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++ ++ gpiochip_disable_irq(&sfp->gc, d->hwirq); ++} ++ ++static void jh7110_irq_mask_ack(struct irq_data *d) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); ++ const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; ++ irq_hw_number_t gpio = irqd_to_hwirq(d); ++ void __iomem *ie = sfp->base + irq_reg->ie_reg_base ++ + 4 * (gpio / 32); ++ void __iomem *ic = sfp->base + irq_reg->ic_reg_base ++ + 4 * (gpio / 32); ++ u32 mask = BIT(gpio % 32); ++ unsigned long flags; ++ u32 value; ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ value = readl_relaxed(ie) & ~mask; ++ writel_relaxed(value, ie); ++ ++ value = readl_relaxed(ic) & ~mask; ++ writel_relaxed(value, ic); ++ writel_relaxed(value | mask, ic); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static void jh7110_irq_unmask(struct irq_data *d) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); ++ const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; ++ irq_hw_number_t gpio = irqd_to_hwirq(d); ++ void __iomem *ie = sfp->base + irq_reg->ie_reg_base ++ + 4 * (gpio / 32); ++ u32 mask = BIT(gpio % 32); ++ unsigned long flags; ++ u32 value; ++ ++ gpiochip_enable_irq(&sfp->gc, d->hwirq); ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ value = readl_relaxed(ie) | mask; ++ writel_relaxed(value, ie); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++} ++ ++static int jh7110_irq_set_type(struct irq_data *d, unsigned int trigger) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); ++ const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; ++ irq_hw_number_t gpio = irqd_to_hwirq(d); ++ void __iomem *base = sfp->base + 4 * (gpio / 32); ++ u32 mask = BIT(gpio % 32); ++ u32 irq_type, edge_both, polarity; ++ unsigned long flags; ++ ++ switch (trigger) { ++ case IRQ_TYPE_EDGE_RISING: ++ irq_type = mask; /* 1: edge triggered */ ++ edge_both = 0; /* 0: single edge */ ++ polarity = mask; /* 1: rising edge */ ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ irq_type = mask; /* 1: edge triggered */ ++ edge_both = 0; /* 0: single edge */ ++ polarity = 0; /* 0: falling edge */ ++ break; ++ case IRQ_TYPE_EDGE_BOTH: ++ irq_type = mask; /* 1: edge triggered */ ++ edge_both = mask; /* 1: both edges */ ++ polarity = 0; /* 0: ignored */ ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ irq_type = 0; /* 0: level triggered */ ++ edge_both = 0; /* 0: ignored */ ++ polarity = mask; /* 1: high level */ ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ irq_type = 0; /* 0: level triggered */ ++ edge_both = 0; /* 0: ignored */ ++ polarity = 0; /* 0: low level */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (trigger & IRQ_TYPE_EDGE_BOTH) ++ irq_set_handler_locked(d, handle_edge_irq); ++ else ++ irq_set_handler_locked(d, handle_level_irq); ++ ++ raw_spin_lock_irqsave(&sfp->lock, flags); ++ irq_type |= readl_relaxed(base + irq_reg->is_reg_base) & ~mask; ++ writel_relaxed(irq_type, base + irq_reg->is_reg_base); ++ ++ edge_both |= readl_relaxed(base + irq_reg->ibe_reg_base) & ~mask; ++ writel_relaxed(edge_both, base + irq_reg->ibe_reg_base); ++ ++ polarity |= readl_relaxed(base + irq_reg->iev_reg_base) & ~mask; ++ writel_relaxed(polarity, base + irq_reg->iev_reg_base); ++ raw_spin_unlock_irqrestore(&sfp->lock, flags); ++ return 0; ++} ++ ++static struct irq_chip jh7110_irq_chip = { ++ .irq_ack = jh7110_irq_ack, ++ .irq_mask = jh7110_irq_mask, ++ .irq_mask_ack = jh7110_irq_mask_ack, ++ .irq_unmask = jh7110_irq_unmask, ++ .irq_set_type = jh7110_irq_set_type, ++ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SET_TYPE_MASKED, ++ GPIOCHIP_IRQ_RESOURCE_HELPERS, ++}; ++ ++static void jh7110_disable_clock(void *data) ++{ ++ clk_disable_unprepare(data); ++} ++ ++int jh7110_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ const struct jh7110_pinctrl_soc_info *info; ++ struct jh7110_pinctrl *sfp; ++ struct pinctrl_desc *jh7110_pinctrl_desc; ++ struct reset_control *rst; ++ struct clk *clk; ++ int ret; ++ ++ info = of_device_get_match_data(&pdev->dev); ++ if (!info) ++ return -ENODEV; ++ ++ if (!info->pins || !info->npins) { ++ dev_err(dev, "wrong pinctrl info\n"); ++ return -EINVAL; ++ } ++ ++ sfp = devm_kzalloc(dev, sizeof(*sfp), GFP_KERNEL); ++ if (!sfp) ++ return -ENOMEM; ++ ++ sfp->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(sfp->base)) ++ return PTR_ERR(sfp->base); ++ ++ clk = devm_clk_get_optional(dev, NULL); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), "could not get clock\n"); ++ ++ rst = devm_reset_control_get_exclusive(dev, NULL); ++ if (IS_ERR(rst)) ++ return dev_err_probe(dev, PTR_ERR(rst), "could not get reset\n"); ++ ++ /* ++ * we don't want to assert reset and risk undoing pin muxing for the ++ * early boot serial console, but let's make sure the reset line is ++ * deasserted in case someone runs a really minimal bootloader. ++ */ ++ ret = reset_control_deassert(rst); ++ if (ret) ++ return dev_err_probe(dev, ret, "could not deassert reset\n"); ++ ++ if (clk) { ++ ret = clk_prepare_enable(clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "could not enable clock\n"); ++ ++ ret = devm_add_action_or_reset(dev, jh7110_disable_clock, clk); ++ if (ret) ++ return ret; ++ } ++ ++ jh7110_pinctrl_desc = devm_kzalloc(&pdev->dev, ++ sizeof(*jh7110_pinctrl_desc), ++ GFP_KERNEL); ++ if (!jh7110_pinctrl_desc) ++ return -ENOMEM; ++ ++ jh7110_pinctrl_desc->name = dev_name(dev); ++ jh7110_pinctrl_desc->pins = info->pins; ++ jh7110_pinctrl_desc->npins = info->npins; ++ jh7110_pinctrl_desc->pctlops = &jh7110_pinctrl_ops; ++ jh7110_pinctrl_desc->pmxops = &jh7110_pinmux_ops; ++ jh7110_pinctrl_desc->confops = &jh7110_pinconf_ops; ++ jh7110_pinctrl_desc->owner = THIS_MODULE; ++ ++ sfp->info = info; ++ sfp->dev = dev; ++ platform_set_drvdata(pdev, sfp); ++ sfp->gc.parent = dev; ++ raw_spin_lock_init(&sfp->lock); ++ mutex_init(&sfp->mutex); ++ ++ ret = devm_pinctrl_register_and_init(dev, ++ jh7110_pinctrl_desc, ++ sfp, &sfp->pctl); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "could not register pinctrl driver\n"); ++ ++ sfp->gc.label = dev_name(dev); ++ sfp->gc.owner = THIS_MODULE; ++ sfp->gc.request = jh7110_gpio_request; ++ sfp->gc.free = jh7110_gpio_free; ++ sfp->gc.get_direction = jh7110_gpio_get_direction; ++ sfp->gc.direction_input = jh7110_gpio_direction_input; ++ sfp->gc.direction_output = jh7110_gpio_direction_output; ++ sfp->gc.get = jh7110_gpio_get; ++ sfp->gc.set = jh7110_gpio_set; ++ sfp->gc.set_config = jh7110_gpio_set_config; ++ sfp->gc.add_pin_ranges = jh7110_gpio_add_pin_ranges; ++ sfp->gc.base = info->gc_base; ++ sfp->gc.ngpio = info->ngpios; ++ ++ jh7110_irq_chip.name = sfp->gc.label; ++ gpio_irq_chip_set_chip(&sfp->gc.irq, &jh7110_irq_chip); ++ sfp->gc.irq.parent_handler = info->jh7110_gpio_irq_handler; ++ sfp->gc.irq.num_parents = 1; ++ sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents, ++ sizeof(*sfp->gc.irq.parents), ++ GFP_KERNEL); ++ if (!sfp->gc.irq.parents) ++ return -ENOMEM; ++ sfp->gc.irq.default_type = IRQ_TYPE_NONE; ++ sfp->gc.irq.handler = handle_bad_irq; ++ sfp->gc.irq.init_hw = info->jh7110_gpio_init_hw; ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret < 0) ++ return ret; ++ sfp->gc.irq.parents[0] = ret; ++ ++ ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp); ++ if (ret) ++ return dev_err_probe(dev, ret, "could not register gpiochip\n"); ++ ++ irq_domain_set_pm_device(sfp->gc.irq.domain, dev); ++ ++ dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio); ++ ++ return pinctrl_enable(sfp->pctl); ++} ++EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe); ++ ++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC"); ++MODULE_AUTHOR("Emil Renner Berthing "); ++MODULE_AUTHOR("Jianlong Huang "); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h +@@ -0,0 +1,70 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Pinctrl / GPIO driver for StarFive JH7110 SoC ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef __PINCTRL_STARFIVE_JH7110_H__ ++#define __PINCTRL_STARFIVE_JH7110_H__ ++ ++#include ++#include ++ ++struct jh7110_pinctrl { ++ struct device *dev; ++ struct gpio_chip gc; ++ struct pinctrl_gpio_range gpios; ++ raw_spinlock_t lock; ++ void __iomem *base; ++ struct pinctrl_dev *pctl; ++ /* register read/write mutex */ ++ struct mutex mutex; ++ const struct jh7110_pinctrl_soc_info *info; ++}; ++ ++struct jh7110_gpio_irq_reg { ++ unsigned int is_reg_base; ++ unsigned int ic_reg_base; ++ unsigned int ibe_reg_base; ++ unsigned int iev_reg_base; ++ unsigned int ie_reg_base; ++ unsigned int ris_reg_base; ++ unsigned int mis_reg_base; ++}; ++ ++struct jh7110_pinctrl_soc_info { ++ const struct pinctrl_pin_desc *pins; ++ unsigned int npins; ++ unsigned int ngpios; ++ unsigned int gc_base; ++ ++ /* gpio dout/doen/din/gpioinput register */ ++ unsigned int dout_reg_base; ++ unsigned int dout_mask; ++ unsigned int doen_reg_base; ++ unsigned int doen_mask; ++ unsigned int gpi_reg_base; ++ unsigned int gpi_mask; ++ unsigned int gpioin_reg_base; ++ ++ const struct jh7110_gpio_irq_reg *irq_reg; ++ ++ /* generic pinmux */ ++ int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp, ++ unsigned int pin, ++ unsigned int din, u32 dout, ++ u32 doen, u32 func); ++ /* gpio chip */ ++ int (*jh7110_get_padcfg_base)(struct jh7110_pinctrl *sfp, ++ unsigned int pin); ++ void (*jh7110_gpio_irq_handler)(struct irq_desc *desc); ++ int (*jh7110_gpio_init_hw)(struct gpio_chip *gc); ++}; ++ ++void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin, ++ unsigned int din, u32 dout, u32 doen); ++int jh7110_pinctrl_probe(struct platform_device *pdev); ++struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc); ++ ++#endif /* __PINCTRL_STARFIVE_JH7110_H__ */ diff --git a/target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch b/target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch new file mode 100644 index 0000000000..54e2c7c53b --- /dev/null +++ b/target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch @@ -0,0 +1,224 @@ +From 9c1a9d6dfd6a9c28794536c8af002746a20d840f Mon Sep 17 00:00:00 2001 +From: Jianlong Huang +Date: Thu, 9 Feb 2023 22:37:02 +0800 +Subject: [PATCH 029/122] pinctrl: starfive: Add StarFive JH7110 aon controller + driver + +Add pinctrl driver for StarFive JH7110 SoC aon pinctrl controller. + +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Jianlong Huang +Signed-off-by: Hal Feng +--- + drivers/pinctrl/starfive/Kconfig | 12 ++ + drivers/pinctrl/starfive/Makefile | 1 + + .../starfive/pinctrl-starfive-jh7110-aon.c | 177 ++++++++++++++++++ + 3 files changed, 190 insertions(+) + create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c + +--- a/drivers/pinctrl/starfive/Kconfig ++++ b/drivers/pinctrl/starfive/Kconfig +@@ -37,3 +37,15 @@ config PINCTRL_STARFIVE_JH7110_SYS + This also provides an interface to the GPIO pins not used by other + peripherals supporting inputs, outputs, configuring pull-up/pull-down + and interrupts on input changes. ++ ++config PINCTRL_STARFIVE_JH7110_AON ++ tristate "Always-on pinctrl and GPIO driver for the StarFive JH7110 SoC" ++ depends on SOC_STARFIVE || COMPILE_TEST ++ depends on OF ++ select PINCTRL_STARFIVE_JH7110 ++ default SOC_STARFIVE ++ help ++ Say yes here to support always-on pin control on the StarFive JH7110 SoC. ++ This also provides an interface to the GPIO pins not used by other ++ peripherals supporting inputs, outputs, configuring pull-up/pull-down ++ and interrupts on input changes. +--- a/drivers/pinctrl/starfive/Makefile ++++ b/drivers/pinctrl/starfive/Makefile +@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH7100) += + + obj-$(CONFIG_PINCTRL_STARFIVE_JH7110) += pinctrl-starfive-jh7110.o + obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_SYS) += pinctrl-starfive-jh7110-sys.o ++obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_AON) += pinctrl-starfive-jh7110-aon.o +--- /dev/null ++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Pinctrl / GPIO driver for StarFive JH7110 SoC aon controller ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../core.h" ++#include "../pinconf.h" ++#include "../pinmux.h" ++#include "pinctrl-starfive-jh7110.h" ++ ++#define JH7110_AON_NGPIO 4 ++#define JH7110_AON_GC_BASE 64 ++ ++/* registers */ ++#define JH7110_AON_DOEN 0x0 ++#define JH7110_AON_DOUT 0x4 ++#define JH7110_AON_GPI 0x8 ++#define JH7110_AON_GPIOIN 0x2c ++ ++#define JH7110_AON_GPIOEN 0xc ++#define JH7110_AON_GPIOIS 0x10 ++#define JH7110_AON_GPIOIC 0x14 ++#define JH7110_AON_GPIOIBE 0x18 ++#define JH7110_AON_GPIOIEV 0x1c ++#define JH7110_AON_GPIOIE 0x20 ++#define JH7110_AON_GPIORIS 0x28 ++#define JH7110_AON_GPIOMIS 0x28 ++ ++#define JH7110_AON_GPO_PDA_0_5_CFG 0x30 ++ ++static const struct pinctrl_pin_desc jh7110_aon_pins[] = { ++ PINCTRL_PIN(PAD_TESTEN, "TESTEN"), ++ PINCTRL_PIN(PAD_RGPIO0, "RGPIO0"), ++ PINCTRL_PIN(PAD_RGPIO1, "RGPIO1"), ++ PINCTRL_PIN(PAD_RGPIO2, "RGPIO2"), ++ PINCTRL_PIN(PAD_RGPIO3, "RGPIO3"), ++ PINCTRL_PIN(PAD_RSTN, "RSTN"), ++ PINCTRL_PIN(PAD_GMAC0_MDC, "GMAC0_MDC"), ++ PINCTRL_PIN(PAD_GMAC0_MDIO, "GMAC0_MDIO"), ++ PINCTRL_PIN(PAD_GMAC0_RXD0, "GMAC0_RXD0"), ++ PINCTRL_PIN(PAD_GMAC0_RXD1, "GMAC0_RXD1"), ++ PINCTRL_PIN(PAD_GMAC0_RXD2, "GMAC0_RXD2"), ++ PINCTRL_PIN(PAD_GMAC0_RXD3, "GMAC0_RXD3"), ++ PINCTRL_PIN(PAD_GMAC0_RXDV, "GMAC0_RXDV"), ++ PINCTRL_PIN(PAD_GMAC0_RXC, "GMAC0_RXC"), ++ PINCTRL_PIN(PAD_GMAC0_TXD0, "GMAC0_TXD0"), ++ PINCTRL_PIN(PAD_GMAC0_TXD1, "GMAC0_TXD1"), ++ PINCTRL_PIN(PAD_GMAC0_TXD2, "GMAC0_TXD2"), ++ PINCTRL_PIN(PAD_GMAC0_TXD3, "GMAC0_TXD3"), ++ PINCTRL_PIN(PAD_GMAC0_TXEN, "GMAC0_TXEN"), ++ PINCTRL_PIN(PAD_GMAC0_TXC, "GMAC0_TXC"), ++}; ++ ++static int jh7110_aon_set_one_pin_mux(struct jh7110_pinctrl *sfp, ++ unsigned int pin, ++ unsigned int din, u32 dout, ++ u32 doen, u32 func) ++{ ++ if (pin < sfp->gc.ngpio && func == 0) ++ jh7110_set_gpiomux(sfp, pin, din, dout, doen); ++ ++ return 0; ++} ++ ++static int jh7110_aon_get_padcfg_base(struct jh7110_pinctrl *sfp, ++ unsigned int pin) ++{ ++ if (pin < PAD_GMAC0_MDC) ++ return JH7110_AON_GPO_PDA_0_5_CFG; ++ ++ return -1; ++} ++ ++static void jh7110_aon_irq_handler(struct irq_desc *desc) ++{ ++ struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ unsigned long mis; ++ unsigned int pin; ++ ++ chained_irq_enter(chip, desc); ++ ++ mis = readl_relaxed(sfp->base + JH7110_AON_GPIOMIS); ++ for_each_set_bit(pin, &mis, JH7110_AON_NGPIO) ++ generic_handle_domain_irq(sfp->gc.irq.domain, pin); ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static int jh7110_aon_init_hw(struct gpio_chip *gc) ++{ ++ struct jh7110_pinctrl *sfp = container_of(gc, ++ struct jh7110_pinctrl, gc); ++ ++ /* mask all GPIO interrupts */ ++ writel_relaxed(0, sfp->base + JH7110_AON_GPIOIE); ++ /* clear edge interrupt flags */ ++ writel_relaxed(0, sfp->base + JH7110_AON_GPIOIC); ++ writel_relaxed(0x0f, sfp->base + JH7110_AON_GPIOIC); ++ /* enable GPIO interrupts */ ++ writel_relaxed(1, sfp->base + JH7110_AON_GPIOEN); ++ return 0; ++} ++ ++static const struct jh7110_gpio_irq_reg jh7110_aon_irq_reg = { ++ .is_reg_base = JH7110_AON_GPIOIS, ++ .ic_reg_base = JH7110_AON_GPIOIC, ++ .ibe_reg_base = JH7110_AON_GPIOIBE, ++ .iev_reg_base = JH7110_AON_GPIOIEV, ++ .ie_reg_base = JH7110_AON_GPIOIE, ++ .ris_reg_base = JH7110_AON_GPIORIS, ++ .mis_reg_base = JH7110_AON_GPIOMIS, ++}; ++ ++static const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = { ++ .pins = jh7110_aon_pins, ++ .npins = ARRAY_SIZE(jh7110_aon_pins), ++ .ngpios = JH7110_AON_NGPIO, ++ .gc_base = JH7110_AON_GC_BASE, ++ .dout_reg_base = JH7110_AON_DOUT, ++ .dout_mask = GENMASK(3, 0), ++ .doen_reg_base = JH7110_AON_DOEN, ++ .doen_mask = GENMASK(2, 0), ++ .gpi_reg_base = JH7110_AON_GPI, ++ .gpi_mask = GENMASK(3, 0), ++ .gpioin_reg_base = JH7110_AON_GPIOIN, ++ .irq_reg = &jh7110_aon_irq_reg, ++ .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, ++ .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, ++ .jh7110_gpio_irq_handler = jh7110_aon_irq_handler, ++ .jh7110_gpio_init_hw = jh7110_aon_init_hw, ++}; ++ ++static const struct of_device_id jh7110_aon_pinctrl_of_match[] = { ++ { ++ .compatible = "starfive,jh7110-aon-pinctrl", ++ .data = &jh7110_aon_pinctrl_info, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_aon_pinctrl_of_match); ++ ++static struct platform_driver jh7110_aon_pinctrl_driver = { ++ .probe = jh7110_pinctrl_probe, ++ .driver = { ++ .name = "starfive-jh7110-aon-pinctrl", ++ .of_match_table = jh7110_aon_pinctrl_of_match, ++ }, ++}; ++module_platform_driver(jh7110_aon_pinctrl_driver); ++ ++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC aon controller"); ++MODULE_AUTHOR("Jianlong Huang "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch b/target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch new file mode 100644 index 0000000000..6c6afb853d --- /dev/null +++ b/target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch @@ -0,0 +1,228 @@ +From 537ee9e5bb7b4ebee4ad5a607098c8200af6c261 Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Thu, 18 May 2023 19:27:28 -0700 +Subject: [PATCH 030/122] config: add jh7110 defconfig for test mini + +add jh7110 defconfig for test mini + +Signed-off-by: shanlong.li +--- + arch/riscv/configs/jh7110_defconfig | 212 ++++++++++++++++++++++++++++ + 1 file changed, 212 insertions(+) + create mode 100755 arch/riscv/configs/jh7110_defconfig + +--- /dev/null ++++ b/arch/riscv/configs/jh7110_defconfig +@@ -0,0 +1,212 @@ ++CONFIG_WERROR=y ++CONFIG_SYSVIPC=y ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_PSI=y ++# CONFIG_CPU_ISOLATION is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_CGROUPS=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_NAMESPACES=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_EXPERT=y ++# CONFIG_SYSFS_SYSCALL is not set ++CONFIG_KCMP=y ++CONFIG_PERF_EVENTS=y ++CONFIG_ARCH_STARFIVE=y ++CONFIG_SOC_STARFIVE=y ++CONFIG_ERRATA_SIFIVE=y ++CONFIG_SMP=y ++# CONFIG_RISCV_ISA_SVPBMT is not set ++# CONFIG_COMPAT is not set ++CONFIG_CPU_IDLE=y ++CONFIG_RISCV_SBI_CPUIDLE=y ++CONFIG_JUMP_LABEL=y ++# CONFIG_STACKPROTECTOR is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_COMPRESS_ZSTD=y ++# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set ++CONFIG_BLK_WBT=y ++# CONFIG_BLK_DEBUG_FS is not set ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_MQ_IOSCHED_DEADLINE is not set ++# CONFIG_MQ_IOSCHED_KYBER is not set ++CONFIG_IOSCHED_BFQ=y ++CONFIG_KSM=y ++# CONFIG_VM_EVENT_COUNTERS is not set ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_INET_DIAG=m ++# CONFIG_IPV6_SIT is not set ++CONFIG_IPV6_MULTIPLE_TABLES=y ++# CONFIG_WIRELESS is not set ++# CONFIG_ETHTOOL_NETLINK is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++# CONFIG_STANDALONE is not set ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++# CONFIG_FW_LOADER is not set ++CONFIG_EFI_DISABLE_RUNTIME=y ++CONFIG_ZRAM=y ++CONFIG_ZRAM_MEMORY_TRACKING=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=1 ++CONFIG_NETDEVICES=y ++CONFIG_STMMAC_ETH=y ++CONFIG_DWMAC_DWC_QOS_ETH=y ++# CONFIG_DWMAC_GENERIC is not set ++CONFIG_DWMAC_STARFIVE=y ++CONFIG_MICROCHIP_PHY=y ++CONFIG_MOTORCOMM_PHY=y ++# CONFIG_WLAN is not set ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_SERIO is not set ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_LDISC_AUTOLOAD is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++# CONFIG_SERIAL_8250_16550A_VARIANTS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_DW=y ++CONFIG_SERIAL_OF_PLATFORM=y ++# CONFIG_DEVMEM is not set ++# CONFIG_RANDOM_TRUST_BOOTLOADER is not set ++CONFIG_I2C=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_HELPER_AUTO is not set ++CONFIG_I2C_DESIGNWARE_PLATFORM=y ++# CONFIG_PTP_1588_CLOCK is not set ++CONFIG_PINCTRL_STARFIVE_JH7110=y ++CONFIG_GPIOLIB_FASTPATH_LIMIT=128 ++CONFIG_GPIO_SYSFS=y ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO_RESTART=y ++CONFIG_SENSORS_SFCTEMP=y ++# CONFIG_HID is not set ++CONFIG_MMC=y ++# CONFIG_PWRSEQ_EMMC is not set ++# CONFIG_PWRSEQ_SIMPLE is not set ++CONFIG_MMC_DW=y ++# CONFIG_VIRTIO_MENU is not set ++CONFIG_CLK_STARFIVE_JH7110_AON=y ++# CONFIG_VHOST_MENU is not set ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_BTRFS_FS=y ++CONFIG_BTRFS_FS_POSIX_ACL=y ++# CONFIG_DNOTIFY is not set ++CONFIG_FANOTIFY=y ++CONFIG_AUTOFS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15" ++CONFIG_FAT_DEFAULT_UTF8=y ++CONFIG_PROC_KCORE=y ++CONFIG_PROC_CHILDREN=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_EFIVAR_FS=y ++# CONFIG_MISC_FILESYSTEMS is not set ++# CONFIG_NETWORK_FILESYSTEMS is not set ++CONFIG_NLS_DEFAULT="iso8859-15" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_15=y ++CONFIG_LSM="" ++CONFIG_CRYPTO_ZSTD=y ++# CONFIG_RAID6_PQ_BENCHMARK is not set ++# CONFIG_DEBUG_MISC is not set ++CONFIG_STRIP_ASM_SYMS=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_SLUB_DEBUG is not set ++CONFIG_PAGE_TABLE_CHECK=y ++CONFIG_DEBUG_RODATA_TEST=y ++CONFIG_DEBUG_WX=y ++CONFIG_SOFTLOCKUP_DETECTOR=y ++CONFIG_WQ_WATCHDOG=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_STACKTRACE=y ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_FTRACE is not set ++# CONFIG_RUNTIME_TESTING_MENU is not set ++CONFIG_EXT4_FS=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPU_FREQ=y ++CONFIG_HIBERNATION=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_SWAP=y ++CONFIG_PCIE_STARFIVE=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI=y ++CONFIG_USB_CDNS3_STARFIVE=y ++CONFIG_PHY_STARFIVE_JH7110_PCIE=y ++CONFIG_PHY_STARFIVE_JH7110_USB=y ++CONFIG_USB_CDNS_SUPPORT=y ++CONFIG_USB_CDNS3=y ++CONFIG_USB=y ++CONFIG_USB_SUPPORT=y ++CONFIG_VIDEO_STARFIVE_CAMSS=y ++CONFIG_VIDEO_CADENCE_CSI2RX=y ++CONFIG_VIDEO_DEV=y ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_MEDIA_PLATFORM_DRIVERS=y ++CONFIG_MEDIA_PLATFORM_SUPPORT=y ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_PHY_STARFIVE_DPHY_RX=y ++CONFIG_CRYPTO_DEV_JH7110=y ++CONFIG_CRYPTO_HW=y ++CONFIG_CRYPTO=y ++CONFIG_SND_SOC_JH7110_TDM=y ++CONFIG_SND_SOC_STARFIVE=y ++CONFIG_SND_SOC=y ++CONFIG_SND=y ++CONFIG_SOUND=y ++CONFIG_DW_AXI_DMAC=y ++CONFIG_DMADEVICES=y ++CONFIG_HAS_IOMEM=y ++CONFIG_PWM_STARFIVE_PTC=y ++CONFIG_PWM=y ++CONFIG_STARFIVE_TIMER=y ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_STARFIVE_WATCHDOG=y ++CONFIG_WATCHDOG=y ++CONFIG_HW_RANDOM_JH7110=y ++CONFIG_HW_RANDOM=y ++CONFIG_STMMAC_PLATFORM=y ++CONFIG_SPI_CADENCE_QUADSPI=y ++CONFIG_SPI_MASTER=y ++CONFIG_SPI=y ++CONFIG_MMC_DW_STARFIVE=y ++CONFIG_CLK_STARFIVE_JH7110_PLL=y ++CONFIG_CLK_STARFIVE_JH7110_VOUT=y ++CONFIG_CLK_STARFIVE_JH7110_ISP=y ++CONFIG_CLK_STARFIVE_JH7110_STG=y ++CONFIG_JH71XX_PMU=y ++CONFIG_PM=y ++CONFIG_PINCTRL_STARFIVE_JH7110_AON=y ++CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y ++CONFIG_CLK_STARFIVE_JH7110_AON=y ++CONFIG_CLK_STARFIVE_JH7110_SYS=y ++CONFIG_SIFIVE_CCACHE=y ++CONFIG_CLINT_TIMER=y ++CONFIG_SIFIVE_PLIC=y diff --git a/target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch b/target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch new file mode 100644 index 0000000000..74eb4b2f18 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch @@ -0,0 +1,80 @@ +From 07f62b08668c0295b1c6342f9708b7e36093ff59 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 21 Feb 2023 17:13:48 +0800 +Subject: [PATCH 031/122] dt-bindings: clock: Add StarFive JH7110 PLL clock + generator + +Add bindings for the PLL clock generator on the JH7110 RISC-V SoC. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Xingyu Wu +--- + .../bindings/clock/starfive,jh7110-pll.yaml | 46 +++++++++++++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 6 +++ + 2 files changed, 52 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml +@@ -0,0 +1,46 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-pll.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 PLL Clock Generator ++ ++description: ++ This PLL are high speed, low jitter frequency synthesizers in JH7110. ++ Each PLL clocks work in integer mode or fraction mode by some dividers, ++ and the configuration registers and dividers are set in several syscon ++ registers. So pll node should be a child of SYS-SYSCON node. ++ The formula for calculating frequency is that, ++ Fvco = Fref * (NI + NF) / M / Q1 ++ ++maintainers: ++ - Xingyu Wu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-pll ++ ++ clocks: ++ maxItems: 1 ++ description: Main Oscillator (24 MHz) ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++required: ++ - compatible ++ - clocks ++ - '#clock-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pll-clock-controller { ++ compatible = "starfive,jh7110-pll"; ++ clocks = <&osc>; ++ #clock-cells = <1>; ++ }; +--- a/include/dt-bindings/clock/starfive,jh7110-crg.h ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -6,6 +6,12 @@ + #ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ + #define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ + ++/* PLL clocks */ ++#define JH7110_CLK_PLL0_OUT 0 ++#define JH7110_CLK_PLL1_OUT 1 ++#define JH7110_CLK_PLL2_OUT 2 ++#define JH7110_PLLCLK_END 3 ++ + /* SYSCRG clocks */ + #define JH7110_SYSCLK_CPU_ROOT 0 + #define JH7110_SYSCLK_CPU_CORE 1 diff --git a/target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch b/target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch new file mode 100644 index 0000000000..711e0775cc --- /dev/null +++ b/target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch @@ -0,0 +1,786 @@ +From 0bc7aa28dcdee75a52b1874a02dfbf0107c2d448 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Fri, 17 Feb 2023 17:30:09 +0800 +Subject: [PATCH 032/122] clk: starfive: Add StarFive JH7110 PLL clock driver + +Add driver for the StarFive JH7110 PLL clock controller +and they work by reading and setting syscon registers. + +Signed-off-by: Xingyu Wu +--- + MAINTAINERS | 6 + + drivers/clk/starfive/Kconfig | 8 + + drivers/clk/starfive/Makefile | 1 + + .../clk/starfive/clk-starfive-jh7110-pll.c | 427 ++++++++++++++++++ + .../clk/starfive/clk-starfive-jh7110-pll.h | 293 ++++++++++++ + 5 files changed, 735 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-pll.c + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-pll.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19650,6 +19650,12 @@ M: Emil Renner Berthing ++S: Supported ++F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml ++F: drivers/clk/starfive/clk-starfive-jh7110-pll.* ++ + STARFIVE JH71X0 CLOCK DRIVERS + M: Emil Renner Berthing + M: Hal Feng +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -21,6 +21,14 @@ config CLK_STARFIVE_JH7100_AUDIO + Say Y or M here to support the audio clocks on the StarFive JH7100 + SoC. + ++config CLK_STARFIVE_JH7110_PLL ++ bool "StarFive JH7110 PLL clock support" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ default ARCH_STARFIVE ++ help ++ Say yes here to support the PLL clock controller on the ++ StarFive JH7110 SoC. ++ + config CLK_STARFIVE_JH7110_SYS + bool "StarFive JH7110 system clock support" + depends on ARCH_STARFIVE || COMPILE_TEST +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -4,5 +4,6 @@ obj-$(CONFIG_CLK_STARFIVE_JH71X0) += clk + obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk-starfive-jh7100.o + obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) += clk-starfive-jh7100-audio.o + ++obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL) += clk-starfive-jh7110-pll.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += clk-starfive-jh7110-sys.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_AON) += clk-starfive-jh7110-aon.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.c +@@ -0,0 +1,427 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 PLL Clock Generator Driver ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * This driver is about to register JH7110 PLL clock generator and support ops. ++ * The JH7110 have three PLL clock, PLL0, PLL1 and PLL2. ++ * Each PLL clocks work in integer mode or fraction mode by some dividers, ++ * and the configuration registers and dividers are set in several syscon registers. ++ * The formula for calculating frequency is: ++ * Fvco = Fref * (NI + NF) / M / Q1 ++ * Fref: OSC source clock rate ++ * NI: integer frequency dividing ratio of feedback divider, set by fbdiv[11:0]. ++ * NF: fractional frequency dividing ratio, set by frac[23:0]. NF = frac[23:0] / 2^24 = 0 ~ 0.999. ++ * M: frequency dividing ratio of pre-divider, set by prediv[5:0]. ++ * Q1: frequency dividing ratio of post divider, set by postdiv1[1:0], Q1= 1,2,4,8. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110-pll.h" ++ ++static struct jh7110_clk_pll_data *jh7110_pll_data_from(struct clk_hw *hw) ++{ ++ return container_of(hw, struct jh7110_clk_pll_data, hw); ++} ++ ++static struct jh7110_clk_pll_priv *jh7110_pll_priv_from(struct jh7110_clk_pll_data *data) ++{ ++ return container_of(data, struct jh7110_clk_pll_priv, data[data->idx]); ++} ++ ++/* Read register value from syscon and calculate PLL(x) frequency */ ++static unsigned long jh7110_pll_get_freq(struct jh7110_clk_pll_data *data, ++ unsigned long parent_rate) ++{ ++ struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data); ++ struct jh7110_pll_syscon_offset *offset = &data->offset; ++ struct jh7110_pll_syscon_mask *mask = &data->mask; ++ struct jh7110_pll_syscon_shift *shift = &data->shift; ++ unsigned long freq = 0; ++ unsigned long frac_cal; ++ u32 dacpd; ++ u32 dsmpd; ++ u32 fbdiv; ++ u32 prediv; ++ u32 postdiv1; ++ u32 frac; ++ u32 reg_val; ++ ++ if (regmap_read(priv->syscon_regmap, offset->dacpd, ®_val)) ++ goto read_error; ++ dacpd = (reg_val & mask->dacpd) >> shift->dacpd; ++ ++ if (regmap_read(priv->syscon_regmap, offset->dsmpd, ®_val)) ++ goto read_error; ++ dsmpd = (reg_val & mask->dsmpd) >> shift->dsmpd; ++ ++ if (regmap_read(priv->syscon_regmap, offset->fbdiv, ®_val)) ++ goto read_error; ++ fbdiv = (reg_val & mask->fbdiv) >> shift->fbdiv; ++ /* fbdiv value should be 8 to 4095 */ ++ if (fbdiv < 8) ++ goto read_error; ++ ++ if (regmap_read(priv->syscon_regmap, offset->prediv, ®_val)) ++ goto read_error; ++ prediv = (reg_val & mask->prediv) >> shift->prediv; ++ ++ if (regmap_read(priv->syscon_regmap, offset->postdiv1, ®_val)) ++ goto read_error; ++ /* postdiv1 = 2 ^ reg_val */ ++ postdiv1 = 1 << ((reg_val & mask->postdiv1) >> shift->postdiv1); ++ ++ if (regmap_read(priv->syscon_regmap, offset->frac, ®_val)) ++ goto read_error; ++ frac = (reg_val & mask->frac) >> shift->frac; ++ ++ /* ++ * Integer Mode (Both 1) or Fraction Mode (Both 0). ++ * And the decimal places are counted by expanding them by ++ * a factor of STARFIVE_PLL_FRAC_PATR_SIZE. ++ */ ++ if (dacpd == 1 && dsmpd == 1) ++ frac_cal = 0; ++ else if (dacpd == 0 && dsmpd == 0) ++ frac_cal = (unsigned long)frac * STARFIVE_PLL_FRAC_PATR_SIZE / (1 << 24); ++ else ++ goto read_error; ++ ++ /* Fvco = Fref * (NI + NF) / M / Q1 */ ++ freq = parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE * ++ (fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1; ++ ++read_error: ++ return freq; ++} ++ ++static unsigned long jh7110_pll_rate_sub_fabs(unsigned long rate1, unsigned long rate2) ++{ ++ return rate1 > rate2 ? (rate1 - rate2) : (rate2 - rate1); ++} ++ ++/* Select the appropriate frequency from the already configured registers value */ ++static void jh7110_pll_select_near_freq_id(struct jh7110_clk_pll_data *data, ++ unsigned long rate) ++{ ++ const struct starfive_pll_syscon_value *syscon_val; ++ unsigned int id; ++ unsigned int pll_arry_size; ++ unsigned long rate_diff; ++ ++ if (data->idx == JH7110_CLK_PLL0_OUT) ++ pll_arry_size = ARRAY_SIZE(jh7110_pll0_syscon_freq); ++ else if (data->idx == JH7110_CLK_PLL1_OUT) ++ pll_arry_size = ARRAY_SIZE(jh7110_pll1_syscon_freq); ++ else ++ pll_arry_size = ARRAY_SIZE(jh7110_pll2_syscon_freq); ++ ++ /* compare the frequency one by one from small to large in order */ ++ for (id = 0; id < pll_arry_size; id++) { ++ if (data->idx == JH7110_CLK_PLL0_OUT) ++ syscon_val = &jh7110_pll0_syscon_freq[id]; ++ else if (data->idx == JH7110_CLK_PLL1_OUT) ++ syscon_val = &jh7110_pll1_syscon_freq[id]; ++ else ++ syscon_val = &jh7110_pll2_syscon_freq[id]; ++ ++ if (rate == syscon_val->freq) ++ goto match_end; ++ ++ /* select near frequency */ ++ if (rate < syscon_val->freq) { ++ /* The last frequency is closer to the target rate than this time. */ ++ if (id > 0) ++ if (rate_diff < jh7110_pll_rate_sub_fabs(rate, syscon_val->freq)) ++ id--; ++ ++ goto match_end; ++ } else { ++ rate_diff = jh7110_pll_rate_sub_fabs(rate, syscon_val->freq); ++ } ++ } ++ ++match_end: ++ data->freq_select_idx = id; ++} ++ ++static int jh7110_pll_set_freq_syscon(struct jh7110_clk_pll_data *data) ++{ ++ struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data); ++ struct jh7110_pll_syscon_offset *offset = &data->offset; ++ struct jh7110_pll_syscon_mask *mask = &data->mask; ++ struct jh7110_pll_syscon_shift *shift = &data->shift; ++ unsigned int freq_idx = data->freq_select_idx; ++ const struct starfive_pll_syscon_value *syscon_val; ++ int ret; ++ ++ if (data->idx == JH7110_CLK_PLL0_OUT) ++ syscon_val = &jh7110_pll0_syscon_freq[freq_idx]; ++ else if (data->idx == JH7110_CLK_PLL1_OUT) ++ syscon_val = &jh7110_pll1_syscon_freq[freq_idx]; ++ else ++ syscon_val = &jh7110_pll2_syscon_freq[freq_idx]; ++ ++ ret = regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd, ++ (syscon_val->dacpd << shift->dacpd)); ++ if (ret) ++ goto set_failed; ++ ++ ret = regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd, ++ (syscon_val->dsmpd << shift->dsmpd)); ++ if (ret) ++ goto set_failed; ++ ++ ret = regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv, ++ (syscon_val->prediv << shift->prediv)); ++ if (ret) ++ goto set_failed; ++ ++ ret = regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv, ++ (syscon_val->fbdiv << shift->fbdiv)); ++ if (ret) ++ goto set_failed; ++ ++ ret = regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1, ++ ((syscon_val->postdiv1 >> 1) << shift->postdiv1)); ++ if (ret) ++ goto set_failed; ++ ++ /* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */ ++ if (syscon_val->dacpd == 0 && syscon_val->dsmpd == 0) ++ ret = regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac, ++ (syscon_val->frac << shift->frac)); ++ else if (syscon_val->dacpd != syscon_val->dsmpd) ++ ret = -EINVAL; ++ ++set_failed: ++ return ret; ++} ++ ++static unsigned long jh7110_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw); ++ ++ return jh7110_pll_get_freq(data, parent_rate); ++} ++ ++static int jh7110_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) ++{ ++ struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw); ++ ++ jh7110_pll_select_near_freq_id(data, req->rate); ++ ++ if (data->idx == JH7110_CLK_PLL0_OUT) ++ req->rate = jh7110_pll0_syscon_freq[data->freq_select_idx].freq; ++ else if (data->idx == JH7110_CLK_PLL1_OUT) ++ req->rate = jh7110_pll1_syscon_freq[data->freq_select_idx].freq; ++ else ++ req->rate = jh7110_pll2_syscon_freq[data->freq_select_idx].freq; ++ ++ return 0; ++} ++ ++static int jh7110_pll_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw); ++ ++ return jh7110_pll_set_freq_syscon(data); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static void jh7110_pll_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ static const struct debugfs_reg32 jh7110_clk_pll_reg = { ++ .name = "CTRL", ++ .offset = 0, ++ }; ++ struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw); ++ struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data); ++ struct debugfs_regset32 *regset; ++ ++ regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ return; ++ ++ regset->regs = &jh7110_clk_pll_reg; ++ regset->nregs = 1; ++ ++ debugfs_create_regset32("registers", 0400, dentry, regset); ++} ++#else ++#define jh7110_pll_debug_init NULL ++#endif ++ ++static const struct clk_ops jh7110_pll_ops = { ++ .recalc_rate = jh7110_pll_recalc_rate, ++ .determine_rate = jh7110_pll_determine_rate, ++ .set_rate = jh7110_pll_set_rate, ++ .debug_init = jh7110_pll_debug_init, ++}; ++ ++/* get offset, mask and shift of PLL(x) syscon */ ++static int jh7110_pll_data_get(struct jh7110_clk_pll_data *data, int index) ++{ ++ struct jh7110_pll_syscon_offset *offset = &data->offset; ++ struct jh7110_pll_syscon_mask *mask = &data->mask; ++ struct jh7110_pll_syscon_shift *shift = &data->shift; ++ ++ if (index == JH7110_CLK_PLL0_OUT) { ++ offset->dacpd = STARFIVE_JH7110_PLL0_DACPD_OFFSET; ++ offset->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_OFFSET; ++ offset->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_OFFSET; ++ offset->frac = STARFIVE_JH7110_PLL0_FRAC_OFFSET; ++ offset->prediv = STARFIVE_JH7110_PLL0_PREDIV_OFFSET; ++ offset->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET; ++ ++ mask->dacpd = STARFIVE_JH7110_PLL0_DACPD_MASK; ++ mask->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_MASK; ++ mask->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_MASK; ++ mask->frac = STARFIVE_JH7110_PLL0_FRAC_MASK; ++ mask->prediv = STARFIVE_JH7110_PLL0_PREDIV_MASK; ++ mask->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_MASK; ++ ++ shift->dacpd = STARFIVE_JH7110_PLL0_DACPD_SHIFT; ++ shift->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_SHIFT; ++ shift->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_SHIFT; ++ shift->frac = STARFIVE_JH7110_PLL0_FRAC_SHIFT; ++ shift->prediv = STARFIVE_JH7110_PLL0_PREDIV_SHIFT; ++ shift->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT; ++ ++ } else if (index == JH7110_CLK_PLL1_OUT) { ++ offset->dacpd = STARFIVE_JH7110_PLL1_DACPD_OFFSET; ++ offset->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_OFFSET; ++ offset->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_OFFSET; ++ offset->frac = STARFIVE_JH7110_PLL1_FRAC_OFFSET; ++ offset->prediv = STARFIVE_JH7110_PLL1_PREDIV_OFFSET; ++ offset->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET; ++ ++ mask->dacpd = STARFIVE_JH7110_PLL1_DACPD_MASK; ++ mask->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_MASK; ++ mask->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_MASK; ++ mask->frac = STARFIVE_JH7110_PLL1_FRAC_MASK; ++ mask->prediv = STARFIVE_JH7110_PLL1_PREDIV_MASK; ++ mask->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_MASK; ++ ++ shift->dacpd = STARFIVE_JH7110_PLL1_DACPD_SHIFT; ++ shift->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_SHIFT; ++ shift->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_SHIFT; ++ shift->frac = STARFIVE_JH7110_PLL1_FRAC_SHIFT; ++ shift->prediv = STARFIVE_JH7110_PLL1_PREDIV_SHIFT; ++ shift->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT; ++ ++ } else if (index == JH7110_CLK_PLL2_OUT) { ++ offset->dacpd = STARFIVE_JH7110_PLL2_DACPD_OFFSET; ++ offset->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_OFFSET; ++ offset->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_OFFSET; ++ offset->frac = STARFIVE_JH7110_PLL2_FRAC_OFFSET; ++ offset->prediv = STARFIVE_JH7110_PLL2_PREDIV_OFFSET; ++ offset->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET; ++ ++ mask->dacpd = STARFIVE_JH7110_PLL2_DACPD_MASK; ++ mask->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_MASK; ++ mask->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_MASK; ++ mask->frac = STARFIVE_JH7110_PLL2_FRAC_MASK; ++ mask->prediv = STARFIVE_JH7110_PLL2_PREDIV_MASK; ++ mask->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_MASK; ++ ++ shift->dacpd = STARFIVE_JH7110_PLL2_DACPD_SHIFT; ++ shift->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_SHIFT; ++ shift->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_SHIFT; ++ shift->frac = STARFIVE_JH7110_PLL2_FRAC_SHIFT; ++ shift->prediv = STARFIVE_JH7110_PLL2_PREDIV_SHIFT; ++ shift->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT; ++ ++ } else { ++ return -ENOENT; ++ } ++ ++ return 0; ++} ++ ++static struct clk_hw *jh7110_pll_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh7110_clk_pll_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_PLLCLK_END) ++ return &priv->data[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++static int jh7110_pll_probe(struct platform_device *pdev) ++{ ++ const char *pll_name[JH7110_PLLCLK_END] = { ++ "pll0_out", ++ "pll1_out", ++ "pll2_out" ++ }; ++ struct jh7110_clk_pll_priv *priv; ++ struct jh7110_clk_pll_data *data; ++ int ret; ++ unsigned int idx; ++ ++ priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, JH7110_PLLCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = &pdev->dev; ++ priv->syscon_regmap = syscon_node_to_regmap(priv->dev->of_node->parent); ++ if (IS_ERR(priv->syscon_regmap)) ++ return PTR_ERR(priv->syscon_regmap); ++ ++ for (idx = 0; idx < JH7110_PLLCLK_END; idx++) { ++ struct clk_parent_data parents = { ++ .index = 0, ++ }; ++ struct clk_init_data init = { ++ .name = pll_name[idx], ++ .ops = &jh7110_pll_ops, ++ .parent_data = &parents, ++ .num_parents = 1, ++ .flags = 0, ++ }; ++ ++ data = &priv->data[idx]; ++ ++ ret = jh7110_pll_data_get(data, idx); ++ if (ret) ++ return ret; ++ ++ data->hw.init = &init; ++ data->idx = idx; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &data->hw); ++ if (ret) ++ return ret; ++ } ++ ++ return devm_of_clk_add_hw_provider(&pdev->dev, jh7110_pll_get, priv); ++} ++ ++static const struct of_device_id jh7110_pll_match[] = { ++ { .compatible = "starfive,jh7110-pll" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_pll_match); ++ ++static struct platform_driver jh7110_pll_driver = { ++ .driver = { ++ .name = "clk-starfive-jh7110-pll", ++ .of_match_table = jh7110_pll_match, ++ }, ++}; ++builtin_platform_driver_probe(jh7110_pll_driver, jh7110_pll_probe); +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.h +@@ -0,0 +1,293 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * StarFive JH7110 PLL Clock Generator Driver ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef _CLK_STARFIVE_JH7110_PLL_H_ ++#define _CLK_STARFIVE_JH7110_PLL_H_ ++ ++#include ++ ++/* The decimal places are counted by expanding them by a factor of STARFIVE_PLL_FRAC_PATR_SIZE */ ++#define STARFIVE_PLL_FRAC_PATR_SIZE 1000 ++ ++#define STARFIVE_JH7110_PLL0_DACPD_OFFSET 0x18 ++#define STARFIVE_JH7110_PLL0_DACPD_SHIFT 24 ++#define STARFIVE_JH7110_PLL0_DACPD_MASK BIT(24) ++#define STARFIVE_JH7110_PLL0_DSMPD_OFFSET 0x18 ++#define STARFIVE_JH7110_PLL0_DSMPD_SHIFT 25 ++#define STARFIVE_JH7110_PLL0_DSMPD_MASK BIT(25) ++#define STARFIVE_JH7110_PLL0_FBDIV_OFFSET 0x1c ++#define STARFIVE_JH7110_PLL0_FBDIV_SHIFT 0 ++#define STARFIVE_JH7110_PLL0_FBDIV_MASK GENMASK(11, 0) ++#define STARFIVE_JH7110_PLL0_FRAC_OFFSET 0x20 ++#define STARFIVE_JH7110_PLL0_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_PLL0_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET 0x20 ++#define STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_PLL0_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_PLL0_PREDIV_OFFSET 0x24 ++#define STARFIVE_JH7110_PLL0_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_PLL0_PREDIV_MASK GENMASK(5, 0) ++ ++#define STARFIVE_JH7110_PLL1_DACPD_OFFSET 0x24 ++#define STARFIVE_JH7110_PLL1_DACPD_SHIFT 15 ++#define STARFIVE_JH7110_PLL1_DACPD_MASK BIT(15) ++#define STARFIVE_JH7110_PLL1_DSMPD_OFFSET 0x24 ++#define STARFIVE_JH7110_PLL1_DSMPD_SHIFT 16 ++#define STARFIVE_JH7110_PLL1_DSMPD_MASK BIT(16) ++#define STARFIVE_JH7110_PLL1_FBDIV_OFFSET 0x24 ++#define STARFIVE_JH7110_PLL1_FBDIV_SHIFT 17 ++#define STARFIVE_JH7110_PLL1_FBDIV_MASK GENMASK(28, 17) ++#define STARFIVE_JH7110_PLL1_FRAC_OFFSET 0x28 ++#define STARFIVE_JH7110_PLL1_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_PLL1_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET 0x28 ++#define STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_PLL1_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_PLL1_PREDIV_OFFSET 0x2c ++#define STARFIVE_JH7110_PLL1_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_PLL1_PREDIV_MASK GENMASK(5, 0) ++ ++#define STARFIVE_JH7110_PLL2_DACPD_OFFSET 0x2c ++#define STARFIVE_JH7110_PLL2_DACPD_SHIFT 15 ++#define STARFIVE_JH7110_PLL2_DACPD_MASK BIT(15) ++#define STARFIVE_JH7110_PLL2_DSMPD_OFFSET 0x2c ++#define STARFIVE_JH7110_PLL2_DSMPD_SHIFT 16 ++#define STARFIVE_JH7110_PLL2_DSMPD_MASK BIT(16) ++#define STARFIVE_JH7110_PLL2_FBDIV_OFFSET 0x2c ++#define STARFIVE_JH7110_PLL2_FBDIV_SHIFT 17 ++#define STARFIVE_JH7110_PLL2_FBDIV_MASK GENMASK(28, 17) ++#define STARFIVE_JH7110_PLL2_FRAC_OFFSET 0x30 ++#define STARFIVE_JH7110_PLL2_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_PLL2_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET 0x30 ++#define STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_PLL2_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_PLL2_PREDIV_OFFSET 0x34 ++#define STARFIVE_JH7110_PLL2_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_PLL2_PREDIV_MASK GENMASK(5, 0) ++ ++struct jh7110_pll_syscon_offset { ++ unsigned int dacpd; ++ unsigned int dsmpd; ++ unsigned int fbdiv; ++ unsigned int frac; ++ unsigned int prediv; ++ unsigned int postdiv1; ++}; ++ ++struct jh7110_pll_syscon_mask { ++ u32 dacpd; ++ u32 dsmpd; ++ u32 fbdiv; ++ u32 frac; ++ u32 prediv; ++ u32 postdiv1; ++}; ++ ++struct jh7110_pll_syscon_shift { ++ char dacpd; ++ char dsmpd; ++ char fbdiv; ++ char frac; ++ char prediv; ++ char postdiv1; ++}; ++ ++struct jh7110_clk_pll_data { ++ struct clk_hw hw; ++ unsigned int idx; ++ unsigned int freq_select_idx; ++ ++ struct jh7110_pll_syscon_offset offset; ++ struct jh7110_pll_syscon_mask mask; ++ struct jh7110_pll_syscon_shift shift; ++}; ++ ++struct jh7110_clk_pll_priv { ++ struct device *dev; ++ struct regmap *syscon_regmap; ++ struct jh7110_clk_pll_data data[]; ++}; ++ ++struct starfive_pll_syscon_value { ++ unsigned long freq; ++ u32 prediv; ++ u32 fbdiv; ++ u32 postdiv1; ++/* Both daxpd and dsmpd set 1 while integer mode */ ++/* Both daxpd and dsmpd set 0 while fraction mode */ ++ u32 dacpd; ++ u32 dsmpd; ++/* frac value should be decimals multiplied by 2^24 */ ++ u32 frac; ++}; ++ ++enum starfive_pll0_freq_index { ++ PLL0_FREQ_375 = 0, ++ PLL0_FREQ_500, ++ PLL0_FREQ_625, ++ PLL0_FREQ_750, ++ PLL0_FREQ_875, ++ PLL0_FREQ_1000, ++ PLL0_FREQ_1250, ++ PLL0_FREQ_1375, ++ PLL0_FREQ_1500, ++ PLL0_FREQ_MAX ++}; ++ ++enum starfive_pll1_freq_index { ++ PLL1_FREQ_1066 = 0, ++ PLL1_FREQ_1200, ++ PLL1_FREQ_1400, ++ PLL1_FREQ_1600, ++ PLL1_FREQ_MAX ++}; ++ ++enum starfive_pll2_freq_index { ++ PLL2_FREQ_1188 = 0, ++ PLL2_FREQ_12288, ++ PLL2_FREQ_MAX ++}; ++ ++/* ++ * Because the pll frequency is relatively fixed, ++ * it cannot be set arbitrarily, so it needs a specific configuration. ++ * PLL0 frequency should be multiple of 125MHz (USB frequency). ++ */ ++static const struct starfive_pll_syscon_value ++ jh7110_pll0_syscon_freq[PLL0_FREQ_MAX] = { ++ [PLL0_FREQ_375] = { ++ .freq = 375000000, ++ .prediv = 8, ++ .fbdiv = 125, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_500] = { ++ .freq = 500000000, ++ .prediv = 6, ++ .fbdiv = 125, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_625] = { ++ .freq = 625000000, ++ .prediv = 24, ++ .fbdiv = 625, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_750] = { ++ .freq = 750000000, ++ .prediv = 4, ++ .fbdiv = 125, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_875] = { ++ .freq = 875000000, ++ .prediv = 24, ++ .fbdiv = 875, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_1000] = { ++ .freq = 1000000000, ++ .prediv = 3, ++ .fbdiv = 125, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_1250] = { ++ .freq = 1250000000, ++ .prediv = 12, ++ .fbdiv = 625, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_1375] = { ++ .freq = 1375000000, ++ .prediv = 24, ++ .fbdiv = 1375, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL0_FREQ_1500] = { ++ .freq = 1500000000, ++ .prediv = 2, ++ .fbdiv = 125, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++}; ++ ++static const struct starfive_pll_syscon_value ++ jh7110_pll1_syscon_freq[PLL1_FREQ_MAX] = { ++ [PLL1_FREQ_1066] = { ++ .freq = 1066000000, ++ .prediv = 12, ++ .fbdiv = 533, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL1_FREQ_1200] = { ++ .freq = 1200000000, ++ .prediv = 1, ++ .fbdiv = 50, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL1_FREQ_1400] = { ++ .freq = 1400000000, ++ .prediv = 6, ++ .fbdiv = 350, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL1_FREQ_1600] = { ++ .freq = 1600000000, ++ .prediv = 3, ++ .fbdiv = 200, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++}; ++ ++static const struct starfive_pll_syscon_value ++ jh7110_pll2_syscon_freq[PLL2_FREQ_MAX] = { ++ [PLL2_FREQ_1188] = { ++ .freq = 1188000000, ++ .prediv = 2, ++ .fbdiv = 99, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++ [PLL2_FREQ_12288] = { ++ .freq = 1228800000, ++ .prediv = 5, ++ .fbdiv = 256, ++ .postdiv1 = 1, ++ .dacpd = 1, ++ .dsmpd = 1, ++ }, ++}; ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch b/target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch new file mode 100644 index 0000000000..4fd78cd5bb --- /dev/null +++ b/target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch @@ -0,0 +1,75 @@ +From 1f788a0a5092b1e1cfd02aa7f31ceb551befa7e6 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 14 Mar 2023 16:43:50 +0800 +Subject: [PATCH 033/122] dt-bindings: clock: jh7110-syscrg: Add PLL clock + inputs + +Add PLL clock inputs from PLL clock generator. + +Acked-by: Krzysztof Kozlowski +Signed-off-by: Xingyu Wu +--- + .../clock/starfive,jh7110-syscrg.yaml | 20 +++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml +@@ -27,6 +27,9 @@ properties: + - description: External I2S RX left/right channel clock + - description: External TDM clock + - description: External audio master clock ++ - description: PLL0 ++ - description: PLL1 ++ - description: PLL2 + + - items: + - description: Main Oscillator (24 MHz) +@@ -38,6 +41,9 @@ properties: + - description: External I2S RX left/right channel clock + - description: External TDM clock + - description: External audio master clock ++ - description: PLL0 ++ - description: PLL1 ++ - description: PLL2 + + clock-names: + oneOf: +@@ -52,6 +58,9 @@ properties: + - const: i2srx_lrck_ext + - const: tdm_ext + - const: mclk_ext ++ - const: pll0_out ++ - const: pll1_out ++ - const: pll2_out + + - items: + - const: osc +@@ -63,6 +72,9 @@ properties: + - const: i2srx_lrck_ext + - const: tdm_ext + - const: mclk_ext ++ - const: pll0_out ++ - const: pll1_out ++ - const: pll2_out + + '#clock-cells': + const: 1 +@@ -93,12 +105,16 @@ examples: + <&gmac1_rgmii_rxin>, + <&i2stx_bclk_ext>, <&i2stx_lrck_ext>, + <&i2srx_bclk_ext>, <&i2srx_lrck_ext>, +- <&tdm_ext>, <&mclk_ext>; ++ <&tdm_ext>, <&mclk_ext>, ++ <&pllclk JH7110_CLK_PLL0_OUT>, ++ <&pllclk JH7110_CLK_PLL1_OUT>, ++ <&pllclk JH7110_CLK_PLL2_OUT>; + clock-names = "osc", "gmac1_rmii_refin", + "gmac1_rgmii_rxin", + "i2stx_bclk_ext", "i2stx_lrck_ext", + "i2srx_bclk_ext", "i2srx_lrck_ext", +- "tdm_ext", "mclk_ext"; ++ "tdm_ext", "mclk_ext", ++ "pll0_out", "pll1_out", "pll2_out"; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch b/target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch new file mode 100644 index 0000000000..3e6237681f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch @@ -0,0 +1,71 @@ +From ffd7ee4fbd69d477a2156d9cba6ae80434a4c894 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 14 Mar 2023 17:16:07 +0800 +Subject: [PATCH 034/122] clk: starfive: jh7110-sys: Modify PLL clocks source + +Modify PLL clocks source to be got from dts instead of +the fixed factor clocks. + +Signed-off-by: Xingyu Wu +--- + drivers/clk/starfive/Kconfig | 1 + + .../clk/starfive/clk-starfive-jh7110-sys.c | 31 ++++--------------- + 2 files changed, 7 insertions(+), 25 deletions(-) + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -35,6 +35,7 @@ config CLK_STARFIVE_JH7110_SYS + select AUXILIARY_BUS + select CLK_STARFIVE_JH71X0 + select RESET_STARFIVE_JH7110 ++ select CLK_STARFIVE_JH7110_PLL + default ARCH_STARFIVE + help + Say yes here to support the system clock controller on the +--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c +@@ -404,29 +404,6 @@ static int __init jh7110_syscrg_probe(st + + dev_set_drvdata(priv->dev, (void *)(&priv->base)); + +- /* +- * These PLL clocks are not actually fixed factor clocks and can be +- * controlled by the syscon registers of JH7110. They will be dropped +- * and registered in the PLL clock driver instead. +- */ +- /* 24MHz -> 1000.0MHz */ +- priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out", +- "osc", 0, 125, 3); +- if (IS_ERR(priv->pll[0])) +- return PTR_ERR(priv->pll[0]); +- +- /* 24MHz -> 1066.0MHz */ +- priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out", +- "osc", 0, 533, 12); +- if (IS_ERR(priv->pll[1])) +- return PTR_ERR(priv->pll[1]); +- +- /* 24MHz -> 1188.0MHz */ +- priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out", +- "osc", 0, 99, 2); +- if (IS_ERR(priv->pll[2])) +- return PTR_ERR(priv->pll[2]); +- + for (idx = 0; idx < JH7110_SYSCLK_END; idx++) { + u32 max = jh7110_sysclk_data[idx].max; + struct clk_parent_data parents[4] = {}; +@@ -464,8 +441,12 @@ static int __init jh7110_syscrg_probe(st + parents[i].fw_name = "tdm_ext"; + else if (pidx == JH7110_SYSCLK_MCLK_EXT) + parents[i].fw_name = "mclk_ext"; +- else +- parents[i].hw = priv->pll[pidx - JH7110_SYSCLK_PLL0_OUT]; ++ else if (pidx == JH7110_SYSCLK_PLL0_OUT) ++ parents[i].fw_name = "pll0_out"; ++ else if (pidx == JH7110_SYSCLK_PLL1_OUT) ++ parents[i].fw_name = "pll1_out"; ++ else if (pidx == JH7110_SYSCLK_PLL2_OUT) ++ parents[i].fw_name = "pll2_out"; + } + + clk->hw.init = &init; diff --git a/target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch b/target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch new file mode 100644 index 0000000000..cf5fc7cbba --- /dev/null +++ b/target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch @@ -0,0 +1,86 @@ +From 35bc6491a7b24872155a616f7770d3a5d6e40344 Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Thu, 19 Jan 2023 17:44:46 +0800 +Subject: [PATCH 035/122] dt-bindings: power: Add starfive,jh7110-pmu + +Add bindings for the Power Management Unit on the StarFive JH7110 SoC. + +Signed-off-by: Walker Chen +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Conor Dooley +Reviewed-by: Heiko Stuebner +--- + .../bindings/power/starfive,jh7110-pmu.yaml | 45 +++++++++++++++++++ + .../dt-bindings/power/starfive,jh7110-pmu.h | 17 +++++++ + 2 files changed, 62 insertions(+) + create mode 100644 Documentation/devicetree/bindings/power/starfive,jh7110-pmu.yaml + create mode 100644 include/dt-bindings/power/starfive,jh7110-pmu.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/power/starfive,jh7110-pmu.yaml +@@ -0,0 +1,45 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/power/starfive,jh7110-pmu.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 Power Management Unit ++ ++maintainers: ++ - Walker Chen ++ ++description: | ++ StarFive JH7110 SoC includes support for multiple power domains which can be ++ powered on/off by software based on different application scenes to save power. ++ ++properties: ++ compatible: ++ enum: ++ - starfive,jh7110-pmu ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ "#power-domain-cells": ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - "#power-domain-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pwrc: power-controller@17030000 { ++ compatible = "starfive,jh7110-pmu"; ++ reg = <0x17030000 0x10000>; ++ interrupts = <111>; ++ #power-domain-cells = <1>; ++ }; +--- /dev/null ++++ b/include/dt-bindings/power/starfive,jh7110-pmu.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Author: Walker Chen ++ */ ++#ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__ ++#define __DT_BINDINGS_POWER_JH7110_POWER_H__ ++ ++#define JH7110_PD_SYSTOP 0 ++#define JH7110_PD_CPU 1 ++#define JH7110_PD_GPUA 2 ++#define JH7110_PD_VDEC 3 ++#define JH7110_PD_VOUT 4 ++#define JH7110_PD_ISP 5 ++#define JH7110_PD_VENC 6 ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch b/target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch new file mode 100644 index 0000000000..a5a33876fa --- /dev/null +++ b/target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch @@ -0,0 +1,478 @@ +From 3e3b85a1064b07a5107504af1e8f0a42ff9d1fc1 Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Thu, 19 Jan 2023 17:44:47 +0800 +Subject: [PATCH 036/122] soc: starfive: Add StarFive JH71XX pmu driver + +Add pmu driver for the StarFive JH71XX SoC. + +As the power domains provider, the Power Management Unit (PMU) is +designed for including multiple PM domains that can be used for power +gating of selected IP blocks for power saving by reduced leakage +current. It accepts software encourage command to switch the power mode +of SoC. + +Signed-off-by: Walker Chen +Reviewed-by: Conor Dooley +Reviewed-by: Heiko Stuebner +--- + MAINTAINERS | 14 ++ + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/starfive/Kconfig | 12 + + drivers/soc/starfive/Makefile | 3 + + drivers/soc/starfive/jh71xx_pmu.c | 383 ++++++++++++++++++++++++++++++ + 6 files changed, 414 insertions(+) + create mode 100644 drivers/soc/starfive/Kconfig + create mode 100644 drivers/soc/starfive/Makefile + create mode 100644 drivers/soc/starfive/jh71xx_pmu.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19682,6 +19682,20 @@ F: Documentation/devicetree/bindings/res + F: drivers/reset/starfive/reset-starfive-jh71* + F: include/dt-bindings/reset/starfive?jh71*.h + ++STARFIVE SOC DRIVER ++M: Conor Dooley ++S: Maintained ++T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ ++F: drivers/soc/starfive/ ++F: include/soc/starfive/ ++ ++STARFIVE JH71XX PMU CONTROLLER DRIVER ++M: Walker Chen ++S: Supported ++F: Documentation/devicetree/bindings/power/starfive* ++F: drivers/soc/starfive/jh71xx_pmu.c ++F: include/dt-bindings/power/starfive,jh7110-pmu.h ++ + STATIC BRANCH/CALL + M: Peter Zijlstra + M: Josh Poimboeuf +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -21,6 +21,7 @@ source "drivers/soc/renesas/Kconfig" + source "drivers/soc/rockchip/Kconfig" + source "drivers/soc/samsung/Kconfig" + source "drivers/soc/sifive/Kconfig" ++source "drivers/soc/starfive/Kconfig" + source "drivers/soc/sunxi/Kconfig" + source "drivers/soc/tegra/Kconfig" + source "drivers/soc/ti/Kconfig" +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -27,6 +27,7 @@ obj-y += renesas/ + obj-y += rockchip/ + obj-$(CONFIG_SOC_SAMSUNG) += samsung/ + obj-$(CONFIG_SOC_SIFIVE) += sifive/ ++obj-$(CONFIG_SOC_STARFIVE) += starfive/ + obj-y += sunxi/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ + obj-y += ti/ +--- /dev/null ++++ b/drivers/soc/starfive/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++config JH71XX_PMU ++ bool "Support PMU for StarFive JH71XX Soc" ++ depends on PM ++ depends on SOC_STARFIVE || COMPILE_TEST ++ default SOC_STARFIVE ++ select PM_GENERIC_DOMAINS ++ help ++ Say 'y' here to enable support power domain support. ++ In order to meet low power requirements, a Power Management Unit (PMU) ++ is designed for controlling power resources in StarFive JH71XX SoCs. +--- /dev/null ++++ b/drivers/soc/starfive/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-$(CONFIG_JH71XX_PMU) += jh71xx_pmu.o +--- /dev/null ++++ b/drivers/soc/starfive/jh71xx_pmu.c +@@ -0,0 +1,383 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * StarFive JH71XX PMU (Power Management Unit) Controller Driver ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* register offset */ ++#define JH71XX_PMU_SW_TURN_ON_POWER 0x0C ++#define JH71XX_PMU_SW_TURN_OFF_POWER 0x10 ++#define JH71XX_PMU_SW_ENCOURAGE 0x44 ++#define JH71XX_PMU_TIMER_INT_MASK 0x48 ++#define JH71XX_PMU_CURR_POWER_MODE 0x80 ++#define JH71XX_PMU_EVENT_STATUS 0x88 ++#define JH71XX_PMU_INT_STATUS 0x8C ++ ++/* sw encourage cfg */ ++#define JH71XX_PMU_SW_ENCOURAGE_EN_LO 0x05 ++#define JH71XX_PMU_SW_ENCOURAGE_EN_HI 0x50 ++#define JH71XX_PMU_SW_ENCOURAGE_DIS_LO 0x0A ++#define JH71XX_PMU_SW_ENCOURAGE_DIS_HI 0xA0 ++#define JH71XX_PMU_SW_ENCOURAGE_ON 0xFF ++ ++/* pmu int status */ ++#define JH71XX_PMU_INT_SEQ_DONE BIT(0) ++#define JH71XX_PMU_INT_HW_REQ BIT(1) ++#define JH71XX_PMU_INT_SW_FAIL GENMASK(3, 2) ++#define JH71XX_PMU_INT_HW_FAIL GENMASK(5, 4) ++#define JH71XX_PMU_INT_PCH_FAIL GENMASK(8, 6) ++#define JH71XX_PMU_INT_ALL_MASK GENMASK(8, 0) ++ ++/* ++ * The time required for switching power status is based on the time ++ * to turn on the largest domain's power, which is at microsecond level ++ */ ++#define JH71XX_PMU_TIMEOUT_US 100 ++ ++struct jh71xx_domain_info { ++ const char * const name; ++ unsigned int flags; ++ u8 bit; ++}; ++ ++struct jh71xx_pmu_match_data { ++ const struct jh71xx_domain_info *domain_info; ++ int num_domains; ++}; ++ ++struct jh71xx_pmu { ++ struct device *dev; ++ const struct jh71xx_pmu_match_data *match_data; ++ void __iomem *base; ++ struct generic_pm_domain **genpd; ++ struct genpd_onecell_data genpd_data; ++ int irq; ++ spinlock_t lock; /* protects pmu reg */ ++}; ++ ++struct jh71xx_pmu_dev { ++ const struct jh71xx_domain_info *domain_info; ++ struct jh71xx_pmu *pmu; ++ struct generic_pm_domain genpd; ++}; ++ ++static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on) ++{ ++ struct jh71xx_pmu *pmu = pmd->pmu; ++ ++ if (!mask) ++ return -EINVAL; ++ ++ *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask; ++ ++ return 0; ++} ++ ++static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) ++{ ++ struct jh71xx_pmu *pmu = pmd->pmu; ++ unsigned long flags; ++ u32 val; ++ u32 mode; ++ u32 encourage_lo; ++ u32 encourage_hi; ++ bool is_on; ++ int ret; ++ ++ ret = jh71xx_pmu_get_state(pmd, mask, &is_on); ++ if (ret) { ++ dev_dbg(pmu->dev, "unable to get current state for %s\n", ++ pmd->genpd.name); ++ return ret; ++ } ++ ++ if (is_on == on) { ++ dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n", ++ pmd->genpd.name, on ? "en" : "dis"); ++ return 0; ++ } ++ ++ spin_lock_irqsave(&pmu->lock, flags); ++ ++ /* ++ * The PMU accepts software encourage to switch power mode in the following 2 steps: ++ * ++ * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to ++ * the bit corresponding to the power domain that will be turned on ++ * and writing 0 to the others. ++ * Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by ++ * writing 1 to the bit corresponding to the power domain that will be ++ * turned off and writing 0 to the others. ++ */ ++ if (on) { ++ mode = JH71XX_PMU_SW_TURN_ON_POWER; ++ encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO; ++ encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI; ++ } else { ++ mode = JH71XX_PMU_SW_TURN_OFF_POWER; ++ encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO; ++ encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI; ++ } ++ ++ writel(mask, pmu->base + mode); ++ ++ /* ++ * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44) ++ * First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset ++ * the state machine which parses the command sequence. This register must be ++ * written every time software wants to power on/off a domain. ++ * Then write the lower bits of the command sequence, followed by the upper ++ * bits. The sequence differs between powering on & off a domain. ++ */ ++ writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE); ++ writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE); ++ writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE); ++ ++ spin_unlock_irqrestore(&pmu->lock, flags); ++ ++ /* Wait for the power domain bit to be enabled / disabled */ ++ if (on) { ++ ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, ++ val, val & mask, ++ 1, JH71XX_PMU_TIMEOUT_US); ++ } else { ++ ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, ++ val, !(val & mask), ++ 1, JH71XX_PMU_TIMEOUT_US); ++ } ++ ++ if (ret) { ++ dev_err(pmu->dev, "%s: failed to power %s\n", ++ pmd->genpd.name, on ? "on" : "off"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int jh71xx_pmu_on(struct generic_pm_domain *genpd) ++{ ++ struct jh71xx_pmu_dev *pmd = container_of(genpd, ++ struct jh71xx_pmu_dev, genpd); ++ u32 pwr_mask = BIT(pmd->domain_info->bit); ++ ++ return jh71xx_pmu_set_state(pmd, pwr_mask, true); ++} ++ ++static int jh71xx_pmu_off(struct generic_pm_domain *genpd) ++{ ++ struct jh71xx_pmu_dev *pmd = container_of(genpd, ++ struct jh71xx_pmu_dev, genpd); ++ u32 pwr_mask = BIT(pmd->domain_info->bit); ++ ++ return jh71xx_pmu_set_state(pmd, pwr_mask, false); ++} ++ ++static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable) ++{ ++ u32 val; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pmu->lock, flags); ++ val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK); ++ ++ if (enable) ++ val &= ~mask; ++ else ++ val |= mask; ++ ++ writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK); ++ spin_unlock_irqrestore(&pmu->lock, flags); ++} ++ ++static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data) ++{ ++ struct jh71xx_pmu *pmu = data; ++ u32 val; ++ ++ val = readl(pmu->base + JH71XX_PMU_INT_STATUS); ++ ++ if (val & JH71XX_PMU_INT_SEQ_DONE) ++ dev_dbg(pmu->dev, "sequence done.\n"); ++ if (val & JH71XX_PMU_INT_HW_REQ) ++ dev_dbg(pmu->dev, "hardware encourage requestion.\n"); ++ if (val & JH71XX_PMU_INT_SW_FAIL) ++ dev_err(pmu->dev, "software encourage fail.\n"); ++ if (val & JH71XX_PMU_INT_HW_FAIL) ++ dev_err(pmu->dev, "hardware encourage fail.\n"); ++ if (val & JH71XX_PMU_INT_PCH_FAIL) ++ dev_err(pmu->dev, "p-channel fail event.\n"); ++ ++ /* clear interrupts */ ++ writel(val, pmu->base + JH71XX_PMU_INT_STATUS); ++ writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS); ++ ++ return IRQ_HANDLED; ++} ++ ++static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index) ++{ ++ struct jh71xx_pmu_dev *pmd; ++ u32 pwr_mask; ++ int ret; ++ bool is_on = false; ++ ++ pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL); ++ if (!pmd) ++ return -ENOMEM; ++ ++ pmd->domain_info = &pmu->match_data->domain_info[index]; ++ pmd->pmu = pmu; ++ pwr_mask = BIT(pmd->domain_info->bit); ++ ++ pmd->genpd.name = pmd->domain_info->name; ++ pmd->genpd.flags = pmd->domain_info->flags; ++ ++ ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on); ++ if (ret) ++ dev_warn(pmu->dev, "unable to get current state for %s\n", ++ pmd->genpd.name); ++ ++ pmd->genpd.power_on = jh71xx_pmu_on; ++ pmd->genpd.power_off = jh71xx_pmu_off; ++ pm_genpd_init(&pmd->genpd, NULL, !is_on); ++ ++ pmu->genpd_data.domains[index] = &pmd->genpd; ++ ++ return 0; ++} ++ ++static int jh71xx_pmu_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ const struct jh71xx_pmu_match_data *match_data; ++ struct jh71xx_pmu *pmu; ++ unsigned int i; ++ int ret; ++ ++ pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL); ++ if (!pmu) ++ return -ENOMEM; ++ ++ pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pmu->base)) ++ return PTR_ERR(pmu->base); ++ ++ pmu->irq = platform_get_irq(pdev, 0); ++ if (pmu->irq < 0) ++ return pmu->irq; ++ ++ ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt, ++ 0, pdev->name, pmu); ++ if (ret) ++ dev_err(dev, "failed to request irq\n"); ++ ++ match_data = of_device_get_match_data(dev); ++ if (!match_data) ++ return -EINVAL; ++ ++ pmu->genpd = devm_kcalloc(dev, match_data->num_domains, ++ sizeof(struct generic_pm_domain *), ++ GFP_KERNEL); ++ if (!pmu->genpd) ++ return -ENOMEM; ++ ++ pmu->dev = dev; ++ pmu->match_data = match_data; ++ pmu->genpd_data.domains = pmu->genpd; ++ pmu->genpd_data.num_domains = match_data->num_domains; ++ ++ for (i = 0; i < match_data->num_domains; i++) { ++ ret = jh71xx_pmu_init_domain(pmu, i); ++ if (ret) { ++ dev_err(dev, "failed to initialize power domain\n"); ++ return ret; ++ } ++ } ++ ++ spin_lock_init(&pmu->lock); ++ jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true); ++ ++ ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data); ++ if (ret) { ++ dev_err(dev, "failed to register genpd driver: %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(dev, "registered %u power domains\n", i); ++ ++ return 0; ++} ++ ++static const struct jh71xx_domain_info jh7110_power_domains[] = { ++ [JH7110_PD_SYSTOP] = { ++ .name = "SYSTOP", ++ .bit = 0, ++ .flags = GENPD_FLAG_ALWAYS_ON, ++ }, ++ [JH7110_PD_CPU] = { ++ .name = "CPU", ++ .bit = 1, ++ .flags = GENPD_FLAG_ALWAYS_ON, ++ }, ++ [JH7110_PD_GPUA] = { ++ .name = "GPUA", ++ .bit = 2, ++ }, ++ [JH7110_PD_VDEC] = { ++ .name = "VDEC", ++ .bit = 3, ++ }, ++ [JH7110_PD_VOUT] = { ++ .name = "VOUT", ++ .bit = 4, ++ }, ++ [JH7110_PD_ISP] = { ++ .name = "ISP", ++ .bit = 5, ++ }, ++ [JH7110_PD_VENC] = { ++ .name = "VENC", ++ .bit = 6, ++ }, ++}; ++ ++static const struct jh71xx_pmu_match_data jh7110_pmu = { ++ .num_domains = ARRAY_SIZE(jh7110_power_domains), ++ .domain_info = jh7110_power_domains, ++}; ++ ++static const struct of_device_id jh71xx_pmu_of_match[] = { ++ { ++ .compatible = "starfive,jh7110-pmu", ++ .data = (void *)&jh7110_pmu, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static struct platform_driver jh71xx_pmu_driver = { ++ .probe = jh71xx_pmu_probe, ++ .driver = { ++ .name = "jh71xx-pmu", ++ .of_match_table = jh71xx_pmu_of_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver(jh71xx_pmu_driver); ++ ++MODULE_AUTHOR("Walker Chen "); ++MODULE_DESCRIPTION("StarFive JH71XX PMU Driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch b/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch new file mode 100644 index 0000000000..c4bf9bc56f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch @@ -0,0 +1,98 @@ +From 27d38dda7527414eb84ef471425e96c9d2566b38 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Thu, 6 Apr 2023 15:46:13 +0800 +Subject: [PATCH 037/122] dt-bindings: soc: starfive: Add StarFive syscon + module + +Add documentation to describe StarFive System Controller Registers. + +Signed-off-by: William Qiu +--- + .../soc/starfive/starfive,jh7110-syscon.yaml | 58 +++++++++++++++++++ + MAINTAINERS | 6 ++ + 2 files changed, 64 insertions(+) + create mode 100644 Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml +@@ -0,0 +1,58 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/soc/starfive/starfive,jh7110-syscon.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 SoC system controller ++ ++maintainers: ++ - William Qiu ++ ++description: | ++ The StarFive JH7110 SoC system controller provides register information such ++ as offset, mask and shift to configure related modules such as MMC and PCIe. ++ ++properties: ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - starfive,jh7110-aon-syscon ++ - starfive,jh7110-sys-syscon ++ - const: syscon ++ - const: simple-mfd ++ - items: ++ - const: starfive,jh7110-stg-syscon ++ - const: syscon ++ ++ reg: ++ maxItems: 1 ++ ++ clock-controller: ++ $ref: /schemas/clock/starfive,jh7110-pll.yaml# ++ type: object ++ ++ power-controller: ++ $ref: /schemas/power/starfive,jh7110-pmu.yaml# ++ type: object ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: false ++ ++examples: ++ - | ++ syscon@10240000 { ++ compatible = "starfive,jh7110-stg-syscon", "syscon"; ++ reg = <0x10240000 0x1000>; ++ }; ++ ++ syscon@13030000 { ++ compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd"; ++ reg = <0x13030000 0x1000>; ++ }; ++ ++... +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19656,6 +19656,11 @@ S: Supported + F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml + F: drivers/clk/starfive/clk-starfive-jh7110-pll.* + ++STARFIVE JH7110 SYSCON ++M: William Qiu ++S: Supported ++F: Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml ++ + STARFIVE JH71X0 CLOCK DRIVERS + M: Emil Renner Berthing + M: Hal Feng +@@ -19686,6 +19691,7 @@ STARFIVE SOC DRIVER + M: Conor Dooley + S: Maintained + T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ ++F: Documentation/devicetree/bindings/soc/starfive/ + F: drivers/soc/starfive/ + F: include/soc/starfive/ + diff --git a/target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch b/target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch new file mode 100644 index 0000000000..ad748151c7 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch @@ -0,0 +1,52 @@ +From 40098f3d986dc90f6a7be0e5a35ddaccd1ded0b5 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Thu, 6 Apr 2023 15:46:34 +0800 +Subject: [PATCH 038/122] riscv: dts: starfive: jh7110: Add syscon nodes + +Add stg_syscon/sys_syscon/aon_syscon nodes for JH7110 Soc. + +Signed-off-by: William Qiu +Reviewed-by: Conor Dooley +Reviewed-by: Emil Renner Berthing +--- + arch/riscv/boot/dts/starfive/jh7110.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi +@@ -353,6 +353,11 @@ + status = "disabled"; + }; + ++ stg_syscon: syscon@10240000 { ++ compatible = "starfive,jh7110-stg-syscon", "syscon"; ++ reg = <0x0 0x10240000 0x0 0x1000>; ++ }; ++ + uart3: serial@12000000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x12000000 0x0 0x10000>; +@@ -457,6 +462,11 @@ + #reset-cells = <1>; + }; + ++ sys_syscon: syscon@13030000 { ++ compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd"; ++ reg = <0x0 0x13030000 0x0 0x1000>; ++ }; ++ + sysgpio: pinctrl@13040000 { + compatible = "starfive,jh7110-sys-pinctrl"; + reg = <0x0 0x13040000 0x0 0x10000>; +@@ -486,6 +496,11 @@ + #reset-cells = <1>; + }; + ++ aon_syscon: syscon@17010000 { ++ compatible = "starfive,jh7110-aon-syscon", "syscon", "simple-mfd"; ++ reg = <0x0 0x17010000 0x0 0x1000>; ++ }; ++ + aongpio: pinctrl@17020000 { + compatible = "starfive,jh7110-aon-pinctrl"; + reg = <0x0 0x17020000 0x0 0x10000>; diff --git a/target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch b/target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch new file mode 100644 index 0000000000..c771512bd3 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch @@ -0,0 +1,48 @@ +From f0548ab9212ef35abe79f46e5f509f4fc9d78699 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Mon, 20 Feb 2023 14:33:33 +0800 +Subject: [PATCH 039/122] riscv: dts: starfive: jh7110: Add PLL clock node and + modify syscrg node + +Add the PLL clock node for the Starfive JH7110 SoC and +modify the SYSCRG node to add PLL clocks input. + +Signed-off-by: Xingyu Wu +--- + arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi +@@ -452,12 +452,16 @@ + <&gmac1_rgmii_rxin>, + <&i2stx_bclk_ext>, <&i2stx_lrck_ext>, + <&i2srx_bclk_ext>, <&i2srx_lrck_ext>, +- <&tdm_ext>, <&mclk_ext>; ++ <&tdm_ext>, <&mclk_ext>, ++ <&pllclk JH7110_CLK_PLL0_OUT>, ++ <&pllclk JH7110_CLK_PLL1_OUT>, ++ <&pllclk JH7110_CLK_PLL2_OUT>; + clock-names = "osc", "gmac1_rmii_refin", + "gmac1_rgmii_rxin", + "i2stx_bclk_ext", "i2stx_lrck_ext", + "i2srx_bclk_ext", "i2srx_lrck_ext", +- "tdm_ext", "mclk_ext"; ++ "tdm_ext", "mclk_ext", ++ "pll0_out", "pll1_out", "pll2_out"; + #clock-cells = <1>; + #reset-cells = <1>; + }; +@@ -465,6 +469,12 @@ + sys_syscon: syscon@13030000 { + compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd"; + reg = <0x0 0x13030000 0x0 0x1000>; ++ ++ pllclk: clock-controller { ++ compatible = "starfive,jh7110-pll"; ++ clocks = <&osc>; ++ #clock-cells = <1>; ++ }; + }; + + sysgpio: pinctrl@13040000 { diff --git a/target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch b/target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch new file mode 100644 index 0000000000..139cd8445b --- /dev/null +++ b/target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch @@ -0,0 +1,49 @@ +From 5866a8486a261decacd19769556d1b79b5d1269d Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Mon, 8 Aug 2022 17:13:34 +0200 +Subject: [PATCH 040/122] dt-bindings: net: snps,dwmac: Add dwmac-5.20 version + +Add dwmac-5.20 IP version to snps.dwmac.yaml + +Acked-by: Krzysztof Kozlowski +Signed-off-by: Emil Renner Berthing +Signed-off-by: Samin Guo +Signed-off-by: Paolo Abeni +--- + Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml ++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml +@@ -30,6 +30,7 @@ select: + - snps,dwmac-4.10a + - snps,dwmac-4.20a + - snps,dwmac-5.10a ++ - snps,dwmac-5.20 + - snps,dwxgmac + - snps,dwxgmac-2.10 + +@@ -87,6 +88,7 @@ properties: + - snps,dwmac-4.10a + - snps,dwmac-4.20a + - snps,dwmac-5.10a ++ - snps,dwmac-5.20 + - snps,dwxgmac + - snps,dwxgmac-2.10 + +@@ -393,6 +395,7 @@ allOf: + - snps,dwmac-3.50a + - snps,dwmac-4.10a + - snps,dwmac-4.20a ++ - snps,dwmac-5.20 + - snps,dwxgmac + - snps,dwxgmac-2.10 + - st,spear600-gmac +@@ -447,6 +450,7 @@ allOf: + - snps,dwmac-4.10a + - snps,dwmac-4.20a + - snps,dwmac-5.10a ++ - snps,dwmac-5.20 + - snps,dwxgmac + - snps,dwxgmac-2.10 + - st,spear600-gmac diff --git a/target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch b/target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch new file mode 100644 index 0000000000..077f161dcd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch @@ -0,0 +1,29 @@ +From cb00f835fc9f3ece473e7081f17c8613bf08a8ef Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sun, 7 Aug 2022 22:26:00 +0200 +Subject: [PATCH 041/122] net: stmmac: platform: Add snps,dwmac-5.20 IP + compatible string + +Add "snps,dwmac-5.20" compatible string for 5.20 version that can avoid +to define some platform data in the glue layer. + +Tested-by: Tommaso Merciai +Signed-off-by: Emil Renner Berthing +Signed-off-by: Paolo Abeni +Signed-off-by: Samin Guo +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -519,7 +519,8 @@ stmmac_probe_config_dt(struct platform_d + if (of_device_is_compatible(np, "snps,dwmac-4.00") || + of_device_is_compatible(np, "snps,dwmac-4.10a") || + of_device_is_compatible(np, "snps,dwmac-4.20a") || +- of_device_is_compatible(np, "snps,dwmac-5.10a")) { ++ of_device_is_compatible(np, "snps,dwmac-5.10a") || ++ of_device_is_compatible(np, "snps,dwmac-5.20")) { + plat->has_gmac4 = 1; + plat->has_gmac = 0; + plat->pmt = 1; diff --git a/target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch b/target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch new file mode 100644 index 0000000000..5b73752fd6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch @@ -0,0 +1,46 @@ +From 3b0609e57e031a3b680131b3fc25bc1165e3360f Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Mon, 27 Feb 2023 18:26:04 +0800 +Subject: [PATCH 042/122] dt-bindings: net: snps,dwmac: Add 'ahb' + reset/reset-name + +According to: +stmmac_platform.c: stmmac_probe_config_dt +stmmac_main.c: stmmac_dvr_probe + +dwmac controller may require one (stmmaceth) or two (stmmaceth+ahb) +reset signals, and the maxItems of resets/reset-names is going to be 2. + +The gmac of Starfive Jh7110 SOC must have two resets. +it uses snps,dwmac-5.20 IP. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Samin Guo +Signed-off-by: Paolo Abeni +--- + .../devicetree/bindings/net/snps,dwmac.yaml | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml ++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml +@@ -133,12 +133,16 @@ properties: + - ptp_ref + + resets: +- maxItems: 1 +- description: +- MAC Reset signal. ++ minItems: 1 ++ items: ++ - description: GMAC stmmaceth reset ++ - description: AHB reset + + reset-names: +- const: stmmaceth ++ minItems: 1 ++ items: ++ - const: stmmaceth ++ - const: ahb + + power-domains: + maxItems: 1 diff --git a/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch b/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch new file mode 100644 index 0000000000..4487c6995f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch @@ -0,0 +1,190 @@ +From 6bef17fa124f20723724e2a9a1d890fd1a9d5eaa Mon Sep 17 00:00:00 2001 +From: Yanhong Wang +Date: Mon, 31 Oct 2022 18:08:15 +0800 +Subject: [PATCH 043/122] dt-bindings: net: Add support StarFive dwmac + +Add documentation to describe StarFive dwmac driver(GMAC). + +Signed-off-by: Yanhong Wang +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Paolo Abeni +Signed-off-by: Samin Guo +--- + .../devicetree/bindings/net/snps,dwmac.yaml | 1 + + .../bindings/net/starfive,jh7110-dwmac.yaml | 144 ++++++++++++++++++ + MAINTAINERS | 6 + + 3 files changed, 151 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml + +--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml ++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml +@@ -91,6 +91,7 @@ properties: + - snps,dwmac-5.20 + - snps,dwxgmac + - snps,dwxgmac-2.10 ++ - starfive,jh7110-dwmac + + reg: + minItems: 1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml +@@ -0,0 +1,144 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++# Copyright (C) 2022 StarFive Technology Co., Ltd. ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/starfive,jh7110-dwmac.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 DWMAC glue layer ++ ++maintainers: ++ - Emil Renner Berthing ++ - Samin Guo ++ ++select: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - starfive,jh7110-dwmac ++ required: ++ - compatible ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - starfive,jh7110-dwmac ++ - const: snps,dwmac-5.20 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: GMAC main clock ++ - description: GMAC AHB clock ++ - description: PTP clock ++ - description: TX clock ++ - description: GTX clock ++ ++ clock-names: ++ items: ++ - const: stmmaceth ++ - const: pclk ++ - const: ptp_ref ++ - const: tx ++ - const: gtx ++ ++ interrupts: ++ minItems: 3 ++ maxItems: 3 ++ ++ interrupt-names: ++ minItems: 3 ++ maxItems: 3 ++ ++ resets: ++ items: ++ - description: MAC Reset signal. ++ - description: AHB Reset signal. ++ ++ reset-names: ++ items: ++ - const: stmmaceth ++ - const: ahb ++ ++ starfive,tx-use-rgmii-clk: ++ description: ++ Tx clock is provided by external rgmii clock. ++ type: boolean ++ ++ starfive,syscon: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ - items: ++ - description: phandle to syscon that configures phy mode ++ - description: Offset of phy mode selection ++ - description: Shift of phy mode selection ++ description: ++ A phandle to syscon with two arguments that configure phy mode. ++ The argument one is the offset of phy mode selection, the ++ argument two is the shift of phy mode selection. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - interrupts ++ - interrupt-names ++ - resets ++ - reset-names ++ ++allOf: ++ - $ref: snps,dwmac.yaml# ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ ethernet@16030000 { ++ compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; ++ reg = <0x16030000 0x10000>; ++ clocks = <&clk 3>, <&clk 2>, <&clk 109>, ++ <&clk 6>, <&clk 111>; ++ clock-names = "stmmaceth", "pclk", "ptp_ref", ++ "tx", "gtx"; ++ resets = <&rst 1>, <&rst 2>; ++ reset-names = "stmmaceth", "ahb"; ++ interrupts = <7>, <6>, <5>; ++ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; ++ phy-mode = "rgmii-id"; ++ snps,multicast-filter-bins = <64>; ++ snps,perfect-filter-entries = <8>; ++ rx-fifo-depth = <2048>; ++ tx-fifo-depth = <2048>; ++ snps,fixed-burst; ++ snps,no-pbl-x8; ++ snps,tso; ++ snps,force_thresh_dma_mode; ++ snps,axi-config = <&stmmac_axi_setup>; ++ snps,en-tx-lpi-clockgating; ++ snps,txpbl = <16>; ++ snps,rxpbl = <16>; ++ starfive,syscon = <&aon_syscon 0xc 0x12>; ++ phy-handle = <&phy0>; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "snps,dwmac-mdio"; ++ ++ phy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ }; ++ ++ stmmac_axi_setup: stmmac-axi-config { ++ snps,lpi_en; ++ snps,wr_osr_lmt = <4>; ++ snps,rd_osr_lmt = <4>; ++ snps,blen = <256 128 64 32 0 0 0>; ++ }; ++ }; +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19650,6 +19650,12 @@ M: Emil Renner Berthing ++M: Samin Guo ++S: Maintained ++F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml ++ + STARFIVE JH7110 PLL CLOCK DRIVER + M: Xingyu Wu + S: Supported diff --git a/target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch b/target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch new file mode 100644 index 0000000000..37ad5a192a --- /dev/null +++ b/target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch @@ -0,0 +1,187 @@ +From 7c82049adb0460985dd6a1e5c9b6954d901247d2 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Fri, 3 Mar 2023 16:50:58 +0800 +Subject: [PATCH 044/122] net: stmmac: Add glue layer for StarFive JH7110 SoC + +This adds StarFive dwmac driver support on the StarFive JH7110 SoC. + +Tested-by: Tommaso Merciai +Co-developed-by: Emil Renner Berthing +Signed-off-by: Emil Renner Berthing +Signed-off-by: Paolo Abeni +Signed-off-by: Samin Guo +--- + MAINTAINERS | 1 + + drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++ + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + + .../ethernet/stmicro/stmmac/dwmac-starfive.c | 123 ++++++++++++++++++ + 4 files changed, 137 insertions(+) + create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19655,6 +19655,7 @@ M: Emil Renner Berthing + S: Maintained + F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml ++F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c + + STARFIVE JH7110 PLL CLOCK DRIVER + M: Xingyu Wu +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -165,6 +165,18 @@ config DWMAC_SOCFPGA + for the stmmac device driver. This driver is used for + arria5 and cyclone5 FPGA SoCs. + ++config DWMAC_STARFIVE ++ tristate "StarFive dwmac support" ++ depends on OF && (ARCH_STARFIVE || COMPILE_TEST) ++ select MFD_SYSCON ++ default m if ARCH_STARFIVE ++ help ++ Support for ethernet controllers on StarFive RISC-V SoCs ++ ++ This selects the StarFive platform specific glue layer support for ++ the stmmac device driver. This driver is used for StarFive JH7110 ++ ethernet controller. ++ + config DWMAC_STI + tristate "STi GMAC support" + default ARCH_STI +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas + obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o + obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o + obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o ++obj-$(CONFIG_DWMAC_STARFIVE) += dwmac-starfive.o + obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o + obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o + obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o +--- /dev/null ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +@@ -0,0 +1,123 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * StarFive DWMAC platform driver ++ * ++ * Copyright (C) 2021 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "stmmac_platform.h" ++ ++struct starfive_dwmac { ++ struct device *dev; ++ struct clk *clk_tx; ++}; ++ ++static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed) ++{ ++ struct starfive_dwmac *dwmac = priv; ++ unsigned long rate; ++ int err; ++ ++ rate = clk_get_rate(dwmac->clk_tx); ++ ++ switch (speed) { ++ case SPEED_1000: ++ rate = 125000000; ++ break; ++ case SPEED_100: ++ rate = 25000000; ++ break; ++ case SPEED_10: ++ rate = 2500000; ++ break; ++ default: ++ dev_err(dwmac->dev, "invalid speed %u\n", speed); ++ break; ++ } ++ ++ err = clk_set_rate(dwmac->clk_tx, rate); ++ if (err) ++ dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); ++} ++ ++static int starfive_dwmac_probe(struct platform_device *pdev) ++{ ++ struct plat_stmmacenet_data *plat_dat; ++ struct stmmac_resources stmmac_res; ++ struct starfive_dwmac *dwmac; ++ struct clk *clk_gtx; ++ int err; ++ ++ err = stmmac_get_platform_resources(pdev, &stmmac_res); ++ if (err) ++ return dev_err_probe(&pdev->dev, err, ++ "failed to get resources\n"); ++ ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); ++ if (IS_ERR(plat_dat)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat), ++ "dt configuration failed\n"); ++ ++ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); ++ if (!dwmac) ++ return -ENOMEM; ++ ++ dwmac->clk_tx = devm_clk_get_enabled(&pdev->dev, "tx"); ++ if (IS_ERR(dwmac->clk_tx)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->clk_tx), ++ "error getting tx clock\n"); ++ ++ clk_gtx = devm_clk_get_enabled(&pdev->dev, "gtx"); ++ if (IS_ERR(clk_gtx)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(clk_gtx), ++ "error getting gtx clock\n"); ++ ++ /* Generally, the rgmii_tx clock is provided by the internal clock, ++ * which needs to match the corresponding clock frequency according ++ * to different speeds. If the rgmii_tx clock is provided by the ++ * external rgmii_rxin, there is no need to configure the clock ++ * internally, because rgmii_rxin will be adaptively adjusted. ++ */ ++ if (!device_property_read_bool(&pdev->dev, "starfive,tx-use-rgmii-clk")) ++ plat_dat->fix_mac_speed = starfive_dwmac_fix_mac_speed; ++ ++ dwmac->dev = &pdev->dev; ++ plat_dat->bsp_priv = dwmac; ++ plat_dat->dma_cfg->dche = true; ++ ++ err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); ++ if (err) { ++ stmmac_remove_config_dt(pdev, plat_dat); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id starfive_dwmac_match[] = { ++ { .compatible = "starfive,jh7110-dwmac" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, starfive_dwmac_match); ++ ++static struct platform_driver starfive_dwmac_driver = { ++ .probe = starfive_dwmac_probe, ++ .remove = stmmac_pltfr_remove, ++ .driver = { ++ .name = "starfive-dwmac", ++ .pm = &stmmac_pltfr_pm_ops, ++ .of_match_table = starfive_dwmac_match, ++ }, ++}; ++module_platform_driver(starfive_dwmac_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("StarFive DWMAC platform driver"); ++MODULE_AUTHOR("Emil Renner Berthing "); ++MODULE_AUTHOR("Samin Guo "); diff --git a/target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch b/target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch new file mode 100644 index 0000000000..a532c0e4dd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch @@ -0,0 +1,93 @@ +From 20886cd583e8d569d78ea0e723f98384a61ab54b Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 2 Mar 2023 19:52:37 +0800 +Subject: [PATCH 045/122] net: stmmac: dwmac-starfive: Add phy interface + settings + +dwmac supports multiple modess. When working under rmii and rgmii, +you need to set different phy interfaces. + +According to the dwmac document, when working in rmii, it needs to be +set to 0x4, and rgmii needs to be set to 0x1. + +The phy interface needs to be set in syscon, the format is as follows: +starfive,syscon: <&syscon, offset, shift> + +Tested-by: Tommaso Merciai +Signed-off-by: Paolo Abeni +Signed-off-by: Samin Guo +--- + .../ethernet/stmicro/stmmac/dwmac-starfive.c | 48 +++++++++++++++++++ + 1 file changed, 48 insertions(+) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +@@ -13,6 +13,10 @@ + + #include "stmmac_platform.h" + ++#define STARFIVE_DWMAC_PHY_INFT_RGMII 0x1 ++#define STARFIVE_DWMAC_PHY_INFT_RMII 0x4 ++#define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U ++ + struct starfive_dwmac { + struct device *dev; + struct clk *clk_tx; +@@ -46,6 +50,46 @@ static void starfive_dwmac_fix_mac_speed + dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); + } + ++static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat) ++{ ++ struct starfive_dwmac *dwmac = plat_dat->bsp_priv; ++ struct regmap *regmap; ++ unsigned int args[2]; ++ unsigned int mode; ++ int err; ++ ++ switch (plat_dat->interface) { ++ case PHY_INTERFACE_MODE_RMII: ++ mode = STARFIVE_DWMAC_PHY_INFT_RMII; ++ break; ++ ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ mode = STARFIVE_DWMAC_PHY_INFT_RGMII; ++ break; ++ ++ default: ++ dev_err(dwmac->dev, "unsupported interface %d\n", ++ plat_dat->interface); ++ return -EINVAL; ++ } ++ ++ regmap = syscon_regmap_lookup_by_phandle_args(dwmac->dev->of_node, ++ "starfive,syscon", ++ 2, args); ++ if (IS_ERR(regmap)) ++ return dev_err_probe(dwmac->dev, PTR_ERR(regmap), "getting the regmap failed\n"); ++ ++ /* args[0]:offset args[1]: shift */ ++ err = regmap_update_bits(regmap, args[0], ++ STARFIVE_DWMAC_PHY_INFT_FIELD << args[1], ++ mode << args[1]); ++ if (err) ++ return dev_err_probe(dwmac->dev, err, "error setting phy mode\n"); ++ ++ return 0; ++} ++ + static int starfive_dwmac_probe(struct platform_device *pdev) + { + struct plat_stmmacenet_data *plat_dat; +@@ -91,6 +135,10 @@ static int starfive_dwmac_probe(struct p + plat_dat->bsp_priv = dwmac; + plat_dat->dma_cfg->dche = true; + ++ err = starfive_dwmac_set_mode(plat_dat); ++ if (err) ++ return err; ++ + err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (err) { + stmmac_remove_config_dt(pdev, plat_dat); diff --git a/target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch b/target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch new file mode 100644 index 0000000000..50ad56f568 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch @@ -0,0 +1,101 @@ +From cad740398f4cb6604abf1ddcc70121b2634ac233 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Fri, 3 Mar 2023 16:49:31 +0800 +Subject: [PATCH 046/122] riscv: dts: starfive: jh7110: Add ethernet device + nodes + +Add JH7110 ethernet device node to support gmac driver for the JH7110 +RISC-V SoC. + +Tested-by: Tommaso Merciai +Signed-off-by: Yanhong Wang +Signed-off-by: Samin Guo +--- + arch/riscv/boot/dts/starfive/jh7110.dtsi | 69 ++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi +@@ -230,6 +230,13 @@ + #clock-cells = <0>; + }; + ++ stmmac_axi_setup: stmmac-axi-config { ++ snps,lpi_en; ++ snps,wr_osr_lmt = <4>; ++ snps,rd_osr_lmt = <4>; ++ snps,blen = <256 128 64 32 0 0 0>; ++ }; ++ + tdm_ext: tdm-ext-clock { + compatible = "fixed-clock"; + clock-output-names = "tdm_ext"; +@@ -489,6 +496,68 @@ + #gpio-cells = <2>; + }; + ++ gmac0: ethernet@16030000 { ++ compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; ++ reg = <0x0 0x16030000 0x0 0x10000>; ++ clocks = <&aoncrg JH7110_AONCLK_GMAC0_AXI>, ++ <&aoncrg JH7110_AONCLK_GMAC0_AHB>, ++ <&syscrg JH7110_SYSCLK_GMAC0_PTP>, ++ <&aoncrg JH7110_AONCLK_GMAC0_TX_INV>, ++ <&syscrg JH7110_SYSCLK_GMAC0_GTXC>; ++ clock-names = "stmmaceth", "pclk", "ptp_ref", ++ "tx", "gtx"; ++ resets = <&aoncrg JH7110_AONRST_GMAC0_AXI>, ++ <&aoncrg JH7110_AONRST_GMAC0_AHB>; ++ reset-names = "stmmaceth", "ahb"; ++ interrupts = <7>, <6>, <5>; ++ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; ++ rx-fifo-depth = <2048>; ++ tx-fifo-depth = <2048>; ++ snps,multicast-filter-bins = <64>; ++ snps,perfect-filter-entries = <8>; ++ snps,fixed-burst; ++ snps,no-pbl-x8; ++ snps,force_thresh_dma_mode; ++ snps,axi-config = <&stmmac_axi_setup>; ++ snps,tso; ++ snps,en-tx-lpi-clockgating; ++ snps,txpbl = <16>; ++ snps,rxpbl = <16>; ++ starfive,syscon = <&aon_syscon 0xc 0x12>; ++ status = "disabled"; ++ }; ++ ++ gmac1: ethernet@16040000 { ++ compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; ++ reg = <0x0 0x16040000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_GMAC1_AXI>, ++ <&syscrg JH7110_SYSCLK_GMAC1_AHB>, ++ <&syscrg JH7110_SYSCLK_GMAC1_PTP>, ++ <&syscrg JH7110_SYSCLK_GMAC1_TX_INV>, ++ <&syscrg JH7110_SYSCLK_GMAC1_GTXC>; ++ clock-names = "stmmaceth", "pclk", "ptp_ref", ++ "tx", "gtx"; ++ resets = <&syscrg JH7110_SYSRST_GMAC1_AXI>, ++ <&syscrg JH7110_SYSRST_GMAC1_AHB>; ++ reset-names = "stmmaceth", "ahb"; ++ interrupts = <78>, <77>, <76>; ++ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; ++ rx-fifo-depth = <2048>; ++ tx-fifo-depth = <2048>; ++ snps,multicast-filter-bins = <64>; ++ snps,perfect-filter-entries = <8>; ++ snps,fixed-burst; ++ snps,no-pbl-x8; ++ snps,force_thresh_dma_mode; ++ snps,axi-config = <&stmmac_axi_setup>; ++ snps,tso; ++ snps,en-tx-lpi-clockgating; ++ snps,txpbl = <16>; ++ snps,rxpbl = <16>; ++ starfive,syscon = <&sys_syscon 0x90 0x2>; ++ status = "disabled"; ++ }; ++ + aoncrg: clock-controller@17000000 { + compatible = "starfive,jh7110-aoncrg"; + reg = <0x0 0x17000000 0x0 0x10000>; diff --git a/target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch b/target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch new file mode 100644 index 0000000000..9fbdebf5f4 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch @@ -0,0 +1,128 @@ +From 6fd84cb9cceaa711671500a92dcee5b1072ab95a Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Tue, 1 Nov 2022 18:11:02 +0800 +Subject: [PATCH 047/122] riscv: dts: starfive: visionfive 2: Add configuration + of gmac and phy + +v1.3B: + v1.3B uses motorcomm YT8531(rgmii-id phy) x2, need delay and + inverse configurations. + The tx_clk of v1.3B uses an external clock and needs to be + switched to an external clock source. + +v1.2A: + v1.2A gmac0 uses motorcomm YT8531(rgmii-id) PHY, and needs delay + configurations. + v1.2A gmac1 uses motorcomm YT8512(rmii) PHY, and needs to + switch rx and rx to external clock sources. + +Tested-by: Tommaso Merciai +Signed-off-by: Samin Guo +--- + .../jh7110-starfive-visionfive-2-v1.2a.dts | 13 +++++++ + .../jh7110-starfive-visionfive-2-v1.3b.dts | 27 +++++++++++++++ + .../jh7110-starfive-visionfive-2.dtsi | 34 +++++++++++++++++++ + 3 files changed, 74 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts +@@ -11,3 +11,16 @@ + model = "StarFive VisionFive 2 v1.2A"; + compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110"; + }; ++ ++&gmac1 { ++ phy-mode = "rmii"; ++ assigned-clocks = <&syscrg JH7110_SYSCLK_GMAC1_TX>, ++ <&syscrg JH7110_SYSCLK_GMAC1_RX>; ++ assigned-clock-parents = <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>, ++ <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>; ++}; ++ ++&phy0 { ++ rx-internal-delay-ps = <1900>; ++ tx-internal-delay-ps = <1350>; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts +@@ -11,3 +11,30 @@ + model = "StarFive VisionFive 2 v1.3B"; + compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110"; + }; ++ ++&gmac0 { ++ starfive,tx-use-rgmii-clk; ++ assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>; ++ assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>; ++}; ++ ++&gmac1 { ++ starfive,tx-use-rgmii-clk; ++ assigned-clocks = <&syscrg JH7110_SYSCLK_GMAC1_TX>; ++ assigned-clock-parents = <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>; ++}; ++ ++&phy0 { ++ motorcomm,tx-clk-adj-enabled; ++ motorcomm,tx-clk-100-inverted; ++ motorcomm,tx-clk-1000-inverted; ++ rx-internal-delay-ps = <1500>; ++ tx-internal-delay-ps = <1500>; ++}; ++ ++&phy1 { ++ motorcomm,tx-clk-adj-enabled; ++ motorcomm,tx-clk-100-inverted; ++ rx-internal-delay-ps = <300>; ++ tx-internal-delay-ps = <0>; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -11,6 +11,8 @@ + + / { + aliases { ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + i2c0 = &i2c0; + i2c2 = &i2c2; + i2c5 = &i2c5; +@@ -86,6 +88,38 @@ + clock-frequency = <49152000>; + }; + ++&gmac0 { ++ phy-handle = <&phy0>; ++ phy-mode = "rgmii-id"; ++ status = "okay"; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "snps,dwmac-mdio"; ++ ++ phy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ }; ++}; ++ ++&gmac1 { ++ phy-handle = <&phy1>; ++ phy-mode = "rgmii-id"; ++ status = "okay"; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "snps,dwmac-mdio"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <0>; ++ }; ++ }; ++}; ++ + &i2c0 { + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <300>; diff --git a/target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch b/target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch new file mode 100644 index 0000000000..376481ee0f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch @@ -0,0 +1,147 @@ +From 96edc2f71ea7ac6683011609f6d1f51ae9ea0b7a Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Thu, 2 Feb 2023 11:00:33 +0800 +Subject: [PATCH 048/122] dt-bindings: net: Add Motorcomm yt8xxx ethernet phy + +Add a YAML binding document for the Motorcomm yt8xxx Ethernet phy. + +Signed-off-by: Frank Sae +Reviewed-by: Rob Herring +Signed-off-by: David S. Miller +--- + .../bindings/net/motorcomm,yt8xxx.yaml | 117 ++++++++++++++++++ + .../devicetree/bindings/vendor-prefixes.yaml | 2 + + 2 files changed, 119 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml +@@ -0,0 +1,117 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/motorcomm,yt8xxx.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MotorComm yt8xxx Ethernet PHY ++ ++maintainers: ++ - Frank Sae ++ ++allOf: ++ - $ref: ethernet-phy.yaml# ++ ++properties: ++ compatible: ++ enum: ++ - ethernet-phy-id4f51.e91a ++ - ethernet-phy-id4f51.e91b ++ ++ rx-internal-delay-ps: ++ description: | ++ RGMII RX Clock Delay used only when PHY operates in RGMII mode with ++ internal delay (phy-mode is 'rgmii-id' or 'rgmii-rxid') in pico-seconds. ++ enum: [ 0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, 1650, ++ 1800, 1900, 1950, 2050, 2100, 2200, 2250, 2350, 2500, 2650, 2800, ++ 2950, 3100, 3250, 3400, 3550, 3700, 3850, 4000, 4150 ] ++ default: 1950 ++ ++ tx-internal-delay-ps: ++ description: | ++ RGMII TX Clock Delay used only when PHY operates in RGMII mode with ++ internal delay (phy-mode is 'rgmii-id' or 'rgmii-txid') in pico-seconds. ++ enum: [ 0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, 1650, 1800, ++ 1950, 2100, 2250 ] ++ default: 1950 ++ ++ motorcomm,clk-out-frequency-hz: ++ description: clock output on clock output pin. ++ enum: [0, 25000000, 125000000] ++ default: 0 ++ ++ motorcomm,keep-pll-enabled: ++ description: | ++ If set, keep the PLL enabled even if there is no link. Useful if you ++ want to use the clock output without an ethernet link. ++ type: boolean ++ ++ motorcomm,auto-sleep-disabled: ++ description: | ++ If set, PHY will not enter sleep mode and close AFE after unplug cable ++ for a timer. ++ type: boolean ++ ++ motorcomm,tx-clk-adj-enabled: ++ description: | ++ This configuration is mainly to adapt to VF2 with JH7110 SoC. ++ Useful if you want to use tx-clk-xxxx-inverted to adj the delay of tx clk. ++ type: boolean ++ ++ motorcomm,tx-clk-10-inverted: ++ description: | ++ Use original or inverted RGMII Transmit PHY Clock to drive the RGMII ++ Transmit PHY Clock delay train configuration when speed is 10Mbps. ++ type: boolean ++ ++ motorcomm,tx-clk-100-inverted: ++ description: | ++ Use original or inverted RGMII Transmit PHY Clock to drive the RGMII ++ Transmit PHY Clock delay train configuration when speed is 100Mbps. ++ type: boolean ++ ++ motorcomm,tx-clk-1000-inverted: ++ description: | ++ Use original or inverted RGMII Transmit PHY Clock to drive the RGMII ++ Transmit PHY Clock delay train configuration when speed is 1000Mbps. ++ type: boolean ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ phy-mode = "rgmii-id"; ++ ethernet-phy@4 { ++ /* Only needed to make DT lint tools work. Do not copy/paste ++ * into real DTS files. ++ */ ++ compatible = "ethernet-phy-id4f51.e91a"; ++ ++ reg = <4>; ++ rx-internal-delay-ps = <2100>; ++ tx-internal-delay-ps = <150>; ++ motorcomm,clk-out-frequency-hz = <0>; ++ motorcomm,keep-pll-enabled; ++ motorcomm,auto-sleep-disabled; ++ }; ++ }; ++ - | ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ phy-mode = "rgmii"; ++ ethernet-phy@5 { ++ /* Only needed to make DT lint tools work. Do not copy/paste ++ * into real DTS files. ++ */ ++ compatible = "ethernet-phy-id4f51.e91a"; ++ ++ reg = <5>; ++ motorcomm,clk-out-frequency-hz = <125000000>; ++ motorcomm,keep-pll-enabled; ++ motorcomm,auto-sleep-disabled; ++ }; ++ }; +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -831,6 +831,8 @@ patternProperties: + description: Moortec Semiconductor Ltd. + "^mosaixtech,.*": + description: Mosaix Technologies, Inc. ++ "^motorcomm,.*": ++ description: MotorComm, Inc. + "^motorola,.*": + description: Motorola, Inc. + "^moxa,.*": diff --git a/target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch b/target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch new file mode 100644 index 0000000000..b9e9c65251 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch @@ -0,0 +1,34 @@ +From 2d146c6e550a4fb7f24ca44739cf14594cc2f892 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Tue, 25 Apr 2023 18:51:15 +0800 +Subject: [PATCH 049/122] dt-bindings: net: motorcomm: Add pad driver strength + cfg + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, the value range of pad driver +strength is 0 to 7. + +Signed-off-by: Samin Guo +--- + .../devicetree/bindings/net/motorcomm,yt8xxx.yaml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml ++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml +@@ -18,6 +18,16 @@ properties: + - ethernet-phy-id4f51.e91a + - ethernet-phy-id4f51.e91b + ++ rx-clk-driver-strength: ++ description: drive strength of rx_clk pad. ++ enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] ++ default: 3 ++ ++ rx-data-driver-strength: ++ description: drive strength of rxd/rx_ctl rgmii pad. ++ enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] ++ default: 3 ++ + rx-internal-delay-ps: + description: | + RGMII RX Clock Delay used only when PHY operates in RGMII mode with diff --git a/target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch b/target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch new file mode 100644 index 0000000000..8dca72ad16 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch @@ -0,0 +1,34 @@ +From c156cb9ec64669600c96dbb01bf38dd2370b1850 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Wed, 26 Apr 2023 14:41:12 +0800 +Subject: [PATCH 050/122] riscv: dts: starfive: visionfive-2-v1.3B: Set the + driver strength of RXC/RXD + +VisionFive 2 v1.3B needs to increase the driver strength of rxd/rxc +to increase the stability of gmac's transmission. + +Signed-off-by: Samin Guo +--- + .../boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts +@@ -28,6 +28,8 @@ + motorcomm,tx-clk-adj-enabled; + motorcomm,tx-clk-100-inverted; + motorcomm,tx-clk-1000-inverted; ++ rx-clk-driver-strength = <0x6>; ++ rx-data-driver-strength = <0x3>; + rx-internal-delay-ps = <1500>; + tx-internal-delay-ps = <1500>; + }; +@@ -35,6 +37,8 @@ + &phy1 { + motorcomm,tx-clk-adj-enabled; + motorcomm,tx-clk-100-inverted; ++ rx-clk-driver-strength = <0x6>; ++ rx-data-driver-strength = <0x3>; + rx-internal-delay-ps = <300>; + tx-internal-delay-ps = <0>; + }; diff --git a/target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch b/target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch new file mode 100644 index 0000000000..6617e79965 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch @@ -0,0 +1,193 @@ +From 84575863e4cf1a5dd877a11d31115c19004ac36a Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:24 +0800 +Subject: [PATCH 051/122] dt-bindings: clock: Add StarFive JH7110 + System-Top-Group clock and reset generator + +Add bindings for the System-Top-Group clock and reset generator (STGCRG) +on the JH7110 RISC-V SoC by StarFive Ltd. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Xingyu Wu +--- + .../clock/starfive,jh7110-stgcrg.yaml | 82 +++++++++++++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 34 ++++++++ + .../dt-bindings/reset/starfive,jh7110-crg.h | 28 +++++++ + 3 files changed, 144 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-stgcrg.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-stgcrg.yaml +@@ -0,0 +1,82 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-stgcrg.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 System-Top-Group Clock and Reset Generator ++ ++maintainers: ++ - Xingyu Wu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-stgcrg ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: Main Oscillator (24 MHz) ++ - description: HIFI4 core ++ - description: STG AXI/AHB ++ - description: USB (125 MHz) ++ - description: CPU Bus ++ - description: HIFI4 Axi ++ - description: NOC STG Bus ++ - description: APB Bus ++ ++ clock-names: ++ items: ++ - const: osc ++ - const: hifi4_core ++ - const: stg_axiahb ++ - const: usb_125m ++ - const: cpu_bus ++ - const: hifi4_axi ++ - const: nocstg_bus ++ - const: apb_bus ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ '#reset-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - '#clock-cells' ++ - '#reset-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ stgcrg: clock-controller@10230000 { ++ compatible = "starfive,jh7110-stgcrg"; ++ reg = <0x10230000 0x10000>; ++ clocks = <&osc>, ++ <&syscrg JH7110_SYSCLK_HIFI4_CORE>, ++ <&syscrg JH7110_SYSCLK_STG_AXIAHB>, ++ <&syscrg JH7110_SYSCLK_USB_125M>, ++ <&syscrg JH7110_SYSCLK_CPU_BUS>, ++ <&syscrg JH7110_SYSCLK_HIFI4_AXI>, ++ <&syscrg JH7110_SYSCLK_NOCSTG_BUS>, ++ <&syscrg JH7110_SYSCLK_APB_BUS>; ++ clock-names = "osc", "hifi4_core", ++ "stg_axiahb", "usb_125m", ++ "cpu_bus", "hifi4_axi", ++ "nocstg_bus", "apb_bus"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; +--- a/include/dt-bindings/clock/starfive,jh7110-crg.h ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 OR MIT */ + /* + * Copyright 2022 Emil Renner Berthing ++ * Copyright 2022 StarFive Technology Co., Ltd. + */ + + #ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ +@@ -224,4 +225,37 @@ + + #define JH7110_AONCLK_END 14 + ++/* STGCRG clocks */ ++#define JH7110_STGCLK_HIFI4_CLK_CORE 0 ++#define JH7110_STGCLK_USB0_APB 1 ++#define JH7110_STGCLK_USB0_UTMI_APB 2 ++#define JH7110_STGCLK_USB0_AXI 3 ++#define JH7110_STGCLK_USB0_LPM 4 ++#define JH7110_STGCLK_USB0_STB 5 ++#define JH7110_STGCLK_USB0_APP_125 6 ++#define JH7110_STGCLK_USB0_REFCLK 7 ++#define JH7110_STGCLK_PCIE0_AXI_MST0 8 ++#define JH7110_STGCLK_PCIE0_APB 9 ++#define JH7110_STGCLK_PCIE0_TL 10 ++#define JH7110_STGCLK_PCIE1_AXI_MST0 11 ++#define JH7110_STGCLK_PCIE1_APB 12 ++#define JH7110_STGCLK_PCIE1_TL 13 ++#define JH7110_STGCLK_PCIE_SLV_MAIN 14 ++#define JH7110_STGCLK_SEC_AHB 15 ++#define JH7110_STGCLK_SEC_MISC_AHB 16 ++#define JH7110_STGCLK_GRP0_MAIN 17 ++#define JH7110_STGCLK_GRP0_BUS 18 ++#define JH7110_STGCLK_GRP0_STG 19 ++#define JH7110_STGCLK_GRP1_MAIN 20 ++#define JH7110_STGCLK_GRP1_BUS 21 ++#define JH7110_STGCLK_GRP1_STG 22 ++#define JH7110_STGCLK_GRP1_HIFI 23 ++#define JH7110_STGCLK_E2_RTC 24 ++#define JH7110_STGCLK_E2_CORE 25 ++#define JH7110_STGCLK_E2_DBG 26 ++#define JH7110_STGCLK_DMA1P_AXI 27 ++#define JH7110_STGCLK_DMA1P_AHB 28 ++ ++#define JH7110_STGCLK_END 29 ++ + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */ +--- a/include/dt-bindings/reset/starfive,jh7110-crg.h ++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 OR MIT */ + /* + * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. + */ + + #ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ +@@ -151,4 +152,31 @@ + + #define JH7110_AONRST_END 8 + ++/* STGCRG resets */ ++#define JH7110_STGRST_SYSCON 0 ++#define JH7110_STGRST_HIFI4_CORE 1 ++#define JH7110_STGRST_HIFI4_AXI 2 ++#define JH7110_STGRST_SEC_AHB 3 ++#define JH7110_STGRST_E24_CORE 4 ++#define JH7110_STGRST_DMA1P_AXI 5 ++#define JH7110_STGRST_DMA1P_AHB 6 ++#define JH7110_STGRST_USB0_AXI 7 ++#define JH7110_STGRST_USB0_APB 8 ++#define JH7110_STGRST_USB0_UTMI_APB 9 ++#define JH7110_STGRST_USB0_PWRUP 10 ++#define JH7110_STGRST_PCIE0_AXI_MST0 11 ++#define JH7110_STGRST_PCIE0_AXI_SLV0 12 ++#define JH7110_STGRST_PCIE0_AXI_SLV 13 ++#define JH7110_STGRST_PCIE0_BRG 14 ++#define JH7110_STGRST_PCIE0_CORE 15 ++#define JH7110_STGRST_PCIE0_APB 16 ++#define JH7110_STGRST_PCIE1_AXI_MST0 17 ++#define JH7110_STGRST_PCIE1_AXI_SLV0 18 ++#define JH7110_STGRST_PCIE1_AXI_SLV 19 ++#define JH7110_STGRST_PCIE1_BRG 20 ++#define JH7110_STGRST_PCIE1_CORE 21 ++#define JH7110_STGRST_PCIE1_APB 22 ++ ++#define JH7110_STGRST_END 23 ++ + #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */ diff --git a/target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch b/target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch new file mode 100644 index 0000000000..88b24a9c6d --- /dev/null +++ b/target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch @@ -0,0 +1,218 @@ +From 9a02d66b0515d987037d0229b99367412b9eb38c Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Thu, 18 May 2023 18:12:25 +0800 +Subject: [PATCH 052/122] clk: starfive: Add StarFive JH7110 System-Top-Group + clock driver + +Add driver for the StarFive JH7110 System-Top-Group clock controller. + +Co-developed-by: Xingyu Wu +Signed-off-by: Xingyu Wu +Signed-off-by: Emil Renner Berthing +--- + drivers/clk/starfive/Kconfig | 11 ++ + drivers/clk/starfive/Makefile | 1 + + .../clk/starfive/clk-starfive-jh7110-stg.c | 173 ++++++++++++++++++ + 3 files changed, 185 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-stg.c + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -51,3 +51,14 @@ config CLK_STARFIVE_JH7110_AON + help + Say yes here to support the always-on clock controller on the + StarFive JH7110 SoC. ++ ++config CLK_STARFIVE_JH7110_STG ++ tristate "StarFive JH7110 System-Top-Group clock support" ++ depends on CLK_STARFIVE_JH7110_SYS ++ select AUXILIARY_BUS ++ select CLK_STARFIVE_JH71X0 ++ select RESET_STARFIVE_JH7110 ++ default m if ARCH_STARFIVE ++ help ++ Say yes here to support the System-Top-Group clock controller ++ on the StarFive JH7110 SoC. +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) + obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL) += clk-starfive-jh7110-pll.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += clk-starfive-jh7110-sys.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_AON) += clk-starfive-jh7110-aon.o ++obj-$(CONFIG_CLK_STARFIVE_JH7110_STG) += clk-starfive-jh7110-stg.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-stg.c +@@ -0,0 +1,173 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 System-Top-Group Clock Driver ++ * ++ * Copyright (C) 2022 Emil Renner Berthing ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110.h" ++ ++/* external clocks */ ++#define JH7110_STGCLK_OSC (JH7110_STGCLK_END + 0) ++#define JH7110_STGCLK_HIFI4_CORE (JH7110_STGCLK_END + 1) ++#define JH7110_STGCLK_STG_AXIAHB (JH7110_STGCLK_END + 2) ++#define JH7110_STGCLK_USB_125M (JH7110_STGCLK_END + 3) ++#define JH7110_STGCLK_CPU_BUS (JH7110_STGCLK_END + 4) ++#define JH7110_STGCLK_HIFI4_AXI (JH7110_STGCLK_END + 5) ++#define JH7110_STGCLK_NOCSTG_BUS (JH7110_STGCLK_END + 6) ++#define JH7110_STGCLK_APB_BUS (JH7110_STGCLK_END + 7) ++#define JH7110_STGCLK_EXT_END (JH7110_STGCLK_END + 8) ++ ++static const struct jh71x0_clk_data jh7110_stgclk_data[] = { ++ /* hifi4 */ ++ JH71X0_GATE(JH7110_STGCLK_HIFI4_CLK_CORE, "hifi4_clk_core", 0, ++ JH7110_STGCLK_HIFI4_CORE), ++ /* usb */ ++ JH71X0_GATE(JH7110_STGCLK_USB0_APB, "usb0_apb", 0, JH7110_STGCLK_APB_BUS), ++ JH71X0_GATE(JH7110_STGCLK_USB0_UTMI_APB, "usb0_utmi_apb", 0, JH7110_STGCLK_APB_BUS), ++ JH71X0_GATE(JH7110_STGCLK_USB0_AXI, "usb0_axi", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GDIV(JH7110_STGCLK_USB0_LPM, "usb0_lpm", 0, 2, JH7110_STGCLK_OSC), ++ JH71X0_GDIV(JH7110_STGCLK_USB0_STB, "usb0_stb", 0, 4, JH7110_STGCLK_OSC), ++ JH71X0_GATE(JH7110_STGCLK_USB0_APP_125, "usb0_app_125", 0, JH7110_STGCLK_USB_125M), ++ JH71X0__DIV(JH7110_STGCLK_USB0_REFCLK, "usb0_refclk", 2, JH7110_STGCLK_OSC), ++ /* pci-e */ ++ JH71X0_GATE(JH7110_STGCLK_PCIE0_AXI_MST0, "pcie0_axi_mst0", 0, ++ JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_PCIE0_APB, "pcie0_apb", 0, JH7110_STGCLK_APB_BUS), ++ JH71X0_GATE(JH7110_STGCLK_PCIE0_TL, "pcie0_tl", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_PCIE1_AXI_MST0, "pcie1_axi_mst0", 0, ++ JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_PCIE1_APB, "pcie1_apb", 0, JH7110_STGCLK_APB_BUS), ++ JH71X0_GATE(JH7110_STGCLK_PCIE1_TL, "pcie1_tl", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_PCIE_SLV_MAIN, "pcie_slv_main", CLK_IS_CRITICAL, ++ JH7110_STGCLK_STG_AXIAHB), ++ /* security */ ++ JH71X0_GATE(JH7110_STGCLK_SEC_AHB, "sec_ahb", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_SEC_MISC_AHB, "sec_misc_ahb", 0, JH7110_STGCLK_STG_AXIAHB), ++ /* stg mtrx */ ++ JH71X0_GATE(JH7110_STGCLK_GRP0_MAIN, "mtrx_grp0_main", CLK_IS_CRITICAL, ++ JH7110_STGCLK_CPU_BUS), ++ JH71X0_GATE(JH7110_STGCLK_GRP0_BUS, "mtrx_grp0_bus", CLK_IS_CRITICAL, ++ JH7110_STGCLK_NOCSTG_BUS), ++ JH71X0_GATE(JH7110_STGCLK_GRP0_STG, "mtrx_grp0_stg", CLK_IS_CRITICAL, ++ JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_GRP1_MAIN, "mtrx_grp1_main", CLK_IS_CRITICAL, ++ JH7110_STGCLK_CPU_BUS), ++ JH71X0_GATE(JH7110_STGCLK_GRP1_BUS, "mtrx_grp1_bus", CLK_IS_CRITICAL, ++ JH7110_STGCLK_NOCSTG_BUS), ++ JH71X0_GATE(JH7110_STGCLK_GRP1_STG, "mtrx_grp1_stg", CLK_IS_CRITICAL, ++ JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_GRP1_HIFI, "mtrx_grp1_hifi", CLK_IS_CRITICAL, ++ JH7110_STGCLK_HIFI4_AXI), ++ /* e24_rvpi */ ++ JH71X0_GDIV(JH7110_STGCLK_E2_RTC, "e2_rtc", 0, 24, JH7110_STGCLK_OSC), ++ JH71X0_GATE(JH7110_STGCLK_E2_CORE, "e2_core", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_E2_DBG, "e2_dbg", 0, JH7110_STGCLK_STG_AXIAHB), ++ /* dw_sgdma1p */ ++ JH71X0_GATE(JH7110_STGCLK_DMA1P_AXI, "dma1p_axi", 0, JH7110_STGCLK_STG_AXIAHB), ++ JH71X0_GATE(JH7110_STGCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7110_STGCLK_STG_AXIAHB), ++}; ++ ++static struct clk_hw *jh7110_stgclk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh71x0_clk_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_STGCLK_END) ++ return &priv->reg[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++static int jh7110_stgcrg_probe(struct platform_device *pdev) ++{ ++ struct jh71x0_clk_priv *priv; ++ unsigned int idx; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7110_STGCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->rmw_lock); ++ priv->dev = &pdev->dev; ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ for (idx = 0; idx < JH7110_STGCLK_END; idx++) { ++ u32 max = jh7110_stgclk_data[idx].max; ++ struct clk_parent_data parents[4] = {}; ++ struct clk_init_data init = { ++ .name = jh7110_stgclk_data[idx].name, ++ .ops = starfive_jh71x0_clk_ops(max), ++ .parent_data = parents, ++ .num_parents = ++ ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, ++ .flags = jh7110_stgclk_data[idx].flags, ++ }; ++ struct jh71x0_clk *clk = &priv->reg[idx]; ++ const char *fw_name[JH7110_STGCLK_EXT_END - JH7110_STGCLK_END] = { ++ "osc", ++ "hifi4_core", ++ "stg_axiahb", ++ "usb_125m", ++ "cpu_bus", ++ "hifi4_axi", ++ "nocstg_bus", ++ "apb_bus" ++ }; ++ unsigned int i; ++ ++ for (i = 0; i < init.num_parents; i++) { ++ unsigned int pidx = jh7110_stgclk_data[idx].parents[i]; ++ ++ if (pidx < JH7110_STGCLK_END) ++ parents[i].hw = &priv->reg[pidx].hw; ++ else if (pidx < JH7110_STGCLK_EXT_END) ++ parents[i].fw_name = fw_name[pidx - JH7110_STGCLK_END]; ++ } ++ ++ clk->hw.init = &init; ++ clk->idx = idx; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clk->hw); ++ if (ret) ++ return ret; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_stgclk_get, priv); ++ if (ret) ++ return ret; ++ ++ return jh7110_reset_controller_register(priv, "rst-stg", 2); ++} ++ ++static const struct of_device_id jh7110_stgcrg_match[] = { ++ { .compatible = "starfive,jh7110-stgcrg" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_stgcrg_match); ++ ++static struct platform_driver jh7110_stgcrg_driver = { ++ .probe = jh7110_stgcrg_probe, ++ .driver = { ++ .name = "clk-starfive-jh7110-stg", ++ .of_match_table = jh7110_stgcrg_match, ++ }, ++}; ++module_platform_driver(jh7110_stgcrg_driver); ++ ++MODULE_AUTHOR("Xingyu Wu "); ++MODULE_AUTHOR("Emil Renner Berthing "); ++MODULE_DESCRIPTION("StarFive JH7110 System-Top-Group clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch b/target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch new file mode 100644 index 0000000000..eda4a0280a --- /dev/null +++ b/target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch @@ -0,0 +1,156 @@ +From 70df2590923e262ce8bf2b4f497f3481511d4fd6 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:26 +0800 +Subject: [PATCH 053/122] dt-bindings: clock: Add StarFive JH7110 + Image-Signal-Process clock and reset generator + +Add bindings for the Image-Signal-Process clock and reset +generator (ISPCRG) on the JH7110 RISC-V SoC by StarFive Ltd. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Xingyu Wu +--- + .../clock/starfive,jh7110-ispcrg.yaml | 87 +++++++++++++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 18 ++++ + .../dt-bindings/reset/starfive,jh7110-crg.h | 16 ++++ + 3 files changed, 121 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-ispcrg.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-ispcrg.yaml +@@ -0,0 +1,87 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-ispcrg.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 Image-Signal-Process Clock and Reset Generator ++ ++maintainers: ++ - Xingyu Wu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-ispcrg ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: ISP Top core ++ - description: ISP Top Axi ++ - description: NOC ISP Bus ++ - description: external DVP ++ ++ clock-names: ++ items: ++ - const: isp_top_core ++ - const: isp_top_axi ++ - const: noc_bus_isp_axi ++ - const: dvp_clk ++ ++ resets: ++ items: ++ - description: ISP Top core ++ - description: ISP Top Axi ++ - description: NOC ISP Bus ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ '#reset-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ power-domains: ++ maxItems: 1 ++ description: ++ ISP domain power ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - '#clock-cells' ++ - '#reset-cells' ++ - power-domains ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ ++ ispcrg: clock-controller@19810000 { ++ compatible = "starfive,jh7110-ispcrg"; ++ reg = <0x19810000 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_ISP_TOP_CORE>, ++ <&syscrg JH7110_SYSCLK_ISP_TOP_AXI>, ++ <&syscrg JH7110_SYSCLK_NOC_BUS_ISP_AXI>, ++ <&dvp_clk>; ++ clock-names = "isp_top_core", "isp_top_axi", ++ "noc_bus_isp_axi", "dvp_clk"; ++ resets = <&syscrg JH7110_SYSRST_ISP_TOP>, ++ <&syscrg JH7110_SYSRST_ISP_TOP_AXI>, ++ <&syscrg JH7110_SYSRST_NOC_BUS_ISP_AXI>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ power-domains = <&pwrc JH7110_PD_ISP>; ++ }; +--- a/include/dt-bindings/clock/starfive,jh7110-crg.h ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -258,4 +258,22 @@ + + #define JH7110_STGCLK_END 29 + ++/* ISPCRG clocks */ ++#define JH7110_ISPCLK_DOM4_APB_FUNC 0 ++#define JH7110_ISPCLK_MIPI_RX0_PXL 1 ++#define JH7110_ISPCLK_DVP_INV 2 ++#define JH7110_ISPCLK_M31DPHY_CFG_IN 3 ++#define JH7110_ISPCLK_M31DPHY_REF_IN 4 ++#define JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0 5 ++#define JH7110_ISPCLK_VIN_APB 6 ++#define JH7110_ISPCLK_VIN_SYS 7 ++#define JH7110_ISPCLK_VIN_PIXEL_IF0 8 ++#define JH7110_ISPCLK_VIN_PIXEL_IF1 9 ++#define JH7110_ISPCLK_VIN_PIXEL_IF2 10 ++#define JH7110_ISPCLK_VIN_PIXEL_IF3 11 ++#define JH7110_ISPCLK_VIN_P_AXI_WR 12 ++#define JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C 13 ++ ++#define JH7110_ISPCLK_END 14 ++ + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */ +--- a/include/dt-bindings/reset/starfive,jh7110-crg.h ++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h +@@ -179,4 +179,20 @@ + + #define JH7110_STGRST_END 23 + ++/* ISPCRG resets */ ++#define JH7110_ISPRST_ISPV2_TOP_WRAPPER_P 0 ++#define JH7110_ISPRST_ISPV2_TOP_WRAPPER_C 1 ++#define JH7110_ISPRST_M31DPHY_HW 2 ++#define JH7110_ISPRST_M31DPHY_B09_AON 3 ++#define JH7110_ISPRST_VIN_APB 4 ++#define JH7110_ISPRST_VIN_PIXEL_IF0 5 ++#define JH7110_ISPRST_VIN_PIXEL_IF1 6 ++#define JH7110_ISPRST_VIN_PIXEL_IF2 7 ++#define JH7110_ISPRST_VIN_PIXEL_IF3 8 ++#define JH7110_ISPRST_VIN_SYS 9 ++#define JH7110_ISPRST_VIN_P_AXI_RD 10 ++#define JH7110_ISPRST_VIN_P_AXI_WR 11 ++ ++#define JH7110_ISPRST_END 12 ++ + #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */ diff --git a/target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch b/target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch new file mode 100644 index 0000000000..2e049e77dd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch @@ -0,0 +1,293 @@ +From 003c13d81b525a184c5ca551e536e6786e2d2f5c Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:27 +0800 +Subject: [PATCH 054/122] clk: starfive: Add StarFive JH7110 + Image-Signal-Process clock driver + +Add driver for the StarFive JH7110 Image-Signal-Process clock controller. +And these clock controllers should power on and enable the clocks from +SYSCRG first before registering. + +Signed-off-by: Xingyu Wu +--- + drivers/clk/starfive/Kconfig | 11 + + drivers/clk/starfive/Makefile | 1 + + .../clk/starfive/clk-starfive-jh7110-isp.c | 232 ++++++++++++++++++ + drivers/clk/starfive/clk-starfive-jh7110.h | 6 + + 4 files changed, 250 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-isp.c + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -62,3 +62,14 @@ config CLK_STARFIVE_JH7110_STG + help + Say yes here to support the System-Top-Group clock controller + on the StarFive JH7110 SoC. ++ ++config CLK_STARFIVE_JH7110_ISP ++ tristate "StarFive JH7110 Image-Signal-Process clock support" ++ depends on CLK_STARFIVE_JH7110_SYS && JH71XX_PMU ++ select AUXILIARY_BUS ++ select CLK_STARFIVE_JH71X0 ++ select RESET_STARFIVE_JH7110 ++ default m if ARCH_STARFIVE ++ help ++ Say yes here to support the Image-Signal-Process clock controller ++ on the StarFive JH7110 SoC. +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL) += + obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += clk-starfive-jh7110-sys.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_AON) += clk-starfive-jh7110-aon.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_STG) += clk-starfive-jh7110-stg.o ++obj-$(CONFIG_CLK_STARFIVE_JH7110_ISP) += clk-starfive-jh7110-isp.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c +@@ -0,0 +1,232 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 Image-Signal-Process Clock Driver ++ * ++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110.h" ++ ++/* external clocks */ ++#define JH7110_ISPCLK_ISP_TOP_CORE (JH7110_ISPCLK_END + 0) ++#define JH7110_ISPCLK_ISP_TOP_AXI (JH7110_ISPCLK_END + 1) ++#define JH7110_ISPCLK_NOC_BUS_ISP_AXI (JH7110_ISPCLK_END + 2) ++#define JH7110_ISPCLK_DVP_CLK (JH7110_ISPCLK_END + 3) ++#define JH7110_ISPCLK_EXT_END (JH7110_ISPCLK_END + 4) ++ ++static struct clk_bulk_data jh7110_isp_top_clks[] = { ++ { .id = "isp_top_core" }, ++ { .id = "isp_top_axi" } ++}; ++ ++static const struct jh71x0_clk_data jh7110_ispclk_data[] = { ++ /* syscon */ ++ JH71X0__DIV(JH7110_ISPCLK_DOM4_APB_FUNC, "dom4_apb_func", 15, ++ JH7110_ISPCLK_ISP_TOP_AXI), ++ JH71X0__DIV(JH7110_ISPCLK_MIPI_RX0_PXL, "mipi_rx0_pxl", 8, ++ JH7110_ISPCLK_ISP_TOP_CORE), ++ JH71X0__INV(JH7110_ISPCLK_DVP_INV, "dvp_inv", JH7110_ISPCLK_DVP_CLK), ++ /* vin */ ++ JH71X0__DIV(JH7110_ISPCLK_M31DPHY_CFG_IN, "m31dphy_cfg_in", 16, ++ JH7110_ISPCLK_ISP_TOP_CORE), ++ JH71X0__DIV(JH7110_ISPCLK_M31DPHY_REF_IN, "m31dphy_ref_in", 16, ++ JH7110_ISPCLK_ISP_TOP_CORE), ++ JH71X0__DIV(JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0, "m31dphy_tx_esc_lan0", 60, ++ JH7110_ISPCLK_ISP_TOP_CORE), ++ JH71X0_GATE(JH7110_ISPCLK_VIN_APB, "vin_apb", 0, ++ JH7110_ISPCLK_DOM4_APB_FUNC), ++ JH71X0__DIV(JH7110_ISPCLK_VIN_SYS, "vin_sys", 8, JH7110_ISPCLK_ISP_TOP_CORE), ++ JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF0, "vin_pixel_if0", 0, ++ JH7110_ISPCLK_MIPI_RX0_PXL), ++ JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF1, "vin_pixel_if1", 0, ++ JH7110_ISPCLK_MIPI_RX0_PXL), ++ JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF2, "vin_pixel_if2", 0, ++ JH7110_ISPCLK_MIPI_RX0_PXL), ++ JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF3, "vin_pixel_if3", 0, ++ JH7110_ISPCLK_MIPI_RX0_PXL), ++ JH71X0__MUX(JH7110_ISPCLK_VIN_P_AXI_WR, "vin_p_axi_wr", 2, ++ JH7110_ISPCLK_MIPI_RX0_PXL, ++ JH7110_ISPCLK_DVP_INV), ++ /* ispv2_top_wrapper */ ++ JH71X0_GMUX(JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C, "ispv2_top_wrapper_c", 0, 2, ++ JH7110_ISPCLK_MIPI_RX0_PXL, ++ JH7110_ISPCLK_DVP_INV), ++}; ++ ++static inline int jh7110_isp_top_rst_init(struct jh71x0_clk_priv *priv) ++{ ++ struct reset_control *top_rsts; ++ ++ /* The resets should be shared and other ISP modules will use its. */ ++ top_rsts = devm_reset_control_array_get_shared(priv->dev); ++ if (IS_ERR(top_rsts)) ++ return dev_err_probe(priv->dev, PTR_ERR(top_rsts), ++ "failed to get top resets\n"); ++ ++ return reset_control_deassert(top_rsts); ++} ++ ++static struct clk_hw *jh7110_ispclk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh71x0_clk_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_ISPCLK_END) ++ return &priv->reg[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++#ifdef CONFIG_PM ++static int jh7110_ispcrg_suspend(struct device *dev) ++{ ++ struct top_sysclk *top = dev_get_drvdata(dev); ++ ++ clk_bulk_disable_unprepare(top->top_clks_num, top->top_clks); ++ ++ return 0; ++} ++ ++static int jh7110_ispcrg_resume(struct device *dev) ++{ ++ struct top_sysclk *top = dev_get_drvdata(dev); ++ ++ return clk_bulk_prepare_enable(top->top_clks_num, top->top_clks); ++} ++#endif ++ ++static const struct dev_pm_ops jh7110_ispcrg_pm_ops = { ++ SET_RUNTIME_PM_OPS(jh7110_ispcrg_suspend, jh7110_ispcrg_resume, NULL) ++}; ++ ++static int jh7110_ispcrg_probe(struct platform_device *pdev) ++{ ++ struct jh71x0_clk_priv *priv; ++ struct top_sysclk *top; ++ unsigned int idx; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, ++ struct_size(priv, reg, JH7110_ISPCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ top = devm_kzalloc(&pdev->dev, sizeof(*top), GFP_KERNEL); ++ if (!top) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->rmw_lock); ++ priv->dev = &pdev->dev; ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ top->top_clks = jh7110_isp_top_clks; ++ top->top_clks_num = ARRAY_SIZE(jh7110_isp_top_clks); ++ ret = devm_clk_bulk_get(priv->dev, top->top_clks_num, top->top_clks); ++ if (ret) ++ return dev_err_probe(priv->dev, ret, "failed to get main clocks\n"); ++ dev_set_drvdata(priv->dev, top); ++ ++ /* enable power domain and clocks */ ++ pm_runtime_enable(priv->dev); ++ ret = pm_runtime_get_sync(priv->dev); ++ if (ret < 0) ++ return dev_err_probe(priv->dev, ret, "failed to turn on power\n"); ++ ++ ret = jh7110_isp_top_rst_init(priv); ++ if (ret) ++ goto err_exit; ++ ++ for (idx = 0; idx < JH7110_ISPCLK_END; idx++) { ++ u32 max = jh7110_ispclk_data[idx].max; ++ struct clk_parent_data parents[4] = {}; ++ struct clk_init_data init = { ++ .name = jh7110_ispclk_data[idx].name, ++ .ops = starfive_jh71x0_clk_ops(max), ++ .parent_data = parents, ++ .num_parents = ++ ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, ++ .flags = jh7110_ispclk_data[idx].flags, ++ }; ++ struct jh71x0_clk *clk = &priv->reg[idx]; ++ unsigned int i; ++ const char *fw_name[JH7110_ISPCLK_EXT_END - JH7110_ISPCLK_END] = { ++ "isp_top_core", ++ "isp_top_axi", ++ "noc_bus_isp_axi", ++ "dvp_clk" ++ }; ++ ++ for (i = 0; i < init.num_parents; i++) { ++ unsigned int pidx = jh7110_ispclk_data[idx].parents[i]; ++ ++ if (pidx < JH7110_ISPCLK_END) ++ parents[i].hw = &priv->reg[pidx].hw; ++ else ++ parents[i].fw_name = fw_name[pidx - JH7110_ISPCLK_END]; ++ } ++ ++ clk->hw.init = &init; ++ clk->idx = idx; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clk->hw); ++ if (ret) ++ goto err_exit; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_ispclk_get, priv); ++ if (ret) ++ goto err_exit; ++ ++ ret = jh7110_reset_controller_register(priv, "rst-isp", 3); ++ if (ret) ++ goto err_exit; ++ ++ return 0; ++ ++err_exit: ++ pm_runtime_put_sync(priv->dev); ++ pm_runtime_disable(priv->dev); ++ return ret; ++} ++ ++static int jh7110_ispcrg_remove(struct platform_device *pdev) ++{ ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id jh7110_ispcrg_match[] = { ++ { .compatible = "starfive,jh7110-ispcrg" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_ispcrg_match); ++ ++static struct platform_driver jh7110_ispcrg_driver = { ++ .probe = jh7110_ispcrg_probe, ++ .remove = jh7110_ispcrg_remove, ++ .driver = { ++ .name = "clk-starfive-jh7110-isp", ++ .of_match_table = jh7110_ispcrg_match, ++ .pm = &jh7110_ispcrg_pm_ops, ++ }, ++}; ++module_platform_driver(jh7110_ispcrg_driver); ++ ++MODULE_AUTHOR("Xingyu Wu "); ++MODULE_DESCRIPTION("StarFive JH7110 Image-Signal-Process clock driver"); ++MODULE_LICENSE("GPL"); +--- a/drivers/clk/starfive/clk-starfive-jh7110.h ++++ b/drivers/clk/starfive/clk-starfive-jh7110.h +@@ -4,6 +4,12 @@ + + #include "clk-starfive-jh71x0.h" + ++/* top clocks of ISP/VOUT domain from SYSCRG */ ++struct top_sysclk { ++ struct clk_bulk_data *top_clks; ++ int top_clks_num; ++}; ++ + int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv, + const char *adev_name, + u32 adev_id); diff --git a/target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch b/target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch new file mode 100644 index 0000000000..fabc6aac17 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch @@ -0,0 +1,163 @@ +From 06fa910083f37ecbc9234c7230dcbbd4d83e2f02 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:28 +0800 +Subject: [PATCH 055/122] dt-bindings: clock: Add StarFive JH7110 Video-Output + clock and reset generator + +Add bindings for the Video-Output clock and reset generator (VOUTCRG) +on the JH7110 RISC-V SoC by StarFive Ltd. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Xingyu Wu +--- + .../clock/starfive,jh7110-voutcrg.yaml | 90 +++++++++++++++++++ + .../dt-bindings/clock/starfive,jh7110-crg.h | 22 +++++ + .../dt-bindings/reset/starfive,jh7110-crg.h | 16 ++++ + 3 files changed, 128 insertions(+) + create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-voutcrg.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-voutcrg.yaml +@@ -0,0 +1,90 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/starfive,jh7110-voutcrg.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 Video-Output Clock and Reset Generator ++ ++maintainers: ++ - Xingyu Wu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-voutcrg ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: Vout Top core ++ - description: Vout Top Ahb ++ - description: Vout Top Axi ++ - description: Vout Top HDMI MCLK ++ - description: I2STX0 BCLK ++ - description: external HDMI pixel ++ ++ clock-names: ++ items: ++ - const: vout_src ++ - const: vout_top_ahb ++ - const: vout_top_axi ++ - const: vout_top_hdmitx0_mclk ++ - const: i2stx0_bclk ++ - const: hdmitx0_pixelclk ++ ++ resets: ++ maxItems: 1 ++ description: Vout Top core ++ ++ '#clock-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ '#reset-cells': ++ const: 1 ++ description: ++ See for valid indices. ++ ++ power-domains: ++ maxItems: 1 ++ description: ++ Vout domain power ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - '#clock-cells' ++ - '#reset-cells' ++ - power-domains ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ ++ voutcrg: clock-controller@295C0000 { ++ compatible = "starfive,jh7110-voutcrg"; ++ reg = <0x295C0000 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>, ++ <&syscrg JH7110_SYSCLK_I2STX0_BCLK>, ++ <&hdmitx0_pixelclk>; ++ clock-names = "vout_src", "vout_top_ahb", ++ "vout_top_axi", "vout_top_hdmitx0_mclk", ++ "i2stx0_bclk", "hdmitx0_pixelclk"; ++ resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ power-domains = <&pwrc JH7110_PD_VOUT>; ++ }; +--- a/include/dt-bindings/clock/starfive,jh7110-crg.h ++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h +@@ -276,4 +276,26 @@ + + #define JH7110_ISPCLK_END 14 + ++/* VOUTCRG clocks */ ++#define JH7110_VOUTCLK_APB 0 ++#define JH7110_VOUTCLK_DC8200_PIX 1 ++#define JH7110_VOUTCLK_DSI_SYS 2 ++#define JH7110_VOUTCLK_TX_ESC 3 ++#define JH7110_VOUTCLK_DC8200_AXI 4 ++#define JH7110_VOUTCLK_DC8200_CORE 5 ++#define JH7110_VOUTCLK_DC8200_AHB 6 ++#define JH7110_VOUTCLK_DC8200_PIX0 7 ++#define JH7110_VOUTCLK_DC8200_PIX1 8 ++#define JH7110_VOUTCLK_DOM_VOUT_TOP_LCD 9 ++#define JH7110_VOUTCLK_DSITX_APB 10 ++#define JH7110_VOUTCLK_DSITX_SYS 11 ++#define JH7110_VOUTCLK_DSITX_DPI 12 ++#define JH7110_VOUTCLK_DSITX_TXESC 13 ++#define JH7110_VOUTCLK_MIPITX_DPHY_TXESC 14 ++#define JH7110_VOUTCLK_HDMI_TX_MCLK 15 ++#define JH7110_VOUTCLK_HDMI_TX_BCLK 16 ++#define JH7110_VOUTCLK_HDMI_TX_SYS 17 ++ ++#define JH7110_VOUTCLK_END 18 ++ + #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */ +--- a/include/dt-bindings/reset/starfive,jh7110-crg.h ++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h +@@ -195,4 +195,20 @@ + + #define JH7110_ISPRST_END 12 + ++/* VOUTCRG resets */ ++#define JH7110_VOUTRST_DC8200_AXI 0 ++#define JH7110_VOUTRST_DC8200_AHB 1 ++#define JH7110_VOUTRST_DC8200_CORE 2 ++#define JH7110_VOUTRST_DSITX_DPI 3 ++#define JH7110_VOUTRST_DSITX_APB 4 ++#define JH7110_VOUTRST_DSITX_RXESC 5 ++#define JH7110_VOUTRST_DSITX_SYS 6 ++#define JH7110_VOUTRST_DSITX_TXBYTEHS 7 ++#define JH7110_VOUTRST_DSITX_TXESC 8 ++#define JH7110_VOUTRST_HDMI_TX_HDMI 9 ++#define JH7110_VOUTRST_MIPITX_DPHY_SYS 10 ++#define JH7110_VOUTRST_MIPITX_DPHY_TXBYTEHS 11 ++ ++#define JH7110_VOUTRST_END 12 ++ + #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */ diff --git a/target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch b/target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch new file mode 100644 index 0000000000..8c31af5089 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch @@ -0,0 +1,284 @@ +From 2e632d5c5f8b4577ac823f6a9dcf3eacdb14a0ba Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:29 +0800 +Subject: [PATCH 056/122] clk: starfive: Add StarFive JH7110 Video-Output clock + driver + +Add driver for the StarFive JH7110 Video-Output clock controller. +And these clock controllers should power on and enable the clocks from +SYSCRG first before registering. + +Signed-off-by: Xingyu Wu +--- + drivers/clk/starfive/Kconfig | 11 + + drivers/clk/starfive/Makefile | 1 + + .../clk/starfive/clk-starfive-jh7110-vout.c | 239 ++++++++++++++++++ + 3 files changed, 251 insertions(+) + create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-vout.c + +--- a/drivers/clk/starfive/Kconfig ++++ b/drivers/clk/starfive/Kconfig +@@ -73,3 +73,14 @@ config CLK_STARFIVE_JH7110_ISP + help + Say yes here to support the Image-Signal-Process clock controller + on the StarFive JH7110 SoC. ++ ++config CLK_STARFIVE_JH7110_VOUT ++ tristate "StarFive JH7110 Video-Output clock support" ++ depends on CLK_STARFIVE_JH7110_SYS && JH71XX_PMU ++ select AUXILIARY_BUS ++ select CLK_STARFIVE_JH71X0 ++ select RESET_STARFIVE_JH7110 ++ default m if ARCH_STARFIVE ++ help ++ Say yes here to support the Video-Output clock controller ++ on the StarFive JH7110 SoC. +--- a/drivers/clk/starfive/Makefile ++++ b/drivers/clk/starfive/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS) += + obj-$(CONFIG_CLK_STARFIVE_JH7110_AON) += clk-starfive-jh7110-aon.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_STG) += clk-starfive-jh7110-stg.o + obj-$(CONFIG_CLK_STARFIVE_JH7110_ISP) += clk-starfive-jh7110-isp.o ++obj-$(CONFIG_CLK_STARFIVE_JH7110_VOUT) += clk-starfive-jh7110-vout.o +--- /dev/null ++++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c +@@ -0,0 +1,239 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive JH7110 Video-Output Clock Driver ++ * ++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "clk-starfive-jh7110.h" ++ ++/* external clocks */ ++#define JH7110_VOUTCLK_VOUT_SRC (JH7110_VOUTCLK_END + 0) ++#define JH7110_VOUTCLK_VOUT_TOP_AHB (JH7110_VOUTCLK_END + 1) ++#define JH7110_VOUTCLK_VOUT_TOP_AXI (JH7110_VOUTCLK_END + 2) ++#define JH7110_VOUTCLK_VOUT_TOP_HDMITX0_MCLK (JH7110_VOUTCLK_END + 3) ++#define JH7110_VOUTCLK_I2STX0_BCLK (JH7110_VOUTCLK_END + 4) ++#define JH7110_VOUTCLK_HDMITX0_PIXELCLK (JH7110_VOUTCLK_END + 5) ++#define JH7110_VOUTCLK_EXT_END (JH7110_VOUTCLK_END + 6) ++ ++static struct clk_bulk_data jh7110_vout_top_clks[] = { ++ { .id = "vout_src" }, ++ { .id = "vout_top_ahb" } ++}; ++ ++static const struct jh71x0_clk_data jh7110_voutclk_data[] = { ++ /* divider */ ++ JH71X0__DIV(JH7110_VOUTCLK_APB, "apb", 8, JH7110_VOUTCLK_VOUT_TOP_AHB), ++ JH71X0__DIV(JH7110_VOUTCLK_DC8200_PIX, "dc8200_pix", 63, JH7110_VOUTCLK_VOUT_SRC), ++ JH71X0__DIV(JH7110_VOUTCLK_DSI_SYS, "dsi_sys", 31, JH7110_VOUTCLK_VOUT_SRC), ++ JH71X0__DIV(JH7110_VOUTCLK_TX_ESC, "tx_esc", 31, JH7110_VOUTCLK_VOUT_TOP_AHB), ++ /* dc8200 */ ++ JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI), ++ JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI), ++ JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB), ++ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2, ++ JH7110_VOUTCLK_DC8200_PIX, ++ JH7110_VOUTCLK_HDMITX0_PIXELCLK), ++ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2, ++ JH7110_VOUTCLK_DC8200_PIX, ++ JH7110_VOUTCLK_HDMITX0_PIXELCLK), ++ /* LCD */ ++ JH71X0_GMUX(JH7110_VOUTCLK_DOM_VOUT_TOP_LCD, "dom_vout_top_lcd", 0, 2, ++ JH7110_VOUTCLK_DC8200_PIX0, ++ JH7110_VOUTCLK_DC8200_PIX1), ++ /* dsiTx */ ++ JH71X0_GATE(JH7110_VOUTCLK_DSITX_APB, "dsiTx_apb", 0, JH7110_VOUTCLK_DSI_SYS), ++ JH71X0_GATE(JH7110_VOUTCLK_DSITX_SYS, "dsiTx_sys", 0, JH7110_VOUTCLK_DSI_SYS), ++ JH71X0_GMUX(JH7110_VOUTCLK_DSITX_DPI, "dsiTx_dpi", 0, 2, ++ JH7110_VOUTCLK_DC8200_PIX, ++ JH7110_VOUTCLK_HDMITX0_PIXELCLK), ++ JH71X0_GATE(JH7110_VOUTCLK_DSITX_TXESC, "dsiTx_txesc", 0, JH7110_VOUTCLK_TX_ESC), ++ /* mipitx DPHY */ ++ JH71X0_GATE(JH7110_VOUTCLK_MIPITX_DPHY_TXESC, "mipitx_dphy_txesc", 0, ++ JH7110_VOUTCLK_TX_ESC), ++ /* hdmi */ ++ JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_MCLK, "hdmi_tx_mclk", 0, ++ JH7110_VOUTCLK_VOUT_TOP_HDMITX0_MCLK), ++ JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_BCLK, "hdmi_tx_bclk", 0, ++ JH7110_VOUTCLK_I2STX0_BCLK), ++ JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_SYS, "hdmi_tx_sys", 0, JH7110_VOUTCLK_APB), ++}; ++ ++static int jh7110_vout_top_rst_init(struct jh71x0_clk_priv *priv) ++{ ++ struct reset_control *top_rst; ++ ++ /* The reset should be shared and other Vout modules will use its. */ ++ top_rst = devm_reset_control_get_shared(priv->dev, NULL); ++ if (IS_ERR(top_rst)) ++ return dev_err_probe(priv->dev, PTR_ERR(top_rst), "failed to get top reset\n"); ++ ++ return reset_control_deassert(top_rst); ++} ++ ++static struct clk_hw *jh7110_voutclk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct jh71x0_clk_priv *priv = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx < JH7110_VOUTCLK_END) ++ return &priv->reg[idx].hw; ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++#ifdef CONFIG_PM ++static int jh7110_voutcrg_suspend(struct device *dev) ++{ ++ struct top_sysclk *top = dev_get_drvdata(dev); ++ ++ clk_bulk_disable_unprepare(top->top_clks_num, top->top_clks); ++ ++ return 0; ++} ++ ++static int jh7110_voutcrg_resume(struct device *dev) ++{ ++ struct top_sysclk *top = dev_get_drvdata(dev); ++ ++ return clk_bulk_prepare_enable(top->top_clks_num, top->top_clks); ++} ++#endif ++ ++static const struct dev_pm_ops jh7110_voutcrg_pm_ops = { ++ SET_RUNTIME_PM_OPS(jh7110_voutcrg_suspend, jh7110_voutcrg_resume, NULL) ++}; ++ ++static int jh7110_voutcrg_probe(struct platform_device *pdev) ++{ ++ struct jh71x0_clk_priv *priv; ++ struct top_sysclk *top; ++ unsigned int idx; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, ++ struct_size(priv, reg, JH7110_VOUTCLK_END), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ top = devm_kzalloc(&pdev->dev, sizeof(*top), GFP_KERNEL); ++ if (!top) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->rmw_lock); ++ priv->dev = &pdev->dev; ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ top->top_clks = jh7110_vout_top_clks; ++ top->top_clks_num = ARRAY_SIZE(jh7110_vout_top_clks); ++ ret = devm_clk_bulk_get(priv->dev, top->top_clks_num, top->top_clks); ++ if (ret) ++ return dev_err_probe(priv->dev, ret, "failed to get top clocks\n"); ++ dev_set_drvdata(priv->dev, top); ++ ++ /* enable power domain and clocks */ ++ pm_runtime_enable(priv->dev); ++ ret = pm_runtime_get_sync(priv->dev); ++ if (ret < 0) ++ return dev_err_probe(priv->dev, ret, "failed to turn on power\n"); ++ ++ ret = jh7110_vout_top_rst_init(priv); ++ if (ret) ++ goto err_exit; ++ ++ for (idx = 0; idx < JH7110_VOUTCLK_END; idx++) { ++ u32 max = jh7110_voutclk_data[idx].max; ++ struct clk_parent_data parents[4] = {}; ++ struct clk_init_data init = { ++ .name = jh7110_voutclk_data[idx].name, ++ .ops = starfive_jh71x0_clk_ops(max), ++ .parent_data = parents, ++ .num_parents = ++ ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1, ++ .flags = jh7110_voutclk_data[idx].flags, ++ }; ++ struct jh71x0_clk *clk = &priv->reg[idx]; ++ unsigned int i; ++ const char *fw_name[JH7110_VOUTCLK_EXT_END - JH7110_VOUTCLK_END] = { ++ "vout_src", ++ "vout_top_ahb", ++ "vout_top_axi", ++ "vout_top_hdmitx0_mclk", ++ "i2stx0_bclk", ++ "hdmitx0_pixelclk" ++ }; ++ ++ for (i = 0; i < init.num_parents; i++) { ++ unsigned int pidx = jh7110_voutclk_data[idx].parents[i]; ++ ++ if (pidx < JH7110_VOUTCLK_END) ++ parents[i].hw = &priv->reg[pidx].hw; ++ else if (pidx < JH7110_VOUTCLK_EXT_END) ++ parents[i].fw_name = fw_name[pidx - JH7110_VOUTCLK_END]; ++ } ++ ++ clk->hw.init = &init; ++ clk->idx = idx; ++ clk->max_div = max & JH71X0_CLK_DIV_MASK; ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clk->hw); ++ if (ret) ++ goto err_exit; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_voutclk_get, priv); ++ if (ret) ++ goto err_exit; ++ ++ ret = jh7110_reset_controller_register(priv, "rst-vo", 4); ++ if (ret) ++ goto err_exit; ++ ++ return 0; ++ ++err_exit: ++ pm_runtime_put_sync(priv->dev); ++ pm_runtime_disable(priv->dev); ++ return ret; ++} ++ ++static int jh7110_voutcrg_remove(struct platform_device *pdev) ++{ ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id jh7110_voutcrg_match[] = { ++ { .compatible = "starfive,jh7110-voutcrg" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7110_voutcrg_match); ++ ++static struct platform_driver jh7110_voutcrg_driver = { ++ .probe = jh7110_voutcrg_probe, ++ .remove = jh7110_voutcrg_remove, ++ .driver = { ++ .name = "clk-starfive-jh7110-vout", ++ .of_match_table = jh7110_voutcrg_match, ++ .pm = &jh7110_voutcrg_pm_ops, ++ }, ++}; ++module_platform_driver(jh7110_voutcrg_driver); ++ ++MODULE_AUTHOR("Xingyu Wu "); ++MODULE_DESCRIPTION("StarFive JH7110 Video-Output clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch b/target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch new file mode 100644 index 0000000000..197337bb70 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch @@ -0,0 +1,61 @@ +From a04a6eb3b4d112f3600bbd783249f24a43797e7a Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Thu, 18 May 2023 18:12:31 +0800 +Subject: [PATCH 057/122] reset: starfive: jh7110: Add StarFive STG/ISP/VOUT + resets support + +Add new struct members and auxiliary_device_id of resets to support +System-Top-Group, Image-Signal-Process and Video-Output on the StarFive +JH7110 SoC. + +Signed-off-by: Xingyu Wu +--- + .../reset/starfive/reset-starfive-jh7110.c | 30 +++++++++++++++++++ + 1 file changed, 30 insertions(+) + +--- a/drivers/reset/starfive/reset-starfive-jh7110.c ++++ b/drivers/reset/starfive/reset-starfive-jh7110.c +@@ -31,6 +31,24 @@ static const struct jh7110_reset_info jh + .status_offset = 0x3C, + }; + ++static const struct jh7110_reset_info jh7110_stg_info = { ++ .nr_resets = JH7110_STGRST_END, ++ .assert_offset = 0x74, ++ .status_offset = 0x78, ++}; ++ ++static const struct jh7110_reset_info jh7110_isp_info = { ++ .nr_resets = JH7110_ISPRST_END, ++ .assert_offset = 0x38, ++ .status_offset = 0x3C, ++}; ++ ++static const struct jh7110_reset_info jh7110_vout_info = { ++ .nr_resets = JH7110_VOUTRST_END, ++ .assert_offset = 0x48, ++ .status_offset = 0x4C, ++}; ++ + static int jh7110_reset_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) + { +@@ -58,6 +76,18 @@ static const struct auxiliary_device_id + .name = "clk_starfive_jh7110_sys.rst-aon", + .driver_data = (kernel_ulong_t)&jh7110_aon_info, + }, ++ { ++ .name = "clk_starfive_jh7110_sys.rst-stg", ++ .driver_data = (kernel_ulong_t)&jh7110_stg_info, ++ }, ++ { ++ .name = "clk_starfive_jh7110_sys.rst-isp", ++ .driver_data = (kernel_ulong_t)&jh7110_isp_info, ++ }, ++ { ++ .name = "clk_starfive_jh7110_sys.rst-vo", ++ .driver_data = (kernel_ulong_t)&jh7110_vout_info, ++ }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(auxiliary, jh7110_reset_ids); diff --git a/target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch b/target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch new file mode 100644 index 0000000000..fc3da897a5 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch @@ -0,0 +1,819 @@ +From 758c8c4c30f495465f34735aef2458c0cc255a75 Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Wed, 31 May 2023 01:03:02 -0700 +Subject: [PATCH 058/122] clk: starfive: update jh7110 PLL clock driver + +Update the StarFive JH7110 PLL clock controller +and they work by reading and setting syscon registers. + +Signed-off-by: shanlong.li +--- + .../clk/starfive/clk-starfive-jh7110-pll.c | 269 +++++------------- + .../clk/starfive/clk-starfive-jh7110-pll.h | 264 +++++++++-------- + 2 files changed, 227 insertions(+), 306 deletions(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7110-pll.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.c +@@ -24,11 +24,29 @@ + #include + #include + #include ++#include + + #include + + #include "clk-starfive-jh7110-pll.h" + ++struct jh7110_pll_conf_variant { ++ unsigned int pll_nums; ++ struct jh7110_pll_syscon_conf conf[]; ++}; ++ ++static const struct jh7110_pll_conf_variant jh7110_pll_variant = { ++ .pll_nums = JH7110_PLLCLK_END, ++ .conf = { ++ JH7110_PLL(JH7110_CLK_PLL0_OUT, "pll0_out", ++ JH7110_PLL0_FREQ_MAX, jh7110_pll0_syscon_val_preset), ++ JH7110_PLL(JH7110_CLK_PLL1_OUT, "pll1_out", ++ JH7110_PLL1_FREQ_MAX, jh7110_pll1_syscon_val_preset), ++ JH7110_PLL(JH7110_CLK_PLL2_OUT, "pll2_out", ++ JH7110_PLL2_FREQ_MAX, jh7110_pll2_syscon_val_preset), ++ }, ++}; ++ + static struct jh7110_clk_pll_data *jh7110_pll_data_from(struct clk_hw *hw) + { + return container_of(hw, struct jh7110_clk_pll_data, hw); +@@ -44,10 +62,9 @@ static unsigned long jh7110_pll_get_freq + unsigned long parent_rate) + { + struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data); +- struct jh7110_pll_syscon_offset *offset = &data->offset; +- struct jh7110_pll_syscon_mask *mask = &data->mask; +- struct jh7110_pll_syscon_shift *shift = &data->shift; +- unsigned long freq = 0; ++ struct jh7110_pll_syscon_offset *offset = &data->conf.offsets; ++ struct jh7110_pll_syscon_mask *mask = &data->conf.masks; ++ struct jh7110_pll_syscon_shift *shift = &data->conf.shifts; + unsigned long frac_cal; + u32 dacpd; + u32 dsmpd; +@@ -57,32 +74,23 @@ static unsigned long jh7110_pll_get_freq + u32 frac; + u32 reg_val; + +- if (regmap_read(priv->syscon_regmap, offset->dacpd, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->dacpd, ®_val); + dacpd = (reg_val & mask->dacpd) >> shift->dacpd; + +- if (regmap_read(priv->syscon_regmap, offset->dsmpd, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->dsmpd, ®_val); + dsmpd = (reg_val & mask->dsmpd) >> shift->dsmpd; + +- if (regmap_read(priv->syscon_regmap, offset->fbdiv, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->fbdiv, ®_val); + fbdiv = (reg_val & mask->fbdiv) >> shift->fbdiv; +- /* fbdiv value should be 8 to 4095 */ +- if (fbdiv < 8) +- goto read_error; + +- if (regmap_read(priv->syscon_regmap, offset->prediv, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->prediv, ®_val); + prediv = (reg_val & mask->prediv) >> shift->prediv; + +- if (regmap_read(priv->syscon_regmap, offset->postdiv1, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->postdiv1, ®_val); + /* postdiv1 = 2 ^ reg_val */ + postdiv1 = 1 << ((reg_val & mask->postdiv1) >> shift->postdiv1); + +- if (regmap_read(priv->syscon_regmap, offset->frac, ®_val)) +- goto read_error; ++ regmap_read(priv->syscon_regmap, offset->frac, ®_val); + frac = (reg_val & mask->frac) >> shift->frac; + + /* +@@ -95,14 +103,11 @@ static unsigned long jh7110_pll_get_freq + else if (dacpd == 0 && dsmpd == 0) + frac_cal = (unsigned long)frac * STARFIVE_PLL_FRAC_PATR_SIZE / (1 << 24); + else +- goto read_error; ++ return 0; + + /* Fvco = Fref * (NI + NF) / M / Q1 */ +- freq = parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE * +- (fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1; +- +-read_error: +- return freq; ++ return (parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE * ++ (fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1); + } + + static unsigned long jh7110_pll_rate_sub_fabs(unsigned long rate1, unsigned long rate2) +@@ -114,40 +119,27 @@ static unsigned long jh7110_pll_rate_sub + static void jh7110_pll_select_near_freq_id(struct jh7110_clk_pll_data *data, + unsigned long rate) + { +- const struct starfive_pll_syscon_value *syscon_val; ++ const struct jh7110_pll_syscon_val *val; + unsigned int id; +- unsigned int pll_arry_size; + unsigned long rate_diff; + +- if (data->idx == JH7110_CLK_PLL0_OUT) +- pll_arry_size = ARRAY_SIZE(jh7110_pll0_syscon_freq); +- else if (data->idx == JH7110_CLK_PLL1_OUT) +- pll_arry_size = ARRAY_SIZE(jh7110_pll1_syscon_freq); +- else +- pll_arry_size = ARRAY_SIZE(jh7110_pll2_syscon_freq); +- + /* compare the frequency one by one from small to large in order */ +- for (id = 0; id < pll_arry_size; id++) { +- if (data->idx == JH7110_CLK_PLL0_OUT) +- syscon_val = &jh7110_pll0_syscon_freq[id]; +- else if (data->idx == JH7110_CLK_PLL1_OUT) +- syscon_val = &jh7110_pll1_syscon_freq[id]; +- else +- syscon_val = &jh7110_pll2_syscon_freq[id]; ++ for (id = 0; id < data->conf.preset_val_nums; id++) { ++ val = &data->conf.preset_val[id]; + +- if (rate == syscon_val->freq) ++ if (rate == val->freq) + goto match_end; + + /* select near frequency */ +- if (rate < syscon_val->freq) { ++ if (rate < val->freq) { + /* The last frequency is closer to the target rate than this time. */ + if (id > 0) +- if (rate_diff < jh7110_pll_rate_sub_fabs(rate, syscon_val->freq)) ++ if (rate_diff < jh7110_pll_rate_sub_fabs(rate, val->freq)) + id--; + + goto match_end; + } else { +- rate_diff = jh7110_pll_rate_sub_fabs(rate, syscon_val->freq); ++ rate_diff = jh7110_pll_rate_sub_fabs(rate, val->freq); + } + } + +@@ -158,54 +150,34 @@ match_end: + static int jh7110_pll_set_freq_syscon(struct jh7110_clk_pll_data *data) + { + struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data); +- struct jh7110_pll_syscon_offset *offset = &data->offset; +- struct jh7110_pll_syscon_mask *mask = &data->mask; +- struct jh7110_pll_syscon_shift *shift = &data->shift; +- unsigned int freq_idx = data->freq_select_idx; +- const struct starfive_pll_syscon_value *syscon_val; +- int ret; ++ struct jh7110_pll_syscon_offset *offset = &data->conf.offsets; ++ struct jh7110_pll_syscon_mask *mask = &data->conf.masks; ++ struct jh7110_pll_syscon_shift *shift = &data->conf.shifts; ++ const struct jh7110_pll_syscon_val *val = &data->conf.preset_val[data->freq_select_idx]; + +- if (data->idx == JH7110_CLK_PLL0_OUT) +- syscon_val = &jh7110_pll0_syscon_freq[freq_idx]; +- else if (data->idx == JH7110_CLK_PLL1_OUT) +- syscon_val = &jh7110_pll1_syscon_freq[freq_idx]; +- else +- syscon_val = &jh7110_pll2_syscon_freq[freq_idx]; ++ /* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */ ++ if (val->dacpd == 0 && val->dsmpd == 0) ++ regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac, ++ (val->frac << shift->frac)); ++ else if (val->dacpd != val->dsmpd) ++ return -EINVAL; + +- ret = regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd, +- (syscon_val->dacpd << shift->dacpd)); +- if (ret) +- goto set_failed; +- +- ret = regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd, +- (syscon_val->dsmpd << shift->dsmpd)); +- if (ret) +- goto set_failed; +- +- ret = regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv, +- (syscon_val->prediv << shift->prediv)); +- if (ret) +- goto set_failed; +- +- ret = regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv, +- (syscon_val->fbdiv << shift->fbdiv)); +- if (ret) +- goto set_failed; +- +- ret = regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1, +- ((syscon_val->postdiv1 >> 1) << shift->postdiv1)); +- if (ret) +- goto set_failed; ++ /* fbdiv value should be 8 to 4095 */ ++ if (val->fbdiv < 8) ++ return -EINVAL; + +- /* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */ +- if (syscon_val->dacpd == 0 && syscon_val->dsmpd == 0) +- ret = regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac, +- (syscon_val->frac << shift->frac)); +- else if (syscon_val->dacpd != syscon_val->dsmpd) +- ret = -EINVAL; ++ regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd, ++ (val->dacpd << shift->dacpd)); ++ regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd, ++ (val->dsmpd << shift->dsmpd)); ++ regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv, ++ (val->prediv << shift->prediv)); ++ regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv, ++ (val->fbdiv << shift->fbdiv)); ++ regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1, ++ ((val->postdiv1 >> 1) << shift->postdiv1)); + +-set_failed: +- return ret; ++ return 0; + } + + static unsigned long jh7110_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +@@ -220,13 +192,7 @@ static int jh7110_pll_determine_rate(str + struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw); + + jh7110_pll_select_near_freq_id(data, req->rate); +- +- if (data->idx == JH7110_CLK_PLL0_OUT) +- req->rate = jh7110_pll0_syscon_freq[data->freq_select_idx].freq; +- else if (data->idx == JH7110_CLK_PLL1_OUT) +- req->rate = jh7110_pll1_syscon_freq[data->freq_select_idx].freq; +- else +- req->rate = jh7110_pll2_syscon_freq[data->freq_select_idx].freq; ++ req->rate = data->conf.preset_val[data->freq_select_idx].freq; + + return 0; + } +@@ -270,92 +236,12 @@ static const struct clk_ops jh7110_pll_o + .debug_init = jh7110_pll_debug_init, + }; + +-/* get offset, mask and shift of PLL(x) syscon */ +-static int jh7110_pll_data_get(struct jh7110_clk_pll_data *data, int index) +-{ +- struct jh7110_pll_syscon_offset *offset = &data->offset; +- struct jh7110_pll_syscon_mask *mask = &data->mask; +- struct jh7110_pll_syscon_shift *shift = &data->shift; +- +- if (index == JH7110_CLK_PLL0_OUT) { +- offset->dacpd = STARFIVE_JH7110_PLL0_DACPD_OFFSET; +- offset->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_OFFSET; +- offset->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_OFFSET; +- offset->frac = STARFIVE_JH7110_PLL0_FRAC_OFFSET; +- offset->prediv = STARFIVE_JH7110_PLL0_PREDIV_OFFSET; +- offset->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET; +- +- mask->dacpd = STARFIVE_JH7110_PLL0_DACPD_MASK; +- mask->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_MASK; +- mask->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_MASK; +- mask->frac = STARFIVE_JH7110_PLL0_FRAC_MASK; +- mask->prediv = STARFIVE_JH7110_PLL0_PREDIV_MASK; +- mask->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_MASK; +- +- shift->dacpd = STARFIVE_JH7110_PLL0_DACPD_SHIFT; +- shift->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_SHIFT; +- shift->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_SHIFT; +- shift->frac = STARFIVE_JH7110_PLL0_FRAC_SHIFT; +- shift->prediv = STARFIVE_JH7110_PLL0_PREDIV_SHIFT; +- shift->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT; +- +- } else if (index == JH7110_CLK_PLL1_OUT) { +- offset->dacpd = STARFIVE_JH7110_PLL1_DACPD_OFFSET; +- offset->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_OFFSET; +- offset->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_OFFSET; +- offset->frac = STARFIVE_JH7110_PLL1_FRAC_OFFSET; +- offset->prediv = STARFIVE_JH7110_PLL1_PREDIV_OFFSET; +- offset->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET; +- +- mask->dacpd = STARFIVE_JH7110_PLL1_DACPD_MASK; +- mask->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_MASK; +- mask->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_MASK; +- mask->frac = STARFIVE_JH7110_PLL1_FRAC_MASK; +- mask->prediv = STARFIVE_JH7110_PLL1_PREDIV_MASK; +- mask->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_MASK; +- +- shift->dacpd = STARFIVE_JH7110_PLL1_DACPD_SHIFT; +- shift->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_SHIFT; +- shift->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_SHIFT; +- shift->frac = STARFIVE_JH7110_PLL1_FRAC_SHIFT; +- shift->prediv = STARFIVE_JH7110_PLL1_PREDIV_SHIFT; +- shift->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT; +- +- } else if (index == JH7110_CLK_PLL2_OUT) { +- offset->dacpd = STARFIVE_JH7110_PLL2_DACPD_OFFSET; +- offset->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_OFFSET; +- offset->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_OFFSET; +- offset->frac = STARFIVE_JH7110_PLL2_FRAC_OFFSET; +- offset->prediv = STARFIVE_JH7110_PLL2_PREDIV_OFFSET; +- offset->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET; +- +- mask->dacpd = STARFIVE_JH7110_PLL2_DACPD_MASK; +- mask->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_MASK; +- mask->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_MASK; +- mask->frac = STARFIVE_JH7110_PLL2_FRAC_MASK; +- mask->prediv = STARFIVE_JH7110_PLL2_PREDIV_MASK; +- mask->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_MASK; +- +- shift->dacpd = STARFIVE_JH7110_PLL2_DACPD_SHIFT; +- shift->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_SHIFT; +- shift->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_SHIFT; +- shift->frac = STARFIVE_JH7110_PLL2_FRAC_SHIFT; +- shift->prediv = STARFIVE_JH7110_PLL2_PREDIV_SHIFT; +- shift->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT; +- +- } else { +- return -ENOENT; +- } +- +- return 0; +-} +- + static struct clk_hw *jh7110_pll_get(struct of_phandle_args *clkspec, void *data) + { + struct jh7110_clk_pll_priv *priv = data; + unsigned int idx = clkspec->args[0]; + +- if (idx < JH7110_PLLCLK_END) ++ if (idx < priv->pll_nums) + return &priv->data[idx].hw; + + return ERR_PTR(-EINVAL); +@@ -363,17 +249,17 @@ static struct clk_hw *jh7110_pll_get(str + + static int jh7110_pll_probe(struct platform_device *pdev) + { +- const char *pll_name[JH7110_PLLCLK_END] = { +- "pll0_out", +- "pll1_out", +- "pll2_out" +- }; ++ const struct jh7110_pll_conf_variant *variant; + struct jh7110_clk_pll_priv *priv; + struct jh7110_clk_pll_data *data; + int ret; + unsigned int idx; + +- priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, JH7110_PLLCLK_END), ++ variant = of_device_get_match_data(&pdev->dev); ++ if (!variant) ++ return -ENOMEM; ++ ++ priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, variant->pll_nums), + GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -383,12 +269,13 @@ static int jh7110_pll_probe(struct platf + if (IS_ERR(priv->syscon_regmap)) + return PTR_ERR(priv->syscon_regmap); + +- for (idx = 0; idx < JH7110_PLLCLK_END; idx++) { ++ priv->pll_nums = variant->pll_nums; ++ for (idx = 0; idx < priv->pll_nums; idx++) { + struct clk_parent_data parents = { + .index = 0, + }; + struct clk_init_data init = { +- .name = pll_name[idx], ++ .name = variant->conf[idx].name, + .ops = &jh7110_pll_ops, + .parent_data = &parents, + .num_parents = 1, +@@ -396,11 +283,7 @@ static int jh7110_pll_probe(struct platf + }; + + data = &priv->data[idx]; +- +- ret = jh7110_pll_data_get(data, idx); +- if (ret) +- return ret; +- ++ data->conf = variant->conf[idx]; + data->hw.init = &init; + data->idx = idx; + +@@ -413,7 +296,7 @@ static int jh7110_pll_probe(struct platf + } + + static const struct of_device_id jh7110_pll_match[] = { +- { .compatible = "starfive,jh7110-pll" }, ++ { .compatible = "starfive,jh7110-pll", .data = &jh7110_pll_variant }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, jh7110_pll_match); +--- a/drivers/clk/starfive/clk-starfive-jh7110-pll.h ++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.h +@@ -13,62 +13,93 @@ + /* The decimal places are counted by expanding them by a factor of STARFIVE_PLL_FRAC_PATR_SIZE */ + #define STARFIVE_PLL_FRAC_PATR_SIZE 1000 + +-#define STARFIVE_JH7110_PLL0_DACPD_OFFSET 0x18 +-#define STARFIVE_JH7110_PLL0_DACPD_SHIFT 24 +-#define STARFIVE_JH7110_PLL0_DACPD_MASK BIT(24) +-#define STARFIVE_JH7110_PLL0_DSMPD_OFFSET 0x18 +-#define STARFIVE_JH7110_PLL0_DSMPD_SHIFT 25 +-#define STARFIVE_JH7110_PLL0_DSMPD_MASK BIT(25) +-#define STARFIVE_JH7110_PLL0_FBDIV_OFFSET 0x1c +-#define STARFIVE_JH7110_PLL0_FBDIV_SHIFT 0 +-#define STARFIVE_JH7110_PLL0_FBDIV_MASK GENMASK(11, 0) +-#define STARFIVE_JH7110_PLL0_FRAC_OFFSET 0x20 +-#define STARFIVE_JH7110_PLL0_FRAC_SHIFT 0 +-#define STARFIVE_JH7110_PLL0_FRAC_MASK GENMASK(23, 0) +-#define STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET 0x20 +-#define STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT 28 +-#define STARFIVE_JH7110_PLL0_POSTDIV1_MASK GENMASK(29, 28) +-#define STARFIVE_JH7110_PLL0_PREDIV_OFFSET 0x24 +-#define STARFIVE_JH7110_PLL0_PREDIV_SHIFT 0 +-#define STARFIVE_JH7110_PLL0_PREDIV_MASK GENMASK(5, 0) +- +-#define STARFIVE_JH7110_PLL1_DACPD_OFFSET 0x24 +-#define STARFIVE_JH7110_PLL1_DACPD_SHIFT 15 +-#define STARFIVE_JH7110_PLL1_DACPD_MASK BIT(15) +-#define STARFIVE_JH7110_PLL1_DSMPD_OFFSET 0x24 +-#define STARFIVE_JH7110_PLL1_DSMPD_SHIFT 16 +-#define STARFIVE_JH7110_PLL1_DSMPD_MASK BIT(16) +-#define STARFIVE_JH7110_PLL1_FBDIV_OFFSET 0x24 +-#define STARFIVE_JH7110_PLL1_FBDIV_SHIFT 17 +-#define STARFIVE_JH7110_PLL1_FBDIV_MASK GENMASK(28, 17) +-#define STARFIVE_JH7110_PLL1_FRAC_OFFSET 0x28 +-#define STARFIVE_JH7110_PLL1_FRAC_SHIFT 0 +-#define STARFIVE_JH7110_PLL1_FRAC_MASK GENMASK(23, 0) +-#define STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET 0x28 +-#define STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT 28 +-#define STARFIVE_JH7110_PLL1_POSTDIV1_MASK GENMASK(29, 28) +-#define STARFIVE_JH7110_PLL1_PREDIV_OFFSET 0x2c +-#define STARFIVE_JH7110_PLL1_PREDIV_SHIFT 0 +-#define STARFIVE_JH7110_PLL1_PREDIV_MASK GENMASK(5, 0) +- +-#define STARFIVE_JH7110_PLL2_DACPD_OFFSET 0x2c +-#define STARFIVE_JH7110_PLL2_DACPD_SHIFT 15 +-#define STARFIVE_JH7110_PLL2_DACPD_MASK BIT(15) +-#define STARFIVE_JH7110_PLL2_DSMPD_OFFSET 0x2c +-#define STARFIVE_JH7110_PLL2_DSMPD_SHIFT 16 +-#define STARFIVE_JH7110_PLL2_DSMPD_MASK BIT(16) +-#define STARFIVE_JH7110_PLL2_FBDIV_OFFSET 0x2c +-#define STARFIVE_JH7110_PLL2_FBDIV_SHIFT 17 +-#define STARFIVE_JH7110_PLL2_FBDIV_MASK GENMASK(28, 17) +-#define STARFIVE_JH7110_PLL2_FRAC_OFFSET 0x30 +-#define STARFIVE_JH7110_PLL2_FRAC_SHIFT 0 +-#define STARFIVE_JH7110_PLL2_FRAC_MASK GENMASK(23, 0) +-#define STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET 0x30 +-#define STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT 28 +-#define STARFIVE_JH7110_PLL2_POSTDIV1_MASK GENMASK(29, 28) +-#define STARFIVE_JH7110_PLL2_PREDIV_OFFSET 0x34 +-#define STARFIVE_JH7110_PLL2_PREDIV_SHIFT 0 +-#define STARFIVE_JH7110_PLL2_PREDIV_MASK GENMASK(5, 0) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_OFFSET 0x18 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_SHIFT 24 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_MASK BIT(24) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_OFFSET 0x18 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_SHIFT 25 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_MASK BIT(25) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_OFFSET 0x1c ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_MASK GENMASK(11, 0) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_OFFSET 0x20 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_OFFSET 0x20 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_OFFSET 0x24 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_MASK GENMASK(5, 0) ++ ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_OFFSET 0x24 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_SHIFT 15 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_MASK BIT(15) ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_OFFSET 0x24 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_SHIFT 16 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_MASK BIT(16) ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_OFFSET 0x24 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_SHIFT 17 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_MASK GENMASK(28, 17) ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_OFFSET 0x28 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_OFFSET 0x28 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_OFFSET 0x2c ++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_MASK GENMASK(5, 0) ++ ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_OFFSET 0x2c ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_SHIFT 15 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_MASK BIT(15) ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_OFFSET 0x2c ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_SHIFT 16 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_MASK BIT(16) ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_OFFSET 0x2c ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_SHIFT 17 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_MASK GENMASK(28, 17) ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_OFFSET 0x30 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_MASK GENMASK(23, 0) ++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_OFFSET 0x30 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_SHIFT 28 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_MASK GENMASK(29, 28) ++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_OFFSET 0x34 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_SHIFT 0 ++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_MASK GENMASK(5, 0) ++ ++#define JH7110_PLL(_idx, _name, _nums, _val) \ ++[_idx] = { \ ++ .name = _name, \ ++ .offsets = { \ ++ .dacpd = STARFIVE_##_idx##_DACPD_OFFSET, \ ++ .dsmpd = STARFIVE_##_idx##_DSMPD_OFFSET, \ ++ .fbdiv = STARFIVE_##_idx##_FBDIV_OFFSET, \ ++ .frac = STARFIVE_##_idx##_FRAC_OFFSET, \ ++ .prediv = STARFIVE_##_idx##_PREDIV_OFFSET, \ ++ .postdiv1 = STARFIVE_##_idx##_POSTDIV1_OFFSET, \ ++ }, \ ++ .masks = { \ ++ .dacpd = STARFIVE_##_idx##_DACPD_MASK, \ ++ .dsmpd = STARFIVE_##_idx##_DSMPD_MASK, \ ++ .fbdiv = STARFIVE_##_idx##_FBDIV_MASK, \ ++ .frac = STARFIVE_##_idx##_FRAC_MASK, \ ++ .prediv = STARFIVE_##_idx##_PREDIV_MASK, \ ++ .postdiv1 = STARFIVE_##_idx##_POSTDIV1_MASK, \ ++ }, \ ++ .shifts = { \ ++ .dacpd = STARFIVE_##_idx##_DACPD_SHIFT, \ ++ .dsmpd = STARFIVE_##_idx##_DSMPD_SHIFT, \ ++ .fbdiv = STARFIVE_##_idx##_FBDIV_SHIFT, \ ++ .frac = STARFIVE_##_idx##_FRAC_SHIFT, \ ++ .prediv = STARFIVE_##_idx##_PREDIV_SHIFT, \ ++ .postdiv1 = STARFIVE_##_idx##_POSTDIV1_SHIFT, \ ++ }, \ ++ .preset_val_nums = _nums, \ ++ .preset_val = _val, \ ++} + + struct jh7110_pll_syscon_offset { + unsigned int dacpd; +@@ -97,23 +128,7 @@ struct jh7110_pll_syscon_shift { + char postdiv1; + }; + +-struct jh7110_clk_pll_data { +- struct clk_hw hw; +- unsigned int idx; +- unsigned int freq_select_idx; +- +- struct jh7110_pll_syscon_offset offset; +- struct jh7110_pll_syscon_mask mask; +- struct jh7110_pll_syscon_shift shift; +-}; +- +-struct jh7110_clk_pll_priv { +- struct device *dev; +- struct regmap *syscon_regmap; +- struct jh7110_clk_pll_data data[]; +-}; +- +-struct starfive_pll_syscon_value { ++struct jh7110_pll_syscon_val { + unsigned long freq; + u32 prediv; + u32 fbdiv; +@@ -126,31 +141,54 @@ struct starfive_pll_syscon_value { + u32 frac; + }; + +-enum starfive_pll0_freq_index { +- PLL0_FREQ_375 = 0, +- PLL0_FREQ_500, +- PLL0_FREQ_625, +- PLL0_FREQ_750, +- PLL0_FREQ_875, +- PLL0_FREQ_1000, +- PLL0_FREQ_1250, +- PLL0_FREQ_1375, +- PLL0_FREQ_1500, +- PLL0_FREQ_MAX +-}; +- +-enum starfive_pll1_freq_index { +- PLL1_FREQ_1066 = 0, +- PLL1_FREQ_1200, +- PLL1_FREQ_1400, +- PLL1_FREQ_1600, +- PLL1_FREQ_MAX +-}; +- +-enum starfive_pll2_freq_index { +- PLL2_FREQ_1188 = 0, +- PLL2_FREQ_12288, +- PLL2_FREQ_MAX ++struct jh7110_pll_syscon_conf { ++ char *name; ++ struct jh7110_pll_syscon_offset offsets; ++ struct jh7110_pll_syscon_mask masks; ++ struct jh7110_pll_syscon_shift shifts; ++ unsigned int preset_val_nums; ++ const struct jh7110_pll_syscon_val *preset_val; ++}; ++ ++struct jh7110_clk_pll_data { ++ struct clk_hw hw; ++ unsigned int idx; ++ unsigned int freq_select_idx; ++ struct jh7110_pll_syscon_conf conf; ++}; ++ ++struct jh7110_clk_pll_priv { ++ unsigned int pll_nums; ++ struct device *dev; ++ struct regmap *syscon_regmap; ++ struct jh7110_clk_pll_data data[]; ++}; ++ ++enum jh7110_pll0_freq_index { ++ JH7110_PLL0_FREQ_375 = 0, ++ JH7110_PLL0_FREQ_500, ++ JH7110_PLL0_FREQ_625, ++ JH7110_PLL0_FREQ_750, ++ JH7110_PLL0_FREQ_875, ++ JH7110_PLL0_FREQ_1000, ++ JH7110_PLL0_FREQ_1250, ++ JH7110_PLL0_FREQ_1375, ++ JH7110_PLL0_FREQ_1500, ++ JH7110_PLL0_FREQ_MAX ++}; ++ ++enum jh7110_pll1_freq_index { ++ JH7110_PLL1_FREQ_1066 = 0, ++ JH7110_PLL1_FREQ_1200, ++ JH7110_PLL1_FREQ_1400, ++ JH7110_PLL1_FREQ_1600, ++ JH7110_PLL1_FREQ_MAX ++}; ++ ++enum jh7110_pll2_freq_index { ++ JH7110_PLL2_FREQ_1188 = 0, ++ JH7110_PLL2_FREQ_12288, ++ JH7110_PLL2_FREQ_MAX + }; + + /* +@@ -158,9 +196,9 @@ enum starfive_pll2_freq_index { + * it cannot be set arbitrarily, so it needs a specific configuration. + * PLL0 frequency should be multiple of 125MHz (USB frequency). + */ +-static const struct starfive_pll_syscon_value +- jh7110_pll0_syscon_freq[PLL0_FREQ_MAX] = { +- [PLL0_FREQ_375] = { ++static const struct jh7110_pll_syscon_val ++ jh7110_pll0_syscon_val_preset[] = { ++ [JH7110_PLL0_FREQ_375] = { + .freq = 375000000, + .prediv = 8, + .fbdiv = 125, +@@ -168,7 +206,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_500] = { ++ [JH7110_PLL0_FREQ_500] = { + .freq = 500000000, + .prediv = 6, + .fbdiv = 125, +@@ -176,7 +214,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_625] = { ++ [JH7110_PLL0_FREQ_625] = { + .freq = 625000000, + .prediv = 24, + .fbdiv = 625, +@@ -184,7 +222,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_750] = { ++ [JH7110_PLL0_FREQ_750] = { + .freq = 750000000, + .prediv = 4, + .fbdiv = 125, +@@ -192,7 +230,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_875] = { ++ [JH7110_PLL0_FREQ_875] = { + .freq = 875000000, + .prediv = 24, + .fbdiv = 875, +@@ -200,7 +238,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_1000] = { ++ [JH7110_PLL0_FREQ_1000] = { + .freq = 1000000000, + .prediv = 3, + .fbdiv = 125, +@@ -208,7 +246,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_1250] = { ++ [JH7110_PLL0_FREQ_1250] = { + .freq = 1250000000, + .prediv = 12, + .fbdiv = 625, +@@ -216,7 +254,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_1375] = { ++ [JH7110_PLL0_FREQ_1375] = { + .freq = 1375000000, + .prediv = 24, + .fbdiv = 1375, +@@ -224,7 +262,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL0_FREQ_1500] = { ++ [JH7110_PLL0_FREQ_1500] = { + .freq = 1500000000, + .prediv = 2, + .fbdiv = 125, +@@ -234,9 +272,9 @@ static const struct starfive_pll_syscon_ + }, + }; + +-static const struct starfive_pll_syscon_value +- jh7110_pll1_syscon_freq[PLL1_FREQ_MAX] = { +- [PLL1_FREQ_1066] = { ++static const struct jh7110_pll_syscon_val ++ jh7110_pll1_syscon_val_preset[] = { ++ [JH7110_PLL1_FREQ_1066] = { + .freq = 1066000000, + .prediv = 12, + .fbdiv = 533, +@@ -244,7 +282,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL1_FREQ_1200] = { ++ [JH7110_PLL1_FREQ_1200] = { + .freq = 1200000000, + .prediv = 1, + .fbdiv = 50, +@@ -252,7 +290,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL1_FREQ_1400] = { ++ [JH7110_PLL1_FREQ_1400] = { + .freq = 1400000000, + .prediv = 6, + .fbdiv = 350, +@@ -260,7 +298,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL1_FREQ_1600] = { ++ [JH7110_PLL1_FREQ_1600] = { + .freq = 1600000000, + .prediv = 3, + .fbdiv = 200, +@@ -270,9 +308,9 @@ static const struct starfive_pll_syscon_ + }, + }; + +-static const struct starfive_pll_syscon_value +- jh7110_pll2_syscon_freq[PLL2_FREQ_MAX] = { +- [PLL2_FREQ_1188] = { ++static const struct jh7110_pll_syscon_val ++ jh7110_pll2_syscon_val_preset[] = { ++ [JH7110_PLL2_FREQ_1188] = { + .freq = 1188000000, + .prediv = 2, + .fbdiv = 99, +@@ -280,7 +318,7 @@ static const struct starfive_pll_syscon_ + .dacpd = 1, + .dsmpd = 1, + }, +- [PLL2_FREQ_12288] = { ++ [JH7110_PLL2_FREQ_12288] = { + .freq = 1228800000, + .prediv = 5, + .fbdiv = 256, diff --git a/target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch b/target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch new file mode 100644 index 0000000000..f0b5b98610 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch @@ -0,0 +1,113 @@ +From 944b96d734199642e2ede978c48d754109ca334c Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Mon, 20 Mar 2023 21:54:31 +0800 +Subject: [PATCH 059/122] dt-bindings: timer: Add timer for StarFive JH7110 SoC + +Add bindings for the timer on the JH7110 RISC-V SoC +by StarFive Technology Ltd. + +Signed-off-by: Xingyu Wu +Reviewed-by: Krzysztof Kozlowski +--- + .../bindings/timer/starfive,jh7110-timer.yaml | 95 +++++++++++++++++++ + 1 file changed, 95 insertions(+) + create mode 100644 Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml +@@ -0,0 +1,95 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/timer/starfive,jh7110-timer.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 Timer ++maintainers: ++ - Xingyu Wu ++ - Samin Guo ++ ++description: ++ This timer has four free-running 32 bit counters in StarFive JH7110 SoC. ++ And each channel(counter) triggers an interrupt when timeout. They support ++ one-shot mode and continuous-run mode. ++ ++properties: ++ compatible: ++ const: starfive,jh7110-timer ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ items: ++ - description: channel 0 ++ - description: channel 1 ++ - description: channel 2 ++ - description: channel 3 ++ ++ clocks: ++ items: ++ - description: timer APB ++ - description: channel 0 ++ - description: channel 1 ++ - description: channel 2 ++ - description: channel 3 ++ ++ clock-names: ++ items: ++ - const: apb ++ - const: ch0 ++ - const: ch1 ++ - const: ch2 ++ - const: ch3 ++ ++ resets: ++ items: ++ - description: timer APB ++ - description: channel 0 ++ - description: channel 1 ++ - description: channel 2 ++ - description: channel 3 ++ ++ reset-names: ++ items: ++ - const: apb ++ - const: ch0 ++ - const: ch1 ++ - const: ch2 ++ - const: ch3 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ - resets ++ - reset-names ++ ++additionalProperties: false ++ ++examples: ++ - | ++ timer@13050000 { ++ compatible = "starfive,jh7110-timer"; ++ reg = <0x13050000 0x10000>; ++ interrupts = <69>, <70>, <71> ,<72>; ++ clocks = <&clk 124>, ++ <&clk 125>, ++ <&clk 126>, ++ <&clk 127>, ++ <&clk 128>; ++ clock-names = "apb", "ch0", "ch1", ++ "ch2", "ch3"; ++ resets = <&rst 117>, ++ <&rst 118>, ++ <&rst 119>, ++ <&rst 120>, ++ <&rst 121>; ++ reset-names = "apb", "ch0", "ch1", ++ "ch2", "ch3"; ++ }; ++ diff --git a/target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch b/target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch new file mode 100644 index 0000000000..dc6f1e0bf8 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch @@ -0,0 +1,540 @@ +From 3fbdabd59bac0978536fb11b1b9deb81559f1c54 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Mon, 20 Mar 2023 21:54:32 +0800 +Subject: [PATCH 060/122] clocksource: Add StarFive timer driver + +Add timer driver for the StarFive JH7110 SoC. + +Signed-off-by: Xingyu Wu +--- + drivers/clocksource/Kconfig | 12 + + drivers/clocksource/Makefile | 1 + + drivers/clocksource/timer-starfive.c | 390 +++++++++++++++++++++++++++ + drivers/clocksource/timer-starfive.h | 96 +++++++ + 4 files changed, 499 insertions(+) + create mode 100644 drivers/clocksource/timer-starfive.c + create mode 100644 drivers/clocksource/timer-starfive.h + +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -630,6 +630,18 @@ config RISCV_TIMER + is accessed via both the SBI and the rdcycle instruction. This is + required for all RISC-V systems. + ++config STARFIVE_TIMER ++ bool "Timer for the STARFIVE SoCs" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ select TIMER_OF ++ select CLKSRC_MMIO ++ default ARCH_STARFIVE ++ help ++ This enables the timer for StarFive SoCs. On RISC-V platform, ++ the system has started RISCV_TIMER. But you can also use this timer ++ to do a lot more on StarFive SoCs. This timer can provide high ++ precision and four channels to use in JH7110 SoC. ++ + config CLINT_TIMER + bool "CLINT Timer for the RISC-V platform" if COMPILE_TEST + depends on GENERIC_SCHED_CLOCK && RISCV +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -80,6 +80,7 @@ obj-$(CONFIG_INGENIC_TIMER) += ingenic- + obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o + obj-$(CONFIG_X86_NUMACHIP) += numachip.o + obj-$(CONFIG_RISCV_TIMER) += timer-riscv.o ++obj-$(CONFIG_STARFIVE_TIMER) += timer-starfive.o + obj-$(CONFIG_CLINT_TIMER) += timer-clint.o + obj-$(CONFIG_CSKY_MP_TIMER) += timer-mp-csky.o + obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o +--- /dev/null ++++ b/drivers/clocksource/timer-starfive.c +@@ -0,0 +1,390 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Starfive Timer driver ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * ++ * Author: ++ * Xingyu Wu ++ * Samin Guo ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "timer-starfive.h" ++ ++static const struct starfive_timer_chan_base starfive_timer_jh7110_base = { ++ .ctrl = STARFIVE_TIMER_JH7110_CTL, ++ .load = STARFIVE_TIMER_JH7110_LOAD, ++ .enable = STARFIVE_TIMER_JH7110_ENABLE, ++ .reload = STARFIVE_TIMER_JH7110_RELOAD, ++ .value = STARFIVE_TIMER_JH7110_VALUE, ++ .intclr = STARFIVE_TIMER_JH7110_INT_CLR, ++ .intmask = STARFIVE_TIMER_JH7110_INT_MASK, ++ .channel_num = STARFIVE_TIMER_CH_4, ++ .channel_base = {STARFIVE_TIMER_CH_BASE(0), STARFIVE_TIMER_CH_BASE(1), ++ STARFIVE_TIMER_CH_BASE(2), STARFIVE_TIMER_CH_BASE(3)}, ++}; ++ ++static inline struct starfive_clkevt *to_starfive_clkevt(struct clock_event_device *evt) ++{ ++ return container_of(evt, struct starfive_clkevt, evt); ++} ++ ++/* 0:continuous-run mode, 1:single-run mode */ ++static inline void starfive_timer_set_mod(struct starfive_clkevt *clkevt, int mod) ++{ ++ writel(mod, clkevt->ctrl); ++} ++ ++/* Interrupt Mask Register, 0:Unmask, 1:Mask */ ++static inline void starfive_timer_int_enable(struct starfive_clkevt *clkevt) ++{ ++ writel(STARFIVE_TIMER_INTMASK_DIS, clkevt->intmask); ++} ++ ++static inline void starfive_timer_int_disable(struct starfive_clkevt *clkevt) ++{ ++ writel(STARFIVE_TIMER_INTMASK_ENA, clkevt->intmask); ++} ++ ++/* ++ * BIT(0): Read value represent channel intr status. ++ * Write 1 to this bit to clear interrupt. Write 0 has no effects. ++ * BIT(1): "1" means that it is clearing interrupt. BIT(0) can not be written. ++ */ ++static inline int starfive_timer_int_clear(struct starfive_clkevt *clkevt) ++{ ++ u32 value; ++ int ret; ++ ++ /* waiting interrupt can be to clearing */ ++ ret = readl_poll_timeout_atomic(clkevt->intclr, value, ++ !(value & STARFIVE_TIMER_JH7110_INT_CLR_AVA_MASK), ++ STARFIVE_DELAY_US, STARFIVE_TIMEOUT_US); ++ if (!ret) ++ writel(0x1, clkevt->intclr); ++ ++ return ret; ++} ++ ++/* ++ * The initial value to be loaded into the ++ * counter and is also used as the reload value. ++ * val = clock rate --> 1s ++ */ ++static inline void starfive_timer_set_load(struct starfive_clkevt *clkevt, u32 val) ++{ ++ writel(val, clkevt->load); ++} ++ ++static inline u32 starfive_timer_get_val(struct starfive_clkevt *clkevt) ++{ ++ return readl(clkevt->value); ++} ++ ++/* ++ * Write RELOAD register to reload preset value to counter. ++ * (Write 0 and write 1 are both ok) ++ */ ++static inline void starfive_timer_set_reload(struct starfive_clkevt *clkevt) ++{ ++ writel(0, clkevt->reload); ++} ++ ++static inline void starfive_timer_enable(struct starfive_clkevt *clkevt) ++{ ++ writel(STARFIVE_TIMER_ENA, clkevt->enable); ++} ++ ++static inline void starfive_timer_disable(struct starfive_clkevt *clkevt) ++{ ++ writel(STARFIVE_TIMER_DIS, clkevt->enable); ++} ++ ++static int starfive_timer_int_init_enable(struct starfive_clkevt *clkevt) ++{ ++ int ret; ++ ++ starfive_timer_int_disable(clkevt); ++ ret = starfive_timer_int_clear(clkevt); ++ if (ret) ++ return ret; ++ ++ starfive_timer_int_enable(clkevt); ++ starfive_timer_enable(clkevt); ++ ++ return 0; ++} ++ ++static int starfive_timer_shutdown(struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ starfive_timer_disable(clkevt); ++ return starfive_timer_int_clear(clkevt); ++} ++ ++static void starfive_timer_suspend(struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ clkevt->reload_val = starfive_timer_get_val(clkevt); ++ starfive_timer_shutdown(evt); ++} ++ ++static void starfive_timer_resume(struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ starfive_timer_set_load(clkevt, clkevt->reload_val); ++ starfive_timer_set_reload(clkevt); ++ starfive_timer_int_enable(clkevt); ++ starfive_timer_enable(clkevt); ++} ++ ++static int starfive_timer_tick_resume(struct clock_event_device *evt) ++{ ++ starfive_timer_resume(evt); ++ ++ return 0; ++} ++ ++static int starfive_clocksource_init(struct starfive_clkevt *clkevt) ++{ ++ int ret; ++ ++ starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_CONTIN); ++ starfive_timer_set_load(clkevt, STARFIVE_TIMER_MAX_TICKS); ++ ret = starfive_timer_int_init_enable(clkevt); ++ if (ret) ++ return ret; ++ ++ return clocksource_mmio_init(clkevt->value, clkevt->name, clkevt->rate, ++ STARFIVE_CLOCK_SOURCE_RATING, STARFIVE_VALID_BITS, ++ clocksource_mmio_readl_down); ++} ++ ++/* IRQ handler for the timer */ ++static irqreturn_t starfive_timer_interrupt(int irq, void *priv) ++{ ++ struct clock_event_device *evt = (struct clock_event_device *)priv; ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ if (starfive_timer_int_clear(clkevt)) ++ return IRQ_NONE; ++ ++ if (evt->event_handler) ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static int starfive_timer_set_periodic(struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ starfive_timer_disable(clkevt); ++ starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_CONTIN); ++ starfive_timer_set_load(clkevt, clkevt->periodic); ++ ++ return starfive_timer_int_init_enable(clkevt); ++} ++ ++static int starfive_timer_set_oneshot(struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ starfive_timer_disable(clkevt); ++ starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_SINGLE); ++ starfive_timer_set_load(clkevt, STARFIVE_TIMER_MAX_TICKS); ++ ++ return starfive_timer_int_init_enable(clkevt); ++} ++ ++static int starfive_timer_set_next_event(unsigned long next, ++ struct clock_event_device *evt) ++{ ++ struct starfive_clkevt *clkevt = to_starfive_clkevt(evt); ++ ++ starfive_timer_disable(clkevt); ++ starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_SINGLE); ++ starfive_timer_set_load(clkevt, next); ++ starfive_timer_enable(clkevt); ++ ++ return 0; ++} ++ ++static void starfive_set_clockevent(struct clock_event_device *evt) ++{ ++ evt->features = CLOCK_EVT_FEAT_PERIODIC | ++ CLOCK_EVT_FEAT_ONESHOT | ++ CLOCK_EVT_FEAT_DYNIRQ; ++ evt->set_state_shutdown = starfive_timer_shutdown; ++ evt->set_state_periodic = starfive_timer_set_periodic; ++ evt->set_state_oneshot = starfive_timer_set_oneshot; ++ evt->set_state_oneshot_stopped = starfive_timer_shutdown; ++ evt->tick_resume = starfive_timer_tick_resume; ++ evt->set_next_event = starfive_timer_set_next_event; ++ evt->suspend = starfive_timer_suspend; ++ evt->resume = starfive_timer_resume; ++ evt->rating = STARFIVE_CLOCKEVENT_RATING; ++} ++ ++static void starfive_clockevents_register(struct starfive_clkevt *clkevt) ++{ ++ clkevt->rate = clk_get_rate(clkevt->clk); ++ clkevt->periodic = DIV_ROUND_CLOSEST(clkevt->rate, HZ); ++ ++ starfive_set_clockevent(&clkevt->evt); ++ clkevt->evt.name = clkevt->name; ++ clkevt->evt.irq = clkevt->irq; ++ clkevt->evt.cpumask = cpu_possible_mask; ++ ++ clockevents_config_and_register(&clkevt->evt, clkevt->rate, ++ STARFIVE_TIMER_MIN_TICKS, STARFIVE_TIMER_MAX_TICKS); ++} ++ ++static void __init starfive_clkevt_base_init(const struct starfive_timer_chan_base *timer, ++ struct starfive_clkevt *clkevt, ++ void __iomem *base, int ch) ++{ ++ void __iomem *channel_base; ++ ++ channel_base = base + timer->channel_base[ch]; ++ clkevt->base = channel_base; ++ clkevt->ctrl = channel_base + timer->ctrl; ++ clkevt->load = channel_base + timer->load; ++ clkevt->enable = channel_base + timer->enable; ++ clkevt->reload = channel_base + timer->reload; ++ clkevt->value = channel_base + timer->value; ++ clkevt->intclr = channel_base + timer->intclr; ++ clkevt->intmask = channel_base + timer->intmask; ++} ++ ++static int __init starfive_timer_probe(struct platform_device *pdev) ++{ ++ const struct starfive_timer_chan_base *timer_base = of_device_get_match_data(&pdev->dev); ++ char name[10]; ++ struct starfive_timer_priv *priv; ++ struct starfive_clkevt *clkevt; ++ struct clk *pclk; ++ struct reset_control *rst; ++ int ch; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, struct_size(priv, clkevt, timer_base->channel_num), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->base), ++ "failed to map registers\n"); ++ ++ rst = devm_reset_control_get_exclusive(&pdev->dev, "apb"); ++ if (IS_ERR(rst)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(rst), "failed to get apb reset\n"); ++ ++ pclk = devm_clk_get_enabled(&pdev->dev, "apb"); ++ if (IS_ERR(pclk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pclk), ++ "failed to get & enable apb clock\n"); ++ ++ ret = reset_control_deassert(rst); ++ if (ret) ++ goto err; ++ ++ priv->dev = &pdev->dev; ++ platform_set_drvdata(pdev, priv); ++ ++ for (ch = 0; ch < timer_base->channel_num; ch++) { ++ clkevt = &priv->clkevt[ch]; ++ snprintf(name, sizeof(name), "ch%d", ch); ++ ++ starfive_clkevt_base_init(timer_base, clkevt, priv->base, ch); ++ /* Ensure timers are disabled */ ++ starfive_timer_disable(clkevt); ++ ++ rst = devm_reset_control_get_exclusive(&pdev->dev, name); ++ if (IS_ERR(rst)) { ++ ret = PTR_ERR(rst); ++ goto err; ++ } ++ ++ clkevt->clk = devm_clk_get_enabled(&pdev->dev, name); ++ if (IS_ERR(clkevt->clk)) { ++ ret = PTR_ERR(clkevt->clk); ++ goto err; ++ } ++ ++ ret = reset_control_deassert(rst); ++ if (ret) ++ goto ch_err; ++ ++ clkevt->irq = platform_get_irq(pdev, ch); ++ if (clkevt->irq < 0) { ++ ret = clkevt->irq; ++ goto ch_err; ++ } ++ ++ snprintf(clkevt->name, sizeof(clkevt->name), "%s.ch%d", pdev->name, ch); ++ starfive_clockevents_register(clkevt); ++ ++ ret = devm_request_irq(&pdev->dev, clkevt->irq, starfive_timer_interrupt, ++ IRQF_TIMER | IRQF_IRQPOLL, ++ clkevt->name, &clkevt->evt); ++ if (ret) ++ goto ch_err; ++ ++ ret = starfive_clocksource_init(clkevt); ++ if (ret) ++ goto ch_err; ++ } ++ ++ return 0; ++ ++ch_err: ++ /* Only unregister the failed channel and the rest timer channels continue to work. */ ++ clk_disable_unprepare(clkevt->clk); ++err: ++ /* If no other channel successfully registers, pclk should be disabled. */ ++ if (!ch) ++ clk_disable_unprepare(pclk); ++ ++ return ret; ++} ++ ++static const struct of_device_id starfive_timer_match[] = { ++ { .compatible = "starfive,jh7110-timer", .data = &starfive_timer_jh7110_base }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, starfive_timer_match); ++ ++static struct platform_driver starfive_timer_driver = { ++ .probe = starfive_timer_probe, ++ .driver = { ++ .name = "starfive-timer", ++ .of_match_table = starfive_timer_match, ++ }, ++}; ++module_platform_driver(starfive_timer_driver); ++ ++MODULE_AUTHOR("Xingyu Wu "); ++MODULE_DESCRIPTION("StarFive timer driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/clocksource/timer-starfive.h +@@ -0,0 +1,96 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef __STARFIVE_TIMER_H__ ++#define __STARFIVE_TIMER_H__ ++ ++/* Bias: Ch0-0x0, Ch1-0x40, Ch2-0x80, and so on. */ ++#define STARFIVE_TIMER_CH_LEN 0x40 ++#define STARFIVE_TIMER_CH_BASE(x) ((STARFIVE_TIMER_CH_##x) * STARFIVE_TIMER_CH_LEN) ++ ++#define STARFIVE_CLOCK_SOURCE_RATING 200 ++#define STARFIVE_VALID_BITS 32 ++#define STARFIVE_DELAY_US 0 ++#define STARFIVE_TIMEOUT_US 10000 ++#define STARFIVE_CLOCKEVENT_RATING 300 ++#define STARFIVE_TIMER_MAX_TICKS 0xffffffff ++#define STARFIVE_TIMER_MIN_TICKS 0xf ++ ++#define STARFIVE_TIMER_JH7110_INT_STATUS 0x00 /* RO[0:4]: Interrupt Status for channel0~4 */ ++#define STARFIVE_TIMER_JH7110_CTL 0x04 /* RW[0]: 0-continuous run, 1-single run */ ++#define STARFIVE_TIMER_JH7110_LOAD 0x08 /* RW: load value to counter */ ++#define STARFIVE_TIMER_JH7110_ENABLE 0x10 /* RW[0]: timer enable register */ ++#define STARFIVE_TIMER_JH7110_RELOAD 0x14 /* RW: write 1 or 0 both reload counter */ ++#define STARFIVE_TIMER_JH7110_VALUE 0x18 /* RO: timer value register */ ++#define STARFIVE_TIMER_JH7110_INT_CLR 0x20 /* RW: timer interrupt clear register */ ++#define STARFIVE_TIMER_JH7110_INT_MASK 0x24 /* RW[0]: timer interrupt mask register */ ++#define STARFIVE_TIMER_JH7110_INT_CLR_AVA_MASK BIT(1) ++ ++enum STARFIVE_TIMER_CH { ++ STARFIVE_TIMER_CH_0 = 0, ++ STARFIVE_TIMER_CH_1, ++ STARFIVE_TIMER_CH_2, ++ STARFIVE_TIMER_CH_3, ++ STARFIVE_TIMER_CH_4, ++ STARFIVE_TIMER_CH_5, ++ STARFIVE_TIMER_CH_6, ++ STARFIVE_TIMER_CH_7, ++ STARFIVE_TIMER_CH_MAX ++}; ++ ++enum STARFIVE_TIMER_INTMASK { ++ STARFIVE_TIMER_INTMASK_DIS = 0, ++ STARFIVE_TIMER_INTMASK_ENA = 1 ++}; ++ ++enum STARFIVE_TIMER_MOD { ++ STARFIVE_TIMER_MOD_CONTIN = 0, ++ STARFIVE_TIMER_MOD_SINGLE = 1 ++}; ++ ++enum STARFIVE_TIMER_CTL_EN { ++ STARFIVE_TIMER_DIS = 0, ++ STARFIVE_TIMER_ENA = 1 ++}; ++ ++struct starfive_timer_chan_base { ++ /* Resgister */ ++ unsigned int ctrl; ++ unsigned int load; ++ unsigned int enable; ++ unsigned int reload; ++ unsigned int value; ++ unsigned int intclr; ++ unsigned int intmask; ++ ++ unsigned int channel_num; /* timer channel numbers */ ++ unsigned int channel_base[]; ++}; ++ ++struct starfive_clkevt { ++ struct clock_event_device evt; ++ struct clk *clk; ++ char name[20]; ++ int irq; ++ u32 periodic; ++ u32 rate; ++ u32 reload_val; ++ void __iomem *base; ++ void __iomem *ctrl; ++ void __iomem *load; ++ void __iomem *enable; ++ void __iomem *reload; ++ void __iomem *value; ++ void __iomem *intclr; ++ void __iomem *intmask; ++}; ++ ++struct starfive_timer_priv { ++ struct device *dev; ++ void __iomem *base; ++ struct starfive_clkevt clkevt[]; ++}; ++ ++#endif /* __STARFIVE_TIMER_H__ */ diff --git a/target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch b/target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch new file mode 100644 index 0000000000..58f29cda8f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch @@ -0,0 +1,36 @@ +From 16214121afaadb8ae9aaf73351e874405eb47c15 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Tue, 25 Apr 2023 18:51:15 +0800 +Subject: [PATCH 061/122] dt-bindings: net: motorcomm: Add pad driver strength + cfg + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, the value range of pad driver +strength is 0 to 7. + +Signed-off-by: Samin Guo +--- + .../devicetree/bindings/net/motorcomm,yt8xxx.yaml | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml ++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml +@@ -62,6 +62,18 @@ properties: + for a timer. + type: boolean + ++ motorcomm,rx-clk-driver-strength: ++ description: drive strength of rx_clk pad. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] ++ default: 3 ++ ++ motorcomm,rx-data-driver-strength: ++ description: drive strength of rx_data/rx_ctl rgmii pad. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] ++ default: 3 ++ + motorcomm,tx-clk-adj-enabled: + description: | + This configuration is mainly to adapt to VF2 with JH7110 SoC. diff --git a/target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch b/target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch new file mode 100644 index 0000000000..20546650a3 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch @@ -0,0 +1,71 @@ +From 99f0bf43994dada29e33fd8718fd25484634da3a Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Tue, 21 Mar 2023 13:52:27 +0800 +Subject: [PATCH 062/122] dt-bindings: PWM: Add StarFive PWM module + +Add documentation to describe StarFive Pulse Width Modulation +controller driver. + +Signed-off-by: William Qiu +Reviewed-by: Krzysztof Kozlowski +--- + .../bindings/pwm/starfive,jh7110-pwm.yaml | 53 +++++++++++++++++++ + 1 file changed, 53 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pwm/starfive,jh7110-pwm.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pwm/starfive,jh7110-pwm.yaml +@@ -0,0 +1,53 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/pwm/starfive,jh7110-pwm.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive PWM controller ++ ++maintainers: ++ - William Qiu ++ ++description: ++ StarFive SoCs contain PWM and when operating in PWM mode, the PTC core generates ++ binary signal with user-programmable low and high periods. Clock source for the ++ PWM can be either system clockor external clock. Each PWM timer block provides 8 ++ PWM channels. ++ ++allOf: ++ - $ref: pwm.yaml# ++ ++properties: ++ compatible: ++ const: starfive,jh7110-pwm ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ "#pwm-cells": ++ const: 3 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pwm@120d0000 { ++ compatible = "starfive,jh7110-pwm"; ++ reg = <0x120d0000 0x10000>; ++ clocks = <&syscrg 121>; ++ resets = <&syscrg 108>; ++ #pwm-cells = <3>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch b/target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch new file mode 100644 index 0000000000..0433160a20 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch @@ -0,0 +1,294 @@ +From fddea961e7ce1f26dd549e3d92ede624246690c0 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Tue, 21 Mar 2023 13:52:28 +0800 +Subject: [PATCH 063/122] pwm: starfive: Add PWM driver support + +Add Pulse Width Modulation driver support for StarFive +JH7110 soc. + +Signed-off-by: Hal Feng +Signed-off-by: William Qiu +--- + drivers/pwm/Kconfig | 10 ++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-starfive-ptc.c | 245 +++++++++++++++++++++++++++++++++ + 3 files changed, 256 insertions(+) + create mode 100644 drivers/pwm/pwm-starfive-ptc.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -536,6 +536,16 @@ config PWM_SPRD + To compile this driver as a module, choose M here: the module + will be called pwm-sprd. + ++config PWM_STARFIVE_PTC ++ tristate "StarFive PWM PTC support" ++ depends on OF ++ depends on COMMON_CLK ++ help ++ Generic PWM framework driver for StarFive SoCs. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-starfive-ptc. ++ + config PWM_STI + tristate "STiH4xx PWM support" + depends on ARCH_STI || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -49,6 +49,7 @@ obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o + obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o + obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o + obj-$(CONFIG_PWM_SPRD) += pwm-sprd.o ++obj-$(CONFIG_PWM_STARFIVE_PTC) += pwm-starfive-ptc.o + obj-$(CONFIG_PWM_STI) += pwm-sti.o + obj-$(CONFIG_PWM_STM32) += pwm-stm32.o + obj-$(CONFIG_PWM_STM32_LP) += pwm-stm32-lp.o +--- /dev/null ++++ b/drivers/pwm/pwm-starfive-ptc.c +@@ -0,0 +1,245 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PWM driver for the StarFive JH7110 SoC ++ * ++ * Copyright (C) 2018 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* how many parameters can be transferred to ptc */ ++#define OF_PWM_N_CELLS 3 ++ ++/* PTC Register offsets */ ++#define REG_RPTC_CNTR 0x0 ++#define REG_RPTC_HRC 0x4 ++#define REG_RPTC_LRC 0x8 ++#define REG_RPTC_CTRL 0xC ++ ++/* Bit for PWM clock */ ++#define BIT_PWM_CLOCK_EN 31 ++ ++/* Bit for clock gen soft reset */ ++#define BIT_CLK_GEN_SOFT_RESET 13 ++ ++#define NS_PER_SECOND 1000000000 ++ ++/* ++ * Access PTC register (cntr hrc lrc and ctrl), ++ * need to replace PWM_BASE_ADDR ++ */ ++#define REG_PTC_BASE_ADDR_SUB(base, N) \ ++((base) + (((N) > 3) ? (((N) % 4) * 0x10 + (1 << 15)) : ((N) * 0x10))) ++#define REG_PTC_RPTC_CNTR(base, N) (REG_PTC_BASE_ADDR_SUB(base, N)) ++#define REG_PTC_RPTC_HRC(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0x4) ++#define REG_PTC_RPTC_LRC(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0x8) ++#define REG_PTC_RPTC_CTRL(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0xC) ++ ++/* PTC_RPTC_CTRL */ ++#define PTC_EN BIT(0) ++#define PTC_ECLK BIT(1) ++#define PTC_NEC BIT(2) ++#define PTC_OE BIT(3) ++#define PTC_SIGNLE BIT(4) ++#define PTC_INTE BIT(5) ++#define PTC_INT BIT(6) ++#define PTC_CNTRRST BIT(7) ++#define PTC_CAPTE BIT(8) ++ ++struct starfive_pwm_ptc_device { ++ struct pwm_chip chip; ++ struct clk *clk; ++ struct reset_control *rst; ++ void __iomem *regs; ++ int irq; ++ unsigned int approx_freq;/*pwm apb clock frequency*/ ++}; ++ ++static inline ++struct starfive_pwm_ptc_device *chip_to_starfive_ptc(struct pwm_chip *c) ++{ ++ return container_of(c, struct starfive_pwm_ptc_device, chip); ++} ++ ++static int starfive_pwm_ptc_get_state(struct pwm_chip *chip, ++ struct pwm_device *dev, ++ struct pwm_state *state) ++{ ++ struct starfive_pwm_ptc_device *pwm = chip_to_starfive_ptc(chip); ++ u32 data_lrc, data_hrc; ++ u32 pwm_clk_ns = 0; ++ ++ data_lrc = ioread32(REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm)); ++ data_hrc = ioread32(REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm)); ++ ++ pwm_clk_ns = NS_PER_SECOND / pwm->approx_freq; ++ ++ state->period = data_lrc * pwm_clk_ns; ++ state->duty_cycle = data_hrc * pwm_clk_ns; ++ state->polarity = PWM_POLARITY_NORMAL; ++ state->enabled = 1; ++ ++ return 0; ++} ++ ++static int starfive_pwm_ptc_apply(struct pwm_chip *chip, ++ struct pwm_device *dev, ++ struct pwm_state *state) ++{ ++ struct starfive_pwm_ptc_device *pwm = chip_to_starfive_ptc(chip); ++ u32 data_hrc = 0; ++ u32 data_lrc = 0; ++ u32 period_data = 0; ++ u32 duty_data = 0; ++ s64 multi = pwm->approx_freq; ++ s64 div = NS_PER_SECOND; ++ void __iomem *reg_addr; ++ ++ if (state->duty_cycle > state->period) ++ state->duty_cycle = state->period; ++ ++ while (multi % 10 == 0 && div % 10 == 0 && multi > 0 && div > 0) { ++ multi /= 10; ++ div /= 10; ++ } ++ ++ period_data = (u32)(state->period * multi / div); ++ if (abs(period_data * div / multi - state->period) ++ > abs((period_data + 1) * div / multi - state->period) || ++ (state->period > 0 && period_data == 0)) ++ period_data += 1; ++ ++ if (state->enabled) { ++ duty_data = (u32)(state->duty_cycle * multi / div); ++ if (abs(duty_data * div / multi - state->duty_cycle) ++ > abs((duty_data + 1) * div / multi - state->duty_cycle) || ++ (state->duty_cycle > 0 && duty_data == 0)) ++ duty_data += 1; ++ } else { ++ duty_data = 0; ++ } ++ ++ if (state->polarity == PWM_POLARITY_NORMAL) ++ data_hrc = period_data - duty_data; ++ else ++ data_hrc = duty_data; ++ ++ data_lrc = period_data; ++ ++ reg_addr = REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm); ++ iowrite32(data_hrc, reg_addr); ++ ++ reg_addr = REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm); ++ iowrite32(data_lrc, reg_addr); ++ ++ reg_addr = REG_PTC_RPTC_CNTR(pwm->regs, dev->hwpwm); ++ iowrite32(0, reg_addr); ++ ++ reg_addr = REG_PTC_RPTC_CTRL(pwm->regs, dev->hwpwm); ++ iowrite32(PTC_EN | PTC_OE, reg_addr); ++ ++ return 0; ++} ++ ++static const struct pwm_ops starfive_pwm_ptc_ops = { ++ .get_state = starfive_pwm_ptc_get_state, ++ .apply = (void *)starfive_pwm_ptc_apply, ++ .owner = THIS_MODULE, ++}; ++ ++static int starfive_pwm_ptc_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct starfive_pwm_ptc_device *pwm; ++ struct pwm_chip *chip; ++ int ret; ++ ++ pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL); ++ if (!pwm) ++ return -ENOMEM; ++ ++ chip = &pwm->chip; ++ chip->dev = dev; ++ chip->ops = &starfive_pwm_ptc_ops; ++ chip->npwm = 8; ++ ++ chip->of_pwm_n_cells = OF_PWM_N_CELLS; ++ chip->base = -1; ++ ++ pwm->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pwm->regs)) ++ return dev_err_probe(dev, PTR_ERR(pwm->regs), ++ "Unable to map IO resources\n"); ++ ++ pwm->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(pwm->clk)) ++ return dev_err_probe(dev, PTR_ERR(pwm->clk), ++ "Unable to get pwm clock\n"); ++ ++ pwm->rst = devm_reset_control_get_exclusive(dev, NULL); ++ if (IS_ERR(pwm->rst)) ++ return dev_err_probe(dev, PTR_ERR(pwm->rst), ++ "Unable to get pwm reset\n"); ++ ++ ret = clk_prepare_enable(pwm->clk); ++ if (ret) { ++ dev_err(dev, ++ "Failed to enable pwm clock, %d\n", ret); ++ return ret; ++ } ++ ++ reset_control_deassert(pwm->rst); ++ ++ pwm->approx_freq = (unsigned int)clk_get_rate(pwm->clk); ++ if (!pwm->approx_freq) ++ dev_err(dev, "get pwm apb clock rate failed.\n"); ++ ++ ret = devm_pwmchip_add(dev, chip); ++ if (ret < 0) { ++ dev_err(dev, "cannot register PTC: %d\n", ret); ++ clk_disable_unprepare(pwm->clk); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, pwm); ++ ++ return 0; ++} ++ ++static int starfive_pwm_ptc_remove(struct platform_device *dev) ++{ ++ struct starfive_pwm_ptc_device *pwm = platform_get_drvdata(dev); ++ struct pwm_chip *chip = &pwm->chip; ++ ++ pwmchip_remove(chip); ++ ++ return 0; ++} ++ ++static const struct of_device_id starfive_pwm_ptc_of_match[] = { ++ { .compatible = "starfive,jh7110-pwm" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, starfive_pwm_ptc_of_match); ++ ++static struct platform_driver starfive_pwm_ptc_driver = { ++ .probe = starfive_pwm_ptc_probe, ++ .remove = starfive_pwm_ptc_remove, ++ .driver = { ++ .name = "pwm-starfive-ptc", ++ .of_match_table = starfive_pwm_ptc_of_match, ++ }, ++}; ++module_platform_driver(starfive_pwm_ptc_driver); ++ ++MODULE_AUTHOR("Jenny Zhang "); ++MODULE_AUTHOR("Hal Feng "); ++MODULE_DESCRIPTION("StarFive PWM PTC driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch b/target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch new file mode 100644 index 0000000000..09b2dccef9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch @@ -0,0 +1,90 @@ +From 207dde3ed123613cd84c8f706a24d75cefece67c Mon Sep 17 00:00:00 2001 +From: Jia Jie Ho +Date: Mon, 15 May 2023 20:53:52 +0800 +Subject: [PATCH 064/122] dt-bindings: crypto: Add StarFive crypto module + +Add documentation to describe StarFive cryptographic engine. + +Co-developed-by: Huan Feng +Signed-off-by: Huan Feng +Signed-off-by: Jia Jie Ho +Reviewed-by: Rob Herring +Signed-off-by: Herbert Xu +--- + .../crypto/starfive,jh7110-crypto.yaml | 70 +++++++++++++++++++ + 1 file changed, 70 insertions(+) + create mode 100644 Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml +@@ -0,0 +1,70 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/crypto/starfive,jh7110-crypto.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive Cryptographic Module ++ ++maintainers: ++ - Jia Jie Ho ++ - William Qiu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-crypto ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: Hardware reference clock ++ - description: AHB reference clock ++ ++ clock-names: ++ items: ++ - const: hclk ++ - const: ahb ++ ++ interrupts: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ dmas: ++ items: ++ - description: TX DMA channel ++ - description: RX DMA channel ++ ++ dma-names: ++ items: ++ - const: tx ++ - const: rx ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - dmas ++ - dma-names ++ ++additionalProperties: false ++ ++examples: ++ - | ++ crypto: crypto@16000000 { ++ compatible = "starfive,jh7110-crypto"; ++ reg = <0x16000000 0x4000>; ++ clocks = <&clk 15>, <&clk 16>; ++ clock-names = "hclk", "ahb"; ++ interrupts = <28>; ++ resets = <&reset 3>; ++ dmas = <&dma 1 2>, ++ <&dma 0 2>; ++ dma-names = "tx", "rx"; ++ }; ++... diff --git a/target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch b/target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch new file mode 100644 index 0000000000..5aa3bc10f6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch @@ -0,0 +1,337 @@ +From 8b1069fcc1dbb524556d851f3dedf0629a71f17b Mon Sep 17 00:00:00 2001 +From: Jia Jie Ho +Date: Mon, 15 May 2023 20:53:53 +0800 +Subject: [PATCH 065/122] crypto: starfive - Add crypto engine support + +Adding device probe and DMA init for StarFive cryptographic module. + +Co-developed-by: Huan Feng +Signed-off-by: Huan Feng +Signed-off-by: Jia Jie Ho +Signed-off-by: Herbert Xu +--- + drivers/crypto/Kconfig | 1 + + drivers/crypto/Makefile | 1 + + drivers/crypto/starfive/Kconfig | 17 +++ + drivers/crypto/starfive/Makefile | 4 + + drivers/crypto/starfive/jh7110-cryp.c | 201 ++++++++++++++++++++++++++ + drivers/crypto/starfive/jh7110-cryp.h | 63 ++++++++ + 6 files changed, 287 insertions(+) + create mode 100644 drivers/crypto/starfive/Kconfig + create mode 100644 drivers/crypto/starfive/Makefile + create mode 100644 drivers/crypto/starfive/jh7110-cryp.c + create mode 100644 drivers/crypto/starfive/jh7110-cryp.h + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -823,5 +823,6 @@ config CRYPTO_DEV_SA2UL + + source "drivers/crypto/keembay/Kconfig" + source "drivers/crypto/aspeed/Kconfig" ++source "drivers/crypto/starfive/Kconfig" + + endif # CRYPTO_HW +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -53,3 +53,4 @@ obj-y += xilinx/ + obj-y += hisilicon/ + obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ + obj-y += keembay/ ++obj-y += starfive/ +--- /dev/null ++++ b/drivers/crypto/starfive/Kconfig +@@ -0,0 +1,17 @@ ++# ++# StarFive crypto drivers configuration ++# ++ ++config CRYPTO_DEV_JH7110 ++ tristate "StarFive JH7110 cryptographic engine driver" ++ depends on SOC_STARFIVE || COMPILE_TEST ++ select CRYPTO_ENGINE ++ select ARM_AMBA ++ select DMADEVICES ++ select AMBA_PL08X ++ help ++ Support for StarFive JH7110 crypto hardware acceleration engine. ++ This module provides acceleration for public key algo, ++ skciphers, AEAD and hash functions. ++ ++ If you choose 'M' here, this module will be called jh7110-crypto. +--- /dev/null ++++ b/drivers/crypto/starfive/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o ++jh7110-crypto-objs := jh7110-cryp.o +--- /dev/null ++++ b/drivers/crypto/starfive/jh7110-cryp.c +@@ -0,0 +1,201 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Cryptographic API. ++ * ++ * Support for StarFive hardware cryptographic engine. ++ * Copyright (c) 2022 StarFive Technology ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "jh7110-cryp.h" ++ ++#define DRIVER_NAME "jh7110-crypto" ++ ++struct starfive_dev_list { ++ struct list_head dev_list; ++ spinlock_t lock; /* protect dev_list */ ++}; ++ ++static struct starfive_dev_list dev_list = { ++ .dev_list = LIST_HEAD_INIT(dev_list.dev_list), ++ .lock = __SPIN_LOCK_UNLOCKED(dev_list.lock), ++}; ++ ++struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) ++{ ++ struct starfive_cryp_dev *cryp = NULL, *tmp; ++ ++ spin_lock_bh(&dev_list.lock); ++ if (!ctx->cryp) { ++ list_for_each_entry(tmp, &dev_list.dev_list, list) { ++ cryp = tmp; ++ break; ++ } ++ ctx->cryp = cryp; ++ } else { ++ cryp = ctx->cryp; ++ } ++ ++ spin_unlock_bh(&dev_list.lock); ++ ++ return cryp; ++} ++ ++static int starfive_dma_init(struct starfive_cryp_dev *cryp) ++{ ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ cryp->tx = dma_request_chan(cryp->dev, "tx"); ++ if (IS_ERR(cryp->tx)) ++ return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx), ++ "Error requesting tx dma channel.\n"); ++ ++ cryp->rx = dma_request_chan(cryp->dev, "rx"); ++ if (IS_ERR(cryp->rx)) { ++ dma_release_channel(cryp->tx); ++ return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx), ++ "Error requesting rx dma channel.\n"); ++ } ++ ++ return 0; ++} ++ ++static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp) ++{ ++ dma_release_channel(cryp->tx); ++ dma_release_channel(cryp->rx); ++} ++ ++static int starfive_cryp_probe(struct platform_device *pdev) ++{ ++ struct starfive_cryp_dev *cryp; ++ struct resource *res; ++ int ret; ++ ++ cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL); ++ if (!cryp) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, cryp); ++ cryp->dev = &pdev->dev; ++ ++ cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(cryp->base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base), ++ "Error remapping memory for platform device\n"); ++ ++ cryp->phys_base = res->start; ++ cryp->dma_maxburst = 32; ++ ++ cryp->hclk = devm_clk_get(&pdev->dev, "hclk"); ++ if (IS_ERR(cryp->hclk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk), ++ "Error getting hardware reference clock\n"); ++ ++ cryp->ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(cryp->ahb)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb), ++ "Error getting ahb reference clock\n"); ++ ++ cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL); ++ if (IS_ERR(cryp->rst)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst), ++ "Error getting hardware reset line\n"); ++ ++ clk_prepare_enable(cryp->hclk); ++ clk_prepare_enable(cryp->ahb); ++ reset_control_deassert(cryp->rst); ++ ++ spin_lock(&dev_list.lock); ++ list_add(&cryp->list, &dev_list.dev_list); ++ spin_unlock(&dev_list.lock); ++ ++ ret = starfive_dma_init(cryp); ++ if (ret) { ++ if (ret == -EPROBE_DEFER) ++ goto err_probe_defer; ++ else ++ goto err_dma_init; ++ } ++ ++ /* Initialize crypto engine */ ++ cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1); ++ if (!cryp->engine) { ++ ret = -ENOMEM; ++ goto err_engine; ++ } ++ ++ ret = crypto_engine_start(cryp->engine); ++ if (ret) ++ goto err_engine_start; ++ ++ return 0; ++ ++err_engine_start: ++ crypto_engine_exit(cryp->engine); ++err_engine: ++ starfive_dma_cleanup(cryp); ++err_dma_init: ++ spin_lock(&dev_list.lock); ++ list_del(&cryp->list); ++ spin_unlock(&dev_list.lock); ++ ++ clk_disable_unprepare(cryp->hclk); ++ clk_disable_unprepare(cryp->ahb); ++ reset_control_assert(cryp->rst); ++err_probe_defer: ++ return ret; ++} ++ ++static int starfive_cryp_remove(struct platform_device *pdev) ++{ ++ struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev); ++ ++ crypto_engine_stop(cryp->engine); ++ crypto_engine_exit(cryp->engine); ++ ++ starfive_dma_cleanup(cryp); ++ ++ spin_lock(&dev_list.lock); ++ list_del(&cryp->list); ++ spin_unlock(&dev_list.lock); ++ ++ clk_disable_unprepare(cryp->hclk); ++ clk_disable_unprepare(cryp->ahb); ++ reset_control_assert(cryp->rst); ++ ++ return 0; ++} ++ ++static const struct of_device_id starfive_dt_ids[] __maybe_unused = { ++ { .compatible = "starfive,jh7110-crypto", .data = NULL}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, starfive_dt_ids); ++ ++static struct platform_driver starfive_cryp_driver = { ++ .probe = starfive_cryp_probe, ++ .remove = starfive_cryp_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .of_match_table = starfive_dt_ids, ++ }, ++}; ++ ++module_platform_driver(starfive_cryp_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module"); +--- /dev/null ++++ b/drivers/crypto/starfive/jh7110-cryp.h +@@ -0,0 +1,63 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __STARFIVE_STR_H__ ++#define __STARFIVE_STR_H__ ++ ++#include ++#include ++#include ++ ++#include ++ ++#define STARFIVE_ALG_CR_OFFSET 0x0 ++#define STARFIVE_ALG_FIFO_OFFSET 0x4 ++#define STARFIVE_IE_MASK_OFFSET 0x8 ++#define STARFIVE_IE_FLAG_OFFSET 0xc ++#define STARFIVE_DMA_IN_LEN_OFFSET 0x10 ++#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14 ++ ++#define STARFIVE_MSG_BUFFER_SIZE SZ_16K ++ ++union starfive_alg_cr { ++ u32 v; ++ struct { ++ u32 start :1; ++ u32 aes_dma_en :1; ++ u32 rsvd_0 :1; ++ u32 hash_dma_en :1; ++ u32 alg_done :1; ++ u32 rsvd_1 :3; ++ u32 clear :1; ++ u32 rsvd_2 :23; ++ }; ++}; ++ ++struct starfive_cryp_ctx { ++ struct crypto_engine_ctx enginectx; ++ struct starfive_cryp_dev *cryp; ++}; ++ ++struct starfive_cryp_dev { ++ struct list_head list; ++ struct device *dev; ++ ++ struct clk *hclk; ++ struct clk *ahb; ++ struct reset_control *rst; ++ ++ void __iomem *base; ++ phys_addr_t phys_base; ++ ++ u32 dma_maxburst; ++ struct dma_chan *tx; ++ struct dma_chan *rx; ++ struct dma_slave_config cfg_in; ++ struct dma_slave_config cfg_out; ++ ++ struct crypto_engine *engine; ++ ++ union starfive_alg_cr alg_cr; ++}; ++ ++struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx); ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch b/target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch new file mode 100644 index 0000000000..fc8e86bad5 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch @@ -0,0 +1,29 @@ +From 0d3ee821ed469a787e8007de2d87e98a2370e087 Mon Sep 17 00:00:00 2001 +From: Jia Jie Ho +Date: Fri, 19 May 2023 21:42:33 +0800 +Subject: [PATCH 066/122] crypto: starfive - Fix driver dependencies + +Kconfig updated to depend on DMADEVICES instead of selecting it. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/oe-kbuild-all/202305191929.Eq4OVZ6D-lkp@intel.com/ +Signed-off-by: Jia Jie Ho +Signed-off-by: Herbert Xu +--- + drivers/crypto/starfive/Kconfig | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/crypto/starfive/Kconfig ++++ b/drivers/crypto/starfive/Kconfig +@@ -4,10 +4,9 @@ + + config CRYPTO_DEV_JH7110 + tristate "StarFive JH7110 cryptographic engine driver" +- depends on SOC_STARFIVE || COMPILE_TEST ++ depends on (SOC_STARFIVE || COMPILE_TEST) && DMADEVICES + select CRYPTO_ENGINE + select ARM_AMBA +- select DMADEVICES + select AMBA_PL08X + help + Support for StarFive JH7110 crypto hardware acceleration engine. diff --git a/target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch b/target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch new file mode 100644 index 0000000000..2deca609e1 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch @@ -0,0 +1,23 @@ +From e8d070e2eb856856055566d3515072a8346446f3 Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Wed, 31 May 2023 01:37:41 -0700 +Subject: [PATCH 067/122] riscv: Kconfig: Add select ARM_AMBA to SOC_STARFIVE + +Selects ARM_AMBA platform support for StarFive SoCs required by spi and +crypto dma engine. + +Signed-off-by: shanlong.li +--- + arch/riscv/Kconfig.socs | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/riscv/Kconfig.socs ++++ b/arch/riscv/Kconfig.socs +@@ -4,6 +4,7 @@ config SOC_MICROCHIP_POLARFIRE + bool "Microchip PolarFire SoCs" + select MCHP_CLK_MPFS + select SIFIVE_PLIC ++ select ARM_AMBA + help + This enables support for Microchip PolarFire SoC platforms. + diff --git a/target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch b/target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch new file mode 100644 index 0000000000..41d0a8fe11 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch @@ -0,0 +1,117 @@ +From 3b90e0fb53c31c50e64d2039e30ec25c1d8a8d5c Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Fri, 26 May 2023 22:54:00 +0800 +Subject: [PATCH 068/122] ASoC: dt-bindings: Add TDM controller bindings for + StarFive JH7110 + +Add bindings for TDM driver which supports multi-channel audio playback +and capture on JH7110 platform. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Walker Chen +--- + .../bindings/sound/starfive,jh7110-tdm.yaml | 98 +++++++++++++++++++ + 1 file changed, 98 insertions(+) + create mode 100644 Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml +@@ -0,0 +1,98 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/starfive,jh7110-tdm.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 TDM Controller ++ ++description: | ++ The TDM Controller is a Time Division Multiplexed audio interface ++ integrated in StarFive JH7110 SoC, allowing up to 8 channels of ++ audio over a serial interface. The TDM controller can operate both ++ in master and slave mode. ++ ++maintainers: ++ - Walker Chen ++ ++allOf: ++ - $ref: dai-common.yaml# ++ ++properties: ++ compatible: ++ enum: ++ - starfive,jh7110-tdm ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: TDM AHB Clock ++ - description: TDM APB Clock ++ - description: TDM Internal Clock ++ - description: TDM Clock ++ - description: Inner MCLK ++ - description: TDM External Clock ++ ++ clock-names: ++ items: ++ - const: tdm_ahb ++ - const: tdm_apb ++ - const: tdm_internal ++ - const: tdm ++ - const: mclk_inner ++ - const: tdm_ext ++ ++ resets: ++ items: ++ - description: tdm ahb reset line ++ - description: tdm apb reset line ++ - description: tdm core reset line ++ ++ dmas: ++ items: ++ - description: RX DMA Channel ++ - description: TX DMA Channel ++ ++ dma-names: ++ items: ++ - const: rx ++ - const: tx ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - dmas ++ - dma-names ++ - "#sound-dai-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ tdm@10090000 { ++ compatible = "starfive,jh7110-tdm"; ++ reg = <0x10090000 0x1000>; ++ clocks = <&syscrg 184>, ++ <&syscrg 185>, ++ <&syscrg 186>, ++ <&syscrg 187>, ++ <&syscrg 17>, ++ <&tdm_ext>; ++ clock-names = "tdm_ahb", "tdm_apb", ++ "tdm_internal", "tdm", ++ "mclk_inner", "tdm_ext"; ++ resets = <&syscrg 105>, ++ <&syscrg 107>, ++ <&syscrg 106>; ++ dmas = <&dma 20>, <&dma 21>; ++ dma-names = "rx","tx"; ++ #sound-dai-cells = <0>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch b/target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch new file mode 100644 index 0000000000..57ea99d685 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch @@ -0,0 +1,744 @@ +From 9d90936b0f69d891001a11d3f6c0c3728d8b6d85 Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Fri, 26 May 2023 22:54:01 +0800 +Subject: [PATCH 069/122] ASoC: starfive: Add JH7110 TDM driver + +Add tdm driver support for the StarFive JH7110 SoC. + +Signed-off-by: Walker Chen +--- + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/starfive/Kconfig | 15 + + sound/soc/starfive/Makefile | 2 + + sound/soc/starfive/jh7110_tdm.c | 679 ++++++++++++++++++++++++++++++++ + 5 files changed, 698 insertions(+) + create mode 100644 sound/soc/starfive/Kconfig + create mode 100644 sound/soc/starfive/Makefile + create mode 100644 sound/soc/starfive/jh7110_tdm.c + +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -91,6 +91,7 @@ source "sound/soc/sh/Kconfig" + source "sound/soc/sof/Kconfig" + source "sound/soc/spear/Kconfig" + source "sound/soc/sprd/Kconfig" ++source "sound/soc/starfive/Kconfig" + source "sound/soc/sti/Kconfig" + source "sound/soc/stm/Kconfig" + source "sound/soc/sunxi/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -59,6 +59,7 @@ obj-$(CONFIG_SND_SOC) += sh/ + obj-$(CONFIG_SND_SOC) += sof/ + obj-$(CONFIG_SND_SOC) += spear/ + obj-$(CONFIG_SND_SOC) += sprd/ ++obj-$(CONFIG_SND_SOC) += starfive/ + obj-$(CONFIG_SND_SOC) += sti/ + obj-$(CONFIG_SND_SOC) += stm/ + obj-$(CONFIG_SND_SOC) += sunxi/ +--- /dev/null ++++ b/sound/soc/starfive/Kconfig +@@ -0,0 +1,15 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config SND_SOC_STARFIVE ++ tristate "Audio support for StarFive SoC" ++ depends on COMPILE_TEST || ARCH_STARFIVE ++ help ++ Say Y or M if you want to add support for codecs attached to ++ the Starfive SoCs' Audio interfaces. You will also need to ++ select the audio interfaces to support below. ++ ++config SND_SOC_JH7110_TDM ++ tristate "JH7110 TDM device driver" ++ depends on HAVE_CLK && SND_SOC_STARFIVE ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ help ++ Say Y or M if you want to add support for StarFive TDM driver. +--- /dev/null ++++ b/sound/soc/starfive/Makefile +@@ -0,0 +1,2 @@ ++# StarFive Platform Support ++obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o +--- /dev/null ++++ b/sound/soc/starfive/jh7110_tdm.c +@@ -0,0 +1,679 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * jh7110_tdm.c -- StarFive JH7110 TDM driver ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * Author: Walker Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TDM_PCMGBCR 0x00 ++ #define PCMGBCR_MASK 0x1e ++ #define PCMGBCR_ENABLE BIT(0) ++ #define PCMGBCR_TRITXEN BIT(4) ++ #define CLKPOL_BIT 5 ++ #define TRITXEN_BIT 4 ++ #define ELM_BIT 3 ++ #define SYNCM_BIT 2 ++ #define MS_BIT 1 ++#define TDM_PCMTXCR 0x04 ++ #define PCMTXCR_TXEN BIT(0) ++ #define IFL_BIT 11 ++ #define WL_BIT 8 ++ #define SSCALE_BIT 4 ++ #define SL_BIT 2 ++ #define LRJ_BIT 1 ++#define TDM_PCMRXCR 0x08 ++ #define PCMRXCR_RXEN BIT(0) ++ #define PCMRXCR_RXSL_MASK 0xc ++ #define PCMRXCR_RXSL_16BIT 0x4 ++ #define PCMRXCR_RXSL_32BIT 0x8 ++ #define PCMRXCR_SCALE_MASK 0xf0 ++ #define PCMRXCR_SCALE_1CH 0x10 ++#define TDM_PCMDIV 0x0c ++ ++#define JH7110_TDM_FIFO 0x170c0000 ++#define JH7110_TDM_FIFO_DEPTH 32 ++ ++enum TDM_MASTER_SLAVE_MODE { ++ TDM_AS_MASTER = 0, ++ TDM_AS_SLAVE, ++}; ++ ++enum TDM_CLKPOL { ++ /* tx raising and rx falling */ ++ TDM_TX_RASING_RX_FALLING = 0, ++ /* tx falling and rx raising */ ++ TDM_TX_FALLING_RX_RASING, ++}; ++ ++enum TDM_ELM { ++ /* only work while SYNCM=0 */ ++ TDM_ELM_LATE = 0, ++ TDM_ELM_EARLY, ++}; ++ ++enum TDM_SYNCM { ++ /* short frame sync */ ++ TDM_SYNCM_SHORT = 0, ++ /* long frame sync */ ++ TDM_SYNCM_LONG, ++}; ++ ++enum TDM_IFL { ++ /* FIFO to send or received : half-1/2, Quarter-1/4 */ ++ TDM_FIFO_HALF = 0, ++ TDM_FIFO_QUARTER, ++}; ++ ++enum TDM_WL { ++ /* send or received word length */ ++ TDM_8BIT_WORD_LEN = 0, ++ TDM_16BIT_WORD_LEN, ++ TDM_20BIT_WORD_LEN, ++ TDM_24BIT_WORD_LEN, ++ TDM_32BIT_WORD_LEN, ++}; ++ ++enum TDM_SL { ++ /* send or received slot length */ ++ TDM_8BIT_SLOT_LEN = 0, ++ TDM_16BIT_SLOT_LEN, ++ TDM_32BIT_SLOT_LEN, ++}; ++ ++enum TDM_LRJ { ++ /* left-justify or right-justify */ ++ TDM_RIGHT_JUSTIFY = 0, ++ TDM_LEFT_JUSTIFT, ++}; ++ ++struct tdm_chan_cfg { ++ enum TDM_IFL ifl; ++ enum TDM_WL wl; ++ unsigned char sscale; ++ enum TDM_SL sl; ++ enum TDM_LRJ lrj; ++ unsigned char enable; ++}; ++ ++struct jh7110_tdm_dev { ++ void __iomem *tdm_base; ++ struct device *dev; ++ struct clk_bulk_data clks[6]; ++ struct reset_control *resets; ++ ++ enum TDM_CLKPOL clkpolity; ++ enum TDM_ELM elm; ++ enum TDM_SYNCM syncm; ++ enum TDM_MASTER_SLAVE_MODE ms_mode; ++ ++ struct tdm_chan_cfg tx; ++ struct tdm_chan_cfg rx; ++ ++ u16 syncdiv; ++ u32 samplerate; ++ u32 pcmclk; ++ ++ /* data related to DMA transfers b/w tdm and DMAC */ ++ struct snd_dmaengine_dai_dma_data play_dma_data; ++ struct snd_dmaengine_dai_dma_data capture_dma_data; ++ u32 saved_pcmgbcr; ++ u32 saved_pcmtxcr; ++ u32 saved_pcmrxcr; ++ u32 saved_pcmdiv; ++}; ++ ++static inline u32 jh7110_tdm_readl(struct jh7110_tdm_dev *tdm, u16 reg) ++{ ++ return readl_relaxed(tdm->tdm_base + reg); ++} ++ ++static inline void jh7110_tdm_writel(struct jh7110_tdm_dev *tdm, u16 reg, u32 val) ++{ ++ writel_relaxed(val, tdm->tdm_base + reg); ++} ++ ++static void jh7110_tdm_save_context(struct jh7110_tdm_dev *tdm, ++ struct snd_pcm_substream *substream) ++{ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ tdm->saved_pcmtxcr = jh7110_tdm_readl(tdm, TDM_PCMTXCR); ++ else ++ tdm->saved_pcmrxcr = jh7110_tdm_readl(tdm, TDM_PCMRXCR); ++} ++ ++static void jh7110_tdm_start(struct jh7110_tdm_dev *tdm, ++ struct snd_pcm_substream *substream) ++{ ++ u32 data; ++ ++ data = jh7110_tdm_readl(tdm, TDM_PCMGBCR); ++ jh7110_tdm_writel(tdm, TDM_PCMGBCR, data | PCMGBCR_ENABLE); ++ ++ /* restore context */ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ jh7110_tdm_writel(tdm, TDM_PCMTXCR, tdm->saved_pcmtxcr | PCMTXCR_TXEN); ++ else ++ jh7110_tdm_writel(tdm, TDM_PCMRXCR, tdm->saved_pcmrxcr | PCMRXCR_RXEN); ++} ++ ++static void jh7110_tdm_stop(struct jh7110_tdm_dev *tdm, ++ struct snd_pcm_substream *substream) ++{ ++ unsigned int val; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ val = jh7110_tdm_readl(tdm, TDM_PCMTXCR); ++ val &= ~PCMTXCR_TXEN; ++ jh7110_tdm_writel(tdm, TDM_PCMTXCR, val); ++ } else { ++ val = jh7110_tdm_readl(tdm, TDM_PCMRXCR); ++ val &= ~PCMRXCR_RXEN; ++ jh7110_tdm_writel(tdm, TDM_PCMRXCR, val); ++ } ++} ++ ++static int jh7110_tdm_syncdiv(struct jh7110_tdm_dev *tdm) ++{ ++ u32 sl, sscale, syncdiv; ++ ++ if (tdm->rx.sl >= tdm->tx.sl) ++ sl = tdm->rx.sl; ++ else ++ sl = tdm->tx.sl; ++ ++ if (tdm->rx.sscale >= tdm->tx.sscale) ++ sscale = tdm->rx.sscale; ++ else ++ sscale = tdm->tx.sscale; ++ ++ syncdiv = tdm->pcmclk / tdm->samplerate - 1; ++ ++ if ((syncdiv + 1) < (sl * sscale)) { ++ dev_err(tdm->dev, "Failed to set syncdiv!\n"); ++ return -EINVAL; ++ } ++ ++ if (tdm->syncm == TDM_SYNCM_LONG && ++ (tdm->rx.sscale <= 1 || tdm->tx.sscale <= 1) && ++ ((syncdiv + 1) <= sl)) { ++ dev_err(tdm->dev, "Wrong syncdiv! It must be (syncdiv+1) > max[tx.sl, rx.sl]\n"); ++ return -EINVAL; ++ } ++ ++ jh7110_tdm_writel(tdm, TDM_PCMDIV, syncdiv); ++ return 0; ++} ++ ++static int jh7110_tdm_config(struct jh7110_tdm_dev *tdm, ++ struct snd_pcm_substream *substream) ++{ ++ u32 datarx, datatx; ++ int ret; ++ ++ ret = jh7110_tdm_syncdiv(tdm); ++ if (ret) ++ return ret; ++ ++ datarx = (tdm->rx.ifl << IFL_BIT) | ++ (tdm->rx.wl << WL_BIT) | ++ (tdm->rx.sscale << SSCALE_BIT) | ++ (tdm->rx.sl << SL_BIT) | ++ (tdm->rx.lrj << LRJ_BIT); ++ ++ datatx = (tdm->tx.ifl << IFL_BIT) | ++ (tdm->tx.wl << WL_BIT) | ++ (tdm->tx.sscale << SSCALE_BIT) | ++ (tdm->tx.sl << SL_BIT) | ++ (tdm->tx.lrj << LRJ_BIT); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ jh7110_tdm_writel(tdm, TDM_PCMTXCR, datatx); ++ else ++ jh7110_tdm_writel(tdm, TDM_PCMRXCR, datarx); ++ ++ return 0; ++} ++ ++static void jh7110_tdm_clk_disable(struct jh7110_tdm_dev *tdm) ++{ ++ clk_bulk_disable_unprepare(ARRAY_SIZE(tdm->clks), tdm->clks); ++} ++ ++static int jh7110_tdm_clk_enable(struct jh7110_tdm_dev *tdm) ++{ ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(ARRAY_SIZE(tdm->clks), tdm->clks); ++ if (ret) { ++ dev_err(tdm->dev, "Failed to enable tdm clocks\n"); ++ return ret; ++ } ++ ++ ret = reset_control_deassert(tdm->resets); ++ if (ret) { ++ dev_err(tdm->dev, "Failed to deassert tdm resets\n"); ++ goto dis_tdm_clk; ++ } ++ ++ /* select tdm_ext clock as the clock source for tdm */ ++ ret = clk_set_parent(tdm->clks[5].clk, tdm->clks[4].clk); ++ if (ret) { ++ dev_err(tdm->dev, "Can't set extern clock source for clk_tdm\n"); ++ goto dis_tdm_clk; ++ } ++ ++ return 0; ++ ++dis_tdm_clk: ++ clk_bulk_disable_unprepare(ARRAY_SIZE(tdm->clks), tdm->clks); ++ ++ return ret; ++} ++ ++static int jh7110_tdm_runtime_suspend(struct device *dev) ++{ ++ struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); ++ ++ jh7110_tdm_clk_disable(tdm); ++ return 0; ++} ++ ++static int jh7110_tdm_runtime_resume(struct device *dev) ++{ ++ struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); ++ ++ return jh7110_tdm_clk_enable(tdm); ++} ++ ++static int jh7110_tdm_system_suspend(struct device *dev) ++{ ++ struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); ++ ++ /* save context */ ++ tdm->saved_pcmgbcr = jh7110_tdm_readl(tdm, TDM_PCMGBCR); ++ tdm->saved_pcmdiv = jh7110_tdm_readl(tdm, TDM_PCMDIV); ++ ++ return pm_runtime_force_suspend(dev); ++} ++ ++static int jh7110_tdm_system_resume(struct device *dev) ++{ ++ struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev); ++ ++ /* restore context */ ++ jh7110_tdm_writel(tdm, TDM_PCMGBCR, tdm->saved_pcmgbcr); ++ jh7110_tdm_writel(tdm, TDM_PCMDIV, tdm->saved_pcmdiv); ++ ++ return pm_runtime_force_resume(dev); ++} ++ ++static const struct snd_soc_component_driver jh7110_tdm_component = { ++ .name = "jh7110-tdm", ++}; ++ ++static int jh7110_tdm_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *cpu_dai) ++{ ++ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); ++ struct snd_soc_dai_link *dai_link = rtd->dai_link; ++ ++ dai_link->stop_dma_first = 1; ++ ++ return 0; ++} ++ ++static int jh7110_tdm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai); ++ int chan_wl, chan_sl, chan_nr; ++ unsigned int data_width; ++ unsigned int dma_bus_width; ++ struct snd_dmaengine_dai_dma_data *dma_data = NULL; ++ int ret; ++ ++ data_width = params_width(params); ++ ++ tdm->samplerate = params_rate(params); ++ tdm->pcmclk = params_channels(params) * tdm->samplerate * data_width; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ chan_wl = TDM_16BIT_WORD_LEN; ++ chan_sl = TDM_16BIT_SLOT_LEN; ++ dma_bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ break; ++ ++ case SNDRV_PCM_FORMAT_S32_LE: ++ chan_wl = TDM_32BIT_WORD_LEN; ++ chan_sl = TDM_32BIT_SLOT_LEN; ++ dma_bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ break; ++ ++ default: ++ dev_err(tdm->dev, "tdm: unsupported PCM fmt"); ++ return -EINVAL; ++ } ++ ++ chan_nr = params_channels(params); ++ switch (chan_nr) { ++ case 1: ++ case 2: ++ case 4: ++ case 6: ++ case 8: ++ break; ++ default: ++ dev_err(tdm->dev, "channel not supported\n"); ++ return -EINVAL; ++ } ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ tdm->tx.wl = chan_wl; ++ tdm->tx.sl = chan_sl; ++ tdm->tx.sscale = chan_nr; ++ tdm->play_dma_data.addr_width = dma_bus_width; ++ dma_data = &tdm->play_dma_data; ++ } else { ++ tdm->rx.wl = chan_wl; ++ tdm->rx.sl = chan_sl; ++ tdm->rx.sscale = chan_nr; ++ tdm->capture_dma_data.addr_width = dma_bus_width; ++ dma_data = &tdm->capture_dma_data; ++ } ++ ++ snd_soc_dai_set_dma_data(dai, substream, dma_data); ++ ++ ret = jh7110_tdm_config(tdm, substream); ++ if (ret) ++ return ret; ++ ++ jh7110_tdm_save_context(tdm, substream); ++ return 0; ++} ++ ++static int jh7110_tdm_trigger(struct snd_pcm_substream *substream, ++ int cmd, struct snd_soc_dai *dai) ++{ ++ struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai); ++ int ret = 0; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ jh7110_tdm_start(tdm, substream); ++ break; ++ ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ jh7110_tdm_stop(tdm, substream); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int jh7110_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, ++ unsigned int fmt) ++{ ++ struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(cpu_dai); ++ unsigned int gbcr; ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { ++ case SND_SOC_DAIFMT_BP_FP: ++ /* cpu is master */ ++ tdm->ms_mode = TDM_AS_MASTER; ++ break; ++ case SND_SOC_DAIFMT_BC_FC: ++ /* codec is master */ ++ tdm->ms_mode = TDM_AS_SLAVE; ++ break; ++ case SND_SOC_DAIFMT_BC_FP: ++ case SND_SOC_DAIFMT_BP_FC: ++ return -EINVAL; ++ default: ++ dev_dbg(tdm->dev, "dwc : Invalid clock provider format\n"); ++ return -EINVAL; ++ } ++ ++ gbcr = (tdm->clkpolity << CLKPOL_BIT) | ++ (tdm->elm << ELM_BIT) | ++ (tdm->syncm << SYNCM_BIT) | ++ (tdm->ms_mode << MS_BIT); ++ jh7110_tdm_writel(tdm, TDM_PCMGBCR, gbcr); ++ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops jh7110_tdm_dai_ops = { ++ .startup = jh7110_tdm_startup, ++ .hw_params = jh7110_tdm_hw_params, ++ .trigger = jh7110_tdm_trigger, ++ .set_fmt = jh7110_tdm_set_dai_fmt, ++}; ++ ++static int jh7110_tdm_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai); ++ ++ snd_soc_dai_init_dma_data(dai, &tdm->play_dma_data, &tdm->capture_dma_data); ++ snd_soc_dai_set_drvdata(dai, tdm); ++ return 0; ++} ++ ++#define JH7110_TDM_RATES SNDRV_PCM_RATE_8000_48000 ++ ++#define JH7110_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++static struct snd_soc_dai_driver jh7110_tdm_dai = { ++ .name = "sf_tdm", ++ .id = 0, ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = JH7110_TDM_RATES, ++ .formats = JH7110_TDM_FORMATS, ++ }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = JH7110_TDM_RATES, ++ .formats = JH7110_TDM_FORMATS, ++ }, ++ .ops = &jh7110_tdm_dai_ops, ++ .probe = jh7110_tdm_dai_probe, ++ .symmetric_rate = 1, ++}; ++ ++static const struct snd_pcm_hardware jh7110_pcm_hardware = { ++ .info = (SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | ++ SNDRV_PCM_INFO_RESUME | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER), ++ .buffer_bytes_max = 192512, ++ .period_bytes_min = 4096, ++ .period_bytes_max = 32768, ++ .periods_min = 1, ++ .periods_max = 48, ++ .fifo_size = 16, ++}; ++ ++static const struct snd_dmaengine_pcm_config jh7110_dmaengine_pcm_config = { ++ .pcm_hardware = &jh7110_pcm_hardware, ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .prealloc_buffer_size = 192512, ++}; ++ ++static void jh7110_tdm_init_params(struct jh7110_tdm_dev *tdm) ++{ ++ tdm->clkpolity = TDM_TX_RASING_RX_FALLING; ++ tdm->elm = TDM_ELM_LATE; ++ tdm->syncm = TDM_SYNCM_SHORT; ++ ++ tdm->rx.ifl = TDM_FIFO_HALF; ++ tdm->tx.ifl = TDM_FIFO_HALF; ++ tdm->rx.wl = TDM_16BIT_WORD_LEN; ++ tdm->tx.wl = TDM_16BIT_WORD_LEN; ++ tdm->rx.sscale = 2; ++ tdm->tx.sscale = 2; ++ tdm->rx.lrj = TDM_LEFT_JUSTIFT; ++ tdm->tx.lrj = TDM_LEFT_JUSTIFT; ++ ++ tdm->play_dma_data.addr = JH7110_TDM_FIFO; ++ tdm->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ tdm->play_dma_data.fifo_size = JH7110_TDM_FIFO_DEPTH / 2; ++ tdm->play_dma_data.maxburst = 16; ++ ++ tdm->capture_dma_data.addr = JH7110_TDM_FIFO; ++ tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ tdm->capture_dma_data.fifo_size = JH7110_TDM_FIFO_DEPTH / 2; ++ tdm->capture_dma_data.maxburst = 8; ++} ++ ++static int jh7110_tdm_clk_reset_get(struct platform_device *pdev, ++ struct jh7110_tdm_dev *tdm) ++{ ++ int ret; ++ ++ tdm->clks[0].id = "mclk_inner"; ++ tdm->clks[1].id = "tdm_ahb"; ++ tdm->clks[2].id = "tdm_apb"; ++ tdm->clks[3].id = "tdm_internal"; ++ tdm->clks[4].id = "tdm_ext"; ++ tdm->clks[5].id = "tdm"; ++ ++ ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(tdm->clks), tdm->clks); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to get tdm clocks\n"); ++ return ret; ++ } ++ ++ tdm->resets = devm_reset_control_array_get_exclusive(&pdev->dev); ++ if (IS_ERR_OR_NULL(tdm->resets)) { ++ ret = PTR_ERR(tdm->resets); ++ dev_err(&pdev->dev, "Failed to get tdm resets"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int jh7110_tdm_probe(struct platform_device *pdev) ++{ ++ struct jh7110_tdm_dev *tdm; ++ int ret; ++ ++ tdm = devm_kzalloc(&pdev->dev, sizeof(*tdm), GFP_KERNEL); ++ if (!tdm) ++ return -ENOMEM; ++ ++ tdm->tdm_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(tdm->tdm_base)) ++ return PTR_ERR(tdm->tdm_base); ++ ++ tdm->dev = &pdev->dev; ++ ++ ret = jh7110_tdm_clk_reset_get(pdev, tdm); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to enable audio-tdm clock\n"); ++ return ret; ++ } ++ ++ jh7110_tdm_init_params(tdm); ++ ++ dev_set_drvdata(&pdev->dev, tdm); ++ ret = devm_snd_soc_register_component(&pdev->dev, &jh7110_tdm_component, ++ &jh7110_tdm_dai, 1); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to register dai\n"); ++ return ret; ++ } ++ ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, ++ &jh7110_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ if (ret) { ++ dev_err(&pdev->dev, "Could not register pcm: %d\n", ret); ++ return ret; ++ } ++ ++ pm_runtime_enable(&pdev->dev); ++ if (!pm_runtime_enabled(&pdev->dev)) { ++ ret = jh7110_tdm_runtime_resume(&pdev->dev); ++ if (ret) ++ goto err_pm_disable; ++ } ++ ++ return 0; ++ ++err_pm_disable: ++ pm_runtime_disable(&pdev->dev); ++ ++ return ret; ++} ++ ++static int jh7110_tdm_dev_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ return 0; ++} ++ ++static const struct of_device_id jh7110_tdm_of_match[] = { ++ { .compatible = "starfive,jh7110-tdm", }, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, jh7110_tdm_of_match); ++ ++static const struct dev_pm_ops jh7110_tdm_pm_ops = { ++ RUNTIME_PM_OPS(jh7110_tdm_runtime_suspend, ++ jh7110_tdm_runtime_resume, NULL) ++ SYSTEM_SLEEP_PM_OPS(jh7110_tdm_system_suspend, ++ jh7110_tdm_system_resume) ++}; ++ ++static struct platform_driver jh7110_tdm_driver = { ++ .driver = { ++ .name = "jh7110-tdm", ++ .of_match_table = jh7110_tdm_of_match, ++ .pm = pm_ptr(&jh7110_tdm_pm_ops), ++ }, ++ .probe = jh7110_tdm_probe, ++ .remove = jh7110_tdm_dev_remove, ++}; ++module_platform_driver(jh7110_tdm_driver); ++ ++MODULE_DESCRIPTION("StarFive JH7110 TDM ASoC Driver"); ++MODULE_AUTHOR("Walker Chen "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch b/target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch new file mode 100644 index 0000000000..d8ba979f55 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch @@ -0,0 +1,32 @@ +From 598083825494088f927fa42c5a7bb2872029a7bc Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Thu, 18 May 2023 23:01:59 -0700 +Subject: [PATCH 070/122] dt-bindings: power: Add power-domain header for + JH7110 + +Add power-domain header for JH7110 SoC, it can use to operate dphy +power. + +Signed-off-by: Changhuang Liang +--- + include/dt-bindings/power/starfive,jh7110-pmu.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/include/dt-bindings/power/starfive,jh7110-pmu.h ++++ b/include/dt-bindings/power/starfive,jh7110-pmu.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + /* +- * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd. + * Author: Walker Chen + */ + #ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__ +@@ -14,4 +14,7 @@ + #define JH7110_PD_ISP 5 + #define JH7110_PD_VENC 6 + ++#define JH7110_PD_DPHY_TX 0 ++#define JH7110_PD_DPHY_RX 1 ++ + #endif diff --git a/target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch b/target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch new file mode 100644 index 0000000000..fa0201b6ca --- /dev/null +++ b/target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch @@ -0,0 +1,28 @@ +From d83b51f60997365b80637f71924ab3dec91d5b77 Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Thu, 18 May 2023 23:02:00 -0700 +Subject: [PATCH 071/122] soc: starfive: Replace SOC_STARFIVE with + ARCH_STARFIVE + +Using ARCH_FOO symbol is preferred than SOC_FOO. + +Reviewed-by: Conor Dooley +Reviewed-by: Walker Chen +Signed-off-by: Changhuang Liang +--- + drivers/soc/starfive/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/soc/starfive/Kconfig ++++ b/drivers/soc/starfive/Kconfig +@@ -3,8 +3,8 @@ + config JH71XX_PMU + bool "Support PMU for StarFive JH71XX Soc" + depends on PM +- depends on SOC_STARFIVE || COMPILE_TEST +- default SOC_STARFIVE ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ default ARCH_STARFIVE + select PM_GENERIC_DOMAINS + help + Say 'y' here to enable support power domain support. diff --git a/target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch b/target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch new file mode 100644 index 0000000000..5f2cb2810f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch @@ -0,0 +1,175 @@ +From 52e2ade50f3ec212468e284b1236aaa521ba5913 Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Thu, 18 May 2023 23:02:01 -0700 +Subject: [PATCH 072/122] soc: starfive: Extract JH7110 pmu private operations + +Move JH7110 private operation into private data of compatible. Convenient +to add AON PMU which would not have interrupts property. + +Signed-off-by: Changhuang Liang +Reviewed-by: Walker Chen +--- + drivers/soc/starfive/jh71xx_pmu.c | 89 +++++++++++++++++++++---------- + 1 file changed, 62 insertions(+), 27 deletions(-) + +--- a/drivers/soc/starfive/jh71xx_pmu.c ++++ b/drivers/soc/starfive/jh71xx_pmu.c +@@ -51,9 +51,17 @@ struct jh71xx_domain_info { + u8 bit; + }; + ++struct jh71xx_pmu; ++struct jh71xx_pmu_dev; ++ + struct jh71xx_pmu_match_data { + const struct jh71xx_domain_info *domain_info; + int num_domains; ++ unsigned int pmu_status; ++ int (*pmu_parse_irq)(struct platform_device *pdev, ++ struct jh71xx_pmu *pmu); ++ int (*pmu_set_state)(struct jh71xx_pmu_dev *pmd, ++ u32 mask, bool on); + }; + + struct jh71xx_pmu { +@@ -79,12 +87,12 @@ static int jh71xx_pmu_get_state(struct j + if (!mask) + return -EINVAL; + +- *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask; ++ *is_on = readl(pmu->base + pmu->match_data->pmu_status) & mask; + + return 0; + } + +-static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) ++static int jh7110_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) + { + struct jh71xx_pmu *pmu = pmd->pmu; + unsigned long flags; +@@ -92,22 +100,8 @@ static int jh71xx_pmu_set_state(struct j + u32 mode; + u32 encourage_lo; + u32 encourage_hi; +- bool is_on; + int ret; + +- ret = jh71xx_pmu_get_state(pmd, mask, &is_on); +- if (ret) { +- dev_dbg(pmu->dev, "unable to get current state for %s\n", +- pmd->genpd.name); +- return ret; +- } +- +- if (is_on == on) { +- dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n", +- pmd->genpd.name, on ? "en" : "dis"); +- return 0; +- } +- + spin_lock_irqsave(&pmu->lock, flags); + + /* +@@ -166,6 +160,29 @@ static int jh71xx_pmu_set_state(struct j + return 0; + } + ++static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) ++{ ++ struct jh71xx_pmu *pmu = pmd->pmu; ++ const struct jh71xx_pmu_match_data *match_data = pmu->match_data; ++ bool is_on; ++ int ret; ++ ++ ret = jh71xx_pmu_get_state(pmd, mask, &is_on); ++ if (ret) { ++ dev_dbg(pmu->dev, "unable to get current state for %s\n", ++ pmd->genpd.name); ++ return ret; ++ } ++ ++ if (is_on == on) { ++ dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n", ++ pmd->genpd.name, on ? "en" : "dis"); ++ return 0; ++ } ++ ++ return match_data->pmu_set_state(pmd, mask, on); ++} ++ + static int jh71xx_pmu_on(struct generic_pm_domain *genpd) + { + struct jh71xx_pmu_dev *pmd = container_of(genpd, +@@ -226,6 +243,25 @@ static irqreturn_t jh71xx_pmu_interrupt( + return IRQ_HANDLED; + } + ++static int jh7110_pmu_parse_irq(struct platform_device *pdev, struct jh71xx_pmu *pmu) ++{ ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ pmu->irq = platform_get_irq(pdev, 0); ++ if (pmu->irq < 0) ++ return pmu->irq; ++ ++ ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt, ++ 0, pdev->name, pmu); ++ if (ret) ++ dev_err(dev, "failed to request irq\n"); ++ ++ jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true); ++ ++ return 0; ++} ++ + static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index) + { + struct jh71xx_pmu_dev *pmd; +@@ -275,19 +311,18 @@ static int jh71xx_pmu_probe(struct platf + if (IS_ERR(pmu->base)) + return PTR_ERR(pmu->base); + +- pmu->irq = platform_get_irq(pdev, 0); +- if (pmu->irq < 0) +- return pmu->irq; +- +- ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt, +- 0, pdev->name, pmu); +- if (ret) +- dev_err(dev, "failed to request irq\n"); ++ spin_lock_init(&pmu->lock); + + match_data = of_device_get_match_data(dev); + if (!match_data) + return -EINVAL; + ++ ret = match_data->pmu_parse_irq(pdev, pmu); ++ if (ret) { ++ dev_err(dev, "failed to parse irq\n"); ++ return ret; ++ } ++ + pmu->genpd = devm_kcalloc(dev, match_data->num_domains, + sizeof(struct generic_pm_domain *), + GFP_KERNEL); +@@ -307,9 +342,6 @@ static int jh71xx_pmu_probe(struct platf + } + } + +- spin_lock_init(&pmu->lock); +- jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true); +- + ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data); + if (ret) { + dev_err(dev, "failed to register genpd driver: %d\n", ret); +@@ -357,6 +389,9 @@ static const struct jh71xx_domain_info j + static const struct jh71xx_pmu_match_data jh7110_pmu = { + .num_domains = ARRAY_SIZE(jh7110_power_domains), + .domain_info = jh7110_power_domains, ++ .pmu_status = JH71XX_PMU_CURR_POWER_MODE, ++ .pmu_parse_irq = jh7110_pmu_parse_irq, ++ .pmu_set_state = jh7110_pmu_set_state, + }; + + static const struct of_device_id jh71xx_pmu_of_match[] = { diff --git a/target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch b/target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch new file mode 100644 index 0000000000..ec7a476b8f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch @@ -0,0 +1,119 @@ +From 3124d653318c50e20eadbb3998eafa5928ac9b63 Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Thu, 18 May 2023 23:02:02 -0700 +Subject: [PATCH 073/122] soc: starfive: Add JH7110 AON PMU support + +Add AON PMU for StarFive JH7110 SoC. It can be used to turn on/off the +dphy rx/tx power switch. + +Reviewed-by: Walker Chen +Signed-off-by: Changhuang Liang +--- + drivers/soc/starfive/jh71xx_pmu.c | 57 ++++++++++++++++++++++++++++--- + 1 file changed, 52 insertions(+), 5 deletions(-) + +--- a/drivers/soc/starfive/jh71xx_pmu.c ++++ b/drivers/soc/starfive/jh71xx_pmu.c +@@ -2,7 +2,7 @@ + /* + * StarFive JH71XX PMU (Power Management Unit) Controller Driver + * +- * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd. + */ + + #include +@@ -24,6 +24,9 @@ + #define JH71XX_PMU_EVENT_STATUS 0x88 + #define JH71XX_PMU_INT_STATUS 0x8C + ++/* aon pmu register offset */ ++#define JH71XX_AON_PMU_SWITCH 0x00 ++ + /* sw encourage cfg */ + #define JH71XX_PMU_SW_ENCOURAGE_EN_LO 0x05 + #define JH71XX_PMU_SW_ENCOURAGE_EN_HI 0x50 +@@ -160,6 +163,26 @@ static int jh7110_pmu_set_state(struct j + return 0; + } + ++static int jh7110_aon_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) ++{ ++ struct jh71xx_pmu *pmu = pmd->pmu; ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&pmu->lock, flags); ++ val = readl(pmu->base + JH71XX_AON_PMU_SWITCH); ++ ++ if (on) ++ val |= mask; ++ else ++ val &= ~mask; ++ ++ writel(val, pmu->base + JH71XX_AON_PMU_SWITCH); ++ spin_unlock_irqrestore(&pmu->lock, flags); ++ ++ return 0; ++} ++ + static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) + { + struct jh71xx_pmu *pmu = pmd->pmu; +@@ -317,10 +340,12 @@ static int jh71xx_pmu_probe(struct platf + if (!match_data) + return -EINVAL; + +- ret = match_data->pmu_parse_irq(pdev, pmu); +- if (ret) { +- dev_err(dev, "failed to parse irq\n"); +- return ret; ++ if (match_data->pmu_parse_irq) { ++ ret = match_data->pmu_parse_irq(pdev, pmu); ++ if (ret) { ++ dev_err(dev, "failed to parse irq\n"); ++ return ret; ++ } + } + + pmu->genpd = devm_kcalloc(dev, match_data->num_domains, +@@ -394,11 +419,32 @@ static const struct jh71xx_pmu_match_dat + .pmu_set_state = jh7110_pmu_set_state, + }; + ++static const struct jh71xx_domain_info jh7110_aon_power_domains[] = { ++ [JH7110_PD_DPHY_TX] = { ++ .name = "DPHY-TX", ++ .bit = 30, ++ }, ++ [JH7110_PD_DPHY_RX] = { ++ .name = "DPHY-RX", ++ .bit = 31, ++ }, ++}; ++ ++static const struct jh71xx_pmu_match_data jh7110_aon_pmu = { ++ .num_domains = ARRAY_SIZE(jh7110_aon_power_domains), ++ .domain_info = jh7110_aon_power_domains, ++ .pmu_status = JH71XX_AON_PMU_SWITCH, ++ .pmu_set_state = jh7110_aon_pmu_set_state, ++}; ++ + static const struct of_device_id jh71xx_pmu_of_match[] = { + { + .compatible = "starfive,jh7110-pmu", + .data = (void *)&jh7110_pmu, + }, { ++ .compatible = "starfive,jh7110-aon-syscon", ++ .data = (void *)&jh7110_aon_pmu, ++ }, { + /* sentinel */ + } + }; +@@ -414,5 +460,6 @@ static struct platform_driver jh71xx_pmu + builtin_platform_driver(jh71xx_pmu_driver); + + MODULE_AUTHOR("Walker Chen "); ++MODULE_AUTHOR("Changhuang Liang "); + MODULE_DESCRIPTION("StarFive JH71XX PMU Driver"); + MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch b/target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch new file mode 100644 index 0000000000..6368e53d84 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch @@ -0,0 +1,88 @@ +From 7492ebbdd926da258f9abea5c41a9f8c4ec48631 Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Mon, 29 May 2023 05:15:01 -0700 +Subject: [PATCH 074/122] dt-bindings: phy: Add starfive,jh7110-dphy-rx + +StarFive SoCs like the jh7110 use a MIPI D-PHY RX controller based on +a M31 IP. Add a binding for it. + +Signed-off-by: Changhuang Liang +--- + .../bindings/phy/starfive,jh7110-dphy-rx.yaml | 71 +++++++++++++++++++ + 1 file changed, 71 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-rx.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-rx.yaml +@@ -0,0 +1,71 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/starfive,jh7110-dphy-rx.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive SoC MIPI D-PHY Rx Controller ++ ++maintainers: ++ - Jack Zhu ++ - Changhuang Liang ++ ++description: ++ The StarFive SoC uses the MIPI CSI D-PHY based on M31 IP to transfer ++ CSI camera data. ++ ++properties: ++ compatible: ++ const: starfive,jh7110-dphy-rx ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: config clock ++ - description: reference clock ++ - description: escape mode transmit clock ++ ++ clock-names: ++ items: ++ - const: cfg ++ - const: ref ++ - const: tx ++ ++ resets: ++ items: ++ - description: DPHY_HW reset ++ - description: DPHY_B09_ALWAYS_ON reset ++ ++ power-domains: ++ maxItems: 1 ++ ++ "#phy-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - power-domains ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ phy@19820000 { ++ compatible = "starfive,jh7110-dphy-rx"; ++ reg = <0x19820000 0x10000>; ++ clocks = <&ispcrg 3>, ++ <&ispcrg 4>, ++ <&ispcrg 5>; ++ clock-names = "cfg", "ref", "tx"; ++ resets = <&ispcrg 2>, ++ <&ispcrg 3>; ++ power-domains = <&dphy_pwrc 1>; ++ #phy-cells = <0>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch b/target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch new file mode 100644 index 0000000000..d5db36a1e6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch @@ -0,0 +1,365 @@ +From f6fbb431f9e3ac5c9144edf05340db9a96dffa59 Mon Sep 17 00:00:00 2001 +From: Changhuang Liang +Date: Mon, 29 May 2023 05:15:02 -0700 +Subject: [PATCH 075/122] phy: starfive: Add mipi dphy rx support + +Add mipi dphy rx support for the StarFive JH7110 SoC. It is used to +transfer CSI camera data. + +Signed-off-by: Changhuang Liang +--- + drivers/phy/Kconfig | 1 + + drivers/phy/Makefile | 1 + + drivers/phy/starfive/Kconfig | 13 + + drivers/phy/starfive/Makefile | 2 + + drivers/phy/starfive/phy-starfive-dphy-rx.c | 301 ++++++++++++++++++++ + 5 files changed, 318 insertions(+) + create mode 100644 drivers/phy/starfive/Kconfig + create mode 100644 drivers/phy/starfive/Makefile + create mode 100644 drivers/phy/starfive/phy-starfive-dphy-rx.c + +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -91,6 +91,7 @@ source "drivers/phy/rockchip/Kconfig" + source "drivers/phy/samsung/Kconfig" + source "drivers/phy/socionext/Kconfig" + source "drivers/phy/st/Kconfig" ++source "drivers/phy/starfive/Kconfig" + source "drivers/phy/sunplus/Kconfig" + source "drivers/phy/tegra/Kconfig" + source "drivers/phy/ti/Kconfig" +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -31,6 +31,7 @@ obj-y += allwinner/ \ + samsung/ \ + socionext/ \ + st/ \ ++ starfive/ \ + sunplus/ \ + tegra/ \ + ti/ \ +--- /dev/null ++++ b/drivers/phy/starfive/Kconfig +@@ -0,0 +1,13 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Phy drivers for StarFive platforms ++# ++ ++config PHY_STARFIVE_DPHY_RX ++ tristate "StarFive D-PHY RX Support" ++ select GENERIC_PHY ++ select GENERIC_PHY_MIPI_DPHY ++ help ++ Choose this option if you have a StarFive D-PHY in your ++ system. If M is selected, the module will be called ++ phy-starfive-dphy-rx. +--- /dev/null ++++ b/drivers/phy/starfive/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_PHY_STARFIVE_DPHY_RX) += phy-starfive-dphy-rx.o +--- /dev/null ++++ b/drivers/phy/starfive/phy-starfive-dphy-rx.c +@@ -0,0 +1,301 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * DPHY driver for the StarFive JH7110 SoC ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define STF_DPHY_APBCFGSAIF_SYSCFG(x) (x) ++ ++#define STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_EN BIT(6) ++#define STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_IN GENMASK(12, 7) ++#define STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_EN BIT(19) ++#define STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_IN GENMASK(25, 20) ++ ++#define STF_DPHY_DATA_BUS16_8 BIT(8) ++#define STF_DPHY_DEBUG_MODE_SEL GENMASK(15, 9) ++ ++#define STF_DPHY_ENABLE_CLK BIT(6) ++#define STF_DPHY_ENABLE_CLK1 BIT(7) ++#define STF_DPHY_ENABLE_LAN0 BIT(8) ++#define STF_DPHY_ENABLE_LAN1 BIT(9) ++#define STF_DPHY_ENABLE_LAN2 BIT(10) ++#define STF_DPHY_ENABLE_LAN3 BIT(11) ++#define STF_DPHY_GPI_EN GENMASK(17, 12) ++#define STF_DPHY_HS_FREQ_CHANGE_CLK BIT(18) ++#define STF_DPHY_HS_FREQ_CHANGE_CLK1 BIT(19) ++#define STF_DPHY_LANE_SWAP_CLK GENMASK(22, 20) ++#define STF_DPHY_LANE_SWAP_CLK1 GENMASK(25, 23) ++#define STF_DPHY_LANE_SWAP_LAN0 GENMASK(28, 26) ++#define STF_DPHY_LANE_SWAP_LAN1 GENMASK(31, 29) ++ ++#define STF_DPHY_LANE_SWAP_LAN2 GENMASK(2, 0) ++#define STF_DPHY_LANE_SWAP_LAN3 GENMASK(5, 3) ++#define STF_DPHY_MP_TEST_EN BIT(6) ++#define STF_DPHY_MP_TEST_MODE_SEL GENMASK(11, 7) ++#define STF_DPHY_PLL_CLK_SEL GENMASK(21, 12) ++#define STF_DPHY_PRECOUNTER_IN_CLK GENMASK(29, 22) ++ ++#define STF_DPHY_PRECOUNTER_IN_CLK1 GENMASK(7, 0) ++#define STF_DPHY_PRECOUNTER_IN_LAN0 GENMASK(15, 8) ++#define STF_DPHY_PRECOUNTER_IN_LAN1 GENMASK(23, 16) ++#define STF_DPHY_PRECOUNTER_IN_LAN2 GENMASK(31, 24) ++ ++#define STF_DPHY_PRECOUNTER_IN_LAN3 GENMASK(7, 0) ++#define STF_DPHY_RX_1C2C_SEL BIT(8) ++ ++#define STF_MAP_LANES_NUM 6 ++ ++struct regval { ++ u32 addr; ++ u32 val; ++}; ++ ++struct stf_dphy_info { ++ /** ++ * @maps: ++ * ++ * Physical lanes and logic lanes mapping table. ++ * ++ * The default order is: ++ * [clk lane0, data lane 0, data lane 1, data lane 2, date lane 3, clk lane 1] ++ */ ++ u8 maps[STF_MAP_LANES_NUM]; ++}; ++ ++struct stf_dphy { ++ struct device *dev; ++ void __iomem *regs; ++ struct clk *cfg_clk; ++ struct clk *ref_clk; ++ struct clk *tx_clk; ++ struct reset_control *rstc; ++ struct regulator *mipi_0p9; ++ struct phy *phy; ++ const struct stf_dphy_info *info; ++}; ++ ++static const struct regval stf_dphy_init_list[] = { ++ { STF_DPHY_APBCFGSAIF_SYSCFG(4), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(8), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(12), 0x0000fff0 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(16), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(20), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(24), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(28), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(32), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(36), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(40), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(40), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(48), 0x24000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(52), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(56), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(60), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(64), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(68), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(72), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(76), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(80), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(84), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(88), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(92), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(96), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(100), 0x02000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(104), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(108), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(112), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(116), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(120), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(124), 0x0000000c }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(128), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(132), 0xcc500000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(136), 0x000000cc }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(140), 0x00000000 }, ++ { STF_DPHY_APBCFGSAIF_SYSCFG(144), 0x00000000 }, ++}; ++ ++static int stf_dphy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ struct stf_dphy *dphy = phy_get_drvdata(phy); ++ const struct stf_dphy_info *info = dphy->info; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(stf_dphy_init_list); i++) ++ writel(stf_dphy_init_list[i].val, ++ dphy->regs + stf_dphy_init_list[i].addr); ++ ++ writel(FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_EN, 1) | ++ FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_IN, 0x1b) | ++ FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_EN, 1) | ++ FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_IN, 0x1b), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(0)); ++ ++ writel(FIELD_PREP(STF_DPHY_DATA_BUS16_8, 0) | ++ FIELD_PREP(STF_DPHY_DEBUG_MODE_SEL, 0x5a), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(184)); ++ ++ writel(FIELD_PREP(STF_DPHY_ENABLE_CLK, 1) | ++ FIELD_PREP(STF_DPHY_ENABLE_CLK1, 1) | ++ FIELD_PREP(STF_DPHY_ENABLE_LAN0, 1) | ++ FIELD_PREP(STF_DPHY_ENABLE_LAN1, 1) | ++ FIELD_PREP(STF_DPHY_ENABLE_LAN2, 1) | ++ FIELD_PREP(STF_DPHY_ENABLE_LAN3, 1) | ++ FIELD_PREP(STF_DPHY_GPI_EN, 0) | ++ FIELD_PREP(STF_DPHY_HS_FREQ_CHANGE_CLK, 0) | ++ FIELD_PREP(STF_DPHY_HS_FREQ_CHANGE_CLK1, 0) | ++ FIELD_PREP(STF_DPHY_LANE_SWAP_CLK, info->maps[0]) | ++ FIELD_PREP(STF_DPHY_LANE_SWAP_CLK1, info->maps[5]) | ++ FIELD_PREP(STF_DPHY_LANE_SWAP_LAN0, info->maps[1]) | ++ FIELD_PREP(STF_DPHY_LANE_SWAP_LAN1, info->maps[2]), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(188)); ++ ++ writel(FIELD_PREP(STF_DPHY_LANE_SWAP_LAN2, info->maps[3]) | ++ FIELD_PREP(STF_DPHY_LANE_SWAP_LAN3, info->maps[4]) | ++ FIELD_PREP(STF_DPHY_MP_TEST_EN, 0) | ++ FIELD_PREP(STF_DPHY_MP_TEST_MODE_SEL, 0) | ++ FIELD_PREP(STF_DPHY_PLL_CLK_SEL, 0x37c) | ++ FIELD_PREP(STF_DPHY_PRECOUNTER_IN_CLK, 8), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(192)); ++ ++ writel(FIELD_PREP(STF_DPHY_PRECOUNTER_IN_CLK1, 8) | ++ FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN0, 7) | ++ FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN1, 7) | ++ FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN2, 7), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(196)); ++ ++ writel(FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN3, 7) | ++ FIELD_PREP(STF_DPHY_RX_1C2C_SEL, 0), ++ dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(200)); ++ ++ return 0; ++} ++ ++static int stf_dphy_power_on(struct phy *phy) ++{ ++ struct stf_dphy *dphy = phy_get_drvdata(phy); ++ int ret; ++ ++ pm_runtime_get_sync(dphy->dev); ++ ++ ret = regulator_enable(dphy->mipi_0p9); ++ if (ret) ++ return ret; ++ ++ clk_set_rate(dphy->cfg_clk, 99000000); ++ clk_set_rate(dphy->ref_clk, 49500000); ++ clk_set_rate(dphy->tx_clk, 19800000); ++ reset_control_deassert(dphy->rstc); ++ ++ return 0; ++} ++ ++static int stf_dphy_power_off(struct phy *phy) ++{ ++ struct stf_dphy *dphy = phy_get_drvdata(phy); ++ ++ reset_control_assert(dphy->rstc); ++ ++ regulator_disable(dphy->mipi_0p9); ++ ++ pm_runtime_put_sync(dphy->dev); ++ ++ return 0; ++} ++ ++static const struct phy_ops stf_dphy_ops = { ++ .configure = stf_dphy_configure, ++ .power_on = stf_dphy_power_on, ++ .power_off = stf_dphy_power_off, ++}; ++ ++static int stf_dphy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct stf_dphy *dphy; ++ ++ dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL); ++ if (!dphy) ++ return -ENOMEM; ++ ++ dphy->info = of_device_get_match_data(&pdev->dev); ++ ++ dev_set_drvdata(&pdev->dev, dphy); ++ dphy->dev = &pdev->dev; ++ ++ dphy->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(dphy->regs)) ++ return PTR_ERR(dphy->regs); ++ ++ dphy->cfg_clk = devm_clk_get(&pdev->dev, "cfg"); ++ if (IS_ERR(dphy->cfg_clk)) ++ return PTR_ERR(dphy->cfg_clk); ++ ++ dphy->ref_clk = devm_clk_get(&pdev->dev, "ref"); ++ if (IS_ERR(dphy->ref_clk)) ++ return PTR_ERR(dphy->ref_clk); ++ ++ dphy->tx_clk = devm_clk_get(&pdev->dev, "tx"); ++ if (IS_ERR(dphy->tx_clk)) ++ return PTR_ERR(dphy->tx_clk); ++ ++ dphy->rstc = devm_reset_control_array_get_exclusive(&pdev->dev); ++ if (IS_ERR(dphy->rstc)) ++ return PTR_ERR(dphy->rstc); ++ ++ dphy->mipi_0p9 = devm_regulator_get(&pdev->dev, "mipi_0p9"); ++ if (IS_ERR(dphy->mipi_0p9)) ++ return PTR_ERR(dphy->mipi_0p9); ++ ++ dphy->phy = devm_phy_create(&pdev->dev, NULL, &stf_dphy_ops); ++ if (IS_ERR(dphy->phy)) { ++ dev_err(&pdev->dev, "Failed to create PHY\n"); ++ return PTR_ERR(dphy->phy); ++ } ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ phy_set_drvdata(dphy->phy, dphy); ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, ++ of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct stf_dphy_info starfive_dphy_info = { ++ .maps = {4, 0, 1, 2, 3, 5}, ++}; ++ ++static const struct of_device_id stf_dphy_dt_ids[] = { ++ { ++ .compatible = "starfive,jh7110-dphy-rx", ++ .data = &starfive_dphy_info, ++ }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, stf_dphy_dt_ids); ++ ++static struct platform_driver stf_dphy_driver = { ++ .probe = stf_dphy_probe, ++ .driver = { ++ .name = "starfive-dphy-rx", ++ .of_match_table = stf_dphy_dt_ids, ++ }, ++}; ++module_platform_driver(stf_dphy_driver); ++ ++MODULE_AUTHOR("Jack Zhu "); ++MODULE_AUTHOR("Changhuang Liang "); ++MODULE_DESCRIPTION("StarFive DPHY RX driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch b/target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch new file mode 100644 index 0000000000..4cabffbe53 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch @@ -0,0 +1,306 @@ +From 243b040c3517093309a41877e3c1c6e8a7540071 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Tue, 23 May 2023 16:56:22 +0800 +Subject: [PATCH 076/122] media: dt-bindings: cadence-csi2rx: Convert to DT + schema + +Convert DT bindings document for Cadence MIPI-CSI2 RX controller to +DT schema format. + +For compatible, new compatibles should not be messed with conversion, +but the original binding did not specify any SoC-specific compatible +string, so add the StarFive compatible string. + +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Laurent Pinchart +Signed-off-by: Jack Zhu +--- + .../devicetree/bindings/media/cdns,csi2rx.txt | 100 ---------- + .../bindings/media/cdns,csi2rx.yaml | 177 ++++++++++++++++++ + 2 files changed, 177 insertions(+), 100 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/media/cdns,csi2rx.txt + create mode 100644 Documentation/devicetree/bindings/media/cdns,csi2rx.yaml + +--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.txt ++++ /dev/null +@@ -1,100 +0,0 @@ +-Cadence MIPI-CSI2 RX controller +-=============================== +- +-The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI +-lanes in input, and 4 different pixel streams in output. +- +-Required properties: +- - compatible: must be set to "cdns,csi2rx" and an SoC-specific compatible +- - reg: base address and size of the memory mapped region +- - clocks: phandles to the clocks driving the controller +- - clock-names: must contain: +- * sys_clk: main clock +- * p_clk: register bank clock +- * pixel_if[0-3]_clk: pixel stream output clock, one for each stream +- implemented in hardware, between 0 and 3 +- +-Optional properties: +- - phys: phandle to the external D-PHY, phy-names must be provided +- - phy-names: must contain "dphy", if the implementation uses an +- external D-PHY +- +-Required subnodes: +- - ports: A ports node with one port child node per device input and output +- port, in accordance with the video interface bindings defined in +- Documentation/devicetree/bindings/media/video-interfaces.txt. The +- port nodes are numbered as follows: +- +- Port Description +- ----------------------------- +- 0 CSI-2 input +- 1 Stream 0 output +- 2 Stream 1 output +- 3 Stream 2 output +- 4 Stream 3 output +- +- The stream output port nodes are optional if they are not +- connected to anything at the hardware level or implemented +- in the design.Since there is only one endpoint per port, +- the endpoints are not numbered. +- +- +-Example: +- +-csi2rx: csi-bridge@0d060000 { +- compatible = "cdns,csi2rx"; +- reg = <0x0d060000 0x1000>; +- clocks = <&byteclock>, <&byteclock> +- <&coreclock>, <&coreclock>, +- <&coreclock>, <&coreclock>; +- clock-names = "sys_clk", "p_clk", +- "pixel_if0_clk", "pixel_if1_clk", +- "pixel_if2_clk", "pixel_if3_clk"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- +- csi2rx_in_sensor: endpoint { +- remote-endpoint = <&sensor_out_csi2rx>; +- clock-lanes = <0>; +- data-lanes = <1 2>; +- }; +- }; +- +- port@1 { +- reg = <1>; +- +- csi2rx_out_grabber0: endpoint { +- remote-endpoint = <&grabber0_in_csi2rx>; +- }; +- }; +- +- port@2 { +- reg = <2>; +- +- csi2rx_out_grabber1: endpoint { +- remote-endpoint = <&grabber1_in_csi2rx>; +- }; +- }; +- +- port@3 { +- reg = <3>; +- +- csi2rx_out_grabber2: endpoint { +- remote-endpoint = <&grabber2_in_csi2rx>; +- }; +- }; +- +- port@4 { +- reg = <4>; +- +- csi2rx_out_grabber3: endpoint { +- remote-endpoint = <&grabber3_in_csi2rx>; +- }; +- }; +- }; +-}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml +@@ -0,0 +1,177 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Cadence MIPI-CSI2 RX controller ++ ++maintainers: ++ - Maxime Ripard ++ ++description: ++ The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI ++ lanes in input, and 4 different pixel streams in output. ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - starfive,jh7110-csi2rx ++ - const: cdns,csi2rx ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: CSI2Rx system clock ++ - description: Gated Register bank clock for APB interface ++ - description: pixel Clock for Stream interface 0 ++ - description: pixel Clock for Stream interface 1 ++ - description: pixel Clock for Stream interface 2 ++ - description: pixel Clock for Stream interface 3 ++ ++ clock-names: ++ items: ++ - const: sys_clk ++ - const: p_clk ++ - const: pixel_if0_clk ++ - const: pixel_if1_clk ++ - const: pixel_if2_clk ++ - const: pixel_if3_clk ++ ++ phys: ++ maxItems: 1 ++ description: MIPI D-PHY ++ ++ phy-names: ++ items: ++ - const: dphy ++ ++ ports: ++ $ref: /schemas/graph.yaml#/properties/ports ++ ++ properties: ++ port@0: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: ++ Input port node, single endpoint describing the CSI-2 transmitter. ++ ++ properties: ++ endpoint: ++ $ref: video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ bus-type: ++ const: 4 ++ ++ clock-lanes: ++ const: 0 ++ ++ data-lanes: ++ minItems: 1 ++ maxItems: 4 ++ items: ++ maximum: 4 ++ ++ required: ++ - data-lanes ++ ++ port@1: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Stream 0 Output port node ++ ++ port@2: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Stream 1 Output port node ++ ++ port@3: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Stream 2 Output port node ++ ++ port@4: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Stream 3 Output port node ++ ++ required: ++ - port@0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - ports ++ ++additionalProperties: false ++ ++examples: ++ - | ++ csi@d060000 { ++ compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx"; ++ reg = <0x0d060000 0x1000>; ++ clocks = <&byteclock 7>, <&byteclock 6>, ++ <&coreclock 8>, <&coreclock 9>, ++ <&coreclock 10>, <&coreclock 11>; ++ clock-names = "sys_clk", "p_clk", ++ "pixel_if0_clk", "pixel_if1_clk", ++ "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&csi_phy>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ csi2rx_in_sensor: endpoint { ++ remote-endpoint = <&sensor_out_csi2rx>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ csi2rx_out_grabber0: endpoint { ++ remote-endpoint = <&grabber0_in_csi2rx>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ ++ csi2rx_out_grabber1: endpoint { ++ remote-endpoint = <&grabber1_in_csi2rx>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ ++ csi2rx_out_grabber2: endpoint { ++ remote-endpoint = <&grabber2_in_csi2rx>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ ++ csi2rx_out_grabber3: endpoint { ++ remote-endpoint = <&grabber3_in_csi2rx>; ++ }; ++ }; ++ }; ++ }; ++ ++... diff --git a/target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch b/target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch new file mode 100644 index 0000000000..55b3fade7d --- /dev/null +++ b/target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch @@ -0,0 +1,55 @@ +From 60817a4e755c6e98092fdceec35fcda94d35e4b1 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Tue, 23 May 2023 16:56:23 +0800 +Subject: [PATCH 077/122] media: dt-bindings: cadence-csi2rx: Add resets + property + +Add resets property for Cadence MIPI-CSI2 RX controller + +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Laurent Pinchart +Signed-off-by: Jack Zhu +--- + .../bindings/media/cdns,csi2rx.yaml | 24 +++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml ++++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml +@@ -41,6 +41,24 @@ properties: + - const: pixel_if2_clk + - const: pixel_if3_clk + ++ resets: ++ items: ++ - description: CSI2Rx system reset ++ - description: Gated Register bank reset for APB interface ++ - description: pixel reset for Stream interface 0 ++ - description: pixel reset for Stream interface 1 ++ - description: pixel reset for Stream interface 2 ++ - description: pixel reset for Stream interface 3 ++ ++ reset-names: ++ items: ++ - const: sys ++ - const: reg_bank ++ - const: pixel_if0 ++ - const: pixel_if1 ++ - const: pixel_if2 ++ - const: pixel_if3 ++ + phys: + maxItems: 1 + description: MIPI D-PHY +@@ -123,6 +141,12 @@ examples: + clock-names = "sys_clk", "p_clk", + "pixel_if0_clk", "pixel_if1_clk", + "pixel_if2_clk", "pixel_if3_clk"; ++ resets = <&bytereset 9>, <&bytereset 4>, ++ <&corereset 5>, <&corereset 6>, ++ <&corereset 7>, <&corereset 8>; ++ reset-names = "sys", "reg_bank", ++ "pixel_if0", "pixel_if1", ++ "pixel_if2", "pixel_if3"; + phys = <&csi_phy>; + phy-names = "dphy"; + diff --git a/target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch b/target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch new file mode 100644 index 0000000000..2cc7b69089 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch @@ -0,0 +1,129 @@ +From 2fbf4d367b25de4fa2f2d9cec57c88766c37d9de Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Tue, 23 May 2023 16:56:24 +0800 +Subject: [PATCH 078/122] media: cadence: Add operation on reset + +Add operation on reset for Cadence MIPI-CSI2 RX Controller. + +Reviewed-by: Laurent Pinchart +Signed-off-by: Jack Zhu +--- + drivers/media/platform/cadence/cdns-csi2rx.c | 40 +++++++++++++++++--- + 1 file changed, 35 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/cadence/cdns-csi2rx.c ++++ b/drivers/media/platform/cadence/cdns-csi2rx.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -68,6 +69,9 @@ struct csi2rx_priv { + struct clk *sys_clk; + struct clk *p_clk; + struct clk *pixel_clk[CSI2RX_STREAMS_MAX]; ++ struct reset_control *sys_rst; ++ struct reset_control *p_rst; ++ struct reset_control *pixel_rst[CSI2RX_STREAMS_MAX]; + struct phy *dphy; + + u8 lanes[CSI2RX_LANES_MAX]; +@@ -112,6 +116,7 @@ static int csi2rx_start(struct csi2rx_pr + if (ret) + return ret; + ++ reset_control_deassert(csi2rx->p_rst); + csi2rx_reset(csi2rx); + + reg = csi2rx->num_lanes << 8; +@@ -154,6 +159,8 @@ static int csi2rx_start(struct csi2rx_pr + if (ret) + goto err_disable_pixclk; + ++ reset_control_deassert(csi2rx->pixel_rst[i]); ++ + writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF, + csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); + +@@ -169,13 +176,16 @@ static int csi2rx_start(struct csi2rx_pr + if (ret) + goto err_disable_pixclk; + ++ reset_control_deassert(csi2rx->sys_rst); + clk_disable_unprepare(csi2rx->p_clk); + + return 0; + + err_disable_pixclk: +- for (; i > 0; i--) ++ for (; i > 0; i--) { ++ reset_control_assert(csi2rx->pixel_rst[i - 1]); + clk_disable_unprepare(csi2rx->pixel_clk[i - 1]); ++ } + + err_disable_pclk: + clk_disable_unprepare(csi2rx->p_clk); +@@ -188,14 +198,17 @@ static void csi2rx_stop(struct csi2rx_pr + unsigned int i; + + clk_prepare_enable(csi2rx->p_clk); ++ reset_control_assert(csi2rx->sys_rst); + clk_disable_unprepare(csi2rx->sys_clk); + + for (i = 0; i < csi2rx->max_streams; i++) { + writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); + ++ reset_control_assert(csi2rx->pixel_rst[i]); + clk_disable_unprepare(csi2rx->pixel_clk[i]); + } + ++ reset_control_assert(csi2rx->p_rst); + clk_disable_unprepare(csi2rx->p_clk); + + if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false)) +@@ -299,6 +312,16 @@ static int csi2rx_get_resources(struct c + return PTR_ERR(csi2rx->p_clk); + } + ++ csi2rx->sys_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, ++ "sys"); ++ if (IS_ERR(csi2rx->sys_rst)) ++ return PTR_ERR(csi2rx->sys_rst); ++ ++ csi2rx->p_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, ++ "reg_bank"); ++ if (IS_ERR(csi2rx->p_rst)) ++ return PTR_ERR(csi2rx->p_rst); ++ + csi2rx->dphy = devm_phy_optional_get(&pdev->dev, "dphy"); + if (IS_ERR(csi2rx->dphy)) { + dev_err(&pdev->dev, "Couldn't get external D-PHY\n"); +@@ -349,14 +372,21 @@ static int csi2rx_get_resources(struct c + } + + for (i = 0; i < csi2rx->max_streams; i++) { +- char clk_name[16]; ++ char name[16]; + +- snprintf(clk_name, sizeof(clk_name), "pixel_if%u_clk", i); +- csi2rx->pixel_clk[i] = devm_clk_get(&pdev->dev, clk_name); ++ snprintf(name, sizeof(name), "pixel_if%u_clk", i); ++ csi2rx->pixel_clk[i] = devm_clk_get(&pdev->dev, name); + if (IS_ERR(csi2rx->pixel_clk[i])) { +- dev_err(&pdev->dev, "Couldn't get clock %s\n", clk_name); ++ dev_err(&pdev->dev, "Couldn't get clock %s\n", name); + return PTR_ERR(csi2rx->pixel_clk[i]); + } ++ ++ snprintf(name, sizeof(name), "pixel_if%u", i); ++ csi2rx->pixel_rst[i] = ++ devm_reset_control_get_optional_exclusive(&pdev->dev, ++ name); ++ if (IS_ERR(csi2rx->pixel_rst[i])) ++ return PTR_ERR(csi2rx->pixel_rst[i]); + } + + return 0; diff --git a/target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch b/target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch new file mode 100644 index 0000000000..77e506eb47 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch @@ -0,0 +1,141 @@ +From e97eb58b321b5b25b7d5c40880e6eb133d381581 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Tue, 23 May 2023 16:56:25 +0800 +Subject: [PATCH 079/122] media: cadence: Add support for external dphy + +Add support for external MIPI D-PHY. + +Reviewed-by: Laurent Pinchart +Signed-off-by: Jack Zhu +--- + drivers/media/platform/cadence/cdns-csi2rx.c | 66 +++++++++++++++++--- + 1 file changed, 56 insertions(+), 10 deletions(-) + +--- a/drivers/media/platform/cadence/cdns-csi2rx.c ++++ b/drivers/media/platform/cadence/cdns-csi2rx.c +@@ -31,6 +31,12 @@ + #define CSI2RX_STATIC_CFG_DLANE_MAP(llane, plane) ((plane) << (16 + (llane) * 4)) + #define CSI2RX_STATIC_CFG_LANES_MASK GENMASK(11, 8) + ++#define CSI2RX_DPHY_LANE_CTRL_REG 0x40 ++#define CSI2RX_DPHY_CL_RST BIT(16) ++#define CSI2RX_DPHY_DL_RST(i) BIT((i) + 12) ++#define CSI2RX_DPHY_CL_EN BIT(4) ++#define CSI2RX_DPHY_DL_EN(i) BIT(i) ++ + #define CSI2RX_STREAM_BASE(n) (((n) + 1) * 0x100) + + #define CSI2RX_STREAM_CTRL_REG(n) (CSI2RX_STREAM_BASE(n) + 0x000) +@@ -105,6 +111,24 @@ static void csi2rx_reset(struct csi2rx_p + writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG); + } + ++static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx) ++{ ++ union phy_configure_opts opts = { }; ++ int ret; ++ ++ ret = phy_power_on(csi2rx->dphy); ++ if (ret) ++ return ret; ++ ++ ret = phy_configure(csi2rx->dphy, &opts); ++ if (ret) { ++ phy_power_off(csi2rx->dphy); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int csi2rx_start(struct csi2rx_priv *csi2rx) + { + unsigned int i; +@@ -144,6 +168,17 @@ static int csi2rx_start(struct csi2rx_pr + if (ret) + goto err_disable_pclk; + ++ /* Enable DPHY clk and data lanes. */ ++ if (csi2rx->dphy) { ++ reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST; ++ for (i = 0; i < csi2rx->num_lanes; i++) { ++ reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1); ++ reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1); ++ } ++ ++ writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); ++ } ++ + /* + * Create a static mapping between the CSI virtual channels + * and the output stream. +@@ -177,10 +212,22 @@ static int csi2rx_start(struct csi2rx_pr + goto err_disable_pixclk; + + reset_control_deassert(csi2rx->sys_rst); ++ ++ if (csi2rx->dphy) { ++ ret = csi2rx_configure_ext_dphy(csi2rx); ++ if (ret) { ++ dev_err(csi2rx->dev, ++ "Failed to configure external DPHY: %d\n", ret); ++ goto err_disable_sysclk; ++ } ++ } ++ + clk_disable_unprepare(csi2rx->p_clk); + + return 0; + ++err_disable_sysclk: ++ clk_disable_unprepare(csi2rx->sys_clk); + err_disable_pixclk: + for (; i > 0; i--) { + reset_control_assert(csi2rx->pixel_rst[i - 1]); +@@ -213,6 +260,13 @@ static void csi2rx_stop(struct csi2rx_pr + + if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false)) + dev_warn(csi2rx->dev, "Couldn't disable our subdev\n"); ++ ++ if (csi2rx->dphy) { ++ writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); ++ ++ if (phy_power_off(csi2rx->dphy)) ++ dev_warn(csi2rx->dev, "Couldn't power off DPHY\n"); ++ } + } + + static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable) +@@ -328,15 +382,6 @@ static int csi2rx_get_resources(struct c + return PTR_ERR(csi2rx->dphy); + } + +- /* +- * FIXME: Once we'll have external D-PHY support, the check +- * will need to be removed. +- */ +- if (csi2rx->dphy) { +- dev_err(&pdev->dev, "External D-PHY not supported yet\n"); +- return -EINVAL; +- } +- + ret = clk_prepare_enable(csi2rx->p_clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't prepare and enable P clock\n"); +@@ -366,7 +411,7 @@ static int csi2rx_get_resources(struct c + * FIXME: Once we'll have internal D-PHY support, the check + * will need to be removed. + */ +- if (csi2rx->has_internal_dphy) { ++ if (!csi2rx->dphy && csi2rx->has_internal_dphy) { + dev_err(&pdev->dev, "Internal D-PHY not supported yet\n"); + return -EINVAL; + } +@@ -494,6 +539,7 @@ static int csi2rx_probe(struct platform_ + dev_info(&pdev->dev, + "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n", + csi2rx->num_lanes, csi2rx->max_lanes, csi2rx->max_streams, ++ csi2rx->dphy ? "external" : + csi2rx->has_internal_dphy ? "internal" : "no"); + + return 0; diff --git a/target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch b/target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch new file mode 100644 index 0000000000..f3527840b6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch @@ -0,0 +1,23 @@ +From d541f0ab42983dbc856f2229ee471677e80945a3 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Tue, 23 May 2023 16:56:26 +0800 +Subject: [PATCH 080/122] media: cadence: Add support for JH7110 SoC + +Add support for Starfive JH7110 SoC which has the cadence csi2 receiver. + +Reviewed-by: Laurent Pinchart +Signed-off-by: Jack Zhu +--- + drivers/media/platform/cadence/cdns-csi2rx.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/platform/cadence/cdns-csi2rx.c ++++ b/drivers/media/platform/cadence/cdns-csi2rx.c +@@ -565,6 +565,7 @@ static int csi2rx_remove(struct platform + } + + static const struct of_device_id csi2rx_of_table[] = { ++ { .compatible = "starfive,jh7110-csi2rx" }, + { .compatible = "cdns,csi2rx" }, + { }, + }; diff --git a/target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch b/target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch new file mode 100644 index 0000000000..0b3bf80b46 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch @@ -0,0 +1,197 @@ +From f3195b45a3845fd3892ca932a9cc8e352942dbcd Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:39 +0800 +Subject: [PATCH 081/122] media: dt-bindings: Add JH7110 Camera Subsystem + +Add the bindings documentation for Starfive JH7110 Camera Subsystem +which is used for handing image sensor data. + +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Jack Zhu +--- + .../bindings/media/starfive,jh7110-camss.yaml | 179 ++++++++++++++++++ + 1 file changed, 179 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml +@@ -0,0 +1,179 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/starfive,jh7110-camss.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Starfive SoC CAMSS ISP ++ ++maintainers: ++ - Jack Zhu ++ - Changhuang Liang ++ ++description: ++ The Starfive CAMSS ISP is a Camera interface for Starfive JH7110 SoC. It ++ consists of a VIN controller (Video In Controller, a top-level control until) ++ and an ISP. ++ ++properties: ++ compatible: ++ const: starfive,jh7110-camss ++ ++ reg: ++ maxItems: 2 ++ ++ reg-names: ++ items: ++ - const: syscon ++ - const: isp ++ ++ clocks: ++ maxItems: 7 ++ ++ clock-names: ++ items: ++ - const: apb_func ++ - const: wrapper_clk_c ++ - const: dvp_inv ++ - const: axiwr ++ - const: mipi_rx0_pxl ++ - const: ispcore_2x ++ - const: isp_axi ++ ++ resets: ++ maxItems: 6 ++ ++ reset-names: ++ items: ++ - const: wrapper_p ++ - const: wrapper_c ++ - const: axird ++ - const: axiwr ++ - const: isp_top_n ++ - const: isp_top_axi ++ ++ power-domains: ++ items: ++ - description: JH7110 ISP Power Domain Switch Controller. ++ ++ interrupts: ++ maxItems: 4 ++ ++ ports: ++ $ref: /schemas/graph.yaml#/properties/ports ++ ++ properties: ++ port@0: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: Input port for receiving DVP data. ++ ++ properties: ++ endpoint: ++ $ref: video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ bus-type: ++ enum: [5, 6] ++ ++ bus-width: ++ enum: [8, 10, 12] ++ ++ data-shift: ++ enum: [0, 2] ++ default: 0 ++ ++ hsync-active: ++ enum: [0, 1] ++ default: 1 ++ ++ vsync-active: ++ enum: [0, 1] ++ default: 1 ++ ++ required: ++ - bus-type ++ - bus-width ++ ++ port@1: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: Input port for receiving CSI data. ++ ++ required: ++ - port@0 ++ - port@1 ++ ++required: ++ - compatible ++ - reg ++ - reg-names ++ - clocks ++ - clock-names ++ - resets ++ - reset-names ++ - power-domains ++ - interrupts ++ - ports ++ ++additionalProperties: false ++ ++examples: ++ - | ++ isp@19840000 { ++ compatible = "starfive,jh7110-camss"; ++ reg = <0x19840000 0x10000>, ++ <0x19870000 0x30000>; ++ reg-names = "syscon", "isp"; ++ clocks = <&ispcrg 0>, ++ <&ispcrg 13>, ++ <&ispcrg 2>, ++ <&ispcrg 12>, ++ <&ispcrg 1>, ++ <&syscrg 51>, ++ <&syscrg 52>; ++ clock-names = "apb_func", ++ "wrapper_clk_c", ++ "dvp_inv", ++ "axiwr", ++ "mipi_rx0_pxl", ++ "ispcore_2x", ++ "isp_axi"; ++ resets = <&ispcrg 0>, ++ <&ispcrg 1>, ++ <&ispcrg 10>, ++ <&ispcrg 11>, ++ <&syscrg 41>, ++ <&syscrg 42>; ++ reset-names = "wrapper_p", ++ "wrapper_c", ++ "axird", ++ "axiwr", ++ "isp_top_n", ++ "isp_top_axi"; ++ power-domains = <&pwrc 5>; ++ interrupts = <92>, <87>, <88>, <90>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ vin_from_sc2235: endpoint { ++ remote-endpoint = <&sc2235_to_vin>; ++ bus-width = <8>; ++ data-shift = <2>; ++ hsync-active = <1>; ++ vsync-active = <0>; ++ pclk-sample = <1>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ vin_from_csi2rx: endpoint { ++ remote-endpoint = <&csi2rx_to_vin>; ++ }; ++ }; ++ }; ++ }; diff --git a/target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch b/target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch new file mode 100644 index 0000000000..7d59112e8e --- /dev/null +++ b/target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch @@ -0,0 +1,106 @@ +From 949807343300a75b6e7c3e47463f817a7b6bc790 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:40 +0800 +Subject: [PATCH 082/122] media: admin-guide: Add starfive_camss.rst for + Starfive Camera Subsystem + +Add starfive_camss.rst file that documents the Starfive Camera +Subsystem driver which is used for handing image sensor data. + +Signed-off-by: Jack Zhu +--- + .../admin-guide/media/starfive_camss.rst | 57 +++++++++++++++++++ + .../media/starfive_camss_graph.dot | 16 ++++++ + .../admin-guide/media/v4l-drivers.rst | 1 + + 3 files changed, 74 insertions(+) + create mode 100644 Documentation/admin-guide/media/starfive_camss.rst + create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot + +--- /dev/null ++++ b/Documentation/admin-guide/media/starfive_camss.rst +@@ -0,0 +1,57 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++.. include:: ++ ++================================ ++Starfive Camera Subsystem driver ++================================ ++ ++Introduction ++------------ ++ ++This file documents the driver for the Starfive Camera Subsystem found on ++Starfive JH7110 SoC. The driver is located under drivers/media/platform/ ++starfive. ++ ++The driver implements V4L2, Media controller and v4l2_subdev interfaces. ++Camera sensor using V4L2 subdev interface in the kernel is supported. ++ ++The driver has been successfully used on the Gstreamer 1.18.5 with ++v4l2src plugin. ++ ++ ++Starfive Camera Subsystem hardware ++---------------------------------- ++ ++The Starfive Camera Subsystem hardware consists of: ++ ++- MIPI DPHY Receiver: receives mipi data from a MIPI camera sensor. ++- MIPI CSIRx Controller: is responsible for handling and decoding CSI2 protocol ++ based camera sensor data stream. ++- ISP: handles the image data streams from the MIPI CSIRx Controller. ++- VIN(Video In): a top-level module, is responsible for controlling power ++ and clocks to other modules, dumps the input data to memory or transfers the ++ input data to ISP. ++ ++ ++Topology ++-------- ++ ++The media controller pipeline graph is as follows: ++ ++.. _starfive_camss_graph: ++ ++.. kernel-figure:: starfive_camss_graph.dot ++ :alt: starfive_camss_graph.dot ++ :align: center ++ ++The driver has 2 video devices: ++ ++- stf_vin0_wr_video0: capture device for images directly from the VIN module. ++- stf_vin0_isp0_video1: capture device for images without scaling. ++ ++The driver has 3 subdevices: ++ ++- stf_isp0: is responsible for all the isp operations. ++- stf_vin0_wr: used to dump RAW images to memory. ++- stf_vin0_isp0: used to capture images for the stf_vin0_isp0_video1 device. +--- /dev/null ++++ b/Documentation/admin-guide/media/starfive_camss_graph.dot +@@ -0,0 +1,16 @@ ++digraph board { ++ rankdir=TB ++ n00000001 [label="{{ 0} | stf_isp0\n/dev/v4l-subdev0 | { 1}}", shape=Mrecord, style=filled, fillcolor=green] ++ n00000001:port1 -> n0000000d:port0 ++ n00000004 [label="{{ 0} | stf_vin0_wr\n/dev/v4l-subdev1 | { 1}}", shape=Mrecord, style=filled, fillcolor=green] ++ n00000004:port1 -> n00000007 [style=bold] ++ n00000007 [label="stf_vin0_wr_video0\n/dev/video0", shape=box, style=filled, fillcolor=yellow] ++ n0000000d [label="{{ 0} | stf_vin0_isp0\n/dev/v4l-subdev2 | { 1}}", shape=Mrecord, style=filled, fillcolor=green] ++ n0000000d:port1 -> n00000010 [style=bold] ++ n00000010 [label="stf_vin0_isp0_video1\n/dev/video1", shape=box, style=filled, fillcolor=yellow] ++ n00000018 [label="{{ 0} | cdns_csi2rx.19800000.csi-bridge\n | { 1 | 2 | 3 | 4}}", shape=Mrecord, style=filled, fillcolor=green] ++ n00000018:port1 -> n00000004:port0 [style=dashed] ++ n00000018:port1 -> n00000001:port0 ++ n00000028 [label="{{} | imx219 6-0010\n | { 0}}", shape=Mrecord, style=filled, fillcolor=green] ++ n00000028:port0 -> n00000018:port0 [style=bold] ++} +--- a/Documentation/admin-guide/media/v4l-drivers.rst ++++ b/Documentation/admin-guide/media/v4l-drivers.rst +@@ -30,5 +30,6 @@ Video4Linux (V4L) driver-specific docume + si470x + si4713 + si476x ++ starfive_camss + vimc + vivid diff --git a/target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch b/target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch new file mode 100644 index 0000000000..bc5141cfbc --- /dev/null +++ b/target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch @@ -0,0 +1,630 @@ +From 0dc93c9321ba947ac429baeb58202496e4b0f219 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:41 +0800 +Subject: [PATCH 083/122] media: starfive: Add basic driver + +Add basic platform driver for StarFive Camera Subsystem. + +Signed-off-by: Jack Zhu +Reviewed-by: Bryan O'Donoghue +--- + drivers/media/platform/Kconfig | 1 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/starfive/Kconfig | 19 + + drivers/media/platform/starfive/Makefile | 9 + + drivers/media/platform/starfive/stf_camss.c | 372 +++++++++++++++++++ + drivers/media/platform/starfive/stf_camss.h | 153 ++++++++ + drivers/media/platform/starfive/stf_common.h | 18 + + 7 files changed, 573 insertions(+) + create mode 100644 drivers/media/platform/starfive/Kconfig + create mode 100644 drivers/media/platform/starfive/Makefile + create mode 100644 drivers/media/platform/starfive/stf_camss.c + create mode 100644 drivers/media/platform/starfive/stf_camss.h + create mode 100644 drivers/media/platform/starfive/stf_common.h + +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -79,6 +79,7 @@ source "drivers/media/platform/renesas/K + source "drivers/media/platform/rockchip/Kconfig" + source "drivers/media/platform/samsung/Kconfig" + source "drivers/media/platform/st/Kconfig" ++source "drivers/media/platform/starfive/Kconfig" + source "drivers/media/platform/sunxi/Kconfig" + source "drivers/media/platform/ti/Kconfig" + source "drivers/media/platform/verisilicon/Kconfig" +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -22,6 +22,7 @@ obj-y += renesas/ + obj-y += rockchip/ + obj-y += samsung/ + obj-y += st/ ++obj-y += starfive/ + obj-y += sunxi/ + obj-y += ti/ + obj-y += verisilicon/ +--- /dev/null ++++ b/drivers/media/platform/starfive/Kconfig +@@ -0,0 +1,19 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++comment "Starfive media platform drivers" ++ ++config VIDEO_STARFIVE_CAMSS ++ tristate "Starfive Camera Subsystem driver" ++ depends on V4L_PLATFORM_DRIVERS ++ depends on VIDEO_DEV && OF ++ depends on DMA_CMA ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_FWNODE ++ help ++ Enable this to support for the Starfive Camera subsystem ++ found on Starfive JH7110 SoC. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called stf-camss. +--- /dev/null ++++ b/drivers/media/platform/starfive/Makefile +@@ -0,0 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for StarFive camera subsystem driver. ++# ++ ++starfive-camss-objs += \ ++ stf_camss.o ++ ++obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \ +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_camss.c +@@ -0,0 +1,372 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_camss.c ++ * ++ * Starfive Camera Subsystem driver ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stf_camss.h" ++ ++static const char * const stfcamss_clocks[] = { ++ "clk_apb_func", ++ "clk_wrapper_clk_c", ++ "clk_dvp_inv", ++ "clk_axiwr", ++ "clk_mipi_rx0_pxl", ++ "clk_ispcore_2x", ++ "clk_isp_axi", ++}; ++ ++static const char * const stfcamss_resets[] = { ++ "rst_wrapper_p", ++ "rst_wrapper_c", ++ "rst_axird", ++ "rst_axiwr", ++ "rst_isp_top_n", ++ "rst_isp_top_axi", ++}; ++ ++static int stfcamss_get_mem_res(struct platform_device *pdev, ++ struct stfcamss *stfcamss) ++{ ++ stfcamss->syscon_base = ++ devm_platform_ioremap_resource_byname(pdev, "syscon"); ++ if (IS_ERR(stfcamss->syscon_base)) ++ return PTR_ERR(stfcamss->syscon_base); ++ ++ stfcamss->isp_base = ++ devm_platform_ioremap_resource_byname(pdev, "isp"); ++ if (IS_ERR(stfcamss->isp_base)) ++ return PTR_ERR(stfcamss->isp_base); ++ ++ return 0; ++} ++ ++/* ++ * stfcamss_of_parse_endpoint_node - Parse port endpoint node ++ * @dev: Device ++ * @node: Device node to be parsed ++ * @csd: Parsed data from port endpoint node ++ * ++ * Return 0 on success or a negative error code on failure ++ */ ++static int stfcamss_of_parse_endpoint_node(struct device *dev, ++ struct device_node *node, ++ struct stfcamss_async_subdev *csd) ++{ ++ struct v4l2_fwnode_endpoint vep = { { 0 } }; ++ ++ v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep); ++ dev_dbg(dev, "vep.base.port = 0x%x, id = 0x%x\n", ++ vep.base.port, vep.base.id); ++ ++ csd->port = vep.base.port; ++ ++ return 0; ++} ++ ++/* ++ * stfcamss_of_parse_ports - Parse ports node ++ * @stfcamss: STFCAMSS device ++ * ++ * Return number of "port" nodes found in "ports" node ++ */ ++static int stfcamss_of_parse_ports(struct stfcamss *stfcamss) ++{ ++ struct device *dev = stfcamss->dev; ++ struct device_node *node = NULL; ++ struct device_node *remote = NULL; ++ int ret, num_subdevs = 0; ++ ++ for_each_endpoint_of_node(dev->of_node, node) { ++ struct stfcamss_async_subdev *csd; ++ ++ if (!of_device_is_available(node)) ++ continue; ++ ++ remote = of_graph_get_remote_port_parent(node); ++ if (!remote) { ++ dev_err(dev, "Cannot get remote parent\n"); ++ ret = -EINVAL; ++ goto err_cleanup; ++ } ++ ++ csd = v4l2_async_nf_add_fwnode(&stfcamss->notifier, ++ of_fwnode_handle(remote), ++ struct stfcamss_async_subdev); ++ of_node_put(remote); ++ if (IS_ERR(csd)) { ++ ret = PTR_ERR(csd); ++ goto err_cleanup; ++ } ++ ++ ret = stfcamss_of_parse_endpoint_node(dev, node, csd); ++ if (ret < 0) ++ goto err_cleanup; ++ ++ num_subdevs++; ++ } ++ ++ return num_subdevs; ++ ++err_cleanup: ++ of_node_put(node); ++ return ret; ++} ++ ++static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async, ++ struct v4l2_subdev *subdev, ++ struct v4l2_async_subdev *asd) ++{ ++ struct stfcamss *stfcamss = ++ container_of(async, struct stfcamss, notifier); ++ struct host_data *host_data = &stfcamss->host_data; ++ struct media_entity *source; ++ int i, j; ++ ++ source = &subdev->entity; ++ ++ for (i = 0; i < source->num_pads; i++) { ++ if (source->pads[i].flags & MEDIA_PAD_FL_SOURCE) ++ break; ++ } ++ ++ if (i == source->num_pads) { ++ dev_err(stfcamss->dev, "No source pad in external entity\n"); ++ return -EINVAL; ++ } ++ ++ for (j = 0; host_data->host_entity[j] && (j < HOST_ENTITY_MAX); j++) { ++ struct media_entity *input; ++ int ret; ++ ++ input = host_data->host_entity[j]; ++ ++ ret = media_create_pad_link( ++ source, ++ i, ++ input, ++ STF_PAD_SINK, ++ source->function == MEDIA_ENT_F_CAM_SENSOR ? ++ MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED : ++ 0); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, ++ "Failed to link %s->%s entities: %d\n", ++ source->name, input->name, ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf) ++{ ++ struct stfcamss *stfcamss = ++ container_of(ntf, struct stfcamss, notifier); ++ ++ return v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev); ++} ++ ++static const struct v4l2_async_notifier_operations ++stfcamss_subdev_notifier_ops = { ++ .bound = stfcamss_subdev_notifier_bound, ++ .complete = stfcamss_subdev_notifier_complete, ++}; ++ ++static const struct media_device_ops stfcamss_media_ops = { ++ .link_notify = v4l2_pipeline_link_notify, ++}; ++ ++static void stfcamss_mc_init(struct platform_device *pdev, ++ struct stfcamss *stfcamss) ++{ ++ stfcamss->media_dev.dev = stfcamss->dev; ++ strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem", ++ sizeof(stfcamss->media_dev.model)); ++ snprintf(stfcamss->media_dev.bus_info, ++ sizeof(stfcamss->media_dev.bus_info), ++ "%s:%s", dev_bus_name(&pdev->dev), pdev->name); ++ stfcamss->media_dev.hw_revision = 0x01; ++ stfcamss->media_dev.ops = &stfcamss_media_ops; ++ media_device_init(&stfcamss->media_dev); ++ ++ stfcamss->v4l2_dev.mdev = &stfcamss->media_dev; ++} ++ ++/* ++ * stfcamss_probe - Probe STFCAMSS platform device ++ * @pdev: Pointer to STFCAMSS platform device ++ * ++ * Return 0 on success or a negative error code on failure ++ */ ++static int stfcamss_probe(struct platform_device *pdev) ++{ ++ struct stfcamss *stfcamss; ++ struct device *dev = &pdev->dev; ++ int ret = 0, i, num_subdevs; ++ ++ stfcamss = devm_kzalloc(dev, sizeof(*stfcamss), GFP_KERNEL); ++ if (!stfcamss) ++ return -ENOMEM; ++ ++ for (i = 0; i < ARRAY_SIZE(stfcamss->irq); ++i) { ++ stfcamss->irq[i] = platform_get_irq(pdev, i); ++ if (stfcamss->irq[i] < 0) ++ return dev_err_probe(&pdev->dev, stfcamss->irq[i], ++ "Failed to get clock%d", i); ++ } ++ ++ stfcamss->nclks = ARRAY_SIZE(stfcamss->sys_clk); ++ for (i = 0; i < ARRAY_SIZE(stfcamss->sys_clk); ++i) ++ stfcamss->sys_clk[i].id = stfcamss_clocks[i]; ++ ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk); ++ if (ret) { ++ dev_err(dev, "Failed to get clk controls\n"); ++ return ret; ++ } ++ ++ stfcamss->nrsts = ARRAY_SIZE(stfcamss->sys_rst); ++ for (i = 0; i < ARRAY_SIZE(stfcamss->sys_rst); ++i) ++ stfcamss->sys_rst[i].id = stfcamss_resets[i]; ++ ret = devm_reset_control_bulk_get_shared(dev, stfcamss->nrsts, ++ stfcamss->sys_rst); ++ if (ret) { ++ dev_err(dev, "Failed to get reset controls\n"); ++ return ret; ++ } ++ ++ ret = stfcamss_get_mem_res(pdev, stfcamss); ++ if (ret) { ++ dev_err(dev, "Could not map registers\n"); ++ return ret; ++ } ++ ++ stfcamss->dev = dev; ++ platform_set_drvdata(pdev, stfcamss); ++ ++ v4l2_async_nf_init(&stfcamss->notifier); ++ ++ num_subdevs = stfcamss_of_parse_ports(stfcamss); ++ if (num_subdevs < 0) { ++ dev_err(dev, "Failed to find subdevices\n"); ++ return -ENODEV; ++ } ++ ++ stfcamss_mc_init(pdev, stfcamss); ++ ++ ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev); ++ if (ret < 0) { ++ dev_err(dev, "Failed to register V4L2 device: %d\n", ret); ++ goto err_cleanup_notifier; ++ } ++ ++ ret = media_device_register(&stfcamss->media_dev); ++ if (ret) { ++ dev_err(dev, "Failed to register media device: %d\n", ret); ++ goto err_unregister_device; ++ } ++ ++ stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops; ++ ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier); ++ if (ret) { ++ dev_err(dev, "Failed to register async subdev nodes: %d\n", ++ ret); ++ goto err_unregister_media_dev; ++ } ++ ++ pm_runtime_enable(dev); ++ ++ return 0; ++ ++err_unregister_media_dev: ++ media_device_unregister(&stfcamss->media_dev); ++err_unregister_device: ++ v4l2_device_unregister(&stfcamss->v4l2_dev); ++err_cleanup_notifier: ++ v4l2_async_nf_cleanup(&stfcamss->notifier); ++ return ret; ++} ++ ++/* ++ * stfcamss_remove - Remove STFCAMSS platform device ++ * @pdev: Pointer to STFCAMSS platform device ++ * ++ * Always returns 0. ++ */ ++static int stfcamss_remove(struct platform_device *pdev) ++{ ++ struct stfcamss *stfcamss = platform_get_drvdata(pdev); ++ ++ v4l2_device_unregister(&stfcamss->v4l2_dev); ++ media_device_cleanup(&stfcamss->media_dev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id stfcamss_of_match[] = { ++ { .compatible = "starfive,jh7110-camss" }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, stfcamss_of_match); ++ ++static int __maybe_unused stfcamss_runtime_suspend(struct device *dev) ++{ ++ struct stfcamss *stfcamss = dev_get_drvdata(dev); ++ ++ reset_control_assert(stfcamss->sys_rst[STF_RST_ISP_TOP_AXI].rstc); ++ reset_control_assert(stfcamss->sys_rst[STF_RST_ISP_TOP_N].rstc); ++ clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_ISP_AXI].clk); ++ clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_ISPCORE_2X].clk); ++ ++ return 0; ++} ++ ++static int __maybe_unused stfcamss_runtime_resume(struct device *dev) ++{ ++ struct stfcamss *stfcamss = dev_get_drvdata(dev); ++ ++ clk_prepare_enable(stfcamss->sys_clk[STF_CLK_ISPCORE_2X].clk); ++ clk_prepare_enable(stfcamss->sys_clk[STF_CLK_ISP_AXI].clk); ++ reset_control_deassert(stfcamss->sys_rst[STF_RST_ISP_TOP_N].rstc); ++ reset_control_deassert(stfcamss->sys_rst[STF_RST_ISP_TOP_AXI].rstc); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops stfcamss_pm_ops = { ++ SET_RUNTIME_PM_OPS(stfcamss_runtime_suspend, ++ stfcamss_runtime_resume, ++ NULL) ++}; ++ ++static struct platform_driver stfcamss_driver = { ++ .probe = stfcamss_probe, ++ .remove = stfcamss_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = &stfcamss_pm_ops, ++ .of_match_table = of_match_ptr(stfcamss_of_match), ++ }, ++}; ++ ++module_platform_driver(stfcamss_driver); ++ ++MODULE_AUTHOR("StarFive Corporation"); ++MODULE_DESCRIPTION("StarFive Camera Subsystem driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_camss.h +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * stf_camss.h ++ * ++ * Starfive Camera Subsystem driver ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef STF_CAMSS_H ++#define STF_CAMSS_H ++ ++#include ++#include ++#include ++#include ++ ++#include "stf_common.h" ++ ++#define DRV_NAME "starfive-camss" ++#define STF_DVP_NAME "stf_dvp" ++#define STF_CSI_NAME "cdns_csi2rx" ++#define STF_ISP_NAME "stf_isp" ++#define STF_VIN_NAME "stf_vin" ++ ++#define STF_PAD_SINK 0 ++#define STF_PAD_SRC 1 ++#define STF_PADS_NUM 2 ++ ++enum port_num { ++ PORT_NUMBER_DVP_SENSOR = 0, ++ PORT_NUMBER_CSI2RX ++}; ++ ++enum stf_clk { ++ STF_CLK_APB_FUNC = 0, ++ STF_CLK_WRAPPER_CLK_C, ++ STF_CLK_DVP_INV, ++ STF_CLK_AXIWR, ++ STF_CLK_MIPI_RX0_PXL, ++ STF_CLK_ISPCORE_2X, ++ STF_CLK_ISP_AXI, ++ STF_CLK_NUM ++}; ++ ++enum stf_rst { ++ STF_RST_WRAPPER_P = 0, ++ STF_RST_WRAPPER_C, ++ STF_RST_AXIRD, ++ STF_RST_AXIWR, ++ STF_RST_ISP_TOP_N, ++ STF_RST_ISP_TOP_AXI, ++ STF_RST_NUM ++}; ++ ++enum stf_irq { ++ STF_IRQ_VINWR = 0, ++ STF_IRQ_ISP, ++ STF_IRQ_ISPCSIL, ++ STF_IRQ_NUM ++}; ++ ++#define HOST_ENTITY_MAX 2 ++ ++struct host_data { ++ struct media_entity *host_entity[HOST_ENTITY_MAX]; ++}; ++ ++struct stfcamss { ++ struct v4l2_device v4l2_dev; ++ struct media_device media_dev; ++ struct media_pipeline pipe; ++ struct device *dev; ++ struct v4l2_async_notifier notifier; ++ struct host_data host_data; ++ void __iomem *syscon_base; ++ void __iomem *isp_base; ++ int irq[STF_IRQ_NUM]; ++ struct clk_bulk_data sys_clk[STF_CLK_NUM]; ++ int nclks; ++ struct reset_control_bulk_data sys_rst[STF_RST_NUM]; ++ int nrsts; ++}; ++ ++struct stfcamss_async_subdev { ++ struct v4l2_async_subdev asd; /* must be first */ ++ enum port_num port; ++}; ++ ++static inline u32 stf_isp_reg_read(struct stfcamss *stfcamss, u32 reg) ++{ ++ return ioread32(stfcamss->isp_base + reg); ++} ++ ++static inline void stf_isp_reg_write(struct stfcamss *stfcamss, ++ u32 reg, u32 val) ++{ ++ iowrite32(val, stfcamss->isp_base + reg); ++} ++ ++static inline void stf_isp_reg_write_delay(struct stfcamss *stfcamss, ++ u32 reg, u32 val, u32 delay) ++{ ++ iowrite32(val, stfcamss->isp_base + reg); ++ usleep_range(1000 * delay, 1000 * delay + 100); ++} ++ ++static inline void stf_isp_reg_set_bit(struct stfcamss *stfcamss, ++ u32 reg, u32 mask, u32 val) ++{ ++ u32 value; ++ ++ value = ioread32(stfcamss->isp_base + reg) & ~mask; ++ val &= mask; ++ val |= value; ++ iowrite32(val, stfcamss->isp_base + reg); ++} ++ ++static inline void stf_isp_reg_set(struct stfcamss *stfcamss, u32 reg, u32 mask) ++{ ++ iowrite32(ioread32(stfcamss->isp_base + reg) | mask, ++ stfcamss->isp_base + reg); ++} ++ ++static inline u32 stf_syscon_reg_read(struct stfcamss *stfcamss, u32 reg) ++{ ++ return ioread32(stfcamss->syscon_base + reg); ++} ++ ++static inline void stf_syscon_reg_write(struct stfcamss *stfcamss, ++ u32 reg, u32 val) ++{ ++ iowrite32(val, stfcamss->syscon_base + reg); ++} ++ ++static inline void stf_syscon_reg_set_bit(struct stfcamss *stfcamss, ++ u32 reg, u32 bit_mask) ++{ ++ u32 value; ++ ++ value = ioread32(stfcamss->syscon_base + reg); ++ iowrite32(value | bit_mask, stfcamss->syscon_base + reg); ++} ++ ++static inline void stf_syscon_reg_clear_bit(struct stfcamss *stfcamss, ++ u32 reg, u32 bit_mask) ++{ ++ u32 value; ++ ++ value = ioread32(stfcamss->syscon_base + reg); ++ iowrite32(value & ~bit_mask, stfcamss->syscon_base + reg); ++} ++#endif /* STF_CAMSS_H */ +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_common.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * stf_common.h ++ * ++ * StarFive Camera Subsystem - Common definitions ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef STF_COMMON_H ++#define STF_COMMON_H ++ ++enum stf_subdev_type { ++ STF_SUBDEV_TYPE_VIN, ++ STF_SUBDEV_TYPE_ISP, ++}; ++ ++#endif /* STF_COMMON_H */ diff --git a/target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch b/target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch new file mode 100644 index 0000000000..f9317485a2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch @@ -0,0 +1,992 @@ +From 70a588f7daefe34697ccd04fa6ac3a6d4b63be88 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:42 +0800 +Subject: [PATCH 084/122] media: starfive: Add video driver + +Add video driver for StarFive Camera Subsystem. + +Signed-off-by: Jack Zhu +--- + drivers/media/platform/starfive/Makefile | 3 +- + drivers/media/platform/starfive/stf_video.c | 864 ++++++++++++++++++++ + drivers/media/platform/starfive/stf_video.h | 95 +++ + 3 files changed, 961 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/platform/starfive/stf_video.c + create mode 100644 drivers/media/platform/starfive/stf_video.h + +--- a/drivers/media/platform/starfive/Makefile ++++ b/drivers/media/platform/starfive/Makefile +@@ -4,6 +4,7 @@ + # + + starfive-camss-objs += \ +- stf_camss.o ++ stf_camss.o \ ++ stf_video.o + + obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \ +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_video.c +@@ -0,0 +1,864 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_video.c ++ * ++ * StarFive Camera Subsystem - V4L2 device node ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "stf_camss.h" ++#include "stf_video.h" ++ ++static const struct stfcamss_format_info formats_pix_wr[] = { ++ { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 1, ++ { { 1, 1 } }, { { 1, 1 } }, { 10 } }, ++ { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 1, ++ { { 1, 1 } }, { { 1, 1 } }, { 10 } }, ++ { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 1, ++ { { 1, 1 } }, { { 1, 1 } }, { 10 } }, ++ { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 1, ++ { { 1, 1 } }, { { 1, 1 } }, { 10 } }, ++}; ++ ++static const struct stfcamss_format_info formats_pix_isp[] = { ++ { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1, ++ { { 1, 1 } }, { { 2, 3 } }, { 8 } }, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Helper functions ++ */ ++ ++static int video_find_format(u32 code, u32 pixelformat, ++ const struct stfcamss_format_info *formats, ++ unsigned int nformats) ++{ ++ int i; ++ ++ for (i = 0; i < nformats; i++) { ++ if (formats[i].code == code && ++ formats[i].pixelformat == pixelformat) ++ return i; ++ } ++ ++ for (i = 0; i < nformats; i++) ++ if (formats[i].code == code) ++ return i; ++ ++ for (i = 0; i < nformats; i++) ++ if (formats[i].pixelformat == pixelformat) ++ return i; ++ ++ return -EINVAL; ++} ++ ++static int __video_try_fmt(struct stfcamss_video *video, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format *pix; ++ const struct stfcamss_format_info *fi; ++ u32 width, height; ++ u32 bpl; ++ int i; ++ ++ pix = &f->fmt.pix; ++ ++ for (i = 0; i < video->nformats; i++) ++ if (pix->pixelformat == video->formats[i].pixelformat) ++ break; ++ ++ if (i == video->nformats) ++ i = 0; /* default format */ ++ ++ fi = &video->formats[i]; ++ width = pix->width; ++ height = pix->height; ++ ++ memset(pix, 0, sizeof(*pix)); ++ ++ pix->pixelformat = fi->pixelformat; ++ pix->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH, ++ STFCAMSS_FRAME_MAX_WIDTH); ++ pix->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT, ++ STFCAMSS_FRAME_MAX_HEIGHT); ++ bpl = pix->width / fi->hsub[0].numerator * ++ fi->hsub[0].denominator * fi->bpp[0] / 8; ++ bpl = ALIGN(bpl, video->bpl_alignment); ++ pix->bytesperline = bpl; ++ pix->sizeimage = pix->height / fi->vsub[0].numerator * ++ fi->vsub[0].denominator * bpl; ++ ++ pix->field = V4L2_FIELD_NONE; ++ pix->colorspace = V4L2_COLORSPACE_SRGB; ++ pix->flags = 0; ++ pix->ycbcr_enc = ++ V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace); ++ pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, ++ pix->colorspace, ++ pix->ycbcr_enc); ++ pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace); ++ ++ return 0; ++} ++ ++static int stf_video_init_format(struct stfcamss_video *video) ++{ ++ int ret; ++ struct v4l2_format format = { ++ .type = video->type, ++ .fmt.pix = { ++ .width = 1920, ++ .height = 1080, ++ .pixelformat = V4L2_PIX_FMT_RGB565, ++ }, ++ }; ++ ++ ret = __video_try_fmt(video, &format); ++ ++ if (ret < 0) ++ return ret; ++ ++ video->active_fmt = format; ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Video queue operations ++ */ ++ ++static int video_queue_setup(struct vb2_queue *q, ++ unsigned int *num_buffers, ++ unsigned int *num_planes, ++ unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct stfcamss_video *video = vb2_get_drv_priv(q); ++ const struct v4l2_pix_format *format = &video->active_fmt.fmt.pix; ++ ++ if (*num_planes) { ++ if (*num_planes != 1) ++ return -EINVAL; ++ ++ if (sizes[0] < format->sizeimage) ++ return -EINVAL; ++ } ++ ++ *num_planes = 1; ++ sizes[0] = format->sizeimage; ++ if (!sizes[0]) ++ dev_err(video->stfcamss->dev, ++ "%s: error size is zero!!!\n", __func__); ++ ++ dev_dbg(video->stfcamss->dev, "planes = %d, size = %d\n", ++ *num_planes, sizes[0]); ++ ++ return 0; ++} ++ ++static int video_buf_init(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue); ++ struct stfcamss_buffer *buffer = ++ container_of(vbuf, struct stfcamss_buffer, vb); ++ const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix; ++ dma_addr_t *paddr; ++ ++ buffer->sizeimage = 0; ++ ++ paddr = vb2_plane_cookie(vb, 0); ++ buffer->sizeimage = vb2_plane_size(vb, 0); ++ buffer->addr[0] = *paddr; ++ if (fmt->pixelformat == V4L2_PIX_FMT_NV12 || ++ fmt->pixelformat == V4L2_PIX_FMT_NV21 || ++ fmt->pixelformat == V4L2_PIX_FMT_NV16 || ++ fmt->pixelformat == V4L2_PIX_FMT_NV61) ++ buffer->addr[1] = ++ buffer->addr[0] + fmt->bytesperline * fmt->height; ++ ++ return 0; ++} ++ ++static int video_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue); ++ const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix; ++ ++ if (fmt->sizeimage > vb2_plane_size(vb, 0)) { ++ dev_err(video->stfcamss->dev, ++ "sizeimage = %d, plane size = %d\n", ++ fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0)); ++ return -EINVAL; ++ } ++ vb2_set_plane_payload(vb, 0, fmt->sizeimage); ++ ++ vbuf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static void video_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue); ++ struct stfcamss_buffer *buffer = ++ container_of(vbuf, struct stfcamss_buffer, vb); ++ ++ video->ops->queue_buffer(video, buffer); ++} ++ ++/* ++ * video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format ++ * @mbus: v4l2_mbus_framefmt format (input) ++ * @pix: v4l2_pix_format_mplane format (output) ++ * @f: a pointer to formats array element to be used for the conversion ++ * @alignment: bytesperline alignment value ++ * ++ * Fill the output pix structure with information from the input mbus format. ++ * ++ * Return 0 on success or a negative error code otherwise ++ */ ++static int video_mbus_to_pix(const struct v4l2_mbus_framefmt *mbus, ++ struct v4l2_pix_format *pix, ++ const struct stfcamss_format_info *f, ++ unsigned int alignment) ++{ ++ u32 bytesperline; ++ ++ memset(pix, 0, sizeof(*pix)); ++ v4l2_fill_pix_format(pix, mbus); ++ pix->pixelformat = f->pixelformat; ++ bytesperline = pix->width / f->hsub[0].numerator * ++ f->hsub[0].denominator * f->bpp[0] / 8; ++ bytesperline = ALIGN(bytesperline, alignment); ++ pix->bytesperline = bytesperline; ++ pix->sizeimage = pix->height / f->vsub[0].numerator * ++ f->vsub[0].denominator * bytesperline; ++ return 0; ++} ++ ++static struct v4l2_subdev *video_remote_subdev(struct stfcamss_video *video, ++ u32 *pad) ++{ ++ struct media_pad *remote; ++ ++ remote = media_pad_remote_pad_first(&video->pad); ++ ++ if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) ++ return NULL; ++ ++ if (pad) ++ *pad = remote->index; ++ ++ return media_entity_to_v4l2_subdev(remote->entity); ++} ++ ++static int video_get_subdev_format(struct stfcamss_video *video, ++ struct v4l2_format *format) ++{ ++ struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix; ++ struct v4l2_subdev_format fmt; ++ struct v4l2_subdev *subdev; ++ u32 pixelformat; ++ u32 pad; ++ int ret; ++ ++ subdev = video_remote_subdev(video, &pad); ++ if (!subdev) ++ return -EPIPE; ++ ++ fmt.pad = pad; ++ fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ++ ++ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); ++ if (ret) ++ return ret; ++ ++ pixelformat = pix->pixelformat; ++ ret = video_find_format(fmt.format.code, pixelformat, ++ video->formats, video->nformats); ++ if (ret < 0) ++ return ret; ++ ++ format->type = video->type; ++ ++ return video_mbus_to_pix(&fmt.format, &format->fmt.pix, ++ &video->formats[ret], video->bpl_alignment); ++} ++ ++static int video_check_format(struct stfcamss_video *video) ++{ ++ struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix; ++ struct v4l2_format format; ++ struct v4l2_pix_format *sd_pix = &format.fmt.pix; ++ int ret; ++ ++ sd_pix->pixelformat = pix->pixelformat; ++ ret = video_get_subdev_format(video, &format); ++ if (ret < 0) ++ return ret; ++ ++ if (pix->pixelformat != sd_pix->pixelformat || ++ pix->height > sd_pix->height || ++ pix->width > sd_pix->width || ++ pix->field != format.fmt.pix.field) { ++ dev_err(video->stfcamss->dev, ++ "%s, not match:\n" ++ "0x%x 0x%x\n0x%x 0x%x\n0x%x 0x%x\n", ++ __func__, ++ pix->pixelformat, sd_pix->pixelformat, ++ pix->height, sd_pix->height, ++ pix->field, format.fmt.pix.field); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static int video_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct stfcamss_video *video = vb2_get_drv_priv(q); ++ struct video_device *vdev = &video->vdev; ++ struct media_entity *entity; ++ struct media_pad *pad; ++ struct v4l2_subdev *subdev; ++ int ret; ++ ++ ret = video_device_pipeline_start(vdev, &video->stfcamss->pipe); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to media_pipeline_start: %d\n", ret); ++ return ret; ++ } ++ ++ ret = video_check_format(video); ++ if (ret < 0) ++ goto error; ++ entity = &vdev->entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ break; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ break; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ ++ ret = v4l2_subdev_call(subdev, video, s_stream, 1); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ goto error; ++ } ++ return 0; ++ ++error: ++ video_device_pipeline_stop(vdev); ++ video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED); ++ return ret; ++} ++ ++static void video_stop_streaming(struct vb2_queue *q) ++{ ++ struct stfcamss_video *video = vb2_get_drv_priv(q); ++ struct video_device *vdev = &video->vdev; ++ struct media_entity *entity; ++ struct media_pad *pad; ++ struct v4l2_subdev *subdev; ++ ++ entity = &vdev->entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ break; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ break; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ ++ v4l2_subdev_call(subdev, video, s_stream, 0); ++ } ++ ++ video_device_pipeline_stop(vdev); ++ video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR); ++} ++ ++static const struct vb2_ops stf_video_vb2_q_ops = { ++ .queue_setup = video_queue_setup, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++ .buf_init = video_buf_init, ++ .buf_prepare = video_buf_prepare, ++ .buf_queue = video_buf_queue, ++ .start_streaming = video_start_streaming, ++ .stop_streaming = video_stop_streaming, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 ioctls ++ */ ++ ++static int video_querycap(struct file *file, void *fh, ++ struct v4l2_capability *cap) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ ++ strscpy(cap->driver, "stf camss", sizeof(cap->driver)); ++ strscpy(cap->card, "Starfive Camera Subsystem", sizeof(cap->card)); ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ++ dev_name(video->stfcamss->dev)); ++ return 0; ++} ++ ++static int video_get_pfmt_by_index(struct stfcamss_video *video, int ndx) ++{ ++ int i, j, k; ++ ++ /* find index "i" of "k"th unique pixelformat in formats array */ ++ k = -1; ++ for (i = 0; i < video->nformats; i++) { ++ for (j = 0; j < i; j++) { ++ if (video->formats[i].pixelformat == ++ video->formats[j].pixelformat) ++ break; ++ } ++ ++ if (j == i) ++ k++; ++ ++ if (k == ndx) ++ return i; ++ } ++ ++ return -EINVAL; ++} ++ ++static int video_get_pfmt_by_mcode(struct stfcamss_video *video, u32 mcode) ++{ ++ int i; ++ ++ for (i = 0; i < video->nformats; i++) { ++ if (video->formats[i].code == mcode) ++ return i; ++ } ++ ++ return -EINVAL; ++} ++ ++static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ int i; ++ ++ if (f->type != video->type) ++ return -EINVAL; ++ if (f->index >= video->nformats) ++ return -EINVAL; ++ ++ if (f->mbus_code) { ++ /* Each entry in formats[] table has unique mbus_code */ ++ if (f->index > 0) ++ return -EINVAL; ++ ++ i = video_get_pfmt_by_mcode(video, f->mbus_code); ++ } else { ++ i = video_get_pfmt_by_index(video, f->index); ++ } ++ ++ if (i < 0) ++ return -EINVAL; ++ ++ f->pixelformat = video->formats[i].pixelformat; ++ ++ return 0; ++} ++ ++static int video_enum_framesizes(struct file *file, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ int i; ++ ++ if (fsize->index) ++ return -EINVAL; ++ ++ for (i = 0; i < video->nformats; i++) { ++ if (video->formats[i].pixelformat == fsize->pixel_format) ++ break; ++ } ++ ++ if (i == video->nformats) ++ return -EINVAL; ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; ++ fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH; ++ fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH; ++ fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT; ++ fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ ++ *f = video->active_fmt; ++ ++ return 0; ++} ++ ++static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ int ret; ++ ++ if (vb2_is_busy(&video->vb2_q)) ++ return -EBUSY; ++ ++ ret = __video_try_fmt(video, f); ++ if (ret < 0) ++ return ret; ++ ++ video->active_fmt = *f; ++ ++ return 0; ++} ++ ++static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ ++ return __video_try_fmt(video, f); ++} ++ ++static int video_enum_input(struct file *file, void *fh, ++ struct v4l2_input *input) ++{ ++ if (input->index > 0) ++ return -EINVAL; ++ ++ strscpy(input->name, "camera", sizeof(input->name)); ++ input->type = V4L2_INPUT_TYPE_CAMERA; ++ ++ return 0; ++} ++ ++static int video_g_input(struct file *file, void *fh, unsigned int *input) ++{ ++ *input = 0; ++ ++ return 0; ++} ++ ++static int video_s_input(struct file *file, void *fh, unsigned int input) ++{ ++ return input == 0 ? 0 : -EINVAL; ++} ++ ++static int video_g_parm(struct file *file, void *priv, ++ struct v4l2_streamparm *p) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ struct video_device *vdev = &video->vdev; ++ struct media_entity *entity; ++ struct v4l2_subdev *subdev; ++ struct media_pad *pad; ++ int ret, is_support = 0; ++ ++ entity = &vdev->entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ break; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ break; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ ++ ret = v4l2_g_parm_cap(vdev, subdev, p); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ break; ++ if (!ret) ++ is_support = 1; ++ } ++ ++ return is_support ? 0 : ret; ++} ++ ++static int video_s_parm(struct file *file, void *priv, ++ struct v4l2_streamparm *p) ++{ ++ struct stfcamss_video *video = video_drvdata(file); ++ struct video_device *vdev = &video->vdev; ++ struct media_entity *entity; ++ struct v4l2_subdev *subdev; ++ struct media_pad *pad; ++ struct v4l2_streamparm tmp_p; ++ int ret, is_support = 0; ++ ++ entity = &vdev->entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ break; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ break; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ ++ tmp_p = *p; ++ ret = v4l2_s_parm_cap(vdev, subdev, &tmp_p); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ break; ++ if (!ret) { ++ is_support = 1; ++ *p = tmp_p; ++ } ++ } ++ ++ return is_support ? 0 : ret; ++} ++ ++static const struct v4l2_ioctl_ops stf_vid_vin_ioctl_ops = { ++ .vidioc_querycap = video_querycap, ++ .vidioc_enum_fmt_vid_cap = video_enum_fmt, ++ .vidioc_enum_fmt_vid_out = video_enum_fmt, ++ .vidioc_enum_framesizes = video_enum_framesizes, ++ .vidioc_g_fmt_vid_cap = video_g_fmt, ++ .vidioc_s_fmt_vid_cap = video_s_fmt, ++ .vidioc_try_fmt_vid_cap = video_try_fmt, ++ .vidioc_g_fmt_vid_out = video_g_fmt, ++ .vidioc_s_fmt_vid_out = video_s_fmt, ++ .vidioc_try_fmt_vid_out = video_try_fmt, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ .vidioc_enum_input = video_enum_input, ++ .vidioc_g_input = video_g_input, ++ .vidioc_s_input = video_s_input, ++ .vidioc_g_parm = video_g_parm, ++ .vidioc_s_parm = video_s_parm, ++}; ++ ++static const struct v4l2_ioctl_ops stf_vid_isp_ioctl_ops = { ++ .vidioc_querycap = video_querycap, ++ .vidioc_enum_fmt_vid_cap = video_enum_fmt, ++ .vidioc_enum_fmt_vid_out = video_enum_fmt, ++ .vidioc_enum_framesizes = video_enum_framesizes, ++ .vidioc_g_fmt_vid_cap = video_g_fmt, ++ .vidioc_s_fmt_vid_cap = video_s_fmt, ++ .vidioc_try_fmt_vid_cap = video_try_fmt, ++ .vidioc_g_fmt_vid_out = video_g_fmt, ++ .vidioc_s_fmt_vid_out = video_s_fmt, ++ .vidioc_try_fmt_vid_out = video_try_fmt, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ .vidioc_enum_input = video_enum_input, ++ .vidioc_g_input = video_g_input, ++ .vidioc_s_input = video_s_input, ++ .vidioc_g_parm = video_g_parm, ++ .vidioc_s_parm = video_s_parm, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 file operations ++ */ ++ ++static int video_open(struct file *file) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct stfcamss_video *video = video_drvdata(file); ++ struct v4l2_fh *vfh; ++ int ret; ++ ++ mutex_lock(&video->lock); ++ ++ vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); ++ if (!vfh) { ++ ret = -ENOMEM; ++ goto error_alloc; ++ } ++ ++ v4l2_fh_init(vfh, vdev); ++ v4l2_fh_add(vfh); ++ ++ file->private_data = vfh; ++ ++ ret = v4l2_pipeline_pm_get(&vdev->entity); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to power up pipeline: %d\n", ret); ++ goto error_pm_use; ++ } ++ mutex_unlock(&video->lock); ++ ++ return 0; ++ ++error_pm_use: ++ v4l2_fh_release(file); ++error_alloc: ++ mutex_unlock(&video->lock); ++ return ret; ++} ++ ++static int video_release(struct file *file) ++{ ++ struct video_device *vdev = video_devdata(file); ++ ++ vb2_fop_release(file); ++ v4l2_pipeline_pm_put(&vdev->entity); ++ file->private_data = NULL; ++ ++ return 0; ++} ++ ++static const struct v4l2_file_operations stf_vid_fops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = video_ioctl2, ++ .open = video_open, ++ .release = video_release, ++ .poll = vb2_fop_poll, ++ .mmap = vb2_fop_mmap, ++ .read = vb2_fop_read, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * STFCAMSS video core ++ */ ++ ++static void stf_video_release(struct video_device *vdev) ++{ ++ struct stfcamss_video *video = video_get_drvdata(vdev); ++ ++ media_entity_cleanup(&vdev->entity); ++ ++ mutex_destroy(&video->q_lock); ++ mutex_destroy(&video->lock); ++} ++ ++int stf_video_register(struct stfcamss_video *video, ++ struct v4l2_device *v4l2_dev, const char *name) ++{ ++ struct video_device *vdev; ++ struct vb2_queue *q; ++ struct media_pad *pad = &video->pad; ++ int ret; ++ ++ vdev = &video->vdev; ++ ++ mutex_init(&video->q_lock); ++ ++ q = &video->vb2_q; ++ q->drv_priv = video; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->ops = &stf_video_vb2_q_ops; ++ q->type = video->type; ++ q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ; ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ q->buf_struct_size = sizeof(struct stfcamss_buffer); ++ q->dev = video->stfcamss->dev; ++ q->lock = &video->q_lock; ++ q->min_buffers_needed = STFCAMSS_MIN_BUFFERS; ++ ret = vb2_queue_init(q); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to init vb2 queue: %d\n", ret); ++ goto err_vb2_init; ++ } ++ ++ pad->flags = MEDIA_PAD_FL_SINK; ++ ret = media_entity_pads_init(&vdev->entity, 1, pad); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to init video entity: %d\n", ret); ++ goto err_vb2_init; ++ } ++ ++ mutex_init(&video->lock); ++ ++ if (video->id == STF_V_LINE_WR) { ++ video->formats = formats_pix_wr; ++ video->nformats = ARRAY_SIZE(formats_pix_wr); ++ video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8; ++ vdev->ioctl_ops = &stf_vid_vin_ioctl_ops; ++ } else { ++ video->formats = formats_pix_isp; ++ video->nformats = ARRAY_SIZE(formats_pix_isp); ++ video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8; ++ vdev->ioctl_ops = &stf_vid_isp_ioctl_ops; ++ } ++ ++ ret = stf_video_init_format(video); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to init format: %d\n", ret); ++ goto err_vid_init_format; ++ } ++ ++ vdev->fops = &stf_vid_fops; ++ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE; ++ vdev->vfl_dir = VFL_DIR_RX; ++ vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; ++ vdev->release = stf_video_release; ++ vdev->v4l2_dev = v4l2_dev; ++ vdev->queue = &video->vb2_q; ++ vdev->lock = &video->lock; ++ strscpy(vdev->name, name, sizeof(vdev->name)); ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, video->id); ++ if (ret < 0) { ++ dev_err(video->stfcamss->dev, ++ "Failed to register video device: %d\n", ret); ++ goto err_vid_reg; ++ } ++ ++ video_set_drvdata(vdev, video); ++ return 0; ++ ++err_vid_reg: ++err_vid_init_format: ++ media_entity_cleanup(&vdev->entity); ++ mutex_destroy(&video->lock); ++err_vb2_init: ++ mutex_destroy(&video->q_lock); ++ return ret; ++} ++ ++void stf_video_unregister(struct stfcamss_video *video) ++{ ++ vb2_video_unregister_device(&video->vdev); ++} +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_video.h +@@ -0,0 +1,95 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * stf_video.h ++ * ++ * StarFive Camera Subsystem - V4L2 device node ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef STF_VIDEO_H ++#define STF_VIDEO_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define STFCAMSS_FRAME_MIN_WIDTH 64 ++#define STFCAMSS_FRAME_MAX_WIDTH 1920 ++#define STFCAMSS_FRAME_MIN_HEIGHT 64 ++#define STFCAMSS_FRAME_MAX_HEIGHT 1080 ++#define STFCAMSS_FRAME_WIDTH_ALIGN_8 8 ++#define STFCAMSS_FRAME_WIDTH_ALIGN_128 128 ++#define STFCAMSS_MIN_BUFFERS 2 ++ ++#define STFCAMSS_MAX_ENTITY_NAME_LEN 27 ++ ++enum stf_v_line_id { ++ STF_V_LINE_WR = 0, ++ STF_V_LINE_ISP, ++ STF_V_LINE_MAX, ++}; ++ ++struct stfcamss_buffer { ++ struct vb2_v4l2_buffer vb; ++ dma_addr_t addr[3]; ++ struct list_head queue; ++ int sizeimage; ++}; ++ ++struct fract { ++ u8 numerator; ++ u8 denominator; ++}; ++ ++/* ++ * struct stfcamss_format_info - ISP media bus format information ++ * @code: V4L2 media bus format code ++ * @pixelformat: V4L2 pixel format FCC identifier ++ * @planes: Number of planes ++ * @hsub: Horizontal subsampling (for each plane) ++ * @vsub: Vertical subsampling (for each plane) ++ * @bpp: Bits per pixel when stored in memory (for each plane) ++ */ ++struct stfcamss_format_info { ++ u32 code; ++ u32 pixelformat; ++ u8 planes; ++ struct fract hsub[3]; ++ struct fract vsub[3]; ++ u8 bpp[3]; ++}; ++ ++struct stfcamss_video { ++ struct stfcamss *stfcamss; ++ u8 id; ++ struct vb2_queue vb2_q; ++ struct video_device vdev; ++ struct media_pad pad; ++ struct media_pipeline pipe; ++ struct v4l2_format active_fmt; ++ enum v4l2_buf_type type; ++ const struct stfcamss_video_ops *ops; ++ struct mutex lock; /* serialize device access */ ++ struct mutex q_lock; /* protects the queue */ ++ unsigned int bpl_alignment; ++ const struct stfcamss_format_info *formats; ++ unsigned int nformats; ++}; ++ ++struct stfcamss_video_ops { ++ int (*queue_buffer)(struct stfcamss_video *vid, ++ struct stfcamss_buffer *buf); ++ int (*flush_buffers)(struct stfcamss_video *vid, ++ enum vb2_buffer_state state); ++}; ++ ++int stf_video_register(struct stfcamss_video *video, ++ struct v4l2_device *v4l2_dev, const char *name); ++ ++void stf_video_unregister(struct stfcamss_video *video); ++ ++#endif /* STF_VIDEO_H */ diff --git a/target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch b/target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch new file mode 100644 index 0000000000..3a871b5a7f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch @@ -0,0 +1,1667 @@ +From 3b814965133cd53b1f30a34e4425294726cb0087 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:43 +0800 +Subject: [PATCH 085/122] media: starfive: Add ISP driver + +Add ISP driver for StarFive Camera Subsystem. + +Signed-off-by: Jack Zhu +--- + drivers/media/platform/starfive/Makefile | 2 + + drivers/media/platform/starfive/stf_camss.c | 71 ++- + drivers/media/platform/starfive/stf_camss.h | 2 + + drivers/media/platform/starfive/stf_isp.c | 550 ++++++++++++++++++ + drivers/media/platform/starfive/stf_isp.h | 476 +++++++++++++++ + .../media/platform/starfive/stf_isp_hw_ops.c | 452 ++++++++++++++ + 6 files changed, 1551 insertions(+), 2 deletions(-) + create mode 100644 drivers/media/platform/starfive/stf_isp.c + create mode 100644 drivers/media/platform/starfive/stf_isp.h + create mode 100644 drivers/media/platform/starfive/stf_isp_hw_ops.c + +--- a/drivers/media/platform/starfive/Makefile ++++ b/drivers/media/platform/starfive/Makefile +@@ -5,6 +5,8 @@ + + starfive-camss-objs += \ + stf_camss.o \ ++ stf_isp.o \ ++ stf_isp_hw_ops.o \ + stf_video.o + + obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \ +--- a/drivers/media/platform/starfive/stf_camss.c ++++ b/drivers/media/platform/starfive/stf_camss.c +@@ -126,16 +126,66 @@ err_cleanup: + return ret; + } + ++/* ++ * stfcamss_init_subdevices - Initialize subdev structures and resources ++ * @stfcamss: STFCAMSS device ++ * ++ * Return 0 on success or a negative error code on failure ++ */ ++static int stfcamss_init_subdevices(struct stfcamss *stfcamss) ++{ ++ int ret; ++ ++ ret = stf_isp_subdev_init(stfcamss); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, "Failed to init isp subdev: %d\n", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int stfcamss_register_subdevices(struct stfcamss *stfcamss) ++{ ++ int ret; ++ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; ++ ++ ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, ++ "Failed to register stf isp%d entity: %d\n", 0, ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss) ++{ ++ stf_isp_unregister(&stfcamss->isp_dev); ++} ++ + static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) + { + struct stfcamss *stfcamss = + container_of(async, struct stfcamss, notifier); ++ struct stfcamss_async_subdev *csd = ++ container_of(asd, struct stfcamss_async_subdev, asd); ++ enum port_num port = csd->port; ++ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; + struct host_data *host_data = &stfcamss->host_data; + struct media_entity *source; + int i, j; + ++ if (port == PORT_NUMBER_CSI2RX) { ++ host_data->host_entity[1] = &isp_dev->subdev.entity; ++ } else if (port == PORT_NUMBER_DVP_SENSOR) { ++ dev_err(stfcamss->dev, "Not support DVP sensor\n"); ++ return -EPERM; ++ } ++ + source = &subdev->entity; + + for (i = 0; i < source->num_pads; i++) { +@@ -266,12 +316,18 @@ static int stfcamss_probe(struct platfor + return -ENODEV; + } + ++ ret = stfcamss_init_subdevices(stfcamss); ++ if (ret < 0) { ++ dev_err(dev, "Failed to init subdevice: %d\n", ret); ++ goto err_cleanup_notifier; ++ } ++ + stfcamss_mc_init(pdev, stfcamss); + + ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev); + if (ret < 0) { + dev_err(dev, "Failed to register V4L2 device: %d\n", ret); +- goto err_cleanup_notifier; ++ goto err_cleanup_media_device; + } + + ret = media_device_register(&stfcamss->media_dev); +@@ -280,22 +336,32 @@ static int stfcamss_probe(struct platfor + goto err_unregister_device; + } + ++ ret = stfcamss_register_subdevices(stfcamss); ++ if (ret < 0) { ++ dev_err(dev, "Failed to register subdevice: %d\n", ret); ++ goto err_unregister_media_dev; ++ } ++ + stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops; + ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier); + if (ret) { + dev_err(dev, "Failed to register async subdev nodes: %d\n", + ret); +- goto err_unregister_media_dev; ++ goto err_unregister_subdevs; + } + + pm_runtime_enable(dev); + + return 0; + ++err_unregister_subdevs: ++ stfcamss_unregister_subdevices(stfcamss); + err_unregister_media_dev: + media_device_unregister(&stfcamss->media_dev); + err_unregister_device: + v4l2_device_unregister(&stfcamss->v4l2_dev); ++err_cleanup_media_device: ++ media_device_cleanup(&stfcamss->media_dev); + err_cleanup_notifier: + v4l2_async_nf_cleanup(&stfcamss->notifier); + return ret; +@@ -311,6 +377,7 @@ static int stfcamss_remove(struct platfo + { + struct stfcamss *stfcamss = platform_get_drvdata(pdev); + ++ stfcamss_unregister_subdevices(stfcamss); + v4l2_device_unregister(&stfcamss->v4l2_dev); + media_device_cleanup(&stfcamss->media_dev); + pm_runtime_disable(&pdev->dev); +--- a/drivers/media/platform/starfive/stf_camss.h ++++ b/drivers/media/platform/starfive/stf_camss.h +@@ -16,6 +16,7 @@ + #include + + #include "stf_common.h" ++#include "stf_isp.h" + + #define DRV_NAME "starfive-camss" + #define STF_DVP_NAME "stf_dvp" +@@ -71,6 +72,7 @@ struct stfcamss { + struct media_device media_dev; + struct media_pipeline pipe; + struct device *dev; ++ struct stf_isp_dev isp_dev; + struct v4l2_async_notifier notifier; + struct host_data host_data; + void __iomem *syscon_base; +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_isp.c +@@ -0,0 +1,550 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_isp.c ++ * ++ * StarFive Camera Subsystem - ISP Module ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++#include ++#include ++ ++#include "stf_camss.h" ++ ++#define SINK_FORMATS_INDEX 0 ++#define UO_FORMATS_INDEX 1 ++ ++static int isp_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_selection *sel); ++ ++static const struct isp_format isp_formats_sink[] = { ++ { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, ++ { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, ++ { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, ++ { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, ++}; ++ ++static const struct isp_format isp_formats_uo[] = { ++ { MEDIA_BUS_FMT_Y12_1X12, 8 }, ++}; ++ ++static const struct isp_format_table isp_formats_st7110[] = { ++ { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) }, ++ { isp_formats_uo, ARRAY_SIZE(isp_formats_uo) }, ++}; ++ ++int stf_isp_subdev_init(struct stfcamss *stfcamss) ++{ ++ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; ++ ++ isp_dev->sdev_type = STF_SUBDEV_TYPE_ISP; ++ isp_dev->stfcamss = stfcamss; ++ isp_dev->formats = isp_formats_st7110; ++ isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110); ++ ++ mutex_init(&isp_dev->stream_lock); ++ mutex_init(&isp_dev->power_lock); ++ return 0; ++} ++ ++static int isp_set_power(struct v4l2_subdev *sd, int on) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ ++ mutex_lock(&isp_dev->power_lock); ++ if (on) { ++ if (isp_dev->power_count == 0) ++ dev_dbg(isp_dev->stfcamss->dev, "turn on isp\n"); ++ isp_dev->power_count++; ++ } else { ++ if (isp_dev->power_count == 0) ++ goto exit; ++ isp_dev->power_count--; ++ } ++exit: ++ mutex_unlock(&isp_dev->power_lock); ++ ++ return 0; ++} ++ ++static struct v4l2_mbus_framefmt * ++__isp_get_format(struct stf_isp_dev *isp_dev, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ enum v4l2_subdev_format_whence which) ++{ ++ if (which == V4L2_SUBDEV_FORMAT_TRY) ++ return v4l2_subdev_get_try_format(&isp_dev->subdev, state, pad); ++ ++ return &isp_dev->fmt[pad]; ++} ++ ++static int isp_set_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ int ret = 0; ++ struct v4l2_mbus_framefmt *fmt; ++ struct v4l2_event src_ch = { 0 }; ++ ++ fmt = __isp_get_format(isp_dev, NULL, STF_ISP_PAD_SINK, ++ V4L2_SUBDEV_FORMAT_ACTIVE); ++ mutex_lock(&isp_dev->stream_lock); ++ if (enable) { ++ if (isp_dev->stream_count == 0) { ++ stf_isp_clk_enable(isp_dev); ++ stf_isp_reset(isp_dev); ++ stf_isp_init_cfg(isp_dev); ++ stf_isp_settings(isp_dev, isp_dev->rect, fmt->code); ++ stf_isp_stream_set(isp_dev); ++ } ++ isp_dev->stream_count++; ++ } else { ++ if (isp_dev->stream_count == 0) ++ goto exit; ++ ++ if (isp_dev->stream_count == 1) ++ stf_isp_clk_disable(isp_dev); ++ ++ isp_dev->stream_count--; ++ } ++ src_ch.type = V4L2_EVENT_SOURCE_CHANGE, ++ src_ch.u.src_change.changes = isp_dev->stream_count, ++ ++ v4l2_subdev_notify_event(sd, &src_ch); ++exit: ++ mutex_unlock(&isp_dev->stream_lock); ++ ++ return ret; ++} ++ ++static void isp_try_format(struct stf_isp_dev *isp_dev, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ struct v4l2_mbus_framefmt *fmt, ++ enum v4l2_subdev_format_whence which) ++{ ++ const struct isp_format_table *formats; ++ struct stf_isp_crop *rect; ++ int i; ++ ++ switch (pad) { ++ case STF_ISP_PAD_SINK: ++ /* Set format on sink pad */ ++ formats = &isp_dev->formats[SINK_FORMATS_INDEX]; ++ rect = &isp_dev->rect[SINK_FORMATS_INDEX]; ++ fmt->width = clamp_t(u32, ++ fmt->width, STFCAMSS_FRAME_MIN_WIDTH, ++ STFCAMSS_FRAME_MAX_WIDTH); ++ fmt->height = clamp_t(u32, ++ fmt->height, STFCAMSS_FRAME_MIN_HEIGHT, ++ STFCAMSS_FRAME_MAX_HEIGHT); ++ fmt->height &= ~0x1; ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->flags = 0; ++ break; ++ ++ case STF_ISP_PAD_SRC: ++ formats = &isp_dev->formats[UO_FORMATS_INDEX]; ++ rect = &isp_dev->rect[UO_FORMATS_INDEX]; ++ *fmt = *__isp_get_format(isp_dev, state, ++ STF_ISP_PAD_SINK, which); ++ break; ++ } ++ ++ for (i = 0; i < formats->nfmts; i++) { ++ if (fmt->code == formats->fmts[i].code) ++ break; ++ } ++ ++ if (i >= formats->nfmts) { ++ fmt->code = formats->fmts[0].code; ++ rect->bpp = formats->fmts[0].bpp; ++ } else { ++ rect->bpp = formats->fmts[i].bpp; ++ } ++} ++ ++static int isp_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ const struct isp_format_table *formats; ++ ++ if (code->index >= isp_dev->nformats) ++ return -EINVAL; ++ if (code->pad == STF_ISP_PAD_SINK) { ++ formats = &isp_dev->formats[SINK_FORMATS_INDEX]; ++ code->code = formats->fmts[code->index].code; ++ } else { ++ struct v4l2_mbus_framefmt *sink_fmt; ++ ++ sink_fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, ++ code->which); ++ ++ code->code = sink_fmt->code; ++ if (!code->code) ++ return -EINVAL; ++ } ++ code->flags = 0; ++ ++ return 0; ++} ++ ++static int isp_enum_frame_size(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt format; ++ ++ if (fse->index != 0) ++ return -EINVAL; ++ ++ format.code = fse->code; ++ format.width = 1; ++ format.height = 1; ++ isp_try_format(isp_dev, state, fse->pad, &format, fse->which); ++ fse->min_width = format.width; ++ fse->min_height = format.height; ++ ++ if (format.code != fse->code) ++ return -EINVAL; ++ ++ format.code = fse->code; ++ format.width = -1; ++ format.height = -1; ++ isp_try_format(isp_dev, state, fse->pad, &format, fse->which); ++ fse->max_width = format.width; ++ fse->max_height = format.height; ++ ++ return 0; ++} ++ ++static int isp_get_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt *format; ++ ++ format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which); ++ if (!format) ++ return -EINVAL; ++ ++ fmt->format = *format; ++ ++ return 0; ++} ++ ++static int isp_set_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt *format; ++ ++ format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which); ++ if (!format) ++ return -EINVAL; ++ ++ mutex_lock(&isp_dev->stream_lock); ++ ++ isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which); ++ *format = fmt->format; ++ ++ mutex_unlock(&isp_dev->stream_lock); ++ ++ /* Propagate to in crop */ ++ if (fmt->pad == STF_ISP_PAD_SINK) { ++ struct v4l2_subdev_selection sel = { 0 }; ++ int ret; ++ ++ /* Reset sink pad compose selection */ ++ sel.which = fmt->which; ++ sel.pad = STF_ISP_PAD_SINK; ++ sel.target = V4L2_SEL_TGT_CROP; ++ sel.r.width = fmt->format.width; ++ sel.r.height = fmt->format.height; ++ ret = isp_set_selection(sd, state, &sel); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct v4l2_rect * ++__isp_get_crop(struct stf_isp_dev *isp_dev, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ enum v4l2_subdev_format_whence which) ++{ ++ if (which == V4L2_SUBDEV_FORMAT_TRY) ++ return v4l2_subdev_get_try_crop(&isp_dev->subdev, state, ++ STF_ISP_PAD_SINK); ++ ++ return &isp_dev->rect[pad].rect; ++} ++ ++static void isp_try_crop(struct stf_isp_dev *isp_dev, ++ struct v4l2_subdev_state *state, ++ struct v4l2_rect *rect, ++ enum v4l2_subdev_format_whence which) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which); ++ ++ if (rect->width > fmt->width) ++ rect->width = fmt->width; ++ ++ if (rect->width + rect->left > fmt->width) ++ rect->left = fmt->width - rect->width; ++ ++ if (rect->height > fmt->height) ++ rect->height = fmt->height; ++ ++ if (rect->height + rect->top > fmt->height) ++ rect->top = fmt->height - rect->height; ++ ++ if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) { ++ rect->left = 0; ++ rect->width = STFCAMSS_FRAME_MAX_WIDTH; ++ } ++ ++ if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) { ++ rect->top = 0; ++ rect->height = STFCAMSS_FRAME_MAX_HEIGHT; ++ } ++ rect->height &= ~0x1; ++} ++ ++static int isp_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ struct v4l2_subdev_format fmt = { 0 }; ++ struct v4l2_rect *rect; ++ int ret; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ if (sel->pad == STF_ISP_PAD_SINK) { ++ fmt.pad = sel->pad; ++ fmt.which = sel->which; ++ ret = isp_get_format(sd, state, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = fmt.format.width; ++ sel->r.height = fmt.format.height; ++ } else if (sel->pad == STF_ISP_PAD_SRC) { ++ rect = __isp_get_crop(isp_dev, state, ++ sel->pad, sel->which); ++ sel->r = *rect; ++ } ++ break; ++ ++ case V4L2_SEL_TGT_CROP: ++ rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which); ++ if (!rect) ++ return -EINVAL; ++ ++ sel->r = *rect; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int isp_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); ++ struct v4l2_rect *rect; ++ int ret = 0; ++ ++ if (sel->target == V4L2_SEL_TGT_CROP && ++ sel->pad == STF_ISP_PAD_SINK) { ++ struct v4l2_subdev_selection crop = { 0 }; ++ ++ rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which); ++ if (!rect) ++ return -EINVAL; ++ ++ mutex_lock(&isp_dev->stream_lock); ++ isp_try_crop(isp_dev, state, &sel->r, sel->which); ++ *rect = sel->r; ++ mutex_unlock(&isp_dev->stream_lock); ++ ++ /* Reset source crop selection */ ++ crop.which = sel->which; ++ crop.pad = STF_ISP_PAD_SRC; ++ crop.target = V4L2_SEL_TGT_CROP; ++ crop.r = *rect; ++ ret = isp_set_selection(sd, state, &crop); ++ } else if (sel->target == V4L2_SEL_TGT_CROP && ++ sel->pad == STF_ISP_PAD_SRC) { ++ struct v4l2_subdev_format fmt = { 0 }; ++ ++ rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which); ++ if (!rect) ++ return -EINVAL; ++ ++ mutex_lock(&isp_dev->stream_lock); ++ isp_try_crop(isp_dev, state, &sel->r, sel->which); ++ *rect = sel->r; ++ mutex_unlock(&isp_dev->stream_lock); ++ ++ /* Reset source pad format width and height */ ++ fmt.which = sel->which; ++ fmt.pad = STF_ISP_PAD_SRC; ++ fmt.format.width = rect->width; ++ fmt.format.height = rect->height; ++ ret = isp_set_format(sd, state, &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ dev_dbg(isp_dev->stfcamss->dev, "pad: %d sel(%d,%d)/%dx%d\n", ++ sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); ++ ++ return 0; ++} ++ ++static int isp_init_formats(struct v4l2_subdev *sd, ++ struct v4l2_subdev_fh *fh) ++{ ++ struct v4l2_subdev_format format = { ++ .pad = STF_ISP_PAD_SINK, ++ .which = ++ fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE, ++ .format = { ++ .code = MEDIA_BUS_FMT_RGB565_2X8_LE, ++ .width = 1920, ++ .height = 1080 ++ } ++ }; ++ ++ return isp_set_format(sd, fh ? fh->state : NULL, &format); ++} ++ ++static int isp_link_setup(struct media_entity *entity, ++ const struct media_pad *local, ++ const struct media_pad *remote, u32 flags) ++{ ++ if (flags & MEDIA_LNK_FL_ENABLED) ++ if (media_pad_remote_pad_first(local)) ++ return -EBUSY; ++ return 0; ++} ++ ++static int stf_isp_subscribe_event(struct v4l2_subdev *sd, ++ struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ switch (sub->type) { ++ case V4L2_EVENT_SOURCE_CHANGE: ++ return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static const struct v4l2_subdev_core_ops isp_core_ops = { ++ .s_power = isp_set_power, ++ .subscribe_event = stf_isp_subscribe_event, ++ .unsubscribe_event = v4l2_event_subdev_unsubscribe, ++}; ++ ++static const struct v4l2_subdev_video_ops isp_video_ops = { ++ .s_stream = isp_set_stream, ++}; ++ ++static const struct v4l2_subdev_pad_ops isp_pad_ops = { ++ .enum_mbus_code = isp_enum_mbus_code, ++ .enum_frame_size = isp_enum_frame_size, ++ .get_fmt = isp_get_format, ++ .set_fmt = isp_set_format, ++ .get_selection = isp_get_selection, ++ .set_selection = isp_set_selection, ++}; ++ ++static const struct v4l2_subdev_ops isp_v4l2_ops = { ++ .core = &isp_core_ops, ++ .video = &isp_video_ops, ++ .pad = &isp_pad_ops, ++}; ++ ++static const struct v4l2_subdev_internal_ops isp_v4l2_internal_ops = { ++ .open = isp_init_formats, ++}; ++ ++static const struct media_entity_operations isp_media_ops = { ++ .link_setup = isp_link_setup, ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev) ++{ ++ struct v4l2_subdev *sd = &isp_dev->subdev; ++ struct media_pad *pads = isp_dev->pads; ++ int ret; ++ ++ v4l2_subdev_init(sd, &isp_v4l2_ops); ++ sd->internal_ops = &isp_v4l2_internal_ops; ++ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; ++ snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", STF_ISP_NAME, 0); ++ v4l2_set_subdevdata(sd, isp_dev); ++ ++ ret = isp_init_formats(sd, NULL); ++ if (ret < 0) { ++ dev_err(isp_dev->stfcamss->dev, "Failed to init format: %d\n", ++ ret); ++ return ret; ++ } ++ ++ pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; ++ pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; ++ ++ sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; ++ sd->entity.ops = &isp_media_ops; ++ ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads); ++ if (ret < 0) { ++ dev_err(isp_dev->stfcamss->dev, ++ "Failed to init media entity: %d\n", ret); ++ return ret; ++ } ++ ++ ret = v4l2_device_register_subdev(v4l2_dev, sd); ++ if (ret < 0) { ++ dev_err(isp_dev->stfcamss->dev, ++ "Failed to register subdev: %d\n", ret); ++ goto err_sreg; ++ } ++ ++ return 0; ++ ++err_sreg: ++ media_entity_cleanup(&sd->entity); ++ return ret; ++} ++ ++int stf_isp_unregister(struct stf_isp_dev *isp_dev) ++{ ++ v4l2_device_unregister_subdev(&isp_dev->subdev); ++ media_entity_cleanup(&isp_dev->subdev.entity); ++ mutex_destroy(&isp_dev->stream_lock); ++ mutex_destroy(&isp_dev->power_lock); ++ return 0; ++} +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_isp.h +@@ -0,0 +1,476 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * stf_isp.h ++ * ++ * StarFive Camera Subsystem - ISP Module ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef STF_ISP_H ++#define STF_ISP_H ++ ++#include ++#include ++ ++#include "stf_video.h" ++ ++#define ISP_RAW_DATA_BITS 12 ++#define SCALER_RATIO_MAX 1 ++#define STF_ISP_REG_OFFSET_MAX 0x0fff ++#define STF_ISP_REG_DELAY_MAX 100 ++ ++/* isp registers */ ++#define ISP_REG_CSI_INPUT_EN_AND_STATUS 0x000 ++#define CSI_SCD_ERR BIT(6) ++#define CSI_ITU656_ERR BIT(4) ++#define CSI_ITU656_F BIT(3) ++#define CSI_SCD_DONE BIT(2) ++#define CSI_BUSY_S BIT(1) ++#define CSI_EN_S BIT(0) ++ ++#define ISP_REG_CSIINTS 0x008 ++#define CSI_INTS(n) ((n) << 16) ++#define CSI_SHA_M(n) ((n) << 0) ++#define CSI_INTS_MASK GENMASK(17, 16) ++ ++#define ISP_REG_CSI_MODULE_CFG 0x010 ++#define CSI_DUMP_EN BIT(19) ++#define CSI_VS_EN BIT(18) ++#define CSI_SC_EN BIT(17) ++#define CSI_OBA_EN BIT(16) ++#define CSI_AWB_EN BIT(7) ++#define CSI_LCCF_EN BIT(6) ++#define CSI_OECFHM_EN BIT(5) ++#define CSI_OECF_EN BIT(4) ++#define CSI_LCBQ_EN BIT(3) ++#define CSI_OBC_EN BIT(2) ++#define CSI_DEC_EN BIT(1) ++#define CSI_DC_EN BIT(0) ++ ++#define ISP_REG_SENSOR 0x014 ++#define DVP_SYNC_POL(n) ((n) << 2) ++#define ITU656_EN(n) ((n) << 1) ++#define IMAGER_SEL(n) ((n) << 0) ++ ++#define ISP_REG_RAW_FORMAT_CFG 0x018 ++#define SMY13(n) ((n) << 14) ++#define SMY12(n) ((n) << 12) ++#define SMY11(n) ((n) << 10) ++#define SMY10(n) ((n) << 8) ++#define SMY3(n) ((n) << 6) ++#define SMY2(n) ((n) << 4) ++#define SMY1(n) ((n) << 2) ++#define SMY0(n) ((n) << 0) ++ ++#define ISP_REG_PIC_CAPTURE_START_CFG 0x01c ++#define VSTART_CAP(n) ((n) << 16) ++#define HSTART_CAP(n) ((n) << 0) ++ ++#define ISP_REG_PIC_CAPTURE_END_CFG 0x020 ++#define VEND_CAP(n) ((n) << 16) ++#define HEND_CAP(n) ((n) << 0) ++ ++#define ISP_REG_DUMP_CFG_0 0x024 ++#define ISP_REG_DUMP_CFG_1 0x028 ++#define DUMP_ID(n) ((n) << 24) ++#define DUMP_SHT(n) ((n) << 20) ++#define DUMP_BURST_LEN(n) ((n) << 16) ++#define DUMP_SD(n) ((n) << 0) ++#define DUMP_BURST_LEN_MASK GENMASK(17, 16) ++#define DUMP_SD_MASK GENMASK(15, 0) ++ ++#define ISP_REG_DEC_CFG 0x030 ++#define DEC_V_KEEP(n) ((n) << 24) ++#define DEC_V_PERIOD(n) ((n) << 16) ++#define DEC_H_KEEP(n) ((n) << 8) ++#define DEC_H_PERIOD(n) ((n) << 0) ++ ++#define ISP_REG_OBC_CFG 0x034 ++#define OBC_W_H(y) ((y) << 4) ++#define OBC_W_W(x) ((x) << 0) ++ ++#define ISP_REG_DC_CFG_1 0x044 ++#define DC_AXI_ID(n) ((n) << 0) ++ ++#define ISP_REG_LCCF_CFG_0 0x050 ++#define Y_DISTANCE(y) ((y) << 16) ++#define X_DISTANCE(x) ((x) << 16) ++ ++#define ISP_REG_LCCF_CFG_1 0x058 ++#define LCCF_MAX_DIS(n) ((n) << 0) ++ ++#define ISP_REG_LCBQ_CFG_0 0x074 ++#define H_LCBQ(y) ((y) << 12) ++#define W_LCBQ(x) ((x) << 8) ++ ++#define ISP_REG_LCBQ_CFG_1 0x07c ++#define Y_COOR(y) ((y) << 16) ++#define X_COOR(x) ((x) << 0) ++ ++#define ISP_REG_OECF_X0_CFG0 0x100 ++#define ISP_REG_OECF_X0_CFG1 0x104 ++#define ISP_REG_OECF_X0_CFG2 0x108 ++#define ISP_REG_OECF_X0_CFG3 0x10c ++#define ISP_REG_OECF_X0_CFG4 0x110 ++#define ISP_REG_OECF_X0_CFG5 0x114 ++#define ISP_REG_OECF_X0_CFG6 0x118 ++#define ISP_REG_OECF_X0_CFG7 0x11c ++ ++#define ISP_REG_OECF_Y3_CFG0 0x1e0 ++#define ISP_REG_OECF_Y3_CFG1 0x1e4 ++#define ISP_REG_OECF_Y3_CFG2 0x1e8 ++#define ISP_REG_OECF_Y3_CFG3 0x1ec ++#define ISP_REG_OECF_Y3_CFG4 0x1f0 ++#define ISP_REG_OECF_Y3_CFG5 0x1f4 ++#define ISP_REG_OECF_Y3_CFG6 0x1f8 ++#define ISP_REG_OECF_Y3_CFG7 0x1fc ++ ++#define ISP_REG_OECF_S0_CFG0 0x200 ++#define ISP_REG_OECF_S3_CFG7 0x27c ++#define OCEF_PAR_H(n) ((n) << 16) ++#define OCEF_PAR_L(n) ((n) << 0) ++ ++#define ISP_REG_AWB_X0_CFG_0 0x280 ++#define ISP_REG_AWB_X0_CFG_1 0x284 ++#define ISP_REG_AWB_X1_CFG_0 0x288 ++#define ISP_REG_AWB_X1_CFG_1 0x28c ++#define ISP_REG_AWB_X2_CFG_0 0x290 ++#define ISP_REG_AWB_X2_CFG_1 0x294 ++#define ISP_REG_AWB_X3_CFG_0 0x298 ++#define ISP_REG_AWB_X3_CFG_1 0x29c ++#define AWB_X_SYMBOL_H(n) ((n) << 16) ++#define AWB_X_SYMBOL_L(n) ((n) << 0) ++ ++#define ISP_REG_AWB_Y0_CFG_0 0x2a0 ++#define ISP_REG_AWB_Y0_CFG_1 0x2a4 ++#define ISP_REG_AWB_Y1_CFG_0 0x2a8 ++#define ISP_REG_AWB_Y1_CFG_1 0x2ac ++#define ISP_REG_AWB_Y2_CFG_0 0x2b0 ++#define ISP_REG_AWB_Y2_CFG_1 0x2b4 ++#define ISP_REG_AWB_Y3_CFG_0 0x2b8 ++#define ISP_REG_AWB_Y3_CFG_1 0x2bc ++#define AWB_Y_SYMBOL_H(n) ((n) << 16) ++#define AWB_Y_SYMBOL_L(n) ((n) << 0) ++ ++#define ISP_REG_AWB_S0_CFG_0 0x2c0 ++#define ISP_REG_AWB_S0_CFG_1 0x2c4 ++#define ISP_REG_AWB_S1_CFG_0 0x2c8 ++#define ISP_REG_AWB_S1_CFG_1 0x2cc ++#define ISP_REG_AWB_S2_CFG_0 0x2d0 ++#define ISP_REG_AWB_S2_CFG_1 0x2d4 ++#define ISP_REG_AWB_S3_CFG_0 0x2d8 ++#define ISP_REG_AWB_S3_CFG_1 0x2dc ++#define AWB_S_SYMBOL_H(n) ((n) << 16) ++#define AWB_S_SYMBOL_L(n) ((n) << 0) ++ ++#define ISP_REG_OBCG_CFG_0 0x2e0 ++#define ISP_REG_OBCG_CFG_1 0x2e4 ++#define ISP_REG_OBCG_CFG_2 0x2e8 ++#define ISP_REG_OBCG_CFG_3 0x2ec ++#define ISP_REG_OBCO_CFG_0 0x2f0 ++#define ISP_REG_OBCO_CFG_1 0x2f4 ++#define ISP_REG_OBCO_CFG_2 0x2f8 ++#define ISP_REG_OBCO_CFG_3 0x2fc ++#define GAIN_D_POINT(x) ((x) << 24) ++#define GAIN_C_POINT(x) ((x) << 16) ++#define GAIN_B_POINT(x) ((x) << 8) ++#define GAIN_A_POINT(x) ((x) << 0) ++#define OFFSET_D_POINT(x) ((x) << 24) ++#define OFFSET_C_POINT(x) ((x) << 16) ++#define OFFSET_B_POINT(x) ((x) << 8) ++#define OFFSET_A_POINT(x) ((x) << 0) ++ ++#define ISP_REG_ISP_CTRL_0 0xa00 ++#define ISPC_SCFEINT BIT(27) ++#define ISPC_VSFWINT BIT(26) ++#define ISPC_VSINT BIT(25) ++#define ISPC_INTS BIT(24) ++#define ISPC_ENUO BIT(20) ++#define ISPC_ENLS BIT(17) ++#define ISPC_ENSS1 BIT(12) ++#define ISPC_ENSS0 BIT(11) ++#define ISPC_RST BIT(1) ++#define ISPC_EN BIT(0) ++#define ISPC_RST_MASK BIT(1) ++ ++#define ISP_REG_ISP_CTRL_1 0xa08 ++#define CTRL_SAT(n) ((n) << 28) ++#define CTRL_DBC BIT(22) ++#define CTRL_CTC BIT(21) ++#define CTRL_YHIST BIT(20) ++#define CTRL_YCURVE BIT(19) ++#define CTRL_CTM BIT(18) ++#define CTRL_BIYUV BIT(17) ++#define CTRL_SCE BIT(8) ++#define CTRL_EE BIT(7) ++#define CTRL_CCE BIT(5) ++#define CTRL_RGE BIT(4) ++#define CTRL_CME BIT(3) ++#define CTRL_AE BIT(2) ++#define CTRL_CE BIT(1) ++#define CTRL_SAT_MASK GENMASK(31, 28) ++ ++#define ISP_REG_PIPELINE_XY_SIZE 0xa0c ++#define H_ACT_CAP(n) ((n) << 16) ++#define W_ACT_CAP(n) ((n) << 0) ++ ++#define ISP_REG_ICTC 0xa10 ++#define GF_MODE(n) ((n) << 30) ++#define MAXGT(n) ((n) << 16) ++#define MINGT(n) ((n) << 0) ++ ++#define ISP_REG_IDBC 0xa14 ++#define BADGT(n) ((n) << 16) ++#define BADXT(n) ((n) << 0) ++ ++#define ISP_REG_ICFAM 0xa1c ++#define CROSS_COV(n) ((n) << 4) ++#define HV_W(n) ((n) << 0) ++ ++#define ISP_REG_CS_GAIN 0xa30 ++#define CMAD(n) ((n) << 16) ++#define CMAB(n) ((n) << 0) ++ ++#define ISP_REG_CS_THRESHOLD 0xa34 ++#define CMD(n) ((n) << 16) ++#define CMB(n) ((n) << 0) ++ ++#define ISP_REG_CS_OFFSET 0xa38 ++#define VOFF(n) ((n) << 16) ++#define UOFF(n) ((n) << 0) ++ ++#define ISP_REG_CS_HUE_F 0xa3c ++#define SIN(n) ((n) << 16) ++#define COS(n) ((n) << 0) ++ ++#define ISP_REG_CS_SCALE 0xa40 ++#define CMSF(n) ((n) << 0) ++ ++#define ISP_REG_IESHD 0xa50 ++#define SHAD_UP_M BIT(1) ++#define SHAD_UP_EN BIT(0) ++ ++#define ISP_REG_YADJ0 0xa54 ++#define YOIR(n) ((n) << 16) ++#define YIMIN(n) ((n) << 0) ++ ++#define ISP_REG_YADJ1 0xa58 ++#define YOMAX(n) ((n) << 16) ++#define YOMIN(n) ((n) << 0) ++ ++#define ISP_REG_Y_PLANE_START_ADDR 0xa80 ++#define ISP_REG_UV_PLANE_START_ADDR 0xa84 ++ ++#define ISP_REG_STRIDE 0xa88 ++#define IMG_STR(n) ((n) << 0) ++ ++#define ISP_REG_ITIIWSR 0xb20 ++#define ITI_HSIZE(n) ((n) << 16) ++#define ITI_WSIZE(n) ((n) << 0) ++ ++#define ISP_REG_ITIDWLSR 0xb24 ++#define ITI_WSTRIDE(n) ((n) << 0) ++ ++#define ISP_REG_ITIPDFR 0xb38 ++#define ITI_PACKAGE_FMT(n) ((n) << 0) ++ ++#define ISP_REG_ITIDRLSR 0xb3C ++#define ITI_STRIDE_L(n) ((n) << 0) ++ ++#define ISP_REG_DNYUV_YSWR0 0xc00 ++#define ISP_REG_DNYUV_YSWR1 0xc04 ++#define ISP_REG_DNYUV_CSWR0 0xc08 ++#define ISP_REG_DNYUV_CSWR1 0xc0c ++#define YUVSW5(n) ((n) << 20) ++#define YUVSW4(n) ((n) << 16) ++#define YUVSW3(n) ((n) << 12) ++#define YUVSW2(n) ((n) << 8) ++#define YUVSW1(n) ((n) << 4) ++#define YUVSW0(n) ((n) << 0) ++ ++#define ISP_REG_DNYUV_YDR0 0xc10 ++#define ISP_REG_DNYUV_YDR1 0xc14 ++#define ISP_REG_DNYUV_YDR2 0xc18 ++#define ISP_REG_DNYUV_CDR0 0xc1c ++#define ISP_REG_DNYUV_CDR1 0xc20 ++#define ISP_REG_DNYUV_CDR2 0xc24 ++#define CURVE_D_H(n) ((n) << 16) ++#define CURVE_D_L(n) ((n) << 0) ++ ++#define ISP_REG_ICAMD_0 0xc40 ++#define DNRM_F(n) ((n) << 16) ++#define ISP_REG_ICAMD_12 0xc70 ++#define ISP_REG_ICAMD_20 0xc90 ++#define ISP_REG_ICAMD_24 0xca0 ++#define ISP_REG_ICAMD_25 0xca4 ++#define CCM_M_DAT(n) ((n) << 0) ++ ++#define ISP_REG_GAMMA_VAL0 0xe00 ++#define ISP_REG_GAMMA_VAL1 0xe04 ++#define ISP_REG_GAMMA_VAL2 0xe08 ++#define ISP_REG_GAMMA_VAL3 0xe0c ++#define ISP_REG_GAMMA_VAL4 0xe10 ++#define ISP_REG_GAMMA_VAL5 0xe14 ++#define ISP_REG_GAMMA_VAL6 0xe18 ++#define ISP_REG_GAMMA_VAL7 0xe1c ++#define ISP_REG_GAMMA_VAL8 0xe20 ++#define ISP_REG_GAMMA_VAL9 0xe24 ++#define ISP_REG_GAMMA_VAL10 0xe28 ++#define ISP_REG_GAMMA_VAL11 0xe2c ++#define ISP_REG_GAMMA_VAL12 0xe30 ++#define ISP_REG_GAMMA_VAL13 0xe34 ++#define ISP_REG_GAMMA_VAL14 0xe38 ++#define GAMMA_S_VAL(n) ((n) << 16) ++#define GAMMA_VAL(n) ((n) << 0) ++ ++#define ISP_REG_R2Y_0 0xe40 ++#define ISP_REG_R2Y_1 0xe44 ++#define ISP_REG_R2Y_2 0xe48 ++#define ISP_REG_R2Y_3 0xe4c ++#define ISP_REG_R2Y_4 0xe50 ++#define ISP_REG_R2Y_5 0xe54 ++#define ISP_REG_R2Y_6 0xe58 ++#define ISP_REG_R2Y_7 0xe5c ++#define ISP_REG_R2Y_8 0xe60 ++#define CSC_M(n) ((n) << 0) ++ ++#define ISP_REG_SHARPEN0 0xe80 ++#define ISP_REG_SHARPEN1 0xe84 ++#define ISP_REG_SHARPEN2 0xe88 ++#define ISP_REG_SHARPEN3 0xe8c ++#define ISP_REG_SHARPEN4 0xe90 ++#define ISP_REG_SHARPEN5 0xe94 ++#define ISP_REG_SHARPEN6 0xe98 ++#define ISP_REG_SHARPEN7 0xe9c ++#define ISP_REG_SHARPEN8 0xea0 ++#define ISP_REG_SHARPEN9 0xea4 ++#define ISP_REG_SHARPEN10 0xea8 ++#define ISP_REG_SHARPEN11 0xeac ++#define ISP_REG_SHARPEN12 0xeb0 ++#define ISP_REG_SHARPEN13 0xeb4 ++#define ISP_REG_SHARPEN14 0xeb8 ++#define S_DELTA(n) ((n) << 16) ++#define S_WEIGHT(n) ((n) << 8) ++ ++#define ISP_REG_SHARPEN_FS0 0xebc ++#define ISP_REG_SHARPEN_FS1 0xec0 ++#define ISP_REG_SHARPEN_FS2 0xec4 ++#define ISP_REG_SHARPEN_FS3 0xec8 ++#define ISP_REG_SHARPEN_FS4 0xecc ++#define ISP_REG_SHARPEN_FS5 0xed0 ++#define S_FACTOR(n) ((n) << 24) ++#define S_SLOPE(n) ((n) << 0) ++ ++#define ISP_REG_SHARPEN_WN 0xed4 ++#define PDIRF(n) ((n) << 28) ++#define NDIRF(n) ((n) << 24) ++#define WSUM(n) ((n) << 0) ++ ++#define ISP_REG_IUVS1 0xed8 ++#define UVDIFF2(n) ((n) << 16) ++#define UVDIFF1(n) ((n) << 0) ++ ++#define ISP_REG_IUVS2 0xedc ++#define UVF(n) ((n) << 24) ++#define UVSLOPE(n) ((n) << 0) ++ ++#define ISP_REG_IUVCKS1 0xee0 ++#define UVCKDIFF2(n) ((n) << 16) ++#define UVCKDIFF1(n) ((n) << 0) ++ ++#define ISP_REG_IUVCKS2 0xee4 ++#define UVCKSLOPE(n) ((n) << 0) ++ ++#define ISP_REG_ISHRPET 0xee8 ++#define TH(n) ((n) << 8) ++#define EN(n) ((n) << 0) ++ ++#define ISP_REG_YCURVE_0 0xf00 ++#define ISP_REG_YCURVE_63 0xffc ++#define L_PARAM(n) ((n) << 0) ++ ++#define IMAGE_MAX_WIDTH 1920 ++#define IMAGE_MAX_HEIGH 1080 ++ ++/* The output line of ISP */ ++enum isp_line_id { ++ STF_ISP_LINE_INVALID = -1, ++ STF_ISP_LINE_SRC = 1, ++ STF_ISP_LINE_MAX = STF_ISP_LINE_SRC ++}; ++ ++/* pad id for media framework */ ++enum isp_pad_id { ++ STF_ISP_PAD_SINK = 0, ++ STF_ISP_PAD_SRC, ++ STF_ISP_PAD_MAX ++}; ++ ++enum { ++ EN_INT_NONE = 0, ++ EN_INT_ISP_DONE = (0x1 << 24), ++ EN_INT_CSI_DONE = (0x1 << 25), ++ EN_INT_SC_DONE = (0x1 << 26), ++ EN_INT_LINE_INT = (0x1 << 27), ++ EN_INT_ALL = (0xF << 24), ++}; ++ ++enum { ++ INTERFACE_DVP = 0, ++ INTERFACE_CSI, ++}; ++ ++struct isp_format { ++ u32 code; ++ u8 bpp; ++}; ++ ++struct isp_format_table { ++ const struct isp_format *fmts; ++ int nfmts; ++}; ++ ++struct regval_t { ++ u32 addr; ++ u32 val; ++ u32 delay_ms; ++}; ++ ++struct reg_table { ++ const struct regval_t *regval; ++ int regval_num; ++}; ++ ++struct stf_isp_crop { ++ struct v4l2_rect rect; ++ u32 bpp; ++}; ++ ++struct stf_isp_dev { ++ enum stf_subdev_type sdev_type; /* This member must be first */ ++ struct stfcamss *stfcamss; ++ struct v4l2_subdev subdev; ++ struct media_pad pads[STF_ISP_PAD_MAX]; ++ struct v4l2_mbus_framefmt fmt[STF_ISP_PAD_MAX]; ++ struct stf_isp_crop rect[STF_ISP_PAD_MAX]; ++ const struct isp_format_table *formats; ++ unsigned int nformats; ++ struct mutex power_lock; /* serialize power control*/ ++ int power_count; ++ struct mutex stream_lock; /* serialize stream control */ ++ int stream_count; ++}; ++ ++int stf_isp_clk_enable(struct stf_isp_dev *isp_dev); ++int stf_isp_clk_disable(struct stf_isp_dev *isp_dev); ++int stf_isp_reset(struct stf_isp_dev *isp_dev); ++void stf_isp_init_cfg(struct stf_isp_dev *isp_dev); ++void stf_isp_settings(struct stf_isp_dev *isp_dev, ++ struct stf_isp_crop *crop_array, u32 mcode); ++void stf_isp_stream_set(struct stf_isp_dev *isp_dev); ++int stf_isp_subdev_init(struct stfcamss *stfcamss); ++int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev); ++int stf_isp_unregister(struct stf_isp_dev *isp_dev); ++ ++#endif /* STF_ISP_H */ +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_isp_hw_ops.c +@@ -0,0 +1,452 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_isp_hw_ops.c ++ * ++ * Register interface file for StarFive ISP driver ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ * ++ */ ++ ++#include "stf_camss.h" ++ ++static void stf_isp_config_obc(struct stfcamss *stfcamss) ++{ ++ u32 reg_val, reg_add; ++ ++ stf_isp_reg_write(stfcamss, ISP_REG_OBC_CFG, OBC_W_H(11) | OBC_W_W(11)); ++ ++ reg_val = GAIN_D_POINT(0x40) | GAIN_C_POINT(0x40) | ++ GAIN_B_POINT(0x40) | GAIN_A_POINT(0x40); ++ for (reg_add = ISP_REG_OBCG_CFG_0; reg_add <= ISP_REG_OBCG_CFG_3;) { ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ } ++ ++ reg_val = OFFSET_D_POINT(0) | OFFSET_C_POINT(0) | ++ OFFSET_B_POINT(0) | OFFSET_A_POINT(0); ++ for (reg_add = ISP_REG_OBCO_CFG_0; reg_add <= ISP_REG_OBCO_CFG_3;) { ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ } ++} ++ ++static void stf_isp_config_oecf(struct stfcamss *stfcamss) ++{ ++ u32 reg_add, par_val; ++ u16 par_h, par_l; ++ ++ par_h = 0x10; par_l = 0; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG0; reg_add <= ISP_REG_OECF_Y3_CFG0;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x40; par_l = 0x20; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG1; reg_add <= ISP_REG_OECF_Y3_CFG1;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x80; par_l = 0x60; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG2; reg_add <= ISP_REG_OECF_Y3_CFG2;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0xc0; par_l = 0xa0; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG3; reg_add <= ISP_REG_OECF_Y3_CFG3;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x100; par_l = 0xe0; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG4; reg_add <= ISP_REG_OECF_Y3_CFG4;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x200; par_l = 0x180; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG5; reg_add <= ISP_REG_OECF_Y3_CFG5;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x300; par_l = 0x280; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG6; reg_add <= ISP_REG_OECF_Y3_CFG6;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x3fe; par_l = 0x380; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_X0_CFG7; reg_add <= ISP_REG_OECF_Y3_CFG7;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 0x20; ++ } ++ ++ par_h = 0x80; par_l = 0x80; ++ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l); ++ for (reg_add = ISP_REG_OECF_S0_CFG0; reg_add <= ISP_REG_OECF_S3_CFG7;) { ++ stf_isp_reg_write(stfcamss, reg_add, par_val); ++ reg_add += 4; ++ } ++} ++ ++static void stf_isp_config_awb(struct stfcamss *stfcamss) ++{ ++ u32 reg_val, reg_add; ++ u16 symbol_h, symbol_l; ++ ++ symbol_h = 0x0; symbol_l = 0x0; ++ reg_val = AWB_X_SYMBOL_H(symbol_h) | AWB_X_SYMBOL_L(symbol_l); ++ ++ for (reg_add = ISP_REG_AWB_X0_CFG_0; reg_add <= ISP_REG_AWB_X3_CFG_1;) { ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ } ++ ++ symbol_h = 0x0, symbol_l = 0x0; ++ reg_val = AWB_Y_SYMBOL_H(symbol_h) | AWB_Y_SYMBOL_L(symbol_l); ++ ++ for (reg_add = ISP_REG_AWB_Y0_CFG_0; reg_add <= ISP_REG_AWB_Y3_CFG_1;) { ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ } ++ ++ symbol_h = 0x80, symbol_l = 0x80; ++ reg_val = AWB_S_SYMBOL_H(symbol_h) | AWB_S_SYMBOL_L(symbol_l); ++ ++ for (reg_add = ISP_REG_AWB_S0_CFG_0; reg_add <= ISP_REG_AWB_S3_CFG_1;) { ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ } ++} ++ ++static void stf_isp_config_grgb(struct stfcamss *stfcamss) ++{ ++ stf_isp_reg_write(stfcamss, ISP_REG_ICTC, ++ GF_MODE(1) | MAXGT(0x140) | MINGT(0x40)); ++ stf_isp_reg_write(stfcamss, ISP_REG_IDBC, BADGT(0x200) | BADXT(0x200)); ++} ++ ++static void stf_isp_config_cfa(struct stfcamss *stfcamss) ++{ ++ stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, ++ SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | SMY3(2) | ++ SMY2(3) | SMY1(2) | SMY0(3)); ++ stf_isp_reg_write(stfcamss, ISP_REG_ICFAM, CROSS_COV(3) | HV_W(2)); ++} ++ ++static void stf_isp_config_ccm(struct stfcamss *stfcamss) ++{ ++ u32 reg_add; ++ ++ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_0, DNRM_F(6) | CCM_M_DAT(0)); ++ ++ for (reg_add = ISP_REG_ICAMD_12; reg_add <= ISP_REG_ICAMD_20;) { ++ stf_isp_reg_write(stfcamss, reg_add, CCM_M_DAT(0x80)); ++ reg_add += 0x10; ++ } ++ ++ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_24, CCM_M_DAT(0x700)); ++ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_25, CCM_M_DAT(0x200)); ++} ++ ++static void stf_isp_config_gamma(struct stfcamss *stfcamss) ++{ ++ u32 reg_val, reg_add; ++ u16 gamma_slope_v, gamma_v; ++ ++ gamma_slope_v = 0x2400; gamma_v = 0x0; ++ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v); ++ stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL0, reg_val); ++ ++ gamma_slope_v = 0x800; gamma_v = 0x20; ++ for (reg_add = ISP_REG_GAMMA_VAL1; reg_add <= ISP_REG_GAMMA_VAL7;) { ++ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v); ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ gamma_v += 0x20; ++ } ++ ++ gamma_v = 0x100; ++ for (reg_add = ISP_REG_GAMMA_VAL8; reg_add <= ISP_REG_GAMMA_VAL13;) { ++ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v); ++ stf_isp_reg_write(stfcamss, reg_add, reg_val); ++ reg_add += 4; ++ gamma_v += 0x80; ++ } ++ ++ gamma_v = 0x3fe; ++ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v); ++ stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL14, reg_val); ++} ++ ++static void stf_isp_config_r2y(struct stfcamss *stfcamss) ++{ ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_0, CSC_M(0x4C)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_1, CSC_M(0x97)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_2, CSC_M(0x1d)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_3, CSC_M(0x1d5)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_4, CSC_M(0x1ac)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_5, CSC_M(0x80)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_6, CSC_M(0x80)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_7, CSC_M(0x194)); ++ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_8, CSC_M(0x1ec)); ++} ++ ++static void stf_isp_config_y_curve(struct stfcamss *stfcamss) ++{ ++ u32 reg_add; ++ u16 y_curve; ++ ++ y_curve = 0x0; ++ for (reg_add = ISP_REG_YCURVE_0; reg_add <= ISP_REG_YCURVE_63;) { ++ stf_isp_reg_write(stfcamss, reg_add, y_curve); ++ reg_add += 4; ++ y_curve += 0x10; ++ } ++} ++ ++static void stf_isp_config_sharpen(struct stfcamss *sc) ++{ ++ u32 reg_add; ++ ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN0, S_DELTA(0x7) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN1, S_DELTA(0x18) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN2, S_DELTA(0x80) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN3, S_DELTA(0x100) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN4, S_DELTA(0x10) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN5, S_DELTA(0x60) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN6, S_DELTA(0x100) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN7, S_DELTA(0x190) | S_WEIGHT(0xf)); ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN8, S_DELTA(0x0) | S_WEIGHT(0xf)); ++ ++ for (reg_add = ISP_REG_SHARPEN9; reg_add <= ISP_REG_SHARPEN14;) { ++ stf_isp_reg_write(sc, reg_add, S_WEIGHT(0xf)); ++ reg_add += 4; ++ } ++ ++ for (reg_add = ISP_REG_SHARPEN_FS0; reg_add <= ISP_REG_SHARPEN_FS5;) { ++ stf_isp_reg_write(sc, reg_add, S_FACTOR(0x10) | S_SLOPE(0x0)); ++ reg_add += 4; ++ } ++ ++ stf_isp_reg_write(sc, ISP_REG_SHARPEN_WN, ++ PDIRF(0x8) | NDIRF(0x8) | WSUM(0xd7c)); ++ stf_isp_reg_write(sc, ISP_REG_IUVS1, UVDIFF2(0xC0) | UVDIFF1(0x40)); ++ stf_isp_reg_write(sc, ISP_REG_IUVS2, UVF(0xff) | UVSLOPE(0x0)); ++ stf_isp_reg_write(sc, ISP_REG_IUVCKS1, ++ UVCKDIFF2(0xa0) | UVCKDIFF1(0x40)); ++} ++ ++static void stf_isp_config_dnyuv(struct stfcamss *stfcamss) ++{ ++ u32 reg_val; ++ ++ reg_val = YUVSW5(7) | YUVSW4(7) | YUVSW3(7) | YUVSW2(7) | ++ YUVSW1(7) | YUVSW0(7); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR0, reg_val); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR0, reg_val); ++ ++ reg_val = YUVSW3(7) | YUVSW2(7) | YUVSW1(7) | YUVSW0(7); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR1, reg_val); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR1, reg_val); ++ ++ reg_val = CURVE_D_H(0x60) | CURVE_D_L(0x40); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR0, reg_val); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR0, reg_val); ++ ++ reg_val = CURVE_D_H(0xd8) | CURVE_D_L(0x90); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR1, reg_val); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR1, reg_val); ++ ++ reg_val = CURVE_D_H(0x1e6) | CURVE_D_L(0x144); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR2, reg_val); ++ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR2, reg_val); ++} ++ ++static void stf_isp_config_sat(struct stfcamss *stfcamss) ++{ ++ stf_isp_reg_write(stfcamss, ISP_REG_CS_GAIN, CMAD(0x0) | CMAB(0x100)); ++ stf_isp_reg_write(stfcamss, ISP_REG_CS_THRESHOLD, CMD(0x1f) | CMB(0x1)); ++ stf_isp_reg_write(stfcamss, ISP_REG_CS_OFFSET, VOFF(0x0) | UOFF(0x0)); ++ stf_isp_reg_write(stfcamss, ISP_REG_CS_HUE_F, SIN(0x0) | COS(0x100)); ++ stf_isp_reg_write(stfcamss, ISP_REG_CS_SCALE, CMSF(0x8)); ++ stf_isp_reg_write(stfcamss, ISP_REG_YADJ0, YOIR(0x401) | YIMIN(0x1)); ++ stf_isp_reg_write(stfcamss, ISP_REG_YADJ1, YOMAX(0x3ff) | YOMIN(0x1)); ++} ++ ++int stf_isp_clk_enable(struct stf_isp_dev *isp_dev) ++{ ++ struct stfcamss *stfcamss = isp_dev->stfcamss; ++ ++ clk_prepare_enable(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk); ++ reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc); ++ reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc); ++ ++ return 0; ++} ++ ++int stf_isp_clk_disable(struct stf_isp_dev *isp_dev) ++{ ++ struct stfcamss *stfcamss = isp_dev->stfcamss; ++ ++ reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc); ++ reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc); ++ clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk); ++ ++ return 0; ++} ++ ++int stf_isp_reset(struct stf_isp_dev *isp_dev) ++{ ++ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0, ++ ISPC_RST_MASK, ISPC_RST); ++ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0, ++ ISPC_RST_MASK, 0); ++ ++ return 0; ++} ++ ++void stf_isp_init_cfg(struct stf_isp_dev *isp_dev) ++{ ++ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DC_CFG_1, DC_AXI_ID(0x0)); ++ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DEC_CFG, ++ DEC_V_KEEP(0x0) | ++ DEC_V_PERIOD(0x0) | ++ DEC_H_KEEP(0x0) | ++ DEC_H_PERIOD(0x0)); ++ ++ stf_isp_config_obc(isp_dev->stfcamss); ++ stf_isp_config_oecf(isp_dev->stfcamss); ++ stf_isp_config_awb(isp_dev->stfcamss); ++ stf_isp_config_grgb(isp_dev->stfcamss); ++ stf_isp_config_cfa(isp_dev->stfcamss); ++ stf_isp_config_ccm(isp_dev->stfcamss); ++ stf_isp_config_gamma(isp_dev->stfcamss); ++ stf_isp_config_r2y(isp_dev->stfcamss); ++ stf_isp_config_y_curve(isp_dev->stfcamss); ++ stf_isp_config_sharpen(isp_dev->stfcamss); ++ stf_isp_config_dnyuv(isp_dev->stfcamss); ++ stf_isp_config_sat(isp_dev->stfcamss); ++ ++ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_CSI_MODULE_CFG, ++ CSI_DUMP_EN | CSI_SC_EN | CSI_AWB_EN | ++ CSI_LCCF_EN | CSI_OECF_EN | CSI_OBC_EN | CSI_DEC_EN); ++ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_ISP_CTRL_1, ++ CTRL_SAT(1) | CTRL_DBC | CTRL_CTC | CTRL_YHIST | ++ CTRL_YCURVE | CTRL_BIYUV | CTRL_SCE | CTRL_EE | ++ CTRL_CCE | CTRL_RGE | CTRL_CME | CTRL_AE | CTRL_CE); ++} ++ ++static void stf_isp_config_crop(struct stfcamss *stfcamss, ++ struct stf_isp_crop *crop) ++{ ++ struct v4l2_rect *rect = &crop[STF_ISP_PAD_SRC].rect; ++ u32 bpp = crop[STF_ISP_PAD_SRC].bpp; ++ u32 val; ++ ++ val = VSTART_CAP(rect->top) | HSTART_CAP(rect->left); ++ stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_START_CFG, val); ++ ++ val = VEND_CAP(rect->height + rect->top - 1) | ++ HEND_CAP(rect->width + rect->left - 1); ++ stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_END_CFG, val); ++ ++ val = H_ACT_CAP(rect->height) | W_ACT_CAP(rect->width); ++ stf_isp_reg_write(stfcamss, ISP_REG_PIPELINE_XY_SIZE, val); ++ ++ val = ALIGN(rect->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8); ++ stf_isp_reg_write(stfcamss, ISP_REG_STRIDE, val); ++} ++ ++static void stf_isp_config_raw_fmt(struct stfcamss *stfcamss, u32 mcode) ++{ ++ u32 val, val1; ++ ++ switch (mcode) { ++ case MEDIA_BUS_FMT_SRGGB10_1X10: ++ case MEDIA_BUS_FMT_SRGGB8_1X8: ++ /* 3 2 3 2 1 0 1 0 B Gb B Gb Gr R Gr R */ ++ val = SMY13(3) | SMY12(2) | SMY11(3) | SMY10(2) | ++ SMY3(1) | SMY2(0) | SMY1(1) | SMY0(0); ++ val1 = CTRL_SAT(0x0); ++ break; ++ case MEDIA_BUS_FMT_SGRBG10_1X10: ++ case MEDIA_BUS_FMT_SGRBG8_1X8: ++ /* 2 3 2 3 0 1 0 1, Gb B Gb B R Gr R Gr */ ++ val = SMY13(2) | SMY12(3) | SMY11(2) | SMY10(3) | ++ SMY3(0) | SMY2(1) | SMY1(0) | SMY0(1); ++ val1 = CTRL_SAT(0x2); ++ break; ++ case MEDIA_BUS_FMT_SGBRG10_1X10: ++ case MEDIA_BUS_FMT_SGBRG8_1X8: ++ /* 1 0 1 0 3 2 3 2, Gr R Gr R B Gb B Gb */ ++ val = SMY13(1) | SMY12(0) | SMY11(1) | SMY10(0) | ++ SMY3(3) | SMY2(2) | SMY1(3) | SMY0(2); ++ val1 = CTRL_SAT(0x3); ++ break; ++ case MEDIA_BUS_FMT_SBGGR10_1X10: ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ /* 0 1 0 1 2 3 2 3 R Gr R Gr Gb B Gb B */ ++ val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | ++ SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3); ++ val1 = CTRL_SAT(0x1); ++ break; ++ default: ++ val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | ++ SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3); ++ val1 = CTRL_SAT(0x1); ++ break; ++ } ++ stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, val); ++ stf_isp_reg_set_bit(stfcamss, ISP_REG_ISP_CTRL_1, CTRL_SAT_MASK, val1); ++} ++ ++void stf_isp_settings(struct stf_isp_dev *isp_dev, ++ struct stf_isp_crop *crop, u32 mcode) ++{ ++ struct stfcamss *stfcamss = isp_dev->stfcamss; ++ ++ stf_isp_config_crop(stfcamss, crop); ++ stf_isp_config_raw_fmt(stfcamss, mcode); ++ ++ stf_isp_reg_set_bit(stfcamss, ISP_REG_DUMP_CFG_1, ++ DUMP_BURST_LEN_MASK | DUMP_SD_MASK, ++ DUMP_BURST_LEN(3)); ++ ++ stf_isp_reg_write(stfcamss, ISP_REG_ITIIWSR, ++ ITI_HSIZE(IMAGE_MAX_HEIGH) | ++ ITI_WSIZE(IMAGE_MAX_WIDTH)); ++ stf_isp_reg_write(stfcamss, ISP_REG_ITIDWLSR, ITI_WSTRIDE(0x960)); ++ stf_isp_reg_write(stfcamss, ISP_REG_ITIDRLSR, ITI_STRIDE_L(0x960)); ++ stf_isp_reg_write(stfcamss, ISP_REG_SENSOR, 0x1); ++} ++ ++void stf_isp_stream_set(struct stf_isp_dev *isp_dev) ++{ ++ struct stfcamss *stfcamss = isp_dev->stfcamss; ++ ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0, ++ ISPC_ENUO | ISPC_ENLS | ISPC_RST, 10); ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0, ++ ISPC_ENUO | ISPC_ENLS, 10); ++ stf_isp_reg_write(stfcamss, ISP_REG_IESHD, SHAD_UP_M); ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0, ++ ISPC_ENUO | ISPC_ENLS | ISPC_EN, 10); ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS, ++ CSI_INTS(1) | CSI_SHA_M(4), 10); ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS, ++ CSI_INTS(2) | CSI_SHA_M(4), 10); ++ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSI_INPUT_EN_AND_STATUS, ++ CSI_EN_S, 10); ++} diff --git a/target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch b/target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch new file mode 100644 index 0000000000..2ab822ae96 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch @@ -0,0 +1,1694 @@ +From 030f0312433a85899fab4dccada5b2cbceb3bad5 Mon Sep 17 00:00:00 2001 +From: Jack Zhu +Date: Fri, 12 May 2023 18:28:44 +0800 +Subject: [PATCH 086/122] media: starfive: Add VIN driver + +Add Video In Controller driver for StarFive Camera Subsystem. + +Signed-off-by: Jack Zhu +--- + drivers/media/platform/starfive/Makefile | 4 +- + drivers/media/platform/starfive/stf_camss.c | 39 +- + drivers/media/platform/starfive/stf_camss.h | 2 + + drivers/media/platform/starfive/stf_vin.c | 1134 +++++++++++++++++ + drivers/media/platform/starfive/stf_vin.h | 180 +++ + .../media/platform/starfive/stf_vin_hw_ops.c | 241 ++++ + 6 files changed, 1598 insertions(+), 2 deletions(-) + create mode 100644 drivers/media/platform/starfive/stf_vin.c + create mode 100644 drivers/media/platform/starfive/stf_vin.h + create mode 100644 drivers/media/platform/starfive/stf_vin_hw_ops.c + +--- a/drivers/media/platform/starfive/Makefile ++++ b/drivers/media/platform/starfive/Makefile +@@ -7,6 +7,8 @@ starfive-camss-objs += \ + stf_camss.o \ + stf_isp.o \ + stf_isp_hw_ops.o \ +- stf_video.o ++ stf_video.o \ ++ stf_vin.o \ ++ stf_vin_hw_ops.o + + obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \ +--- a/drivers/media/platform/starfive/stf_camss.c ++++ b/drivers/media/platform/starfive/stf_camss.c +@@ -142,27 +142,61 @@ static int stfcamss_init_subdevices(stru + return ret; + } + ++ ret = stf_vin_subdev_init(stfcamss); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, "Failed to init vin subdev: %d\n", ret); ++ return ret; ++ } + return ret; + } + + static int stfcamss_register_subdevices(struct stfcamss *stfcamss) + { + int ret; ++ struct stf_vin_dev *vin_dev = &stfcamss->vin_dev; + struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; + + ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev); + if (ret < 0) { + dev_err(stfcamss->dev, + "Failed to register stf isp%d entity: %d\n", 0, ret); +- return ret; ++ goto err_reg_isp; ++ } ++ ++ ret = stf_vin_register(vin_dev, &stfcamss->v4l2_dev); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, ++ "Failed to register vin entity: %d\n", ret); ++ goto err_reg_vin; + } + ++ ret = media_create_pad_link(&isp_dev->subdev.entity, ++ STF_ISP_PAD_SRC, ++ &vin_dev->line[VIN_LINE_ISP].subdev.entity, ++ STF_VIN_PAD_SINK, ++ 0); ++ if (ret < 0) { ++ dev_err(stfcamss->dev, ++ "Failed to link %s->%s entities: %d\n", ++ isp_dev->subdev.entity.name, ++ vin_dev->line[VIN_LINE_ISP].subdev.entity.name, ret); ++ goto err_link; ++ } ++ ++ return ret; ++ ++err_link: ++ stf_vin_unregister(&stfcamss->vin_dev); ++err_reg_vin: ++ stf_isp_unregister(&stfcamss->isp_dev); ++err_reg_isp: + return ret; + } + + static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss) + { + stf_isp_unregister(&stfcamss->isp_dev); ++ stf_vin_unregister(&stfcamss->vin_dev); + } + + static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async, +@@ -175,11 +209,14 @@ static int stfcamss_subdev_notifier_boun + container_of(asd, struct stfcamss_async_subdev, asd); + enum port_num port = csd->port; + struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; ++ struct stf_vin_dev *vin_dev = &stfcamss->vin_dev; + struct host_data *host_data = &stfcamss->host_data; + struct media_entity *source; + int i, j; + + if (port == PORT_NUMBER_CSI2RX) { ++ host_data->host_entity[0] = ++ &vin_dev->line[VIN_LINE_WR].subdev.entity; + host_data->host_entity[1] = &isp_dev->subdev.entity; + } else if (port == PORT_NUMBER_DVP_SENSOR) { + dev_err(stfcamss->dev, "Not support DVP sensor\n"); +--- a/drivers/media/platform/starfive/stf_camss.h ++++ b/drivers/media/platform/starfive/stf_camss.h +@@ -17,6 +17,7 @@ + + #include "stf_common.h" + #include "stf_isp.h" ++#include "stf_vin.h" + + #define DRV_NAME "starfive-camss" + #define STF_DVP_NAME "stf_dvp" +@@ -72,6 +73,7 @@ struct stfcamss { + struct media_device media_dev; + struct media_pipeline pipe; + struct device *dev; ++ struct stf_vin_dev vin_dev; + struct stf_isp_dev isp_dev; + struct v4l2_async_notifier notifier; + struct host_data host_data; +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_vin.c +@@ -0,0 +1,1134 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_vin.c ++ * ++ * StarFive Camera Subsystem - VIN Module ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++#include ++ ++#include "stf_camss.h" ++ ++#define vin_line_array(ptr_line) \ ++ ((const struct vin_line (*)[]) &(ptr_line)[-((ptr_line)->id)]) ++ ++#define line_to_vin_dev(ptr_line) \ ++ container_of(vin_line_array(ptr_line), struct stf_vin_dev, line) ++ ++#define VIN_FRAME_DROP_MAX_VAL 90 ++#define VIN_FRAME_DROP_MIN_VAL 4 ++#define VIN_FRAME_PER_SEC_MAX_VAL 90 ++ ++/* ISP ctrl need 1 sec to let frames become stable. */ ++#define VIN_FRAME_DROP_SEC_FOR_ISP_CTRL 1 ++ ++static const struct vin_format vin_formats_wr[] = { ++ { MEDIA_BUS_FMT_SRGGB10_1X10, 10}, ++ { MEDIA_BUS_FMT_SGRBG10_1X10, 10}, ++ { MEDIA_BUS_FMT_SGBRG10_1X10, 10}, ++ { MEDIA_BUS_FMT_SBGGR10_1X10, 10}, ++}; ++ ++static const struct vin_format vin_formats_uo[] = { ++ { MEDIA_BUS_FMT_Y12_1X12, 8}, ++}; ++ ++static const struct vin_format_table vin_formats_table[] = { ++ /* VIN_LINE_WR */ ++ { vin_formats_wr, ARRAY_SIZE(vin_formats_wr) }, ++ /* VIN_LINE_ISP */ ++ { vin_formats_uo, ARRAY_SIZE(vin_formats_uo) }, ++}; ++ ++static void vin_buffer_done(struct vin_line *line); ++static void vin_change_buffer(struct vin_line *line); ++static struct stfcamss_buffer *vin_buf_get_pending(struct vin_output *output); ++static void vin_output_init_addrs(struct vin_line *line); ++static void vin_init_outputs(struct vin_line *line); ++static struct v4l2_mbus_framefmt * ++__vin_get_format(struct vin_line *line, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ enum v4l2_subdev_format_whence which); ++ ++static char *vin_get_line_subdevname(int line_id) ++{ ++ char *name = NULL; ++ ++ switch (line_id) { ++ case VIN_LINE_WR: ++ name = "wr"; ++ break; ++ case VIN_LINE_ISP: ++ name = "isp0"; ++ break; ++ default: ++ name = "unknown"; ++ break; ++ } ++ return name; ++} ++ ++static enum isp_line_id vin_map_isp_line(enum vin_line_id line) ++{ ++ enum isp_line_id line_id; ++ ++ if (line > VIN_LINE_WR && line < VIN_LINE_MAX) ++ line_id = STF_ISP_LINE_SRC; ++ else ++ line_id = STF_ISP_LINE_INVALID; ++ ++ return line_id; ++} ++ ++enum isp_pad_id stf_vin_map_isp_pad(enum vin_line_id line, enum isp_pad_id def) ++{ ++ enum isp_pad_id pad_id; ++ ++ if (line == VIN_LINE_WR) ++ pad_id = STF_ISP_PAD_SINK; ++ else if ((line > VIN_LINE_WR) && (line < VIN_LINE_MAX)) ++ pad_id = (enum isp_pad_id)vin_map_isp_line(line); ++ else ++ pad_id = def; ++ ++ return pad_id; ++} ++ ++int stf_vin_subdev_init(struct stfcamss *stfcamss) ++{ ++ struct device *dev = stfcamss->dev; ++ struct stf_vin_dev *vin_dev = &stfcamss->vin_dev; ++ int i, ret = 0; ++ ++ vin_dev->stfcamss = stfcamss; ++ ++ vin_dev->isr_ops = devm_kzalloc(dev, sizeof(*vin_dev->isr_ops), ++ GFP_KERNEL); ++ if (!vin_dev->isr_ops) ++ return -ENOMEM; ++ vin_dev->isr_ops->isr_buffer_done = vin_buffer_done; ++ vin_dev->isr_ops->isr_change_buffer = vin_change_buffer; ++ ++ atomic_set(&vin_dev->ref_count, 0); ++ ++ ret = devm_request_irq(dev, ++ stfcamss->irq[STF_IRQ_VINWR], ++ stf_vin_wr_irq_handler, ++ 0, "vin_axiwr_irq", vin_dev); ++ if (ret) { ++ dev_err(dev, "Failed to request irq\n"); ++ goto out; ++ } ++ ++ ret = devm_request_irq(dev, ++ stfcamss->irq[STF_IRQ_ISP], ++ stf_vin_isp_irq_handler, ++ 0, "vin_isp_irq", vin_dev); ++ if (ret) { ++ dev_err(dev, "Failed to request isp irq\n"); ++ goto out; ++ } ++ ++ ret = devm_request_irq(dev, ++ stfcamss->irq[STF_IRQ_ISPCSIL], ++ stf_vin_isp_irq_csiline_handler, ++ 0, "vin_isp_irq_csiline", vin_dev); ++ if (ret) { ++ dev_err(dev, "failed to request isp irq csiline\n"); ++ goto out; ++ } ++ ++ mutex_init(&vin_dev->power_lock); ++ vin_dev->power_count = 0; ++ ++ for (i = 0; i < STF_DUMMY_MODULE_NUMS; i++) { ++ struct dummy_buffer *dummy_buffer = &vin_dev->dummy_buffer[i]; ++ ++ mutex_init(&dummy_buffer->stream_lock); ++ dummy_buffer->nums = ++ i == 0 ? VIN_DUMMY_BUFFER_NUMS : ISP_DUMMY_BUFFER_NUMS; ++ dummy_buffer->stream_count = 0; ++ dummy_buffer->buffer = ++ devm_kzalloc(dev, ++ dummy_buffer->nums * sizeof(struct vin_dummy_buffer), ++ GFP_KERNEL); ++ atomic_set(&dummy_buffer->frame_skip, 0); ++ } ++ ++ for (i = VIN_LINE_WR; i < STF_ISP_LINE_MAX + 1; i++) { ++ struct vin_line *l = &vin_dev->line[i]; ++ ++ l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ l->video_out.stfcamss = stfcamss; ++ l->id = i; ++ l->sdev_type = STF_SUBDEV_TYPE_VIN; ++ l->formats = vin_formats_table[i].fmts; ++ l->nformats = vin_formats_table[i].nfmts; ++ spin_lock_init(&l->output_lock); ++ ++ mutex_init(&l->stream_lock); ++ l->stream_count = 0; ++ mutex_init(&l->power_lock); ++ l->power_count = 0; ++ } ++ ++ return 0; ++out: ++ return ret; ++} ++ ++static enum link vin_get_link(struct media_entity *entity) ++{ ++ struct v4l2_subdev *subdev; ++ struct media_pad *pad; ++ bool isp = false; ++ ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ return LINK_ERROR; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ return LINK_ERROR; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ ++ if (!strncmp(subdev->name, STF_CSI_NAME, ++ strlen(STF_CSI_NAME))) { ++ if (isp) ++ return LINK_CSI_TO_ISP; ++ else ++ return LINK_CSI_TO_WR; ++ } else if (!strncmp(subdev->name, STF_DVP_NAME, ++ strlen(STF_DVP_NAME))) { ++ if (isp) ++ return LINK_DVP_TO_ISP; ++ else ++ return LINK_DVP_TO_WR; ++ } else if (!strncmp(subdev->name, STF_ISP_NAME, ++ strlen(STF_ISP_NAME))) { ++ isp = true; ++ } else { ++ return LINK_ERROR; ++ } ++ } ++} ++ ++static int vin_set_power(struct v4l2_subdev *sd, int on) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ struct stf_vin_dev *vin_dev = line_to_vin_dev(line); ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ enum link link; ++ ++ mutex_lock(&line->power_lock); ++ if (on) { ++ if (line->power_count == 0) ++ vin_init_outputs(line); ++ line->power_count++; ++ } else { ++ if (line->power_count == 0) { ++ dev_err(stfcamss->dev, ++ "line power off on power_count = 0\n"); ++ goto exit_line; ++ } ++ line->power_count--; ++ } ++exit_line: ++ mutex_unlock(&line->power_lock); ++ ++ mutex_lock(&vin_dev->power_lock); ++ link = vin_get_link(&sd->entity); ++ if (link == LINK_ERROR) ++ goto exit; ++ ++ if (on) { ++ if (vin_dev->power_count == 0) { ++ pm_runtime_get_sync(stfcamss->dev); ++ stf_vin_clk_enable(vin_dev, link); ++ } ++ vin_dev->power_count++; ++ } else { ++ if (vin_dev->power_count == 0) { ++ dev_err(stfcamss->dev, ++ "vin_dev power off on power_count=0\n"); ++ goto exit; ++ } ++ if (vin_dev->power_count == 1) { ++ stf_vin_clk_disable(vin_dev, link); ++ pm_runtime_put_sync(stfcamss->dev); ++ } ++ vin_dev->power_count--; ++ } ++exit: ++ ++ mutex_unlock(&vin_dev->power_lock); ++ ++ return 0; ++} ++ ++static int vin_enable_output(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ output->state = VIN_OUTPUT_IDLE; ++ ++ output->buf[0] = vin_buf_get_pending(output); ++ ++ if (!output->buf[0] && output->buf[1]) { ++ output->buf[0] = output->buf[1]; ++ output->buf[1] = NULL; ++ } ++ ++ if (output->buf[0]) ++ output->state = VIN_OUTPUT_SINGLE; ++ ++ output->sequence = 0; ++ ++ vin_output_init_addrs(line); ++ spin_unlock_irqrestore(&line->output_lock, flags); ++ return 0; ++} ++ ++static int vin_disable_output(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ output->state = VIN_OUTPUT_OFF; ++ ++ spin_unlock_irqrestore(&line->output_lock, flags); ++ return 0; ++} ++ ++static u32 vin_line_to_dummy_module(struct vin_line *line) ++{ ++ u32 dummy_module = 0; ++ ++ switch (line->id) { ++ case VIN_LINE_WR: ++ dummy_module = STF_DUMMY_VIN; ++ break; ++ case VIN_LINE_ISP: ++ dummy_module = STF_DUMMY_ISP; ++ break; ++ default: ++ dummy_module = STF_DUMMY_VIN; ++ break; ++ } ++ ++ return dummy_module; ++} ++ ++static int vin_alloc_dummy_buffer(struct stf_vin_dev *vin_dev, ++ struct v4l2_mbus_framefmt *fmt, ++ int dummy_module) ++{ ++ struct device *dev = vin_dev->stfcamss->dev; ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[dummy_module]; ++ struct vin_dummy_buffer *buffer = NULL; ++ int ret = 0, i; ++ u32 aligns; ++ ++ for (i = 0; i < dummy_buffer->nums; i++) { ++ buffer = &vin_dev->dummy_buffer[dummy_module].buffer[i]; ++ buffer->width = fmt->width; ++ buffer->height = fmt->height; ++ buffer->mcode = fmt->code; ++ if (i == STF_VIN_PAD_SINK) { ++ aligns = ALIGN(fmt->width * 4, ++ STFCAMSS_FRAME_WIDTH_ALIGN_8); ++ buffer->buffer_size = PAGE_ALIGN(aligns * fmt->height); ++ } else if (i == STF_ISP_PAD_SRC) { ++ aligns = ALIGN(fmt->width, ++ STFCAMSS_FRAME_WIDTH_ALIGN_8); ++ buffer->buffer_size = ++ PAGE_ALIGN(aligns * fmt->height * 3 / 2); ++ } else { ++ continue; ++ } ++ ++ buffer->vaddr = dma_alloc_coherent(dev, ++ buffer->buffer_size, ++ &buffer->paddr[0], ++ GFP_DMA | GFP_KERNEL); ++ ++ if (buffer->vaddr) { ++ if (i == STF_ISP_PAD_SRC) ++ buffer->paddr[1] = ++ (dma_addr_t)(buffer->paddr[0] + aligns * fmt->height); ++ else ++ dev_dbg(dev, "signal plane\n"); ++ } ++ } ++ ++ return ret; ++} ++ ++static void vin_free_dummy_buffer(struct stf_vin_dev *vin_dev, int dummy_module) ++{ ++ struct device *dev = vin_dev->stfcamss->dev; ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[dummy_module]; ++ struct vin_dummy_buffer *buffer = NULL; ++ int i; ++ ++ for (i = 0; i < dummy_buffer->nums; i++) { ++ buffer = &dummy_buffer->buffer[i]; ++ if (buffer->vaddr) ++ dma_free_coherent(dev, buffer->buffer_size, ++ buffer->vaddr, buffer->paddr[0]); ++ memset(buffer, 0, sizeof(struct vin_dummy_buffer)); ++ } ++} ++ ++static void vin_set_dummy_buffer(struct vin_line *line, u32 pad) ++{ ++ struct stf_vin_dev *vin_dev = line_to_vin_dev(line); ++ int dummy_module = vin_line_to_dummy_module(line); ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[dummy_module]; ++ struct vin_dummy_buffer *buffer = NULL; ++ ++ switch (pad) { ++ case STF_VIN_PAD_SINK: ++ if (line->id == VIN_LINE_WR) { ++ buffer = &dummy_buffer->buffer[STF_VIN_PAD_SINK]; ++ stf_vin_wr_set_ping_addr(vin_dev, buffer->paddr[0]); ++ stf_vin_wr_set_pong_addr(vin_dev, buffer->paddr[0]); ++ } else { ++ buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC]; ++ stf_vin_isp_set_yuv_addr(vin_dev, ++ buffer->paddr[0], ++ buffer->paddr[1]); ++ } ++ break; ++ case STF_ISP_PAD_SRC: ++ buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC]; ++ stf_vin_isp_set_yuv_addr(vin_dev, ++ buffer->paddr[0], ++ buffer->paddr[1]); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int vin_set_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ struct stf_vin_dev *vin_dev = line_to_vin_dev(line); ++ int dummy_module = vin_line_to_dummy_module(line); ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[dummy_module]; ++ struct v4l2_mbus_framefmt *fmt; ++ enum link link; ++ ++ fmt = __vin_get_format(line, NULL, ++ STF_VIN_PAD_SINK, V4L2_SUBDEV_FORMAT_ACTIVE); ++ mutex_lock(&dummy_buffer->stream_lock); ++ if (enable) { ++ if (dummy_buffer->stream_count == 0) { ++ vin_alloc_dummy_buffer(vin_dev, fmt, dummy_module); ++ vin_set_dummy_buffer(line, STF_VIN_PAD_SINK); ++ atomic_set(&dummy_buffer->frame_skip, ++ VIN_FRAME_DROP_MIN_VAL + 30); ++ } ++ dummy_buffer->stream_count++; ++ } else { ++ if (dummy_buffer->stream_count == 1) { ++ vin_free_dummy_buffer(vin_dev, dummy_module); ++ /* set buffer addr to zero */ ++ vin_set_dummy_buffer(line, STF_VIN_PAD_SINK); ++ } else { ++ vin_set_dummy_buffer(line, ++ stf_vin_map_isp_pad(line->id, STF_ISP_PAD_SINK)); ++ } ++ ++ dummy_buffer->stream_count--; ++ } ++ mutex_unlock(&dummy_buffer->stream_lock); ++ ++ mutex_lock(&line->stream_lock); ++ link = vin_get_link(&sd->entity); ++ if (link == LINK_ERROR) ++ goto exit; ++ ++ if (enable) { ++ if (line->stream_count == 0) { ++ stf_vin_stream_set(vin_dev, link); ++ if (line->id == VIN_LINE_WR) { ++ stf_vin_wr_irq_enable(vin_dev, 1); ++ stf_vin_wr_stream_set(vin_dev); ++ } ++ } ++ line->stream_count++; ++ } else { ++ if (line->stream_count == 1 && line->id == VIN_LINE_WR) ++ stf_vin_wr_irq_enable(vin_dev, 0); ++ line->stream_count--; ++ } ++exit: ++ mutex_unlock(&line->stream_lock); ++ ++ if (enable) ++ vin_enable_output(line); ++ else ++ vin_disable_output(line); ++ ++ return 0; ++} ++ ++static struct v4l2_mbus_framefmt * ++__vin_get_format(struct vin_line *line, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ enum v4l2_subdev_format_whence which) ++{ ++ if (which == V4L2_SUBDEV_FORMAT_TRY) ++ return v4l2_subdev_get_try_format(&line->subdev, state, pad); ++ return &line->fmt[pad]; ++} ++ ++static void vin_try_format(struct vin_line *line, ++ struct v4l2_subdev_state *state, ++ unsigned int pad, ++ struct v4l2_mbus_framefmt *fmt, ++ enum v4l2_subdev_format_whence which) ++{ ++ unsigned int i; ++ ++ switch (pad) { ++ case STF_VIN_PAD_SINK: ++ /* Set format on sink pad */ ++ for (i = 0; i < line->nformats; i++) ++ if (fmt->code == line->formats[i].code) ++ break; ++ ++ /* If not found, use UYVY as default */ ++ if (i >= line->nformats) ++ fmt->code = line->formats[0].code; ++ ++ fmt->width = clamp_t(u32, fmt->width, ++ STFCAMSS_FRAME_MIN_WIDTH, ++ STFCAMSS_FRAME_MAX_WIDTH); ++ fmt->height = clamp_t(u32, fmt->height, ++ STFCAMSS_FRAME_MIN_HEIGHT, ++ STFCAMSS_FRAME_MAX_HEIGHT); ++ ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->flags = 0; ++ break; ++ ++ case STF_VIN_PAD_SRC: ++ /* Set and return a format same as sink pad */ ++ *fmt = *__vin_get_format(line, state, STF_VIN_PAD_SINK, which); ++ break; ++ } ++ ++ fmt->colorspace = V4L2_COLORSPACE_SRGB; ++} ++ ++static int vin_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ ++ if (code->index >= line->nformats) ++ return -EINVAL; ++ if (code->pad == STF_VIN_PAD_SINK) { ++ code->code = line->formats[code->index].code; ++ } else { ++ struct v4l2_mbus_framefmt *sink_fmt; ++ ++ sink_fmt = __vin_get_format(line, state, STF_VIN_PAD_SINK, ++ code->which); ++ ++ code->code = sink_fmt->code; ++ if (!code->code) ++ return -EINVAL; ++ } ++ code->flags = 0; ++ ++ return 0; ++} ++ ++static int vin_enum_frame_size(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt format; ++ ++ if (fse->index != 0) ++ return -EINVAL; ++ ++ format.code = fse->code; ++ format.width = 1; ++ format.height = 1; ++ vin_try_format(line, state, fse->pad, &format, fse->which); ++ fse->min_width = format.width; ++ fse->min_height = format.height; ++ ++ if (format.code != fse->code) ++ return -EINVAL; ++ ++ format.code = fse->code; ++ format.width = -1; ++ format.height = -1; ++ vin_try_format(line, state, fse->pad, &format, fse->which); ++ fse->max_width = format.width; ++ fse->max_height = format.height; ++ ++ return 0; ++} ++ ++static int vin_get_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt *format; ++ ++ format = __vin_get_format(line, state, fmt->pad, fmt->which); ++ if (!format) ++ return -EINVAL; ++ ++ fmt->format = *format; ++ ++ return 0; ++} ++ ++static int vin_set_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct vin_line *line = v4l2_get_subdevdata(sd); ++ struct v4l2_mbus_framefmt *format; ++ ++ format = __vin_get_format(line, state, fmt->pad, fmt->which); ++ if (!format) ++ return -EINVAL; ++ ++ mutex_lock(&line->stream_lock); ++ if (line->stream_count) { ++ fmt->format = *format; ++ mutex_unlock(&line->stream_lock); ++ goto out; ++ } else { ++ vin_try_format(line, state, fmt->pad, &fmt->format, fmt->which); ++ *format = fmt->format; ++ } ++ mutex_unlock(&line->stream_lock); ++ ++ if (fmt->pad == STF_VIN_PAD_SINK) { ++ /* Propagate the format from sink to source */ ++ format = __vin_get_format(line, state, STF_VIN_PAD_SRC, ++ fmt->which); ++ ++ *format = fmt->format; ++ vin_try_format(line, state, STF_VIN_PAD_SRC, format, ++ fmt->which); ++ } ++ ++out: ++ return 0; ++} ++ ++static int vin_init_formats(struct v4l2_subdev *sd, ++ struct v4l2_subdev_fh *fh) ++{ ++ struct v4l2_subdev_format format = { ++ .pad = STF_VIN_PAD_SINK, ++ .which = fh ? ++ V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE, ++ .format = { ++ .code = MEDIA_BUS_FMT_RGB565_2X8_LE, ++ .width = 1920, ++ .height = 1080 ++ } ++ }; ++ ++ return vin_set_format(sd, fh ? fh->state : NULL, &format); ++} ++ ++static void vin_output_init_addrs(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ struct stf_vin_dev *vin_dev = line_to_vin_dev(line); ++ dma_addr_t ping_addr; ++ dma_addr_t y_addr, uv_addr; ++ ++ output->active_buf = 0; ++ ++ if (output->buf[0]) { ++ ping_addr = output->buf[0]->addr[0]; ++ y_addr = output->buf[0]->addr[0]; ++ uv_addr = output->buf[0]->addr[1]; ++ } else { ++ return; ++ } ++ ++ switch (vin_map_isp_line(line->id)) { ++ case STF_ISP_LINE_SRC: ++ stf_vin_isp_set_yuv_addr(vin_dev, y_addr, uv_addr); ++ break; ++ default: ++ if (line->id == VIN_LINE_WR) { ++ stf_vin_wr_set_ping_addr(vin_dev, ping_addr); ++ stf_vin_wr_set_pong_addr(vin_dev, ping_addr); ++ } ++ break; ++ } ++} ++ ++static void vin_init_outputs(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ ++ output->state = VIN_OUTPUT_OFF; ++ output->buf[0] = NULL; ++ output->buf[1] = NULL; ++ output->active_buf = 0; ++ INIT_LIST_HEAD(&output->pending_bufs); ++ INIT_LIST_HEAD(&output->ready_bufs); ++} ++ ++static void vin_buf_add_ready(struct vin_output *output, ++ struct stfcamss_buffer *buffer) ++{ ++ INIT_LIST_HEAD(&buffer->queue); ++ list_add_tail(&buffer->queue, &output->ready_bufs); ++} ++ ++static struct stfcamss_buffer *vin_buf_get_ready(struct vin_output *output) ++{ ++ struct stfcamss_buffer *buffer = NULL; ++ ++ if (!list_empty(&output->ready_bufs)) { ++ buffer = list_first_entry(&output->ready_bufs, ++ struct stfcamss_buffer, ++ queue); ++ list_del(&buffer->queue); ++ } ++ ++ return buffer; ++} ++ ++static void vin_buf_add_pending(struct vin_output *output, ++ struct stfcamss_buffer *buffer) ++{ ++ INIT_LIST_HEAD(&buffer->queue); ++ list_add_tail(&buffer->queue, &output->pending_bufs); ++} ++ ++static struct stfcamss_buffer *vin_buf_get_pending(struct vin_output *output) ++{ ++ struct stfcamss_buffer *buffer = NULL; ++ ++ if (!list_empty(&output->pending_bufs)) { ++ buffer = list_first_entry(&output->pending_bufs, ++ struct stfcamss_buffer, ++ queue); ++ list_del(&buffer->queue); ++ } ++ ++ return buffer; ++} ++ ++static void vin_buf_update_on_last(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ ++ switch (output->state) { ++ case VIN_OUTPUT_CONTINUOUS: ++ output->state = VIN_OUTPUT_SINGLE; ++ output->active_buf = !output->active_buf; ++ break; ++ case VIN_OUTPUT_SINGLE: ++ output->state = VIN_OUTPUT_STOPPING; ++ break; ++ default: ++ break; ++ } ++} ++ ++static void vin_buf_update_on_next(struct vin_line *line) ++{ ++ struct vin_output *output = &line->output; ++ ++ switch (output->state) { ++ case VIN_OUTPUT_CONTINUOUS: ++ output->active_buf = !output->active_buf; ++ break; ++ case VIN_OUTPUT_SINGLE: ++ default: ++ break; ++ } ++} ++ ++static void vin_buf_update_on_new(struct vin_line *line, ++ struct vin_output *output, ++ struct stfcamss_buffer *new_buf) ++{ ++ switch (output->state) { ++ case VIN_OUTPUT_SINGLE: ++ vin_buf_add_pending(output, new_buf); ++ break; ++ case VIN_OUTPUT_IDLE: ++ if (!output->buf[0]) { ++ output->buf[0] = new_buf; ++ vin_output_init_addrs(line); ++ output->state = VIN_OUTPUT_SINGLE; ++ } else { ++ vin_buf_add_pending(output, new_buf); ++ } ++ break; ++ case VIN_OUTPUT_STOPPING: ++ if (output->last_buffer) { ++ output->buf[output->active_buf] = output->last_buffer; ++ output->last_buffer = NULL; ++ } ++ ++ output->state = VIN_OUTPUT_SINGLE; ++ vin_buf_add_pending(output, new_buf); ++ break; ++ case VIN_OUTPUT_CONTINUOUS: ++ default: ++ vin_buf_add_pending(output, new_buf); ++ break; ++ } ++} ++ ++static void vin_buf_flush(struct vin_output *output, ++ enum vb2_buffer_state state) ++{ ++ struct stfcamss_buffer *buf; ++ struct stfcamss_buffer *t; ++ ++ list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) { ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ list_del(&buf->queue); ++ } ++ list_for_each_entry_safe(buf, t, &output->ready_bufs, queue) { ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ list_del(&buf->queue); ++ } ++} ++ ++static void vin_buffer_done(struct vin_line *line) ++{ ++ struct stfcamss_buffer *ready_buf; ++ struct vin_output *output = &line->output; ++ unsigned long flags; ++ u64 ts = ktime_get_ns(); ++ ++ if (output->state == VIN_OUTPUT_OFF || ++ output->state == VIN_OUTPUT_RESERVED) ++ return; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ while ((ready_buf = vin_buf_get_ready(output))) { ++ ready_buf->vb.vb2_buf.timestamp = ts; ++ ready_buf->vb.sequence = output->sequence++; ++ ++ vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); ++ } ++ ++ spin_unlock_irqrestore(&line->output_lock, flags); ++} ++ ++static void vin_change_buffer(struct vin_line *line) ++{ ++ struct stfcamss_buffer *ready_buf; ++ struct vin_output *output = &line->output; ++ struct stf_vin_dev *vin_dev = line_to_vin_dev(line); ++ dma_addr_t *new_addr; ++ unsigned long flags; ++ u32 active_index; ++ ++ if (output->state == VIN_OUTPUT_OFF || ++ output->state == VIN_OUTPUT_STOPPING || ++ output->state == VIN_OUTPUT_RESERVED || ++ output->state == VIN_OUTPUT_IDLE) ++ return; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ active_index = output->active_buf; ++ ++ ready_buf = output->buf[active_index]; ++ if (!ready_buf) { ++ dev_warn(vin_dev->stfcamss->dev, "Missing ready buf %d %d!\n", ++ active_index, output->state); ++ active_index = !active_index; ++ ready_buf = output->buf[active_index]; ++ if (!ready_buf) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Missing ready buf2 %d %d!\n", ++ active_index, output->state); ++ goto out_unlock; ++ } ++ } ++ ++ /* Get next buffer */ ++ output->buf[active_index] = vin_buf_get_pending(output); ++ if (!output->buf[active_index]) { ++ /* No next buffer - set same address */ ++ new_addr = ready_buf->addr; ++ vin_buf_update_on_last(line); ++ } else { ++ new_addr = output->buf[active_index]->addr; ++ vin_buf_update_on_next(line); ++ } ++ ++ if (output->state == VIN_OUTPUT_STOPPING) { ++ output->last_buffer = ready_buf; ++ } else { ++ switch (vin_map_isp_line(line->id)) { ++ case STF_ISP_LINE_SRC: ++ stf_vin_isp_set_yuv_addr(vin_dev, ++ new_addr[0], ++ new_addr[1]); ++ break; ++ default: ++ if (line->id == VIN_LINE_WR) { ++ stf_vin_wr_set_ping_addr(vin_dev, new_addr[0]); ++ stf_vin_wr_set_pong_addr(vin_dev, new_addr[0]); ++ } ++ break; ++ } ++ ++ vin_buf_add_ready(output, ready_buf); ++ } ++ ++ spin_unlock_irqrestore(&line->output_lock, flags); ++ return; ++ ++out_unlock: ++ spin_unlock_irqrestore(&line->output_lock, flags); ++} ++ ++static int vin_queue_buffer(struct stfcamss_video *vid, ++ struct stfcamss_buffer *buf) ++{ ++ struct vin_line *line = container_of(vid, struct vin_line, video_out); ++ struct vin_output *output; ++ unsigned long flags; ++ ++ output = &line->output; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ vin_buf_update_on_new(line, output, buf); ++ ++ spin_unlock_irqrestore(&line->output_lock, flags); ++ ++ return 0; ++} ++ ++static int vin_flush_buffers(struct stfcamss_video *vid, ++ enum vb2_buffer_state state) ++{ ++ struct vin_line *line = container_of(vid, struct vin_line, video_out); ++ struct vin_output *output = &line->output; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&line->output_lock, flags); ++ ++ vin_buf_flush(output, state); ++ if (output->buf[0]) ++ vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state); ++ ++ if (output->buf[1]) ++ vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state); ++ ++ if (output->last_buffer) { ++ vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state); ++ output->last_buffer = NULL; ++ } ++ output->buf[0] = NULL; ++ output->buf[1] = NULL; ++ ++ spin_unlock_irqrestore(&line->output_lock, flags); ++ return 0; ++} ++ ++static int vin_link_setup(struct media_entity *entity, ++ const struct media_pad *local, ++ const struct media_pad *remote, u32 flags) ++{ ++ if (flags & MEDIA_LNK_FL_ENABLED) ++ if (media_pad_remote_pad_first(local)) ++ return -EBUSY; ++ return 0; ++} ++ ++static const struct v4l2_subdev_core_ops vin_core_ops = { ++ .s_power = vin_set_power, ++}; ++ ++static const struct v4l2_subdev_video_ops vin_video_ops = { ++ .s_stream = vin_set_stream, ++}; ++ ++static const struct v4l2_subdev_pad_ops vin_pad_ops = { ++ .enum_mbus_code = vin_enum_mbus_code, ++ .enum_frame_size = vin_enum_frame_size, ++ .get_fmt = vin_get_format, ++ .set_fmt = vin_set_format, ++}; ++ ++static const struct v4l2_subdev_ops vin_v4l2_ops = { ++ .core = &vin_core_ops, ++ .video = &vin_video_ops, ++ .pad = &vin_pad_ops, ++}; ++ ++static const struct v4l2_subdev_internal_ops vin_v4l2_internal_ops = { ++ .open = vin_init_formats, ++}; ++ ++static const struct stfcamss_video_ops stfcamss_vin_video_ops = { ++ .queue_buffer = vin_queue_buffer, ++ .flush_buffers = vin_flush_buffers, ++}; ++ ++static const struct media_entity_operations vin_media_ops = { ++ .link_setup = vin_link_setup, ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++int stf_vin_register(struct stf_vin_dev *vin_dev, struct v4l2_device *v4l2_dev) ++{ ++ struct v4l2_subdev *sd; ++ struct stfcamss_video *video_out; ++ struct media_pad *pads; ++ int ret; ++ int i; ++ ++ for (i = 0; i < STF_ISP_LINE_MAX + 1; i++) { ++ char name[32]; ++ char *sub_name = vin_get_line_subdevname(i); ++ ++ sd = &vin_dev->line[i].subdev; ++ pads = vin_dev->line[i].pads; ++ video_out = &vin_dev->line[i].video_out; ++ video_out->id = i; ++ ++ v4l2_subdev_init(sd, &vin_v4l2_ops); ++ sd->internal_ops = &vin_v4l2_internal_ops; ++ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s", ++ STF_VIN_NAME, 0, sub_name); ++ v4l2_set_subdevdata(sd, &vin_dev->line[i]); ++ ++ ret = vin_init_formats(sd, NULL); ++ if (ret < 0) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Failed to init format: %d\n", ret); ++ goto err_init; ++ } ++ ++ pads[STF_VIN_PAD_SINK].flags = MEDIA_PAD_FL_SINK; ++ pads[STF_VIN_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; ++ ++ sd->entity.function = ++ MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; ++ sd->entity.ops = &vin_media_ops; ++ ret = media_entity_pads_init(&sd->entity, ++ STF_VIN_PADS_NUM, pads); ++ if (ret < 0) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Failed to init media entity: %d\n", ++ ret); ++ goto err_init; ++ } ++ ++ ret = v4l2_device_register_subdev(v4l2_dev, sd); ++ if (ret < 0) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Failed to register subdev: %d\n", ret); ++ goto err_reg_subdev; ++ } ++ ++ video_out->ops = &stfcamss_vin_video_ops; ++ video_out->bpl_alignment = 16 * 8; ++ ++ snprintf(name, ARRAY_SIZE(name), "%s_%s%d", ++ sd->name, "video", i); ++ ret = stf_video_register(video_out, v4l2_dev, name); ++ if (ret < 0) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Failed to register video node: %d\n", ret); ++ goto err_vid_reg; ++ } ++ ++ ret = media_create_pad_link( ++ &sd->entity, STF_VIN_PAD_SRC, ++ &video_out->vdev.entity, 0, ++ MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); ++ if (ret < 0) { ++ dev_err(vin_dev->stfcamss->dev, ++ "Failed to link %s->%s entities: %d\n", ++ sd->entity.name, video_out->vdev.entity.name, ++ ret); ++ goto err_create_link; ++ } ++ } ++ ++ return 0; ++ ++err_create_link: ++ stf_video_unregister(video_out); ++err_vid_reg: ++ v4l2_device_unregister_subdev(sd); ++err_reg_subdev: ++ media_entity_cleanup(&sd->entity); ++err_init: ++ for (i--; i >= 0; i--) { ++ sd = &vin_dev->line[i].subdev; ++ video_out = &vin_dev->line[i].video_out; ++ ++ stf_video_unregister(video_out); ++ v4l2_device_unregister_subdev(sd); ++ media_entity_cleanup(&sd->entity); ++ } ++ return ret; ++} ++ ++int stf_vin_unregister(struct stf_vin_dev *vin_dev) ++{ ++ struct v4l2_subdev *sd; ++ struct stfcamss_video *video_out; ++ int i; ++ ++ mutex_destroy(&vin_dev->power_lock); ++ for (i = 0; i < STF_DUMMY_MODULE_NUMS; i++) ++ mutex_destroy(&vin_dev->dummy_buffer[i].stream_lock); ++ ++ for (i = 0; i < STF_ISP_LINE_MAX + 1; i++) { ++ sd = &vin_dev->line[i].subdev; ++ video_out = &vin_dev->line[i].video_out; ++ ++ stf_video_unregister(video_out); ++ v4l2_device_unregister_subdev(sd); ++ media_entity_cleanup(&sd->entity); ++ mutex_destroy(&vin_dev->line[i].stream_lock); ++ mutex_destroy(&vin_dev->line[i].power_lock); ++ } ++ return 0; ++} +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_vin.h +@@ -0,0 +1,180 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * stf_vin.h ++ * ++ * StarFive Camera Subsystem - VIN Module ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++ ++#ifndef STF_VIN_H ++#define STF_VIN_H ++ ++#include ++#include ++#include ++ ++#include "stf_video.h" ++ ++#define SYSCONSAIF_SYSCFG(x) (x) ++ ++/* syscon offset 0 */ ++#define U0_VIN_CNFG_AXI_DVP_EN BIT(2) ++ ++/* syscon offset 20 */ ++#define U0_VIN_CHANNEL_SEL_MASK GENMASK(3, 0) ++#define U0_VIN_AXIWR0_EN BIT(4) ++#define CHANNEL(x) ((x) << 0) ++ ++/* syscon offset 32 */ ++#define U0_VIN_INTR_CLEAN BIT(0) ++#define U0_VIN_INTR_M BIT(1) ++#define U0_VIN_PIX_CNT_END_MASK GENMASK(12, 2) ++#define U0_VIN_PIX_CT_MASK GENMASK(14, 13) ++#define U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS GENMASK(16, 15) ++ ++#define PIX_CNT_END(x) ((x) << 2) ++#define PIX_CT(x) ((x) << 13) ++#define PIXEL_HEIGH_BIT_SEL(x) ((x) << 15) ++ ++/* syscon offset 36 */ ++#define U0_VIN_CNFG_DVP_HS_POS BIT(1) ++#define U0_VIN_CNFG_DVP_SWAP_EN BIT(2) ++#define U0_VIN_CNFG_DVP_VS_POS BIT(3) ++#define U0_VIN_CNFG_GEN_EN_AXIRD BIT(4) ++#define U0_VIN_CNFG_ISP_DVP_EN0 BIT(5) ++#define U0_VIN_MIPI_BYTE_EN_ISP0(n) ((n) << 6) ++#define U0_VIN_MIPI_CHANNEL_SEL0(n) ((n) << 8) ++#define U0_VIN_P_I_MIPI_HAEDER_EN0(n) ((n) << 12) ++#define U0_VIN_PIX_NUM(n) ((n) << 13) ++#define U0_VIN_MIPI_BYTE_EN_ISP0_MASK GENMASK(7, 6) ++#define U0_VIN_MIPI_CHANNEL_SEL0_MASK GENMASK(11, 8) ++#define U0_VIN_P_I_MIPI_HAEDER_EN0_MASK BIT(12) ++#define U0_VIN_PIX_NUM_MASK GENMASK(16, 13) ++ ++#define STF_VIN_PAD_SINK 0 ++#define STF_VIN_PAD_SRC 1 ++#define STF_VIN_PADS_NUM 2 ++ ++#define ISP_DUMMY_BUFFER_NUMS STF_ISP_PAD_MAX ++#define VIN_DUMMY_BUFFER_NUMS 1 ++ ++enum { ++ STF_DUMMY_VIN, ++ STF_DUMMY_ISP, ++ STF_DUMMY_MODULE_NUMS, ++}; ++ ++enum link { ++ LINK_ERROR = -1, ++ LINK_DVP_TO_WR, ++ LINK_DVP_TO_ISP, ++ LINK_CSI_TO_WR, ++ LINK_CSI_TO_ISP, ++}; ++ ++struct vin_format { ++ u32 code; ++ u8 bpp; ++}; ++ ++struct vin_format_table { ++ const struct vin_format *fmts; ++ int nfmts; ++}; ++ ++enum vin_output_state { ++ VIN_OUTPUT_OFF, ++ VIN_OUTPUT_RESERVED, ++ VIN_OUTPUT_SINGLE, ++ VIN_OUTPUT_CONTINUOUS, ++ VIN_OUTPUT_IDLE, ++ VIN_OUTPUT_STOPPING ++}; ++ ++struct vin_output { ++ int active_buf; ++ struct stfcamss_buffer *buf[2]; ++ struct stfcamss_buffer *last_buffer; ++ struct list_head pending_bufs; ++ struct list_head ready_bufs; ++ enum vin_output_state state; ++ unsigned int sequence; ++ unsigned int frame_skip; ++}; ++ ++/* The vin output lines */ ++enum vin_line_id { ++ VIN_LINE_NONE = -1, ++ VIN_LINE_WR = 0, ++ VIN_LINE_ISP, ++ VIN_LINE_MAX, ++}; ++ ++struct vin_line { ++ enum stf_subdev_type sdev_type; /* must be frist */ ++ enum vin_line_id id; ++ struct v4l2_subdev subdev; ++ struct media_pad pads[STF_VIN_PADS_NUM]; ++ struct v4l2_mbus_framefmt fmt[STF_VIN_PADS_NUM]; ++ struct stfcamss_video video_out; ++ struct mutex stream_lock; /* serialize stream control */ ++ int stream_count; ++ struct mutex power_lock; /* serialize pipeline control in power process*/ ++ int power_count; ++ struct vin_output output; /* pipeline and stream states */ ++ spinlock_t output_lock; ++ const struct vin_format *formats; ++ unsigned int nformats; ++}; ++ ++struct vin_dummy_buffer { ++ dma_addr_t paddr[3]; ++ void *vaddr; ++ u32 buffer_size; ++ u32 width; ++ u32 height; ++ u32 mcode; ++}; ++ ++struct dummy_buffer { ++ struct vin_dummy_buffer *buffer; ++ u32 nums; ++ struct mutex stream_lock; /* protects buffer data */ ++ int stream_count; ++ atomic_t frame_skip; ++}; ++ ++struct vin_isr_ops { ++ void (*isr_buffer_done)(struct vin_line *line); ++ void (*isr_change_buffer)(struct vin_line *line); ++}; ++ ++struct stf_vin_dev { ++ struct stfcamss *stfcamss; ++ struct vin_line line[VIN_LINE_MAX]; ++ struct dummy_buffer dummy_buffer[STF_DUMMY_MODULE_NUMS]; ++ struct vin_isr_ops *isr_ops; ++ atomic_t ref_count; ++ struct mutex power_lock; /* serialize power control*/ ++ int power_count; ++}; ++ ++int stf_vin_clk_enable(struct stf_vin_dev *vin_dev, enum link link); ++int stf_vin_clk_disable(struct stf_vin_dev *vin_dev, enum link link); ++int stf_vin_wr_stream_set(struct stf_vin_dev *vin_dev); ++int stf_vin_stream_set(struct stf_vin_dev *vin_dev, enum link link); ++void stf_vin_wr_irq_enable(struct stf_vin_dev *vin_dev, int enable); ++void stf_vin_wr_set_ping_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr); ++void stf_vin_wr_set_pong_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr); ++void stf_vin_isp_set_yuv_addr(struct stf_vin_dev *vin_dev, ++ dma_addr_t y_addr, dma_addr_t uv_addr); ++irqreturn_t stf_vin_wr_irq_handler(int irq, void *priv); ++irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv); ++irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv); ++int stf_vin_subdev_init(struct stfcamss *stfcamss); ++int stf_vin_register(struct stf_vin_dev *vin_dev, struct v4l2_device *v4l2_dev); ++int stf_vin_unregister(struct stf_vin_dev *vin_dev); ++enum isp_pad_id stf_vin_map_isp_pad(enum vin_line_id line, enum isp_pad_id def); ++ ++#endif /* STF_VIN_H */ +--- /dev/null ++++ b/drivers/media/platform/starfive/stf_vin_hw_ops.c +@@ -0,0 +1,241 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * stf_vin_hw_ops.c ++ * ++ * Register interface file for StarFive VIN module driver ++ * ++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd. ++ */ ++#include "stf_camss.h" ++ ++static void vin_intr_clear(struct stfcamss *stfcamss) ++{ ++ stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_CLEAN); ++ stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_CLEAN); ++} ++ ++irqreturn_t stf_vin_wr_irq_handler(int irq, void *priv) ++{ ++ struct stf_vin_dev *vin_dev = priv; ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[STF_DUMMY_VIN]; ++ ++ if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) { ++ vin_dev->isr_ops->isr_change_buffer(&vin_dev->line[VIN_LINE_WR]); ++ vin_dev->isr_ops->isr_buffer_done(&vin_dev->line[VIN_LINE_WR]); ++ } ++ ++ vin_intr_clear(stfcamss); ++ ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv) ++{ ++ struct stf_vin_dev *vin_dev = priv; ++ u32 int_status; ++ ++ int_status = stf_isp_reg_read(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0); ++ ++ if (int_status & ISPC_INTS) { ++ if ((int_status & ISPC_ENUO)) ++ vin_dev->isr_ops->isr_buffer_done( ++ &vin_dev->line[VIN_LINE_ISP]); ++ ++ /* clear interrupt */ ++ stf_isp_reg_write(vin_dev->stfcamss, ++ ISP_REG_ISP_CTRL_0, ++ (int_status & ~EN_INT_ALL) | ++ EN_INT_ISP_DONE | ++ EN_INT_CSI_DONE | ++ EN_INT_SC_DONE); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv) ++{ ++ struct stf_vin_dev *vin_dev = priv; ++ struct stf_isp_dev *isp_dev; ++ u32 int_status; ++ ++ isp_dev = &vin_dev->stfcamss->isp_dev; ++ ++ int_status = stf_isp_reg_read(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0); ++ if (int_status & ISPC_SCFEINT) { ++ struct dummy_buffer *dummy_buffer = ++ &vin_dev->dummy_buffer[STF_DUMMY_ISP]; ++ ++ if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) { ++ if ((int_status & ISPC_ENUO)) ++ vin_dev->isr_ops->isr_change_buffer( ++ &vin_dev->line[VIN_LINE_ISP]); ++ } ++ ++ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_CSIINTS, ++ CSI_INTS_MASK, CSI_INTS(0x3)); ++ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_IESHD, ++ SHAD_UP_M | SHAD_UP_EN, 0x3); ++ ++ /* clear interrupt */ ++ stf_isp_reg_write(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0, ++ (int_status & ~EN_INT_ALL) | EN_INT_LINE_INT); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++int stf_vin_clk_enable(struct stf_vin_dev *vin_dev, enum link link) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ clk_set_rate(stfcamss->sys_clk[STF_CLK_APB_FUNC].clk, 49500000); ++ ++ switch (link) { ++ case LINK_CSI_TO_WR: ++ clk_set_rate(stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk, ++ 198000000); ++ reset_control_deassert(stfcamss->sys_rst[STF_RST_AXIWR].rstc); ++ clk_set_parent(stfcamss->sys_clk[STF_CLK_AXIWR].clk, ++ stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk); ++ break; ++ case LINK_CSI_TO_ISP: ++ clk_set_rate(stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk, ++ 198000000); ++ clk_set_parent(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk, ++ stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk); ++ break; ++ case LINK_DVP_TO_WR: ++ case LINK_DVP_TO_ISP: ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int stf_vin_clk_disable(struct stf_vin_dev *vin_dev, enum link link) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ switch (link) { ++ case LINK_CSI_TO_WR: ++ reset_control_assert(stfcamss->sys_rst[STF_RST_AXIWR].rstc); ++ break; ++ case LINK_CSI_TO_ISP: ++ break; ++ case LINK_DVP_TO_WR: ++ case LINK_DVP_TO_ISP: ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int stf_vin_wr_stream_set(struct stf_vin_dev *vin_dev) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ /* make the axiwr alway on */ ++ stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(20), ++ U0_VIN_AXIWR0_EN); ++ ++ return 0; ++} ++ ++int stf_vin_stream_set(struct stf_vin_dev *vin_dev, enum link link) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ u32 val; ++ ++ switch (link) { ++ case LINK_CSI_TO_WR: ++ val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(20)); ++ val &= ~U0_VIN_CHANNEL_SEL_MASK; ++ val |= CHANNEL(0); ++ stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(20), val); ++ ++ val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(28)); ++ val &= ~U0_VIN_PIX_CT_MASK; ++ val |= PIX_CT(1); ++ ++ val &= ~U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS; ++ val |= PIXEL_HEIGH_BIT_SEL(0); ++ ++ val &= ~U0_VIN_PIX_CNT_END_MASK; ++ val |= PIX_CNT_END(IMAGE_MAX_WIDTH / 4 - 1); ++ ++ stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(28), val); ++ break; ++ case LINK_CSI_TO_ISP: ++ val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(36)); ++ val &= ~U0_VIN_MIPI_BYTE_EN_ISP0_MASK; ++ val |= U0_VIN_MIPI_BYTE_EN_ISP0(0); ++ ++ val &= ~U0_VIN_MIPI_CHANNEL_SEL0_MASK; ++ val |= U0_VIN_MIPI_CHANNEL_SEL0(0); ++ ++ val &= ~U0_VIN_PIX_NUM_MASK; ++ val |= U0_VIN_PIX_NUM(0); ++ ++ val &= ~U0_VIN_P_I_MIPI_HAEDER_EN0_MASK; ++ val |= U0_VIN_P_I_MIPI_HAEDER_EN0(1); ++ ++ stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(36), val); ++ break; ++ case LINK_DVP_TO_WR: ++ case LINK_DVP_TO_ISP: ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void stf_vin_wr_irq_enable(struct stf_vin_dev *vin_dev, int enable) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ if (enable) { ++ stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_M); ++ } else { ++ /* clear vin interrupt */ ++ stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_CLEAN); ++ stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_CLEAN); ++ stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28), ++ U0_VIN_INTR_M); ++ } ++} ++ ++void stf_vin_wr_set_ping_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ /* set the start address */ ++ stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(32), (long)addr); ++} ++ ++void stf_vin_wr_set_pong_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr) ++{ ++ struct stfcamss *stfcamss = vin_dev->stfcamss; ++ ++ /* set the start address */ ++ stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(24), (long)addr); ++} ++ ++void stf_vin_isp_set_yuv_addr(struct stf_vin_dev *vin_dev, ++ dma_addr_t y_addr, dma_addr_t uv_addr) ++{ ++ stf_isp_reg_write(vin_dev->stfcamss, ++ ISP_REG_Y_PLANE_START_ADDR, y_addr); ++ stf_isp_reg_write(vin_dev->stfcamss, ++ ISP_REG_UV_PLANE_START_ADDR, uv_addr); ++} diff --git a/target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch b/target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch new file mode 100644 index 0000000000..08eee9ca9e --- /dev/null +++ b/target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch @@ -0,0 +1,68 @@ +From 2ebd77fa8fb95f60b275cefb98ea7d6f4df06e55 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:44 +0800 +Subject: [PATCH 087/122] dt-bindings: phy: Add StarFive JH7110 USB PHY + +Add StarFive JH7110 SoC USB 2.0 PHY dt-binding. + +Signed-off-by: Minda Chen +Reviewed-by: Hal Feng +Reviewed-by: Rob Herring +--- + .../bindings/phy/starfive,jh7110-usb-phy.yaml | 50 +++++++++++++++++++ + 1 file changed, 50 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/starfive,jh7110-usb-phy.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-usb-phy.yaml +@@ -0,0 +1,50 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/starfive,jh7110-usb-phy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 USB 2.0 PHY ++ ++maintainers: ++ - Minda Chen ++ ++properties: ++ compatible: ++ const: starfive,jh7110-usb-phy ++ ++ reg: ++ maxItems: 1 ++ ++ "#phy-cells": ++ const: 0 ++ ++ clocks: ++ items: ++ - description: PHY 125m ++ - description: app 125m ++ ++ clock-names: ++ items: ++ - const: 125m ++ - const: app_125m ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ phy@10200000 { ++ compatible = "starfive,jh7110-usb-phy"; ++ reg = <0x10200000 0x10000>; ++ clocks = <&syscrg 95>, ++ <&stgcrg 6>; ++ clock-names = "125m", "app_125m"; ++ #phy-cells = <0>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0088-dt-bindings-phy-Add-StarFive-JH7110-PCIe-PHY.patch b/target/linux/starfive/patches-6.1/0088-dt-bindings-phy-Add-StarFive-JH7110-PCIe-PHY.patch new file mode 100644 index 0000000000..6911bba9d2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0088-dt-bindings-phy-Add-StarFive-JH7110-PCIe-PHY.patch @@ -0,0 +1,77 @@ +From d57245d420a2ced6a588cc6e03e2eaacbbf1bfb2 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:45 +0800 +Subject: [PATCH 088/122] dt-bindings: phy: Add StarFive JH7110 PCIe PHY + +Add StarFive JH7110 SoC PCIe 2.0 PHY dt-binding. +PCIe PHY0 (phy@10210000) can be used as USB 3.0 PHY. + +Signed-off-by: Minda Chen +Reviewed-by: Hal Feng +Reviewed-by: Rob Herring +--- + .../phy/starfive,jh7110-pcie-phy.yaml | 58 +++++++++++++++++++ + 1 file changed, 58 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/starfive,jh7110-pcie-phy.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-pcie-phy.yaml +@@ -0,0 +1,58 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/starfive,jh7110-pcie-phy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 PCIe 2.0 PHY ++ ++maintainers: ++ - Minda Chen ++ ++properties: ++ compatible: ++ const: starfive,jh7110-pcie-phy ++ ++ reg: ++ maxItems: 1 ++ ++ "#phy-cells": ++ const: 0 ++ ++ starfive,sys-syscon: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ - items: ++ - description: phandle to System Register Controller sys_syscon node. ++ - description: PHY connect offset of SYS_SYSCONSAIF__SYSCFG register for USB PHY. ++ description: ++ The phandle to System Register Controller syscon node and the PHY connect offset ++ of SYS_SYSCONSAIF__SYSCFG register. Connect PHY to USB3 controller. ++ ++ starfive,stg-syscon: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ - items: ++ - description: phandle to System Register Controller stg_syscon node. ++ - description: PHY mode offset of STG_SYSCONSAIF__SYSCFG register. ++ - description: PHY enable for USB offset of STG_SYSCONSAIF__SYSCFG register. ++ description: ++ The phandle to System Register Controller syscon node and the offset ++ of STG_SYSCONSAIF__SYSCFG register for PCIe PHY. Total 2 regsisters offset. ++ ++required: ++ - compatible ++ - reg ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ phy@10210000 { ++ compatible = "starfive,jh7110-pcie-phy"; ++ reg = <0x10210000 0x10000>; ++ #phy-cells = <0>; ++ starfive,sys-syscon = <&sys_syscon 0x18>; ++ starfive,stg-syscon = <&stg_syscon 0x148 0x1f4>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0089-phy-starfive-Add-JH7110-USB-2.0-PHY-driver.patch b/target/linux/starfive/patches-6.1/0089-phy-starfive-Add-JH7110-USB-2.0-PHY-driver.patch new file mode 100644 index 0000000000..0b608868c1 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0089-phy-starfive-Add-JH7110-USB-2.0-PHY-driver.patch @@ -0,0 +1,192 @@ +From 3d74980ca3ba91dae6e84fbc23750e702e71d41a Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:46 +0800 +Subject: [PATCH 089/122] phy: starfive: Add JH7110 USB 2.0 PHY driver + +Add Starfive JH7110 SoC USB 2.0 PHY driver support. +USB 2.0 PHY default connect to Cadence USB controller. + +Signed-off-by: Minda Chen +--- + drivers/phy/starfive/Kconfig | 11 ++ + drivers/phy/starfive/Makefile | 1 + + drivers/phy/starfive/phy-jh7110-usb.c | 150 ++++++++++++++++++++++++++ + 3 files changed, 162 insertions(+) + create mode 100644 drivers/phy/starfive/phy-jh7110-usb.c + +--- a/drivers/phy/starfive/Kconfig ++++ b/drivers/phy/starfive/Kconfig +@@ -11,3 +11,14 @@ config PHY_STARFIVE_DPHY_RX + Choose this option if you have a StarFive D-PHY in your + system. If M is selected, the module will be called + phy-starfive-dphy-rx. ++ ++config PHY_STARFIVE_JH7110_USB ++ tristate "Starfive JH7110 USB 2.0 PHY support" ++ depends on USB_SUPPORT ++ select GENERIC_PHY ++ select USB_PHY ++ help ++ Enable this to support the StarFive USB 2.0 PHY, ++ used with the Cadence USB controller. ++ If M is selected, the module will be called ++ phy-jh7110-usb.ko. +--- a/drivers/phy/starfive/Makefile ++++ b/drivers/phy/starfive/Makefile +@@ -1,2 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_PHY_STARFIVE_DPHY_RX) += phy-starfive-dphy-rx.o ++obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o +--- /dev/null ++++ b/drivers/phy/starfive/phy-jh7110-usb.c +@@ -0,0 +1,150 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * StarFive JH7110 USB 2.0 PHY driver ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * Author: Minda Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USB_125M_CLK_RATE 125000000 ++#define USB_LS_KEEPALIVE_OFF 0x4 ++#define USB_LS_KEEPALIVE_ENABLE BIT(4) ++ ++struct jh7110_usb2_phy { ++ struct phy *phy; ++ void __iomem *regs; ++ struct clk *usb_125m_clk; ++ struct clk *app_125m; ++ enum phy_mode mode; ++}; ++ ++static void jh7110_usb2_mode_set(struct jh7110_usb2_phy *phy) ++{ ++ unsigned int val; ++ ++ if (phy->mode != PHY_MODE_USB_HOST) { ++ /* Enable the LS speed keep-alive signal */ ++ val = readl(phy->regs + USB_LS_KEEPALIVE_OFF); ++ val |= USB_LS_KEEPALIVE_ENABLE; ++ writel(val, phy->regs + USB_LS_KEEPALIVE_OFF); ++ } ++} ++ ++static int jh7110_usb2_phy_set_mode(struct phy *_phy, ++ enum phy_mode mode, int submode) ++{ ++ struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); ++ ++ switch (mode) { ++ case PHY_MODE_USB_HOST: ++ case PHY_MODE_USB_DEVICE: ++ case PHY_MODE_USB_OTG: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (mode != phy->mode) { ++ dev_dbg(&_phy->dev, "Changing phy to %d\n", mode); ++ phy->mode = mode; ++ jh7110_usb2_mode_set(phy); ++ } ++ ++ return 0; ++} ++ ++static int jh7110_usb2_phy_init(struct phy *_phy) ++{ ++ struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); ++ int ret; ++ ++ ret = clk_set_rate(phy->usb_125m_clk, USB_125M_CLK_RATE); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(phy->app_125m); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int jh7110_usb2_phy_exit(struct phy *_phy) ++{ ++ struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); ++ ++ clk_disable_unprepare(phy->app_125m); ++ ++ return 0; ++} ++ ++static const struct phy_ops jh7110_usb2_phy_ops = { ++ .init = jh7110_usb2_phy_init, ++ .exit = jh7110_usb2_phy_exit, ++ .set_mode = jh7110_usb2_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static int jh7110_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct jh7110_usb2_phy *phy; ++ struct device *dev = &pdev->dev; ++ struct phy_provider *phy_provider; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ phy->usb_125m_clk = devm_clk_get(dev, "125m"); ++ if (IS_ERR(phy->usb_125m_clk)) ++ return dev_err_probe(dev, PTR_ERR(phy->usb_125m_clk), ++ "Failed to get 125m clock\n"); ++ ++ phy->app_125m = devm_clk_get(dev, "app_125m"); ++ if (IS_ERR(phy->app_125m)) ++ return dev_err_probe(dev, PTR_ERR(phy->app_125m), ++ "Failed to get app 125m clock\n"); ++ ++ phy->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(phy->regs)) ++ return dev_err_probe(dev, PTR_ERR(phy->regs), ++ "Failed to map phy base\n"); ++ ++ phy->phy = devm_phy_create(dev, NULL, &jh7110_usb2_phy_ops); ++ if (IS_ERR(phy->phy)) ++ return dev_err_probe(dev, PTR_ERR(phy->phy), ++ "Failed to create phy\n"); ++ ++ phy_set_drvdata(phy->phy, phy); ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id jh7110_usb_phy_of_match[] = { ++ { .compatible = "starfive,jh7110-usb-phy" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, jh7110_usb_phy_of_match); ++ ++static struct platform_driver jh7110_usb_phy_driver = { ++ .probe = jh7110_usb_phy_probe, ++ .driver = { ++ .of_match_table = jh7110_usb_phy_of_match, ++ .name = "jh7110-usb-phy", ++ } ++}; ++module_platform_driver(jh7110_usb_phy_driver); ++ ++MODULE_DESCRIPTION("StarFive JH7110 USB 2.0 PHY driver"); ++MODULE_AUTHOR("Minda Chen "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0090-phy-starfive-Add-JH7110-PCIE-2.0-PHY-driver.patch b/target/linux/starfive/patches-6.1/0090-phy-starfive-Add-JH7110-PCIE-2.0-PHY-driver.patch new file mode 100644 index 0000000000..452ffd25c6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0090-phy-starfive-Add-JH7110-PCIE-2.0-PHY-driver.patch @@ -0,0 +1,250 @@ +From d900724fdae7c41a663b31e1ed9b8ba10b998e6f Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:47 +0800 +Subject: [PATCH 090/122] phy: starfive: Add JH7110 PCIE 2.0 PHY driver + +Add Starfive JH7110 SoC PCIe 2.0 PHY driver support. +PCIe 2.0 PHY default connect to PCIe controller. +PCIe PHY can connect to USB 3.0 controller. + +Signed-off-by: Minda Chen +--- + drivers/phy/starfive/Kconfig | 10 ++ + drivers/phy/starfive/Makefile | 1 + + drivers/phy/starfive/phy-jh7110-pcie.c | 204 +++++++++++++++++++++++++ + 3 files changed, 215 insertions(+) + create mode 100644 drivers/phy/starfive/phy-jh7110-pcie.c + +--- a/drivers/phy/starfive/Kconfig ++++ b/drivers/phy/starfive/Kconfig +@@ -12,6 +12,16 @@ config PHY_STARFIVE_DPHY_RX + system. If M is selected, the module will be called + phy-starfive-dphy-rx. + ++config PHY_STARFIVE_JH7110_PCIE ++ tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support" ++ select GENERIC_PHY ++ select USB_PHY ++ help ++ Enable this to support the StarFive PCIe 2.0 PHY, ++ or used as USB 3.0 PHY. ++ If M is selected, the module will be called ++ phy-jh7110-pcie.ko. ++ + config PHY_STARFIVE_JH7110_USB + tristate "Starfive JH7110 USB 2.0 PHY support" + depends on USB_SUPPORT +--- a/drivers/phy/starfive/Makefile ++++ b/drivers/phy/starfive/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_PHY_STARFIVE_DPHY_RX) += phy-starfive-dphy-rx.o ++obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o + obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o +--- /dev/null ++++ b/drivers/phy/starfive/phy-jh7110-pcie.c +@@ -0,0 +1,204 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * StarFive JH7110 PCIe 2.0 PHY driver ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * Author: Minda Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PCIE_KVCO_LEVEL_OFF 0x28 ++#define PCIE_USB3_PHY_PLL_CTL_OFF 0x7c ++#define PCIE_KVCO_TUNE_SIGNAL_OFF 0x80 ++#define PCIE_USB3_PHY_ENABLE BIT(4) ++#define PHY_KVCO_FINE_TUNE_LEVEL 0x91 ++#define PHY_KVCO_FINE_TUNE_SIGNALS 0xc ++ ++#define USB_PDRSTN_SPLIT BIT(17) ++ ++#define PCIE_PHY_MODE BIT(20) ++#define PCIE_PHY_MODE_MASK GENMASK(21, 20) ++#define PCIE_USB3_BUS_WIDTH_MASK GENMASK(3, 2) ++#define PCIE_USB3_BUS_WIDTH BIT(3) ++#define PCIE_USB3_RATE_MASK GENMASK(6, 5) ++#define PCIE_USB3_RX_STANDBY_MASK BIT(7) ++#define PCIE_USB3_PHY_ENABLE BIT(4) ++ ++struct jh7110_pcie_phy { ++ struct phy *phy; ++ struct regmap *stg_syscon; ++ struct regmap *sys_syscon; ++ void __iomem *regs; ++ u32 sys_phy_connect; ++ u32 stg_pcie_mode; ++ u32 stg_pcie_usb; ++ enum phy_mode mode; ++}; ++ ++static int phy_usb3_mode_set(struct jh7110_pcie_phy *data) ++{ ++ if (!data->stg_syscon || !data->sys_syscon) { ++ dev_err(&data->phy->dev, "doesn't support usb3 mode\n"); ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_mode, ++ PCIE_PHY_MODE_MASK, PCIE_PHY_MODE); ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb, ++ PCIE_USB3_BUS_WIDTH_MASK, 0); ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb, ++ PCIE_USB3_PHY_ENABLE, PCIE_USB3_PHY_ENABLE); ++ ++ /* Connect usb 3.0 phy mode */ ++ regmap_update_bits(data->sys_syscon, data->sys_phy_connect, ++ USB_PDRSTN_SPLIT, 0); ++ ++ /* Configuare spread-spectrum mode: down-spread-spectrum */ ++ writel(PCIE_USB3_PHY_ENABLE, data->regs + PCIE_USB3_PHY_PLL_CTL_OFF); ++ ++ return 0; ++} ++ ++static void phy_pcie_mode_set(struct jh7110_pcie_phy *data) ++{ ++ u32 val; ++ ++ /* default is PCIe mode */ ++ if (!data->stg_syscon || !data->sys_syscon) ++ return; ++ ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_mode, ++ PCIE_PHY_MODE_MASK, 0); ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb, ++ PCIE_USB3_BUS_WIDTH_MASK, ++ PCIE_USB3_BUS_WIDTH); ++ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb, ++ PCIE_USB3_PHY_ENABLE, 0); ++ ++ regmap_update_bits(data->sys_syscon, data->sys_phy_connect, ++ USB_PDRSTN_SPLIT, 0); ++ ++ val = readl(data->regs + PCIE_USB3_PHY_PLL_CTL_OFF); ++ val &= ~PCIE_USB3_PHY_ENABLE; ++ writel(val, data->regs + PCIE_USB3_PHY_PLL_CTL_OFF); ++} ++ ++static void phy_kvco_gain_set(struct jh7110_pcie_phy *phy) ++{ ++ /* PCIe Multi-PHY PLL KVCO Gain fine tune settings: */ ++ writel(PHY_KVCO_FINE_TUNE_LEVEL, phy->regs + PCIE_KVCO_LEVEL_OFF); ++ writel(PHY_KVCO_FINE_TUNE_SIGNALS, phy->regs + PCIE_KVCO_TUNE_SIGNAL_OFF); ++} ++ ++static int jh7110_pcie_phy_set_mode(struct phy *_phy, ++ enum phy_mode mode, int submode) ++{ ++ struct jh7110_pcie_phy *phy = phy_get_drvdata(_phy); ++ int ret; ++ ++ if (mode == phy->mode) ++ return 0; ++ ++ switch (mode) { ++ case PHY_MODE_USB_HOST: ++ case PHY_MODE_USB_DEVICE: ++ case PHY_MODE_USB_OTG: ++ ret = phy_usb3_mode_set(phy); ++ if (ret) ++ return ret; ++ break; ++ case PHY_MODE_PCIE: ++ phy_pcie_mode_set(phy); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ dev_dbg(&_phy->dev, "Changing phy mode to %d\n", mode); ++ phy->mode = mode; ++ ++ return 0; ++} ++ ++static const struct phy_ops jh7110_pcie_phy_ops = { ++ .set_mode = jh7110_pcie_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static int jh7110_pcie_phy_probe(struct platform_device *pdev) ++{ ++ struct jh7110_pcie_phy *phy; ++ struct device *dev = &pdev->dev; ++ struct phy_provider *phy_provider; ++ u32 args[2]; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ phy->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(phy->regs)) ++ return PTR_ERR(phy->regs); ++ ++ phy->phy = devm_phy_create(dev, NULL, &jh7110_pcie_phy_ops); ++ if (IS_ERR(phy->phy)) ++ return dev_err_probe(dev, PTR_ERR(phy->regs), ++ "Failed to map phy base\n"); ++ ++ phy->sys_syscon = ++ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, ++ "starfive,sys-syscon", ++ 1, args); ++ ++ if (!IS_ERR_OR_NULL(phy->sys_syscon)) ++ phy->sys_phy_connect = args[0]; ++ else ++ phy->sys_syscon = NULL; ++ ++ phy->stg_syscon = ++ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, ++ "starfive,stg-syscon", ++ 2, args); ++ ++ if (!IS_ERR_OR_NULL(phy->stg_syscon)) { ++ phy->stg_pcie_mode = args[0]; ++ phy->stg_pcie_usb = args[1]; ++ } else { ++ phy->stg_syscon = NULL; ++ } ++ ++ phy_kvco_gain_set(phy); ++ ++ phy_set_drvdata(phy->phy, phy); ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id jh7110_pcie_phy_of_match[] = { ++ { .compatible = "starfive,jh7110-pcie-phy" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, jh7110_pcie_phy_of_match); ++ ++static struct platform_driver jh7110_pcie_phy_driver = { ++ .probe = jh7110_pcie_phy_probe, ++ .driver = { ++ .of_match_table = jh7110_pcie_phy_of_match, ++ .name = "jh7110-pcie-phy", ++ } ++}; ++module_platform_driver(jh7110_pcie_phy_driver); ++ ++MODULE_DESCRIPTION("StarFive JH7110 PCIe 2.0 PHY driver"); ++MODULE_AUTHOR("Minda Chen "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0091-dt-bindings-usb-Add-StarFive-JH7110-USB-controller.patch b/target/linux/starfive/patches-6.1/0091-dt-bindings-usb-Add-StarFive-JH7110-USB-controller.patch new file mode 100644 index 0000000000..8a7575094c --- /dev/null +++ b/target/linux/starfive/patches-6.1/0091-dt-bindings-usb-Add-StarFive-JH7110-USB-controller.patch @@ -0,0 +1,135 @@ +From 6a2392c96041d0599d33799a9aedbcdbfb4030b6 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:48 +0800 +Subject: [PATCH 091/122] dt-bindings: usb: Add StarFive JH7110 USB controller + +StarFive JH7110 platforms USB have a wrapper module around +the Cadence USBSS-DRD controller. Add binding information doc +for that. + +Signed-off-by: Minda Chen +Reviewed-by: Peter Chen +Reviewed-by: Hal Feng +--- + .../bindings/usb/starfive,jh7110-usb.yaml | 115 ++++++++++++++++++ + 1 file changed, 115 insertions(+) + create mode 100644 Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml +@@ -0,0 +1,115 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/usb/starfive,jh7110-usb.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 wrapper module for the Cadence USBSS-DRD controller ++ ++maintainers: ++ - Minda Chen ++ ++properties: ++ compatible: ++ const: starfive,jh7110-usb ++ ++ ranges: true ++ ++ starfive,stg-syscon: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ - items: ++ - description: phandle to System Register Controller stg_syscon node. ++ - description: dr mode register offset of STG_SYSCONSAIF__SYSCFG register for USB. ++ description: ++ The phandle to System Register Controller syscon node and the offset ++ of STG_SYSCONSAIF__SYSCFG register for USB. ++ ++ dr_mode: ++ enum: [host, otg, peripheral] ++ ++ "#address-cells": ++ enum: [1, 2] ++ ++ "#size-cells": ++ enum: [1, 2] ++ ++ clocks: ++ items: ++ - description: link power management clock ++ - description: standby clock ++ - description: APB clock ++ - description: AXI clock ++ - description: UTMI APB clock ++ ++ clock-names: ++ items: ++ - const: lpm ++ - const: stb ++ - const: apb ++ - const: axi ++ - const: utmi_apb ++ ++ resets: ++ items: ++ - description: Power up reset ++ - description: APB clock reset ++ - description: AXI clock reset ++ - description: UTMI APB clock reset ++ ++ reset-names: ++ items: ++ - const: pwrup ++ - const: apb ++ - const: axi ++ - const: utmi_apb ++ ++patternProperties: ++ "^usb@[0-9a-f]+$": ++ $ref: cdns,usb3.yaml# ++ description: Required child node ++ ++required: ++ - compatible ++ - ranges ++ - starfive,stg-syscon ++ - '#address-cells' ++ - '#size-cells' ++ - dr_mode ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ usb@10100000 { ++ compatible = "starfive,jh7110-usb"; ++ ranges = <0x0 0x10100000 0x100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ starfive,stg-syscon = <&stg_syscon 0x4>; ++ clocks = <&syscrg 4>, ++ <&stgcrg 5>, ++ <&stgcrg 1>, ++ <&stgcrg 3>, ++ <&stgcrg 2>; ++ clock-names = "lpm", "stb", "apb", "axi", "utmi_apb"; ++ resets = <&stgcrg 10>, ++ <&stgcrg 8>, ++ <&stgcrg 7>, ++ <&stgcrg 9>; ++ reset-names = "pwrup", "apb", "axi", "utmi_apb"; ++ dr_mode = "host"; ++ ++ usb@0 { ++ compatible = "cdns,usb3"; ++ reg = <0x0 0x10000>, ++ <0x10000 0x10000>, ++ <0x20000 0x10000>; ++ reg-names = "otg", "xhci", "dev"; ++ interrupts = <100>, <108>, <110>; ++ interrupt-names = "host", "peripheral", "otg"; ++ maximum-speed = "super-speed"; ++ }; ++ }; diff --git a/target/linux/starfive/patches-6.1/0092-dt-bindings-qspi-cdns-qspi-nor-constrain-minItems-ma.patch b/target/linux/starfive/patches-6.1/0092-dt-bindings-qspi-cdns-qspi-nor-constrain-minItems-ma.patch new file mode 100644 index 0000000000..650545cf3c --- /dev/null +++ b/target/linux/starfive/patches-6.1/0092-dt-bindings-qspi-cdns-qspi-nor-constrain-minItems-ma.patch @@ -0,0 +1,78 @@ +From 464fa29e8f3fb2c209647efbb365470b35daec38 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Thu, 2 Mar 2023 18:52:20 +0800 +Subject: [PATCH 092/122] dt-bindings: qspi: cdns,qspi-nor: constrain + minItems/maxItems of resets + +The QSPI controller needs three reset items to work properly on JH7110 SoC, +so there is need to change the maxItems's value to 3 and add minItems +whose value is equal to 2. Other platforms do not have this constraint. + +Signed-off-by: William Qiu +--- + .../bindings/spi/cdns,qspi-nor.yaml | 37 +++++++++++++++++-- + 1 file changed, 33 insertions(+), 4 deletions(-) + +--- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml ++++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml +@@ -19,6 +19,33 @@ allOf: + then: + required: + - power-domains ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: starfive,jh7110-qspi ++ then: ++ properties: ++ resets: ++ minItems: 2 ++ maxItems: 3 ++ ++ reset-names: ++ minItems: 2 ++ maxItems: 3 ++ items: ++ enum: [ qspi, qspi-ocp, rstc_ref ] ++ ++ else: ++ properties: ++ resets: ++ maxItems: 2 ++ ++ reset-names: ++ minItems: 1 ++ maxItems: 2 ++ items: ++ enum: [ qspi, qspi-ocp ] + + properties: + compatible: +@@ -30,6 +57,7 @@ properties: + - intel,lgm-qspi + - xlnx,versal-ospi-1.0 + - intel,socfpga-qspi ++ - starfive,jh7110-qspi + - const: cdns,qspi-nor + - const: cdns,qspi-nor + +@@ -79,13 +107,14 @@ properties: + maxItems: 1 + + resets: +- maxItems: 2 ++ minItems: 2 ++ maxItems: 3 + + reset-names: +- minItems: 1 +- maxItems: 2 ++ minItems: 2 ++ maxItems: 3 + items: +- enum: [ qspi, qspi-ocp ] ++ enum: [ qspi, qspi-ocp, rstc_ref ] + + required: + - compatible diff --git a/target/linux/starfive/patches-6.1/0093-usb-cdns3-Add-StarFive-JH7110-USB-driver.patch b/target/linux/starfive/patches-6.1/0093-usb-cdns3-Add-StarFive-JH7110-USB-driver.patch new file mode 100644 index 0000000000..2431dc45dd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0093-usb-cdns3-Add-StarFive-JH7110-USB-driver.patch @@ -0,0 +1,298 @@ +From 27c75f360a76084ee6a249876483cfa8d0bedd65 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 18 May 2023 19:27:49 +0800 +Subject: [PATCH 093/122] usb: cdns3: Add StarFive JH7110 USB driver + +Adds Specific Glue layer to support USB peripherals on +StarFive JH7110 SoC. +There is a Cadence USB3 core for JH7110 SoCs, the cdns +core is the child of this USB wrapper module device. + +Signed-off-by: Minda Chen +Acked-by: Peter Chen +--- + drivers/usb/cdns3/Kconfig | 11 ++ + drivers/usb/cdns3/Makefile | 1 + + drivers/usb/cdns3/cdns3-starfive.c | 246 +++++++++++++++++++++++++++++ + 3 files changed, 258 insertions(+) + create mode 100644 drivers/usb/cdns3/cdns3-starfive.c + +--- a/drivers/usb/cdns3/Kconfig ++++ b/drivers/usb/cdns3/Kconfig +@@ -78,6 +78,17 @@ config USB_CDNS3_IMX + + For example, imx8qm and imx8qxp. + ++config USB_CDNS3_STARFIVE ++ tristate "Cadence USB3 support on StarFive SoC platforms" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ help ++ Say 'Y' or 'M' here if you are building for StarFive SoCs ++ platforms that contain Cadence USB3 controller core. ++ ++ e.g. JH7110. ++ ++ If you choose to build this driver as module it will ++ be dynamically linked and module will be called cdns3-starfive.ko + endif + + if USB_CDNS_SUPPORT +--- a/drivers/usb/cdns3/Makefile ++++ b/drivers/usb/cdns3/Makefile +@@ -24,6 +24,7 @@ endif + obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o + obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o + obj-$(CONFIG_USB_CDNS3_IMX) += cdns3-imx.o ++obj-$(CONFIG_USB_CDNS3_STARFIVE) += cdns3-starfive.o + + cdnsp-udc-pci-y := cdnsp-pci.o + +--- /dev/null ++++ b/drivers/usb/cdns3/cdns3-starfive.c +@@ -0,0 +1,246 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * cdns3-starfive.c - StarFive specific Glue layer for Cadence USB Controller ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * Author: Minda Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "core.h" ++ ++#define USB_STRAP_HOST BIT(17) ++#define USB_STRAP_DEVICE BIT(18) ++#define USB_STRAP_MASK GENMASK(18, 16) ++ ++#define USB_SUSPENDM_HOST BIT(19) ++#define USB_SUSPENDM_MASK BIT(19) ++ ++#define USB_MISC_CFG_MASK GENMASK(23, 20) ++#define USB_SUSPENDM_BYPS BIT(20) ++#define USB_PLL_EN BIT(22) ++#define USB_REFCLK_MODE BIT(23) ++ ++struct cdns_starfive { ++ struct device *dev; ++ struct regmap *stg_syscon; ++ struct reset_control *resets; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ u32 stg_usb_mode; ++}; ++ ++static void cdns_mode_init(struct platform_device *pdev, ++ struct cdns_starfive *data) ++{ ++ enum usb_dr_mode mode; ++ ++ regmap_update_bits(data->stg_syscon, data->stg_usb_mode, ++ USB_MISC_CFG_MASK, ++ USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE); ++ ++ /* dr mode setting */ ++ mode = usb_get_dr_mode(&pdev->dev); ++ ++ switch (mode) { ++ case USB_DR_MODE_HOST: ++ regmap_update_bits(data->stg_syscon, ++ data->stg_usb_mode, ++ USB_STRAP_MASK, ++ USB_STRAP_HOST); ++ regmap_update_bits(data->stg_syscon, ++ data->stg_usb_mode, ++ USB_SUSPENDM_MASK, ++ USB_SUSPENDM_HOST); ++ break; ++ ++ case USB_DR_MODE_PERIPHERAL: ++ regmap_update_bits(data->stg_syscon, data->stg_usb_mode, ++ USB_STRAP_MASK, USB_STRAP_DEVICE); ++ regmap_update_bits(data->stg_syscon, data->stg_usb_mode, ++ USB_SUSPENDM_MASK, 0); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int cdns_clk_rst_init(struct cdns_starfive *data) ++{ ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(data->num_clks, data->clks); ++ if (ret) ++ return dev_err_probe(data->dev, ret, ++ "failed to enable clocks\n"); ++ ++ ret = reset_control_deassert(data->resets); ++ if (ret) { ++ dev_err(data->dev, "failed to reset clocks\n"); ++ goto err_clk_init; ++ } ++ ++ return ret; ++ ++err_clk_init: ++ clk_bulk_disable_unprepare(data->num_clks, data->clks); ++ return ret; ++} ++ ++static void cdns_clk_rst_deinit(struct cdns_starfive *data) ++{ ++ reset_control_assert(data->resets); ++ clk_bulk_disable_unprepare(data->num_clks, data->clks); ++} ++ ++static int cdns_starfive_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct cdns_starfive *data; ++ unsigned int args; ++ int ret; ++ ++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->dev = dev; ++ ++ data->stg_syscon = ++ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, ++ "starfive,stg-syscon", 1, &args); ++ ++ if (IS_ERR(data->stg_syscon)) ++ return dev_err_probe(dev, PTR_ERR(data->stg_syscon), ++ "Failed to parse starfive,stg-syscon\n"); ++ ++ data->stg_usb_mode = args; ++ ++ data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks); ++ if (data->num_clks < 0) ++ return dev_err_probe(data->dev, -ENODEV, ++ "Failed to get clocks\n"); ++ ++ data->resets = devm_reset_control_array_get_exclusive(data->dev); ++ if (IS_ERR(data->resets)) ++ return dev_err_probe(data->dev, PTR_ERR(data->resets), ++ "Failed to get resets"); ++ ++ cdns_mode_init(pdev, data); ++ ret = cdns_clk_rst_init(data); ++ if (ret) ++ return ret; ++ ++ ret = of_platform_populate(dev->of_node, NULL, NULL, dev); ++ if (ret) { ++ dev_err(dev, "Failed to create children\n"); ++ cdns_clk_rst_deinit(data); ++ return ret; ++ } ++ ++ device_set_wakeup_capable(dev, true); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ platform_set_drvdata(pdev, data); ++ ++ return 0; ++} ++ ++static int cdns_starfive_remove_core(struct device *dev, void *c) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ ++ platform_device_unregister(pdev); ++ ++ return 0; ++} ++ ++static int cdns_starfive_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct cdns_starfive *data = dev_get_drvdata(dev); ++ ++ pm_runtime_get_sync(dev); ++ device_for_each_child(dev, NULL, cdns_starfive_remove_core); ++ ++ pm_runtime_disable(dev); ++ pm_runtime_put_noidle(dev); ++ cdns_clk_rst_deinit(data); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int cdns_starfive_runtime_resume(struct device *dev) ++{ ++ struct cdns_starfive *data = dev_get_drvdata(dev); ++ ++ return clk_bulk_prepare_enable(data->num_clks, data->clks); ++} ++ ++static int cdns_starfive_runtime_suspend(struct device *dev) ++{ ++ struct cdns_starfive *data = dev_get_drvdata(dev); ++ ++ clk_bulk_disable_unprepare(data->num_clks, data->clks); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int cdns_starfive_resume(struct device *dev) ++{ ++ struct cdns_starfive *data = dev_get_drvdata(dev); ++ ++ return cdns_clk_rst_init(data); ++} ++ ++static int cdns_starfive_suspend(struct device *dev) ++{ ++ struct cdns_starfive *data = dev_get_drvdata(dev); ++ ++ cdns_clk_rst_deinit(data); ++ ++ return 0; ++} ++#endif ++#endif ++ ++static const struct dev_pm_ops cdns_starfive_pm_ops = { ++ SET_RUNTIME_PM_OPS(cdns_starfive_runtime_suspend, ++ cdns_starfive_runtime_resume, NULL) ++ SET_SYSTEM_SLEEP_PM_OPS(cdns_starfive_suspend, cdns_starfive_resume) ++}; ++ ++static const struct of_device_id cdns_starfive_of_match[] = { ++ { .compatible = "starfive,jh7110-usb", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, cdns_starfive_of_match); ++ ++static struct platform_driver cdns_starfive_driver = { ++ .probe = cdns_starfive_probe, ++ .remove = cdns_starfive_remove, ++ .driver = { ++ .name = "cdns3-starfive", ++ .of_match_table = cdns_starfive_of_match, ++ .pm = &cdns_starfive_pm_ops, ++ }, ++}; ++module_platform_driver(cdns_starfive_driver); ++ ++MODULE_ALIAS("platform:cdns3-starfive"); ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Cadence USB3 StarFive Glue Layer"); diff --git a/target/linux/starfive/patches-6.1/0094-dt-binding-pci-add-JH7110-PCIe-dt-binding-documents.patch b/target/linux/starfive/patches-6.1/0094-dt-binding-pci-add-JH7110-PCIe-dt-binding-documents.patch new file mode 100644 index 0000000000..150fef8eb4 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0094-dt-binding-pci-add-JH7110-PCIe-dt-binding-documents.patch @@ -0,0 +1,181 @@ +From 3d555cfd72df1a02849565f281149d321e0f8425 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 6 Apr 2023 19:11:40 +0800 +Subject: [PATCH 094/122] dt-binding: pci: add JH7110 PCIe dt-binding + documents. + +Add PCIe controller driver dt-binding documents +for StarFive JH7110 SoC platform. + +Signed-off-by: Minda Chen +--- + .../bindings/pci/starfive,jh7110-pcie.yaml | 163 ++++++++++++++++++ + 1 file changed, 163 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml +@@ -0,0 +1,163 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/pci/starfive,jh7110-pcie.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7110 PCIe 2.0 host controller ++ ++maintainers: ++ - Minda Chen ++ ++allOf: ++ - $ref: /schemas/pci/pci-bus.yaml# ++ - $ref: /schemas/interrupt-controller/msi-controller.yaml# ++ ++properties: ++ compatible: ++ const: starfive,jh7110-pcie ++ ++ reg: ++ maxItems: 2 ++ ++ reg-names: ++ items: ++ - const: reg ++ - const: config ++ ++ msi-parent: true ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 4 ++ ++ clock-names: ++ items: ++ - const: noc ++ - const: tl ++ - const: axi_mst0 ++ - const: apb ++ ++ resets: ++ items: ++ - description: AXI MST0 reset ++ - description: AXI SLAVE reset ++ - description: AXI SLAVE0 reset ++ - description: PCIE BRIDGE reset ++ - description: PCIE CORE reset ++ - description: PCIE APB reset ++ ++ reset-names: ++ items: ++ - const: mst0 ++ - const: slv0 ++ - const: slv ++ - const: brg ++ - const: core ++ - const: apb ++ ++ starfive,stg-syscon: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ items: ++ - description: phandle to System Register Controller stg_syscon node. ++ - description: register0 offset of STG_SYSCONSAIF__SYSCFG register for PCIe. ++ - description: register1 offset of STG_SYSCONSAIF__SYSCFG register for PCIe. ++ - description: register2 offset of STG_SYSCONSAIF__SYSCFG register for PCIe. ++ - description: register3 offset of STG_SYSCONSAIF__SYSCFG register for PCIe. ++ description: ++ The phandle to System Register Controller syscon node and the offset ++ of STG_SYSCONSAIF__SYSCFG register for PCIe. Total 4 regsisters offset ++ for PCIe. ++ ++ pwren-gpios: ++ description: Should specify the GPIO for controlling the PCI bus device power on. ++ maxItems: 1 ++ ++ reset-gpios: ++ maxItems: 1 ++ ++ phys: ++ maxItems: 1 ++ ++ interrupt-controller: ++ type: object ++ properties: ++ '#address-cells': ++ const: 0 ++ ++ '#interrupt-cells': ++ const: 1 ++ ++ interrupt-controller: true ++ ++ required: ++ - '#address-cells' ++ - '#interrupt-cells' ++ - interrupt-controller ++ ++ additionalProperties: false ++ ++required: ++ - reg ++ - reg-names ++ - "#interrupt-cells" ++ - interrupts ++ - interrupt-map-mask ++ - interrupt-map ++ - clocks ++ - clock-names ++ - resets ++ - msi-controller ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ bus { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ pcie0: pcie@2B000000 { ++ compatible = "starfive,jh7110-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ reg = <0x0 0x2B000000 0x0 0x1000000>, ++ <0x9 0x40000000 0x0 0x10000000>; ++ reg-names = "reg", "config"; ++ device_type = "pci"; ++ starfive,stg-syscon = <&stg_syscon 0xc0 0xc4 0x130 0x1b8>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>, ++ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>; ++ interrupt-parent = <&plic>; ++ interrupts = <56>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>, ++ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>, ++ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>, ++ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>; ++ msi-parent = <&pcie0>; ++ msi-controller; ++ clocks = <&syscrg 86>, ++ <&stgcrg 10>, ++ <&stgcrg 8>, ++ <&stgcrg 9>; ++ clock-names = "noc", "tl", "axi_mst0", "apb"; ++ resets = <&stgcrg 11>, ++ <&stgcrg 12>, ++ <&stgcrg 13>, ++ <&stgcrg 14>, ++ <&stgcrg 15>, ++ <&stgcrg 16>; ++ ++ pcie_intc0: interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ }; ++ }; ++ }; diff --git a/target/linux/starfive/patches-6.1/0095-spi-cadence-quadspi-Add-support-for-StarFive-JH7110-.patch b/target/linux/starfive/patches-6.1/0095-spi-cadence-quadspi-Add-support-for-StarFive-JH7110-.patch new file mode 100644 index 0000000000..de701baaa9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0095-spi-cadence-quadspi-Add-support-for-StarFive-JH7110-.patch @@ -0,0 +1,79 @@ +From a3749d68d81488ae07878393485278eab24a5818 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Thu, 2 Mar 2023 18:52:21 +0800 +Subject: [PATCH 095/122] spi: cadence-quadspi: Add support for StarFive JH7110 + QSPI + +Add QSPI reset operation in device probe and add RISCV support to +QUAD SPI Kconfig. + +Co-developed-by: Ziv Xu +Signed-off-by: Ziv Xu +Signed-off-by: William Qiu +--- + drivers/spi/Kconfig | 2 +- + drivers/spi/spi-cadence-quadspi.c | 21 ++++++++++++++++++++- + 2 files changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -230,7 +230,7 @@ config SPI_CADENCE + + config SPI_CADENCE_QUADSPI + tristate "Cadence Quad SPI controller" +- depends on OF && (ARM || ARM64 || X86 || COMPILE_TEST) ++ depends on OF && (ARM || ARM64 || X86 || RISCV || COMPILE_TEST) + help + Enable support for the Cadence Quad SPI Flash controller. + +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -1575,7 +1575,7 @@ static int cqspi_setup_flash(struct cqsp + static int cqspi_probe(struct platform_device *pdev) + { + const struct cqspi_driver_platdata *ddata; +- struct reset_control *rstc, *rstc_ocp; ++ struct reset_control *rstc, *rstc_ocp, *rstc_ref; + struct device *dev = &pdev->dev; + struct spi_master *master; + struct resource *res_ahb; +@@ -1668,6 +1668,17 @@ static int cqspi_probe(struct platform_d + goto probe_reset_failed; + } + ++ if (of_device_is_compatible(pdev->dev.of_node, "starfive,jh7110-qspi")) { ++ rstc_ref = devm_reset_control_get_optional_exclusive(dev, "rstc_ref"); ++ if (IS_ERR(rstc_ref)) { ++ ret = PTR_ERR(rstc_ref); ++ dev_err(dev, "Cannot get QSPI REF reset.\n"); ++ goto probe_reset_failed; ++ } ++ reset_control_assert(rstc_ref); ++ reset_control_deassert(rstc_ref); ++ } ++ + reset_control_assert(rstc); + reset_control_deassert(rstc); + +@@ -1827,6 +1838,10 @@ static const struct cqspi_driver_platdat + .get_dma_status = cqspi_get_versal_dma_status, + }; + ++static const struct cqspi_driver_platdata jh7110_qspi = { ++ .quirks = CQSPI_DISABLE_DAC_MODE, ++}; ++ + static const struct of_device_id cqspi_dt_ids[] = { + { + .compatible = "cdns,qspi-nor", +@@ -1852,6 +1867,10 @@ static const struct of_device_id cqspi_d + .compatible = "intel,socfpga-qspi", + .data = &socfpga_qspi, + }, ++ { ++ .compatible = "starfive,jh7110-qspi", ++ .data = &jh7110_qspi, ++ }, + { /* end of table */ } + }; + diff --git a/target/linux/starfive/patches-6.1/0096-pcie-starfive-add-StarFive-JH7110-PCIe-driver.patch b/target/linux/starfive/patches-6.1/0096-pcie-starfive-add-StarFive-JH7110-PCIe-driver.patch new file mode 100644 index 0000000000..ffd413c088 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0096-pcie-starfive-add-StarFive-JH7110-PCIe-driver.patch @@ -0,0 +1,1004 @@ +From e0cd43bcbc9b74343e529fde66a3ec20b533ac61 Mon Sep 17 00:00:00 2001 +From: Minda Chen +Date: Thu, 6 Apr 2023 19:11:41 +0800 +Subject: [PATCH 096/122] pcie: starfive: add StarFive JH7110 PCIe driver. + +Add PCIe controller driver for StarFive JH7110 +SoC platform. The PCIe controller is PCIe 2.0, single lane. + +Signed-off-by: Minda Chen +--- + drivers/pci/controller/Kconfig | 8 + + drivers/pci/controller/Makefile | 1 + + drivers/pci/controller/pcie-starfive.c | 958 +++++++++++++++++++++++++ + 3 files changed, 967 insertions(+) + create mode 100644 drivers/pci/controller/pcie-starfive.c + +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -343,6 +343,14 @@ config PCIE_MT7621 + help + This selects a driver for the MediaTek MT7621 PCIe Controller. + ++config PCIE_STARFIVE ++ tristate "StarFive JH7110 PCIe controller" ++ depends on PCI_MSI && OF ++ select PCI_MSI_IRQ_DOMAIN ++ help ++ Say 'Y' here if you want kernel to support the StarFive JH7110 ++ PCIe Host driver. ++ + source "drivers/pci/controller/dwc/Kconfig" + source "drivers/pci/controller/mobiveil/Kconfig" + source "drivers/pci/controller/cadence/Kconfig" +--- a/drivers/pci/controller/Makefile ++++ b/drivers/pci/controller/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_PCI_LOONGSON) += pci-loongs + obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o + obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o + obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o ++obj-$(CONFIG_PCIE_STARFIVE) += pcie-starfive.o + + # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW + obj-y += dwc/ +--- /dev/null ++++ b/drivers/pci/controller/pcie-starfive.c +@@ -0,0 +1,958 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * PCIe host controller driver for Starfive JH7110 Soc. ++ * ++ * Based on pcie-altera.c, pcie-altera-msi.c. ++ * ++ * Copyright (C) StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../pci.h" ++ ++#define IMASK_LOCAL 0x180 ++#define ISTATUS_LOCAL 0x184 ++#define IMSI_ADDR 0x190 ++#define ISTATUS_MSI 0x194 ++#define GEN_SETTINGS 0x80 ++#define PCIE_PCI_IDS 0x9C ++#define PCIE_WINROM 0xFC ++#define PMSG_SUPPORT_RX 0x3F0 ++ ++#define PCI_MISC 0xB4 ++ ++#define RP_ENABLE 1 ++ ++#define IDS_CLASS_CODE_SHIFT 16 ++ ++#define DATA_LINK_ACTIVE BIT(5) ++#define PREF_MEM_WIN_64_SUPPORT BIT(3) ++#define PMSG_LTR_SUPPORT BIT(2) ++#define LINK_SPEED_GEN2 BIT(12) ++#define PHY_FUNCTION_DIS BIT(15) ++#define PCIE_FUNC_NUM 4 ++#define PHY_FUNC_SHIFT 9 ++ ++#define XR3PCI_ATR_AXI4_SLV0 0x800 ++#define XR3PCI_ATR_SRC_ADDR_LOW 0x0 ++#define XR3PCI_ATR_SRC_ADDR_HIGH 0x4 ++#define XR3PCI_ATR_TRSL_ADDR_LOW 0x8 ++#define XR3PCI_ATR_TRSL_ADDR_HIGH 0xc ++#define XR3PCI_ATR_TRSL_PARAM 0x10 ++#define XR3PCI_ATR_TABLE_OFFSET 0x20 ++#define XR3PCI_ATR_MAX_TABLE_NUM 8 ++ ++#define XR3PCI_ATR_SRC_WIN_SIZE_SHIFT 1 ++#define XR3PCI_ATR_SRC_ADDR_MASK GENMASK(31, 12) ++#define XR3PCI_ATR_TRSL_ADDR_MASK GENMASK(31, 12) ++#define XR3PCI_ECAM_SIZE BIT(28) ++#define XR3PCI_ATR_TRSL_DIR BIT(22) ++/* IDs used in the XR3PCI_ATR_TRSL_PARAM */ ++#define XR3PCI_ATR_TRSLID_PCIE_MEMORY 0x0 ++#define XR3PCI_ATR_TRSLID_PCIE_CONFIG 0x1 ++ ++#define INT_AXI_POST_ERROR BIT(16) ++#define INT_AXI_FETCH_ERROR BIT(17) ++#define INT_AXI_DISCARD_ERROR BIT(18) ++#define INT_PCIE_POST_ERROR BIT(20) ++#define INT_PCIE_FETCH_ERROR BIT(21) ++#define INT_PCIE_DISCARD_ERROR BIT(22) ++#define INT_ERRORS (INT_AXI_POST_ERROR | INT_AXI_FETCH_ERROR | \ ++ INT_AXI_DISCARD_ERROR | INT_PCIE_POST_ERROR | \ ++ INT_PCIE_FETCH_ERROR | INT_PCIE_DISCARD_ERROR) ++ ++#define INTA_OFFSET 24 ++#define INTA BIT(24) ++#define INTB BIT(25) ++#define INTC BIT(26) ++#define INTD BIT(27) ++#define INT_MSI BIT(28) ++#define INT_INTX_MASK (INTA | INTB | INTC | INTD) ++#define INT_MASK (INT_INTX_MASK | INT_MSI | INT_ERRORS) ++ ++#define INT_PCI_MSI_NR 32 ++ ++/* system control */ ++#define STG_SYSCON_K_RP_NEP BIT(8) ++#define STG_SYSCON_AXI4_SLVL_ARFUNC_MASK GENMASK(22, 8) ++#define STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT 8 ++#define STG_SYSCON_AXI4_SLVL_AWFUNC_MASK GENMASK(14, 0) ++#define STG_SYSCON_CLKREQ BIT(22) ++#define STG_SYSCON_CKREF_SRC_SHIFT 18 ++#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18) ++ ++/* MSI information */ ++struct jh7110_pcie_msi { ++ DECLARE_BITMAP(used, INT_PCI_MSI_NR); ++ struct irq_domain *msi_domain; ++ struct irq_domain *inner_domain; ++ /* Protect bitmap variable */ ++ struct mutex lock; ++}; ++ ++struct starfive_jh7110_pcie { ++ struct platform_device *pdev; ++ void __iomem *reg_base; ++ void __iomem *config_base; ++ phys_addr_t config_phyaddr; ++ struct regmap *reg_syscon; ++ struct phy *phy; ++ u32 stg_arfun; ++ u32 stg_awfun; ++ u32 stg_rp_nep; ++ u32 stg_lnksta; ++ int irq; ++ struct irq_domain *legacy_irq_domain; ++ struct pci_host_bridge *bridge; ++ struct jh7110_pcie_msi msi; ++ struct reset_control *resets; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ int atr_table_num; ++ struct gpio_desc *power_gpio; ++ struct gpio_desc *reset_gpio; ++}; ++ ++/* ++ * StarFive PCIe port uses BAR0-BAR1 of RC's configuration space as ++ * the translation from PCI bus to native BUS. Entire DDR region ++ * is mapped into PCIe space using these registers, so it can be ++ * reached by DMA from EP devices. The BAR0/1 of bridge should be ++ * hidden during enumeration to avoid the sizing and resource allocation ++ * by PCIe core. ++ */ ++static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn, ++ int offset) ++{ ++ if (pci_is_root_bus(bus) && (devfn == 0) ++ && ((offset == PCI_BASE_ADDRESS_0) ++ || (offset == PCI_BASE_ADDRESS_1))) ++ return true; ++ ++ return false; ++} ++ ++void __iomem *starfive_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, ++ int where) ++{ ++ struct starfive_jh7110_pcie *pcie = bus->sysdata; ++ ++ return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where); ++} ++ ++int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ if (starfive_pcie_hide_rc_bar(bus, devfn, where)) ++ return PCIBIOS_BAD_REGISTER_NUMBER; ++ ++ return pci_generic_config_write(bus, devfn, where, size, value); ++} ++ ++static void starfive_pcie_handle_msi_irq(struct starfive_jh7110_pcie *pcie) ++{ ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ u32 bit; ++ u32 virq; ++ unsigned long status = readl(pcie->reg_base + ISTATUS_MSI); ++ ++ for_each_set_bit(bit, &status, INT_PCI_MSI_NR) { ++ /* Clear interrupts */ ++ writel(1 << bit, pcie->reg_base + ISTATUS_MSI); ++ virq = irq_find_mapping(msi->inner_domain, bit); ++ if (virq) { ++ if (test_bit(bit, msi->used)) ++ generic_handle_irq(virq); ++ else ++ dev_err(&pcie->pdev->dev, ++ "Unhandled MSI, MSI%d virq %d\n", bit, ++ virq); ++ } else ++ dev_err(&pcie->pdev->dev, "Unexpected MSI, MSI%d\n", ++ bit); ++ } ++ writel(INT_MSI, pcie->reg_base + ISTATUS_LOCAL); ++} ++ ++static void starfive_pcie_handle_intx_irq(struct starfive_jh7110_pcie *pcie, ++ unsigned long status) ++{ ++ u32 bit; ++ u32 virq; ++ ++ status >>= INTA_OFFSET; ++ ++ for_each_set_bit(bit, &status, PCI_NUM_INTX) { ++ /* Clear interrupts */ ++ writel(1 << (bit + INTA_OFFSET), pcie->reg_base + ISTATUS_LOCAL); ++ ++ virq = irq_find_mapping(pcie->legacy_irq_domain, bit); ++ if (virq) ++ generic_handle_irq(virq); ++ else ++ dev_err(&pcie->pdev->dev, ++ "unexpected IRQ, INT%d\n", bit); ++ } ++} ++ ++static void starfive_pcie_handle_errors_irq(struct starfive_jh7110_pcie *pcie, u32 status) ++{ ++ if (status & INT_AXI_POST_ERROR) ++ dev_err(&pcie->pdev->dev, "AXI post error\n"); ++ if (status & INT_AXI_FETCH_ERROR) ++ dev_err(&pcie->pdev->dev, "AXI fetch error\n"); ++ if (status & INT_AXI_DISCARD_ERROR) ++ dev_err(&pcie->pdev->dev, "AXI discard error\n"); ++ if (status & INT_PCIE_POST_ERROR) ++ dev_err(&pcie->pdev->dev, "PCIe post error\n"); ++ if (status & INT_PCIE_FETCH_ERROR) ++ dev_err(&pcie->pdev->dev, "PCIe fetch error\n"); ++ if (status & INT_PCIE_DISCARD_ERROR) ++ dev_err(&pcie->pdev->dev, "PCIe discard error\n"); ++ ++ writel(INT_ERRORS, pcie->reg_base + ISTATUS_LOCAL); ++} ++ ++static void starfive_pcie_isr(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct starfive_jh7110_pcie *pcie; ++ u32 status; ++ ++ chained_irq_enter(chip, desc); ++ pcie = irq_desc_get_handler_data(desc); ++ ++ status = readl(pcie->reg_base + ISTATUS_LOCAL); ++ while ((status = (readl(pcie->reg_base + ISTATUS_LOCAL) & INT_MASK))) { ++ if (status & INT_INTX_MASK) ++ starfive_pcie_handle_intx_irq(pcie, status); ++ ++ if (status & INT_MSI) ++ starfive_pcie_handle_msi_irq(pcie); ++ ++ if (status & INT_ERRORS) ++ starfive_pcie_handle_errors_irq(pcie, status); ++ } ++ ++ chained_irq_exit(chip, desc); ++} ++ ++#ifdef CONFIG_PCI_MSI ++static struct irq_chip starfive_pcie_msi_irq_chip = { ++ .name = "StarFive PCIe MSI", ++ .irq_mask = pci_msi_mask_irq, ++ .irq_unmask = pci_msi_unmask_irq, ++}; ++ ++static struct msi_domain_info starfive_pcie_msi_domain_info = { ++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | ++ MSI_FLAG_PCI_MSIX), ++ .chip = &starfive_pcie_msi_irq_chip, ++}; ++#endif ++ ++static void starfive_pcie_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) ++{ ++ struct starfive_jh7110_pcie *pcie = irq_data_get_irq_chip_data(data); ++ phys_addr_t msi_addr = readl(pcie->reg_base + IMSI_ADDR); ++ ++ msg->address_lo = lower_32_bits(msi_addr); ++ msg->address_hi = upper_32_bits(msi_addr); ++ msg->data = data->hwirq; ++ ++ dev_info(&pcie->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n", ++ (int)data->hwirq, msg->address_hi, msg->address_lo); ++} ++ ++static int starfive_pcie_msi_set_affinity(struct irq_data *irq_data, ++ const struct cpumask *mask, bool force) ++{ ++ return -EINVAL; ++} ++ ++static struct irq_chip starfive_irq_chip = { ++ .name = "StarFive MSI", ++ .irq_compose_msi_msg = starfive_pcie_compose_msi_msg, ++ .irq_set_affinity = starfive_pcie_msi_set_affinity, ++}; ++ ++static int starfive_pcie_msi_alloc(struct irq_domain *domain, unsigned int virq, ++ unsigned int nr_irqs, void *args) ++{ ++ struct starfive_jh7110_pcie *pcie = domain->host_data; ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ int bit; ++ ++ WARN_ON(nr_irqs != 1); ++ mutex_lock(&msi->lock); ++ ++ bit = find_first_zero_bit(msi->used, INT_PCI_MSI_NR); ++ if (bit >= INT_PCI_MSI_NR) { ++ mutex_unlock(&msi->lock); ++ return -ENOSPC; ++ } ++ ++ set_bit(bit, msi->used); ++ ++ irq_domain_set_info(domain, virq, bit, &starfive_irq_chip, ++ domain->host_data, handle_simple_irq, ++ NULL, NULL); ++ mutex_unlock(&msi->lock); ++ ++ return 0; ++} ++ ++static void starfive_pcie_msi_free(struct irq_domain *domain, unsigned int virq, ++ unsigned int nr_irqs) ++{ ++ struct irq_data *data = irq_domain_get_irq_data(domain, virq); ++ struct starfive_jh7110_pcie *pcie = irq_data_get_irq_chip_data(data); ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ ++ mutex_lock(&msi->lock); ++ ++ if (!test_bit(data->hwirq, msi->used)) ++ dev_err(&pcie->pdev->dev, "Trying to free unused MSI#%lu\n", ++ data->hwirq); ++ else ++ __clear_bit(data->hwirq, msi->used); ++ ++ writel(0xffffffff, pcie->reg_base + ISTATUS_MSI); ++ mutex_unlock(&msi->lock); ++} ++ ++static const struct irq_domain_ops dev_msi_domain_ops = { ++ .alloc = starfive_pcie_msi_alloc, ++ .free = starfive_pcie_msi_free, ++}; ++ ++static void starfive_pcie_msi_free_irq_domain(struct starfive_jh7110_pcie *pcie) ++{ ++#ifdef CONFIG_PCI_MSI ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ u32 irq; ++ int i; ++ ++ for (i = 0; i < INT_PCI_MSI_NR; i++) { ++ irq = irq_find_mapping(msi->inner_domain, i); ++ if (irq > 0) ++ irq_dispose_mapping(irq); ++ } ++ ++ if (msi->msi_domain) ++ irq_domain_remove(msi->msi_domain); ++ ++ if (msi->inner_domain) ++ irq_domain_remove(msi->inner_domain); ++#endif ++} ++ ++static void starfive_pcie_free_irq_domain(struct starfive_jh7110_pcie *pcie) ++{ ++ int i; ++ u32 irq; ++ ++ /* Disable all interrupts */ ++ writel(0, pcie->reg_base + IMASK_LOCAL); ++ ++ if (pcie->legacy_irq_domain) { ++ for (i = 0; i < PCI_NUM_INTX; i++) { ++ irq = irq_find_mapping(pcie->legacy_irq_domain, i); ++ if (irq > 0) ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(pcie->legacy_irq_domain); ++ } ++ ++ if (pci_msi_enabled()) ++ starfive_pcie_msi_free_irq_domain(pcie); ++ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); ++} ++ ++static int starfive_pcie_init_msi_irq_domain(struct starfive_jh7110_pcie *pcie) ++{ ++#ifdef CONFIG_PCI_MSI ++ struct fwnode_handle *fwn = of_node_to_fwnode(pcie->pdev->dev.of_node); ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ ++ msi->inner_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR, ++ &dev_msi_domain_ops, pcie); ++ if (!msi->inner_domain) { ++ dev_err(&pcie->pdev->dev, "Failed to create dev IRQ domain\n"); ++ return -ENOMEM; ++ } ++ msi->msi_domain = pci_msi_create_irq_domain(fwn, &starfive_pcie_msi_domain_info, ++ msi->inner_domain); ++ if (!msi->msi_domain) { ++ dev_err(&pcie->pdev->dev, "Failed to create msi IRQ domain\n"); ++ irq_domain_remove(msi->inner_domain); ++ return -ENOMEM; ++ } ++#endif ++ return 0; ++} ++ ++static int starfive_pcie_enable_msi(struct starfive_jh7110_pcie *pcie, struct pci_bus *bus) ++{ ++ struct jh7110_pcie_msi *msi = &pcie->msi; ++ u32 reg; ++ ++ mutex_init(&msi->lock); ++ ++ /* Enable MSI */ ++ reg = readl(pcie->reg_base + IMASK_LOCAL); ++ reg |= INT_MSI; ++ writel(reg, pcie->reg_base + IMASK_LOCAL); ++ return 0; ++} ++ ++static int starfive_pcie_intx_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq); ++ irq_set_chip_data(irq, domain->host_data); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops intx_domain_ops = { ++ .map = starfive_pcie_intx_map, ++ .xlate = pci_irqd_intx_xlate, ++}; ++ ++static int starfive_pcie_init_irq_domain(struct starfive_jh7110_pcie *pcie) ++{ ++ struct device *dev = &pcie->pdev->dev; ++ struct device_node *node = dev->of_node; ++ int ret; ++ ++ if (pci_msi_enabled()) { ++ ret = starfive_pcie_init_msi_irq_domain(pcie); ++ if (ret != 0) ++ return -ENOMEM; ++ } ++ ++ /* Setup INTx */ ++ pcie->legacy_irq_domain = irq_domain_add_linear(node, PCI_NUM_INTX, ++ &intx_domain_ops, pcie); ++ ++ if (!pcie->legacy_irq_domain) { ++ dev_err(dev, "Failed to get a INTx IRQ domain\n"); ++ return -ENOMEM; ++ } ++ ++ irq_set_chained_handler_and_data(pcie->irq, starfive_pcie_isr, pcie); ++ ++ return 0; ++} ++ ++static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie) ++{ ++ struct resource *cfg_res; ++ struct platform_device *pdev = pcie->pdev; ++ unsigned int args[4]; ++ ++ pcie->reg_base = ++ devm_platform_ioremap_resource_byname(pdev, "reg"); ++ ++ if (IS_ERR(pcie->reg_base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pcie->reg_base), ++ "Failed to map reg memory\n"); ++ ++ cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); ++ if (!cfg_res) ++ return dev_err_probe(&pdev->dev, -ENODEV, ++ "Failed to get config memory\n"); ++ ++ pcie->config_base = devm_ioremap_resource(&pdev->dev, cfg_res); ++ if (IS_ERR(pcie->config_base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pcie->config_base), ++ "Failed to map config memory\n"); ++ ++ pcie->config_phyaddr = cfg_res->start; ++ ++ pcie->phy = devm_phy_optional_get(&pdev->dev, NULL); ++ if (IS_ERR(pcie->phy)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pcie->phy), ++ "Failed to get pcie phy\n"); ++ ++ pcie->irq = platform_get_irq(pdev, 0); ++ if (pcie->irq < 0) ++ return dev_err_probe(&pdev->dev, -EINVAL, ++ "Failed to get IRQ: %d\n", pcie->irq); ++ ++ pcie->reg_syscon = syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, ++ "starfive,stg-syscon", 4, args); ++ ++ if (IS_ERR(pcie->reg_syscon)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pcie->reg_syscon), ++ "Failed to parse starfive,stg-syscon\n"); ++ ++ pcie->stg_arfun = args[0]; ++ pcie->stg_awfun = args[1]; ++ pcie->stg_rp_nep = args[2]; ++ pcie->stg_lnksta = args[3]; ++ ++ /* Clear all interrupts */ ++ writel(0xffffffff, pcie->reg_base + ISTATUS_LOCAL); ++ writel(INT_INTX_MASK | INT_ERRORS, pcie->reg_base + IMASK_LOCAL); ++ ++ return 0; ++} ++ ++static struct pci_ops starfive_pcie_ops = { ++ .map_bus = starfive_pcie_map_bus, ++ .read = pci_generic_config_read, ++ .write = starfive_pcie_config_write, ++}; ++ ++static void starfive_pcie_set_atr_entry(struct starfive_jh7110_pcie *pcie, ++ phys_addr_t src_addr, phys_addr_t trsl_addr, ++ size_t window_size, int trsl_param) ++{ ++ void __iomem *base = ++ pcie->reg_base + XR3PCI_ATR_AXI4_SLV0; ++ ++ /* Support AXI4 Slave 0 Address Translation Tables 0-7. */ ++ if (pcie->atr_table_num >= XR3PCI_ATR_MAX_TABLE_NUM) ++ pcie->atr_table_num = XR3PCI_ATR_MAX_TABLE_NUM - 1; ++ base += XR3PCI_ATR_TABLE_OFFSET * pcie->atr_table_num; ++ pcie->atr_table_num++; ++ ++ /* ++ * X3PCI_ATR_SRC_ADDR_LOW: ++ * - bit 0: enable entry, ++ * - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1) ++ * - bits 7-11: reserved ++ * - bits 12-31: start of source address ++ */ ++ writel((lower_32_bits(src_addr) & XR3PCI_ATR_SRC_ADDR_MASK) | ++ (fls(window_size) - 1) << XR3PCI_ATR_SRC_WIN_SIZE_SHIFT | 1, ++ base + XR3PCI_ATR_SRC_ADDR_LOW); ++ writel(upper_32_bits(src_addr), base + XR3PCI_ATR_SRC_ADDR_HIGH); ++ writel((lower_32_bits(trsl_addr) & XR3PCI_ATR_TRSL_ADDR_MASK), ++ base + XR3PCI_ATR_TRSL_ADDR_LOW); ++ writel(upper_32_bits(trsl_addr), base + XR3PCI_ATR_TRSL_ADDR_HIGH); ++ writel(trsl_param, base + XR3PCI_ATR_TRSL_PARAM); ++ ++ dev_info(&pcie->pdev->dev, "ATR entry: 0x%010llx %s 0x%010llx [0x%010llx] (param: 0x%06x)\n", ++ src_addr, (trsl_param & XR3PCI_ATR_TRSL_DIR) ? "<-" : "->", ++ trsl_addr, (u64)window_size, trsl_param); ++} ++ ++static int starfive_pcie_setup_windows(struct starfive_jh7110_pcie *pcie) ++{ ++ struct pci_host_bridge *bridge = pcie->bridge; ++ struct resource_entry *entry; ++ u64 pci_addr; ++ ++ resource_list_for_each_entry(entry, &bridge->windows) { ++ if (resource_type(entry->res) == IORESOURCE_MEM) { ++ pci_addr = entry->res->start - entry->offset; ++ starfive_pcie_set_atr_entry(pcie, ++ entry->res->start, pci_addr, ++ resource_size(entry->res), ++ XR3PCI_ATR_TRSLID_PCIE_MEMORY); ++ } ++ } ++ ++ return 0; ++} ++ ++static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie) ++{ ++ int ret; ++ struct device *dev = &pcie->pdev->dev; ++ ++ pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks); ++ if (pcie->num_clks < 0) ++ return dev_err_probe(dev, -ENODEV, ++ "Failed to get pcie clocks\n"); ++ ++ ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); ++ if (ret) ++ return dev_err_probe(&pcie->pdev->dev, ret, ++ "Failed to enable clocks\n"); ++ ++ pcie->resets = devm_reset_control_array_get_exclusive(dev); ++ if (IS_ERR(pcie->resets)) { ++ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); ++ return dev_err_probe(dev, PTR_ERR(pcie->resets), ++ "Failed to get pcie resets"); ++ } ++ ++ return reset_control_deassert(pcie->resets); ++} ++ ++static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie) ++{ ++ reset_control_assert(pcie->resets); ++ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); ++} ++ ++int starfive_pcie_gpio_init(struct starfive_jh7110_pcie *pcie) ++{ ++ struct device *dev = &pcie->pdev->dev; ++ ++ pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR_OR_NULL(pcie->reset_gpio)) { ++ dev_warn(dev, "Failed to get reset-gpio.\n"); ++ return -EINVAL; ++ } ++ ++ pcie->power_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); ++ if (IS_ERR_OR_NULL(pcie->power_gpio)) ++ pcie->power_gpio = NULL; ++ ++ return 0; ++} ++ ++static void starfive_pcie_hw_init(struct starfive_jh7110_pcie *pcie) ++{ ++ unsigned int value; ++ int i; ++ ++ if (pcie->power_gpio) ++ gpiod_set_value_cansleep(pcie->power_gpio, 1); ++ ++ if (pcie->reset_gpio) ++ gpiod_set_value_cansleep(pcie->reset_gpio, 1); ++ ++ /* Disable physical functions except #0 */ ++ for (i = 1; i < PCIE_FUNC_NUM; i++) { ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_arfun, ++ STG_SYSCON_AXI4_SLVL_ARFUNC_MASK, ++ (i << PHY_FUNC_SHIFT) << ++ STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT); ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_awfun, ++ STG_SYSCON_AXI4_SLVL_AWFUNC_MASK, ++ i << PHY_FUNC_SHIFT); ++ ++ value = readl(pcie->reg_base + PCI_MISC); ++ value |= PHY_FUNCTION_DIS; ++ writel(value, pcie->reg_base + PCI_MISC); ++ } ++ ++ ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_arfun, ++ STG_SYSCON_AXI4_SLVL_ARFUNC_MASK, ++ 0); ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_awfun, ++ STG_SYSCON_AXI4_SLVL_AWFUNC_MASK, ++ 0); ++ ++ /* Enable root port */ ++ value = readl(pcie->reg_base + GEN_SETTINGS); ++ value |= RP_ENABLE; ++ writel(value, pcie->reg_base + GEN_SETTINGS); ++ ++ /* PCIe PCI Standard Configuration Identification Settings. */ ++ value = (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT); ++ writel(value, pcie->reg_base + PCIE_PCI_IDS); ++ ++ /* ++ * The LTR message forwarding of PCIe Message Reception was set by core ++ * as default, but the forward id & addr are also need to be reset. ++ * If we do not disable LTR message forwarding here, or set a legal ++ * forwarding address, the kernel will get stuck after this driver probe. ++ * To workaround, disable the LTR message forwarding support on ++ * PCIe Message Reception. ++ */ ++ value = readl(pcie->reg_base + PMSG_SUPPORT_RX); ++ value &= ~PMSG_LTR_SUPPORT; ++ writel(value, pcie->reg_base + PMSG_SUPPORT_RX); ++ ++ /* Prefetchable memory window 64-bit addressing support */ ++ value = readl(pcie->reg_base + PCIE_WINROM); ++ value |= PREF_MEM_WIN_64_SUPPORT; ++ writel(value, pcie->reg_base + PCIE_WINROM); ++ ++ /* ++ * As the two host bridges in JH7110 soc have the same default ++ * address translation table, this cause the second root port can't ++ * access it's host bridge config space correctly. ++ * To workaround, config the ATR of host bridge config space by SW. ++ */ ++ starfive_pcie_set_atr_entry(pcie, ++ pcie->config_phyaddr, 0, ++ XR3PCI_ECAM_SIZE, ++ XR3PCI_ATR_TRSLID_PCIE_CONFIG); ++ ++ starfive_pcie_setup_windows(pcie); ++ ++ /* Ensure that PERST has been asserted for at least 100 ms */ ++ msleep(300); ++ if (pcie->reset_gpio) ++ gpiod_set_value_cansleep(pcie->reset_gpio, 0); ++} ++ ++static bool starfive_pcie_is_link_up(struct starfive_jh7110_pcie *pcie) ++{ ++ struct device *dev = &pcie->pdev->dev; ++ int ret; ++ u32 stg_reg_val; ++ ++ /* 100ms timeout value should be enough for Gen1/2 training */ ++ ret = regmap_read_poll_timeout(pcie->reg_syscon, ++ pcie->stg_lnksta, ++ stg_reg_val, ++ stg_reg_val & DATA_LINK_ACTIVE, ++ 10 * 1000, 100 * 1000); ++ ++ /* If the link is down (no device in slot), then exit. */ ++ if (ret == -ETIMEDOUT) { ++ dev_info(dev, "Port link down, exit.\n"); ++ return false; ++ } else if (ret == 0) { ++ dev_info(dev, "Port link up.\n"); ++ return true; ++ } ++ ++ dev_warn(dev, "Read stg_linksta failed.\n"); ++ ++ return false; ++} ++ ++static int starfive_pcie_enable_phy(struct device *dev, ++ struct starfive_jh7110_pcie *pcie) ++{ ++ int ret; ++ ++ if (!pcie->phy) ++ return 0; ++ ++ ret = phy_init(pcie->phy); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "failed to initialize pcie phy\n"); ++ ++ ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE); ++ if (ret) { ++ ret = dev_err_probe(dev, ret, ++ "failed to set pcie mode\n"); ++ goto err_phy_on; ++ } ++ ++ ret = phy_power_on(pcie->phy); ++ if (ret) { ++ ret = dev_err_probe(dev, ret, "failed to power on pcie phy\n"); ++ goto err_phy_on; ++ } ++ ++ return 0; ++ ++err_phy_on: ++ phy_exit(pcie->phy); ++ return ret; ++} ++ ++static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie) ++{ ++ phy_power_off(pcie->phy); ++ phy_exit(pcie->phy); ++} ++ ++static int starfive_pcie_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct starfive_jh7110_pcie *pcie; ++ struct pci_bus *bus; ++ struct pci_host_bridge *bridge; ++ int ret; ++ ++ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); ++ if (!pcie) ++ return -ENOMEM; ++ ++ pcie->pdev = pdev; ++ pcie->atr_table_num = 0; ++ ++ ret = starfive_pcie_parse_dt(pcie); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, pcie); ++ ++ ret = starfive_pcie_gpio_init(pcie); ++ if (ret) ++ return ret; ++ ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_rp_nep, ++ STG_SYSCON_K_RP_NEP, ++ STG_SYSCON_K_RP_NEP); ++ ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_awfun, ++ STG_SYSCON_CKREF_SRC_MASK, ++ 2 << STG_SYSCON_CKREF_SRC_SHIFT); ++ ++ regmap_update_bits(pcie->reg_syscon, ++ pcie->stg_awfun, ++ STG_SYSCON_CLKREQ, ++ STG_SYSCON_CLKREQ); ++ ++ ret = starfive_pcie_clk_rst_init(pcie); ++ if (ret) ++ return ret; ++ ++ ret = starfive_pcie_init_irq_domain(pcie); ++ if (ret) ++ return ret; ++ ++ bridge = devm_pci_alloc_host_bridge(dev, 0); ++ if (!bridge) ++ return -ENOMEM; ++ ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_get_sync(&pdev->dev); ++ ++ /* Set default bus ops */ ++ bridge->ops = &starfive_pcie_ops; ++ bridge->sysdata = pcie; ++ pcie->bridge = bridge; ++ ++ starfive_pcie_hw_init(pcie); ++ ++ if (starfive_pcie_is_link_up(pcie) == false) ++ goto release; ++ ++ if (IS_ENABLED(CONFIG_PCI_MSI)) { ++ ret = starfive_pcie_enable_msi(pcie, bus); ++ if (ret < 0) { ++ dev_err(dev, "Failed to enable MSI support: %d\n", ret); ++ goto release; ++ } ++ } ++ ++ ret = starfive_pcie_enable_phy(dev, pcie); ++ if (ret) ++ goto release; ++ ++ ret = pci_host_probe(bridge); ++ if (ret < 0) { ++ dev_err_probe(dev, ret, "Failed to pci host probe: %d\n", ret); ++ goto err_phy_on; ++ } ++ ++ return ret; ++ ++err_phy_on: ++ starfive_pcie_disable_phy(pcie); ++release: ++ if (pcie->power_gpio) ++ gpiod_set_value_cansleep(pcie->power_gpio, 0); ++ ++ starfive_pcie_clk_rst_deinit(pcie); ++ ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ ++ pci_free_host_bridge(pcie->bridge); ++ platform_set_drvdata(pdev, NULL); ++ ++ return ret; ++} ++ ++static int starfive_pcie_remove(struct platform_device *pdev) ++{ ++ struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev); ++ ++ starfive_pcie_disable_phy(pcie); ++ if (pcie->power_gpio) ++ gpiod_set_value_cansleep(pcie->power_gpio, 0); ++ starfive_pcie_free_irq_domain(pcie); ++ starfive_pcie_clk_rst_deinit(pcie); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int __maybe_unused starfive_pcie_suspend_noirq(struct device *dev) ++{ ++ struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); ++ ++ if (!pcie) ++ return 0; ++ ++ starfive_pcie_disable_phy(pcie); ++ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused starfive_pcie_resume_noirq(struct device *dev) ++{ ++ struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); ++ int ret; ++ ++ if (!pcie) ++ return 0; ++ ++ ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "Failed to enable clocks\n"); ++ ++ ret = starfive_pcie_enable_phy(dev, pcie); ++ if (ret) ++ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops starfive_pcie_pm_ops = { ++ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq, ++ starfive_pcie_resume_noirq) ++}; ++#endif ++ ++static const struct of_device_id starfive_pcie_of_match[] = { ++ { .compatible = "starfive,jh7110-pcie"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, starfive_pcie_of_match); ++ ++static struct platform_driver starfive_pcie_driver = { ++ .driver = { ++ .name = "pcie-starfive", ++ .of_match_table = of_match_ptr(starfive_pcie_of_match), ++#ifdef CONFIG_PM_SLEEP ++ .pm = &starfive_pcie_pm_ops, ++#endif ++ }, ++ .probe = starfive_pcie_probe, ++ .remove = starfive_pcie_remove, ++}; ++module_platform_driver(starfive_pcie_driver); ++ ++MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver"); ++MODULE_AUTHOR("Mason Huo "); ++MODULE_AUTHOR("Kevin Xie "); ++MODULE_AUTHOR("Minda Chen "); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/starfive/patches-6.1/0097-cpufreq-dt-platdev-Add-JH7110-SOC-to-the-allowlist.patch b/target/linux/starfive/patches-6.1/0097-cpufreq-dt-platdev-Add-JH7110-SOC-to-the-allowlist.patch new file mode 100644 index 0000000000..cc629f06d2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0097-cpufreq-dt-platdev-Add-JH7110-SOC-to-the-allowlist.patch @@ -0,0 +1,24 @@ +From 214c40d5393cdf08c8b0746224e76bfd2a8d9cf7 Mon Sep 17 00:00:00 2001 +From: Mason Huo +Date: Fri, 21 Apr 2023 11:14:30 +0800 +Subject: [PATCH 097/122] cpufreq: dt-platdev: Add JH7110 SOC to the allowlist + +Add the compatible strings for supporting the generic +cpufreq driver on the StarFive JH7110 SoC. + +Signed-off-by: Mason Huo +--- + drivers/cpufreq/cpufreq-dt-platdev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -86,6 +86,8 @@ static const struct of_device_id allowli + { .compatible = "st-ericsson,u9500", }, + { .compatible = "st-ericsson,u9540", }, + ++ { .compatible = "starfive,jh7110", }, ++ + { .compatible = "ti,omap2", }, + { .compatible = "ti,omap4", }, + { .compatible = "ti,omap5", }, diff --git a/target/linux/starfive/patches-6.1/0098-riscv-dts-starfive-Add-full-support-for-JH7110-and-V.patch b/target/linux/starfive/patches-6.1/0098-riscv-dts-starfive-Add-full-support-for-JH7110-and-V.patch new file mode 100644 index 0000000000..168782a280 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0098-riscv-dts-starfive-Add-full-support-for-JH7110-and-V.patch @@ -0,0 +1,1034 @@ +From 16e358dcf5e072c82f643d11add5b7e55b36a6f8 Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Wed, 31 May 2023 01:53:31 -0700 +Subject: [PATCH 098/122] riscv: dts: starfive: Add full support for JH7110 and + VisionFive 2 board + +Merge all StarFive dts patches together. + +Signed-off-by: shanlong.li +--- + .../jh7110-starfive-visionfive-2-v1.3b.dts | 8 +- + .../jh7110-starfive-visionfive-2.dtsi | 338 ++++++++++++ + arch/riscv/boot/dts/starfive/jh7110.dtsi | 506 +++++++++++++++++- + 3 files changed, 847 insertions(+), 5 deletions(-) + +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts +@@ -28,8 +28,8 @@ + motorcomm,tx-clk-adj-enabled; + motorcomm,tx-clk-100-inverted; + motorcomm,tx-clk-1000-inverted; +- rx-clk-driver-strength = <0x6>; +- rx-data-driver-strength = <0x3>; ++ motorcomm,rx-clk-driver-strength = <0x6>; ++ motorcomm,rx-data-driver-strength = <0x3>; + rx-internal-delay-ps = <1500>; + tx-internal-delay-ps = <1500>; + }; +@@ -37,8 +37,8 @@ + &phy1 { + motorcomm,tx-clk-adj-enabled; + motorcomm,tx-clk-100-inverted; +- rx-clk-driver-strength = <0x6>; +- rx-data-driver-strength = <0x3>; ++ motorcomm,rx-clk-driver-strength = <0x6>; ++ motorcomm,rx-data-driver-strength = <0x3>; + rx-internal-delay-ps = <300>; + tx-internal-delay-ps = <0>; + }; +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -33,11 +33,64 @@ + reg = <0x0 0x40000000 0x1 0x0>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ size = <0x0 0x20000000>; ++ alignment = <0x0 0x1000>; ++ alloc-ranges = <0x0 0x80000000 0x0 0x20000000>; ++ linux,cma-default; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <15000>; ++ ++ thermal-sensors = <&sfctemp>; ++ ++ cooling-maps { ++ }; ++ ++ trips { ++ cpu_alert0: cpu_alert0 { ++ /* milliCelsius */ ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_crit: cpu_crit { ++ /* milliCelsius */ ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ + gpio-restart { + compatible = "gpio-restart"; + gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>; + priority = <224>; + }; ++ ++ clk_ext_camera: clk_ext_camera { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ }; ++}; ++ ++&dvp_clk { ++ clock-frequency = <74250000>; + }; + + &gmac0_rgmii_rxin { +@@ -56,6 +109,10 @@ + clock-frequency = <50000000>; + }; + ++&hdmitx0_pixelclk { ++ clock-frequency = <297000000>; ++}; ++ + &i2srx_bclk_ext { + clock-frequency = <12288000>; + }; +@@ -88,6 +145,39 @@ + clock-frequency = <49152000>; + }; + ++&csi2rx { ++ status = "okay"; ++ ++ assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>; ++ assigned-clock-rates = <297000000>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ csi2rx_from_imx219: endpoint { ++ remote-endpoint = <&imx219_to_csi2rx>; ++ bus-type = <4>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ status = "okay"; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ csi2rx_to_vin: endpoint { ++ remote-endpoint = <&vin_from_csi2rx>; ++ status = "okay"; ++ }; ++ }; ++ }; ++}; ++ + &gmac0 { + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; +@@ -148,6 +238,20 @@ + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins>; + status = "okay"; ++ ++ axp15060: pmic@36 { ++ compatible = "x-powers,axp15060"; ++ reg = <0x36>; ++ ++ regulators { ++ vdd_cpu: dcdc2 { ++ regulator-always-on; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1540000>; ++ regulator-name = "vdd-cpu"; ++ }; ++ }; ++ }; + }; + + &i2c6 { +@@ -158,6 +262,121 @@ + pinctrl-names = "default"; + pinctrl-0 = <&i2c6_pins>; + status = "okay"; ++ ++ imx219: imx219@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ clocks = <&clk_ext_camera>; ++ reset-gpio = <&sysgpio 18 0>; ++ rotation = <0>; ++ orientation = <1>; ++ ++ port { ++ imx219_to_csi2rx: endpoint { ++ remote-endpoint = <&csi2rx_from_imx219>; ++ bus-type = <4>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ link-frequencies = /bits/ 64 <456000000>; ++ }; ++ }; ++ }; ++}; ++ ++&mmc0 { ++ max-frequency = <100000000>; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ non-removable; ++ cap-mmc-hw-reset; ++ post-power-on-delay-ms = <200>; ++ status = "okay"; ++}; ++ ++&mmc1 { ++ max-frequency = <100000000>; ++ bus-width = <4>; ++ no-sdio; ++ no-mmc; ++ broken-cd; ++ cap-sd-highspeed; ++ post-power-on-delay-ms = <200>; ++ status = "okay"; ++}; ++ ++&pcie0 { ++ pinctrl-names = "default"; ++ reset-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>; ++ phys = <&pciephy0>; ++ status = "okay"; ++}; ++ ++&pcie1 { ++ pinctrl-names = "default"; ++ reset-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>; ++ phys = <&pciephy1>; ++ status = "okay"; ++}; ++ ++&ptc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&qspi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ nor_flash: flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg=<0>; ++ cdns,read-delay = <5>; ++ spi-max-frequency = <12000000>; ++ cdns,tshsl-ns = <1>; ++ cdns,tsd2d-ns = <1>; ++ cdns,tchsh-ns = <1>; ++ cdns,tslch-ns = <1>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ spl@0 { ++ reg = <0x0 0x20000>; ++ }; ++ uboot@100000 { ++ reg = <0x100000 0x300000>; ++ }; ++ data@f00000 { ++ reg = <0xf00000 0x100000>; ++ }; ++ }; ++ }; ++}; ++ ++&stfcamss { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ reg = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vin_from_csi2rx: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&csi2rx_to_vin>; ++ status = "okay"; ++ }; ++ }; ++ }; + }; + + &sysgpio { +@@ -217,6 +436,98 @@ + }; + }; + ++ pcie0_wake_default: pcie0_wake_default { ++ wake-pins { ++ pinmux = ; ++ bias-disable; ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ pcie0_clkreq_default: pcie0_clkreq_default { ++ clkreq-pins { ++ bias-disable; ++ pinmux = ; ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ pcie1_wake_default: pcie1_wake_default { ++ wake-pins { ++ bias-disable; ++ pinmux = ; ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ pcie1_clkreq_default: pcie1_clkreq_default { ++ clkreq-pins { ++ bias-disable; ++ pinmux = ; ++ drive-strength = <2>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ pwm_pins: pwm-0 { ++ pwm-pins { ++ pinmux = , ++ ; ++ bias-disable; ++ drive-strength = <12>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ tdm0_pins: tdm0-pins { ++ tdm0-pins-tx { ++ pinmux = ; ++ bias-pull-up; ++ drive-strength = <2>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ ++ tdm0-pins-rx { ++ pinmux = ; ++ input-enable; ++ }; ++ ++ tdm0-pins-sync { ++ pinmux = ; ++ input-enable; ++ }; ++ ++ tdm0-pins-pcmclk { ++ pinmux = ; ++ input-enable; ++ }; ++ }; ++ + uart0_pins: uart0-0 { + tx-pins { + pinmux = ; ++ status = "okay"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + }; ++ ++&usb0 { ++ dr_mode = "peripheral"; ++ status = "okay"; ++}; ++ ++&U74_1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&U74_2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&U74_3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&U74_4 { ++ cpu-supply = <&vdd_cpu>; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi +@@ -6,6 +6,7 @@ + + /dts-v1/; + #include ++#include + #include + + / { +@@ -53,6 +54,9 @@ + next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc_zba_zbb"; + tlb-split; ++ operating-points-v2 = <&cpu_opp>; ++ clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; ++ clock-names = "cpu"; + + cpu1_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; +@@ -79,6 +83,9 @@ + next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc_zba_zbb"; + tlb-split; ++ operating-points-v2 = <&cpu_opp>; ++ clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; ++ clock-names = "cpu"; + + cpu2_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; +@@ -105,6 +112,9 @@ + next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc_zba_zbb"; + tlb-split; ++ operating-points-v2 = <&cpu_opp>; ++ clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; ++ clock-names = "cpu"; + + cpu3_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; +@@ -131,6 +141,9 @@ + next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc_zba_zbb"; + tlb-split; ++ operating-points-v2 = <&cpu_opp>; ++ clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; ++ clock-names = "cpu"; + + cpu4_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; +@@ -164,6 +177,33 @@ + }; + }; + ++ cpu_opp: opp-table-0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ opp-375000000 { ++ opp-hz = /bits/ 64 <375000000>; ++ opp-microvolt = <800000>; ++ }; ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <800000>; ++ }; ++ opp-750000000 { ++ opp-hz = /bits/ 64 <750000000>; ++ opp-microvolt = <800000>; ++ }; ++ opp-1500000000 { ++ opp-hz = /bits/ 64 <1500000000>; ++ opp-microvolt = <1040000>; ++ }; ++ }; ++ ++ dvp_clk: dvp-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "dvp_clk"; ++ #clock-cells = <0>; ++ }; ++ + gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock { + compatible = "fixed-clock"; + clock-output-names = "gmac0_rgmii_rxin"; +@@ -188,6 +228,12 @@ + #clock-cells = <0>; + }; + ++ hdmitx0_pixelclk: hdmitx0-pixel-clock { ++ compatible = "fixed-clock"; ++ clock-output-names = "hdmitx0_pixelclk"; ++ #clock-cells = <0>; ++ }; ++ + i2srx_bclk_ext: i2srx-bclk-ext-clock { + compatible = "fixed-clock"; + clock-output-names = "i2srx_bclk_ext"; +@@ -360,6 +406,99 @@ + status = "disabled"; + }; + ++ tdm: tdm@10090000 { ++ compatible = "starfive,jh7110-tdm"; ++ reg = <0x0 0x10090000 0x0 0x1000>; ++ clocks = <&syscrg JH7110_SYSCLK_TDM_AHB>, ++ <&syscrg JH7110_SYSCLK_TDM_APB>, ++ <&syscrg JH7110_SYSCLK_TDM_INTERNAL>, ++ <&syscrg JH7110_SYSCLK_TDM_TDM>, ++ <&syscrg JH7110_SYSCLK_MCLK_INNER>, ++ <&tdm_ext>; ++ clock-names = "tdm_ahb", "tdm_apb", ++ "tdm_internal", "tdm", ++ "mclk_inner", "tdm_ext"; ++ resets = <&syscrg JH7110_SYSRST_TDM_AHB>, ++ <&syscrg JH7110_SYSRST_TDM_APB>, ++ <&syscrg JH7110_SYSRST_TDM_CORE>; ++ dmas = <&dma 20>, <&dma 21>; ++ dma-names = "rx","tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usb0: usb@10100000 { ++ compatible = "starfive,jh7110-usb"; ++ ranges = <0x0 0x0 0x10100000 0x100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ starfive,stg-syscon = <&stg_syscon 0x4>; ++ clocks = <&stgcrg JH7110_STGCLK_USB0_LPM>, ++ <&stgcrg JH7110_STGCLK_USB0_STB>, ++ <&stgcrg JH7110_STGCLK_USB0_APB>, ++ <&stgcrg JH7110_STGCLK_USB0_AXI>, ++ <&stgcrg JH7110_STGCLK_USB0_UTMI_APB>; ++ clock-names = "lpm", "stb", "apb", "axi", "utmi_apb"; ++ resets = <&stgcrg JH7110_STGRST_USB0_PWRUP>, ++ <&stgcrg JH7110_STGRST_USB0_APB>, ++ <&stgcrg JH7110_STGRST_USB0_AXI>, ++ <&stgcrg JH7110_STGRST_USB0_UTMI_APB>; ++ reset-names = "pwrup", "apb", "axi", "utmi_apb"; ++ status = "disabled"; ++ ++ usb_cdns3: usb@0 { ++ compatible = "cdns,usb3"; ++ reg = <0x0 0x10000>, ++ <0x10000 0x10000>, ++ <0x20000 0x10000>; ++ reg-names = "otg", "xhci", "dev"; ++ interrupts = <100>, <108>, <110>; ++ interrupt-names = "host", "peripheral", "otg"; ++ phys = <&usbphy0>; ++ phy-names = "cdns3,usb2-phy"; ++ }; ++ }; ++ ++ usbphy0: phy@10200000 { ++ compatible = "starfive,jh7110-usb-phy"; ++ reg = <0x0 0x10200000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_USB_125M>, ++ <&stgcrg JH7110_STGCLK_USB0_APP_125>; ++ clock-names = "125m", "app_125m"; ++ #phy-cells = <0>; ++ }; ++ ++ pciephy0: phy@10210000 { ++ compatible = "starfive,jh7110-pcie-phy"; ++ reg = <0x0 0x10210000 0x0 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ pciephy1: phy@10220000 { ++ compatible = "starfive,jh7110-pcie-phy"; ++ reg = <0x0 0x10220000 0x0 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ stgcrg: clock-controller@10230000 { ++ compatible = "starfive,jh7110-stgcrg"; ++ reg = <0x0 0x10230000 0x0 0x10000>; ++ clocks = <&osc>, ++ <&syscrg JH7110_SYSCLK_HIFI4_CORE>, ++ <&syscrg JH7110_SYSCLK_STG_AXIAHB>, ++ <&syscrg JH7110_SYSCLK_USB_125M>, ++ <&syscrg JH7110_SYSCLK_CPU_BUS>, ++ <&syscrg JH7110_SYSCLK_HIFI4_AXI>, ++ <&syscrg JH7110_SYSCLK_NOCSTG_BUS>, ++ <&syscrg JH7110_SYSCLK_APB_BUS>; ++ clock-names = "osc", "hifi4_core", ++ "stg_axiahb", "usb_125m", ++ "cpu_bus", "hifi4_axi", ++ "nocstg_bus", "apb_bus"; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ + stg_syscon: syscon@10240000 { + compatible = "starfive,jh7110-stg-syscon", "syscon"; + reg = <0x0 0x10240000 0x0 0x1000>; +@@ -452,6 +591,45 @@ + status = "disabled"; + }; + ++ ptc: pwm@120d0000 { ++ compatible = "starfive,jh7110-pwm"; ++ reg = <0x0 0x120d0000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_PWM_APB>; ++ resets = <&syscrg JH7110_SYSRST_PWM_APB>; ++ #pwm-cells=<3>; ++ status = "disabled"; ++ }; ++ ++ sfctemp: temperature-sensor@120e0000 { ++ compatible = "starfive,jh7110-temp"; ++ reg = <0x0 0x120e0000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_TEMP_CORE>, ++ <&syscrg JH7110_SYSCLK_TEMP_APB>; ++ clock-names = "sense", "bus"; ++ resets = <&syscrg JH7110_SYSRST_TEMP_CORE>, ++ <&syscrg JH7110_SYSRST_TEMP_APB>; ++ reset-names = "sense", "bus"; ++ #thermal-sensor-cells = <0>; ++ }; ++ ++ qspi: spi@13010000 { ++ compatible = "starfive,jh7110-qspi", "cdns,qspi-nor"; ++ reg = <0x0 0x13010000 0x0 0x10000 ++ 0x0 0x21000000 0x0 0x400000>; ++ interrupts = <25>; ++ clocks = <&syscrg JH7110_SYSCLK_QSPI_REF>, ++ <&syscrg JH7110_SYSCLK_QSPI_AHB>, ++ <&syscrg JH7110_SYSCLK_QSPI_APB>; ++ clock-names = "qspi-ref", "qspi-ahb", "qspi-apb"; ++ resets = <&syscrg JH7110_SYSRST_QSPI_APB>, ++ <&syscrg JH7110_SYSRST_QSPI_AHB>, ++ <&syscrg JH7110_SYSRST_QSPI_REF>; ++ reset-names = "qspi", "qspi-ocp", "rstc_ref"; ++ cdns,fifo-depth = <256>; ++ cdns,fifo-width = <4>; ++ cdns,trigger-address = <0x0>; ++ }; ++ + syscrg: clock-controller@13020000 { + compatible = "starfive,jh7110-syscrg"; + reg = <0x0 0x13020000 0x0 0x10000>; +@@ -496,6 +674,107 @@ + #gpio-cells = <2>; + }; + ++ timer@13050000 { ++ compatible = "starfive,jh7110-timer"; ++ reg = <0x0 0x13050000 0x0 0x10000>; ++ interrupts = <69>, <70>, <71> ,<72>; ++ clocks = <&syscrg JH7110_SYSCLK_TIMER_APB>, ++ <&syscrg JH7110_SYSCLK_TIMER0>, ++ <&syscrg JH7110_SYSCLK_TIMER1>, ++ <&syscrg JH7110_SYSCLK_TIMER2>, ++ <&syscrg JH7110_SYSCLK_TIMER3>; ++ clock-names = "apb", "ch0", "ch1", ++ "ch2", "ch3"; ++ resets = <&syscrg JH7110_SYSRST_TIMER_APB>, ++ <&syscrg JH7110_SYSRST_TIMER0>, ++ <&syscrg JH7110_SYSRST_TIMER1>, ++ <&syscrg JH7110_SYSRST_TIMER2>, ++ <&syscrg JH7110_SYSRST_TIMER3>; ++ reset-names = "apb", "ch0", "ch1", ++ "ch2", "ch3"; ++ }; ++ ++ watchdog@13070000 { ++ compatible = "starfive,jh7110-wdt"; ++ reg = <0x0 0x13070000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_WDT_APB>, ++ <&syscrg JH7110_SYSCLK_WDT_CORE>; ++ clock-names = "apb", "core"; ++ resets = <&syscrg JH7110_SYSRST_WDT_APB>, ++ <&syscrg JH7110_SYSRST_WDT_CORE>; ++ }; ++ ++ crypto: crypto@16000000 { ++ compatible = "starfive,jh7110-crypto"; ++ reg = <0x0 0x16000000 0x0 0x4000>; ++ clocks = <&stgcrg JH7110_STGCLK_SEC_AHB>, ++ <&stgcrg JH7110_STGCLK_SEC_MISC_AHB>; ++ clock-names = "hclk", "ahb"; ++ interrupts = <28>; ++ resets = <&stgcrg JH7110_STGRST_SEC_AHB>; ++ dmas = <&sdma 1 2>, <&sdma 0 2>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ sdma: dma@16008000 { ++ compatible = "arm,pl080", "arm,primecell"; ++ arm,primecell-periphid = <0x00041080>; ++ reg = <0x0 0x16008000 0x0 0x4000>; ++ interrupts = <29>; ++ clocks = <&stgcrg JH7110_STGCLK_SEC_AHB>, ++ <&stgcrg JH7110_STGCLK_SEC_MISC_AHB>; ++ clock-names = "hclk", "apb_pclk"; ++ resets = <&stgcrg JH7110_STGRST_SEC_AHB>; ++ lli-bus-interface-ahb1; ++ mem-bus-interface-ahb1; ++ memcpy-burst-size = <256>; ++ memcpy-bus-width = <32>; ++ #dma-cells = <2>; ++ }; ++ ++ rng: rng@1600c000 { ++ compatible = "starfive,jh7110-trng"; ++ reg = <0x0 0x1600C000 0x0 0x4000>; ++ clocks = <&stgcrg JH7110_STGCLK_SEC_AHB>, ++ <&stgcrg JH7110_STGCLK_SEC_MISC_AHB>; ++ clock-names = "hclk", "ahb"; ++ resets = <&stgcrg JH7110_STGRST_SEC_AHB>; ++ interrupts = <30>; ++ }; ++ ++ mmc0: mmc@16010000 { ++ compatible = "starfive,jh7110-mmc"; ++ reg = <0x0 0x16010000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_SDIO0_AHB>, ++ <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>; ++ clock-names = "biu","ciu"; ++ resets = <&syscrg JH7110_SYSRST_SDIO0_AHB>; ++ reset-names = "reset"; ++ interrupts = <74>; ++ fifo-depth = <32>; ++ fifo-watermark-aligned; ++ data-addr = <0>; ++ starfive,sysreg = <&sys_syscon 0x14 0x1a 0x7c000000>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@16020000 { ++ compatible = "starfive,jh7110-mmc"; ++ reg = <0x0 0x16020000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_SDIO1_AHB>, ++ <&syscrg JH7110_SYSCLK_SDIO1_SDCARD>; ++ clock-names = "biu","ciu"; ++ resets = <&syscrg JH7110_SYSRST_SDIO1_AHB>; ++ reset-names = "reset"; ++ interrupts = <75>; ++ fifo-depth = <32>; ++ fifo-watermark-aligned; ++ data-addr = <0>; ++ starfive,sysreg = <&sys_syscon 0x9c 0x1 0x3e>; ++ status = "disabled"; ++ }; ++ + gmac0: ethernet@16030000 { + compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20"; + reg = <0x0 0x16030000 0x0 0x10000>; +@@ -558,6 +837,24 @@ + status = "disabled"; + }; + ++ dma: dma-controller@16050000 { ++ compatible = "starfive,jh7110-axi-dma"; ++ reg = <0x0 0x16050000 0x0 0x10000>; ++ clocks = <&stgcrg JH7110_STGCLK_DMA1P_AXI>, ++ <&stgcrg JH7110_STGCLK_DMA1P_AHB>; ++ clock-names = "core-clk", "cfgr-clk"; ++ resets = <&stgcrg JH7110_STGRST_DMA1P_AXI>, ++ <&stgcrg JH7110_STGRST_DMA1P_AHB>; ++ interrupts = <73>; ++ #dma-cells = <1>; ++ dma-channels = <4>; ++ snps,dma-masters = <1>; ++ snps,data-width = <3>; ++ snps,block-size = <65536 65536 65536 65536>; ++ snps,priority = <0 1 2 3>; ++ snps,axi-max-burst-len = <16>; ++ }; ++ + aoncrg: clock-controller@17000000 { + compatible = "starfive,jh7110-aoncrg"; + reg = <0x0 0x17000000 0x0 0x10000>; +@@ -576,8 +873,9 @@ + }; + + aon_syscon: syscon@17010000 { +- compatible = "starfive,jh7110-aon-syscon", "syscon", "simple-mfd"; ++ compatible = "starfive,jh7110-aon-syscon", "syscon"; + reg = <0x0 0x17010000 0x0 0x1000>; ++ #power-domain-cells = <1>; + }; + + aongpio: pinctrl@17020000 { +@@ -590,5 +888,211 @@ + gpio-controller; + #gpio-cells = <2>; + }; ++ ++ pwrc: power-controller@17030000 { ++ compatible = "starfive,jh7110-pmu"; ++ reg = <0x0 0x17030000 0x0 0x10000>; ++ interrupts = <111>; ++ #power-domain-cells = <1>; ++ }; ++ ++ csi2rx: csi-bridge@19800000 { ++ compatible = "starfive,jh7110-csi2rx"; ++ reg = <0x0 0x19800000 0x0 0x10000>; ++ clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>, ++ <&ispcrg JH7110_ISPCLK_VIN_APB>, ++ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF0>, ++ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF1>, ++ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF2>, ++ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF3>; ++ clock-names = "sys_clk", "p_clk", ++ "pixel_if0_clk", "pixel_if1_clk", ++ "pixel_if2_clk", "pixel_if3_clk"; ++ resets = <&ispcrg JH7110_ISPRST_VIN_SYS>, ++ <&ispcrg JH7110_ISPRST_VIN_APB>, ++ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF0>, ++ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF1>, ++ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF2>, ++ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF3>; ++ reset-names = "sys", "reg_bank", ++ "pixel_if0", "pixel_if1", ++ "pixel_if2", "pixel_if3"; ++ phys = <&csi_phy>; ++ phy-names = "dphy"; ++ status = "disabled"; ++ }; ++ ++ ispcrg: clock-controller@19810000 { ++ compatible = "starfive,jh7110-ispcrg"; ++ reg = <0x0 0x19810000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_ISP_TOP_CORE>, ++ <&syscrg JH7110_SYSCLK_ISP_TOP_AXI>, ++ <&syscrg JH7110_SYSCLK_NOC_BUS_ISP_AXI>, ++ <&dvp_clk>; ++ clock-names = "isp_top_core", "isp_top_axi", ++ "noc_bus_isp_axi", "dvp_clk"; ++ resets = <&syscrg JH7110_SYSRST_ISP_TOP>, ++ <&syscrg JH7110_SYSRST_ISP_TOP_AXI>, ++ <&syscrg JH7110_SYSRST_NOC_BUS_ISP_AXI>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ power-domains = <&pwrc JH7110_PD_ISP>; ++ }; ++ ++ csi_phy: phy@19820000 { ++ compatible = "starfive,jh7110-dphy-rx"; ++ reg = <0x0 0x19820000 0x0 0x10000>; ++ clocks = <&ispcrg JH7110_ISPCLK_M31DPHY_CFG_IN>, ++ <&ispcrg JH7110_ISPCLK_M31DPHY_REF_IN>, ++ <&ispcrg JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0>; ++ clock-names = "cfg", "ref", "tx"; ++ resets = <&ispcrg JH7110_ISPRST_M31DPHY_HW>, ++ <&ispcrg JH7110_ISPRST_M31DPHY_B09_AON>; ++ power-domains = <&aon_syscon JH7110_PD_DPHY_RX>; ++ #phy-cells = <0>; ++ }; ++ ++ stfcamss: camss@19840000 { ++ compatible = "starfive,jh7110-camss"; ++ reg = <0x0 0x19840000 0x0 0x10000>, ++ <0x0 0x19870000 0x0 0x30000>; ++ reg-names = "syscon", "isp"; ++ clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>, ++ <&ispcrg JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C>, ++ <&ispcrg JH7110_ISPCLK_DVP_INV>, ++ <&ispcrg JH7110_ISPCLK_VIN_P_AXI_WR>, ++ <&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>, ++ <&syscrg JH7110_SYSCLK_ISP_TOP_CORE>, ++ <&syscrg JH7110_SYSCLK_ISP_TOP_AXI>; ++ clock-names = "clk_apb_func", ++ "clk_wrapper_clk_c", ++ "clk_dvp_inv", ++ "clk_axiwr", ++ "clk_mipi_rx0_pxl", ++ "clk_ispcore_2x", ++ "clk_isp_axi"; ++ resets = <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_P>, ++ <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_C>, ++ <&ispcrg JH7110_ISPRST_VIN_P_AXI_RD>, ++ <&ispcrg JH7110_ISPRST_VIN_P_AXI_WR>, ++ <&syscrg JH7110_SYSRST_ISP_TOP>, ++ <&syscrg JH7110_SYSRST_ISP_TOP_AXI>; ++ reset-names = "rst_wrapper_p", ++ "rst_wrapper_c", ++ "rst_axird", ++ "rst_axiwr", ++ "rst_isp_top_n", ++ "rst_isp_top_axi"; ++ power-domains = <&pwrc JH7110_PD_ISP>; ++ /* irq nr: vin, isp, isp_csi, isp_csiline */ ++ interrupts = <92>, <87>, <90>; ++ status = "disabled"; ++ }; ++ ++ voutcrg: clock-controller@295c0000 { ++ compatible = "starfive,jh7110-voutcrg"; ++ reg = <0x0 0x295c0000 0x0 0x10000>; ++ clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>, ++ <&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>, ++ <&syscrg JH7110_SYSCLK_I2STX0_BCLK>, ++ <&hdmitx0_pixelclk>; ++ clock-names = "vout_src", "vout_top_ahb", ++ "vout_top_axi", "vout_top_hdmitx0_mclk", ++ "i2stx0_bclk", "hdmitx0_pixelclk"; ++ resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ power-domains = <&pwrc JH7110_PD_VOUT>; ++ }; ++ ++ pcie0: pcie@2B000000 { ++ compatible = "starfive,jh7110-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ reg = <0x0 0x2B000000 0x0 0x1000000 ++ 0x9 0x40000000 0x0 0x10000000>; ++ reg-names = "reg", "config"; ++ device_type = "pci"; ++ starfive,stg-syscon = <&stg_syscon 0xc0 0xc4 0x130 0x1b8>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>, ++ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>; ++ interrupts = <56>; ++ interrupt-parent = <&plic>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>, ++ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>, ++ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>, ++ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>; ++ msi-parent = <&pcie0>; ++ msi-controller; ++ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>, ++ <&stgcrg JH7110_STGCLK_PCIE0_TL>, ++ <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>, ++ <&stgcrg JH7110_STGCLK_PCIE0_APB>; ++ clock-names = "noc", "tl", "axi_mst0", "apb"; ++ resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>, ++ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>, ++ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>, ++ <&stgcrg JH7110_STGRST_PCIE0_BRG>, ++ <&stgcrg JH7110_STGRST_PCIE0_CORE>, ++ <&stgcrg JH7110_STGRST_PCIE0_APB>; ++ reset-names = "mst0", "slv0", "slv", "brg", ++ "core", "apb"; ++ status = "disabled"; ++ ++ pcie_intc0: interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ }; ++ }; ++ ++ pcie1: pcie@2C000000 { ++ compatible = "starfive,jh7110-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ reg = <0x0 0x2C000000 0x0 0x1000000 ++ 0x9 0xc0000000 0x0 0x10000000>; ++ reg-names = "reg", "config"; ++ device_type = "pci"; ++ starfive,stg-syscon = <&stg_syscon 0x270 0x274 0x2e0 0x368>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>, ++ <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>; ++ interrupts = <57>; ++ interrupt-parent = <&plic>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>, ++ <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>, ++ <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>, ++ <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>; ++ msi-parent = <&pcie1>; ++ msi-controller; ++ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>, ++ <&stgcrg JH7110_STGCLK_PCIE1_TL>, ++ <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>, ++ <&stgcrg JH7110_STGCLK_PCIE1_APB>; ++ clock-names = "noc", "tl", "axi_mst0", "apb"; ++ resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>, ++ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>, ++ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>, ++ <&stgcrg JH7110_STGRST_PCIE1_BRG>, ++ <&stgcrg JH7110_STGRST_PCIE1_CORE>, ++ <&stgcrg JH7110_STGRST_PCIE1_APB>; ++ reset-names = "mst0", "slv0", "slv", "brg", ++ "core", "apb"; ++ status = "disabled"; ++ ++ pcie_intc1: interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ }; ++ }; + }; + }; diff --git a/target/linux/starfive/patches-6.1/0099-update-jh7110_defconfig-for-test.patch b/target/linux/starfive/patches-6.1/0099-update-jh7110_defconfig-for-test.patch new file mode 100644 index 0000000000..d63efb93dd --- /dev/null +++ b/target/linux/starfive/patches-6.1/0099-update-jh7110_defconfig-for-test.patch @@ -0,0 +1,48 @@ +From d91e8a78ce8d6a1f60a3f5c16b4f7c013ba40257 Mon Sep 17 00:00:00 2001 +From: "shanlong.li" +Date: Wed, 31 May 2023 01:56:22 -0700 +Subject: [PATCH 099/122] update jh7110_defconfig for test + +Signed-off-by: shanlong.li +--- + arch/riscv/configs/jh7110_defconfig | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/arch/riscv/configs/jh7110_defconfig ++++ b/arch/riscv/configs/jh7110_defconfig +@@ -106,7 +106,6 @@ CONFIG_MMC=y + # CONFIG_PWRSEQ_SIMPLE is not set + CONFIG_MMC_DW=y + # CONFIG_VIRTIO_MENU is not set +-CONFIG_CLK_STARFIVE_JH7110_AON=y + # CONFIG_VHOST_MENU is not set + # CONFIG_IOMMU_SUPPORT is not set + CONFIG_BTRFS_FS=y +@@ -160,6 +159,19 @@ CONFIG_PCI=y + CONFIG_USB_CDNS3_STARFIVE=y + CONFIG_PHY_STARFIVE_JH7110_PCIE=y + CONFIG_PHY_STARFIVE_JH7110_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++CONFIG_SCSI=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_UAS=y ++CONFIG_USB_CDNS3_GADGET=y ++CONFIG_USB_CDNS3_HOST=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_CONFIGFS=y ++CONFIG_USB_CONFIGFS_F_FS=y + CONFIG_USB_CDNS_SUPPORT=y + CONFIG_USB_CDNS3=y + CONFIG_USB=y +@@ -177,6 +189,7 @@ CONFIG_CRYPTO_HW=y + CONFIG_CRYPTO=y + CONFIG_SND_SOC_JH7110_TDM=y + CONFIG_SND_SOC_STARFIVE=y ++CONFIG_SND_SIMPLE_CARD=y + CONFIG_SND_SOC=y + CONFIG_SND=y + CONFIG_SOUND=y diff --git a/target/linux/starfive/patches-6.1/0100-Add-readme.patch b/target/linux/starfive/patches-6.1/0100-Add-readme.patch new file mode 100644 index 0000000000..82db368796 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0100-Add-readme.patch @@ -0,0 +1,75 @@ +From 13c570f2350f59a7994c26a51f749a50fa9b4726 Mon Sep 17 00:00:00 2001 +From: Hal Feng <87058983+hal-feng@users.noreply.github.com> +Date: Tue, 20 Dec 2022 16:18:35 +0800 +Subject: [PATCH 100/122] Add readme + +--- + README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + create mode 100644 README.md + +--- /dev/null ++++ b/README.md +@@ -0,0 +1,62 @@ ++## JH7110 Upstream Status ## ++ ++To get the latest status of each upstreaming patch series, please visit ++our RVspace. ++ ++https://rvspace.org/en/project/JH7110_Upstream_Plan ++ ++## Build Instructions ## ++ ++1. Configure Kconfig options ++ ++```shell ++# Use default selections ++make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig ++``` ++ ++or ++ ++```shell ++# Select options manually ++make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- nconfig ++``` ++ ++To boot up the VisionFive 2 board, please make sure **SOC_STARFIVE**, ++**CLK_STARFIVE_JH7110_SYS**, **PINCTRL_STARFIVE_JH7110_SYS**, ++**SERIAL_8250_DW** are selected. ++> If you need MMC and GMAC drivers, you should also select ++**MMC_DW_STARFIVE** and **DWMAC_STARFIVE**. ++ ++2. Build ++```shell ++make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- ++``` ++ ++## How to Run on VisionFive 2 Board via Network ## ++ ++1. Power on, enter u-boot and set enviroment parameters ++``` ++setenv fdt_high 0xffffffffffffffff; setenv initrd_high 0xffffffffffffffff; ++setenv scriptaddr 0x88100000; setenv script_offset_f 0x1fff000; setenv script_size_f 0x1000; ++setenv kernel_addr_r 0x84000000; setenv kernel_comp_addr_r 0x90000000; setenv kernel_comp_size 0x10000000; ++setenv fdt_addr_r 0x88000000; setenv ramdisk_addr_r 0x88300000; ++``` ++2. Set IP addresses for the board and your tftp server ++``` ++setenv serverip 192.168.w.x; setenv gatewayip 192.168.w.y; setenv ipaddr 192.168.w.z; setenv hostname starfive; setenv netdev eth0; ++``` ++3. Upload dtb, image and file system to DDR from your tftp server ++``` ++tftpboot ${fdt_addr_r} jh7110-starfive-visionfive-2-v1.3b.dtb; tftpboot ${kernel_addr_r} Image.gz; tftpboot ${ramdisk_addr_r} initramfs.cpio.gz; ++``` ++> If your VisionFive 2 is v1.2A, you should upload jh7110-starfive-visionfive-2-v1.2a.dtb instead. ++4. Load and boot the kernel ++``` ++booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}; ++``` ++When you see the message "buildroot login:", the launch was successful. ++You can just input the following accout and password, then continue. ++``` ++buildroot login: root ++Password: starfive ++``` diff --git a/target/linux/starfive/patches-6.1/0101-dt-bindings-rng-Add-StarFive-TRNG-module.patch b/target/linux/starfive/patches-6.1/0101-dt-bindings-rng-Add-StarFive-TRNG-module.patch new file mode 100644 index 0000000000..60cb6cc433 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0101-dt-bindings-rng-Add-StarFive-TRNG-module.patch @@ -0,0 +1,76 @@ +From 0b99a4626c7e148df128c6a8cb686d500431189b Mon Sep 17 00:00:00 2001 +From: Jia Jie Ho +Date: Tue, 17 Jan 2023 09:54:43 +0800 +Subject: [PATCH 101/122] dt-bindings: rng: Add StarFive TRNG module + +Add documentation to describe Starfive true random number generator +module. + +Co-developed-by: Jenny Zhang +Signed-off-by: Jenny Zhang +Signed-off-by: Jia Jie Ho +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Conor Dooley +--- + .../bindings/rng/starfive,jh7110-trng.yaml | 55 +++++++++++++++++++ + 1 file changed, 55 insertions(+) + create mode 100644 Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/rng/starfive,jh7110-trng.yaml +@@ -0,0 +1,55 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/rng/starfive,jh7110-trng.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive SoC TRNG Module ++ ++maintainers: ++ - Jia Jie Ho ++ ++properties: ++ compatible: ++ const: starfive,jh7110-trng ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: Hardware reference clock ++ - description: AHB reference clock ++ ++ clock-names: ++ items: ++ - const: hclk ++ - const: ahb ++ ++ resets: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - interrupts ++ ++additionalProperties: false ++ ++examples: ++ - | ++ rng: rng@1600C000 { ++ compatible = "starfive,jh7110-trng"; ++ reg = <0x1600C000 0x4000>; ++ clocks = <&clk 15>, <&clk 16>; ++ clock-names = "hclk", "ahb"; ++ resets = <&reset 3>; ++ interrupts = <30>; ++ }; ++... diff --git a/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch b/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch new file mode 100644 index 0000000000..e9f8387e7f --- /dev/null +++ b/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch @@ -0,0 +1,457 @@ +From 99a7ca1d1320288efc5b4532ce4ea637d622aa00 Mon Sep 17 00:00:00 2001 +From: Jia Jie Ho +Date: Tue, 17 Jan 2023 09:54:44 +0800 +Subject: [PATCH 102/122] hwrng: starfive - Add TRNG driver for StarFive SoC + +This adds driver support for the hardware random number generator in +Starfive SoCs and adds StarFive TRNG entry to MAINTAINERS. + +Co-developed-by: Jenny Zhang +Signed-off-by: Jenny Zhang +Signed-off-by: Jia Jie Ho +--- + MAINTAINERS | 6 + + drivers/char/hw_random/Kconfig | 11 + + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/jh7110-trng.c | 393 +++++++++++++++++++++++++++ + 4 files changed, 411 insertions(+) + create mode 100644 drivers/char/hw_random/jh7110-trng.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19709,6 +19709,12 @@ F: Documentation/devicetree/bindings/pow + F: drivers/soc/starfive/jh71xx_pmu.c + F: include/dt-bindings/power/starfive,jh7110-pmu.h + ++STARFIVE TRNG DRIVER ++M: Jia Jie Ho ++S: Supported ++F: Documentation/devicetree/bindings/rng/starfive* ++F: drivers/char/hw_random/starfive-trng.c ++ + STATIC BRANCH/CALL + M: Peter Zijlstra + M: Josh Poimboeuf +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -549,6 +549,17 @@ config HW_RANDOM_CN10K + To compile this driver as a module, choose M here. + The module will be called cn10k_rng. If unsure, say Y. + ++config HW_RANDOM_JH7110 ++ tristate "StarFive JH7110 Random Number Generator support" ++ depends on SOC_STARFIVE ++ depends on HW_RANDOM ++ help ++ This driver provides support for the True Random Number ++ Generator in StarFive JH7110 SoCs. ++ ++ To compile this driver as a module, choose M here. ++ The module will be called jh7110-trng. ++ + endif # HW_RANDOM + + config UML_RANDOM +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -47,3 +47,4 @@ obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphe + obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o + obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o + obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o ++obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o +--- /dev/null ++++ b/drivers/char/hw_random/jh7110-trng.c +@@ -0,0 +1,393 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * TRNG driver for the StarFive JH7110 SoC ++ * ++ * Copyright (C) 2022 StarFive Technology Co. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* trng register offset */ ++#define STARFIVE_CTRL 0x00 ++#define STARFIVE_STAT 0x04 ++#define STARFIVE_MODE 0x08 ++#define STARFIVE_SMODE 0x0C ++#define STARFIVE_IE 0x10 ++#define STARFIVE_ISTAT 0x14 ++#define STARFIVE_RAND0 0x20 ++#define STARFIVE_RAND1 0x24 ++#define STARFIVE_RAND2 0x28 ++#define STARFIVE_RAND3 0x2C ++#define STARFIVE_RAND4 0x30 ++#define STARFIVE_RAND5 0x34 ++#define STARFIVE_RAND6 0x38 ++#define STARFIVE_RAND7 0x3C ++#define STARFIVE_AUTO_RQSTS 0x60 ++#define STARFIVE_AUTO_AGE 0x64 ++ ++/* CTRL CMD */ ++#define STARFIVE_CTRL_EXEC_NOP 0x0 ++#define STARFIVE_CTRL_GENE_RANDNUM 0x1 ++#define STARFIVE_CTRL_EXEC_RANDRESEED 0x2 ++ ++/* STAT */ ++#define STARFIVE_STAT_NONCE_MODE BIT(2) ++#define STARFIVE_STAT_R256 BIT(3) ++#define STARFIVE_STAT_MISSION_MODE BIT(8) ++#define STARFIVE_STAT_SEEDED BIT(9) ++#define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16) ++#define STARFIVE_STAT_SRVC_RQST BIT(27) ++#define STARFIVE_STAT_RAND_GENERATING BIT(30) ++#define STARFIVE_STAT_RAND_SEEDING BIT(31) ++ ++/* MODE */ ++#define STARFIVE_MODE_R256 BIT(3) ++ ++/* SMODE */ ++#define STARFIVE_SMODE_NONCE_MODE BIT(2) ++#define STARFIVE_SMODE_MISSION_MODE BIT(8) ++#define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16) ++ ++/* IE */ ++#define STARFIVE_IE_RAND_RDY_EN BIT(0) ++#define STARFIVE_IE_SEED_DONE_EN BIT(1) ++#define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4) ++#define STARFIVE_IE_GLBL_EN BIT(31) ++ ++#define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \ ++ STARFIVE_IE_RAND_RDY_EN | \ ++ STARFIVE_IE_SEED_DONE_EN | \ ++ STARFIVE_IE_LFSR_LOCKUP_EN) ++ ++/* ISTAT */ ++#define STARFIVE_ISTAT_RAND_RDY BIT(0) ++#define STARFIVE_ISTAT_SEED_DONE BIT(1) ++#define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4) ++ ++#define STARFIVE_RAND_LEN sizeof(u32) ++ ++#define to_trng(p) container_of(p, struct starfive_trng, rng) ++ ++enum reseed { ++ RANDOM_RESEED, ++ NONCE_RESEED, ++}; ++ ++enum mode { ++ PRNG_128BIT, ++ PRNG_256BIT, ++}; ++ ++struct starfive_trng { ++ struct device *dev; ++ void __iomem *base; ++ struct clk *hclk; ++ struct clk *ahb; ++ struct reset_control *rst; ++ struct hwrng rng; ++ struct completion random_done; ++ struct completion reseed_done; ++ u32 mode; ++ u32 mission; ++ u32 reseed; ++ /* protects against concurrent write to ctrl register */ ++ spinlock_t write_lock; ++}; ++ ++static u16 autoreq; ++module_param(autoreq, ushort, 0); ++MODULE_PARM_DESC(autoreq, "Auto-reseeding after random number requests by host reaches specified counter:\n" ++ " 0 - disable counter\n" ++ " other - reload value for internal counter"); ++ ++static u16 autoage; ++module_param(autoage, ushort, 0); ++MODULE_PARM_DESC(autoage, "Auto-reseeding after specified timer countdowns to 0:\n" ++ " 0 - disable timer\n" ++ " other - reload value for internal timer"); ++ ++static inline int starfive_trng_wait_idle(struct starfive_trng *trng) ++{ ++ u32 stat; ++ ++ return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat, ++ !(stat & (STARFIVE_STAT_RAND_GENERATING | ++ STARFIVE_STAT_RAND_SEEDING)), ++ 10, 100000); ++} ++ ++static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng) ++{ ++ /* clear register: ISTAT */ ++ u32 data = readl(trng->base + STARFIVE_ISTAT); ++ ++ writel(data, trng->base + STARFIVE_ISTAT); ++} ++ ++static int starfive_trng_cmd(struct starfive_trng *trng, u32 cmd, bool wait) ++{ ++ int wait_time = 1000; ++ ++ /* allow up to 40 us for wait == 0 */ ++ if (!wait) ++ wait_time = 40; ++ ++ switch (cmd) { ++ case STARFIVE_CTRL_GENE_RANDNUM: ++ reinit_completion(&trng->random_done); ++ spin_lock_irq(&trng->write_lock); ++ writel(cmd, trng->base + STARFIVE_CTRL); ++ spin_unlock_irq(&trng->write_lock); ++ if (!wait_for_completion_timeout(&trng->random_done, usecs_to_jiffies(wait_time))) ++ return -ETIMEDOUT; ++ break; ++ case STARFIVE_CTRL_EXEC_RANDRESEED: ++ reinit_completion(&trng->reseed_done); ++ spin_lock_irq(&trng->write_lock); ++ writel(cmd, trng->base + STARFIVE_CTRL); ++ spin_unlock_irq(&trng->write_lock); ++ if (!wait_for_completion_timeout(&trng->reseed_done, usecs_to_jiffies(wait_time))) ++ return -ETIMEDOUT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int starfive_trng_init(struct hwrng *rng) ++{ ++ struct starfive_trng *trng = to_trng(rng); ++ u32 mode, intr = 0; ++ ++ /* setup Auto Request/Age register */ ++ writel(autoage, trng->base + STARFIVE_AUTO_AGE); ++ writel(autoreq, trng->base + STARFIVE_AUTO_RQSTS); ++ ++ /* clear register: ISTAT */ ++ starfive_trng_irq_mask_clear(trng); ++ ++ intr |= STARFIVE_IE_ALL; ++ writel(intr, trng->base + STARFIVE_IE); ++ ++ mode = readl(trng->base + STARFIVE_MODE); ++ ++ switch (trng->mode) { ++ case PRNG_128BIT: ++ mode &= ~STARFIVE_MODE_R256; ++ break; ++ case PRNG_256BIT: ++ mode |= STARFIVE_MODE_R256; ++ break; ++ default: ++ mode |= STARFIVE_MODE_R256; ++ break; ++ } ++ ++ writel(mode, trng->base + STARFIVE_MODE); ++ ++ return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED, 1); ++} ++ ++static irqreturn_t starfive_trng_irq(int irq, void *priv) ++{ ++ u32 status; ++ struct starfive_trng *trng = (struct starfive_trng *)priv; ++ ++ status = readl(trng->base + STARFIVE_ISTAT); ++ if (status & STARFIVE_ISTAT_RAND_RDY) { ++ writel(STARFIVE_ISTAT_RAND_RDY, trng->base + STARFIVE_ISTAT); ++ complete(&trng->random_done); ++ } ++ ++ if (status & STARFIVE_ISTAT_SEED_DONE) { ++ writel(STARFIVE_ISTAT_SEED_DONE, trng->base + STARFIVE_ISTAT); ++ complete(&trng->reseed_done); ++ } ++ ++ if (status & STARFIVE_ISTAT_LFSR_LOCKUP) { ++ writel(STARFIVE_ISTAT_LFSR_LOCKUP, trng->base + STARFIVE_ISTAT); ++ /* SEU occurred, reseeding required*/ ++ spin_lock(&trng->write_lock); ++ writel(STARFIVE_CTRL_EXEC_RANDRESEED, trng->base + STARFIVE_CTRL); ++ spin_unlock(&trng->write_lock); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void starfive_trng_cleanup(struct hwrng *rng) ++{ ++ struct starfive_trng *trng = to_trng(rng); ++ ++ writel(0, trng->base + STARFIVE_CTRL); ++ ++ reset_control_assert(trng->rst); ++ clk_disable_unprepare(trng->hclk); ++ clk_disable_unprepare(trng->ahb); ++} ++ ++static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct starfive_trng *trng = to_trng(rng); ++ int ret; ++ ++ pm_runtime_get_sync(trng->dev); ++ ++ if (trng->mode == PRNG_256BIT) ++ max = min_t(size_t, max, (STARFIVE_RAND_LEN * 8)); ++ else ++ max = min_t(size_t, max, (STARFIVE_RAND_LEN * 4)); ++ ++ if (wait) { ++ ret = starfive_trng_wait_idle(trng); ++ if (ret) ++ return -ETIMEDOUT; ++ } ++ ++ ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM, wait); ++ if (ret) ++ return ret; ++ ++ memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max); ++ ++ pm_runtime_put_sync_autosuspend(trng->dev); ++ ++ return max; ++} ++ ++static int starfive_trng_probe(struct platform_device *pdev) ++{ ++ int ret; ++ int irq; ++ struct starfive_trng *trng; ++ ++ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); ++ if (!trng) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, trng); ++ trng->dev = &pdev->dev; ++ ++ trng->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(trng->base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(trng->base), ++ "Error remapping memory for platform device.\n"); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ init_completion(&trng->random_done); ++ init_completion(&trng->reseed_done); ++ spin_lock_init(&trng->write_lock); ++ ++ ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name, ++ (void *)trng); ++ if (ret) ++ return dev_err_probe(&pdev->dev, irq, ++ "Failed to register interrupt handler\n"); ++ ++ trng->hclk = devm_clk_get(&pdev->dev, "hclk"); ++ if (IS_ERR(trng->hclk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(trng->hclk), ++ "Error getting hardware reference clock\n"); ++ ++ trng->ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(trng->ahb)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(trng->ahb), ++ "Error getting ahb reference clock\n"); ++ ++ trng->rst = devm_reset_control_get_shared(&pdev->dev, NULL); ++ if (IS_ERR(trng->rst)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(trng->rst), ++ "Error getting hardware reset line\n"); ++ ++ clk_prepare_enable(trng->hclk); ++ clk_prepare_enable(trng->ahb); ++ reset_control_deassert(trng->rst); ++ ++ trng->rng.name = dev_driver_string(&pdev->dev); ++ trng->rng.init = starfive_trng_init; ++ trng->rng.cleanup = starfive_trng_cleanup; ++ trng->rng.read = starfive_trng_read; ++ ++ trng->mode = PRNG_256BIT; ++ trng->mission = 1; ++ trng->reseed = RANDOM_RESEED; ++ ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 100); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = devm_hwrng_register(&pdev->dev, &trng->rng); ++ if (ret) { ++ pm_runtime_disable(&pdev->dev); ++ ++ reset_control_assert(trng->rst); ++ clk_disable_unprepare(trng->ahb); ++ clk_disable_unprepare(trng->hclk); ++ ++ return dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); ++ } ++ ++ return 0; ++} ++ ++static int __maybe_unused starfive_trng_suspend(struct device *dev) ++{ ++ struct starfive_trng *trng = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(trng->hclk); ++ clk_disable_unprepare(trng->ahb); ++ ++ return 0; ++} ++ ++static int __maybe_unused starfive_trng_resume(struct device *dev) ++{ ++ struct starfive_trng *trng = dev_get_drvdata(dev); ++ ++ clk_prepare_enable(trng->hclk); ++ clk_prepare_enable(trng->ahb); ++ ++ return 0; ++} ++ ++static DEFINE_SIMPLE_DEV_PM_OPS(starfive_trng_pm_ops, starfive_trng_suspend, ++ starfive_trng_resume); ++ ++static const struct of_device_id trng_dt_ids[] __maybe_unused = { ++ { .compatible = "starfive,jh7110-trng" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, trng_dt_ids); ++ ++static struct platform_driver starfive_trng_driver = { ++ .probe = starfive_trng_probe, ++ .driver = { ++ .name = "jh7110-trng", ++ .pm = &starfive_trng_pm_ops, ++ .of_match_table = of_match_ptr(trng_dt_ids), ++ }, ++}; ++ ++module_platform_driver(starfive_trng_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("StarFive True Random Number Generator"); diff --git a/target/linux/starfive/patches-6.1/0103-hwrng-starfive-Enable-compile-testing.patch b/target/linux/starfive/patches-6.1/0103-hwrng-starfive-Enable-compile-testing.patch new file mode 100644 index 0000000000..39b4bc6ad9 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0103-hwrng-starfive-Enable-compile-testing.patch @@ -0,0 +1,28 @@ +From 4b02d00911c2e6bd31d8160b0337174dd55dc644 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Fri, 27 Jan 2023 19:03:21 +0800 +Subject: [PATCH 103/122] hwrng: starfive - Enable compile testing + +Enable compile testing for jh7110. Also remove the dependency on +HW_RANDOM. + +Signed-off-by: Herbert Xu +Reviewed-by: Conor Dooley +Reviewed-by: Jia Jie Ho +Signed-off-by: Herbert Xu +--- + drivers/char/hw_random/Kconfig | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -551,8 +551,7 @@ config HW_RANDOM_CN10K + + config HW_RANDOM_JH7110 + tristate "StarFive JH7110 Random Number Generator support" +- depends on SOC_STARFIVE +- depends on HW_RANDOM ++ depends on SOC_STARFIVE || COMPILE_TEST + help + This driver provides support for the True Random Number + Generator in StarFive JH7110 SoCs. diff --git a/target/linux/starfive/patches-6.1/0104-dt-bindings-watchdog-Add-watchdog-for-StarFive-JH710.patch b/target/linux/starfive/patches-6.1/0104-dt-bindings-watchdog-Add-watchdog-for-StarFive-JH710.patch new file mode 100644 index 0000000000..f68232f035 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0104-dt-bindings-watchdog-Add-watchdog-for-StarFive-JH710.patch @@ -0,0 +1,91 @@ +From 8559b2db6aecbee62cf9e02c17349379d72edcfb Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 14 Mar 2023 21:24:35 +0800 +Subject: [PATCH 104/122] dt-bindings: watchdog: Add watchdog for StarFive + JH7100 and JH7110 + +Add bindings to describe the watchdog for the StarFive JH7100/JH7110 SoC. +And Use JH7100 as first StarFive SoC with watchdog. + +Signed-off-by: Xingyu Wu +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Guenter Roeck +--- + .../watchdog/starfive,jh7100-wdt.yaml | 71 +++++++++++++++++++ + 1 file changed, 71 insertions(+) + create mode 100644 Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml +@@ -0,0 +1,71 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/watchdog/starfive,jh7100-wdt.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive Watchdog for JH7100 and JH7110 SoC ++ ++maintainers: ++ - Xingyu Wu ++ - Samin Guo ++ ++description: ++ The JH7100 and JH7110 watchdog both are 32 bit counters. JH7100 watchdog ++ has only one timeout phase and reboots. And JH7110 watchdog has two ++ timeout phases. At the first phase, the signal of watchdog interrupt ++ output(WDOGINT) will rise when counter is 0. The counter will reload ++ the timeout value. And then, if counter decreases to 0 again and WDOGINT ++ isn't cleared, the watchdog will reset the system unless the watchdog ++ reset is disabled. ++ ++allOf: ++ - $ref: watchdog.yaml# ++ ++properties: ++ compatible: ++ enum: ++ - starfive,jh7100-wdt ++ - starfive,jh7110-wdt ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: APB clock ++ - description: Core clock ++ ++ clock-names: ++ items: ++ - const: apb ++ - const: core ++ ++ resets: ++ items: ++ - description: APB reset ++ - description: Core reset ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ watchdog@12480000 { ++ compatible = "starfive,jh7100-wdt"; ++ reg = <0x12480000 0x10000>; ++ clocks = <&clk 171>, ++ <&clk 172>; ++ clock-names = "apb", "core"; ++ resets = <&rst 99>, ++ <&rst 100>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch b/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch new file mode 100644 index 0000000000..ec330250e2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch @@ -0,0 +1,675 @@ +From e835861823130ae47665db5e8039a7097ede14e4 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 14 Mar 2023 21:24:36 +0800 +Subject: [PATCH 105/122] drivers: watchdog: Add StarFive Watchdog driver + +Add watchdog driver for the StarFive JH7100 and JH7110 SoC. + +Signed-off-by: Xingyu Wu +Reviewed-by: Emil Renner Berthing +Reviewed-by: Guenter Roeck +--- + MAINTAINERS | 7 + + drivers/watchdog/Kconfig | 11 + + drivers/watchdog/Makefile | 3 + + drivers/watchdog/starfive-wdt.c | 606 ++++++++++++++++++++++++++++++++ + 4 files changed, 627 insertions(+) + create mode 100644 drivers/watchdog/starfive-wdt.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19715,6 +19715,13 @@ S: Supported + F: Documentation/devicetree/bindings/rng/starfive* + F: drivers/char/hw_random/starfive-trng.c + ++STARFIVE WATCHDOG DRIVER ++M: Xingyu Wu ++M: Samin Guo ++S: Supported ++F: Documentation/devicetree/bindings/watchdog/starfive* ++F: drivers/watchdog/starfive-wdt.c ++ + STATIC BRANCH/CALL + M: Peter Zijlstra + M: Josh Poimboeuf +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1991,6 +1991,17 @@ config WATCHDOG_RTAS + To compile this driver as a module, choose M here. The module + will be called wdrtas. + ++# RISC-V Architecture ++ ++config STARFIVE_WATCHDOG ++ tristate "StarFive Watchdog support" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ select WATCHDOG_CORE ++ default ARCH_STARFIVE ++ help ++ Say Y here to support the watchdog of StarFive JH7100 and JH7110 ++ SoC. This driver can also be built as a module if choose M. ++ + # S390 Architecture + + config DIAG288_WATCHDOG +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -191,6 +191,9 @@ obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt. + obj-$(CONFIG_PSERIES_WDT) += pseries-wdt.o + obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o + ++# RISC-V Architecture ++obj-$(CONFIG_STARFIVE_WATCHDOG) += starfive-wdt.o ++ + # S390 Architecture + obj-$(CONFIG_DIAG288_WATCHDOG) += diag288_wdt.o + +--- /dev/null ++++ b/drivers/watchdog/starfive-wdt.c +@@ -0,0 +1,606 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Starfive Watchdog driver ++ * ++ * Copyright (C) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* JH7100 Watchdog register define */ ++#define STARFIVE_WDT_JH7100_INTSTAUS 0x000 ++#define STARFIVE_WDT_JH7100_CONTROL 0x104 ++#define STARFIVE_WDT_JH7100_LOAD 0x108 ++#define STARFIVE_WDT_JH7100_EN 0x110 ++#define STARFIVE_WDT_JH7100_RELOAD 0x114 /* Write 0 or 1 to reload preset value */ ++#define STARFIVE_WDT_JH7100_VALUE 0x118 ++#define STARFIVE_WDT_JH7100_INTCLR 0x120 /* ++ * [0]: Write 1 to clear interrupt ++ * [1]: 1 mean clearing and 0 mean complete ++ * [31:2]: reserved. ++ */ ++#define STARFIVE_WDT_JH7100_LOCK 0x13c /* write 0x378f0765 to unlock */ ++ ++/* JH7110 Watchdog register define */ ++#define STARFIVE_WDT_JH7110_LOAD 0x000 ++#define STARFIVE_WDT_JH7110_VALUE 0x004 ++#define STARFIVE_WDT_JH7110_CONTROL 0x008 /* ++ * [0]: reset enable; ++ * [1]: interrupt enable && watchdog enable ++ * [31:2]: reserved. ++ */ ++#define STARFIVE_WDT_JH7110_INTCLR 0x00c /* clear intterupt and reload the counter */ ++#define STARFIVE_WDT_JH7110_IMS 0x014 ++#define STARFIVE_WDT_JH7110_LOCK 0xc00 /* write 0x1ACCE551 to unlock */ ++ ++/* WDOGCONTROL */ ++#define STARFIVE_WDT_ENABLE 0x1 ++#define STARFIVE_WDT_EN_SHIFT 0 ++#define STARFIVE_WDT_RESET_EN 0x1 ++#define STARFIVE_WDT_JH7100_RST_EN_SHIFT 0 ++#define STARFIVE_WDT_JH7110_RST_EN_SHIFT 1 ++ ++/* WDOGLOCK */ ++#define STARFIVE_WDT_JH7100_UNLOCK_KEY 0x378f0765 ++#define STARFIVE_WDT_JH7110_UNLOCK_KEY 0x1acce551 ++ ++/* WDOGINTCLR */ ++#define STARFIVE_WDT_INTCLR 0x1 ++#define STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT 1 /* Watchdog can clear interrupt when 0 */ ++ ++#define STARFIVE_WDT_MAXCNT 0xffffffff ++#define STARFIVE_WDT_DEFAULT_TIME (15) ++#define STARFIVE_WDT_DELAY_US 0 ++#define STARFIVE_WDT_TIMEOUT_US 10000 ++ ++/* module parameter */ ++#define STARFIVE_WDT_EARLY_ENA 0 ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++static int heartbeat; ++static bool early_enable = STARFIVE_WDT_EARLY_ENA; ++ ++module_param(heartbeat, int, 0); ++module_param(early_enable, bool, 0); ++module_param(nowayout, bool, 0); ++ ++MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default=" ++ __MODULE_STRING(STARFIVE_WDT_DEFAULT_TIME) ")"); ++MODULE_PARM_DESC(early_enable, ++ "Watchdog is started at boot time if set to 1, default=" ++ __MODULE_STRING(STARFIVE_WDT_EARLY_ENA)); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++struct starfive_wdt_variant { ++ unsigned int control; /* Watchdog Control Resgister for reset enable */ ++ unsigned int load; /* Watchdog Load register */ ++ unsigned int reload; /* Watchdog Reload Control register */ ++ unsigned int enable; /* Watchdog Enable Register */ ++ unsigned int value; /* Watchdog Counter Value Register */ ++ unsigned int int_clr; /* Watchdog Interrupt Clear Register */ ++ unsigned int unlock; /* Watchdog Lock Register */ ++ unsigned int int_status; /* Watchdog Interrupt Status Register */ ++ ++ u32 unlock_key; ++ char enrst_shift; ++ char en_shift; ++ bool intclr_check; /* whether need to check it before clearing interrupt */ ++ char intclr_ava_shift; ++ bool double_timeout; /* The watchdog need twice timeout to reboot */ ++}; ++ ++struct starfive_wdt { ++ struct watchdog_device wdd; ++ spinlock_t lock; /* spinlock for register handling */ ++ void __iomem *base; ++ struct clk *core_clk; ++ struct clk *apb_clk; ++ const struct starfive_wdt_variant *variant; ++ unsigned long freq; ++ u32 count; /* count of timeout */ ++ u32 reload; /* restore the count */ ++}; ++ ++/* Register layout and configuration for the JH7100 */ ++static const struct starfive_wdt_variant starfive_wdt_jh7100_variant = { ++ .control = STARFIVE_WDT_JH7100_CONTROL, ++ .load = STARFIVE_WDT_JH7100_LOAD, ++ .reload = STARFIVE_WDT_JH7100_RELOAD, ++ .enable = STARFIVE_WDT_JH7100_EN, ++ .value = STARFIVE_WDT_JH7100_VALUE, ++ .int_clr = STARFIVE_WDT_JH7100_INTCLR, ++ .unlock = STARFIVE_WDT_JH7100_LOCK, ++ .unlock_key = STARFIVE_WDT_JH7100_UNLOCK_KEY, ++ .int_status = STARFIVE_WDT_JH7100_INTSTAUS, ++ .enrst_shift = STARFIVE_WDT_JH7100_RST_EN_SHIFT, ++ .en_shift = STARFIVE_WDT_EN_SHIFT, ++ .intclr_check = true, ++ .intclr_ava_shift = STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT, ++ .double_timeout = false, ++}; ++ ++/* Register layout and configuration for the JH7110 */ ++static const struct starfive_wdt_variant starfive_wdt_jh7110_variant = { ++ .control = STARFIVE_WDT_JH7110_CONTROL, ++ .load = STARFIVE_WDT_JH7110_LOAD, ++ .enable = STARFIVE_WDT_JH7110_CONTROL, ++ .value = STARFIVE_WDT_JH7110_VALUE, ++ .int_clr = STARFIVE_WDT_JH7110_INTCLR, ++ .unlock = STARFIVE_WDT_JH7110_LOCK, ++ .unlock_key = STARFIVE_WDT_JH7110_UNLOCK_KEY, ++ .int_status = STARFIVE_WDT_JH7110_IMS, ++ .enrst_shift = STARFIVE_WDT_JH7110_RST_EN_SHIFT, ++ .en_shift = STARFIVE_WDT_EN_SHIFT, ++ .intclr_check = false, ++ .double_timeout = true, ++}; ++ ++static int starfive_wdt_enable_clock(struct starfive_wdt *wdt) ++{ ++ int ret; ++ ++ ret = clk_prepare_enable(wdt->apb_clk); ++ if (ret) ++ return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n"); ++ ++ ret = clk_prepare_enable(wdt->core_clk); ++ if (ret) ++ return dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n"); ++ ++ return 0; ++} ++ ++static void starfive_wdt_disable_clock(struct starfive_wdt *wdt) ++{ ++ clk_disable_unprepare(wdt->core_clk); ++ clk_disable_unprepare(wdt->apb_clk); ++} ++ ++static inline int starfive_wdt_get_clock(struct starfive_wdt *wdt) ++{ ++ struct device *dev = wdt->wdd.parent; ++ ++ wdt->apb_clk = devm_clk_get(dev, "apb"); ++ if (IS_ERR(wdt->apb_clk)) ++ return dev_err_probe(dev, PTR_ERR(wdt->apb_clk), "failed to get apb clock\n"); ++ ++ wdt->core_clk = devm_clk_get(dev, "core"); ++ if (IS_ERR(wdt->core_clk)) ++ return dev_err_probe(dev, PTR_ERR(wdt->core_clk), "failed to get core clock\n"); ++ ++ return 0; ++} ++ ++static inline int starfive_wdt_reset_init(struct device *dev) ++{ ++ struct reset_control *rsts; ++ int ret; ++ ++ rsts = devm_reset_control_array_get_exclusive(dev); ++ if (IS_ERR(rsts)) ++ return dev_err_probe(dev, PTR_ERR(rsts), "failed to get resets\n"); ++ ++ ret = reset_control_deassert(rsts); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to deassert resets\n"); ++ ++ return 0; ++} ++ ++static u32 starfive_wdt_ticks_to_sec(struct starfive_wdt *wdt, u32 ticks) ++{ ++ return DIV_ROUND_CLOSEST(ticks, wdt->freq); ++} ++ ++/* Write unlock-key to unlock. Write other value to lock. */ ++static void starfive_wdt_unlock(struct starfive_wdt *wdt) ++{ ++ spin_lock(&wdt->lock); ++ writel(wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); ++} ++ ++static void starfive_wdt_lock(struct starfive_wdt *wdt) ++{ ++ writel(~wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); ++ spin_unlock(&wdt->lock); ++} ++ ++/* enable watchdog interrupt to reset/reboot */ ++static void starfive_wdt_enable_reset(struct starfive_wdt *wdt) ++{ ++ u32 val; ++ ++ val = readl(wdt->base + wdt->variant->control); ++ val |= STARFIVE_WDT_RESET_EN << wdt->variant->enrst_shift; ++ writel(val, wdt->base + wdt->variant->control); ++} ++ ++/* interrupt status whether has been raised from the counter */ ++static bool starfive_wdt_raise_irq_status(struct starfive_wdt *wdt) ++{ ++ return !!readl(wdt->base + wdt->variant->int_status); ++} ++ ++/* waiting interrupt can be free to clear */ ++static int starfive_wdt_wait_int_free(struct starfive_wdt *wdt) ++{ ++ u32 value; ++ ++ return readl_poll_timeout_atomic(wdt->base + wdt->variant->int_clr, value, ++ !(value & BIT(wdt->variant->intclr_ava_shift)), ++ STARFIVE_WDT_DELAY_US, STARFIVE_WDT_TIMEOUT_US); ++} ++ ++/* clear interrupt signal before initialization or reload */ ++static int starfive_wdt_int_clr(struct starfive_wdt *wdt) ++{ ++ int ret; ++ ++ if (wdt->variant->intclr_check) { ++ ret = starfive_wdt_wait_int_free(wdt); ++ if (ret) ++ return dev_err_probe(wdt->wdd.parent, ret, ++ "watchdog is not ready to clear interrupt.\n"); ++ } ++ writel(STARFIVE_WDT_INTCLR, wdt->base + wdt->variant->int_clr); ++ ++ return 0; ++} ++ ++static inline void starfive_wdt_set_count(struct starfive_wdt *wdt, u32 val) ++{ ++ writel(val, wdt->base + wdt->variant->load); ++} ++ ++static inline u32 starfive_wdt_get_count(struct starfive_wdt *wdt) ++{ ++ return readl(wdt->base + wdt->variant->value); ++} ++ ++/* enable watchdog */ ++static inline void starfive_wdt_enable(struct starfive_wdt *wdt) ++{ ++ u32 val; ++ ++ val = readl(wdt->base + wdt->variant->enable); ++ val |= STARFIVE_WDT_ENABLE << wdt->variant->en_shift; ++ writel(val, wdt->base + wdt->variant->enable); ++} ++ ++/* disable watchdog */ ++static inline void starfive_wdt_disable(struct starfive_wdt *wdt) ++{ ++ u32 val; ++ ++ val = readl(wdt->base + wdt->variant->enable); ++ val &= ~(STARFIVE_WDT_ENABLE << wdt->variant->en_shift); ++ writel(val, wdt->base + wdt->variant->enable); ++} ++ ++static inline void starfive_wdt_set_reload_count(struct starfive_wdt *wdt, u32 count) ++{ ++ starfive_wdt_set_count(wdt, count); ++ ++ /* 7100 need set any value to reload register and could reload value to counter */ ++ if (wdt->variant->reload) ++ writel(0x1, wdt->base + wdt->variant->reload); ++} ++ ++static unsigned int starfive_wdt_max_timeout(struct starfive_wdt *wdt) ++{ ++ if (wdt->variant->double_timeout) ++ return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, (wdt->freq / 2)) - 1; ++ ++ return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, wdt->freq) - 1; ++} ++ ++static unsigned int starfive_wdt_get_timeleft(struct watchdog_device *wdd) ++{ ++ struct starfive_wdt *wdt = watchdog_get_drvdata(wdd); ++ u32 count; ++ ++ /* ++ * If the watchdog takes twice timeout and set half count value, ++ * timeleft value should add the count value before first timeout. ++ */ ++ count = starfive_wdt_get_count(wdt); ++ if (wdt->variant->double_timeout && !starfive_wdt_raise_irq_status(wdt)) ++ count += wdt->count; ++ ++ return starfive_wdt_ticks_to_sec(wdt, count); ++} ++ ++static int starfive_wdt_keepalive(struct watchdog_device *wdd) ++{ ++ struct starfive_wdt *wdt = watchdog_get_drvdata(wdd); ++ int ret; ++ ++ starfive_wdt_unlock(wdt); ++ ret = starfive_wdt_int_clr(wdt); ++ if (ret) ++ goto exit; ++ ++ starfive_wdt_set_reload_count(wdt, wdt->count); ++ ++exit: ++ /* exit with releasing spinlock and locking registers */ ++ starfive_wdt_lock(wdt); ++ return ret; ++} ++ ++static int starfive_wdt_start(struct starfive_wdt *wdt) ++{ ++ int ret; ++ ++ starfive_wdt_unlock(wdt); ++ /* disable watchdog, to be safe */ ++ starfive_wdt_disable(wdt); ++ ++ starfive_wdt_enable_reset(wdt); ++ ret = starfive_wdt_int_clr(wdt); ++ if (ret) ++ goto exit; ++ ++ starfive_wdt_set_count(wdt, wdt->count); ++ starfive_wdt_enable(wdt); ++ ++exit: ++ starfive_wdt_lock(wdt); ++ return ret; ++} ++ ++static void starfive_wdt_stop(struct starfive_wdt *wdt) ++{ ++ starfive_wdt_unlock(wdt); ++ starfive_wdt_disable(wdt); ++ starfive_wdt_lock(wdt); ++} ++ ++static int starfive_wdt_pm_start(struct watchdog_device *wdd) ++{ ++ struct starfive_wdt *wdt = watchdog_get_drvdata(wdd); ++ int ret = pm_runtime_get_sync(wdd->parent); ++ ++ if (ret < 0) ++ return ret; ++ ++ return starfive_wdt_start(wdt); ++} ++ ++static int starfive_wdt_pm_stop(struct watchdog_device *wdd) ++{ ++ struct starfive_wdt *wdt = watchdog_get_drvdata(wdd); ++ ++ starfive_wdt_stop(wdt); ++ return pm_runtime_put_sync(wdd->parent); ++} ++ ++static int starfive_wdt_set_timeout(struct watchdog_device *wdd, ++ unsigned int timeout) ++{ ++ struct starfive_wdt *wdt = watchdog_get_drvdata(wdd); ++ unsigned long count = timeout * wdt->freq; ++ ++ /* some watchdogs take two timeouts to reset */ ++ if (wdt->variant->double_timeout) ++ count /= 2; ++ ++ wdt->count = count; ++ wdd->timeout = timeout; ++ ++ starfive_wdt_unlock(wdt); ++ starfive_wdt_disable(wdt); ++ starfive_wdt_set_reload_count(wdt, wdt->count); ++ starfive_wdt_enable(wdt); ++ starfive_wdt_lock(wdt); ++ ++ return 0; ++} ++ ++#define STARFIVE_WDT_OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE) ++ ++static const struct watchdog_info starfive_wdt_info = { ++ .options = STARFIVE_WDT_OPTIONS, ++ .identity = "StarFive Watchdog", ++}; ++ ++static const struct watchdog_ops starfive_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = starfive_wdt_pm_start, ++ .stop = starfive_wdt_pm_stop, ++ .ping = starfive_wdt_keepalive, ++ .set_timeout = starfive_wdt_set_timeout, ++ .get_timeleft = starfive_wdt_get_timeleft, ++}; ++ ++static int starfive_wdt_probe(struct platform_device *pdev) ++{ ++ struct starfive_wdt *wdt; ++ int ret; ++ ++ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); ++ if (!wdt) ++ return -ENOMEM; ++ ++ wdt->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(wdt->base)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(wdt->base), "error mapping registers\n"); ++ ++ wdt->wdd.parent = &pdev->dev; ++ ret = starfive_wdt_get_clock(wdt); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, wdt); ++ pm_runtime_enable(&pdev->dev); ++ if (pm_runtime_enabled(&pdev->dev)) { ++ ret = pm_runtime_get_sync(&pdev->dev); ++ if (ret < 0) ++ return ret; ++ } else { ++ /* runtime PM is disabled but clocks need to be enabled */ ++ ret = starfive_wdt_enable_clock(wdt); ++ if (ret) ++ return ret; ++ } ++ ++ ret = starfive_wdt_reset_init(&pdev->dev); ++ if (ret) ++ goto err_exit; ++ ++ watchdog_set_drvdata(&wdt->wdd, wdt); ++ wdt->wdd.info = &starfive_wdt_info; ++ wdt->wdd.ops = &starfive_wdt_ops; ++ wdt->variant = of_device_get_match_data(&pdev->dev); ++ spin_lock_init(&wdt->lock); ++ ++ wdt->freq = clk_get_rate(wdt->core_clk); ++ if (!wdt->freq) { ++ dev_err(&pdev->dev, "get clock rate failed.\n"); ++ ret = -EINVAL; ++ goto err_exit; ++ } ++ ++ wdt->wdd.min_timeout = 1; ++ wdt->wdd.max_timeout = starfive_wdt_max_timeout(wdt); ++ wdt->wdd.timeout = STARFIVE_WDT_DEFAULT_TIME; ++ watchdog_init_timeout(&wdt->wdd, heartbeat, &pdev->dev); ++ starfive_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout); ++ ++ watchdog_set_nowayout(&wdt->wdd, nowayout); ++ watchdog_stop_on_reboot(&wdt->wdd); ++ watchdog_stop_on_unregister(&wdt->wdd); ++ ++ if (early_enable) { ++ ret = starfive_wdt_start(wdt); ++ if (ret) ++ goto err_exit; ++ set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); ++ } else { ++ starfive_wdt_stop(wdt); ++ } ++ ++ ret = watchdog_register_device(&wdt->wdd); ++ if (ret) ++ goto err_exit; ++ ++ if (!early_enable) ++ return pm_runtime_put_sync(&pdev->dev); ++ ++ return 0; ++ ++err_exit: ++ starfive_wdt_disable_clock(wdt); ++ pm_runtime_disable(&pdev->dev); ++ ++ return ret; ++} ++ ++static int starfive_wdt_remove(struct platform_device *pdev) ++{ ++ struct starfive_wdt *wdt = platform_get_drvdata(pdev); ++ ++ starfive_wdt_stop(wdt); ++ watchdog_unregister_device(&wdt->wdd); ++ ++ if (pm_runtime_enabled(&pdev->dev)) ++ pm_runtime_disable(&pdev->dev); ++ else ++ /* disable clock without PM */ ++ starfive_wdt_disable_clock(wdt); ++ ++ return 0; ++} ++ ++static void starfive_wdt_shutdown(struct platform_device *pdev) ++{ ++ struct starfive_wdt *wdt = platform_get_drvdata(pdev); ++ ++ starfive_wdt_pm_stop(&wdt->wdd); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int starfive_wdt_suspend(struct device *dev) ++{ ++ struct starfive_wdt *wdt = dev_get_drvdata(dev); ++ ++ /* Save watchdog state, and turn it off. */ ++ wdt->reload = starfive_wdt_get_count(wdt); ++ ++ /* Note that WTCNT doesn't need to be saved. */ ++ starfive_wdt_stop(wdt); ++ ++ return pm_runtime_force_suspend(dev); ++} ++ ++static int starfive_wdt_resume(struct device *dev) ++{ ++ struct starfive_wdt *wdt = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret) ++ return ret; ++ ++ starfive_wdt_unlock(wdt); ++ /* Restore watchdog state. */ ++ starfive_wdt_set_reload_count(wdt, wdt->reload); ++ starfive_wdt_lock(wdt); ++ ++ return starfive_wdt_start(wdt); ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++#ifdef CONFIG_PM ++static int starfive_wdt_runtime_suspend(struct device *dev) ++{ ++ struct starfive_wdt *wdt = dev_get_drvdata(dev); ++ ++ starfive_wdt_disable_clock(wdt); ++ ++ return 0; ++} ++ ++static int starfive_wdt_runtime_resume(struct device *dev) ++{ ++ struct starfive_wdt *wdt = dev_get_drvdata(dev); ++ ++ return starfive_wdt_enable_clock(wdt); ++} ++#endif /* CONFIG_PM */ ++ ++static const struct dev_pm_ops starfive_wdt_pm_ops = { ++ SET_RUNTIME_PM_OPS(starfive_wdt_runtime_suspend, starfive_wdt_runtime_resume, NULL) ++ SET_SYSTEM_SLEEP_PM_OPS(starfive_wdt_suspend, starfive_wdt_resume) ++}; ++ ++static const struct of_device_id starfive_wdt_match[] = { ++ { .compatible = "starfive,jh7100-wdt", .data = &starfive_wdt_jh7100_variant }, ++ { .compatible = "starfive,jh7110-wdt", .data = &starfive_wdt_jh7110_variant }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, starfive_wdt_match); ++ ++static struct platform_driver starfive_wdt_driver = { ++ .probe = starfive_wdt_probe, ++ .remove = starfive_wdt_remove, ++ .shutdown = starfive_wdt_shutdown, ++ .driver = { ++ .name = "starfive-wdt", ++ .pm = &starfive_wdt_pm_ops, ++ .of_match_table = of_match_ptr(starfive_wdt_match), ++ }, ++}; ++module_platform_driver(starfive_wdt_driver); ++ ++MODULE_AUTHOR("Xingyu Wu "); ++MODULE_AUTHOR("Samin Guo "); ++MODULE_DESCRIPTION("StarFive Watchdog Device Driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0106-riscv-dts-starfive-jh7100-Add-watchdog-node.patch b/target/linux/starfive/patches-6.1/0106-riscv-dts-starfive-jh7100-Add-watchdog-node.patch new file mode 100644 index 0000000000..a7b7bd88db --- /dev/null +++ b/target/linux/starfive/patches-6.1/0106-riscv-dts-starfive-jh7100-Add-watchdog-node.patch @@ -0,0 +1,31 @@ +From b085b6233065b1e5145fbf93d75264b2042c0eb5 Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Tue, 14 Mar 2023 21:24:37 +0800 +Subject: [PATCH 106/122] riscv: dts: starfive: jh7100: Add watchdog node + +Add watchdog node for the StarFive JH7100 RISC-V SoC. + +Signed-off-by: Xingyu Wu +Reviewed-by: Emil Renner Berthing +--- + arch/riscv/boot/dts/starfive/jh7100.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -238,5 +238,15 @@ + #size-cells = <0>; + status = "disabled"; + }; ++ ++ watchdog@12480000 { ++ compatible = "starfive,jh7100-wdt"; ++ reg = <0x0 0x12480000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_WDTIMER_APB>, ++ <&clkgen JH7100_CLK_WDT_CORE>; ++ clock-names = "apb", "core"; ++ resets = <&rstgen JH7100_RSTN_WDTIMER_APB>, ++ <&rstgen JH7100_RSTN_WDT>; ++ }; + }; + }; diff --git a/target/linux/starfive/patches-6.1/0107-dt-bindings-mmc-Add-StarFive-MMC-module.patch b/target/linux/starfive/patches-6.1/0107-dt-bindings-mmc-Add-StarFive-MMC-module.patch new file mode 100644 index 0000000000..39844b5b77 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0107-dt-bindings-mmc-Add-StarFive-MMC-module.patch @@ -0,0 +1,95 @@ +From fc157f3d411ac570e8261e4238c6e6aac74a6cc6 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Wed, 15 Feb 2023 19:32:46 +0800 +Subject: [PATCH 107/122] dt-bindings: mmc: Add StarFive MMC module + +Add documentation to describe StarFive designware mobile storage +host controller driver. + +Signed-off-by: William Qiu +Reviewed-by: Krzysztof Kozlowski +--- + .../bindings/mmc/starfive,jh7110-mmc.yaml | 77 +++++++++++++++++++ + 1 file changed, 77 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml +@@ -0,0 +1,77 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mmc/starfive,jh7110-mmc.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive Designware Mobile Storage Host Controller ++ ++description: ++ StarFive uses the Synopsys designware mobile storage host controller ++ to interface a SoC with storage medium such as eMMC or SD/MMC cards. ++ ++allOf: ++ - $ref: synopsys-dw-mshc-common.yaml# ++ ++maintainers: ++ - William Qiu ++ ++properties: ++ compatible: ++ const: starfive,jh7110-mmc ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: biu clock ++ - description: ciu clock ++ ++ clock-names: ++ items: ++ - const: biu ++ - const: ciu ++ ++ interrupts: ++ maxItems: 1 ++ ++ starfive,sysreg: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ items: ++ - items: ++ - description: phandle to System Register Controller syscon node ++ - description: offset of SYS_SYSCONSAIF__SYSCFG register for MMC controller ++ - description: shift of SYS_SYSCONSAIF__SYSCFG register for MMC controller ++ - description: mask of SYS_SYSCONSAIF__SYSCFG register for MMC controller ++ description: ++ Should be four parameters, the phandle to System Register Controller ++ syscon node and the offset/shift/mask of SYS_SYSCONSAIF__SYSCFG register ++ for MMC controller. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - interrupts ++ - starfive,sysreg ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ mmc@16010000 { ++ compatible = "starfive,jh7110-mmc"; ++ reg = <0x16010000 0x10000>; ++ clocks = <&syscrg 91>, ++ <&syscrg 93>; ++ clock-names = "biu","ciu"; ++ resets = <&syscrg 64>; ++ reset-names = "reset"; ++ interrupts = <74>; ++ fifo-depth = <32>; ++ fifo-watermark-aligned; ++ data-addr = <0>; ++ starfive,sysreg = <&sys_syscon 0x14 0x1a 0x7c000000>; ++ }; diff --git a/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch b/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch new file mode 100644 index 0000000000..3aecc0a204 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch @@ -0,0 +1,250 @@ +From ee990c664fad993275b2615d0ff06af5d04922f0 Mon Sep 17 00:00:00 2001 +From: William Qiu +Date: Wed, 15 Feb 2023 19:32:47 +0800 +Subject: [PATCH 108/122] mmc: starfive: Add sdio/emmc driver support + +Add sdio/emmc driver support for StarFive JH7110 soc. + +Tested-by: Conor Dooley +Signed-off-by: William Qiu +--- + MAINTAINERS | 6 + + drivers/mmc/host/Kconfig | 10 ++ + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/dw_mmc-starfive.c | 186 +++++++++++++++++++++++++++++ + 4 files changed, 203 insertions(+) + create mode 100644 drivers/mmc/host/dw_mmc-starfive.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19657,6 +19657,12 @@ S: Maintained + F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml + F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c + ++STARFIVE JH7110 MMC/SD/SDIO DRIVER ++M: William Qiu ++S: Supported ++F: Documentation/devicetree/bindings/mmc/starfive* ++F: drivers/mmc/host/dw_mmc-starfive.c ++ + STARFIVE JH7110 PLL CLOCK DRIVER + M: Xingyu Wu + S: Supported +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -872,6 +872,16 @@ config MMC_DW_ROCKCHIP + Synopsys DesignWare Memory Card Interface driver. Select this option + for platforms based on RK3066, RK3188 and RK3288 SoC's. + ++config MMC_DW_STARFIVE ++ tristate "StarFive specific extensions for Synopsys DW Memory Card Interface" ++ depends on SOC_STARFIVE ++ depends on MMC_DW ++ select MMC_DW_PLTFM ++ help ++ This selects support for StarFive JH7110 SoC specific extensions to the ++ Synopsys DesignWare Memory Card Interface driver. Select this option ++ for platforms based on StarFive JH7110 SoC. ++ + config MMC_SH_MMCIF + tristate "SuperH Internal MMCIF support" + depends on SUPERH || ARCH_RENESAS || COMPILE_TEST +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -56,6 +56,7 @@ obj-$(CONFIG_MMC_DW_HI3798CV200) += dw_m + obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o + obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o + obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o ++obj-$(CONFIG_MMC_DW_STARFIVE) += dw_mmc-starfive.o + obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o + obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o + obj-$(CONFIG_MMC_VUB300) += vub300.o +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-starfive.c +@@ -0,0 +1,186 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * StarFive Designware Mobile Storage Host Controller Driver ++ * ++ * Copyright (c) 2022 StarFive Technology Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dw_mmc.h" ++#include "dw_mmc-pltfm.h" ++ ++#define ALL_INT_CLR 0x1ffff ++#define MAX_DELAY_CHAIN 32 ++ ++struct starfive_priv { ++ struct device *dev; ++ struct regmap *reg_syscon; ++ u32 syscon_offset; ++ u32 syscon_shift; ++ u32 syscon_mask; ++}; ++ ++static void dw_mci_starfive_set_ios(struct dw_mci *host, struct mmc_ios *ios) ++{ ++ int ret; ++ unsigned int clock; ++ ++ if (ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_DDR50) { ++ clock = (ios->clock > 50000000 && ios->clock <= 52000000) ? 100000000 : ios->clock; ++ ret = clk_set_rate(host->ciu_clk, clock); ++ if (ret) ++ dev_dbg(host->dev, "Use an external frequency divider %uHz\n", ios->clock); ++ host->bus_hz = clk_get_rate(host->ciu_clk); ++ } else { ++ dev_dbg(host->dev, "Using the internal divider\n"); ++ } ++} ++ ++static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot, ++ u32 opcode) ++{ ++ static const int grade = MAX_DELAY_CHAIN; ++ struct dw_mci *host = slot->host; ++ struct starfive_priv *priv = host->priv; ++ int rise_point = -1, fall_point = -1; ++ int err, prev_err; ++ int i; ++ bool found = 0; ++ u32 regval; ++ ++ /* ++ * Use grade as the max delay chain, and use the rise_point and ++ * fall_point to ensure the best sampling point of a data input ++ * signals. ++ */ ++ for (i = 0; i < grade; i++) { ++ regval = i << priv->syscon_shift; ++ err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset, ++ priv->syscon_mask, regval); ++ if (err) ++ return err; ++ mci_writel(host, RINTSTS, ALL_INT_CLR); ++ ++ err = mmc_send_tuning(slot->mmc, opcode, NULL); ++ if (!err) ++ found = 1; ++ ++ if (i > 0) { ++ if (err && !prev_err) ++ fall_point = i - 1; ++ if (!err && prev_err) ++ rise_point = i; ++ } ++ ++ if (rise_point != -1 && fall_point != -1) ++ goto tuning_out; ++ ++ prev_err = err; ++ err = 0; ++ } ++ ++tuning_out: ++ if (found) { ++ if (rise_point == -1) ++ rise_point = 0; ++ if (fall_point == -1) ++ fall_point = grade - 1; ++ if (fall_point < rise_point) { ++ if ((rise_point + fall_point) > ++ (grade - 1)) ++ i = fall_point / 2; ++ else ++ i = (rise_point + grade - 1) / 2; ++ } else { ++ i = (rise_point + fall_point) / 2; ++ } ++ ++ regval = i << priv->syscon_shift; ++ err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset, ++ priv->syscon_mask, regval); ++ if (err) ++ return err; ++ mci_writel(host, RINTSTS, ALL_INT_CLR); ++ ++ dev_info(host->dev, "Found valid delay chain! use it [delay=%d]\n", i); ++ } else { ++ dev_err(host->dev, "No valid delay chain! use default\n"); ++ err = -EINVAL; ++ } ++ ++ mci_writel(host, RINTSTS, ALL_INT_CLR); ++ return err; ++} ++ ++static int dw_mci_starfive_parse_dt(struct dw_mci *host) ++{ ++ struct of_phandle_args args; ++ struct starfive_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ ret = of_parse_phandle_with_fixed_args(host->dev->of_node, ++ "starfive,sysreg", 3, 0, &args); ++ if (ret) { ++ dev_err(host->dev, "Failed to parse starfive,sysreg\n"); ++ return -EINVAL; ++ } ++ ++ priv->reg_syscon = syscon_node_to_regmap(args.np); ++ of_node_put(args.np); ++ if (IS_ERR(priv->reg_syscon)) ++ return PTR_ERR(priv->reg_syscon); ++ ++ priv->syscon_offset = args.args[0]; ++ priv->syscon_shift = args.args[1]; ++ priv->syscon_mask = args.args[2]; ++ ++ host->priv = priv; ++ ++ return 0; ++} ++ ++static const struct dw_mci_drv_data starfive_data = { ++ .common_caps = MMC_CAP_CMD23, ++ .set_ios = dw_mci_starfive_set_ios, ++ .parse_dt = dw_mci_starfive_parse_dt, ++ .execute_tuning = dw_mci_starfive_execute_tuning, ++}; ++ ++static const struct of_device_id dw_mci_starfive_match[] = { ++ { .compatible = "starfive,jh7110-mmc", ++ .data = &starfive_data }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dw_mci_starfive_match); ++ ++static int dw_mci_starfive_probe(struct platform_device *pdev) ++{ ++ return dw_mci_pltfm_register(pdev, &starfive_data); ++} ++ ++static struct platform_driver dw_mci_starfive_driver = { ++ .probe = dw_mci_starfive_probe, ++ .remove = dw_mci_pltfm_remove, ++ .driver = { ++ .name = "dwmmc_starfive", ++ .probe_type = PROBE_PREFER_ASYNCHRONOUS, ++ .of_match_table = dw_mci_starfive_match, ++ }, ++}; ++module_platform_driver(dw_mci_starfive_driver); ++ ++MODULE_DESCRIPTION("StarFive JH7110 Specific DW-MSHC Driver Extension"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:dwmmc_starfive"); diff --git a/target/linux/starfive/patches-6.1/0109-dt-bindings-hwmon-Add-starfive-jh71x0-temp.patch b/target/linux/starfive/patches-6.1/0109-dt-bindings-hwmon-Add-starfive-jh71x0-temp.patch new file mode 100644 index 0000000000..9f6c4128f3 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0109-dt-bindings-hwmon-Add-starfive-jh71x0-temp.patch @@ -0,0 +1,89 @@ +From a0f2b48b5433d2fbcf87e4edf52e5cc26d0c29c8 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Tue, 21 Mar 2023 10:26:43 +0800 +Subject: [PATCH 109/122] dt-bindings: hwmon: Add starfive,jh71x0-temp + +Add bindings for the temperature sensor on the StarFive JH7100 and +JH7110 SoCs. + +Signed-off-by: Emil Renner Berthing +Signed-off-by: Hal Feng +Reviewed-by: Rob Herring +--- + .../bindings/hwmon/starfive,jh71x0-temp.yaml | 70 +++++++++++++++++++ + 1 file changed, 70 insertions(+) + create mode 100644 Documentation/devicetree/bindings/hwmon/starfive,jh71x0-temp.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/starfive,jh71x0-temp.yaml +@@ -0,0 +1,70 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/hwmon/starfive,jh71x0-temp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH71x0 Temperature Sensor ++ ++maintainers: ++ - Emil Renner Berthing ++ ++description: | ++ StarFive Technology Co. JH71x0 embedded temperature sensor ++ ++properties: ++ compatible: ++ enum: ++ - starfive,jh7100-temp ++ - starfive,jh7110-temp ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 2 ++ maxItems: 2 ++ ++ clock-names: ++ items: ++ - const: "sense" ++ - const: "bus" ++ ++ '#thermal-sensor-cells': ++ const: 0 ++ ++ resets: ++ minItems: 2 ++ maxItems: 2 ++ ++ reset-names: ++ items: ++ - const: "sense" ++ - const: "bus" ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - reset-names ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ temperature-sensor@124a0000 { ++ compatible = "starfive,jh7100-temp"; ++ reg = <0x124a0000 0x10000>; ++ clocks = <&clkgen JH7100_CLK_TEMP_SENSE>, ++ <&clkgen JH7100_CLK_TEMP_APB>; ++ clock-names = "sense", "bus"; ++ #thermal-sensor-cells = <0>; ++ resets = <&rstgen JH7100_RSTN_TEMP_SENSE>, ++ <&rstgen JH7100_RSTN_TEMP_APB>; ++ reset-names = "sense", "bus"; ++ }; diff --git a/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch b/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch new file mode 100644 index 0000000000..b52cbd2ba5 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch @@ -0,0 +1,451 @@ +From 3f68f5d0a8c598a09d26a3908cbbff7312b31487 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Tue, 21 Mar 2023 10:26:44 +0800 +Subject: [PATCH 110/122] hwmon: (sfctemp) Add StarFive JH71x0 temperature + sensor + +Add driver for the StarFive JH71x0 temperature sensor. You +can enable/disable it and read temperature in milli Celcius +through sysfs. + +Signed-off-by: Emil Renner Berthing +Co-developed-by: Samin Guo +Signed-off-by: Samin Guo +Signed-off-by: Hal Feng +--- + Documentation/hwmon/index.rst | 1 + + Documentation/hwmon/sfctemp.rst | 33 ++++ + MAINTAINERS | 8 + + drivers/hwmon/Kconfig | 10 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/sfctemp.c | 331 ++++++++++++++++++++++++++++++++ + 6 files changed, 384 insertions(+) + create mode 100644 Documentation/hwmon/sfctemp.rst + create mode 100644 drivers/hwmon/sfctemp.c + +--- a/Documentation/hwmon/index.rst ++++ b/Documentation/hwmon/index.rst +@@ -179,6 +179,7 @@ Hardware Monitoring Kernel Drivers + sch5627 + sch5636 + scpi-hwmon ++ sfctemp + sht15 + sht21 + sht3x +--- /dev/null ++++ b/Documentation/hwmon/sfctemp.rst +@@ -0,0 +1,33 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++Kernel driver sfctemp ++===================== ++ ++Supported chips: ++ - StarFive JH7100 ++ - StarFive JH7110 ++ ++Authors: ++ - Emil Renner Berthing ++ ++Description ++----------- ++ ++This driver adds support for reading the built-in temperature sensor on the ++JH7100 and JH7110 RISC-V SoCs by StarFive Technology Co. Ltd. ++ ++``sysfs`` interface ++------------------- ++ ++The temperature sensor can be enabled, disabled and queried via the standard ++hwmon interface in sysfs under ``/sys/class/hwmon/hwmonX`` for some value of ++``X``: ++ ++================ ==== ============================================= ++Name Perm Description ++================ ==== ============================================= ++temp1_enable RW Enable or disable temperature sensor. ++ Automatically enabled by the driver, ++ but may be disabled to save power. ++temp1_input RO Temperature reading in milli-degrees Celsius. ++================ ==== ============================================= +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18679,6 +18679,14 @@ L: netdev@vger.kernel.org + S: Supported + F: drivers/net/ethernet/sfc/ + ++SFCTEMP HWMON DRIVER ++M: Emil Renner Berthing ++L: linux-hwmon@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/hwmon/starfive,jh71x0-temp.yaml ++F: Documentation/hwmon/sfctemp.rst ++F: drivers/hwmon/sfctemp.c ++ + SFF/SFP/SFP+ MODULE SUPPORT + M: Russell King + L: netdev@vger.kernel.org +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1911,6 +1911,16 @@ config SENSORS_STTS751 + This driver can also be built as a module. If so, the module + will be called stts751. + ++config SENSORS_SFCTEMP ++ tristate "Starfive JH71x0 temperature sensor" ++ depends on ARCH_STARFIVE || COMPILE_TEST ++ help ++ If you say yes here you get support for temperature sensor ++ on the Starfive JH71x0 SoCs. ++ ++ This driver can also be built as a module. If so, the module ++ will be called sfctemp. ++ + config SENSORS_SMM665 + tristate "Summit Microelectronics SMM665" + depends on I2C +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -179,6 +179,7 @@ obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o + obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o + obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o + obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o ++obj-$(CONFIG_SENSORS_SFCTEMP) += sfctemp.o + obj-$(CONFIG_SENSORS_SL28CPLD) += sl28cpld-hwmon.o + obj-$(CONFIG_SENSORS_SHT15) += sht15.o + obj-$(CONFIG_SENSORS_SHT21) += sht21.o +--- /dev/null ++++ b/drivers/hwmon/sfctemp.c +@@ -0,0 +1,331 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2021 Emil Renner Berthing ++ * Copyright (C) 2021 Samin Guo ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * TempSensor reset. The RSTN can be de-asserted once the analog core has ++ * powered up. Trst(min 100ns) ++ * 0:reset 1:de-assert ++ */ ++#define SFCTEMP_RSTN BIT(0) ++ ++/* ++ * TempSensor analog core power down. The analog core will be powered up ++ * Tpu(min 50us) after PD is de-asserted. RSTN should be held low until the ++ * analog core is powered up. ++ * 0:power up 1:power down ++ */ ++#define SFCTEMP_PD BIT(1) ++ ++/* ++ * TempSensor start conversion enable. ++ * 0:disable 1:enable ++ */ ++#define SFCTEMP_RUN BIT(2) ++ ++/* ++ * TempSensor conversion value output. ++ * Temp(C)=DOUT*Y/4094 - K ++ */ ++#define SFCTEMP_DOUT_POS 16 ++#define SFCTEMP_DOUT_MSK GENMASK(27, 16) ++ ++/* DOUT to Celcius conversion constants */ ++#define SFCTEMP_Y1000 237500L ++#define SFCTEMP_Z 4094L ++#define SFCTEMP_K1000 81100L ++ ++struct sfctemp { ++ /* serialize access to hardware register and enabled below */ ++ struct mutex lock; ++ void __iomem *regs; ++ struct clk *clk_sense; ++ struct clk *clk_bus; ++ struct reset_control *rst_sense; ++ struct reset_control *rst_bus; ++ bool enabled; ++}; ++ ++static void sfctemp_power_up(struct sfctemp *sfctemp) ++{ ++ /* make sure we're powered down first */ ++ writel(SFCTEMP_PD, sfctemp->regs); ++ udelay(1); ++ ++ writel(0, sfctemp->regs); ++ /* wait t_pu(50us) + t_rst(100ns) */ ++ usleep_range(60, 200); ++ ++ /* de-assert reset */ ++ writel(SFCTEMP_RSTN, sfctemp->regs); ++ udelay(1); /* wait t_su(500ps) */ ++} ++ ++static void sfctemp_power_down(struct sfctemp *sfctemp) ++{ ++ writel(SFCTEMP_PD, sfctemp->regs); ++} ++ ++static void sfctemp_run(struct sfctemp *sfctemp) ++{ ++ writel(SFCTEMP_RSTN | SFCTEMP_RUN, sfctemp->regs); ++ udelay(1); ++} ++ ++static void sfctemp_stop(struct sfctemp *sfctemp) ++{ ++ writel(SFCTEMP_RSTN, sfctemp->regs); ++} ++ ++static int sfctemp_enable(struct sfctemp *sfctemp) ++{ ++ int ret = 0; ++ ++ mutex_lock(&sfctemp->lock); ++ if (sfctemp->enabled) ++ goto done; ++ ++ ret = clk_prepare_enable(sfctemp->clk_bus); ++ if (ret) ++ goto err; ++ ret = reset_control_deassert(sfctemp->rst_bus); ++ if (ret) ++ goto err_disable_bus; ++ ++ ret = clk_prepare_enable(sfctemp->clk_sense); ++ if (ret) ++ goto err_assert_bus; ++ ret = reset_control_deassert(sfctemp->rst_sense); ++ if (ret) ++ goto err_disable_sense; ++ ++ sfctemp_power_up(sfctemp); ++ sfctemp_run(sfctemp); ++ sfctemp->enabled = true; ++done: ++ mutex_unlock(&sfctemp->lock); ++ return ret; ++ ++err_disable_sense: ++ clk_disable_unprepare(sfctemp->clk_sense); ++err_assert_bus: ++ reset_control_assert(sfctemp->rst_bus); ++err_disable_bus: ++ clk_disable_unprepare(sfctemp->clk_bus); ++err: ++ mutex_unlock(&sfctemp->lock); ++ return ret; ++} ++ ++static int sfctemp_disable(struct sfctemp *sfctemp) ++{ ++ mutex_lock(&sfctemp->lock); ++ if (!sfctemp->enabled) ++ goto done; ++ ++ sfctemp_stop(sfctemp); ++ sfctemp_power_down(sfctemp); ++ reset_control_assert(sfctemp->rst_sense); ++ clk_disable_unprepare(sfctemp->clk_sense); ++ reset_control_assert(sfctemp->rst_bus); ++ clk_disable_unprepare(sfctemp->clk_bus); ++ sfctemp->enabled = false; ++done: ++ mutex_unlock(&sfctemp->lock); ++ return 0; ++} ++ ++static void sfctemp_disable_action(void *data) ++{ ++ sfctemp_disable(data); ++} ++ ++static int sfctemp_convert(struct sfctemp *sfctemp, long *val) ++{ ++ int ret; ++ ++ mutex_lock(&sfctemp->lock); ++ if (!sfctemp->enabled) { ++ ret = -ENODATA; ++ goto out; ++ } ++ ++ /* calculate temperature in milli Celcius */ ++ *val = (long)((readl(sfctemp->regs) & SFCTEMP_DOUT_MSK) >> SFCTEMP_DOUT_POS) ++ * SFCTEMP_Y1000 / SFCTEMP_Z - SFCTEMP_K1000; ++ ++ ret = 0; ++out: ++ mutex_unlock(&sfctemp->lock); ++ return ret; ++} ++ ++static umode_t sfctemp_is_visible(const void *data, enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ switch (type) { ++ case hwmon_temp: ++ switch (attr) { ++ case hwmon_temp_enable: ++ return 0644; ++ case hwmon_temp_input: ++ return 0444; ++ default: ++ return 0; ++ } ++ default: ++ return 0; ++ } ++} ++ ++static int sfctemp_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ struct sfctemp *sfctemp = dev_get_drvdata(dev); ++ ++ switch (type) { ++ case hwmon_temp: ++ switch (attr) { ++ case hwmon_temp_enable: ++ *val = sfctemp->enabled; ++ return 0; ++ case hwmon_temp_input: ++ return sfctemp_convert(sfctemp, val); ++ default: ++ return -EINVAL; ++ } ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int sfctemp_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long val) ++{ ++ struct sfctemp *sfctemp = dev_get_drvdata(dev); ++ ++ switch (type) { ++ case hwmon_temp: ++ switch (attr) { ++ case hwmon_temp_enable: ++ if (val == 0) ++ return sfctemp_disable(sfctemp); ++ if (val == 1) ++ return sfctemp_enable(sfctemp); ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ } ++ default: ++ return -EINVAL; ++ } ++} ++ ++static const struct hwmon_channel_info *sfctemp_info[] = { ++ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), ++ HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT), ++ NULL ++}; ++ ++static const struct hwmon_ops sfctemp_hwmon_ops = { ++ .is_visible = sfctemp_is_visible, ++ .read = sfctemp_read, ++ .write = sfctemp_write, ++}; ++ ++static const struct hwmon_chip_info sfctemp_chip_info = { ++ .ops = &sfctemp_hwmon_ops, ++ .info = sfctemp_info, ++}; ++ ++static int sfctemp_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device *hwmon_dev; ++ struct sfctemp *sfctemp; ++ int ret; ++ ++ sfctemp = devm_kzalloc(dev, sizeof(*sfctemp), GFP_KERNEL); ++ if (!sfctemp) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, sfctemp); ++ mutex_init(&sfctemp->lock); ++ ++ sfctemp->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(sfctemp->regs)) ++ return PTR_ERR(sfctemp->regs); ++ ++ sfctemp->clk_sense = devm_clk_get(dev, "sense"); ++ if (IS_ERR(sfctemp->clk_sense)) ++ return dev_err_probe(dev, PTR_ERR(sfctemp->clk_sense), ++ "error getting sense clock\n"); ++ ++ sfctemp->clk_bus = devm_clk_get(dev, "bus"); ++ if (IS_ERR(sfctemp->clk_bus)) ++ return dev_err_probe(dev, PTR_ERR(sfctemp->clk_bus), ++ "error getting bus clock\n"); ++ ++ sfctemp->rst_sense = devm_reset_control_get_exclusive(dev, "sense"); ++ if (IS_ERR(sfctemp->rst_sense)) ++ return dev_err_probe(dev, PTR_ERR(sfctemp->rst_sense), ++ "error getting sense reset\n"); ++ ++ sfctemp->rst_bus = devm_reset_control_get_exclusive(dev, "bus"); ++ if (IS_ERR(sfctemp->rst_bus)) ++ return dev_err_probe(dev, PTR_ERR(sfctemp->rst_bus), ++ "error getting busreset\n"); ++ ++ ret = reset_control_assert(sfctemp->rst_sense); ++ if (ret) ++ return dev_err_probe(dev, ret, "error asserting sense reset\n"); ++ ++ ret = reset_control_assert(sfctemp->rst_bus); ++ if (ret) ++ return dev_err_probe(dev, ret, "error asserting bus reset\n"); ++ ++ ret = devm_add_action(dev, sfctemp_disable_action, sfctemp); ++ if (ret) ++ return ret; ++ ++ ret = sfctemp_enable(sfctemp); ++ if (ret) ++ return dev_err_probe(dev, ret, "error enabling temperature sensor: %d\n", ret); ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, "sfctemp", sfctemp, ++ &sfctemp_chip_info, NULL); ++ return PTR_ERR_OR_ZERO(hwmon_dev); ++} ++ ++static const struct of_device_id sfctemp_of_match[] = { ++ { .compatible = "starfive,jh7100-temp" }, ++ { .compatible = "starfive,jh7110-temp" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sfctemp_of_match); ++ ++static struct platform_driver sfctemp_driver = { ++ .probe = sfctemp_probe, ++ .driver = { ++ .name = "sfctemp", ++ .of_match_table = sfctemp_of_match, ++ }, ++}; ++module_platform_driver(sfctemp_driver); ++ ++MODULE_AUTHOR("Emil Renner Berthing"); ++MODULE_DESCRIPTION("StarFive JH71x0 temperature sensor driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/starfive/patches-6.1/0111-dt-bindings-dma-snps-dw-axi-dmac-constrain-the-items.patch b/target/linux/starfive/patches-6.1/0111-dt-bindings-dma-snps-dw-axi-dmac-constrain-the-items.patch new file mode 100644 index 0000000000..860c6c0885 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0111-dt-bindings-dma-snps-dw-axi-dmac-constrain-the-items.patch @@ -0,0 +1,62 @@ +From c2f59eeeee68bb66a3db8555474fe94e73b65b02 Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Wed, 22 Mar 2023 17:48:17 +0800 +Subject: [PATCH 111/122] dt-bindings: dma: snps,dw-axi-dmac: constrain the + items of resets for JH7110 dma + +The DMA controller needs two reset items to work properly on JH7110 SoC, +so there is need to constrain the items' value to 2, other platforms +have 1 reset item at most. + +Reviewed-by: Rob Herring +Signed-off-by: Walker Chen +--- + .../bindings/dma/snps,dw-axi-dmac.yaml | 23 ++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml ++++ b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +@@ -21,6 +21,7 @@ properties: + enum: + - snps,axi-dma-1.01a + - intel,kmb-axi-dma ++ - starfive,jh7110-axi-dma + + reg: + minItems: 1 +@@ -59,7 +60,8 @@ properties: + maximum: 8 + + resets: +- maxItems: 1 ++ minItems: 1 ++ maxItems: 2 + + snps,dma-masters: + description: | +@@ -110,6 +112,25 @@ required: + - snps,priority + - snps,block-size + ++if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - starfive,jh7110-axi-dma ++then: ++ properties: ++ resets: ++ minItems: 2 ++ items: ++ - description: AXI reset line ++ - description: AHB reset line ++ - description: module reset ++else: ++ properties: ++ resets: ++ maxItems: 1 ++ + additionalProperties: false + + examples: diff --git a/target/linux/starfive/patches-6.1/0112-dmaengine-dw-axi-dmac-Add-support-for-StarFive-JH711.patch b/target/linux/starfive/patches-6.1/0112-dmaengine-dw-axi-dmac-Add-support-for-StarFive-JH711.patch new file mode 100644 index 0000000000..8b15fc213a --- /dev/null +++ b/target/linux/starfive/patches-6.1/0112-dmaengine-dw-axi-dmac-Add-support-for-StarFive-JH711.patch @@ -0,0 +1,122 @@ +From 69ed990fda6795039a2b5b37d8ad5df785f4d97b Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Wed, 22 Mar 2023 17:48:18 +0800 +Subject: [PATCH 112/122] dmaengine: dw-axi-dmac: Add support for StarFive + JH7110 DMA + +Add DMA reset operation in device probe and use different configuration +on CH_CFG registers according to match data. Update all uses of +of_device_is_compatible with of_device_get_match_data. + +Signed-off-by: Walker Chen +Reviewed-by: Emil Renner Berthing +--- + .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 38 ++++++++++++++++--- + drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 + + 2 files changed, 34 insertions(+), 5 deletions(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -21,10 +21,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + +@@ -46,6 +48,10 @@ + DMA_SLAVE_BUSWIDTH_32_BYTES | \ + DMA_SLAVE_BUSWIDTH_64_BYTES) + ++#define AXI_DMA_FLAG_HAS_APB_REGS BIT(0) ++#define AXI_DMA_FLAG_HAS_RESETS BIT(1) ++#define AXI_DMA_FLAG_USE_CFG2 BIT(2) ++ + static inline void + axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val) + { +@@ -86,7 +92,8 @@ static inline void axi_chan_config_write + + cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | + config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); +- if (chan->chip->dw->hdata->reg_map_8_channels) { ++ if (chan->chip->dw->hdata->reg_map_8_channels && ++ !chan->chip->dw->hdata->use_cfg2) { + cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | + config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | + config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | +@@ -1367,11 +1374,12 @@ static int parse_device_properties(struc + + static int dw_probe(struct platform_device *pdev) + { +- struct device_node *node = pdev->dev.of_node; + struct axi_dma_chip *chip; + struct resource *mem; + struct dw_axi_dma *dw; + struct dw_axi_dma_hcfg *hdata; ++ struct reset_control *resets; ++ unsigned int flags; + u32 i; + int ret; + +@@ -1400,12 +1408,25 @@ static int dw_probe(struct platform_devi + if (IS_ERR(chip->regs)) + return PTR_ERR(chip->regs); + +- if (of_device_is_compatible(node, "intel,kmb-axi-dma")) { ++ flags = (uintptr_t)of_device_get_match_data(&pdev->dev); ++ if (flags & AXI_DMA_FLAG_HAS_APB_REGS) { + chip->apb_regs = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(chip->apb_regs)) + return PTR_ERR(chip->apb_regs); + } + ++ if (flags & AXI_DMA_FLAG_HAS_RESETS) { ++ resets = devm_reset_control_array_get_exclusive(&pdev->dev); ++ if (IS_ERR(resets)) ++ return PTR_ERR(resets); ++ ++ ret = reset_control_deassert(resets); ++ if (ret) ++ return ret; ++ } ++ ++ chip->dw->hdata->use_cfg2 = !!(flags & AXI_DMA_FLAG_USE_CFG2); ++ + chip->core_clk = devm_clk_get(chip->dev, "core-clk"); + if (IS_ERR(chip->core_clk)) + return PTR_ERR(chip->core_clk); +@@ -1556,8 +1577,15 @@ static const struct dev_pm_ops dw_axi_dm + }; + + static const struct of_device_id dw_dma_of_id_table[] = { +- { .compatible = "snps,axi-dma-1.01a" }, +- { .compatible = "intel,kmb-axi-dma" }, ++ { ++ .compatible = "snps,axi-dma-1.01a" ++ }, { ++ .compatible = "intel,kmb-axi-dma", ++ .data = (void *)AXI_DMA_FLAG_HAS_APB_REGS, ++ }, { ++ .compatible = "starfive,jh7110-axi-dma", ++ .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2), ++ }, + {} + }; + MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +@@ -33,6 +33,7 @@ struct dw_axi_dma_hcfg { + /* Register map for DMAX_NUM_CHANNELS <= 8 */ + bool reg_map_8_channels; + bool restrict_axi_burst_len; ++ bool use_cfg2; + }; + + struct axi_dma_chan { diff --git a/target/linux/starfive/patches-6.1/0113-dmaengine-dw-axi-dmac-Increase-polling-time-to-DMA-t.patch b/target/linux/starfive/patches-6.1/0113-dmaengine-dw-axi-dmac-Increase-polling-time-to-DMA-t.patch new file mode 100644 index 0000000000..903efb43c1 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0113-dmaengine-dw-axi-dmac-Increase-polling-time-to-DMA-t.patch @@ -0,0 +1,29 @@ +From 92c2dc96af79b2f181cc97157ce3ef2be5b48f4c Mon Sep 17 00:00:00 2001 +From: Walker Chen +Date: Wed, 22 Mar 2023 17:48:19 +0800 +Subject: [PATCH 113/122] dmaengine: dw-axi-dmac: Increase polling time to DMA + transmission completion status + +The bit DMAC_CHEN[0] is automatically cleared by hardware to disable the +channel after the last AMBA transfer of the DMA transfer to the +destination has completed. Software can therefore poll this bit to +determine when this channel is free for a new DMA transfer. +This time requires at least 40 milliseconds on JH7110 SoC, otherwise an +error message 'failed to stop' will be reported. + +Signed-off-by: Walker Chen +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -1147,7 +1147,7 @@ static int dma_chan_terminate_all(struct + axi_chan_disable(chan); + + ret = readl_poll_timeout_atomic(chan->chip->regs + DMAC_CHEN, val, +- !(val & chan_active), 1000, 10000); ++ !(val & chan_active), 1000, 50000); + if (ret == -ETIMEDOUT) + dev_warn(dchan2dev(dchan), + "%s failed to stop\n", axi_chan_name(chan)); diff --git a/target/linux/starfive/patches-6.1/0114-RISC-V-Change-suspend_save_csrs-and-suspend_restore_.patch b/target/linux/starfive/patches-6.1/0114-RISC-V-Change-suspend_save_csrs-and-suspend_restore_.patch new file mode 100644 index 0000000000..6c4745462a --- /dev/null +++ b/target/linux/starfive/patches-6.1/0114-RISC-V-Change-suspend_save_csrs-and-suspend_restore_.patch @@ -0,0 +1,50 @@ +From ba1b6ccbf68183b0d9e633ef930c7974144c7b56 Mon Sep 17 00:00:00 2001 +From: Sia Jee Heng +Date: Thu, 30 Mar 2023 14:43:18 +0800 +Subject: [PATCH 114/122] RISC-V: Change suspend_save_csrs and + suspend_restore_csrs to public function + +Currently suspend_save_csrs() and suspend_restore_csrs() functions are +statically defined in the suspend.c. Change the function's attribute +to public so that the functions can be used by hibernation as well. + +Signed-off-by: Sia Jee Heng +Reviewed-by: Ley Foon Tan +Reviewed-by: Mason Huo +Reviewed-by: Conor Dooley +Reviewed-by: Andrew Jones +--- + arch/riscv/include/asm/suspend.h | 3 +++ + arch/riscv/kernel/suspend.c | 4 ++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/arch/riscv/include/asm/suspend.h ++++ b/arch/riscv/include/asm/suspend.h +@@ -33,4 +33,7 @@ int cpu_suspend(unsigned long arg, + /* Low-level CPU resume entry function */ + int __cpu_resume_enter(unsigned long hartid, unsigned long context); + ++/* Used to save and restore the CSRs */ ++void suspend_save_csrs(struct suspend_context *context); ++void suspend_restore_csrs(struct suspend_context *context); + #endif +--- a/arch/riscv/kernel/suspend.c ++++ b/arch/riscv/kernel/suspend.c +@@ -8,7 +8,7 @@ + #include + #include + +-static void suspend_save_csrs(struct suspend_context *context) ++void suspend_save_csrs(struct suspend_context *context) + { + context->scratch = csr_read(CSR_SCRATCH); + context->tvec = csr_read(CSR_TVEC); +@@ -29,7 +29,7 @@ static void suspend_save_csrs(struct sus + #endif + } + +-static void suspend_restore_csrs(struct suspend_context *context) ++void suspend_restore_csrs(struct suspend_context *context) + { + csr_write(CSR_SCRATCH, context->scratch); + csr_write(CSR_TVEC, context->tvec); diff --git a/target/linux/starfive/patches-6.1/0115-RISC-V-Factor-out-common-code-of-__cpu_resume_enter.patch b/target/linux/starfive/patches-6.1/0115-RISC-V-Factor-out-common-code-of-__cpu_resume_enter.patch new file mode 100644 index 0000000000..ccdb77b05c --- /dev/null +++ b/target/linux/starfive/patches-6.1/0115-RISC-V-Factor-out-common-code-of-__cpu_resume_enter.patch @@ -0,0 +1,136 @@ +From f0e2b8f9bb240d7391d3eeca55534160fd385ea8 Mon Sep 17 00:00:00 2001 +From: Sia Jee Heng +Date: Thu, 30 Mar 2023 14:43:19 +0800 +Subject: [PATCH 115/122] RISC-V: Factor out common code of + __cpu_resume_enter() + +The cpu_resume() function is very similar for the suspend to disk and +suspend to ram cases. Factor out the common code into suspend_restore_csrs +macro and suspend_restore_regs macro. + +Signed-off-by: Sia Jee Heng +Reviewed-by: Andrew Jones +Reviewed-by: Conor Dooley +--- + arch/riscv/include/asm/assembler.h | 62 ++++++++++++++++++++++++++++++ + arch/riscv/kernel/suspend_entry.S | 34 ++-------------- + 2 files changed, 65 insertions(+), 31 deletions(-) + create mode 100644 arch/riscv/include/asm/assembler.h + +--- /dev/null ++++ b/arch/riscv/include/asm/assembler.h +@@ -0,0 +1,62 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * Author: Jee Heng Sia ++ */ ++ ++#ifndef __ASSEMBLY__ ++#error "Only include this from assembly code" ++#endif ++ ++#ifndef __ASM_ASSEMBLER_H ++#define __ASM_ASSEMBLER_H ++ ++#include ++#include ++#include ++ ++/* ++ * suspend_restore_csrs - restore CSRs ++ */ ++ .macro suspend_restore_csrs ++ REG_L t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0) ++ csrw CSR_EPC, t0 ++ REG_L t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0) ++ csrw CSR_STATUS, t0 ++ REG_L t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0) ++ csrw CSR_TVAL, t0 ++ REG_L t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0) ++ csrw CSR_CAUSE, t0 ++ .endm ++ ++/* ++ * suspend_restore_regs - Restore registers (except A0 and T0-T6) ++ */ ++ .macro suspend_restore_regs ++ REG_L ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0) ++ REG_L sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0) ++ REG_L gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0) ++ REG_L tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0) ++ REG_L s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0) ++ REG_L s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0) ++ REG_L a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0) ++ REG_L a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0) ++ REG_L a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0) ++ REG_L a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0) ++ REG_L a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0) ++ REG_L a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0) ++ REG_L a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0) ++ REG_L s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0) ++ REG_L s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0) ++ REG_L s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0) ++ REG_L s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0) ++ REG_L s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0) ++ REG_L s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0) ++ REG_L s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0) ++ REG_L s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0) ++ REG_L s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0) ++ REG_L s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0) ++ .endm ++ ++#endif /* __ASM_ASSEMBLER_H */ +--- a/arch/riscv/kernel/suspend_entry.S ++++ b/arch/riscv/kernel/suspend_entry.S +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -83,39 +84,10 @@ ENTRY(__cpu_resume_enter) + add a0, a1, zero + + /* Restore CSRs */ +- REG_L t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0) +- csrw CSR_EPC, t0 +- REG_L t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0) +- csrw CSR_STATUS, t0 +- REG_L t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0) +- csrw CSR_TVAL, t0 +- REG_L t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0) +- csrw CSR_CAUSE, t0 ++ suspend_restore_csrs + + /* Restore registers (except A0 and T0-T6) */ +- REG_L ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0) +- REG_L sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0) +- REG_L gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0) +- REG_L tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0) +- REG_L s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0) +- REG_L s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0) +- REG_L a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0) +- REG_L a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0) +- REG_L a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0) +- REG_L a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0) +- REG_L a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0) +- REG_L a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0) +- REG_L a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0) +- REG_L s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0) +- REG_L s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0) +- REG_L s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0) +- REG_L s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0) +- REG_L s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0) +- REG_L s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0) +- REG_L s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0) +- REG_L s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0) +- REG_L s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0) +- REG_L s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0) ++ suspend_restore_regs + + /* Return zero value */ + add a0, zero, zero diff --git a/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch b/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch new file mode 100644 index 0000000000..eae0559d9c --- /dev/null +++ b/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch @@ -0,0 +1,673 @@ +From 06f1d699e923c3f09869439cdb603e36302c2611 Mon Sep 17 00:00:00 2001 +From: Sia Jee Heng +Date: Thu, 30 Mar 2023 14:43:21 +0800 +Subject: [PATCH 116/122] RISC-V: Add arch functions to support + hibernation/suspend-to-disk + +Low level Arch functions were created to support hibernation. +swsusp_arch_suspend() relies code from __cpu_suspend_enter() to write +cpu state onto the stack, then calling swsusp_save() to save the memory +image. + +Arch specific hibernation header is implemented and is utilized by the +arch_hibernation_header_restore() and arch_hibernation_header_save() +functions. The arch specific hibernation header consists of satp, hartid, +and the cpu_resume address. The kernel built version is also need to be +saved into the hibernation image header to making sure only the same +kernel is restore when resume. + +swsusp_arch_resume() creates a temporary page table that covering only +the linear map. It copies the restore code to a 'safe' page, then start +to restore the memory image. Once completed, it restores the original +kernel's page table. It then calls into __hibernate_cpu_resume() +to restore the CPU context. Finally, it follows the normal hibernation +path back to the hibernation core. + +To enable hibernation/suspend to disk into RISCV, the below config +need to be enabled: +- CONFIG_HIBERNATION +- CONFIG_ARCH_HIBERNATION_HEADER +- CONFIG_ARCH_HIBERNATION_POSSIBLE + +Signed-off-by: Sia Jee Heng +Reviewed-by: Ley Foon Tan +Reviewed-by: Mason Huo +Reviewed-by: Conor Dooley +Reviewed-by: Andrew Jones +--- + arch/riscv/Kconfig | 8 +- + arch/riscv/include/asm/assembler.h | 20 ++ + arch/riscv/include/asm/suspend.h | 19 ++ + arch/riscv/kernel/Makefile | 1 + + arch/riscv/kernel/asm-offsets.c | 5 + + arch/riscv/kernel/hibernate-asm.S | 77 ++++++ + arch/riscv/kernel/hibernate.c | 427 +++++++++++++++++++++++++++++ + 7 files changed, 556 insertions(+), 1 deletion(-) + create mode 100644 arch/riscv/kernel/hibernate-asm.S + create mode 100644 arch/riscv/kernel/hibernate.c + +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -52,7 +52,7 @@ config RISCV + select CLONE_BACKWARDS + select CLINT_TIMER if !MMU + select COMMON_CLK +- select CPU_PM if CPU_IDLE ++ select CPU_PM if CPU_IDLE || HIBERNATION + select EDAC_SUPPORT + select GENERIC_ARCH_TOPOLOGY + select GENERIC_ATOMIC64 if !64BIT +@@ -715,6 +715,12 @@ menu "Power management options" + + source "kernel/power/Kconfig" + ++config ARCH_HIBERNATION_POSSIBLE ++ def_bool y ++ ++config ARCH_HIBERNATION_HEADER ++ def_bool HIBERNATION ++ + endmenu # "Power management options" + + menu "CPU Power Management" +--- a/arch/riscv/include/asm/assembler.h ++++ b/arch/riscv/include/asm/assembler.h +@@ -59,4 +59,24 @@ + REG_L s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0) + .endm + ++/* ++ * copy_page - copy 1 page (4KB) of data from source to destination ++ * @a0 - destination ++ * @a1 - source ++ */ ++ .macro copy_page a0, a1 ++ lui a2, 0x1 ++ add a2, a2, a0 ++1 : ++ REG_L t0, 0(a1) ++ REG_L t1, SZREG(a1) ++ ++ REG_S t0, 0(a0) ++ REG_S t1, SZREG(a0) ++ ++ addi a0, a0, 2 * SZREG ++ addi a1, a1, 2 * SZREG ++ bne a2, a0, 1b ++ .endm ++ + #endif /* __ASM_ASSEMBLER_H */ +--- a/arch/riscv/include/asm/suspend.h ++++ b/arch/riscv/include/asm/suspend.h +@@ -21,6 +21,11 @@ struct suspend_context { + #endif + }; + ++/* ++ * Used by hibernation core and cleared during resume sequence ++ */ ++extern int in_suspend; ++ + /* Low-level CPU suspend entry function */ + int __cpu_suspend_enter(struct suspend_context *context); + +@@ -36,4 +41,18 @@ int __cpu_resume_enter(unsigned long har + /* Used to save and restore the CSRs */ + void suspend_save_csrs(struct suspend_context *context); + void suspend_restore_csrs(struct suspend_context *context); ++ ++/* Low-level API to support hibernation */ ++int swsusp_arch_suspend(void); ++int swsusp_arch_resume(void); ++int arch_hibernation_header_save(void *addr, unsigned int max_size); ++int arch_hibernation_header_restore(void *addr); ++int __hibernate_cpu_resume(void); ++ ++/* Used to resume on the CPU we hibernated on */ ++int hibernate_resume_nonboot_cpu_disable(void); ++ ++asmlinkage void hibernate_restore_image(unsigned long resume_satp, unsigned long satp_temp, ++ unsigned long cpu_resume); ++asmlinkage int hibernate_core_restore_code(void); + #endif +--- a/arch/riscv/kernel/Makefile ++++ b/arch/riscv/kernel/Makefile +@@ -65,6 +65,7 @@ obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o + + obj-$(CONFIG_CPU_PM) += suspend_entry.o suspend.o ++obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o + + obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o + obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o +--- a/arch/riscv/kernel/asm-offsets.c ++++ b/arch/riscv/kernel/asm-offsets.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -116,6 +117,10 @@ void asm_offsets(void) + + OFFSET(SUSPEND_CONTEXT_REGS, suspend_context, regs); + ++ OFFSET(HIBERN_PBE_ADDR, pbe, address); ++ OFFSET(HIBERN_PBE_ORIG, pbe, orig_address); ++ OFFSET(HIBERN_PBE_NEXT, pbe, next); ++ + OFFSET(KVM_ARCH_GUEST_ZERO, kvm_vcpu_arch, guest_context.zero); + OFFSET(KVM_ARCH_GUEST_RA, kvm_vcpu_arch, guest_context.ra); + OFFSET(KVM_ARCH_GUEST_SP, kvm_vcpu_arch, guest_context.sp); +--- /dev/null ++++ b/arch/riscv/kernel/hibernate-asm.S +@@ -0,0 +1,77 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Hibernation low level support for RISCV. ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * Author: Jee Heng Sia ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* ++ * int __hibernate_cpu_resume(void) ++ * Switch back to the hibernated image's page table prior to restoring the CPU ++ * context. ++ * ++ * Always returns 0 ++ */ ++ENTRY(__hibernate_cpu_resume) ++ /* switch to hibernated image's page table. */ ++ csrw CSR_SATP, s0 ++ sfence.vma ++ ++ REG_L a0, hibernate_cpu_context ++ ++ suspend_restore_csrs ++ suspend_restore_regs ++ ++ /* Return zero value. */ ++ mv a0, zero ++ ++ ret ++END(__hibernate_cpu_resume) ++ ++/* ++ * Prepare to restore the image. ++ * a0: satp of saved page tables. ++ * a1: satp of temporary page tables. ++ * a2: cpu_resume. ++ */ ++ENTRY(hibernate_restore_image) ++ mv s0, a0 ++ mv s1, a1 ++ mv s2, a2 ++ REG_L s4, restore_pblist ++ REG_L a1, relocated_restore_code ++ ++ jalr a1 ++END(hibernate_restore_image) ++ ++/* ++ * The below code will be executed from a 'safe' page. ++ * It first switches to the temporary page table, then starts to copy the pages ++ * back to the original memory location. Finally, it jumps to __hibernate_cpu_resume() ++ * to restore the CPU context. ++ */ ++ENTRY(hibernate_core_restore_code) ++ /* switch to temp page table. */ ++ csrw satp, s1 ++ sfence.vma ++.Lcopy: ++ /* The below code will restore the hibernated image. */ ++ REG_L a1, HIBERN_PBE_ADDR(s4) ++ REG_L a0, HIBERN_PBE_ORIG(s4) ++ ++ copy_page a0, a1 ++ ++ REG_L s4, HIBERN_PBE_NEXT(s4) ++ bnez s4, .Lcopy ++ ++ jalr s2 ++END(hibernate_core_restore_code) +--- /dev/null ++++ b/arch/riscv/kernel/hibernate.c +@@ -0,0 +1,427 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Hibernation support for RISCV ++ * ++ * Copyright (C) 2023 StarFive Technology Co., Ltd. ++ * ++ * Author: Jee Heng Sia ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* The logical cpu number we should resume on, initialised to a non-cpu number. */ ++static int sleep_cpu = -EINVAL; ++ ++/* Pointer to the temporary resume page table. */ ++static pgd_t *resume_pg_dir; ++ ++/* CPU context to be saved. */ ++struct suspend_context *hibernate_cpu_context; ++EXPORT_SYMBOL_GPL(hibernate_cpu_context); ++ ++unsigned long relocated_restore_code; ++EXPORT_SYMBOL_GPL(relocated_restore_code); ++ ++/** ++ * struct arch_hibernate_hdr_invariants - container to store kernel build version. ++ * @uts_version: to save the build number and date so that we do not resume with ++ * a different kernel. ++ */ ++struct arch_hibernate_hdr_invariants { ++ char uts_version[__NEW_UTS_LEN + 1]; ++}; ++ ++/** ++ * struct arch_hibernate_hdr - helper parameters that help us to restore the image. ++ * @invariants: container to store kernel build version. ++ * @hartid: to make sure same boot_cpu executes the hibernate/restore code. ++ * @saved_satp: original page table used by the hibernated image. ++ * @restore_cpu_addr: the kernel's image address to restore the CPU context. ++ */ ++static struct arch_hibernate_hdr { ++ struct arch_hibernate_hdr_invariants invariants; ++ unsigned long hartid; ++ unsigned long saved_satp; ++ unsigned long restore_cpu_addr; ++} resume_hdr; ++ ++static void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i) ++{ ++ memset(i, 0, sizeof(*i)); ++ memcpy(i->uts_version, init_utsname()->version, sizeof(i->uts_version)); ++} ++ ++/* ++ * Check if the given pfn is in the 'nosave' section. ++ */ ++int pfn_is_nosave(unsigned long pfn) ++{ ++ unsigned long nosave_begin_pfn = sym_to_pfn(&__nosave_begin); ++ unsigned long nosave_end_pfn = sym_to_pfn(&__nosave_end - 1); ++ ++ return ((pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn)); ++} ++ ++void notrace save_processor_state(void) ++{ ++ WARN_ON(num_online_cpus() != 1); ++} ++ ++void notrace restore_processor_state(void) ++{ ++} ++ ++/* ++ * Helper parameters need to be saved to the hibernation image header. ++ */ ++int arch_hibernation_header_save(void *addr, unsigned int max_size) ++{ ++ struct arch_hibernate_hdr *hdr = addr; ++ ++ if (max_size < sizeof(*hdr)) ++ return -EOVERFLOW; ++ ++ arch_hdr_invariants(&hdr->invariants); ++ ++ hdr->hartid = cpuid_to_hartid_map(sleep_cpu); ++ hdr->saved_satp = csr_read(CSR_SATP); ++ hdr->restore_cpu_addr = (unsigned long)__hibernate_cpu_resume; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(arch_hibernation_header_save); ++ ++/* ++ * Retrieve the helper parameters from the hibernation image header. ++ */ ++int arch_hibernation_header_restore(void *addr) ++{ ++ struct arch_hibernate_hdr_invariants invariants; ++ struct arch_hibernate_hdr *hdr = addr; ++ int ret = 0; ++ ++ arch_hdr_invariants(&invariants); ++ ++ if (memcmp(&hdr->invariants, &invariants, sizeof(invariants))) { ++ pr_crit("Hibernate image not generated by this kernel!\n"); ++ return -EINVAL; ++ } ++ ++ sleep_cpu = riscv_hartid_to_cpuid(hdr->hartid); ++ if (sleep_cpu < 0) { ++ pr_crit("Hibernated on a CPU not known to this kernel!\n"); ++ sleep_cpu = -EINVAL; ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_SMP ++ ret = bringup_hibernate_cpu(sleep_cpu); ++ if (ret) { ++ sleep_cpu = -EINVAL; ++ return ret; ++ } ++#endif ++ resume_hdr = *hdr; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(arch_hibernation_header_restore); ++ ++int swsusp_arch_suspend(void) ++{ ++ int ret = 0; ++ ++ if (__cpu_suspend_enter(hibernate_cpu_context)) { ++ sleep_cpu = smp_processor_id(); ++ suspend_save_csrs(hibernate_cpu_context); ++ ret = swsusp_save(); ++ } else { ++ suspend_restore_csrs(hibernate_cpu_context); ++ flush_tlb_all(); ++ flush_icache_all(); ++ ++ /* ++ * Tell the hibernation core that we've just restored the memory. ++ */ ++ in_suspend = 0; ++ sleep_cpu = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int temp_pgtable_map_pte(pmd_t *dst_pmdp, pmd_t *src_pmdp, unsigned long start, ++ unsigned long end, pgprot_t prot) ++{ ++ pte_t *src_ptep; ++ pte_t *dst_ptep; ++ ++ if (pmd_none(READ_ONCE(*dst_pmdp))) { ++ dst_ptep = (pte_t *)get_safe_page(GFP_ATOMIC); ++ if (!dst_ptep) ++ return -ENOMEM; ++ ++ pmd_populate_kernel(NULL, dst_pmdp, dst_ptep); ++ } ++ ++ dst_ptep = pte_offset_kernel(dst_pmdp, start); ++ src_ptep = pte_offset_kernel(src_pmdp, start); ++ ++ do { ++ pte_t pte = READ_ONCE(*src_ptep); ++ ++ if (pte_present(pte)) ++ set_pte(dst_ptep, __pte(pte_val(pte) | pgprot_val(prot))); ++ } while (dst_ptep++, src_ptep++, start += PAGE_SIZE, start < end); ++ ++ return 0; ++} ++ ++static int temp_pgtable_map_pmd(pud_t *dst_pudp, pud_t *src_pudp, unsigned long start, ++ unsigned long end, pgprot_t prot) ++{ ++ unsigned long next; ++ unsigned long ret; ++ pmd_t *src_pmdp; ++ pmd_t *dst_pmdp; ++ ++ if (pud_none(READ_ONCE(*dst_pudp))) { ++ dst_pmdp = (pmd_t *)get_safe_page(GFP_ATOMIC); ++ if (!dst_pmdp) ++ return -ENOMEM; ++ ++ pud_populate(NULL, dst_pudp, dst_pmdp); ++ } ++ ++ dst_pmdp = pmd_offset(dst_pudp, start); ++ src_pmdp = pmd_offset(src_pudp, start); ++ ++ do { ++ pmd_t pmd = READ_ONCE(*src_pmdp); ++ ++ next = pmd_addr_end(start, end); ++ ++ if (pmd_none(pmd)) ++ continue; ++ ++ if (pmd_leaf(pmd)) { ++ set_pmd(dst_pmdp, __pmd(pmd_val(pmd) | pgprot_val(prot))); ++ } else { ++ ret = temp_pgtable_map_pte(dst_pmdp, src_pmdp, start, next, prot); ++ if (ret) ++ return -ENOMEM; ++ } ++ } while (dst_pmdp++, src_pmdp++, start = next, start != end); ++ ++ return 0; ++} ++ ++static int temp_pgtable_map_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start, ++ unsigned long end, pgprot_t prot) ++{ ++ unsigned long next; ++ unsigned long ret; ++ pud_t *dst_pudp; ++ pud_t *src_pudp; ++ ++ if (p4d_none(READ_ONCE(*dst_p4dp))) { ++ dst_pudp = (pud_t *)get_safe_page(GFP_ATOMIC); ++ if (!dst_pudp) ++ return -ENOMEM; ++ ++ p4d_populate(NULL, dst_p4dp, dst_pudp); ++ } ++ ++ dst_pudp = pud_offset(dst_p4dp, start); ++ src_pudp = pud_offset(src_p4dp, start); ++ ++ do { ++ pud_t pud = READ_ONCE(*src_pudp); ++ ++ next = pud_addr_end(start, end); ++ ++ if (pud_none(pud)) ++ continue; ++ ++ if (pud_leaf(pud)) { ++ set_pud(dst_pudp, __pud(pud_val(pud) | pgprot_val(prot))); ++ } else { ++ ret = temp_pgtable_map_pmd(dst_pudp, src_pudp, start, next, prot); ++ if (ret) ++ return -ENOMEM; ++ } ++ } while (dst_pudp++, src_pudp++, start = next, start != end); ++ ++ return 0; ++} ++ ++static int temp_pgtable_map_p4d(pgd_t *dst_pgdp, pgd_t *src_pgdp, unsigned long start, ++ unsigned long end, pgprot_t prot) ++{ ++ unsigned long next; ++ unsigned long ret; ++ p4d_t *dst_p4dp; ++ p4d_t *src_p4dp; ++ ++ if (pgd_none(READ_ONCE(*dst_pgdp))) { ++ dst_p4dp = (p4d_t *)get_safe_page(GFP_ATOMIC); ++ if (!dst_p4dp) ++ return -ENOMEM; ++ ++ pgd_populate(NULL, dst_pgdp, dst_p4dp); ++ } ++ ++ dst_p4dp = p4d_offset(dst_pgdp, start); ++ src_p4dp = p4d_offset(src_pgdp, start); ++ ++ do { ++ p4d_t p4d = READ_ONCE(*src_p4dp); ++ ++ next = p4d_addr_end(start, end); ++ ++ if (p4d_none(p4d)) ++ continue; ++ ++ if (p4d_leaf(p4d)) { ++ set_p4d(dst_p4dp, __p4d(p4d_val(p4d) | pgprot_val(prot))); ++ } else { ++ ret = temp_pgtable_map_pud(dst_p4dp, src_p4dp, start, next, prot); ++ if (ret) ++ return -ENOMEM; ++ } ++ } while (dst_p4dp++, src_p4dp++, start = next, start != end); ++ ++ return 0; ++} ++ ++static int temp_pgtable_mapping(pgd_t *pgdp, unsigned long start, unsigned long end, pgprot_t prot) ++{ ++ pgd_t *dst_pgdp = pgd_offset_pgd(pgdp, start); ++ pgd_t *src_pgdp = pgd_offset_k(start); ++ unsigned long next; ++ unsigned long ret; ++ ++ do { ++ pgd_t pgd = READ_ONCE(*src_pgdp); ++ ++ next = pgd_addr_end(start, end); ++ ++ if (pgd_none(pgd)) ++ continue; ++ ++ if (pgd_leaf(pgd)) { ++ set_pgd(dst_pgdp, __pgd(pgd_val(pgd) | pgprot_val(prot))); ++ } else { ++ ret = temp_pgtable_map_p4d(dst_pgdp, src_pgdp, start, next, prot); ++ if (ret) ++ return -ENOMEM; ++ } ++ } while (dst_pgdp++, src_pgdp++, start = next, start != end); ++ ++ return 0; ++} ++ ++static unsigned long relocate_restore_code(void) ++{ ++ void *page = (void *)get_safe_page(GFP_ATOMIC); ++ ++ if (!page) ++ return -ENOMEM; ++ ++ copy_page(page, hibernate_core_restore_code); ++ ++ /* Make the page containing the relocated code executable. */ ++ set_memory_x((unsigned long)page, 1); ++ ++ return (unsigned long)page; ++} ++ ++int swsusp_arch_resume(void) ++{ ++ unsigned long end = (unsigned long)pfn_to_virt(max_low_pfn); ++ unsigned long start = PAGE_OFFSET; ++ int ret; ++ ++ /* ++ * Memory allocated by get_safe_page() will be dealt with by the hibernation core, ++ * we don't need to free it here. ++ */ ++ resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC); ++ if (!resume_pg_dir) ++ return -ENOMEM; ++ ++ /* ++ * Create a temporary page table and map the whole linear region as executable and ++ * writable. ++ */ ++ ret = temp_pgtable_mapping(resume_pg_dir, start, end, __pgprot(_PAGE_WRITE | _PAGE_EXEC)); ++ if (ret) ++ return ret; ++ ++ /* Move the restore code to a new page so that it doesn't get overwritten by itself. */ ++ relocated_restore_code = relocate_restore_code(); ++ if (relocated_restore_code == -ENOMEM) ++ return -ENOMEM; ++ ++ /* ++ * Map the __hibernate_cpu_resume() address to the temporary page table so that the ++ * restore code can jumps to it after finished restore the image. The next execution ++ * code doesn't find itself in a different address space after switching over to the ++ * original page table used by the hibernated image. ++ * The __hibernate_cpu_resume() mapping is unnecessary for RV32 since the kernel and ++ * linear addresses are identical, but different for RV64. To ensure consistency, we ++ * map it for both RV32 and RV64 kernels. ++ * Additionally, we should ensure that the page is writable before restoring the image. ++ */ ++ start = (unsigned long)resume_hdr.restore_cpu_addr; ++ end = start + PAGE_SIZE; ++ ++ ret = temp_pgtable_mapping(resume_pg_dir, start, end, __pgprot(_PAGE_WRITE)); ++ if (ret) ++ return ret; ++ ++ hibernate_restore_image(resume_hdr.saved_satp, (PFN_DOWN(__pa(resume_pg_dir)) | satp_mode), ++ resume_hdr.restore_cpu_addr); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP_SMP ++int hibernate_resume_nonboot_cpu_disable(void) ++{ ++ if (sleep_cpu < 0) { ++ pr_err("Failing to resume from hibernate on an unknown CPU\n"); ++ return -ENODEV; ++ } ++ ++ return freeze_secondary_cpus(sleep_cpu); ++} ++#endif ++ ++static int __init riscv_hibernate_init(void) ++{ ++ hibernate_cpu_context = kzalloc(sizeof(*hibernate_cpu_context), GFP_KERNEL); ++ ++ if (WARN_ON(!hibernate_cpu_context)) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++early_initcall(riscv_hibernate_init); diff --git a/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch b/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch new file mode 100644 index 0000000000..18ad298065 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch @@ -0,0 +1,1014 @@ +From e62161318f2fe3e396fc31c50d210e99bec83021 Mon Sep 17 00:00:00 2001 +From: "ziv.xu" +Date: Fri, 4 Aug 2023 13:53:10 +0800 +Subject: [PATCH 117/122] driver: mfd: axp20x: Add support for AXP15060 + +axp20x add support for AXP15060 + +Signed-off-by: ziv.xu +--- + drivers/mfd/axp20x-i2c.c | 2 + + drivers/mfd/axp20x.c | 373 ++++++++++++++++++++++++++++++++++--- + include/linux/mfd/axp20x.h | 218 +++++++++++++++++++++- + 3 files changed, 557 insertions(+), 36 deletions(-) + +--- a/drivers/mfd/axp20x-i2c.c ++++ b/drivers/mfd/axp20x-i2c.c +@@ -66,6 +66,7 @@ static const struct of_device_id axp20x_ + { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, + { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, ++ { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, + { }, + }; + MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); +@@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x + { "axp223", 0 }, + { "axp803", 0 }, + { "axp806", 0 }, ++ { "axp15060", 0 }, + { }, + }; + MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -23,7 +23,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +@@ -34,15 +34,18 @@ + + static const char * const axp20x_model_names[] = { + "AXP152", ++ "AXP192", + "AXP202", + "AXP209", + "AXP221", + "AXP223", + "AXP288", ++ "AXP313a", + "AXP803", + "AXP806", + "AXP809", + "AXP813", ++ "AXP15060", + }; + + static const struct regmap_range axp152_writeable_ranges[] = { +@@ -92,6 +95,35 @@ static const struct regmap_access_table + .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), + }; + ++static const struct regmap_range axp192_writeable_ranges[] = { ++ regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)), ++ regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE), ++ regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL), ++ regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL), ++}; ++ ++static const struct regmap_range axp192_volatile_ranges[] = { ++ regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS), ++ regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE), ++ regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE), ++ regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), ++ regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), ++ regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE), ++ regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE), ++ regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL), ++ regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL), ++}; ++ ++static const struct regmap_access_table axp192_writeable_table = { ++ .yes_ranges = axp192_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp192_volatile_table = { ++ .yes_ranges = axp192_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges), ++}; ++ + /* AXP22x ranges are shared with the AXP809, as they cover the same range */ + static const struct regmap_range axp22x_writeable_ranges[] = { + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), +@@ -119,6 +151,7 @@ static const struct regmap_access_table + + /* AXP288 ranges are shared with the AXP803, as they cover the same range */ + static const struct regmap_range axp288_writeable_ranges[] = { ++ regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), + regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), + }; +@@ -154,6 +187,25 @@ static const struct regmap_range axp806_ + regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), + }; + ++static const struct regmap_range axp313a_writeable_ranges[] = { ++ regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE), ++}; ++ ++static const struct regmap_range axp313a_volatile_ranges[] = { ++ regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL), ++ regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE), ++}; ++ ++static const struct regmap_access_table axp313a_writeable_table = { ++ .yes_ranges = axp313a_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp313a_volatile_table = { ++ .yes_ranges = axp313a_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), ++}; ++ + static const struct regmap_range axp806_volatile_ranges[] = { + regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), + }; +@@ -168,11 +220,49 @@ static const struct regmap_access_table + .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), + }; + ++static const struct regmap_range axp15060_writeable_ranges[] = { ++ regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), ++ regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), ++ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), ++ regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), ++ regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), ++ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), ++}; ++ ++static const struct regmap_range axp15060_volatile_ranges[] = { ++ regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), ++ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), ++ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), ++}; ++ ++static const struct regmap_access_table axp15060_writeable_table = { ++ .yes_ranges = axp15060_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp15060_volatile_table = { ++ .yes_ranges = axp15060_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges), ++}; ++ + static const struct resource axp152_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), + }; + ++static const struct resource axp192_ac_power_supply_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), ++}; ++ ++static const struct resource axp192_usb_power_supply_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), ++}; ++ + static const struct resource axp20x_ac_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), +@@ -221,6 +311,11 @@ static const struct resource axp288_fuel + DEFINE_RES_IRQ(AXP288_IRQ_WL1), + }; + ++static const struct resource axp313a_pek_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"), ++ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), ++}; ++ + static const struct resource axp803_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +@@ -236,6 +331,11 @@ static const struct resource axp809_pek_ + DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), + }; + ++static const struct resource axp15060_pek_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"), ++ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"), ++}; ++ + static const struct regmap_config axp152_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -245,6 +345,15 @@ static const struct regmap_config axp152 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp192_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp192_writeable_table, ++ .volatile_table = &axp192_volatile_table, ++ .max_register = AXP20X_CC_CTRL, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static const struct regmap_config axp20x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -272,6 +381,15 @@ static const struct regmap_config axp288 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp313a_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp313a_writeable_table, ++ .volatile_table = &axp313a_volatile_table, ++ .max_register = AXP313A_IRQ_STATE, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static const struct regmap_config axp806_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -281,6 +399,15 @@ static const struct regmap_config axp806 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp15060_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp15060_writeable_table, ++ .volatile_table = &axp15060_volatile_table, ++ .max_register = AXP15060_IRQ2_STATE, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ + [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } + +@@ -304,6 +431,42 @@ static const struct regmap_irq axp152_re + INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), + }; + ++static const struct regmap_irq axp192_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7), ++ INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6), ++ INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5), ++ INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4), ++ INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3), ++ INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2), ++ INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1), ++ INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7), ++ INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6), ++ INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5), ++ INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4), ++ INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3), ++ INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2), ++ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1), ++ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0), ++ INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7), ++ INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6), ++ INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5), ++ INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4), ++ INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3), ++ INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1), ++ INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0), ++ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7), ++ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6), ++ INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5), ++ INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4), ++ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3), ++ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2), ++ INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0), ++ INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7), ++ INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2), ++ INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1), ++ INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0), ++}; ++ + static const struct regmap_irq axp20x_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), +@@ -415,6 +578,16 @@ static const struct regmap_irq axp288_re + INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), + }; + ++static const struct regmap_irq axp313a_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7), ++ INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6), ++ INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5), ++ INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4), ++ INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3), ++ INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2), ++ INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), ++}; ++ + static const struct regmap_irq axp803_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), +@@ -502,24 +675,65 @@ static const struct regmap_irq axp809_re + INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), + }; + ++static const struct regmap_irq axp15060_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0), ++ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1), ++ INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2), ++ INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3), ++ INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4), ++ INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5), ++ INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6), ++ INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7), ++ INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0), ++ INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1), ++ INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2), ++ INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3), ++ INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4), ++ INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5), ++}; ++ + static const struct regmap_irq_chip axp152_regmap_irq_chip = { + .name = "axp152_irq_chip", + .status_base = AXP152_IRQ1_STATE, + .ack_base = AXP152_IRQ1_STATE, +- .mask_base = AXP152_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP152_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp152_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp152_regmap_irqs), + .num_regs = 3, + }; + ++static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data, ++ unsigned int base, int index) ++{ ++ /* linear mapping for IRQ1 to IRQ4 */ ++ if (index < 4) ++ return base + index; ++ ++ /* handle IRQ5 separately */ ++ if (base == AXP192_IRQ1_EN) ++ return AXP192_IRQ5_EN; ++ ++ return AXP192_IRQ5_STATE; ++} ++ ++static const struct regmap_irq_chip axp192_regmap_irq_chip = { ++ .name = "axp192_irq_chip", ++ .status_base = AXP192_IRQ1_STATE, ++ .ack_base = AXP192_IRQ1_STATE, ++ .unmask_base = AXP192_IRQ1_EN, ++ .init_ack_masked = true, ++ .irqs = axp192_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp192_regmap_irqs), ++ .num_regs = 5, ++ .get_irq_reg = axp192_get_irq_reg, ++}; ++ + static const struct regmap_irq_chip axp20x_regmap_irq_chip = { + .name = "axp20x_irq_chip", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp20x_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), +@@ -531,8 +745,7 @@ static const struct regmap_irq_chip axp2 + .name = "axp22x_irq_chip", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp22x_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs), +@@ -543,8 +756,7 @@ static const struct regmap_irq_chip axp2 + .name = "axp288_irq_chip", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp288_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp288_regmap_irqs), +@@ -552,12 +764,22 @@ static const struct regmap_irq_chip axp2 + + }; + ++static const struct regmap_irq_chip axp313a_regmap_irq_chip = { ++ .name = "axp313a_irq_chip", ++ .status_base = AXP313A_IRQ_STATE, ++ .ack_base = AXP313A_IRQ_STATE, ++ .unmask_base = AXP313A_IRQ_EN, ++ .init_ack_masked = true, ++ .irqs = axp313a_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs), ++ .num_regs = 1, ++}; ++ + static const struct regmap_irq_chip axp803_regmap_irq_chip = { + .name = "axp803", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp803_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp803_regmap_irqs), +@@ -568,8 +790,7 @@ static const struct regmap_irq_chip axp8 + .name = "axp806", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp806_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp806_regmap_irqs), +@@ -580,14 +801,45 @@ static const struct regmap_irq_chip axp8 + .name = "axp809", + .status_base = AXP20X_IRQ1_STATE, + .ack_base = AXP20X_IRQ1_STATE, +- .mask_base = AXP20X_IRQ1_EN, +- .mask_invert = true, ++ .unmask_base = AXP20X_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp809_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), + .num_regs = 5, + }; + ++static const struct regmap_irq_chip axp15060_regmap_irq_chip = { ++ .name = "axp15060", ++ .status_base = AXP15060_IRQ1_STATE, ++ .ack_base = AXP15060_IRQ1_STATE, ++ .unmask_base = AXP15060_IRQ1_EN, ++ .init_ack_masked = true, ++ .irqs = axp15060_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs), ++ .num_regs = 2, ++}; ++ ++static const struct mfd_cell axp192_cells[] = { ++ { ++ .name = "axp192-adc", ++ .of_compatible = "x-powers,axp192-adc", ++ }, { ++ .name = "axp20x-battery-power-supply", ++ .of_compatible = "x-powers,axp192-battery-power-supply", ++ }, { ++ .name = "axp20x-ac-power-supply", ++ .of_compatible = "x-powers,axp202-ac-power-supply", ++ .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources), ++ .resources = axp192_ac_power_supply_resources, ++ }, { ++ .name = "axp20x-usb-power-supply", ++ .of_compatible = "x-powers,axp192-usb-power-supply", ++ .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources), ++ .resources = axp192_usb_power_supply_resources, ++ }, ++ { .name = "axp20x-regulator" }, ++}; ++ + static const struct mfd_cell axp20x_cells[] = { + { + .name = "axp20x-gpio", +@@ -683,6 +935,11 @@ static const struct mfd_cell axp152_cell + }, + }; + ++static struct mfd_cell axp313a_cells[] = { ++ MFD_CELL_NAME("axp20x-regulator"), ++ MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), ++}; ++ + static const struct resource axp288_adc_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), + }; +@@ -832,17 +1089,43 @@ static const struct mfd_cell axp813_cell + }, + }; + +-static struct axp20x_dev *axp20x_pm_power_off; +-static void axp20x_power_off(void) ++static const struct mfd_cell axp15060_cells[] = { ++ { ++ .name = "axp221-pek", ++ .num_resources = ARRAY_SIZE(axp15060_pek_resources), ++ .resources = axp15060_pek_resources, ++ }, { ++ .name = "axp20x-regulator", ++ }, ++}; ++ ++/* For boards that don't have IRQ line connected to SOC. */ ++static const struct mfd_cell axp_regulator_only_cells[] = { ++ { ++ .name = "axp20x-regulator", ++ }, ++}; ++ ++static int axp20x_power_off(struct sys_off_data *data) + { +- if (axp20x_pm_power_off->variant == AXP288_ID) +- return; ++ struct axp20x_dev *axp20x = data->cb_data; ++ unsigned int shutdown_reg; + +- regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, +- AXP20X_OFF); ++ switch (axp20x->variant) { ++ case AXP313A_ID: ++ shutdown_reg = AXP313A_SHUTDOWN_CTRL; ++ break; ++ default: ++ shutdown_reg = AXP20X_OFF_CTRL; ++ break; ++ } ++ ++ regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ + mdelay(500); ++ ++ return NOTIFY_DONE; + } + + int axp20x_match_device(struct axp20x_dev *axp20x) +@@ -874,6 +1157,12 @@ int axp20x_match_device(struct axp20x_de + axp20x->regmap_cfg = &axp152_regmap_config; + axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; + break; ++ case AXP192_ID: ++ axp20x->nr_cells = ARRAY_SIZE(axp192_cells); ++ axp20x->cells = axp192_cells; ++ axp20x->regmap_cfg = &axp192_regmap_config; ++ axp20x->regmap_irq_chip = &axp192_regmap_irq_chip; ++ break; + case AXP202_ID: + case AXP209_ID: + axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); +@@ -900,6 +1189,12 @@ int axp20x_match_device(struct axp20x_de + axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; + axp20x->irq_flags = IRQF_TRIGGER_LOW; + break; ++ case AXP313A_ID: ++ axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); ++ axp20x->cells = axp313a_cells; ++ axp20x->regmap_cfg = &axp313a_regmap_config; ++ axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; ++ break; + case AXP803_ID: + axp20x->nr_cells = ARRAY_SIZE(axp803_cells); + axp20x->cells = axp803_cells; +@@ -942,6 +1237,28 @@ int axp20x_match_device(struct axp20x_de + */ + axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; + break; ++ case AXP15060_ID: ++ /* ++ * Don't register the power key part if there is no interrupt ++ * line. ++ * ++ * Since most use cases of AXP PMICs are Allwinner SOCs, board ++ * designers follow Allwinner's reference design and connects ++ * IRQ line to SOC, there's no need for those variants to deal ++ * with cases that IRQ isn't connected. However, AXP15660 is ++ * used by some other vendors' SOCs that didn't connect IRQ ++ * line, we need to deal with this case. ++ */ ++ if (axp20x->irq > 0) { ++ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); ++ axp20x->cells = axp15060_cells; ++ } else { ++ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); ++ axp20x->cells = axp_regulator_only_cells; ++ } ++ axp20x->regmap_cfg = &axp15060_regmap_config; ++ axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; ++ break; + default: + dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); + return -EINVAL; +@@ -1009,10 +1326,11 @@ int axp20x_device_probe(struct axp20x_de + return ret; + } + +- if (!pm_power_off) { +- axp20x_pm_power_off = axp20x; +- pm_power_off = axp20x_power_off; +- } ++ if (axp20x->variant != AXP288_ID) ++ devm_register_sys_off_handler(axp20x->dev, ++ SYS_OFF_MODE_POWER_OFF, ++ SYS_OFF_PRIO_DEFAULT, ++ axp20x_power_off, axp20x); + + dev_info(axp20x->dev, "AXP20X driver loaded\n"); + +@@ -1022,11 +1340,6 @@ EXPORT_SYMBOL(axp20x_device_probe); + + void axp20x_device_remove(struct axp20x_dev *axp20x) + { +- if (axp20x == axp20x_pm_power_off) { +- axp20x_pm_power_off = NULL; +- pm_power_off = NULL; +- } +- + mfd_remove_devices(axp20x->dev); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); + } +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -12,18 +12,22 @@ + + enum axp20x_variants { + AXP152_ID = 0, ++ AXP192_ID, + AXP202_ID, + AXP209_ID, + AXP221_ID, + AXP223_ID, + AXP288_ID, ++ AXP313A_ID, + AXP803_ID, + AXP806_ID, + AXP809_ID, + AXP813_ID, ++ AXP15060_ID, + NR_AXP20X_VARIANTS, + }; + ++#define AXP192_DATACACHE(m) (0x06 + (m)) + #define AXP20X_DATACACHE(m) (0x04 + (m)) + + /* Power supply */ +@@ -45,6 +49,13 @@ enum axp20x_variants { + #define AXP152_DCDC_FREQ 0x37 + #define AXP152_DCDC_MODE 0x80 + ++#define AXP192_USB_OTG_STATUS 0x04 ++#define AXP192_PWR_OUT_CTRL 0x12 ++#define AXP192_DCDC2_V_OUT 0x23 ++#define AXP192_DCDC1_V_OUT 0x26 ++#define AXP192_DCDC3_V_OUT 0x27 ++#define AXP192_LDO2_3_V_OUT 0x28 ++ + #define AXP20X_PWR_INPUT_STATUS 0x00 + #define AXP20X_PWR_OP_MODE 0x01 + #define AXP20X_USB_OTG_STATUS 0x02 +@@ -91,6 +102,17 @@ enum axp20x_variants { + #define AXP22X_ALDO3_V_OUT 0x2a + #define AXP22X_CHRG_CTRL3 0x35 + ++#define AXP313A_ON_INDICATE 0x00 ++#define AXP313A_OUTPUT_CONTROL 0x10 ++#define AXP313A_DCDC1_CONRTOL 0x13 ++#define AXP313A_DCDC2_CONRTOL 0x14 ++#define AXP313A_DCDC3_CONRTOL 0x15 ++#define AXP313A_ALDO1_CONRTOL 0x16 ++#define AXP313A_DLDO1_CONRTOL 0x17 ++#define AXP313A_SHUTDOWN_CTRL 0x1a ++#define AXP313A_IRQ_EN 0x20 ++#define AXP313A_IRQ_STATE 0x21 ++ + #define AXP806_STARTUP_SRC 0x00 + #define AXP806_CHIP_ID 0x03 + #define AXP806_PWR_OUT_CTRL1 0x10 +@@ -131,6 +153,39 @@ enum axp20x_variants { + /* Other DCDC regulator control registers are the same as AXP803 */ + #define AXP813_DCDC7_V_OUT 0x26 + ++#define AXP15060_STARTUP_SRC 0x00 ++#define AXP15060_PWR_OUT_CTRL1 0x10 ++#define AXP15060_PWR_OUT_CTRL2 0x11 ++#define AXP15060_PWR_OUT_CTRL3 0x12 ++#define AXP15060_DCDC1_V_CTRL 0x13 ++#define AXP15060_DCDC2_V_CTRL 0x14 ++#define AXP15060_DCDC3_V_CTRL 0x15 ++#define AXP15060_DCDC4_V_CTRL 0x16 ++#define AXP15060_DCDC5_V_CTRL 0x17 ++#define AXP15060_DCDC6_V_CTRL 0x18 ++#define AXP15060_ALDO1_V_CTRL 0x19 ++#define AXP15060_DCDC_MODE_CTRL1 0x1a ++#define AXP15060_DCDC_MODE_CTRL2 0x1b ++#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e ++#define AXP15060_IRQ_PWROK_VOFF 0x1f ++#define AXP15060_ALDO2_V_CTRL 0x20 ++#define AXP15060_ALDO3_V_CTRL 0x21 ++#define AXP15060_ALDO4_V_CTRL 0x22 ++#define AXP15060_ALDO5_V_CTRL 0x23 ++#define AXP15060_BLDO1_V_CTRL 0x24 ++#define AXP15060_BLDO2_V_CTRL 0x25 ++#define AXP15060_BLDO3_V_CTRL 0x26 ++#define AXP15060_BLDO4_V_CTRL 0x27 ++#define AXP15060_BLDO5_V_CTRL 0x28 ++#define AXP15060_CLDO1_V_CTRL 0x29 ++#define AXP15060_CLDO2_V_CTRL 0x2a ++#define AXP15060_CLDO3_V_CTRL 0x2b ++#define AXP15060_CLDO4_V_CTRL 0x2d ++#define AXP15060_CPUSLDO_V_CTRL 0x2e ++#define AXP15060_PWR_WAKEUP_CTRL 0x31 ++#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32 ++#define AXP15060_PEK_KEY 0x36 ++ + /* Interrupt */ + #define AXP152_IRQ1_EN 0x40 + #define AXP152_IRQ2_EN 0x41 +@@ -139,6 +194,17 @@ enum axp20x_variants { + #define AXP152_IRQ2_STATE 0x49 + #define AXP152_IRQ3_STATE 0x4a + ++#define AXP192_IRQ1_EN 0x40 ++#define AXP192_IRQ2_EN 0x41 ++#define AXP192_IRQ3_EN 0x42 ++#define AXP192_IRQ4_EN 0x43 ++#define AXP192_IRQ1_STATE 0x44 ++#define AXP192_IRQ2_STATE 0x45 ++#define AXP192_IRQ3_STATE 0x46 ++#define AXP192_IRQ4_STATE 0x47 ++#define AXP192_IRQ5_EN 0x4a ++#define AXP192_IRQ5_STATE 0x4d ++ + #define AXP20X_IRQ1_EN 0x40 + #define AXP20X_IRQ2_EN 0x41 + #define AXP20X_IRQ3_EN 0x42 +@@ -152,7 +218,17 @@ enum axp20x_variants { + #define AXP20X_IRQ5_STATE 0x4c + #define AXP20X_IRQ6_STATE 0x4d + ++#define AXP15060_IRQ1_EN 0x40 ++#define AXP15060_IRQ2_EN 0x41 ++#define AXP15060_IRQ1_STATE 0x48 ++#define AXP15060_IRQ2_STATE 0x49 ++ + /* ADC */ ++#define AXP192_GPIO2_V_ADC_H 0x68 ++#define AXP192_GPIO2_V_ADC_L 0x69 ++#define AXP192_GPIO3_V_ADC_H 0x6a ++#define AXP192_GPIO3_V_ADC_L 0x6b ++ + #define AXP20X_ACIN_V_ADC_H 0x56 + #define AXP20X_ACIN_V_ADC_L 0x57 + #define AXP20X_ACIN_I_ADC_H 0x58 +@@ -182,6 +258,8 @@ enum axp20x_variants { + #define AXP20X_IPSOUT_V_HIGH_L 0x7f + + /* Power supply */ ++#define AXP192_GPIO30_IN_RANGE 0x85 ++ + #define AXP20X_DCDC_MODE 0x80 + #define AXP20X_ADC_EN1 0x82 + #define AXP20X_ADC_EN2 0x83 +@@ -210,6 +288,16 @@ enum axp20x_variants { + #define AXP152_PWM1_FREQ_Y 0x9c + #define AXP152_PWM1_DUTY_CYCLE 0x9d + ++#define AXP192_GPIO0_CTRL 0x90 ++#define AXP192_LDO_IO0_V_OUT 0x91 ++#define AXP192_GPIO1_CTRL 0x92 ++#define AXP192_GPIO2_CTRL 0x93 ++#define AXP192_GPIO2_0_STATE 0x94 ++#define AXP192_GPIO4_3_CTRL 0x95 ++#define AXP192_GPIO4_3_STATE 0x96 ++#define AXP192_GPIO2_0_PULL 0x97 ++#define AXP192_N_RSTO_CTRL 0x9e ++ + #define AXP20X_GPIO0_CTRL 0x90 + #define AXP20X_LDO5_V_OUT 0x91 + #define AXP20X_GPIO1_CTRL 0x92 +@@ -222,6 +310,8 @@ enum axp20x_variants { + #define AXP22X_GPIO_STATE 0x94 + #define AXP22X_GPIO_PULL_DOWN 0x95 + ++#define AXP15060_CLDO4_GPIO2_MODESET 0x2c ++ + /* Battery */ + #define AXP20X_CHRG_CC_31_24 0xb0 + #define AXP20X_CHRG_CC_23_16 0xb1 +@@ -288,6 +378,17 @@ enum axp20x_variants { + + /* Regulators IDs */ + enum { ++ AXP192_DCDC1 = 0, ++ AXP192_DCDC2, ++ AXP192_DCDC3, ++ AXP192_LDO1, ++ AXP192_LDO2, ++ AXP192_LDO3, ++ AXP192_LDO_IO0, ++ AXP192_REG_ID_MAX ++}; ++ ++enum { + AXP20X_LDO1 = 0, + AXP20X_LDO2, + AXP20X_LDO3, +@@ -323,6 +424,16 @@ enum { + }; + + enum { ++ AXP313A_DCDC1 = 0, ++ AXP313A_DCDC2, ++ AXP313A_DCDC3, ++ AXP313A_ALDO1, ++ AXP313A_DLDO1, ++ AXP313A_RTC_LDO, ++ AXP313A_REG_ID_MAX, ++}; ++ ++enum { + AXP806_DCDCA = 0, + AXP806_DCDCB, + AXP806_DCDCC, +@@ -419,6 +530,33 @@ enum { + AXP813_REG_ID_MAX, + }; + ++enum { ++ AXP15060_DCDC1 = 0, ++ AXP15060_DCDC2, ++ AXP15060_DCDC3, ++ AXP15060_DCDC4, ++ AXP15060_DCDC5, ++ AXP15060_DCDC6, ++ AXP15060_ALDO1, ++ AXP15060_ALDO2, ++ AXP15060_ALDO3, ++ AXP15060_ALDO4, ++ AXP15060_ALDO5, ++ AXP15060_BLDO1, ++ AXP15060_BLDO2, ++ AXP15060_BLDO3, ++ AXP15060_BLDO4, ++ AXP15060_BLDO5, ++ AXP15060_CLDO1, ++ AXP15060_CLDO2, ++ AXP15060_CLDO3, ++ AXP15060_CLDO4, ++ AXP15060_CPUSLDO, ++ AXP15060_SW, ++ AXP15060_RTC_LDO, ++ AXP15060_REG_ID_MAX, ++}; ++ + /* IRQs */ + enum { + AXP152_IRQ_LDO0IN_CONNECT = 1, +@@ -432,14 +570,51 @@ enum { + AXP152_IRQ_PEK_SHORT, + AXP152_IRQ_PEK_LONG, + AXP152_IRQ_TIMER, +- AXP152_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP152_IRQ_PEK_FAL_EDGE, ++ AXP152_IRQ_PEK_RIS_EDGE, + AXP152_IRQ_GPIO3_INPUT, + AXP152_IRQ_GPIO2_INPUT, + AXP152_IRQ_GPIO1_INPUT, + AXP152_IRQ_GPIO0_INPUT, + }; + ++enum axp192_irqs { ++ AXP192_IRQ_ACIN_OVER_V = 1, ++ AXP192_IRQ_ACIN_PLUGIN, ++ AXP192_IRQ_ACIN_REMOVAL, ++ AXP192_IRQ_VBUS_OVER_V, ++ AXP192_IRQ_VBUS_PLUGIN, ++ AXP192_IRQ_VBUS_REMOVAL, ++ AXP192_IRQ_VBUS_V_LOW, ++ AXP192_IRQ_BATT_PLUGIN, ++ AXP192_IRQ_BATT_REMOVAL, ++ AXP192_IRQ_BATT_ENT_ACT_MODE, ++ AXP192_IRQ_BATT_EXIT_ACT_MODE, ++ AXP192_IRQ_CHARG, ++ AXP192_IRQ_CHARG_DONE, ++ AXP192_IRQ_BATT_TEMP_HIGH, ++ AXP192_IRQ_BATT_TEMP_LOW, ++ AXP192_IRQ_DIE_TEMP_HIGH, ++ AXP192_IRQ_CHARG_I_LOW, ++ AXP192_IRQ_DCDC1_V_LONG, ++ AXP192_IRQ_DCDC2_V_LONG, ++ AXP192_IRQ_DCDC3_V_LONG, ++ AXP192_IRQ_PEK_SHORT = 22, ++ AXP192_IRQ_PEK_LONG, ++ AXP192_IRQ_N_OE_PWR_ON, ++ AXP192_IRQ_N_OE_PWR_OFF, ++ AXP192_IRQ_VBUS_VALID, ++ AXP192_IRQ_VBUS_NOT_VALID, ++ AXP192_IRQ_VBUS_SESS_VALID, ++ AXP192_IRQ_VBUS_SESS_END, ++ AXP192_IRQ_LOW_PWR_LVL = 31, ++ AXP192_IRQ_TIMER, ++ AXP192_IRQ_GPIO2_INPUT = 37, ++ AXP192_IRQ_GPIO1_INPUT, ++ AXP192_IRQ_GPIO0_INPUT, ++}; ++ + enum { + AXP20X_IRQ_ACIN_OVER_V = 1, + AXP20X_IRQ_ACIN_PLUGIN, +@@ -472,8 +647,9 @@ enum { + AXP20X_IRQ_LOW_PWR_LVL1, + AXP20X_IRQ_LOW_PWR_LVL2, + AXP20X_IRQ_TIMER, +- AXP20X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP20X_IRQ_PEK_FAL_EDGE, ++ AXP20X_IRQ_PEK_RIS_EDGE, + AXP20X_IRQ_GPIO3_INPUT, + AXP20X_IRQ_GPIO2_INPUT, + AXP20X_IRQ_GPIO1_INPUT, +@@ -502,8 +678,9 @@ enum axp22x_irqs { + AXP22X_IRQ_LOW_PWR_LVL1, + AXP22X_IRQ_LOW_PWR_LVL2, + AXP22X_IRQ_TIMER, +- AXP22X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP22X_IRQ_PEK_FAL_EDGE, ++ AXP22X_IRQ_PEK_RIS_EDGE, + AXP22X_IRQ_GPIO1_INPUT, + AXP22X_IRQ_GPIO0_INPUT, + }; +@@ -545,6 +722,16 @@ enum axp288_irqs { + AXP288_IRQ_BC_USB_CHNG, + }; + ++enum axp313a_irqs { ++ AXP313A_IRQ_DIE_TEMP_HIGH, ++ AXP313A_IRQ_DCDC2_V_LOW = 2, ++ AXP313A_IRQ_DCDC3_V_LOW, ++ AXP313A_IRQ_PEK_LONG, ++ AXP313A_IRQ_PEK_SHORT, ++ AXP313A_IRQ_PEK_FAL_EDGE, ++ AXP313A_IRQ_PEK_RIS_EDGE, ++}; ++ + enum axp803_irqs { + AXP803_IRQ_ACIN_OVER_V = 1, + AXP803_IRQ_ACIN_PLUGIN, +@@ -571,8 +758,9 @@ enum axp803_irqs { + AXP803_IRQ_LOW_PWR_LVL1, + AXP803_IRQ_LOW_PWR_LVL2, + AXP803_IRQ_TIMER, +- AXP803_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP803_IRQ_PEK_FAL_EDGE, ++ AXP803_IRQ_PEK_RIS_EDGE, + AXP803_IRQ_PEK_SHORT, + AXP803_IRQ_PEK_LONG, + AXP803_IRQ_PEK_OVER_OFF, +@@ -623,8 +811,9 @@ enum axp809_irqs { + AXP809_IRQ_LOW_PWR_LVL1, + AXP809_IRQ_LOW_PWR_LVL2, + AXP809_IRQ_TIMER, +- AXP809_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP809_IRQ_PEK_FAL_EDGE, ++ AXP809_IRQ_PEK_RIS_EDGE, + AXP809_IRQ_PEK_SHORT, + AXP809_IRQ_PEK_LONG, + AXP809_IRQ_PEK_OVER_OFF, +@@ -632,6 +821,23 @@ enum axp809_irqs { + AXP809_IRQ_GPIO0_INPUT, + }; + ++enum axp15060_irqs { ++ AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1, ++ AXP15060_IRQ_DIE_TEMP_HIGH_LV2, ++ AXP15060_IRQ_DCDC1_V_LOW, ++ AXP15060_IRQ_DCDC2_V_LOW, ++ AXP15060_IRQ_DCDC3_V_LOW, ++ AXP15060_IRQ_DCDC4_V_LOW, ++ AXP15060_IRQ_DCDC5_V_LOW, ++ AXP15060_IRQ_DCDC6_V_LOW, ++ AXP15060_IRQ_PEK_LONG, ++ AXP15060_IRQ_PEK_SHORT, ++ AXP15060_IRQ_GPIO1_INPUT, ++ AXP15060_IRQ_PEK_FAL_EDGE, ++ AXP15060_IRQ_PEK_RIS_EDGE, ++ AXP15060_IRQ_GPIO2_INPUT, ++}; ++ + struct axp20x_dev { + struct device *dev; + int irq; +@@ -698,4 +904,4 @@ int axp20x_device_probe(struct axp20x_de + */ + void axp20x_device_remove(struct axp20x_dev *axp20x); + +-#endif /* __LINUX_MFD_AXP20X_H */ ++#endif /* __LINUX_MFD_AXP20X_H */ +\ No newline at end of file diff --git a/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch b/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch new file mode 100644 index 0000000000..ccb277b3a0 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch @@ -0,0 +1,434 @@ +From 1b017f3376a5df4a2cd5a120c16723e777fc9a36 Mon Sep 17 00:00:00 2001 +From: "ziv.xu" +Date: Fri, 4 Aug 2023 13:55:23 +0800 +Subject: [PATCH 118/122] driver: regulator: axp20x: Support AXP15060 variant. + +Add axp15060 variant support to axp20x + +Signed-off-by: ziv.xu +--- + drivers/regulator/axp20x-regulator.c | 291 ++++++++++++++++++++++++++- + 1 file changed, 283 insertions(+), 8 deletions(-) + +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -134,6 +134,11 @@ + #define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6) + #define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7) + ++#define AXP313A_DCDC1_NUM_VOLTAGES 107 ++#define AXP313A_DCDC23_NUM_VOLTAGES 88 ++#define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) ++#define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) ++ + #define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0) + #define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1) + #define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2) +@@ -270,6 +275,74 @@ + + #define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6) + ++#define AXP15060_DCDC1_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_DCDC2_V_CTRL_MASK GENMASK(6, 0) ++#define AXP15060_DCDC3_V_CTRL_MASK GENMASK(6, 0) ++#define AXP15060_DCDC4_V_CTRL_MASK GENMASK(6, 0) ++#define AXP15060_DCDC5_V_CTRL_MASK GENMASK(6, 0) ++#define AXP15060_DCDC6_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_ALDO1_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_ALDO2_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_ALDO3_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_ALDO4_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_ALDO5_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_BLDO1_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_BLDO2_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_BLDO3_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_BLDO4_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_BLDO5_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_CLDO1_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_CLDO2_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_CLDO3_V_CTRL_MASK GENMASK(4, 0) ++#define AXP15060_CLDO4_V_CTRL_MASK GENMASK(5, 0) ++#define AXP15060_CPUSLDO_V_CTRL_MASK GENMASK(3, 0) ++ ++#define AXP15060_PWR_OUT_DCDC1_MASK BIT_MASK(0) ++#define AXP15060_PWR_OUT_DCDC2_MASK BIT_MASK(1) ++#define AXP15060_PWR_OUT_DCDC3_MASK BIT_MASK(2) ++#define AXP15060_PWR_OUT_DCDC4_MASK BIT_MASK(3) ++#define AXP15060_PWR_OUT_DCDC5_MASK BIT_MASK(4) ++#define AXP15060_PWR_OUT_DCDC6_MASK BIT_MASK(5) ++#define AXP15060_PWR_OUT_ALDO1_MASK BIT_MASK(0) ++#define AXP15060_PWR_OUT_ALDO2_MASK BIT_MASK(1) ++#define AXP15060_PWR_OUT_ALDO3_MASK BIT_MASK(2) ++#define AXP15060_PWR_OUT_ALDO4_MASK BIT_MASK(3) ++#define AXP15060_PWR_OUT_ALDO5_MASK BIT_MASK(4) ++#define AXP15060_PWR_OUT_BLDO1_MASK BIT_MASK(5) ++#define AXP15060_PWR_OUT_BLDO2_MASK BIT_MASK(6) ++#define AXP15060_PWR_OUT_BLDO3_MASK BIT_MASK(7) ++#define AXP15060_PWR_OUT_BLDO4_MASK BIT_MASK(0) ++#define AXP15060_PWR_OUT_BLDO5_MASK BIT_MASK(1) ++#define AXP15060_PWR_OUT_CLDO1_MASK BIT_MASK(2) ++#define AXP15060_PWR_OUT_CLDO2_MASK BIT_MASK(3) ++#define AXP15060_PWR_OUT_CLDO3_MASK BIT_MASK(4) ++#define AXP15060_PWR_OUT_CLDO4_MASK BIT_MASK(5) ++#define AXP15060_PWR_OUT_CPUSLDO_MASK BIT_MASK(6) ++#define AXP15060_PWR_OUT_SW_MASK BIT_MASK(7) ++ ++#define AXP15060_DCDC23_POLYPHASE_DUAL_MASK BIT_MASK(6) ++#define AXP15060_DCDC46_POLYPHASE_DUAL_MASK BIT_MASK(7) ++ ++#define AXP15060_DCDC234_500mV_START 0x00 ++#define AXP15060_DCDC234_500mV_STEPS 70 ++#define AXP15060_DCDC234_500mV_END \ ++ (AXP15060_DCDC234_500mV_START + AXP15060_DCDC234_500mV_STEPS) ++#define AXP15060_DCDC234_1220mV_START 0x47 ++#define AXP15060_DCDC234_1220mV_STEPS 16 ++#define AXP15060_DCDC234_1220mV_END \ ++ (AXP15060_DCDC234_1220mV_START + AXP15060_DCDC234_1220mV_STEPS) ++#define AXP15060_DCDC234_NUM_VOLTAGES 88 ++ ++#define AXP15060_DCDC5_800mV_START 0x00 ++#define AXP15060_DCDC5_800mV_STEPS 32 ++#define AXP15060_DCDC5_800mV_END \ ++ (AXP15060_DCDC5_800mV_START + AXP15060_DCDC5_800mV_STEPS) ++#define AXP15060_DCDC5_1140mV_START 0x21 ++#define AXP15060_DCDC5_1140mV_STEPS 35 ++#define AXP15060_DCDC5_1140mV_END \ ++ (AXP15060_DCDC5_1140mV_START + AXP15060_DCDC5_1140mV_STEPS) ++#define AXP15060_DCDC5_NUM_VOLTAGES 69 ++ + #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _enable_val, _disable_val) \ + [_family##_##_id] = { \ +@@ -638,6 +711,48 @@ static const struct regulator_desc axp22 + .ops = &axp20x_ops_sw, + }; + ++static const struct linear_range axp313a_dcdc1_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), ++ REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000), ++}; ++ ++static const struct linear_range axp313a_dcdc2_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), ++}; ++ ++/* ++ * This is deviating from the datasheet. The values here are taken from the ++ * BSP driver and have been confirmed by measurements. ++ */ ++static const struct linear_range axp313a_dcdc3_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), ++}; ++ ++static const struct regulator_desc axp313a_regulators[] = { ++ AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1", ++ axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES, ++ AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(0)), ++ AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2", ++ axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES, ++ AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(1)), ++ AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3", ++ axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES, ++ AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(2)), ++ AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100, ++ AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(3)), ++ AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100, ++ AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(4)), ++ AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), ++}; ++ + /* DCDC ranges shared with AXP813 */ + static const struct linear_range axp803_dcdc234_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, +@@ -1001,6 +1116,104 @@ static const struct regulator_desc axp81 + AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK), + }; + ++static const struct linear_range axp15060_dcdc234_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, ++ AXP15060_DCDC234_500mV_START, ++ AXP15060_DCDC234_500mV_END, ++ 10000), ++ REGULATOR_LINEAR_RANGE(1220000, ++ AXP15060_DCDC234_1220mV_START, ++ AXP15060_DCDC234_1220mV_END, ++ 20000), ++}; ++ ++static const struct linear_range axp15060_dcdc5_ranges[] = { ++ REGULATOR_LINEAR_RANGE(800000, ++ AXP15060_DCDC5_800mV_START, ++ AXP15060_DCDC5_800mV_END, ++ 10000), ++ REGULATOR_LINEAR_RANGE(1140000, ++ AXP15060_DCDC5_1140mV_START, ++ AXP15060_DCDC5_1140mV_END, ++ 20000), ++}; ++ ++static const struct regulator_desc axp15060_regulators[] = { ++ AXP_DESC(AXP15060, DCDC1, "dcdc1", "vin1", 1500, 3400, 100, ++ AXP15060_DCDC1_V_CTRL, AXP15060_DCDC1_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC1_MASK), ++ AXP_DESC_RANGES(AXP15060, DCDC2, "dcdc2", "vin2", ++ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, ++ AXP15060_DCDC2_V_CTRL, AXP15060_DCDC2_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC2_MASK), ++ AXP_DESC_RANGES(AXP15060, DCDC3, "dcdc3", "vin3", ++ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, ++ AXP15060_DCDC3_V_CTRL, AXP15060_DCDC3_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC3_MASK), ++ AXP_DESC_RANGES(AXP15060, DCDC4, "dcdc4", "vin4", ++ axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, ++ AXP15060_DCDC4_V_CTRL, AXP15060_DCDC4_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC4_MASK), ++ AXP_DESC_RANGES(AXP15060, DCDC5, "dcdc5", "vin5", ++ axp15060_dcdc5_ranges, AXP15060_DCDC5_NUM_VOLTAGES, ++ AXP15060_DCDC5_V_CTRL, AXP15060_DCDC5_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC5_MASK), ++ AXP_DESC(AXP15060, DCDC6, "dcdc6", "vin6", 500, 3400, 100, ++ AXP15060_DCDC6_V_CTRL, AXP15060_DCDC6_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC6_MASK), ++ AXP_DESC(AXP15060, ALDO1, "aldo1", "aldoin", 700, 3300, 100, ++ AXP15060_ALDO1_V_CTRL, AXP15060_ALDO1_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO1_MASK), ++ AXP_DESC(AXP15060, ALDO2, "aldo2", "aldoin", 700, 3300, 100, ++ AXP15060_ALDO2_V_CTRL, AXP15060_ALDO2_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO2_MASK), ++ AXP_DESC(AXP15060, ALDO3, "aldo3", "aldoin", 700, 3300, 100, ++ AXP15060_ALDO3_V_CTRL, AXP15060_ALDO3_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO3_MASK), ++ AXP_DESC(AXP15060, ALDO4, "aldo4", "aldoin", 700, 3300, 100, ++ AXP15060_ALDO4_V_CTRL, AXP15060_ALDO4_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO4_MASK), ++ AXP_DESC(AXP15060, ALDO5, "aldo5", "aldoin", 700, 3300, 100, ++ AXP15060_ALDO5_V_CTRL, AXP15060_ALDO5_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO5_MASK), ++ AXP_DESC(AXP15060, BLDO1, "bldo1", "bldoin", 700, 3300, 100, ++ AXP15060_BLDO1_V_CTRL, AXP15060_BLDO1_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO1_MASK), ++ AXP_DESC(AXP15060, BLDO2, "bldo2", "bldoin", 700, 3300, 100, ++ AXP15060_BLDO2_V_CTRL, AXP15060_BLDO2_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO2_MASK), ++ AXP_DESC(AXP15060, BLDO3, "bldo3", "bldoin", 700, 3300, 100, ++ AXP15060_BLDO3_V_CTRL, AXP15060_BLDO3_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO3_MASK), ++ AXP_DESC(AXP15060, BLDO4, "bldo4", "bldoin", 700, 3300, 100, ++ AXP15060_BLDO4_V_CTRL, AXP15060_BLDO4_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO4_MASK), ++ AXP_DESC(AXP15060, BLDO5, "bldo5", "bldoin", 700, 3300, 100, ++ AXP15060_BLDO5_V_CTRL, AXP15060_BLDO5_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO5_MASK), ++ AXP_DESC(AXP15060, CLDO1, "cldo1", "cldoin", 700, 3300, 100, ++ AXP15060_CLDO1_V_CTRL, AXP15060_CLDO1_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO1_MASK), ++ AXP_DESC(AXP15060, CLDO2, "cldo2", "cldoin", 700, 3300, 100, ++ AXP15060_CLDO2_V_CTRL, AXP15060_CLDO2_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO2_MASK), ++ AXP_DESC(AXP15060, CLDO3, "cldo3", "cldoin", 700, 3300, 100, ++ AXP15060_CLDO3_V_CTRL, AXP15060_CLDO3_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO3_MASK), ++ AXP_DESC(AXP15060, CLDO4, "cldo4", "cldoin", 700, 4200, 100, ++ AXP15060_CLDO4_V_CTRL, AXP15060_CLDO4_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO4_MASK), ++ /* Supply comes from DCDC5 */ ++ AXP_DESC(AXP15060, CPUSLDO, "cpusldo", NULL, 700, 1400, 50, ++ AXP15060_CPUSLDO_V_CTRL, AXP15060_CPUSLDO_V_CTRL_MASK, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CPUSLDO_MASK), ++ /* Supply comes from DCDC1 */ ++ AXP_DESC_SW(AXP15060, SW, "sw", NULL, ++ AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_SW_MASK), ++ /* Supply comes from ALDO1 */ ++ AXP_DESC_FIXED(AXP15060, RTC_LDO, "rtc-ldo", NULL, 1800), ++}; ++ + static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) + { + struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); +@@ -1040,6 +1253,16 @@ static int axp20x_set_dcdc_freq(struct p + def = 3000; + step = 150; + break; ++ case AXP313A_ID: ++ case AXP15060_ID: ++ /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ ++ if (dcdcfreq != 0) { ++ dev_err(&pdev->dev, ++ "DCDC frequency on this PMIC is fixed to 3 MHz.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; + default: + dev_err(&pdev->dev, + "Setting DCDC frequency for unsupported AXP variant\n"); +@@ -1145,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(stru + workmode <<= id - AXP813_DCDC1; + break; + ++ case AXP15060_ID: ++ reg = AXP15060_DCDC_MODE_CTRL2; ++ if (id < AXP15060_DCDC1 || id > AXP15060_DCDC6) ++ return -EINVAL; ++ ++ mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP15060_DCDC1); ++ workmode <<= id - AXP15060_DCDC1; ++ break; ++ + default: + /* should not happen */ + WARN_ON(1); +@@ -1164,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(st + + /* + * Currently in our supported AXP variants, only AXP803, AXP806, +- * and AXP813 have polyphase regulators. ++ * AXP813 and AXP15060 have polyphase regulators. + */ + switch (axp20x->variant) { + case AXP803_ID: +@@ -1196,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(st + } + break; + ++ case AXP15060_ID: ++ regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, ®); ++ ++ switch (id) { ++ case AXP15060_DCDC3: ++ return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK); ++ case AXP15060_DCDC6: ++ return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK); ++ } ++ break; ++ + default: + return false; + } +@@ -1217,6 +1460,7 @@ static int axp20x_regulator_probe(struct + u32 workmode; + const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; + const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; ++ const char *aldo1_name = axp15060_regulators[AXP15060_ALDO1].name; + bool drivevbus = false; + + switch (axp20x->variant) { +@@ -1232,6 +1476,10 @@ static int axp20x_regulator_probe(struct + drivevbus = of_property_read_bool(pdev->dev.parent->of_node, + "x-powers,drive-vbus-en"); + break; ++ case AXP313A_ID: ++ regulators = axp313a_regulators; ++ nregulators = AXP313A_REG_ID_MAX; ++ break; + case AXP803_ID: + regulators = axp803_regulators; + nregulators = AXP803_REG_ID_MAX; +@@ -1252,6 +1500,10 @@ static int axp20x_regulator_probe(struct + drivevbus = of_property_read_bool(pdev->dev.parent->of_node, + "x-powers,drive-vbus-en"); + break; ++ case AXP15060_ID: ++ regulators = axp15060_regulators; ++ nregulators = AXP15060_REG_ID_MAX; ++ break; + default: + dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", + axp20x->variant); +@@ -1278,8 +1530,9 @@ static int axp20x_regulator_probe(struct + continue; + + /* +- * Regulators DC1SW and DC5LDO are connected internally, +- * so we have to handle their supply names separately. ++ * Regulators DC1SW, DC5LDO and RTCLDO on AXP15060 are ++ * connected internally, so we have to handle their supply ++ * names separately. + * + * We always register the regulators in proper sequence, + * so the supply names are correctly read. See the last +@@ -1288,7 +1541,8 @@ static int axp20x_regulator_probe(struct + */ + if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || + (regulators == axp803_regulators && i == AXP803_DC1SW) || +- (regulators == axp809_regulators && i == AXP809_DC1SW)) { ++ (regulators == axp809_regulators && i == AXP809_DC1SW) || ++ (regulators == axp15060_regulators && i == AXP15060_SW)) { + new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + GFP_KERNEL); + if (!new_desc) +@@ -1300,7 +1554,8 @@ static int axp20x_regulator_probe(struct + } + + if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || +- (regulators == axp809_regulators && i == AXP809_DC5LDO)) { ++ (regulators == axp809_regulators && i == AXP809_DC5LDO) || ++ (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) { + new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + GFP_KERNEL); + if (!new_desc) +@@ -1311,6 +1566,18 @@ static int axp20x_regulator_probe(struct + desc = new_desc; + } + ++ ++ if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) { ++ new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), ++ GFP_KERNEL); ++ if (!new_desc) ++ return -ENOMEM; ++ ++ *new_desc = regulators[i]; ++ new_desc->supply_name = aldo1_name; ++ desc = new_desc; ++ } ++ + rdev = devm_regulator_register(&pdev->dev, desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register %s\n", +@@ -1329,19 +1596,26 @@ static int axp20x_regulator_probe(struct + } + + /* +- * Save AXP22X DCDC1 / DCDC5 regulator names for later. ++ * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later. + */ + if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || +- (regulators == axp809_regulators && i == AXP809_DCDC1)) ++ (regulators == axp809_regulators && i == AXP809_DCDC1) || ++ (regulators == axp15060_regulators && i == AXP15060_DCDC1)) + of_property_read_string(rdev->dev.of_node, + "regulator-name", + &dcdc1_name); + + if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) || +- (regulators == axp809_regulators && i == AXP809_DCDC5)) ++ (regulators == axp809_regulators && i == AXP809_DCDC5) || ++ (regulators == axp15060_regulators && i == AXP15060_DCDC5)) + of_property_read_string(rdev->dev.of_node, + "regulator-name", + &dcdc5_name); ++ ++ if (regulators == axp15060_regulators && i == AXP15060_ALDO1) ++ of_property_read_string(rdev->dev.of_node, ++ "regulator-name", ++ &aldo1_name); + } + + if (drivevbus) { +@@ -1364,6 +1638,7 @@ static struct platform_driver axp20x_reg + .probe = axp20x_regulator_probe, + .driver = { + .name = "axp20x-regulator", ++ .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + }; + diff --git a/target/linux/starfive/patches-6.1/0119-riscv-dts-visionfive2-add-EEPROM-node.patch b/target/linux/starfive/patches-6.1/0119-riscv-dts-visionfive2-add-EEPROM-node.patch new file mode 100644 index 0000000000..8aec7fb7e5 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0119-riscv-dts-visionfive2-add-EEPROM-node.patch @@ -0,0 +1,25 @@ +From 6d91484ec63526def63be4097c28790f25d647b8 Mon Sep 17 00:00:00 2001 +From: Zoltan HERPAI +Date: Thu, 10 Aug 2023 23:23:15 +0200 +Subject: [PATCH 119/122] riscv: dts: visionfive2: add EEPROM node + +Signed-off-by: Zoltan HERPAI +--- + .../boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -239,6 +239,12 @@ + pinctrl-0 = <&i2c5_pins>; + status = "okay"; + ++ eeprom@50 { ++ compatible = "atmel,24c04"; ++ reg = <0x50>; ++ pagesize = <16>; ++ }; ++ + axp15060: pmic@36 { + compatible = "x-powers,axp15060"; + reg = <0x36>; diff --git a/target/linux/starfive/patches-6.1/0120-riscv-dts-visionfive2-add-mmc-aliases.patch b/target/linux/starfive/patches-6.1/0120-riscv-dts-visionfive2-add-mmc-aliases.patch new file mode 100644 index 0000000000..e8067e1dcb --- /dev/null +++ b/target/linux/starfive/patches-6.1/0120-riscv-dts-visionfive2-add-mmc-aliases.patch @@ -0,0 +1,21 @@ +From aa5fcd525c1a01ca07a6fdb631dbd304e22c9669 Mon Sep 17 00:00:00 2001 +From: Zoltan HERPAI +Date: Thu, 10 Aug 2023 23:23:45 +0200 +Subject: [PATCH 120/122] riscv: dts: visionfive2: add mmc aliases + +Signed-off-by: Zoltan HERPAI +--- + arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -13,6 +13,8 @@ + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; + i2c0 = &i2c0; + i2c2 = &i2c2; + i2c5 = &i2c5; diff --git a/target/linux/starfive/patches-6.1/0121-drivers-include-cpufreq-Kconfig-for-riscv.patch b/target/linux/starfive/patches-6.1/0121-drivers-include-cpufreq-Kconfig-for-riscv.patch new file mode 100644 index 0000000000..231a844b41 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0121-drivers-include-cpufreq-Kconfig-for-riscv.patch @@ -0,0 +1,21 @@ +From 22b82c89dac3fadaa8c50760c25be7c78a2782a3 Mon Sep 17 00:00:00 2001 +From: Zoltan HERPAI +Date: Thu, 10 Aug 2023 23:42:13 +0200 +Subject: [PATCH] drivers: include cpufreq/Kconfig for riscv + +Signed-off-by: Zoltan HERPAI +--- + drivers/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -237,6 +237,8 @@ source "drivers/most/Kconfig" + + source "drivers/peci/Kconfig" + ++source "drivers/cpufreq/Kconfig" ++ + source "drivers/hte/Kconfig" + + endmenu diff --git a/target/linux/starfive/patches-6.1/0126-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch b/target/linux/starfive/patches-6.1/0126-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch new file mode 100644 index 0000000000..d057797bb2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/0126-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch @@ -0,0 +1,92 @@ +From 8a2d9c6decdbd042b3475d5ab69c1a79f0fd54aa Mon Sep 17 00:00:00 2001 +From: Xingyu Wu +Date: Mon, 21 Aug 2023 23:29:15 +0800 +Subject: [PATCH] clk: starfive: jh7110-sys: Fix lower rate of CPUfreq by + setting PLL0 rate to 1.5GHz + +CPUfreq supports 4 cpu frequency loads on 375/500/750/1500MHz. +But now PLL0 rate is 1GHz and the cpu frequency loads become +333/500/500/1000MHz in fact. + +So PLL0 rate should be set to 1.5GHz. Change the parent of cpu_root clock +and the divider of cpu_core before the setting. + +Reviewed-by: Hal Feng +Fixes: e2c510d6d630 ("riscv: dts: starfive: Add cpu scaling for JH7110 SoC") +Signed-off-by: Xingyu Wu +--- + .../clk/starfive/clk-starfive-jh7110-sys.c | 49 ++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c +@@ -7,6 +7,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -389,6 +390,7 @@ static int __init jh7110_syscrg_probe(st + struct jh71x0_clk_priv *priv; + unsigned int idx; + int ret; ++ struct clk *pllclk; + + priv = devm_kzalloc(&pdev->dev, + struct_size(priv, reg, JH7110_SYSCLK_END), +@@ -462,7 +464,52 @@ static int __init jh7110_syscrg_probe(st + if (ret) + return ret; + +- return jh7110_reset_controller_register(priv, "rst-sys", 0); ++ ret = jh7110_reset_controller_register(priv, "rst-sys", 0); ++ if (ret) ++ return ret; ++ ++ /* ++ * Set PLL0 rate to 1.5GHz ++ * In order to not affect the cpu when the PLL0 rate is changing, ++ * we need to switch the parent of cpu_root clock to osc clock first, ++ * and then switch back after setting the PLL0 rate. ++ */ ++ pllclk = clk_get(priv->dev, "pll0_out"); ++ if (!IS_ERR(pllclk)) { ++ struct clk *osc = clk_get(&pdev->dev, "osc"); ++ struct clk *cpu_root = priv->reg[JH7110_SYSCLK_CPU_ROOT].hw.clk; ++ struct clk *cpu_core = priv->reg[JH7110_SYSCLK_CPU_CORE].hw.clk; ++ ++ if (IS_ERR(osc)) { ++ clk_put(pllclk); ++ return PTR_ERR(osc); ++ } ++ ++ /* ++ * CPU need voltage regulation by CPUfreq if set 1.5GHz. ++ * So in this driver, cpu_core need to be set the divider to be 2 first ++ * and will be 750M after setting parent. ++ */ ++ ret = clk_set_rate(cpu_core, clk_get_rate(cpu_core) / 2); ++ if (ret) ++ goto failed_set; ++ ++ ret = clk_set_parent(cpu_root, osc); ++ if (ret) ++ goto failed_set; ++ ++ ret = clk_set_rate(pllclk, 1500000000); ++ if (ret) ++ goto failed_set; ++ ++ ret = clk_set_parent(cpu_root, pllclk); ++ ++failed_set: ++ clk_put(pllclk); ++ clk_put(osc); ++ } ++ ++ return ret; + } + + static const struct of_device_id jh7110_syscrg_match[] = { diff --git a/target/linux/starfive/patches-6.1/1000-net-stmmac-dwmac-starfive-Add-JH7100-support.patch b/target/linux/starfive/patches-6.1/1000-net-stmmac-dwmac-starfive-Add-JH7100-support.patch new file mode 100644 index 0000000000..d009d375ca --- /dev/null +++ b/target/linux/starfive/patches-6.1/1000-net-stmmac-dwmac-starfive-Add-JH7100-support.patch @@ -0,0 +1,63 @@ +From 22885637d0976473b04d4bae191fcf88e28b3df5 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Wed, 29 Sep 2021 20:50:22 +0200 +Subject: [PATCH 1000/1024] net: stmmac: dwmac-starfive: Add JH7100 support + +This adds support for setting the phy interface and delay chains on the +StarFive JH7100 SoC. + +Signed-off-by: Emil Renner Berthing +--- + .../net/ethernet/stmicro/stmmac/dwmac-starfive.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +@@ -17,6 +17,10 @@ + #define STARFIVE_DWMAC_PHY_INFT_RMII 0x4 + #define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U + ++#define JH7100_SYSMAIN_REGISTER28 0x70 ++/* The value below is not a typo, just really bad naming by StarFive ¯\_(ツ)_/¯ */ ++#define JH7100_SYSMAIN_REGISTER49 0xc8 ++ + struct starfive_dwmac { + struct device *dev; + struct clk *clk_tx; +@@ -56,6 +60,7 @@ static int starfive_dwmac_set_mode(struc + struct regmap *regmap; + unsigned int args[2]; + unsigned int mode; ++ u32 gtxclk_dlychain; + int err; + + switch (plat_dat->interface) { +@@ -65,6 +70,7 @@ static int starfive_dwmac_set_mode(struc + + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: + mode = STARFIVE_DWMAC_PHY_INFT_RGMII; + break; + +@@ -87,6 +93,12 @@ static int starfive_dwmac_set_mode(struc + if (err) + return dev_err_probe(dwmac->dev, err, "error setting phy mode\n"); + ++ if (!of_property_read_u32(dwmac->dev->of_node, "starfive,gtxclk-dlychain", >xclk_dlychain)) { ++ err = regmap_write(regmap, JH7100_SYSMAIN_REGISTER49, gtxclk_dlychain); ++ if (err) ++ return dev_err_probe(dwmac->dev, err, "error selecting gtxclk delay chain\n"); ++ } ++ + return 0; + } + +@@ -149,6 +161,7 @@ static int starfive_dwmac_probe(struct p + } + + static const struct of_device_id starfive_dwmac_match[] = { ++ { .compatible = "starfive,jh7100-dwmac" }, + { .compatible = "starfive,jh7110-dwmac" }, + { /* sentinel */ } + }; diff --git a/target/linux/starfive/patches-6.1/1001-dt-bindings-mfd-syscon-Add-StarFive-JH7100-sysmain-c.patch b/target/linux/starfive/patches-6.1/1001-dt-bindings-mfd-syscon-Add-StarFive-JH7100-sysmain-c.patch new file mode 100644 index 0000000000..5d46eab3f7 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1001-dt-bindings-mfd-syscon-Add-StarFive-JH7100-sysmain-c.patch @@ -0,0 +1,23 @@ +From a5f12fe4b640281c04a9b8b6ad676df9eeba9aa6 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Wed, 6 Oct 2021 20:42:34 +0200 +Subject: [PATCH 1001/1024] dt-bindings: mfd: syscon: Add StarFive JH7100 + sysmain compatible + +Document StarFive JH7100 SoC compatible for sysmain registers. + +Signed-off-by: Emil Renner Berthing +--- + Documentation/devicetree/bindings/mfd/syscon.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/mfd/syscon.yaml ++++ b/Documentation/devicetree/bindings/mfd/syscon.yaml +@@ -69,6 +69,7 @@ properties: + - samsung,exynos5433-sysreg + - samsung,exynos850-sysreg + - samsung,exynosautov9-sysreg ++ - starfive,jh7100-sysmain + + - const: syscon + diff --git a/target/linux/starfive/patches-6.1/1002-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch b/target/linux/starfive/patches-6.1/1002-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch new file mode 100644 index 0000000000..3a5b8fe593 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1002-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch @@ -0,0 +1,25 @@ +From a3e9dc73758c378dd471fb6b1458f39592b020fe Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Thu, 14 Oct 2021 20:56:54 +0200 +Subject: [PATCH 1002/1024] serial: 8250_dw: Add starfive,jh7100-hsuart + compatible + +This adds a compatible for the high speed UARTs on the StarFive JH7100 +RISC-V SoC. Just like the regular uarts we also need to keep the input +clocks at their default rate and rely only on the divisor in the UART. + +Signed-off-by: Emil Renner Berthing +--- + drivers/tty/serial/8250/8250_dw.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -777,6 +777,7 @@ static const struct of_device_id dw8250_ + { .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data }, + { .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data }, + { .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data }, ++ { .compatible = "starfive,jh7100-hsuart", .data = &dw8250_starfive_jh7100_data }, + { .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data }, + { /* Sentinel */ } + }; diff --git a/target/linux/starfive/patches-6.1/1003-riscv-dts-starfive-Group-tuples-in-interrupt-propert.patch b/target/linux/starfive/patches-6.1/1003-riscv-dts-starfive-Group-tuples-in-interrupt-propert.patch new file mode 100644 index 0000000000..a202950455 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1003-riscv-dts-starfive-Group-tuples-in-interrupt-propert.patch @@ -0,0 +1,40 @@ +From 790e1157753b4dcc9bad4521987fe09aa6657876 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 25 Nov 2021 14:21:18 +0100 +Subject: [PATCH 1003/1024] riscv: dts: starfive: Group tuples in interrupt + properties + +To improve human readability and enable automatic validation, the tuples +in the various properties containing interrupt specifiers should be +grouped. + +Fix this by grouping the tuples of "interrupts-extended" properties +using angle brackets. + +Signed-off-by: Geert Uytterhoeven +--- + arch/riscv/boot/dts/starfive/jh7100.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -118,15 +118,15 @@ + clint: clint@2000000 { + compatible = "starfive,jh7100-clint", "sifive,clint0"; + reg = <0x0 0x2000000 0x0 0x10000>; +- interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7 +- &cpu1_intc 3 &cpu1_intc 7>; ++ interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, ++ <&cpu1_intc 3>, <&cpu1_intc 7>; + }; + + plic: interrupt-controller@c000000 { + compatible = "starfive,jh7100-plic", "sifive,plic-1.0.0"; + reg = <0x0 0xc000000 0x0 0x4000000>; +- interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9 +- &cpu1_intc 11 &cpu1_intc 9>; ++ interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>, ++ <&cpu1_intc 11>, <&cpu1_intc 9>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; diff --git a/target/linux/starfive/patches-6.1/1004-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch b/target/linux/starfive/patches-6.1/1004-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch new file mode 100644 index 0000000000..b57ec9121e --- /dev/null +++ b/target/linux/starfive/patches-6.1/1004-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch @@ -0,0 +1,32 @@ +From 6a9196186f9630006c3db022bcc0bd5796f4fae5 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 20 Nov 2021 17:13:22 +0100 +Subject: [PATCH 1004/1024] RISC-V: Add StarFive JH7100 audio clock node + +Add device tree node for the audio clocks on the StarFive JH7100 RISC-V +SoC. + +Signed-off-by: Emil Renner Berthing +--- + arch/riscv/boot/dts/starfive/jh7100.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -133,6 +133,16 @@ + riscv,ndev = <133>; + }; + ++ audclk: clock-controller@10480000 { ++ compatible = "starfive,jh7100-audclk"; ++ reg = <0x0 0x10480000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_AUDIO_SRC>, ++ <&clkgen JH7100_CLK_AUDIO_12288>, ++ <&clkgen JH7100_CLK_DOM7AHB_BUS>; ++ clock-names = "audio_src", "audio_12288", "dom7ahb_bus"; ++ #clock-cells = <1>; ++ }; ++ + clkgen: clock-controller@11800000 { + compatible = "starfive,jh7100-clkgen"; + reg = <0x0 0x11800000 0x0 0x10000>; diff --git a/target/linux/starfive/patches-6.1/1005-RISC-V-Mark-StarFive-JH7100-as-having-non-coherent-D.patch b/target/linux/starfive/patches-6.1/1005-RISC-V-Mark-StarFive-JH7100-as-having-non-coherent-D.patch new file mode 100644 index 0000000000..11fa1155d6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1005-RISC-V-Mark-StarFive-JH7100-as-having-non-coherent-D.patch @@ -0,0 +1,21 @@ +From a22e1110a6ffcc2cf4b3b598f037879cbd0915d3 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Wed, 31 Aug 2022 22:54:07 +0200 +Subject: [PATCH 1005/1024] RISC-V: Mark StarFive JH7100 as having non-coherent + DMAs + +Signed-off-by: Emil Renner Berthing +--- + arch/riscv/boot/dts/starfive/jh7100.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -111,6 +111,7 @@ + soc { + compatible = "simple-bus"; + interrupt-parent = <&plic>; ++ dma-noncoherent; + #address-cells = <2>; + #size-cells = <2>; + ranges; diff --git a/target/linux/starfive/patches-6.1/1006-drivers-tty-serial-8250-update-driver-for-JH7100.patch b/target/linux/starfive/patches-6.1/1006-drivers-tty-serial-8250-update-driver-for-JH7100.patch new file mode 100644 index 0000000000..feb52591b3 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1006-drivers-tty-serial-8250-update-driver-for-JH7100.patch @@ -0,0 +1,28 @@ +From d0c1660c9e88748c9eba81ff3839de54dffba6ad Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Fri, 8 Jan 2021 03:11:04 +0800 +Subject: [PATCH 1006/1024] drivers/tty/serial/8250: update driver for JH7100 + +--- + drivers/tty/serial/8250/8250_port.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -72,8 +72,16 @@ static const struct serial8250_config ua + }, + [PORT_16550] = { + .name = "16550", ++#ifdef CONFIG_SOC_STARFIVE ++ .fifo_size = 16, ++ .tx_loadsz = 16, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, ++ .rxtrig_bytes = {1, 4, 8, 14}, ++ .flags = UART_CAP_FIFO, ++#else + .fifo_size = 1, + .tx_loadsz = 1, ++#endif + }, + [PORT_16550A] = { + .name = "16550A", diff --git a/target/linux/starfive/patches-6.1/1007-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch b/target/linux/starfive/patches-6.1/1007-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch new file mode 100644 index 0000000000..1599e8a2ca --- /dev/null +++ b/target/linux/starfive/patches-6.1/1007-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch @@ -0,0 +1,55 @@ +From 5fdd2623dd3eed156fa1ec65b2096da735bb0cde Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Wed, 17 Nov 2021 14:50:45 +0800 +Subject: [PATCH 1007/1024] dmaengine: dw-axi-dmac: Handle xfer start while + non-idle + +Signed-off-by: Samin Guo +Signed-off-by: Curry Zhang +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 +++++++++++- + drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 + + 2 files changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -382,11 +382,13 @@ static void axi_chan_block_xfer_start(st + u32 irq_mask; + u8 lms = 0; /* Select AXI0 master for LLI fetching */ + ++ chan->is_err = false; + if (unlikely(axi_chan_is_hw_enable(chan))) { + dev_err(chan2dev(chan), "%s is non-idle!\n", + axi_chan_name(chan)); + +- return; ++ axi_chan_disable(chan); ++ chan->is_err = true; + } + + axi_dma_enable(chan->chip); +@@ -1028,6 +1030,14 @@ static noinline void axi_chan_handle_err + axi_chan_name(chan)); + goto out; + } ++ if (chan->is_err) { ++ struct axi_dma_desc *desc = vd_to_axi_desc(vd); ++ ++ axi_chan_block_xfer_start(chan, desc); ++ chan->is_err = false; ++ goto out; ++ } ++ + /* Remove the completed descriptor from issued list */ + list_del(&vd->node); + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +@@ -50,6 +50,7 @@ struct axi_dma_chan { + struct dma_slave_config config; + enum dma_transfer_direction direction; + bool cyclic; ++ bool is_err; + /* these other elements are all protected by vc.lock */ + bool is_paused; + }; diff --git a/target/linux/starfive/patches-6.1/1008-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch b/target/linux/starfive/patches-6.1/1008-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch new file mode 100644 index 0000000000..e01c37fd76 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1008-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch @@ -0,0 +1,64 @@ +From c06352c09ce55999d41036e593293a3aaf0cf70c Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Wed, 17 Nov 2021 14:50:45 +0800 +Subject: [PATCH 1008/1024] dmaengine: dw-axi-dmac: Add StarFive JH7100 support + +Signed-off-by: Samin Guo +Signed-off-by: Emil Renner Berthing +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 ++++++++++++ + drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 4 ++++ + 2 files changed, 16 insertions(+) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -677,8 +677,13 @@ static int dw_axi_dma_set_hw_desc(struct + + hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1); + ++#ifdef CONFIG_SOC_STARFIVE ++ ctllo |= DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_DST_MSIZE_POS | ++ DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_SRC_MSIZE_POS; ++#else + ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | + DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; ++#endif + hw_desc->lli->ctl_lo = cpu_to_le32(ctllo); + + set_desc_src_master(hw_desc); +@@ -1508,7 +1513,11 @@ static int dw_probe(struct platform_devi + * Therefore, set constraint to 1024 * 4. + */ + dw->dma.dev->dma_parms = &dw->dma_parms; ++#ifdef CONFIG_SOC_STARFIVE ++ dma_set_max_seg_size(&pdev->dev, DMAC_MAX_BLK_SIZE); ++#else + dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE); ++#endif + platform_set_drvdata(pdev, chip); + + pm_runtime_enable(chip->dev); +@@ -1593,6 +1602,9 @@ static const struct of_device_id dw_dma_ + .compatible = "intel,kmb-axi-dma", + .data = (void *)AXI_DMA_FLAG_HAS_APB_REGS, + }, { ++ .compatible = "starfive,jh7100-axi-dma", ++ .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2), ++ }, { + .compatible = "starfive,jh7110-axi-dma", + .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2), + }, +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +@@ -283,7 +283,11 @@ enum { + #define CH_CTL_L_SRC_MAST BIT(0) + + /* CH_CFG_H */ ++#ifdef CONFIG_SOC_STARFIVE ++#define CH_CFG_H_PRIORITY_POS 15 ++#else + #define CH_CFG_H_PRIORITY_POS 17 ++#endif + #define CH_CFG_H_DST_PER_POS 12 + #define CH_CFG_H_SRC_PER_POS 7 + #define CH_CFG_H_HS_SEL_DST_POS 4 diff --git a/target/linux/starfive/patches-6.1/1009-pinctrl-starfive-Reset-pinmux-settings.patch b/target/linux/starfive/patches-6.1/1009-pinctrl-starfive-Reset-pinmux-settings.patch new file mode 100644 index 0000000000..d2873ff968 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1009-pinctrl-starfive-Reset-pinmux-settings.patch @@ -0,0 +1,127 @@ +From 89c86fda8cee5b93ce213dcc46b2cf27e5ee3312 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 17 Jul 2021 21:50:38 +0200 +Subject: [PATCH 1009/1024] pinctrl: starfive: Reset pinmux settings + +Current u-boot doesn't seem to take into account that some GPIOs are +configured as inputs/outputs of certain peripherals on power-up. This +means it ends up configuring some GPIOs as inputs to more than one +peripheral which the documentation explicitly says is illegal. Similarly +it also ends up configuring more than one GPIO as output of the same +peripheral. While not explicitly mentioned by the documentation this +also seems like a bad idea. + +The easiest way to remedy this mess is to just disconnect all GPIOs from +peripherals and have our pinmux configuration set everything up +properly. This, however, means that we'd disconnect the serial console +from its pins for a while, so add a device tree property to keep +certain GPIOs from being reset. + +Signed-off-by: Emil Renner Berthing +--- + .../pinctrl/starfive,jh7100-pinctrl.yaml | 4 ++ + .../starfive/pinctrl-starfive-jh7100.c | 66 +++++++++++++++++++ + 2 files changed, 70 insertions(+) + +--- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml +@@ -88,6 +88,10 @@ properties: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3, 4, 5, 6] + ++ starfive,keep-gpiomux: ++ description: Keep pinmux for these GPIOs from being reset at boot. ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ + required: + - compatible + - reg +--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c ++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c +@@ -200,6 +200,10 @@ static u16 starfive_drive_strength_from_ + return (clamp(i, 14U, 63U) - 14) / 7; + } + ++static bool keepmux; ++module_param(keepmux, bool, 0644); ++MODULE_PARM_DESC(keepmux, "Keep pinmux settings from previous boot stage"); ++ + struct starfive_pinctrl { + struct gpio_chip gc; + struct pinctrl_gpio_range gpios; +@@ -1222,6 +1226,65 @@ static void starfive_disable_clock(void + clk_disable_unprepare(data); + } + ++#define GPI_END (GPI_USB_OVER_CURRENT + 1) ++static void starfive_pinmux_reset(struct starfive_pinctrl *sfp) ++{ ++ static const DECLARE_BITMAP(defaults, GPI_END) = { ++ BIT_MASK(GPI_I2C0_PAD_SCK_IN) | ++ BIT_MASK(GPI_I2C0_PAD_SDA_IN) | ++ BIT_MASK(GPI_I2C1_PAD_SCK_IN) | ++ BIT_MASK(GPI_I2C1_PAD_SDA_IN) | ++ BIT_MASK(GPI_I2C2_PAD_SCK_IN) | ++ BIT_MASK(GPI_I2C2_PAD_SDA_IN) | ++ BIT_MASK(GPI_I2C3_PAD_SCK_IN) | ++ BIT_MASK(GPI_I2C3_PAD_SDA_IN) | ++ BIT_MASK(GPI_SDIO0_PAD_CARD_DETECT_N) | ++ ++ BIT_MASK(GPI_SDIO1_PAD_CARD_DETECT_N) | ++ BIT_MASK(GPI_SPI0_PAD_SS_IN_N) | ++ BIT_MASK(GPI_SPI1_PAD_SS_IN_N) | ++ BIT_MASK(GPI_SPI2_PAD_SS_IN_N) | ++ BIT_MASK(GPI_SPI2AHB_PAD_SS_N) | ++ BIT_MASK(GPI_SPI3_PAD_SS_IN_N), ++ ++ BIT_MASK(GPI_UART0_PAD_SIN) | ++ BIT_MASK(GPI_UART1_PAD_SIN) | ++ BIT_MASK(GPI_UART2_PAD_SIN) | ++ BIT_MASK(GPI_UART3_PAD_SIN) | ++ BIT_MASK(GPI_USB_OVER_CURRENT) ++ }; ++ DECLARE_BITMAP(keep, NR_GPIOS) = {}; ++ struct device_node *np = sfp->gc.parent->of_node; ++ int len = of_property_count_u32_elems(np, "starfive,keep-gpiomux"); ++ int i; ++ ++ for (i = 0; i < len; i++) { ++ u32 gpio; ++ ++ of_property_read_u32_index(np, "starfive,keep-gpiomux", i, &gpio); ++ if (gpio < NR_GPIOS) ++ set_bit(gpio, keep); ++ } ++ ++ for (i = 0; i < NR_GPIOS; i++) { ++ if (test_bit(i, keep)) ++ continue; ++ ++ writel_relaxed(GPO_DISABLE, sfp->base + GPON_DOEN_CFG + 8 * i); ++ writel_relaxed(GPO_LOW, sfp->base + GPON_DOUT_CFG + 8 * i); ++ } ++ ++ for (i = 0; i < GPI_END; i++) { ++ void __iomem *reg = sfp->base + GPI_CFG_OFFSET + 4 * i; ++ u32 din = readl_relaxed(reg); ++ ++ if (din >= 2 && din < (NR_GPIOS + 2) && test_bit(din - 2, keep)) ++ continue; ++ ++ writel_relaxed(test_bit(i, defaults), reg); ++ } ++} ++ + static int starfive_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1283,6 +1346,9 @@ static int starfive_probe(struct platfor + writel(value, sfp->padctl + IO_PADSHARE_SEL); + } + ++ if (!keepmux) ++ starfive_pinmux_reset(sfp); ++ + value = readl(sfp->padctl + IO_PADSHARE_SEL); + switch (value) { + case 0: diff --git a/target/linux/starfive/patches-6.1/1010-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch b/target/linux/starfive/patches-6.1/1010-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch new file mode 100644 index 0000000000..a12be8b979 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1010-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch @@ -0,0 +1,302 @@ +From f6c0c8639c7424f915f2f2f18cf86b6b97c7d32a Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 25 Mar 2023 22:57:06 +0100 +Subject: [PATCH 1010/1024] clk: starfive: Add flags argument to JH71X0__MUX + macro + +This flag is needed to add the CLK_SET_RATE_PARENT flag on the gmac_tx +clock on the JH7100, which in turn is needed by the dwmac-starfive +driver to set the clock properly for 1000, 100 and 10 Mbps links. + +This change was mostly made using coccinelle: + +@ match @ +expression idx, name, nparents; +@@ + JH71X0__MUX( +-idx, name, nparents, ++idx, name, 0, nparents, + ...) + +Signed-off-by: Emil Renner Berthing +--- + .../clk/starfive/clk-starfive-jh7100-audio.c | 2 +- + drivers/clk/starfive/clk-starfive-jh7100.c | 32 +++++++++---------- + .../clk/starfive/clk-starfive-jh7110-aon.c | 6 ++-- + .../clk/starfive/clk-starfive-jh7110-isp.c | 2 +- + .../clk/starfive/clk-starfive-jh7110-sys.c | 26 +++++++-------- + drivers/clk/starfive/clk-starfive-jh71x0.h | 4 +-- + 6 files changed, 36 insertions(+), 36 deletions(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c +@@ -80,7 +80,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB), + JH71X0_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB), + JH71X0__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS), +- JH71X0__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2, ++ JH71X0__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 0, 2, + JH7100_AUDCLK_VAD_INTMEM, + JH7100_AUDCLK_AUDIO_12288), + }; +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -24,48 +24,48 @@ + #define JH7100_CLK_GMAC_GR_MII_RX (JH7100_CLK_END + 3) + + static const struct jh71x0_clk_data jh7100_clk_data[] __initconst = { +- JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4, ++ JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 0, 4, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3, ++ JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 0, 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4, ++ JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 0, 4, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3, ++ JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 0, 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2, ++ JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 0, 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT), +- JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2, ++ JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 0, 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3, ++ JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 0, 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3, ++ JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 0, 3, + JH7100_CLK_OSC_AUD, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), + JH71X0_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT), +- JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3, ++ JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 0, 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL1_OUT, + JH7100_CLK_PLL2_OUT), +- JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3, ++ JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 0, 3, + JH7100_CLK_OSC_SYS, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL1_OUT), +- JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3, ++ JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 0, 3, + JH7100_CLK_OSC_AUD, + JH7100_CLK_PLL0_OUT, + JH7100_CLK_PLL2_OUT), +@@ -76,7 +76,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", 0, 31, JH7100_CLK_PERH0_SRC), + JH71X0_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", 0, 31, JH7100_CLK_DLA_ROOT), + JH71X0_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", 0, 31, JH7100_CLK_PERH1_SRC), +- JH71X0__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 2, ++ JH71X0__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 0, 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_OSC_AUD), + JH71X0__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +@@ -142,7 +142,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0__DIV(JH7100_CLK_NOC_COG, "noc_cog", 8, JH7100_CLK_DLA_ROOT), + JH71X0_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", 0, JH7100_CLK_AHB_BUS), + JH71X0__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", 4, JH7100_CLK_DSP_ROOT), +- JH71X0__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 2, ++ JH71X0__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 0, 2, + JH7100_CLK_CPU_AXI, + JH7100_CLK_NNEBUS_SRC1), + JH71X0_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS), +@@ -166,7 +166,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV), + JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32, + JH7100_CLK_USBPHY_ROOTDIV), +- JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2, ++ JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 0, 2, + JH7100_CLK_OSC_SYS, + JH7100_CLK_USBPHY_PLLDIV25M), + JH71X0_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT), +@@ -200,12 +200,12 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV), + JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), + JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), +- JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 3, ++ JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 0, 3, + JH7100_CLK_GMAC_GTX, + JH7100_CLK_GMAC_TX_INV, + JH7100_CLK_GMAC_RMII_TX), + JH71X0__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", JH7100_CLK_GMAC_TX), +- JH71X0__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 2, ++ JH71X0__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 0, 2, + JH7100_CLK_GMAC_GR_MII_RX, + JH7100_CLK_GMAC_RMII_RX), + JH71X0__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE), +--- a/drivers/clk/starfive/clk-starfive-jh7110-aon.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-aon.c +@@ -26,7 +26,7 @@ + static const struct jh71x0_clk_data jh7110_aonclk_data[] = { + /* source */ + JH71X0__DIV(JH7110_AONCLK_OSC_DIV4, "osc_div4", 4, JH7110_AONCLK_OSC), +- JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 2, ++ JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 0, 2, + JH7110_AONCLK_OSC_DIV4, + JH7110_AONCLK_OSC), + /* gmac0 */ +@@ -39,7 +39,7 @@ static const struct jh71x0_clk_data jh71 + JH7110_AONCLK_GMAC0_GTXCLK, + JH7110_AONCLK_GMAC0_RMII_RTX), + JH71X0__INV(JH7110_AONCLK_GMAC0_TX_INV, "gmac0_tx_inv", JH7110_AONCLK_GMAC0_TX), +- JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 2, ++ JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 0, 2, + JH7110_AONCLK_GMAC0_RGMII_RXIN, + JH7110_AONCLK_GMAC0_RMII_RTX), + JH71X0__INV(JH7110_AONCLK_GMAC0_RX_INV, "gmac0_rx_inv", JH7110_AONCLK_GMAC0_RX), +@@ -48,7 +48,7 @@ static const struct jh71x0_clk_data jh71 + /* rtc */ + JH71X0_GATE(JH7110_AONCLK_RTC_APB, "rtc_apb", 0, JH7110_AONCLK_APB_BUS), + JH71X0__DIV(JH7110_AONCLK_RTC_INTERNAL, "rtc_internal", 1022, JH7110_AONCLK_OSC), +- JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 2, ++ JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 0, 2, + JH7110_AONCLK_RTC_OSC, + JH7110_AONCLK_RTC_INTERNAL), + JH71X0_GATE(JH7110_AONCLK_RTC_CAL, "rtc_cal", 0, JH7110_AONCLK_OSC), +--- a/drivers/clk/starfive/clk-starfive-jh7110-isp.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c +@@ -53,7 +53,7 @@ static const struct jh71x0_clk_data jh71 + JH7110_ISPCLK_MIPI_RX0_PXL), + JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF3, "vin_pixel_if3", 0, + JH7110_ISPCLK_MIPI_RX0_PXL), +- JH71X0__MUX(JH7110_ISPCLK_VIN_P_AXI_WR, "vin_p_axi_wr", 2, ++ JH71X0__MUX(JH7110_ISPCLK_VIN_P_AXI_WR, "vin_p_axi_wr", 0, 2, + JH7110_ISPCLK_MIPI_RX0_PXL, + JH7110_ISPCLK_DVP_INV), + /* ispv2_top_wrapper */ +--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c +@@ -36,18 +36,18 @@ + + static const struct jh71x0_clk_data jh7110_sysclk_data[] __initconst = { + /* root */ +- JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 2, ++ JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 0, 2, + JH7110_SYSCLK_OSC, + JH7110_SYSCLK_PLL0_OUT), + JH71X0__DIV(JH7110_SYSCLK_CPU_CORE, "cpu_core", 7, JH7110_SYSCLK_CPU_ROOT), + JH71X0__DIV(JH7110_SYSCLK_CPU_BUS, "cpu_bus", 2, JH7110_SYSCLK_CPU_CORE), +- JH71X0__MUX(JH7110_SYSCLK_GPU_ROOT, "gpu_root", 2, ++ JH71X0__MUX(JH7110_SYSCLK_GPU_ROOT, "gpu_root", 0, 2, + JH7110_SYSCLK_PLL2_OUT, + JH7110_SYSCLK_PLL1_OUT), + JH71X0_MDIV(JH7110_SYSCLK_PERH_ROOT, "perh_root", 2, 2, + JH7110_SYSCLK_PLL0_OUT, + JH7110_SYSCLK_PLL2_OUT), +- JH71X0__MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", 2, ++ JH71X0__MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", 0, 2, + JH7110_SYSCLK_OSC, + JH7110_SYSCLK_PLL2_OUT), + JH71X0__DIV(JH7110_SYSCLK_NOCSTG_BUS, "nocstg_bus", 3, JH7110_SYSCLK_BUS_ROOT), +@@ -62,7 +62,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0__DIV(JH7110_SYSCLK_PLL2_DIV2, "pll2_div2", 2, JH7110_SYSCLK_PLL2_OUT), + JH71X0__DIV(JH7110_SYSCLK_AUDIO_ROOT, "audio_root", 8, JH7110_SYSCLK_PLL2_OUT), + JH71X0__DIV(JH7110_SYSCLK_MCLK_INNER, "mclk_inner", 64, JH7110_SYSCLK_AUDIO_ROOT), +- JH71X0__MUX(JH7110_SYSCLK_MCLK, "mclk", 2, ++ JH71X0__MUX(JH7110_SYSCLK_MCLK, "mclk", 0, 2, + JH7110_SYSCLK_MCLK_INNER, + JH7110_SYSCLK_MCLK_EXT), + JH71X0_GATE(JH7110_SYSCLK_MCLK_OUT, "mclk_out", 0, JH7110_SYSCLK_MCLK_INNER), +@@ -96,7 +96,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0__DIV(JH7110_SYSCLK_OSC_DIV2, "osc_div2", 2, JH7110_SYSCLK_OSC), + JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV4, "pll1_div4", 2, JH7110_SYSCLK_PLL1_DIV2), + JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV8, "pll1_div8", 2, JH7110_SYSCLK_PLL1_DIV4), +- JH71X0__MUX(JH7110_SYSCLK_DDR_BUS, "ddr_bus", 4, ++ JH71X0__MUX(JH7110_SYSCLK_DDR_BUS, "ddr_bus", 0, 4, + JH7110_SYSCLK_OSC_DIV2, + JH7110_SYSCLK_PLL1_DIV2, + JH7110_SYSCLK_PLL1_DIV4, +@@ -186,7 +186,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0__DIV(JH7110_SYSCLK_GMAC1_RMII_RTX, "gmac1_rmii_rtx", 30, + JH7110_SYSCLK_GMAC1_RMII_REFIN), + JH71X0_GDIV(JH7110_SYSCLK_GMAC1_PTP, "gmac1_ptp", 0, 31, JH7110_SYSCLK_GMAC_SRC), +- JH71X0__MUX(JH7110_SYSCLK_GMAC1_RX, "gmac1_rx", 2, ++ JH71X0__MUX(JH7110_SYSCLK_GMAC1_RX, "gmac1_rx", 0, 2, + JH7110_SYSCLK_GMAC1_RGMII_RXIN, + JH7110_SYSCLK_GMAC1_RMII_RTX), + JH71X0__INV(JH7110_SYSCLK_GMAC1_RX_INV, "gmac1_rx_inv", JH7110_SYSCLK_GMAC1_RX), +@@ -270,11 +270,11 @@ static const struct jh71x0_clk_data jh71 + JH71X0_MDIV(JH7110_SYSCLK_I2STX0_LRCK_MST, "i2stx0_lrck_mst", 64, 2, + JH7110_SYSCLK_I2STX0_BCLK_MST_INV, + JH7110_SYSCLK_I2STX0_BCLK_MST), +- JH71X0__MUX(JH7110_SYSCLK_I2STX0_BCLK, "i2stx0_bclk", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2STX0_BCLK, "i2stx0_bclk", 0, 2, + JH7110_SYSCLK_I2STX0_BCLK_MST, + JH7110_SYSCLK_I2STX_BCLK_EXT), + JH71X0__INV(JH7110_SYSCLK_I2STX0_BCLK_INV, "i2stx0_bclk_inv", JH7110_SYSCLK_I2STX0_BCLK), +- JH71X0__MUX(JH7110_SYSCLK_I2STX0_LRCK, "i2stx0_lrck", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2STX0_LRCK, "i2stx0_lrck", 0, 2, + JH7110_SYSCLK_I2STX0_LRCK_MST, + JH7110_SYSCLK_I2STX_LRCK_EXT), + /* i2stx1 */ +@@ -285,11 +285,11 @@ static const struct jh71x0_clk_data jh71 + JH71X0_MDIV(JH7110_SYSCLK_I2STX1_LRCK_MST, "i2stx1_lrck_mst", 64, 2, + JH7110_SYSCLK_I2STX1_BCLK_MST_INV, + JH7110_SYSCLK_I2STX1_BCLK_MST), +- JH71X0__MUX(JH7110_SYSCLK_I2STX1_BCLK, "i2stx1_bclk", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2STX1_BCLK, "i2stx1_bclk", 0, 2, + JH7110_SYSCLK_I2STX1_BCLK_MST, + JH7110_SYSCLK_I2STX_BCLK_EXT), + JH71X0__INV(JH7110_SYSCLK_I2STX1_BCLK_INV, "i2stx1_bclk_inv", JH7110_SYSCLK_I2STX1_BCLK), +- JH71X0__MUX(JH7110_SYSCLK_I2STX1_LRCK, "i2stx1_lrck", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2STX1_LRCK, "i2stx1_lrck", 0, 2, + JH7110_SYSCLK_I2STX1_LRCK_MST, + JH7110_SYSCLK_I2STX_LRCK_EXT), + /* i2srx */ +@@ -300,11 +300,11 @@ static const struct jh71x0_clk_data jh71 + JH71X0_MDIV(JH7110_SYSCLK_I2SRX_LRCK_MST, "i2srx_lrck_mst", 64, 2, + JH7110_SYSCLK_I2SRX_BCLK_MST_INV, + JH7110_SYSCLK_I2SRX_BCLK_MST), +- JH71X0__MUX(JH7110_SYSCLK_I2SRX_BCLK, "i2srx_bclk", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2SRX_BCLK, "i2srx_bclk", 0, 2, + JH7110_SYSCLK_I2SRX_BCLK_MST, + JH7110_SYSCLK_I2SRX_BCLK_EXT), + JH71X0__INV(JH7110_SYSCLK_I2SRX_BCLK_INV, "i2srx_bclk_inv", JH7110_SYSCLK_I2SRX_BCLK), +- JH71X0__MUX(JH7110_SYSCLK_I2SRX_LRCK, "i2srx_lrck", 2, ++ JH71X0__MUX(JH7110_SYSCLK_I2SRX_LRCK, "i2srx_lrck", 0, 2, + JH7110_SYSCLK_I2SRX_LRCK_MST, + JH7110_SYSCLK_I2SRX_LRCK_EXT), + /* pdm */ +@@ -314,7 +314,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GATE(JH7110_SYSCLK_TDM_AHB, "tdm_ahb", 0, JH7110_SYSCLK_AHB0), + JH71X0_GATE(JH7110_SYSCLK_TDM_APB, "tdm_apb", 0, JH7110_SYSCLK_APB0), + JH71X0_GDIV(JH7110_SYSCLK_TDM_INTERNAL, "tdm_internal", 0, 64, JH7110_SYSCLK_MCLK), +- JH71X0__MUX(JH7110_SYSCLK_TDM_TDM, "tdm_tdm", 2, ++ JH71X0__MUX(JH7110_SYSCLK_TDM_TDM, "tdm_tdm", 0, 2, + JH7110_SYSCLK_TDM_INTERNAL, + JH7110_SYSCLK_TDM_EXT), + JH71X0__INV(JH7110_SYSCLK_TDM_TDM_INV, "tdm_tdm_inv", JH7110_SYSCLK_TDM_TDM), +--- a/drivers/clk/starfive/clk-starfive-jh71x0.h ++++ b/drivers/clk/starfive/clk-starfive-jh71x0.h +@@ -61,10 +61,10 @@ struct jh71x0_clk_data { + .parents = { [0] = _parent }, \ + } + +-#define JH71X0__MUX(_idx, _name, _nparents, ...) \ ++#define JH71X0__MUX(_idx, _name, _flags, _nparents, ...) \ + [_idx] = { \ + .name = _name, \ +- .flags = 0, \ ++ .flags = _flags, \ + .max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT, \ + .parents = { __VA_ARGS__ }, \ + } diff --git a/target/linux/starfive/patches-6.1/1011-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch b/target/linux/starfive/patches-6.1/1011-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch new file mode 100644 index 0000000000..e5e750820e --- /dev/null +++ b/target/linux/starfive/patches-6.1/1011-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch @@ -0,0 +1,25 @@ +From 38d50c243d2d4176b88ad732f4948cca9629251b Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 25 Mar 2023 23:04:31 +0100 +Subject: [PATCH 1011/1024] clk: starfive: jh7100: Add CLK_SET_RATE_PARENT to + gmac_tx + +This is needed by the dwmac-starfive ethernet driver to set the clock +for 1000, 100 and 10 Mbps links properly. + +Signed-off-by: Emil Renner Berthing +--- + drivers/clk/starfive/clk-starfive-jh7100.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -200,7 +200,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV), + JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), + JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), +- JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 0, 3, ++ JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 3, + JH7100_CLK_GMAC_GTX, + JH7100_CLK_GMAC_TX_INV, + JH7100_CLK_GMAC_RMII_TX), diff --git a/target/linux/starfive/patches-6.1/1012-clk-starfive-jh7100-Keep-more-clocks-alive.patch b/target/linux/starfive/patches-6.1/1012-clk-starfive-jh7100-Keep-more-clocks-alive.patch new file mode 100644 index 0000000000..3afdf1d9a6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1012-clk-starfive-jh7100-Keep-more-clocks-alive.patch @@ -0,0 +1,94 @@ +From 3e73731c113fbe6f319403d5e2e64a656fcb17ce Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Thu, 14 Oct 2021 20:35:43 +0200 +Subject: [PATCH 1012/1024] clk: starfive: jh7100: Keep more clocks alive + +Signed-off-by: Emil Renner Berthing +--- + drivers/clk/starfive/clk-starfive-jh7100.c | 37 +++++++++++----------- + 1 file changed, 19 insertions(+), 18 deletions(-) + +--- a/drivers/clk/starfive/clk-starfive-jh7100.c ++++ b/drivers/clk/starfive/clk-starfive-jh7100.c +@@ -94,9 +94,9 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI), + JH71X0_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS), + JH71X0__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT), +- JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS), +- JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS), +- JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS), ++ JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS), ++ JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", CLK_IGNORE_UNUSED, JH7100_CLK_APB1_BUS), + JH71X0_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV), + JH71X0__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT), + JH71X0_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC), +@@ -160,11 +160,12 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS), + JH71X0_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", CLK_IS_CRITICAL, 8, JH7100_CLK_CPUNBUS_ROOT_DIV), + JH71X0__DIV(JH7100_CLK_USB_BUS, "usb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV), +- JH71X0_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS), +- JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS), ++ JH71X0_GATE(JH7100_CLK_USB_AXI, "usb_axi", CLK_IGNORE_UNUSED, JH7100_CLK_USB_BUS), ++ JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_USB_BUS), + JH71X0__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT), +- JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV), +- JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32, ++ JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", CLK_IGNORE_UNUSED, 8, ++ JH7100_CLK_USBPHY_ROOTDIV), ++ JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", CLK_IGNORE_UNUSED, 32, + JH7100_CLK_USBPHY_ROOTDIV), + JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 0, 2, + JH7100_CLK_OSC_SYS, +@@ -183,23 +184,23 @@ static const struct jh71x0_clk_data jh71 + JH71X0__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC), + JH71X0_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS), + JH71X0_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS), +- JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT), ++ JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", CLK_IGNORE_UNUSED, 4, JH7100_CLK_VOUT_ROOT), + JH71X0__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT), + JH71X0__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC), +- JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS), +- JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS), ++ JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DISP_BUS), ++ JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DISP_BUS), + JH71X0_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS), + JH71X0_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC), + JH71X0__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT), + JH71X0_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", 0, JH7100_CLK_AHB_BUS), + JH71X0_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", 0, 24, JH7100_CLK_PERH1_SRC), + JH71X0__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", JH7100_CLK_SDIO1_CCLKINT), +- JH71X0_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", 0, JH7100_CLK_AHB_BUS), ++ JH71X0_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", CLK_IGNORE_UNUSED, JH7100_CLK_AHB_BUS), + JH71X0__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", 8, JH7100_CLK_GMACUSB_ROOT), +- JH71X0_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", 0, 31, JH7100_CLK_GMAC_ROOT_DIV), +- JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV), +- JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), +- JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", CLK_IGNORE_UNUSED, 31, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", CLK_IGNORE_UNUSED, 255, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", CLK_IGNORE_UNUSED, 8, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", CLK_IGNORE_UNUSED, 8, JH7100_CLK_GMAC_RMII_REF), + JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 3, + JH7100_CLK_GMAC_GTX, + JH7100_CLK_GMAC_TX_INV, +@@ -209,8 +210,8 @@ static const struct jh71x0_clk_data jh71 + JH7100_CLK_GMAC_GR_MII_RX, + JH7100_CLK_GMAC_RMII_RX), + JH71X0__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE), +- JH71X0_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", 0, JH7100_CLK_GMAC_RMII_REF), +- JH71X0_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", 0, 127, JH7100_CLK_GMAC_ROOT_DIV), ++ JH71X0_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", CLK_IGNORE_UNUSED, JH7100_CLK_GMAC_RMII_REF), ++ JH71X0_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", CLK_IGNORE_UNUSED, 127, JH7100_CLK_GMAC_ROOT_DIV), + JH71X0_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", 0, JH7100_CLK_AHB_BUS), + JH71X0_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", 0, 31, JH7100_CLK_PERH0_SRC), + JH71X0_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", 0, JH7100_CLK_AHB_BUS), +@@ -223,7 +224,7 @@ static const struct jh71x0_clk_data jh71 + JH71X0_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB), + JH71X0_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB), + JH71X0_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB), +- JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS), ++ JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", CLK_IGNORE_UNUSED, JH7100_CLK_APB1_BUS), + JH71X0_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS), + JH71X0_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS), + JH71X0_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC), diff --git a/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch b/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch new file mode 100644 index 0000000000..a341c96bcf --- /dev/null +++ b/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch @@ -0,0 +1,30 @@ +From 1889527687432bd63942c86dbebf8686b6515aad Mon Sep 17 00:00:00 2001 +From: Matteo Croce +Date: Fri, 21 May 2021 03:26:38 +0200 +Subject: [PATCH 1013/1024] net: stmmac: use GFP_DMA32 + +Signed-off-by: Matteo Croce +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1436,7 +1436,7 @@ static int stmmac_init_rx_buffers(struct + { + struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue]; + struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; +- gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); ++ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32); + + if (priv->dma_cap.host_dma_width <= 32) + gfp |= GFP_DMA32; +@@ -4613,7 +4613,7 @@ static inline void stmmac_rx_refill(stru + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; + int dirty = stmmac_rx_dirty(priv, queue); + unsigned int entry = rx_q->dirty_rx; +- gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); ++ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32); + + if (priv->dma_cap.host_dma_width <= 32) + gfp |= GFP_DMA32; diff --git a/target/linux/starfive/patches-6.1/1014-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch b/target/linux/starfive/patches-6.1/1014-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch new file mode 100644 index 0000000000..86d3b1d839 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1014-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch @@ -0,0 +1,477 @@ +From 919bcebc58044a266e953ac302c8e068e255e2a6 Mon Sep 17 00:00:00 2001 +From: Huan Feng +Date: Fri, 8 Jan 2021 03:35:42 +0800 +Subject: [PATCH 1014/1024] hwrng: Add StarFive JH7100 Random Number Generator + driver + +Signed-off-by: Emil Renner Berthing +--- + drivers/char/hw_random/Kconfig | 13 ++ + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/starfive-vic-rng.c | 256 ++++++++++++++++++++++ + drivers/char/hw_random/starfive-vic-rng.h | 167 ++++++++++++++ + 4 files changed, 437 insertions(+) + create mode 100644 drivers/char/hw_random/starfive-vic-rng.c + create mode 100644 drivers/char/hw_random/starfive-vic-rng.h + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -322,6 +322,19 @@ config HW_RANDOM_POWERNV + + If unsure, say Y. + ++config HW_RANDOM_STARFIVE_VIC ++ tristate "Starfive VIC Random Number Generator support" ++ depends on HW_RANDOM && (SOC_STARFIVE || COMPILE_TEST) ++ default SOC_STARFIVE ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Starfive VIC SoC. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called starfive-vic-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_HISI + tristate "Hisilicon Random Number Generator support" + depends on HW_RANDOM && ARCH_HISI +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon + obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o + obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o + obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o ++obj-$(CONFIG_HW_RANDOM_STARFIVE_VIC) += starfive-vic-rng.o + obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o + obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o + obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o +--- /dev/null ++++ b/drivers/char/hw_random/starfive-vic-rng.c +@@ -0,0 +1,256 @@ ++/* ++ ****************************************************************************** ++ * @file starfive-vic-rng.c ++ * @author StarFive Technology ++ * @version V1.0 ++ * @date 08/13/2020 ++ * @brief ++ ****************************************************************************** ++ * @copy ++ * ++ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS ++ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE ++ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY ++ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING ++ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE ++ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. ++ * ++ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "starfive-vic-rng.h" ++ ++#define to_vic_rng(p) container_of(p, struct vic_rng, rng) ++ ++struct vic_rng { ++ struct device *dev; ++ void __iomem *base; ++ struct hwrng rng; ++}; ++ ++static inline void vic_wait_till_idle(struct vic_rng *hrng) ++{ ++ while(readl(hrng->base + VIC_STAT) & VIC_STAT_BUSY) ++ ; ++} ++ ++static inline void vic_rng_irq_mask_clear(struct vic_rng *hrng) ++{ ++ // clear register: ISTAT ++ u32 data = readl(hrng->base + VIC_ISTAT); ++ writel(data, hrng->base + VIC_ISTAT); ++ writel(0, hrng->base + VIC_ALARM); ++} ++ ++static int vic_trng_cmd(struct vic_rng *hrng, u32 cmd) { ++ int res = 0; ++ // wait till idle ++ vic_wait_till_idle(hrng); ++ switch (cmd) { ++ case VIC_CTRL_CMD_NOP: ++ case VIC_CTRL_CMD_GEN_NOISE: ++ case VIC_CTRL_CMD_GEN_NONCE: ++ case VIC_CTRL_CMD_CREATE_STATE: ++ case VIC_CTRL_CMD_RENEW_STATE: ++ case VIC_CTRL_CMD_REFRESH_ADDIN: ++ case VIC_CTRL_CMD_GEN_RANDOM: ++ case VIC_CTRL_CMD_ADVANCE_STATE: ++ case VIC_CTRL_CMD_KAT: ++ case VIC_CTRL_CMD_ZEROIZE: ++ writel(cmd, hrng->base + VIC_CTRL); ++ break; ++ default: ++ res = -1; ++ break; ++ } ++ ++ return res; ++} ++ ++static int vic_rng_init(struct hwrng *rng) ++{ ++ struct vic_rng *hrng = to_vic_rng(rng); ++ ++ // wait till idle ++ ++ // clear register: ISTAT ++ vic_rng_irq_mask_clear(hrng); ++ ++ // set mission mode ++ writel(VIC_SMODE_SECURE_EN(1), hrng->base + VIC_SMODE); ++ ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE); ++ vic_wait_till_idle(hrng); ++ ++ // set interrupt ++ writel(VIC_IE_ALL, hrng->base + VIC_IE); ++ ++ // zeroize ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); ++ ++ vic_wait_till_idle(hrng); ++ ++ return 0; ++} ++ ++static irqreturn_t vic_rng_irq(int irq, void *priv) ++{ ++ u32 status, val; ++ struct vic_rng *hrng = (struct vic_rng *)priv; ++ ++ /* ++ * clearing the interrupt will also clear the error register ++ * read error and status before clearing ++ */ ++ status = readl(hrng->base + VIC_ISTAT); ++ ++ if (status & VIC_ISTAT_ALARMS) { ++ writel(VIC_ISTAT_ALARMS, hrng->base + VIC_ISTAT); ++ val = readl(hrng->base + VIC_ALARM); ++ if (val & VIC_ALARM_ILLEGAL_CMD_SEQ) { ++ writel(VIC_ALARM_ILLEGAL_CMD_SEQ, hrng->base + VIC_ALARM); ++ //dev_info(hrng->dev, "ILLEGAL CMD SEQ: LAST_CMD=0x%x\r\n", ++ //VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT))); ++ } else { ++ dev_info(hrng->dev, "Failed test: %x\r\n", val); ++ } ++ } ++ ++ if (status & VIC_ISTAT_ZEROIZE) { ++ writel(VIC_ISTAT_ZEROIZE, hrng->base + VIC_ISTAT); ++ //dev_info(hrng->dev, "zeroized\r\n"); ++ } ++ ++ if (status & VIC_ISTAT_KAT_COMPLETE) { ++ writel(VIC_ISTAT_KAT_COMPLETE, hrng->base + VIC_ISTAT); ++ //dev_info(hrng->dev, "kat_completed\r\n"); ++ } ++ ++ if (status & VIC_ISTAT_NOISE_RDY) { ++ writel(VIC_ISTAT_NOISE_RDY, hrng->base + VIC_ISTAT); ++ //dev_info(hrng->dev, "noise_rdy\r\n"); ++ } ++ ++ if (status & VIC_ISTAT_DONE) { ++ writel(VIC_ISTAT_DONE, hrng->base + VIC_ISTAT); ++ //dev_info(hrng->dev, "done\r\n"); ++ /* ++ if (VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT)) == ++ VIC_CTRL_CMD_GEN_RANDOM) { ++ dev_info(hrng->dev, "Need Update Buffer\r\n"); ++ } ++ */ ++ } ++ vic_rng_irq_mask_clear(hrng); ++ ++ return IRQ_HANDLED; ++} ++ ++static void vic_rng_cleanup(struct hwrng *rng) ++{ ++ struct vic_rng *hrng = to_vic_rng(rng); ++ ++ writel(0, hrng->base + VIC_CTRL); ++} ++ ++static int vic_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct vic_rng *hrng = to_vic_rng(rng); ++ ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE); ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_CREATE_STATE); ++ ++ vic_wait_till_idle(hrng); ++ max = min_t(size_t, max, (VIC_RAND_LEN * 4)); ++ ++ writel(0x0, hrng->base + VIC_MODE); ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_RANDOM); ++ ++ vic_wait_till_idle(hrng); ++ memcpy_fromio(buf, hrng->base + VIC_RAND0, max); ++ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); ++ ++ vic_wait_till_idle(hrng); ++ return max; ++} ++ ++static int vic_rng_probe(struct platform_device *pdev) ++{ ++ int ret; ++ int irq; ++ struct vic_rng *rng; ++ struct resource *res; ++ ++ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); ++ if (!rng){ ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, rng); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rng->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rng->base)){ ++ return PTR_ERR(rng->base); ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(&pdev->dev, "Couldn't get irq %d\n", irq); ++ return irq; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, irq, vic_rng_irq, 0, pdev->name, ++ (void *)rng); ++ if (ret) { ++ dev_err(&pdev->dev, "Can't get interrupt working.\n"); ++ return ret; ++ } ++ ++ rng->rng.name = pdev->name; ++ rng->rng.init = vic_rng_init; ++ rng->rng.cleanup = vic_rng_cleanup; ++ rng->rng.read = vic_rng_read; ++ ++ rng->dev = &pdev->dev; ++ ++ ret = devm_hwrng_register(&pdev->dev, &rng->rng); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register hwrng\n"); ++ return ret; ++ } ++ ++ dev_info(&pdev->dev, "Initialized\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id vic_rng_dt_ids[] = { ++ { .compatible = "starfive,vic-rng" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, vic_rng_dt_ids); ++ ++static struct platform_driver vic_rng_driver = { ++ .probe = vic_rng_probe, ++ .driver = { ++ .name = "vic-rng", ++ .of_match_table = vic_rng_dt_ids, ++ }, ++}; ++ ++module_platform_driver(vic_rng_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Huan Feng "); ++MODULE_DESCRIPTION("Starfive VIC random number generator driver"); +--- /dev/null ++++ b/drivers/char/hw_random/starfive-vic-rng.h +@@ -0,0 +1,167 @@ ++/* ++ ****************************************************************************** ++ * @file starfive-vic-rng.h ++ * @author StarFive Technology ++ * @version V1.0 ++ * @date 08/13/2020 ++ * @brief ++ ****************************************************************************** ++ * @copy ++ * ++ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS ++ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE ++ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY ++ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING ++ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE ++ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. ++ * ++ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd. ++ */ ++ ++#define VIC_CTRL 0x00 ++#define VIC_MODE 0x04 ++#define VIC_SMODE 0x08 ++#define VIC_STAT 0x0C ++#define VIC_IE 0x10 ++#define VIC_ISTAT 0x14 ++#define VIC_ALARM 0x18 ++#define VIC_BUILD_ID 0x1C ++#define VIC_FEATURES 0x20 ++#define VIC_RAND0 0x24 ++#define VIC_NPA_DATA0 0x34 ++#define VIC_SEED0 0x74 ++#define VIC_IA_RDATA 0xA4 ++#define VIC_IA_WDATA 0xA8 ++#define VIC_IA_ADDR 0xAC ++#define VIC_IA_CMD 0xB0 ++ ++/* CTRL */ ++#define VIC_CTRL_CMD_NOP 0 ++#define VIC_CTRL_CMD_GEN_NOISE 1 ++#define VIC_CTRL_CMD_GEN_NONCE 2 ++#define VIC_CTRL_CMD_CREATE_STATE 3 ++#define VIC_CTRL_CMD_RENEW_STATE 4 ++#define VIC_CTRL_CMD_REFRESH_ADDIN 5 ++#define VIC_CTRL_CMD_GEN_RANDOM 6 ++#define VIC_CTRL_CMD_ADVANCE_STATE 7 ++#define VIC_CTRL_CMD_KAT 8 ++#define VIC_CTRL_CMD_ZEROIZE 15 ++ ++/* MODE */ ++#define _VIC_MODE_ADDIN_PRESENT 4 ++#define _VIC_MODE_PRED_RESIST 3 ++#define _VIC_MODE_KAT_SEL 2 ++#define _VIC_MODE_KAT_VEC 1 ++#define _VIC_MODE_SEC_ALG 0 ++ ++#define VIC_MODE_ADDIN_PRESENT (1UL << _VIC_MODE_ADDIN_PRESENT) ++#define VIC_MODE_PRED_RESIST (1UL << _VIC_MODE_PRED_RESIST) ++#define VIC_MODE_KAT_SEL (1UL << _VIC_MODE_KAT_SEL) ++#define VIC_MODE_KAT_VEC (1UL << _VIC_MODE_KAT_VEC) ++#define VIC_MODE_SEC_ALG (1UL << _VIC_MODE_SEC_ALG) ++ ++/* SMODE */ ++#define _VIC_SMODE_MAX_REJECTS 2 ++#define _VIC_SMODE_SECURE_EN 1 ++#define _VIC_SMODE_NONCE 0 ++ ++#define VIC_SMODE_MAX_REJECTS(x) ((x) << _VIC_SMODE_MAX_REJECTS) ++#define VIC_SMODE_SECURE_EN(x) ((x) << _VIC_SMODE_SECURE_EN) ++#define VIC_SMODE_NONCE (1UL << _VIC_SMODE_NONCE) ++ ++/* STAT */ ++#define _VIC_STAT_BUSY 31 ++#define _VIC_STAT_DRBG_STATE 7 ++#define _VIC_STAT_SECURE 6 ++#define _VIC_STAT_NONCE_MODE 5 ++#define _VIC_STAT_SEC_ALG 4 ++#define _VIC_STAT_LAST_CMD 0 ++ ++#define VIC_STAT_BUSY (1UL << _VIC_STAT_BUSY) ++#define VIC_STAT_DRBG_STATE (1UL << _VIC_STAT_DRBG_STATE) ++#define VIC_STAT_SECURE (1UL << _VIC_STAT_SECURE) ++#define VIC_STAT_NONCE_MODE (1UL << _VIC_STAT_NONCE_MODE) ++#define VIC_STAT_SEC_ALG (1UL << _VIC_STAT_SEC_ALG) ++#define VIC_STAT_LAST_CMD(x) (((x) >> _VIC_STAT_LAST_CMD) & 0xF) ++ ++/* IE */ ++#define _VIC_IE_GLBL 31 ++#define _VIC_IE_DONE 4 ++#define _VIC_IE_ALARMS 3 ++#define _VIC_IE_NOISE_RDY 2 ++#define _VIC_IE_KAT_COMPLETE 1 ++#define _VIC_IE_ZEROIZE 0 ++ ++#define VIC_IE_GLBL (1UL << _VIC_IE_GLBL) ++#define VIC_IE_DONE (1UL << _VIC_IE_DONE) ++#define VIC_IE_ALARMS (1UL << _VIC_IE_ALARMS) ++#define VIC_IE_NOISE_RDY (1UL << _VIC_IE_NOISE_RDY) ++#define VIC_IE_KAT_COMPLETE (1UL << _VIC_IE_KAT_COMPLETE) ++#define VIC_IE_ZEROIZE (1UL << _VIC_IE_ZEROIZE) ++#define VIC_IE_ALL (VIC_IE_GLBL | VIC_IE_DONE | VIC_IE_ALARMS | \ ++ VIC_IE_NOISE_RDY | VIC_IE_KAT_COMPLETE | VIC_IE_ZEROIZE) ++ ++/* ISTAT */ ++#define _VIC_ISTAT_DONE 4 ++#define _VIC_ISTAT_ALARMS 3 ++#define _VIC_ISTAT_NOISE_RDY 2 ++#define _VIC_ISTAT_KAT_COMPLETE 1 ++#define _VIC_ISTAT_ZEROIZE 0 ++ ++#define VIC_ISTAT_DONE (1UL << _VIC_ISTAT_DONE) ++#define VIC_ISTAT_ALARMS (1UL << _VIC_ISTAT_ALARMS) ++#define VIC_ISTAT_NOISE_RDY (1UL << _VIC_ISTAT_NOISE_RDY) ++#define VIC_ISTAT_KAT_COMPLETE (1UL << _VIC_ISTAT_KAT_COMPLETE) ++#define VIC_ISTAT_ZEROIZE (1UL << _VIC_ISTAT_ZEROIZE) ++ ++/* ALARMS */ ++#define VIC_ALARM_ILLEGAL_CMD_SEQ (1UL << 4) ++#define VIC_ALARM_FAILED_TEST_ID_OK 0 ++#define VIC_ALARM_FAILED_TEST_ID_KAT_STAT 1 ++#define VIC_ALARM_FAILED_TEST_ID_KAT 2 ++#define VIC_ALARM_FAILED_TEST_ID_MONOBIT 3 ++#define VIC_ALARM_FAILED_TEST_ID_RUN 4 ++#define VIC_ALARM_FAILED_TEST_ID_LONGRUN 5 ++#define VIC_ALARM_FAILED_TEST_ID_AUTOCORRELATION 6 ++#define VIC_ALARM_FAILED_TEST_ID_POKER 7 ++#define VIC_ALARM_FAILED_TEST_ID_REPETITION_COUNT 8 ++#define VIC_ALARM_FAILED_TEST_ID_ADAPATIVE_PROPORTION 9 ++ ++/* BUILD_ID */ ++#define VIC_BUILD_ID_STEPPING(x) (((x) >> 28) & 0xF) ++#define VIC_BUILD_ID_EPN(x) ((x) & 0xFFFF) ++ ++/* FEATURES */ ++#define VIC_FEATURES_AES_256(x) (((x) >> 9) & 1) ++#define VIC_FEATURES_EXTRA_PS_PRESENT(x) (((x) >> 8) & 1) ++#define VIC_FEATURES_DIAG_LEVEL_NS(x) (((x) >> 7) & 1) ++#define VIC_FEATURES_DIAG_LEVEL_CLP800(x) (((x) >> 4) & 7) ++#define VIC_FEATURES_DIAG_LEVEL_ST_HLT(x) (((x) >> 1) & 7) ++#define VIC_FEATURES_SECURE_RST_STATE(x) ((x) & 1) ++ ++/* IA_CMD */ ++#define VIC_IA_CMD_GO (1UL << 31) ++#define VIC_IA_CMD_WR (1) ++ ++#define _VIC_SMODE_MAX_REJECTS_MASK 255UL ++#define _VIC_SMODE_SECURE_EN_MASK 1UL ++#define _VIC_SMODE_NONCE_MASK 1UL ++#define _VIC_MODE_SEC_ALG_MASK 1UL ++#define _VIC_MODE_ADDIN_PRESENT_MASK 1UL ++#define _VIC_MODE_PRED_RESIST_MASK 1UL ++ ++#define VIC_SMODE_SET_MAX_REJECTS(y, x) (((y) & ~(_VIC_SMODE_MAX_REJECTS_MASK << _VIC_SMODE_MAX_REJECTS)) | ((x) << _VIC_SMODE_MAX_REJECTS)) ++#define VIC_SMODE_SET_SECURE_EN(y, x) (((y) & ~(_VIC_SMODE_SECURE_EN_MASK << _VIC_SMODE_SECURE_EN)) | ((x) << _VIC_SMODE_SECURE_EN)) ++#define VIC_SMODE_SET_NONCE(y, x) (((y) & ~(_VIC_SMODE_NONCE_MASK << _VIC_SMODE_NONCE)) | ((x) << _VIC_SMODE_NONCE)) ++#define VIC_SMODE_GET_MAX_REJECTS(x) (((x) >> _VIC_SMODE_MAX_REJECTS) & _VIC_SMODE_MAX_REJECTS_MASK) ++#define VIC_SMODE_GET_SECURE_EN(x) (((x) >> _VIC_SMODE_SECURE_EN) & _VIC_SMODE_SECURE_EN_MASK) ++#define VIC_SMODE_GET_NONCE(x) (((x) >> _VIC_SMODE_NONCE) & _VIC_SMODE_NONCE_MASK) ++ ++#define VIC_MODE_SET_SEC_ALG(y, x) (((y) & ~(_VIC_MODE_SEC_ALG_MASK << _VIC_MODE_SEC_ALG)) | ((x) << _VIC_MODE_SEC_ALG)) ++#define VIC_MODE_SET_PRED_RESIST(y, x) (((y) & ~(_VIC_MODE_PRED_RESIST_MASK << _VIC_MODE_PRED_RESIST)) | ((x) << _VIC_MODE_PRED_RESIST)) ++#define VIC_MODE_SET_ADDIN_PRESENT(y, x) (((y) & ~(_VIC_MODE_ADDIN_PRESENT_MASK << _VIC_MODE_ADDIN_PRESENT)) | ((x) << _VIC_MODE_ADDIN_PRESENT)) ++#define VIC_MODE_GET_SEC_ALG(x) (((x) >> _VIC_MODE_SEC_ALG) & _VIC_MODE_SEC_ALG_MASK) ++#define VIC_MODE_GET_PRED_RESIST(x) (((x) >> _VIC_MODE_PRED_RESIST) & _VIC_MODE_PRED_RESIST_MASK) ++#define VIC_MODE_GET_ADDIN_PRESENT(x) (((x) >> _VIC_MODE_ADDIN_PRESENT) & _VIC_MODE_ADDIN_PRESENT_MASK) ++ ++#define VIC_RAND_LEN 4 diff --git a/target/linux/starfive/patches-6.1/1015-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch b/target/linux/starfive/patches-6.1/1015-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch new file mode 100644 index 0000000000..7f47f31fc2 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1015-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch @@ -0,0 +1,309 @@ +From 8b3a02992094b5995d5a3e0d6d575aa852961c61 Mon Sep 17 00:00:00 2001 +From: Chenjieqin +Date: Fri, 8 Jan 2021 03:56:54 +0800 +Subject: [PATCH 1015/1024] pwm: sifive-ptc: Add SiFive PWM PTC driver + +yiming.li: clear CNTR of PWM after setting period & duty_cycle +Emil: cleanups, clock, reset and div_u64 + +Signed-off-by: Emil Renner Berthing +--- + drivers/pwm/Kconfig | 11 ++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-sifive-ptc.c | 260 +++++++++++++++++++++++++++++++++++ + 3 files changed, 272 insertions(+) + create mode 100644 drivers/pwm/pwm-sifive-ptc.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -504,6 +504,17 @@ config PWM_SIFIVE + To compile this driver as a module, choose M here: the module + will be called pwm-sifive. + ++config PWM_SIFIVE_PTC ++ tristate "SiFive PWM PTC support" ++ depends on SOC_SIFIVE || SOC_STARFIVE || COMPILE_TEST ++ depends on OF ++ depends on COMMON_CLK ++ help ++ Generic PWM framework driver for SiFive SoCs. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-sifive-ptc. ++ + config PWM_SL28CPLD + tristate "Kontron sl28cpld PWM support" + depends on MFD_SL28CPLD || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -46,6 +46,7 @@ obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-ren + obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o + obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o + obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o ++obj-$(CONFIG_PWM_SIFIVE_PTC) += pwm-sifive-ptc.o + obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o + obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o + obj-$(CONFIG_PWM_SPRD) += pwm-sprd.o +--- /dev/null ++++ b/drivers/pwm/pwm-sifive-ptc.c +@@ -0,0 +1,260 @@ ++/* ++ * Copyright (C) 2018 SiFive, Inc ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2, as published by ++ * the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* max channel of pwm */ ++#define MAX_PWM 8 ++ ++/* PTC Register offsets */ ++#define REG_RPTC_CNTR 0x0 ++#define REG_RPTC_HRC 0x4 ++#define REG_RPTC_LRC 0x8 ++#define REG_RPTC_CTRL 0xC ++ ++/* Bit for PWM clock */ ++#define BIT_PWM_CLOCK_EN 31 ++ ++/* Bit for clock gen soft reset */ ++#define BIT_CLK_GEN_SOFT_RESET 13 ++ ++#define NS_1 1000000000U ++ ++/* Access PTC register (cntr hrc lrc and ctrl), need to replace PWM_BASE_ADDR */ ++#define REG_PTC_BASE_ADDR_SUB(base, N) \ ++ ((base) + (((N) > 3) ? (((N) - 4) * 0x10 + (1 << 15)) : ((N) * 0x10))) ++#define REG_PTC_RPTC_CNTR(base, N) (REG_PTC_BASE_ADDR_SUB(base, N)) ++#define REG_PTC_RPTC_HRC(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0x4) ++#define REG_PTC_RPTC_LRC(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0x8) ++#define REG_PTC_RPTC_CTRL(base, N) (REG_PTC_BASE_ADDR_SUB(base, N) + 0xC) ++ ++/* pwm ptc device */ ++struct sifive_pwm_ptc_device { ++ struct pwm_chip chip; ++ struct clk *clk; ++ void __iomem *regs; ++}; ++ ++static inline struct sifive_pwm_ptc_device *chip_to_sifive_ptc(struct pwm_chip *c) ++{ ++ return container_of(c, struct sifive_pwm_ptc_device, chip); ++} ++ ++static int sifive_pwm_ptc_get_state(struct pwm_chip *chip, struct pwm_device *dev, ++ struct pwm_state *state) ++{ ++ struct sifive_pwm_ptc_device *pwm = chip_to_sifive_ptc(chip); ++ u32 data_lrc; ++ u32 data_hrc; ++ u32 pwm_clk_ns = 0; ++ ++ /* get lrc and hrc data from registe */ ++ data_lrc = ioread32(REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm)); ++ data_hrc = ioread32(REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm)); ++ ++ /* how many ns does apb clock elapse */ ++ pwm_clk_ns = NS_1 / clk_get_rate(pwm->clk); ++ ++ /* pwm period(ns) */ ++ state->period = data_lrc * pwm_clk_ns; ++ ++ /* duty cycle(ns) means high level eclapse ns if it is normal polarity */ ++ state->duty_cycle = data_hrc * pwm_clk_ns; ++ ++ /* polarity, we don't use it now because it is not in dts */ ++ state->polarity = PWM_POLARITY_NORMAL; ++ ++ /* enabled or not */ ++ state->enabled = 1; ++ ++ dev_dbg(pwm->chip.dev, "%s: no:%d\n", __func__, dev->hwpwm); ++ dev_dbg(pwm->chip.dev, "data_hrc:0x%x 0x%x\n", data_hrc, data_lrc); ++ dev_dbg(pwm->chip.dev, "period:%llu\n", state->period); ++ dev_dbg(pwm->chip.dev, "duty_cycle:%llu\n", state->duty_cycle); ++ dev_dbg(pwm->chip.dev, "polarity:%d\n", state->polarity); ++ dev_dbg(pwm->chip.dev, "enabled:%d\n", state->enabled); ++ ++ return 0; ++} ++ ++static int sifive_pwm_ptc_apply(struct pwm_chip *chip, struct pwm_device *dev, ++ const struct pwm_state *state) ++{ ++ struct sifive_pwm_ptc_device *pwm = chip_to_sifive_ptc(chip); ++ void __iomem *reg_addr; ++ u32 pwm_clk_ns = 0; ++ u32 data_hrc = 0; ++ u32 data_lrc = 0; ++ u32 period_data = 0; ++ u32 duty_data = 0; ++ ++ dev_dbg(pwm->chip.dev, "%s: no:%d\n", __func__, dev->hwpwm); ++ dev_dbg(pwm->chip.dev, "period:%llu\n", state->period); ++ dev_dbg(pwm->chip.dev, "duty_cycle:%llu\n", state->duty_cycle); ++ dev_dbg(pwm->chip.dev, "polarity:%d\n", state->polarity); ++ dev_dbg(pwm->chip.dev, "enabled:%d\n", state->enabled); ++ ++ /* duty_cycle should be less or equal than period */ ++ if (state->duty_cycle > state->period) ++ return -EINVAL; ++ ++ /* calculate pwm real period (ns) */ ++ pwm_clk_ns = NS_1 / clk_get_rate(pwm->clk); ++ ++ dev_dbg(pwm->chip.dev, "pwm_clk_ns:%u\n", pwm_clk_ns); ++ ++ /* calculate period count */ ++ period_data = div_u64(state->period, pwm_clk_ns); ++ ++ if (!state->enabled) ++ /* if disabled, just set duty_data to 0, which means low level always */ ++ duty_data = 0; ++ else ++ /* calculate duty count */ ++ duty_data = div_u64(state->duty_cycle, pwm_clk_ns); ++ ++ dev_dbg(pwm->chip.dev, "period_data:%u, duty_data:%u\n", ++ period_data, duty_data); ++ ++ if (state->polarity == PWM_POLARITY_NORMAL) ++ /* calculate data_hrc */ ++ data_hrc = period_data - duty_data; ++ else ++ /* calculate data_hrc */ ++ data_hrc = duty_data; ++ ++ data_lrc = period_data; ++ ++ /* set hrc */ ++ reg_addr = REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm); ++ dev_dbg(pwm->chip.dev, "%s: reg_addr:%p, data:%u\n", ++ __func__, reg_addr, data_hrc); ++ ++ iowrite32(data_hrc, reg_addr); ++ ++ dev_dbg(pwm->chip.dev, "%s: hrc ok\n", __func__); ++ ++ /* set lrc */ ++ reg_addr = REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm); ++ dev_dbg(pwm->chip.dev, "%s: reg_addr:%p, data:%u\n", ++ __func__, reg_addr, data_lrc); ++ ++ iowrite32(data_lrc, reg_addr); ++ dev_dbg(pwm->chip.dev, "%s: lrc ok\n", __func__); ++ ++ /* Clear REG_RPTC_CNTR after setting period & duty_cycle */ ++ reg_addr = REG_PTC_RPTC_CNTR(pwm->regs, dev->hwpwm); ++ iowrite32(0, reg_addr); ++ return 0; ++} ++ ++static const struct pwm_ops sifive_pwm_ptc_ops = { ++ .get_state = sifive_pwm_ptc_get_state, ++ .apply = sifive_pwm_ptc_apply, ++ .owner = THIS_MODULE, ++}; ++ ++static void sifive_pwm_ptc_disable_action(void *data) ++{ ++ clk_disable_unprepare(data); ++} ++ ++static int sifive_pwm_ptc_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = pdev->dev.of_node; ++ struct sifive_pwm_ptc_device *pwm; ++ struct pwm_chip *chip; ++ struct reset_control *rst; ++ int ret; ++ ++ pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL); ++ if (!pwm) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pwm); ++ ++ chip = &pwm->chip; ++ chip->dev = dev; ++ chip->ops = &sifive_pwm_ptc_ops; ++ ++ /* how many parameters can be transferred to ptc, need to fix */ ++ chip->of_pwm_n_cells = 3; ++ chip->base = -1; ++ ++ /* get pwm channels count, max value is 8 */ ++ ret = of_property_read_u32(node, "starfive,npwm", &chip->npwm); ++ if (ret < 0 || chip->npwm > MAX_PWM) ++ chip->npwm = MAX_PWM; ++ ++ dev_dbg(dev, "%s: npwm:0x%x\n", __func__, chip->npwm); ++ ++ /* get IO base address */ ++ pwm->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pwm->regs)) ++ return dev_err_probe(dev, PTR_ERR(pwm->regs), ++ "Unable to map IO resources\n"); ++ ++ pwm->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(pwm->clk)) ++ return dev_err_probe(dev, PTR_ERR(pwm->clk), ++ "Unable to get controller clock\n"); ++ ++ ret = clk_prepare_enable(pwm->clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "Unable to enable clock\n"); ++ ++ ret = devm_add_action_or_reset(dev, sifive_pwm_ptc_disable_action, pwm->clk); ++ if (ret) ++ return ret; ++ ++ rst = devm_reset_control_get_exclusive(dev, NULL); ++ if (IS_ERR(rst)) ++ return dev_err_probe(dev, PTR_ERR(rst), "Unable to get reset\n"); ++ ++ ret = reset_control_deassert(rst); ++ if (ret) ++ return dev_err_probe(dev, ret, "Unable to deassert reset\n"); ++ ++ /* ++ * after pwmchip_add it will show up as /sys/class/pwm/pwmchip0, ++ * 0 is chip->base, pwm0 can be seen after running echo 0 > export ++ */ ++ ret = devm_pwmchip_add(dev, chip); ++ if (ret) ++ return dev_err_probe(dev, ret, "cannot register PTC: %d\n", ret); ++ ++ dev_dbg(dev, "SiFive PWM PTC chip registered %d PWMs\n", chip->npwm); ++ return 0; ++} ++ ++static const struct of_device_id sifive_pwm_ptc_of_match[] = { ++ { .compatible = "starfive,pwm0" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sifive_pwm_ptc_of_match); ++ ++static struct platform_driver sifive_pwm_ptc_driver = { ++ .probe = sifive_pwm_ptc_probe, ++ .driver = { ++ .name = "pwm-sifive-ptc", ++ .of_match_table = sifive_pwm_ptc_of_match, ++ }, ++}; ++module_platform_driver(sifive_pwm_ptc_driver); ++ ++MODULE_DESCRIPTION("SiFive PWM PTC driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/starfive/patches-6.1/1016-riscv-Implement-non-coherent-DMA-support-via-SiFive-.patch b/target/linux/starfive/patches-6.1/1016-riscv-Implement-non-coherent-DMA-support-via-SiFive-.patch new file mode 100644 index 0000000000..d8a2befe64 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1016-riscv-Implement-non-coherent-DMA-support-via-SiFive-.patch @@ -0,0 +1,105 @@ +From d30b864417ea3ad1bc4fcf675ea072cb19011930 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 12 Jun 2021 16:48:31 -0700 +Subject: [PATCH 1016/1024] riscv: Implement non-coherent DMA support via + SiFive cache flushing + +This variant is used on the StarFive JH7100 SoC. + +Signed-off-by: Emil Renner Berthing +--- + arch/riscv/Kconfig | 6 ++++-- + arch/riscv/mm/dma-noncoherent.c | 37 +++++++++++++++++++++++++++++++-- + 2 files changed, 39 insertions(+), 4 deletions(-) + +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -225,12 +225,14 @@ config LOCKDEP_SUPPORT + def_bool y + + config RISCV_DMA_NONCOHERENT +- bool ++ bool "Support non-coherent DMA" ++ default SOC_STARFIVE + select ARCH_HAS_DMA_PREP_COHERENT ++ select ARCH_HAS_DMA_SET_UNCACHED ++ select ARCH_HAS_DMA_CLEAR_UNCACHED + select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select ARCH_HAS_SYNC_DMA_FOR_CPU + select ARCH_HAS_SETUP_DMA_OPS +- select DMA_DIRECT_REMAP + + config AS_HAS_INSN + def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero) +--- a/arch/riscv/mm/dma-noncoherent.c ++++ b/arch/riscv/mm/dma-noncoherent.c +@@ -9,14 +9,21 @@ + #include + #include + #include ++#include + + static bool noncoherent_supported; + + void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, + enum dma_data_direction dir) + { +- void *vaddr = phys_to_virt(paddr); ++ void *vaddr; + ++ if (sifive_ccache_handle_noncoherent()) { ++ sifive_ccache_flush_range(paddr, size); ++ return; ++ } ++ ++ vaddr = phys_to_virt(paddr); + switch (dir) { + case DMA_TO_DEVICE: + ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); +@@ -35,8 +42,14 @@ void arch_sync_dma_for_device(phys_addr_ + void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, + enum dma_data_direction dir) + { +- void *vaddr = phys_to_virt(paddr); ++ void *vaddr; ++ ++ if (sifive_ccache_handle_noncoherent()) { ++ sifive_ccache_flush_range(paddr, size); ++ return; ++ } + ++ vaddr = phys_to_virt(paddr); + switch (dir) { + case DMA_TO_DEVICE: + break; +@@ -49,10 +62,30 @@ void arch_sync_dma_for_cpu(phys_addr_t p + } + } + ++void *arch_dma_set_uncached(void *addr, size_t size) ++{ ++ if (sifive_ccache_handle_noncoherent()) ++ return sifive_ccache_set_uncached(addr, size); ++ ++ return addr; ++} ++ ++void arch_dma_clear_uncached(void *addr, size_t size) ++{ ++ if (sifive_ccache_handle_noncoherent()) ++ sifive_ccache_clear_uncached(addr, size); ++} ++ + void arch_dma_prep_coherent(struct page *page, size_t size) + { + void *flush_addr = page_address(page); + ++ if (sifive_ccache_handle_noncoherent()) { ++ memset(flush_addr, 0, size); ++ sifive_ccache_flush_range(__pa(flush_addr), size); ++ return; ++ } ++ + ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); + } + diff --git a/target/linux/starfive/patches-6.1/1017-dt-bindings-riscv-sifive-ccache-Add-uncached-offset-.patch b/target/linux/starfive/patches-6.1/1017-dt-bindings-riscv-sifive-ccache-Add-uncached-offset-.patch new file mode 100644 index 0000000000..7de04411ed --- /dev/null +++ b/target/linux/starfive/patches-6.1/1017-dt-bindings-riscv-sifive-ccache-Add-uncached-offset-.patch @@ -0,0 +1,30 @@ +From 3b83b32e16fa431c76a5da1ac59c268ca2fecbb5 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sat, 11 Feb 2023 05:18:11 +0200 +Subject: [PATCH 1017/1024] dt-bindings: riscv: sifive-ccache: Add + 'uncached-offset' property + +Add the 'uncached-offset' property to be used for specifying the +uncached memory offset required for handling non-coherent DMA +transactions. + +Signed-off-by: Cristian Ciocaltea +Link: https://lore.kernel.org/r/20230211031821.976408-3-cristian.ciocaltea@collabora.com +--- + Documentation/devicetree/bindings/riscv/sifive,ccache0.yaml | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/riscv/sifive,ccache0.yaml ++++ b/Documentation/devicetree/bindings/riscv/sifive,ccache0.yaml +@@ -70,6 +70,11 @@ properties: + + next-level-cache: true + ++ uncached-offset: ++ $ref: /schemas/types.yaml#/definitions/uint64 ++ description: | ++ Uncached memory offset for handling non-coherent DMA transactions. ++ + memory-region: + maxItems: 1 + description: | diff --git a/target/linux/starfive/patches-6.1/1018-soc-sifive-ccache-Add-StarFive-JH71x0-support.patch b/target/linux/starfive/patches-6.1/1018-soc-sifive-ccache-Add-StarFive-JH71x0-support.patch new file mode 100644 index 0000000000..04d1e5aa1e --- /dev/null +++ b/target/linux/starfive/patches-6.1/1018-soc-sifive-ccache-Add-StarFive-JH71x0-support.patch @@ -0,0 +1,77 @@ +From cde57aebfd86b3b062ce0bcf71395d735d05b2f6 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Wed, 6 Apr 2022 00:38:05 +0200 +Subject: [PATCH 1018/1024] soc: sifive: ccache: Add StarFive JH71x0 support + +This adds support for the StarFive JH7100 and JH7110 SoCs which also +feature this SiFive cache controller. + +Unfortunately the interrupt for uncorrected data is broken on the JH7100 +and fires continuously, so add a quirk to not register a handler for it. + +Signed-off-by: Emil Renner Berthing +--- + arch/riscv/Kconfig.socs | 1 + + drivers/soc/sifive/Kconfig | 2 +- + drivers/soc/sifive/sifive_ccache.c | 12 +++++++++++- + 3 files changed, 13 insertions(+), 2 deletions(-) + +--- a/arch/riscv/Kconfig.socs ++++ b/arch/riscv/Kconfig.socs +@@ -28,6 +28,7 @@ config SOC_STARFIVE + bool "StarFive SoCs" + select PINCTRL + select RESET_CONTROLLER ++ select SIFIVE_CCACHE + select SIFIVE_PLIC + select ARM_AMBA + help +--- a/drivers/soc/sifive/Kconfig ++++ b/drivers/soc/sifive/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + +-if SOC_SIFIVE ++if SOC_SIFIVE || SOC_STARFIVE + + config SIFIVE_CCACHE + bool "Sifive Composable Cache controller" +--- a/drivers/soc/sifive/sifive_ccache.c ++++ b/drivers/soc/sifive/sifive_ccache.c +@@ -106,6 +106,8 @@ static void ccache_config_read(void) + static const struct of_device_id sifive_ccache_ids[] = { + { .compatible = "sifive,fu540-c000-ccache" }, + { .compatible = "sifive,fu740-c000-ccache" }, ++ { .compatible = "starfive,jh7100-ccache", .data = (void *)BIT(DATA_UNCORR) }, ++ { .compatible = "starfive,jh7110-ccache" }, + { .compatible = "sifive,ccache0" }, + { /* end of table */ } + }; +@@ -210,11 +212,15 @@ static int __init sifive_ccache_init(voi + struct device_node *np; + struct resource res; + int i, rc, intr_num; ++ const struct of_device_id *match; ++ unsigned long broken_irqs; + +- np = of_find_matching_node(NULL, sifive_ccache_ids); ++ np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); + if (!np) + return -ENODEV; + ++ broken_irqs = (uintptr_t)match->data; ++ + if (of_address_to_resource(np, 0, &res)) { + rc = -ENODEV; + goto err_node_put; +@@ -240,6 +246,10 @@ static int __init sifive_ccache_init(voi + + for (i = 0; i < intr_num; i++) { + g_irq[i] = irq_of_parse_and_map(np, i); ++ ++ if (broken_irqs & BIT(i)) ++ continue; ++ + rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc", + NULL); + if (rc) { diff --git a/target/linux/starfive/patches-6.1/1019-soc-sifive-ccache-Add-non-coherent-DMA-handling.patch b/target/linux/starfive/patches-6.1/1019-soc-sifive-ccache-Add-non-coherent-DMA-handling.patch new file mode 100644 index 0000000000..0713739b5f --- /dev/null +++ b/target/linux/starfive/patches-6.1/1019-soc-sifive-ccache-Add-non-coherent-DMA-handling.patch @@ -0,0 +1,159 @@ +From 335c32d2653f2415e042c8ad1ae2a6b33019b96f Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 12 Jun 2021 16:48:31 -0700 +Subject: [PATCH 1019/1024] soc: sifive: ccache: Add non-coherent DMA handling + +Add functions to flush the caches and handle non-coherent DMA. + +Signed-off-by: Emil Renner Berthing +--- + drivers/soc/sifive/sifive_ccache.c | 60 +++++++++++++++++++++++++++++- + include/soc/sifive/sifive_ccache.h | 21 +++++++++++ + 2 files changed, 80 insertions(+), 1 deletion(-) + +--- a/drivers/soc/sifive/sifive_ccache.c ++++ b/drivers/soc/sifive/sifive_ccache.c +@@ -8,13 +8,16 @@ + + #define pr_fmt(fmt) "CCACHE: " fmt + ++#include + #include + #include + #include + #include + #include + #include ++#include + #include ++#include + #include + + #define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100 +@@ -39,10 +42,14 @@ + #define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16) + #define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24) + ++#define SIFIVE_CCACHE_FLUSH64 0x200 ++#define SIFIVE_CCACHE_FLUSH32 0x240 ++ + #define SIFIVE_CCACHE_WAYENABLE 0x08 + #define SIFIVE_CCACHE_ECCINJECTERR 0x40 + + #define SIFIVE_CCACHE_MAX_ECCINTR 4 ++#define SIFIVE_CCACHE_LINE_SIZE 64 + + static void __iomem *ccache_base; + static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR]; +@@ -126,6 +133,47 @@ int unregister_sifive_ccache_error_notif + } + EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier); + ++#ifdef CONFIG_RISCV_DMA_NONCOHERENT ++static phys_addr_t uncached_offset; ++DEFINE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key); ++ ++void sifive_ccache_flush_range(phys_addr_t start, size_t len) ++{ ++ phys_addr_t end = start + len; ++ phys_addr_t line; ++ ++ if (!len) ++ return; ++ ++ mb(); ++ for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end; ++ line += SIFIVE_CCACHE_LINE_SIZE) { ++#ifdef CONFIG_32BIT ++ writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32); ++#else ++ writeq(line, ccache_base + SIFIVE_CCACHE_FLUSH64); ++#endif ++ mb(); ++ } ++} ++EXPORT_SYMBOL_GPL(sifive_ccache_flush_range); ++ ++void *sifive_ccache_set_uncached(void *addr, size_t size) ++{ ++ phys_addr_t phys_addr = __pa(addr) + uncached_offset; ++ void *mem_base; ++ ++ mem_base = memremap(phys_addr, size, MEMREMAP_WT); ++ if (!mem_base) { ++ pr_err("%s memremap failed for addr %p\n", __func__, addr); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return mem_base; ++} ++EXPORT_SYMBOL_GPL(sifive_ccache_set_uncached); ++#endif /* CONFIG_RISCV_DMA_NONCOHERENT */ ++ + static int ccache_largest_wayenabled(void) + { + return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF; +@@ -214,6 +262,7 @@ static int __init sifive_ccache_init(voi + int i, rc, intr_num; + const struct of_device_id *match; + unsigned long broken_irqs; ++ u64 __maybe_unused offset; + + np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); + if (!np) +@@ -259,6 +308,15 @@ static int __init sifive_ccache_init(voi + } + of_node_put(np); + ++#ifdef CONFIG_RISCV_DMA_NONCOHERENT ++ if (!of_property_read_u64(np, "uncached-offset", &offset)) { ++ uncached_offset = offset; ++ static_branch_enable(&sifive_ccache_handle_noncoherent_key); ++ riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; ++ riscv_noncoherent_supported(); ++ } ++#endif ++ + ccache_config_read(); + + ccache_cache_ops.get_priv_group = ccache_get_priv_group; +@@ -279,4 +337,4 @@ err_node_put: + return rc; + } + +-device_initcall(sifive_ccache_init); ++arch_initcall(sifive_ccache_init); +--- a/include/soc/sifive/sifive_ccache.h ++++ b/include/soc/sifive/sifive_ccache.h +@@ -7,10 +7,31 @@ + #ifndef __SOC_SIFIVE_CCACHE_H + #define __SOC_SIFIVE_CCACHE_H + ++#include ++#include ++ + extern int register_sifive_ccache_error_notifier(struct notifier_block *nb); + extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb); + + #define SIFIVE_CCACHE_ERR_TYPE_CE 0 + #define SIFIVE_CCACHE_ERR_TYPE_UE 1 + ++DECLARE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key); ++ ++static inline bool sifive_ccache_handle_noncoherent(void) ++{ ++#ifdef CONFIG_SIFIVE_CCACHE ++ return static_branch_unlikely(&sifive_ccache_handle_noncoherent_key); ++#else ++ return false; ++#endif ++} ++ ++void sifive_ccache_flush_range(phys_addr_t start, size_t len); ++void *sifive_ccache_set_uncached(void *addr, size_t size); ++static inline void sifive_ccache_clear_uncached(void *addr, size_t size) ++{ ++ memunmap(addr); ++} ++ + #endif /* __SOC_SIFIVE_CCACHE_H */ diff --git a/target/linux/starfive/patches-6.1/1020-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch b/target/linux/starfive/patches-6.1/1020-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch new file mode 100644 index 0000000000..7641c559d5 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1020-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch @@ -0,0 +1,48 @@ +From f684a12dac29522c6ce9d504522f75dcf024fc5f Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 20 Nov 2021 19:29:25 +0100 +Subject: [PATCH 1020/1024] dt-bindings: reset: Add StarFive JH7100 audio reset + definitions + +Add all resets for the StarFive JH7100 audio reset controller. + +Signed-off-by: Emil Renner Berthing +--- + .../dt-bindings/reset/starfive-jh7100-audio.h | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + create mode 100644 include/dt-bindings/reset/starfive-jh7100-audio.h + +--- /dev/null ++++ b/include/dt-bindings/reset/starfive-jh7100-audio.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__ ++#define __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__ ++ ++#define JH7100_AUDRSTN_APB_BUS 0 ++#define JH7100_AUDRSTN_I2SADC_APB 1 ++#define JH7100_AUDRSTN_I2SADC_SRST 2 ++#define JH7100_AUDRSTN_PDM_APB 3 ++#define JH7100_AUDRSTN_I2SVAD_APB 4 ++#define JH7100_AUDRSTN_I2SVAD_SRST 5 ++#define JH7100_AUDRSTN_SPDIF_APB 6 ++#define JH7100_AUDRSTN_PWMDAC_APB 7 ++#define JH7100_AUDRSTN_I2SDAC_APB 8 ++#define JH7100_AUDRSTN_I2SDAC_SRST 9 ++#define JH7100_AUDRSTN_I2S1_APB 10 ++#define JH7100_AUDRSTN_I2S1_SRST 11 ++#define JH7100_AUDRSTN_I2SDAC16K_APB 12 ++#define JH7100_AUDRSTN_I2SDAC16K_SRST 13 ++#define JH7100_AUDRSTN_DMA1P_AHB 14 ++#define JH7100_AUDRSTN_USB_APB 15 ++#define JH7100_AUDRST_USB_AXI 16 ++#define JH7100_AUDRST_USB_PWRUP_RST_N 17 ++#define JH7100_AUDRST_USB_PONRST 18 ++ ++#define JH7100_AUDRSTN_END 19 ++ ++#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__ */ diff --git a/target/linux/starfive/patches-6.1/1021-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch b/target/linux/starfive/patches-6.1/1021-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch new file mode 100644 index 0000000000..413833707a --- /dev/null +++ b/target/linux/starfive/patches-6.1/1021-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch @@ -0,0 +1,56 @@ +From 9220294c675a111651ff12b2389a81f0935553fd Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Tue, 7 Dec 2021 21:48:51 +0100 +Subject: [PATCH 1021/1024] dt-bindings: reset: Add starfive,jh7100-audrst + bindings + +Add bindings for the audio reset controller on the StarFive JH7100 +RISC-V SoC. + +Signed-off-by: Emil Renner Berthing +--- + .../reset/starfive,jh7100-audrst.yaml | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-audrst.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-audrst.yaml +@@ -0,0 +1,38 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/reset/starfive,jh7100-audrst.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: StarFive JH7100 SoC Audio Reset Controller Device Tree Bindings ++ ++maintainers: ++ - Emil Renner Berthing ++ ++properties: ++ compatible: ++ enum: ++ - starfive,jh7100-audrst ++ ++ reg: ++ maxItems: 1 ++ ++ "#reset-cells": ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - "#reset-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ reset-controller@10490000 { ++ compatible = "starfive,jh7100-audrst"; ++ reg = <0x10490000 0x10000>; ++ #reset-cells = <1>; ++ }; ++ ++... diff --git a/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch b/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch new file mode 100644 index 0000000000..dc25d354d6 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch @@ -0,0 +1,144 @@ +From ff806bda9b04bcf73350e319f3efde5cd049b77a Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 20 Nov 2021 19:30:49 +0100 +Subject: [PATCH 1022/1024] reset: starfive: Add JH7100 audio reset driver + +The audio resets are almost identical to the system resets, there are +just fewer of them. So factor out and export a generic probe function, +so most of the reset controller implementation can be shared. + +Signed-off-by: Emil Renner Berthing +--- + MAINTAINERS | 2 +- + drivers/reset/starfive/Kconfig | 7 ++ + drivers/reset/starfive/Makefile | 2 + + .../starfive/reset-starfive-jh7100-audio.c | 66 +++++++++++++++++++ + .../reset/starfive/reset-starfive-jh7100.h | 16 +++++ + 5 files changed, 92 insertions(+), 1 deletion(-) + create mode 100644 drivers/reset/starfive/reset-starfive-jh7100-audio.c + create mode 100644 drivers/reset/starfive/reset-starfive-jh7100.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -19704,7 +19704,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS + M: Emil Renner Berthing + M: Hal Feng + S: Maintained +-F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml ++F: Documentation/devicetree/bindings/reset/starfive,jh7100-*.yaml + F: drivers/reset/starfive/reset-starfive-jh71* + F: include/dt-bindings/reset/starfive?jh71*.h + +--- a/drivers/reset/starfive/Kconfig ++++ b/drivers/reset/starfive/Kconfig +@@ -11,6 +11,13 @@ config RESET_STARFIVE_JH7100 + help + This enables the reset controller driver for the StarFive JH7100 SoC. + ++config RESET_STARFIVE_JH7100_AUDIO ++ tristate "StarFive JH7100 Audio Reset Driver" ++ depends on RESET_STARFIVE_JH7100 ++ default m if SOC_STARFIVE ++ help ++ This enables the audio reset driver for the StarFive JH7100 SoC. ++ + config RESET_STARFIVE_JH7110 + bool "StarFive JH7110 Reset Driver" + depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS +--- a/drivers/reset/starfive/Makefile ++++ b/drivers/reset/starfive/Makefile +@@ -2,4 +2,6 @@ + obj-$(CONFIG_RESET_STARFIVE_JH71X0) += reset-starfive-jh71x0.o + + obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o ++obj-$(CONFIG_RESET_STARFIVE_JH7100_AUDIO) += reset-starfive-jh7100-audio.o ++ + obj-$(CONFIG_RESET_STARFIVE_JH7110) += reset-starfive-jh7110.o +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh7100-audio.c +@@ -0,0 +1,66 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Audio reset driver for the StarFive JH7100 SoC ++ * ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#include ++#include ++#include ++ ++#include "reset-starfive-jh71x0.h" ++ ++#include ++ ++/* register offsets */ ++#define JH7100_AUDRST_ASSERT0 0x00 ++#define JH7100_AUDRST_STATUS0 0x04 ++ ++/* ++ * Writing a 1 to the n'th bit of the ASSERT register asserts ++ * line n, and writing a 0 deasserts the same line. ++ * Most reset lines have their status inverted so a 0 bit in the STATUS ++ * register means the line is asserted and a 1 means it's deasserted. A few ++ * lines don't though, so store the expected value of the status registers when ++ * all lines are asserted. ++ */ ++static const u32 jh7100_audrst_asserted[1] = { ++ BIT(JH7100_AUDRST_USB_AXI) | ++ BIT(JH7100_AUDRST_USB_PWRUP_RST_N) | ++ BIT(JH7100_AUDRST_USB_PONRST) ++}; ++ ++static int jh7100_audrst_probe(struct platform_device *pdev) ++{ ++ void __iomem *base = devm_platform_ioremap_resource(pdev, 0); ++ ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ return reset_starfive_jh71x0_register(&pdev->dev, pdev->dev.of_node, ++ base + JH7100_AUDRST_ASSERT0, ++ base + JH7100_AUDRST_STATUS0, ++ jh7100_audrst_asserted, ++ JH7100_AUDRSTN_END, ++ THIS_MODULE); ++} ++ ++static const struct of_device_id jh7100_audrst_dt_ids[] = { ++ { .compatible = "starfive,jh7100-audrst" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jh7100_audrst_dt_ids); ++ ++static struct platform_driver jh7100_audrst_driver = { ++ .probe = jh7100_audrst_probe, ++ .driver = { ++ .name = "jh7100-reset-audio", ++ .of_match_table = jh7100_audrst_dt_ids, ++ }, ++}; ++module_platform_driver(jh7100_audrst_driver); ++ ++MODULE_AUTHOR("Emil Renner Berthing"); ++MODULE_DESCRIPTION("StarFive JH7100 audio reset driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/reset/starfive/reset-starfive-jh7100.h +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++#ifndef _RESET_STARFIVE_JH7100_H_ ++#define _RESET_STARFIVE_JH7100_H_ ++ ++#include ++ ++int reset_starfive_jh7100_generic_probe(struct platform_device *pdev, ++ const u32 *asserted, ++ unsigned int status_offset, ++ unsigned int nr_resets); ++ ++#endif diff --git a/target/linux/starfive/patches-6.1/1023-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch b/target/linux/starfive/patches-6.1/1023-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch new file mode 100644 index 0000000000..0ef6fa485e --- /dev/null +++ b/target/linux/starfive/patches-6.1/1023-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch @@ -0,0 +1,28 @@ +From f7ab709727e845ffdfc428ec2f236d0c1997b153 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sat, 20 Nov 2021 21:33:08 +0100 +Subject: [PATCH 1023/1024] RISC-V: Add StarFive JH7100 audio reset node + +Add device tree node for the audio resets on the StarFive JH7100 RISC-V +SoC. + +Signed-off-by: Emil Renner Berthing +--- + arch/riscv/boot/dts/starfive/jh7100.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -144,6 +144,12 @@ + #clock-cells = <1>; + }; + ++ audrst: reset-controller@10490000 { ++ compatible = "starfive,jh7100-audrst"; ++ reg = <0x0 0x10490000 0x0 0x10000>; ++ #reset-cells = <1>; ++ }; ++ + clkgen: clock-controller@11800000 { + compatible = "starfive,jh7100-clkgen"; + reg = <0x0 0x11800000 0x0 0x10000>; diff --git a/target/linux/starfive/patches-6.1/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch b/target/linux/starfive/patches-6.1/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch new file mode 100644 index 0000000000..92176679de --- /dev/null +++ b/target/linux/starfive/patches-6.1/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch @@ -0,0 +1,1265 @@ +From 9912cdc9038c40fbcb1f121445519efb55dec046 Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sun, 31 Oct 2021 17:15:58 +0100 +Subject: [PATCH 1024/1024] riscv: dts: Add full JH7100, Starlight and + VisionFive support + +Based on the device tree in https://github.com/starfive-tech/u-boot/ +with contributions from: +yanhong.wang +Huan.Feng +ke.zhu +yiming.li +jack.zhu +Samin Guo +Chenjieqin +bo.li + +Rearranged, cleanups, fixes, pins and resets added by Emil. +Cleanups, fixes, clocks added by Geert. +Cleanups and GPIO fixes from Drew. +Thermal zone added by Stephen. +PWM pins added by Jianlong. +cpu-map added by Jonas. + +Signed-off-by: Emil Renner Berthing +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Stephen L Arnold +Signed-off-by: Drew Fustini +Signed-off-by: Jianlong Huang +Signed-off-by: Jonas Hahnfeld +--- + arch/riscv/boot/dts/starfive/Makefile | 1 + + .../starfive/jh7100-beaglev-starlight-a1.dts | 30 + + .../dts/starfive/jh7100-beaglev-starlight.dts | 16 + + .../boot/dts/starfive/jh7100-common.dtsi | 434 ++++++++++++++ + .../jh7100-starfive-visionfive-v1.dts | 19 + + arch/riscv/boot/dts/starfive/jh7100.dtsi | 561 ++++++++++++++++++ + 6 files changed, 1061 insertions(+) + create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight-a1.dts + +--- a/arch/riscv/boot/dts/starfive/Makefile ++++ b/arch/riscv/boot/dts/starfive/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 ++dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight-a1.dtb + dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb + dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb + +--- /dev/null ++++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight-a1.dts +@@ -0,0 +1,30 @@ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* ++ * Copyright (C) 2021 Emil Renner Berthing ++ */ ++ ++/dts-v1/; ++#include "jh7100-common.dtsi" ++#include ++ ++/ { ++ model = "BeagleV Starlight Beta A1"; ++ compatible = "beagle,beaglev-starlight-jh7100-a1", "starfive,jh7100"; ++ ++ gpio-restart { ++ compatible = "gpio-restart"; ++ gpios = <&gpio 63 GPIO_ACTIVE_HIGH>; ++ priority = <224>; ++ }; ++}; ++ ++&gpio { ++ /* don't reset gpio mux for serial console and reset gpio */ ++ starfive,keep-gpiomux = <13 14 63>; ++}; ++ ++&mdio { ++ phy: ethernet-phy@7 { ++ reg = <7>; ++ }; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts ++++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts +@@ -6,8 +6,24 @@ + + /dts-v1/; + #include "jh7100-common.dtsi" ++#include + + / { + model = "BeagleV Starlight Beta"; + compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100"; + }; ++ ++&gmac { ++ snps,reset-gpios = <&gpio 63 GPIO_ACTIVE_LOW>; ++}; ++ ++&gpio { ++ /* don't reset gpio mux for serial console on uart3 */ ++ starfive,keep-gpiomux = <13 14>; ++}; ++ ++&mdio { ++ phy: ethernet-phy@7 { ++ reg = <7>; ++ }; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi +@@ -12,7 +12,10 @@ + + / { + aliases { ++ mmc0 = &sdio0; ++ mmc1 = &sdio1; + serial0 = &uart3; ++ serial1 = &uart0; + }; + + chosen { +@@ -39,9 +42,174 @@ + label = "ack"; + }; + }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ size = <0x0 0x28000000>; ++ alignment = <0x0 0x1000>; ++ alloc-ranges = <0x0 0xa0000000 0x0 0x28000000>; ++ linux,cma-default; ++ }; ++ ++ jpu_reserved: framebuffer@c9000000 { ++ reg = <0x0 0xc9000000 0x0 0x4000000>; ++ }; ++ ++ nvdla_reserved: framebuffer@d0000000 { ++ no-map; ++ reg = <0x0 0xd0000000 0x0 0x28000000>; ++ }; ++ ++ vin_reserved: framebuffer@f9000000 { ++ compatible = "shared-dma-pool"; ++ no-map; ++ reg = <0x0 0xf9000000 0x0 0x1000000>; ++ }; ++ ++ sffb_reserved: framebuffer@fb000000 { ++ compatible = "shared-dma-pool"; ++ no-map; ++ reg = <0x0 0xfb000000 0x0 0x2000000>; ++ }; ++ }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio 37 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&display { ++ memory-region = <&sffb_reserved>; ++ status = "okay"; ++}; ++ ++&crtc { ++ ddr-format = <4>; //; ++ status = "okay"; ++ ++ port: port@0 { ++ reg = <0>; ++ ++ crtc_0_out: endpoint { ++ remote-endpoint = <&hdmi_input0>; ++ }; ++ }; ++}; ++ ++&encoder { ++ encoder-type = <2>; // 2-TMDS, 3-LVDS, 6-DSI, 8-DPI ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ hdmi_out: endpoint { ++ remote-endpoint = <&tda998x_0_input>; ++ }; ++ }; ++ ++ port@1 { ++ hdmi_input0: endpoint { ++ remote-endpoint = <&crtc_0_out>; ++ }; ++ }; ++ ++ }; ++}; ++ ++&gmac { ++ starfive,gtxclk-dlychain = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac_pins>; ++ phy-mode = "rgmii-txid"; ++ phy-handle = <&phy>; ++ status = "okay"; ++ ++ mdio: mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "snps,dwmac-mdio"; ++ }; + }; + + &gpio { ++ gmac_pins: gmac-0 { ++ gtxclk-pins { ++ pins = ; ++ bias-pull-up; ++ drive-strength = <35>; ++ input-enable; ++ input-schmitt-enable; ++ slew-rate = <0>; ++ }; ++ miitxclk-pins { ++ pins = ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ tx-pins { ++ pins = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ bias-pull-up; ++ drive-strength = <35>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ rxclk-pins { ++ pins = ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <6>; ++ }; ++ rxer-pins { ++ pins = ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ rx-pins { ++ pins = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-enable; ++ slew-rate = <0>; ++ }; ++ }; ++ + i2c0_pins: i2c0-0 { + i2c-pins { + pinmux = , ++ ; ++ bias-disable; ++ drive-strength = <35>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ pwm_pins: pwm-0 { ++ pwm-pins { ++ pinmux = , ++ ; ++ bias-disable; ++ drive-strength = <35>; ++ input-disable; ++ input-schmitt-disable; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ sdio0_pins: sdio0-0 { ++ clk-pins { ++ pinmux = ; ++ bias-disable; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ sdio-pins { ++ pinmux = , ++ , ++ , ++ , ++ , ++ ; ++ bias-pull-up; ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ sdio1_pins: sdio1-0 { ++ clk-pins { ++ pinmux = ; ++ bias-disable; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ sdio-pins { ++ pinmux = , ++ , ++ , ++ , ++ ; ++ bias-pull-up; ++ input-enable; ++ input-schmitt-enable; ++ }; ++ }; ++ ++ spi2_pins: spi2-0 { ++ mosi-pins { ++ pinmux = ; ++ bias-disable; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ miso-pins { ++ pinmux = ; ++ bias-pull-up; ++ input-enable; ++ input-schmitt-enable; ++ }; ++ sck-pins { ++ pinmux = ; ++ bias-disable; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ ss-pins { ++ pinmux = , ++ ; ++ bias-disable; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ }; ++ ++ uart0_pins: uart0-0 { ++ rx-pins { ++ pinmux = , ++ ; ++ bias-pull-up; ++ drive-strength = <14>; ++ input-enable; ++ input-schmitt-enable; ++ }; ++ tx-pins { ++ pinmux = , ++ ; ++ bias-disable; ++ drive-strength = <35>; ++ input-disable; ++ input-schmitt-disable; ++ }; ++ }; ++ + uart3_pins: uart3-0 { + rx-pins { + pinmux = ; ++ ++ port { ++ tda998x_0_input: endpoint { ++ remote-endpoint = <&hdmi_out>; ++ }; ++ }; ++ }; + }; + + &i2c1 { +@@ -154,8 +493,103 @@ + clock-frequency = <27000000>; + }; + ++&ptc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&pwmdac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwmdac_pins>; ++ status = "okay"; ++}; ++ ++&qspi { ++ nor_flash: nor-flash@0 { ++ compatible = "spi-flash"; ++ reg = <0>; ++ spi-max-frequency = <31250000>; ++ page-size = <256>; ++ block-size = <16>; ++ cdns,read-delay = <4>; ++ cdns,tshsl-ns = <1>; ++ cdns,tsd2d-ns = <1>; ++ cdns,tchsh-ns = <1>; ++ cdns,tslch-ns = <1>; ++ spi-tx-bus-width = <1>; ++ spi-rx-bus-width = <1>; ++ }; ++ ++ nand_flash: nand-flash@1 { ++ compatible = "spi-flash-nand"; ++ reg = <1>; ++ spi-max-frequency = <31250000>; ++ page-size = <2048>; ++ block-size = <17>; ++ cdns,read-delay = <4>; ++ cdns,tshsl-ns = <1>; ++ cdns,tsd2d-ns = <1>; ++ cdns,tchsh-ns = <1>; ++ cdns,tslch-ns = <1>; ++ spi-tx-bus-width = <1>; ++ spi-rx-bus-width = <1>; ++ }; ++}; ++ ++&sdio0 { ++ broken-cd; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio0_pins>; ++ status = "okay"; ++}; ++ ++&sdio1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ cap-power-off-card; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio1_pins>; ++ status = "okay"; ++ ++ wifi@1 { ++ compatible = "brcm,bcm4329-fmac"; ++ reg = <1>; ++ }; ++}; ++ ++&spi2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_pins>; ++ status = "okay"; ++ ++ spi_dev0: spi@0 { ++ compatible = "rohm,dh2228fv"; ++ spi-max-frequency = <10000000>; ++ reg = <0>; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ status = "okay"; ++}; ++ + &uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + status = "okay"; + }; ++ ++&usb3 { ++ dr_mode = "host"; ++ status = "okay"; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts ++++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts +@@ -18,3 +18,22 @@ + priority = <224>; + }; + }; ++ ++&gpio { ++ /* don't reset gpio mux for serial console and reset gpio */ ++ starfive,keep-gpiomux = <13 14 63>; ++}; ++ ++&i2c0 { ++ eeprom@50 { ++ compatible = "atmel,24c04"; ++ reg = <0x50>; ++ pagesize = <16>; ++ }; ++}; ++ ++&mdio { ++ phy: ethernet-phy@0 { ++ reg = <0>; ++ }; ++}; +--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi +@@ -6,7 +6,9 @@ + + /dts-v1/; + #include ++#include + #include ++#include + + / { + compatible = "starfive,jh7100"; +@@ -32,7 +34,9 @@ + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc"; ++ starfive,itim = <&itim0>; + tlb-split; + + cpu0_intc: interrupt-controller { +@@ -57,7 +61,9 @@ + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; ++ next-level-cache = <&ccache>; + riscv,isa = "rv64imafdc"; ++ starfive,itim = <&itim1>; + tlb-split; + + cpu1_intc: interrupt-controller { +@@ -108,6 +114,13 @@ + clock-frequency = <0>; + }; + ++ /* gmac device configuration */ ++ stmmac_axi_setup: stmmac-axi-config { ++ snps,wr_osr_lmt = <0xf>; ++ snps,rd_osr_lmt = <0xf>; ++ snps,blen = <256 128 64 32 0 0 0>; ++ }; ++ + soc { + compatible = "simple-bus"; + interrupt-parent = <&plic>; +@@ -116,6 +129,24 @@ + #size-cells = <2>; + ranges; + ++ dtim: dtim@1000000 { ++ compatible = "starfive,dtim0"; ++ reg = <0x0 0x1000000 0x0 0x2000>; ++ reg-names = "mem"; ++ }; ++ ++ itim0: itim@1808000 { ++ compatible = "starfive,itim0"; ++ reg = <0x0 0x1808000 0x0 0x8000>; ++ reg-names = "mem"; ++ }; ++ ++ itim1: itim@1820000 { ++ compatible = "starfive,itim0"; ++ reg = <0x0 0x1820000 0x0 0x8000>; ++ reg-names = "mem"; ++ }; ++ + clint: clint@2000000 { + compatible = "starfive,jh7100-clint", "sifive,clint0"; + reg = <0x0 0x2000000 0x0 0x10000>; +@@ -123,6 +154,21 @@ + <&cpu1_intc 3>, <&cpu1_intc 7>; + }; + ++ ccache: cache-controller@2010000 { ++ compatible = "starfive,jh7100-ccache", "cache"; ++ reg = <0x0 0x2010000 0x0 0x1000>, ++ <0x0 0x8000000 0x0 0x2000000>; ++ reg-names = "control", "sideband"; ++ interrupts = <128>, <130>, <131>, <129>; ++ cache-block-size = <64>; ++ cache-level = <2>; ++ cache-sets = <2048>; ++ cache-size = <2097152>; ++ cache-unified; ++ /*next-level-cache = <&L40 &L36>;*/ ++ uncached-offset = <0xf 0x80000000>; ++ }; ++ + plic: interrupt-controller@c000000 { + compatible = "starfive,jh7100-plic", "sifive,plic-1.0.0"; + reg = <0x0 0xc000000 0x0 0x4000000>; +@@ -134,6 +180,177 @@ + riscv,ndev = <133>; + }; + ++ sdio0: mmc@10000000 { ++ compatible = "snps,dw-mshc"; ++ reg = <0x0 0x10000000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SDIO0_AHB>, ++ <&clkgen JH7100_CLK_SDIO0_CCLKINT_INV>; ++ clock-names = "biu", "ciu"; ++ interrupts = <4>; ++ data-addr = <0>; ++ fifo-depth = <32>; ++ fifo-watermark-aligned; ++ status = "disabled"; ++ }; ++ ++ sdio1: mmc@10010000 { ++ compatible = "snps,dw-mshc"; ++ reg = <0x0 0x10010000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SDIO1_AHB>, ++ <&clkgen JH7100_CLK_SDIO1_CCLKINT_INV>; ++ clock-names = "biu", "ciu"; ++ interrupts = <5>; ++ data-addr = <0>; ++ fifo-depth = <32>; ++ fifo-watermark-aligned; ++ status = "disabled"; ++ }; ++ ++ gmac: ethernet@10020000 { ++ compatible = "starfive,jh7100-dwmac", "snps,dwmac"; ++ reg = <0x0 0x10020000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_GMAC_ROOT_DIV>, ++ <&clkgen JH7100_CLK_GMAC_AHB>, ++ <&clkgen JH7100_CLK_GMAC_PTP_REF>, ++ <&clkgen JH7100_CLK_GMAC_TX_INV>, ++ <&clkgen JH7100_CLK_GMAC_GTX>; ++ clock-names = "stmmaceth", "pclk", "ptp_ref", "tx", "gtx"; ++ resets = <&rstgen JH7100_RSTN_GMAC_AHB>; ++ reset-names = "ahb"; ++ interrupts = <6>, <7>; ++ interrupt-names = "macirq", "eth_wake_irq"; ++ max-frame-size = <9000>; ++ snps,multicast-filter-bins = <0>; ++ snps,perfect-filter-entries = <128>; ++ starfive,syscon = <&sysmain 0x70 0>; ++ rx-fifo-depth = <32768>; ++ tx-fifo-depth = <16384>; ++ snps,axi-config = <&stmmac_axi_setup>; ++ snps,fixed-burst; ++ /*snps,force_sf_dma_mode;*/ ++ snps,force_thresh_dma_mode; ++ snps,no-pbl-x8; ++ status = "disabled"; ++ }; ++ ++ dma2p: dma-controller@100b0000 { ++ compatible = "starfive,jh7100-axi-dma"; ++ reg = <0x0 0x100b0000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SGDMA2P_AXI>, ++ <&clkgen JH7100_CLK_SGDMA2P_AHB>; ++ clock-names = "core-clk", "cfgr-clk"; ++ resets = <&rstgen JH7100_RSTN_SGDMA2P_AXI>, ++ <&rstgen JH7100_RSTN_SGDMA2P_AHB>; ++ reset-names = "axi", "ahb"; ++ interrupts = <2>; ++ #dma-cells = <1>; ++ dma-channels = <4>; ++ snps,dma-masters = <1>; ++ snps,data-width = <4>; ++ snps,block-size = <4096 4096 4096 4096>; ++ snps,priority = <0 1 2 3>; ++ snps,axi-max-burst-len = <128>; ++ dma-coherent; ++ }; ++ ++ crypto: crypto@100d0000 { ++ compatible = "starfive,vic-sec"; ++ reg = <0x0 0x100d0000 0x0 0x20000>, ++ <0x0 0x11800234 0x0 0xc>; ++ reg-names = "secmem", "secclk"; ++ clocks = <&clkgen JH7100_CLK_SEC_AHB>; ++ interrupts = <31>; ++ }; ++ ++ i2sadc0: i2sadc0@10400000 { ++ compatible = "snps,designware-i2sadc0"; ++ reg = <0x0 0x10400000 0x0 0x1000>; ++ clocks = <&clkgen JH7100_CLK_APB1_BUS>; ++ clock-names = "i2sclk"; ++ interrupt-parent = <&plic>; ++ #sound-dai-cells = <0>; ++ dmas = <&dma2p 28>; ++ dma-names = "rx"; ++ }; ++ ++ i2svad: i2svad@10420000 { ++ compatible = "starfive,sf-i2svad"; ++ reg = <0x0 0x10420000 0x0 0x1000> ; ++ clocks = <&audclk JH7100_AUDCLK_I2SVAD_APB>; ++ clock-names = "i2svad_apb"; ++ resets = <&audrst JH7100_AUDRSTN_I2SVAD_APB>, ++ <&audrst JH7100_AUDRSTN_I2SVAD_SRST>; ++ reset-names = "apb_i2svad", "i2svad_srst"; ++ interrupts = <60>, <61>; ++ interrupt-names = "spintr", "slintr"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ pwmdac: pwmdac@10440000 { ++ compatible = "starfive,pwmdac"; ++ reg = <0x0 0x10440000 0x0 0x1000>; ++ clocks = <&clkgen JH7100_CLK_AUDIO_ROOT>, ++ <&clkgen JH7100_CLK_AUDIO_SRC>, ++ <&clkgen JH7100_CLK_AUDIO_12288>, ++ <&audclk JH7100_AUDCLK_DMA1P_AHB>, ++ <&audclk JH7100_AUDCLK_PWMDAC_APB>, ++ <&audclk JH7100_AUDCLK_DAC_MCLK>; ++ clock-names = "audio_root", ++ "audio_src", ++ "audio_12288", ++ "dma1p_ahb", ++ "pwmdac_apb", ++ "dac_mclk"; ++ resets = <&audrst JH7100_AUDRSTN_APB_BUS>, ++ <&audrst JH7100_AUDRSTN_DMA1P_AHB>, ++ <&audrst JH7100_AUDRSTN_PWMDAC_APB>; ++ reset-names = "apb_bus", "dma1p_ahb", "apb_pwmdac"; ++ dmas = <&dma2p 23>; ++ dma-names = "tx"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ i2sdac0: i2sdac0@10450000 { ++ compatible = "snps,designware-i2sdac0"; ++ reg = <0x0 0x10450000 0x0 0x1000>; ++ clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>, ++ <&audclk JH7100_AUDCLK_I2SDAC_BCLK>, ++ <&audclk JH7100_AUDCLK_I2SDAC_LRCLK>, ++ <&audclk JH7100_AUDCLK_I2SDAC_APB>; ++ clock-names = "dac_mclk", "i2sdac0_bclk", "i2sdac0_lrclk", "i2sdac_apb"; ++ resets = <&audrst JH7100_AUDRSTN_I2SDAC_APB>, ++ <&audrst JH7100_AUDRSTN_I2SDAC_SRST>; ++ reset-names = "apb_i2sdac", "i2sdac_srst"; ++ #sound-dai-cells = <0>; ++ dmas = <&dma2p 30>; ++ dma-names = "tx"; ++ }; ++ ++ i2sdac1: i2sdac1@10460000 { ++ compatible = "snps,designware-i2sdac1"; ++ reg = <0x0 0x10460000 0x0 0x1000>; ++ clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>, ++ <&audclk JH7100_AUDCLK_I2S1_BCLK>, ++ <&audclk JH7100_AUDCLK_I2S1_LRCLK>, ++ <&audclk JH7100_AUDCLK_I2S1_APB>; ++ clock-names = "dac_mclk", "i2sdac1_bclk", "i2sdac1_lrclk", "i2s1_apb"; ++ resets = <&audrst JH7100_AUDRSTN_I2S1_APB>, ++ <&audrst JH7100_AUDRSTN_I2S1_SRST>; ++ #sound-dai-cells = <0>; ++ dmas = <&dma2p 31>; ++ dma-names = "tx"; ++ }; ++ ++ i2sdac16k: i2sdac16k@10470000 { ++ compatible = "snps,designware-i2sdac16k"; ++ reg = <0x0 0x10470000 0x0 0x1000>; ++ clocks = <&clkgen JH7100_CLK_APB1_BUS>; ++ clock-names = "i2sclk"; ++ #sound-dai-cells = <0>; ++ dmas = <&dma2p 29>; ++ dma-names = "tx"; ++ }; ++ + audclk: clock-controller@10480000 { + compatible = "starfive,jh7100-audclk"; + reg = <0x0 0x10480000 0x0 0x10000>; +@@ -150,6 +367,82 @@ + #reset-cells = <1>; + }; + ++ spdif_transmitter: spdif-transmitter { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ spdif_receiver: spdif-receiver { ++ compatible = "linux,spdif-dir"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ pwmdac_codec: pwmdac-transmitter { ++ compatible = "linux,pwmdac-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ dmic_codec: dmic { ++ compatible = "dmic-codec"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ sound: snd-card { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "Starfive-Multi-Sound-Card"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* pwmdac */ ++ simple-audio-card,dai-link@0 { ++ reg = <0>; ++ status = "okay"; ++ format = "left_j"; ++ bitclock-master = <&sndcpu0>; ++ frame-master = <&sndcpu0>; ++ ++ sndcpu0: cpu { ++ sound-dai = <&pwmdac>; ++ }; ++ ++ codec { ++ sound-dai = <&pwmdac_codec>; ++ }; ++ }; ++ }; ++ ++ usb3: usb@104c0000 { ++ compatible = "cdns,usb3"; ++ reg = <0x0 0x104c0000 0x0 0x10000>, // memory area for HOST registers ++ <0x0 0x104d0000 0x0 0x10000>, // memory area for DEVICE registers ++ <0x0 0x104e0000 0x0 0x10000>; // memory area for OTG/DRD registers ++ reg-names = "otg", "xhci", "dev"; ++ interrupts = <44>, <52>, <43>; ++ interrupt-names = "host", "peripheral", "otg"; ++ phy-names = "cdns3,usb3-phy", "cdns3,usb2-phy"; ++ maximum-speed = "super-speed"; ++ status = "disabled"; ++ }; ++ ++ dma1p: dma-controller@10500000 { ++ compatible = "starfive,jh7100-axi-dma"; ++ reg = <0x0 0x10500000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SGDMA1P_AXI>, ++ <&clkgen JH7100_CLK_SGDMA1P_BUS>; ++ clock-names = "core-clk", "cfgr-clk"; ++ resets = <&rstgen JH7100_RSTN_DMA1P_AXI>, ++ <&rstgen JH7100_RSTN_SGDMA1P_AXI>; ++ reset-names = "axi", "ahb"; ++ interrupts = <1>; ++ #dma-cells = <1>; ++ dma-channels = <16>; ++ snps,dma-masters = <1>; ++ snps,data-width = <3>; ++ snps,block-size = <4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096>; ++ snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; ++ snps,axi-max-burst-len = <64>; ++ }; ++ + clkgen: clock-controller@11800000 { + compatible = "starfive,jh7100-clkgen"; + reg = <0x0 0x11800000 0x0 0x10000>; +@@ -158,12 +451,93 @@ + #clock-cells = <1>; + }; + ++ otp: otp@11810000 { ++ compatible = "starfive,fu740-otp"; ++ reg = <0x0 0x11810000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_OTP_APB>; ++ fuse-count = <0x200>; ++ }; ++ + rstgen: reset-controller@11840000 { + compatible = "starfive,jh7100-reset"; + reg = <0x0 0x11840000 0x0 0x10000>; + #reset-cells = <1>; + }; + ++ sysmain: syscon@11850000 { ++ compatible = "starfive,jh7100-sysmain", "syscon"; ++ reg = <0x0 0x11850000 0x0 0x10000>; ++ }; ++ ++ qspi: spi@11860000 { ++ compatible = "cdns,qspi-nor"; ++ reg = <0x0 0x11860000 0x0 0x10000>, ++ <0x0 0x20000000 0x0 0x20000000>; ++ clocks = <&clkgen JH7100_CLK_QSPI_AHB>; ++ interrupts = <3>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cdns,fifo-depth = <256>; ++ cdns,fifo-width = <4>; ++ cdns,trigger-address = <0x0>; ++ spi-max-frequency = <250000000>; ++ status = "disabled"; ++ }; ++ ++ uart0: serial@11870000 { ++ compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart"; ++ reg = <0x0 0x11870000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_UART0_CORE>, ++ <&clkgen JH7100_CLK_UART0_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&rstgen JH7100_RSTN_UART0_APB>; ++ interrupts = <92>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@11880000 { ++ compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart"; ++ reg = <0x0 0x11880000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_UART1_CORE>, ++ <&clkgen JH7100_CLK_UART1_APB>; ++ clock-names = "baudclk", "apb_pclk"; ++ resets = <&rstgen JH7100_RSTN_UART1_APB>; ++ interrupts = <93>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@11890000 { ++ compatible = "snps,dw-apb-ssi"; ++ reg = <0x0 0x11890000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SPI0_CORE>, ++ <&clkgen JH7100_CLK_SPI0_APB>; ++ clock-names = "ssi_clk", "pclk"; ++ resets = <&rstgen JH7100_RSTN_SPI0_APB>; ++ reset-names = "spi"; ++ interrupts = <94>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@118a0000 { ++ compatible = "snps,dw-apb-ssi"; ++ reg = <0x0 0x118a0000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SPI1_CORE>, ++ <&clkgen JH7100_CLK_SPI1_APB>; ++ clock-names = "ssi_clk", "pclk"; ++ resets = <&rstgen JH7100_RSTN_SPI1_APB>; ++ reset-names = "spi"; ++ interrupts = <95>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + i2c0: i2c@118b0000 { + compatible = "snps,designware-i2c"; + reg = <0x0 0x118b0000 0x0 0x10000>; +@@ -190,6 +564,41 @@ + status = "disabled"; + }; + ++ trng: trng@118d0000 { ++ compatible = "starfive,vic-rng"; ++ reg = <0x0 0x118d0000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_TRNG_APB>; ++ interrupts = <98>; ++ }; ++ ++ vpu_enc: vpu_enc@118e0000 { ++ compatible = "cm,cm521-vpu"; ++ reg = <0x0 0x118e0000 0x0 0x4000>; ++ reg-names = "control"; ++ clocks = <&clkgen JH7100_CLK_VP6_CORE>; ++ clock-names = "vcodec"; ++ interrupts = <26>; ++ }; ++ ++ vpu_dec: vpu_dec@118f0000 { ++ compatible = "c&m,cm511-vpu"; ++ reg = <0 0x118f0000 0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_VP6_CORE>; ++ clock-names = "vcodec"; ++ interrupts = <23>; ++ //memory-region = <&vpu_reserved>; ++ }; ++ ++ jpu: coadj12@11900000 { ++ compatible = "cm,codaj12-jpu-1"; ++ reg = <0x0 0x11900000 0x0 0x300>; ++ reg-names = "control"; ++ clocks = <&clkgen JH7100_CLK_JPEG_APB>; ++ clock-names = "jpege"; ++ interrupts = <24>; ++ memory-region = <&jpu_reserved>; ++ }; ++ + gpio: pinctrl@11910000 { + compatible = "starfive,jh7100-pinctrl"; + reg = <0x0 0x11910000 0x0 0x10000>, +@@ -204,6 +613,86 @@ + #interrupt-cells = <2>; + }; + ++ nvdla@11940000 { ++ compatible = "nvidia,nvdla_os_initial"; ++ interrupts = <22>; ++ memory-region = <&nvdla_reserved>; ++ reg = <0x0 0x11940000 0x0 0x40000>; ++ status = "okay"; ++ }; ++ ++ display: display-subsystem { ++ compatible = "starfive,display-subsystem"; ++ dma-coherent; ++ status = "disabled"; ++ }; ++ ++ encoder: display-encoder { ++ compatible = "starfive,display-encoder"; ++ status = "disabled"; ++ }; ++ ++ crtc: crtc@12000000 { ++ compatible = "starfive,jh7100-crtc"; ++ reg = <0x0 0x12000000 0x0 0x10000>, ++ <0x0 0x12040000 0x0 0x10000>, ++ <0x0 0x12080000 0x0 0x10000>, ++ <0x0 0x120c0000 0x0 0x10000>, ++ <0x0 0x12240000 0x0 0x10000>, ++ <0x0 0x12250000 0x0 0x10000>, ++ <0x0 0x12260000 0x0 0x10000>; ++ reg-names = "lcdc", "vpp0", "vpp1", "vpp2", "clk", "rst", "sys"; ++ clocks = <&clkgen JH7100_CLK_DISP_AXI>, <&clkgen JH7100_CLK_VOUT_SRC>; ++ clock-names = "disp_axi", "vout_src"; ++ resets = <&rstgen JH7100_RSTN_DISP_AXI>, <&rstgen JH7100_RSTN_VOUT_SRC>; ++ reset-names = "disp_axi", "vout_src"; ++ interrupts = <101>, <103>; ++ interrupt-names = "lcdc_irq", "vpp1_irq"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ pp1 { ++ pp-id = <1>; ++ fifo-out; ++ //sys-bus-out; ++ src-format = <11>; //; ++ src-width = <1920>; ++ src-height = <1080>; ++ dst-format = <7>; //; ++ dst-width = <1920>; ++ dst-height = <1080>; ++ }; ++ }; ++ ++ spi2: spi@12410000 { ++ compatible = "snps,dw-apb-ssi"; ++ reg = <0x0 0x12410000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SPI2_CORE>, ++ <&clkgen JH7100_CLK_SPI2_APB>; ++ clock-names = "ssi_clk", "pclk"; ++ resets = <&rstgen JH7100_RSTN_SPI2_APB>; ++ reset-names = "spi"; ++ interrupts = <70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi3: spi@12420000 { ++ compatible = "snps,dw-apb-ssi"; ++ reg = <0x0 0x12420000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_SPI3_CORE>, ++ <&clkgen JH7100_CLK_SPI3_APB>; ++ clock-names = "ssi_clk", "pclk"; ++ resets = <&rstgen JH7100_RSTN_SPI3_APB>; ++ reset-names = "spi"; ++ interrupts = <71>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + uart2: serial@12430000 { + compatible = "starfive,jh7100-uart", "snps,dw-apb-uart"; + reg = <0x0 0x12430000 0x0 0x10000>; +@@ -265,5 +754,77 @@ + resets = <&rstgen JH7100_RSTN_WDTIMER_APB>, + <&rstgen JH7100_RSTN_WDT>; + }; ++ ++ ptc: pwm@12490000 { ++ compatible = "starfive,pwm0"; ++ reg = <0x0 0x12490000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_PWM_APB>; ++ resets = <&rstgen JH7100_RSTN_PWM_APB>; ++ #pwm-cells = <3>; ++ sifive,npwm = <8>; ++ status = "disabled"; ++ }; ++ ++ sfctemp: tmon@124a0000 { ++ compatible = "starfive,jh7100-temp"; ++ reg = <0x0 0x124a0000 0x0 0x10000>; ++ clocks = <&clkgen JH7100_CLK_TEMP_SENSE>, ++ <&clkgen JH7100_CLK_TEMP_APB>; ++ clock-names = "sense", "bus"; ++ resets = <&rstgen JH7100_RSTN_TEMP_SENSE>, ++ <&rstgen JH7100_RSTN_TEMP_APB>; ++ reset-names = "sense", "bus"; ++ interrupts = <122>; ++ #thermal-sensor-cells = <0>; ++ }; ++ ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <15000>; ++ ++ thermal-sensors = <&sfctemp>; ++ ++ cooling-maps { ++ }; ++ ++ trips { ++ cpu_alert0: cpu_alert0 { ++ /* milliCelsius */ ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_crit: cpu_crit { ++ /* milliCelsius */ ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ ++ xrp@f0000000 { ++ compatible = "cdns,xrp"; ++ reg = <0x0 0xf0000000 0x0 0x01ffffff>, ++ <0x10 0x72000000 0x0 0x00001000>, ++ <0x10 0x72001000 0x0 0x00fff000>, ++ <0x0 0x124b0000 0x0 0x00010000>; ++ clocks = <&clkgen JH7100_CLK_VP6_CORE>; ++ interrupts = <27>, <28>; ++ firmware-name = "vp6_elf"; ++ dsp-irq = <19 20>; ++ dsp-irq-src = <0x20 0x21>; ++ intc-irq-mode = <1>; ++ intc-irq = <0 1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x40000000 0x0 0x40000000 0x01000000>, ++ <0xb0000000 0x10 0x70000000 0x3000000>; ++ dsp@0 { ++ }; ++ }; + }; + }; diff --git a/target/linux/starfive/patches-6.1/1025-riscv-dts-visionfive1-enable-QSPI.patch b/target/linux/starfive/patches-6.1/1025-riscv-dts-visionfive1-enable-QSPI.patch new file mode 100644 index 0000000000..7d190a5fc0 --- /dev/null +++ b/target/linux/starfive/patches-6.1/1025-riscv-dts-visionfive1-enable-QSPI.patch @@ -0,0 +1,20 @@ +From 21e0e009b1bffea86890fcbf6e1be4c4121258ef Mon Sep 17 00:00:00 2001 +From: Zoltan HERPAI +Date: Fri, 11 Aug 2023 11:28:27 +0200 +Subject: [PATCH 1025/1025] riscv: dts: visionfive1: enable QSPI + +Signed-off-by: Zoltan HERPAI +--- + .../riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts ++++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts +@@ -37,3 +37,7 @@ + reg = <0>; + }; + }; ++ ++&qspi { ++ status = "okay"; ++}; From ce1138867c4b4843e945ccd97144ccf4feeca1d0 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Tue, 22 Aug 2023 23:39:14 +0200 Subject: [PATCH 017/108] mac80211: select BRCMFMAC_SDIO on starfive As the Visionfive V1 board has an Ampak module connected via SDIO, enable support for SDIO in the brcmfmac module. Signed-off-by: Zoltan HERPAI --- package/kernel/mac80211/broadcom.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/package/kernel/mac80211/broadcom.mk b/package/kernel/mac80211/broadcom.mk index d0b0889088..a6f42cd19a 100644 --- a/package/kernel/mac80211/broadcom.mk +++ b/package/kernel/mac80211/broadcom.mk @@ -434,6 +434,7 @@ define KernelPackage/brcmfmac/config bool "Enable SDIO bus interface support" default y if TARGET_bcm27xx default y if TARGET_imx_cortexa7 + default y if TARGET_starfive default y if TARGET_rockchip default y if TARGET_sunxi default n From 1a6954337634474e6c42dec6023daa7af1d52432 Mon Sep 17 00:00:00 2001 From: Kyle Hendry Date: Sun, 18 Feb 2024 12:26:38 -0800 Subject: [PATCH 018/108] bmips: add support for SmartRG SR505n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specifications: - SoC: Broadcom BCM63168 dual 400MHz MIPS - Flash: 16MB SPI NOR W25Q128WFG - RAM: 128MB DDR3 W631GG6KB-15 - Ethernet: 1x 1000M, 3x 100M - Wifi: BCM435F - 1x USB 2.0 port - 3x Button - 12x LED Flashing via serial - Connect to the 3.3V TTL UART on the board (J6 pinout Vcc Rx Tx Gnd) at 115200-8-N-1 - Press any key in the serial console when powering up the board to enter the CFE prompt - Configure an interface on your workstation to static IP 192.168.1.100 and connect it to the board - Start a TFTP server with the firmware image - On the CFE prompt, enter the command "f 192.168.1.100:openwrt-bmips-bcm63268-smartrg_sr505n-squashfs-cfe.bin" Signed-off-by: Kyle Hendry [Remove unneeded LED labels] Signed-off-by: Álvaro Fernández Rojas --- .../bcm63268/base-files/etc/board.d/01_leds | 3 + .../base-files/etc/board.d/02_network | 3 +- .../bmips/dts/bcm63168-smartrg-sr505n.dts | 238 ++++++++++++++++++ target/linux/bmips/image/bcm63268.mk | 14 ++ 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 target/linux/bmips/dts/bcm63168-smartrg-sr505n.dts diff --git a/target/linux/bmips/bcm63268/base-files/etc/board.d/01_leds b/target/linux/bmips/bcm63268/base-files/etc/board.d/01_leds index d5b65a9c0f..8af1b77504 100644 --- a/target/linux/bmips/bcm63268/base-files/etc/board.d/01_leds +++ b/target/linux/bmips/bcm63268/base-files/etc/board.d/01_leds @@ -9,6 +9,9 @@ case "$(board_name)" in comtrend,vr-3032u) ucidef_set_led_usbport "usb" "USB" "green:usb" "usb1-port1" "usb2-port1" ;; +smartrg,sr505n) + ucidef_set_led_usbport "usb" "USB" "green:usb" "usb1-port1" + ;; sercomm,h500-s-lowi |\ sercomm,h500-s-vfes) ucidef_set_led_netdev "wan" "WAN" "green:internet" "wan" diff --git a/target/linux/bmips/bcm63268/base-files/etc/board.d/02_network b/target/linux/bmips/bcm63268/base-files/etc/board.d/02_network index 7fb9333cc1..74b74691cb 100644 --- a/target/linux/bmips/bcm63268/base-files/etc/board.d/02_network +++ b/target/linux/bmips/bcm63268/base-files/etc/board.d/02_network @@ -5,7 +5,8 @@ board_config_update case "$(board_name)" in -comtrend,vr-3032u) +comtrend,vr-3032u |\ +smartrg,sr505n) ucidef_set_bridge_device switch ucidef_set_interface_lan "lan1 lan2 lan3 lan4" ;; diff --git a/target/linux/bmips/dts/bcm63168-smartrg-sr505n.dts b/target/linux/bmips/dts/bcm63168-smartrg-sr505n.dts new file mode 100644 index 0000000000..571289b4c6 --- /dev/null +++ b/target/linux/bmips/dts/bcm63168-smartrg-sr505n.dts @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "bcm63268.dtsi" + +/ { + model = "SmartRG SR505n"; + compatible = "smartrg,sr505n", "brcm,bcm63168", "brcm,bcm63268"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_green; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio 32 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + + wps { + label = "wps"; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + + wlan { + label = "wlan"; + gpios = <&gpio 34 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + }; +}; + +&ehci { + status = "okay"; +}; + +ðernet { + status = "okay"; + + nvmem-cells = <&macaddr_cfe_6a0>; + nvmem-cell-names = "mac-address"; +}; + +&hsspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <16666667>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + reg = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "cfe"; + reg = <0x000000 0x010000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_cfe_6a0: macaddr@6a0 { + reg = <0x6a0 0x6>; + }; + }; + }; + + partition@10000 { + compatible = "brcm,bcm963xx-imagetag"; + label = "firmware"; + reg = <0x010000 0xfd0000>; + }; + + partition@fe0000 { + label = "nvram"; + reg = <0xfe0000 0x020000>; + }; + }; + }; +}; + +&leds { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + wps_green@1 { + reg = <1>; + active-low; + function = LED_FUNCTION_WPS; + color = ; + }; + + inet_green@8 { + reg = <8>; + active-low; + label = "green:inet"; + }; + + lan2_green@9 { + /* EPHY1 Act */ + reg = <9>; + brcm,hardware-controlled; + }; + + lan3_green@10 { + /* EPHY2 Act */ + reg = <10>; + brcm,hardware-controlled; + }; + + lan4_green@11 { + /* EPHY3 Act */ + reg = <11>; + brcm,hardware-controlled; + }; + + lan1_green@12 { + /* GPHY0 Act */ + reg = <12>; + brcm,hardware-controlled; + }; + + dsl_green@14 { + reg = <14>; + active-low; + label = "green:dsl"; + }; + + inet_red@15 { + reg = <15>; + active-low; + label = "red:inet"; + }; + + usb_green@16 { + reg = <16>; + active-low; + function = LED_FUNCTION_USB; + color = ; + }; + + led_power_green: power_green@20 { + reg = <20>; + active-low; + function = LED_FUNCTION_POWER; + color = ; + }; + + led_power_red: power_red@21 { + reg = <21>; + active-low; + function = LED_FUNCTION_POWER; + color = ; + panic-indicator; + }; +}; + +&pinctrl { + pinctrl_leds: leds { + function = "led"; + pins = "gpio1", "gpio8", + "gpio9", "gpio10", + "gpio11", "gpio12", + "gpio14", "gpio15", + "gpio16", "gpio20", + "gpio21"; + }; +}; + +&ohci { + status = "okay"; +}; + +&switch0 { + ports { + port@0 { + reg = <0>; + label = "lan2"; + + phy-handle = <&phy1>; + phy-mode = "mii"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + + phy-handle = <&phy2>; + phy-mode = "mii"; + }; + + port@2 { + reg = <2>; + label = "lan4"; + + phy-handle = <&phy3>; + phy-mode = "mii"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + + phy-handle = <&phy4>; + phy-mode = "gmii"; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&usbh { + status = "okay"; +}; diff --git a/target/linux/bmips/image/bcm63268.mk b/target/linux/bmips/image/bcm63268.mk index 941e83f71b..be3403174e 100644 --- a/target/linux/bmips/image/bcm63268.mk +++ b/target/linux/bmips/image/bcm63268.mk @@ -100,3 +100,17 @@ define Device/sercomm_shg2500 SERCOMM_SWVER := 3207 endef TARGET_DEVICES += sercomm_shg2500 + +define Device/smartrg_sr505n + $(Device/bcm63xx-cfe) + DEVICE_VENDOR := SmartRG + DEVICE_MODEL := SR505n + DEVICE_LOADADDR := $(KERNEL_LOADADDR) + CHIP_ID := 63268 + SOC := bcm63168 + CFE_BOARD_ID := 963168MBV_17AZZ + FLASH_MB := 16 + DEVICE_PACKAGES += $(USB2_PACKAGES) \ + kmod-leds-bcm6328 +endef +TARGET_DEVICES += smartrg_sr505n From 3561015efdfb3a6c268f723f509f5cd2720efdb8 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Fri, 23 Feb 2024 22:54:48 +0100 Subject: [PATCH 019/108] scripts: Kernel bumper script For years, we have struggled and been frustrated at loosing history of files in git, due to the 'copy + add' strategy. This could have been prevented with a double-commit 'mv + add' trick. On the mailing list [0] the discussion was started to put the instructions in a wiki. Instead, it is much better to just script it and put it in the repo. Instead of doing mv + copy, which leads to two commits, but no history on the copied files, it uses move, + copy and merge, which results in three (merge) commits, but keeps the history of all files. As always with renames, `--follow` will be needed. The tool is trivial and works either in the OpenWrt git root directory, or in the actual target directory. Tested on the `realtek` and generic targets. Note, that the tool does not do any of the labor needed after the move, such as updating configs, dropping patches etc. To make sure this script is easily found by any developer, who just wants to do a kernel bump, the script is added here and not to maintainer-tools repo as those scripts are a little bit more specialized. Bumping a kernel is a trivial task that often regular developers do, where most do not even know the existence of maintainer tools, are not part of the main repo they'd clone, not part of the docker container they'd use and so discoverability is probably much more important. [0]: https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html Signed-off-by: Olliver Schinagl Tested-by: Robert Marko Tested-by: Weijie Gao --- scripts/kernel_bump.sh | 225 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100755 scripts/kernel_bump.sh diff --git a/scripts/kernel_bump.sh b/scripts/kernel_bump.sh new file mode 100755 index 0000000000..5896bfc48f --- /dev/null +++ b/scripts/kernel_bump.sh @@ -0,0 +1,225 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024 Olliver Schinagl + +set -eu +if [ -n "${DEBUG_TRACE_SH:-}" ] && \ + [ "${DEBUG_TRACE_SH:-}" != "${DEBUG_TRACE_SH#*"$(basename "${0}")"*}" ] || \ + [ "${DEBUG_TRACE_SH:-}" = 'all' ]; then + set -x +fi + +REQUIRED_COMMANDS=' + [ + basename + command + echo + exit + git + printf + set + shift +' + +_msg() +{ + _level="${1:?Missing argument to function}" + shift + + if [ "${#}" -le 0 ]; then + echo "${_level}: No content for this message ..." + return + fi + + echo "${_level}: ${*}" +} + +e_err() +{ + _msg 'err' "${*}" >&2 +} + +e_warn() +{ + _msg 'warning' "${*}" +} + +e_notice() +{ + _msg 'notice' "${*}" +} + +usage() +{ + echo "Usage: ${0}" + echo 'Helper script to bump the target kernel version, whilst keeping history.' + echo " -p Optional Platform name (e.g. 'ath79' [PLATFORM_NAME]" + echo " -s Source version of kernel (e.g. 'v6.1' [SOURCE_VERSION])" + echo " -t Target version of kernel (e.g. 'v6.6' [TARGET_VERSION]')" + echo + echo 'All options can also be passed in environment variables (listed between [BRACKETS]).' + echo 'Example: scripts/kernel_bump.sh -p realtek -s v6.1 -t v6.6' +} + +cleanup() +{ + trap - EXIT HUP INT QUIT ABRT ALRM TERM + + if [ -n "${initial_branch:-}" ] && \ + [ "$(git rev-parse --abbrev-ref HEAD)" != "${initial_branch:-}" ]; then + git switch "${initial_branch}" + fi +} + +init() +{ + initial_branch="$(git rev-parse --abbrev-ref HEAD)" + initial_commitish="$(git rev-parse HEAD)" + + trap cleanup EXIT HUP INT QUIT ABRT ALRM TERM +} + +do_source_target() +{ + _target_dir="${1:?Missing argument to function}" + _op="${2:?Missing argument to function}" + +} + +bump_kernel() +{ + platform_name="${platform_name##*'/'}" + + if [ -z "${platform_name:-}" ]; then + platform_name="${PWD##*'/'}" + fi + + if [ "${PWD##*'/'}" = "${platform_name}" ]; then + _target_dir='./' + else + _target_dir="target/linux/${platform_name}" + fi + + if [ ! -d "${_target_dir}/image" ]; then + e_err 'Cannot find target linux directory.' + exit 1 + fi + + git switch --force-create '__openwrt_kernel_files_mover' + + for _path in "${_target_dir}/"*; do + if [ ! -s "${_path}" ] || \ + [ "${_path}" = "${_path%%"-${source_version}"}" ]; then + continue + fi + + _target_path="${_path%%"-${source_version}"}-${target_version}" + if [ -s "${_target_path}" ]; then + e_err "Target '${_target_path}' already exists!" + exit 1 + fi + + git mv \ + "${_path}" \ + "${_target_path}" + done + + find "${_target_dir}" -iname "config-${source_version}" | while read -r _config; do + _path="${_config%%"/config-${source_version}"}" + git mv "${_config}" "${_path}/config-${target_version}" + done + + git commit \ + --signoff \ + --message "kernel/${platform_name}: Create kernel files for v${target_version} (from v${source_version})" \ + --message 'This is an automatically generated commit.' \ + --message 'During a `git bisect` session, `git bisect --skip` is recommended.' + + git checkout 'HEAD~' "${_target_dir}" + git commit \ + --signoff \ + --message "kernel/${platform_name}: Restore kernel files for v${source_version}" \ + --message "$(printf "This is an automatically generated commit which aids following Kernel patch history,\nas git will see the move and copy as a rename thus defeating the purpose.\n\nSee: https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html\nfor the original discussion.")" + git switch "${initial_branch:?Unable to switch back to original branch. Quitting.}" + GIT_EDITOR=true git merge --no-ff '__openwrt_kernel_files_mover' + git branch --delete '__openwrt_kernel_files_mover' + + echo "Original commitish was '${initial_commitish}'." + echo 'Kernel bump complete. Remember to use `git log --follow`.' +} + +check_requirements() +{ + for _cmd in ${REQUIRED_COMMANDS}; do + if ! _test_result="$(command -V "${_cmd}")"; then + _test_result_fail="${_test_result_fail:-}${_test_result}\n" + else + _test_result_pass="${_test_result_pass:-}${_test_result}\n" + fi + done + + echo 'Available commands:' + # As the results contain \n, we expect these to be interpreted. + # shellcheck disable=SC2059 + printf "${_test_result_pass:-none\n}" + echo + echo 'Missing commands:' + # shellcheck disable=SC2059 + printf "${_test_result_fail:-none\n}" + echo + + if [ -n "${_test_result_fail:-}" ]; then + echo 'Command test failed, missing programs.' + test_failed=1 + fi +} + +main() +{ + while getopts 'hp:s:t:' _options; do + case "${_options}" in + 'h') + usage + exit 0 + ;; + 'p') + platform_name="${OPTARG}" + ;; + 's') + source_version="${OPTARG#v}" + ;; + 't') + target_version="${OPTARG#v}" + ;; + ':') + e_err "Option -${OPTARG} requires an argument." + exit 1 + ;; + *) + e_err "Invalid option: -${OPTARG}" + exit 1 + ;; + esac + done + shift "$((OPTIND - 1))" + + platform_name="${platform_name:-${PLATFORM_NAME:-}}" + source_version="${source_version:-${SOURCE_VERSION:-}}" + target_version="${target_version:-${TARGET_VERSION:-}}" + + if [ -z "${source_version:-}" ] || [ -z "${target_version:-}" ]; then + e_err "Source (${source_version}) and target (${target_version}) versions need to be defined." + exit 1 + fi + + check_requirements + + init + bump_kernel + cleanup +} + +main "${@}" + +exit 0 From 838a27f64f56e75aae98a3ab2556856224d48d8b Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 18 Feb 2024 13:12:10 +0000 Subject: [PATCH 020/108] dnsmasq: version 2.90 Bump to 2.90 to get upstream's fix for DNSSEC KeyTrap (CVE-2023-50387, CVE-2023-50868) among many other goodies and fixes (notably, upstream 568fb024... fixes a UAF in cache_remove_uid that was routinely crashing dnsmasq in my deployment). Catch up our 200-ubus_dns.patch, too. Signed-off-by: Nathaniel Wesley Filardo --- package/network/services/dnsmasq/Makefile | 4 +- .../dnsmasq/patches/200-ubus_dns.patch | 118 +++++++++--------- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index e33d866304..d2de74d9da 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_UPSTREAM_VERSION:=2.89 +PKG_UPSTREAM_VERSION:=2.90 PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION))) PKG_RELEASE:=8 PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq/ -PKG_HASH:=02bd230346cf0b9d5909f5e151df168b2707103785eb616b56685855adebb609 +PKG_HASH:=8e50309bd837bfec9649a812e066c09b6988b73d749b7d293c06c57d46a109e4 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/network/services/dnsmasq/patches/200-ubus_dns.patch b/package/network/services/dnsmasq/patches/200-ubus_dns.patch index ccbe70ab9c..c1694d5551 100644 --- a/package/network/services/dnsmasq/patches/200-ubus_dns.patch +++ b/package/network/services/dnsmasq/patches/200-ubus_dns.patch @@ -1,6 +1,23 @@ +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 30fb419..776351a 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -2025,6 +2025,10 @@ static void check_dns_listeners(time_t now) + daemon->pipe_to_parent = pipefd[1]; + } + ++#ifdef HAVE_UBUS ++ drop_ubus_listeners(); ++#endif ++ + /* start with no upstream connections. */ + for (s = daemon->servers; s; s = s->next) + s->tcpfd = -1; +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index e455c3f..c84ba48 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -1631,14 +1631,26 @@ void emit_dbus_signal(int action, struct +@@ -1673,14 +1673,26 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname); /* ubus.c */ #ifdef HAVE_UBUS @@ -11,6 +28,7 @@ void set_ubus_listeners(void); void check_ubus_listeners(void); +void drop_ubus_listeners(void); ++int ubus_dns_notify_has_subscribers(void); +struct blob_buf *ubus_dns_notify_prepare(void); +int ubus_dns_notify(const char *type, ubus_dns_notify_cb cb, void *priv); void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface); @@ -19,14 +37,28 @@ void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *pattern, const char *ip, u32 ttl); # endif +#else -+struct blob_buf; -+static inline struct blob_buf *ubus_dns_notify_prepare(void) ++static inline int ubus_dns_notify_has_subscribers(void) +{ -+ return NULL; ++ return 0; +} #endif /* ipset.c */ +diff --git a/src/forward.c b/src/forward.c +index 32f37e4..3d28963 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -803,7 +803,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + cache_secure = 0; + } + +- if (daemon->doctors && do_doctor(header, n, daemon->namebuff)) ++ if ((daemon->doctors || ubus_dns_notify_has_subscribers()) && do_doctor(header, n, daemon->namebuff)) + cache_secure = 0; + + /* check_for_bogus_wildcard() does it's own caching, so +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 387d894..7bf7967 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -13,8 +13,10 @@ @@ -41,7 +73,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, char *name, int isExtract, int extrabytes) -@@ -394,9 +396,64 @@ static int private_net6(struct in6_addr +@@ -384,10 +386,65 @@ static int private_net6(struct in6_addr *a, int ban_localhost) ((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */ } @@ -100,14 +132,15 @@ +} +#endif + - static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, int *doctored) + int do_doctor(struct dns_header *header, size_t qlen, char *namebuff) { + unsigned char *p; - int i, qtype, qclass, rdlen; + int i, qtype, qclass, rdlen, ttl; - - for (i = count; i != 0; i--) - { -@@ -405,7 +462,7 @@ static unsigned char *do_doctor(unsigned + int done = 0; + + if (!(p = skip_questions(header, qlen))) +@@ -404,7 +461,7 @@ int do_doctor(struct dns_header *header, size_t qlen, char *namebuff) GETSHORT(qtype, p); GETSHORT(qclass, p); @@ -116,53 +149,36 @@ GETSHORT(rdlen, p); if (qclass == C_IN && qtype == T_A) -@@ -416,6 +473,9 @@ static unsigned char *do_doctor(unsigned +@@ -415,6 +472,9 @@ int do_doctor(struct dns_header *header, size_t qlen, char *namebuff) if (!CHECK_LEN(header, p, qlen, INADDRSZ)) - return 0; + return done; + if (ubus_dns_doctor(daemon->namebuff, ttl, p, AF_INET)) -+ *doctored = 1; ++ header->hb3 &= ~HB3_AA; + /* alignment */ - memcpy(&addr, p, INADDRSZ); + memcpy(&addr.addr4, p, INADDRSZ); -@@ -433,13 +493,22 @@ static unsigned char *do_doctor(unsigned - addr.s_addr &= ~doctor->mask.s_addr; - addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr); - /* Since we munged the data, the server it came from is no longer authoritative */ -- header->hb3 &= ~HB3_AA; - *doctored = 1; - memcpy(p, &addr, INADDRSZ); +@@ -444,6 +504,14 @@ int do_doctor(struct dns_header *header, size_t qlen, char *namebuff) break; } } -- + else if (qclass == C_IN && qtype == T_AAAA) + { + if (!CHECK_LEN(header, p, qlen, IN6ADDRSZ)) + return 0; + + if (ubus_dns_doctor(daemon->namebuff, ttl, p, AF_INET6)) -+ *doctored = 1; ++ header->hb3 &= ~HB3_AA; + } -+ -+ if (*doctored) -+ header->hb3 &= ~HB3_AA; + if (!ADD_RDLEN(header, p, qlen, rdlen)) - return 0; /* bad packet */ - } -@@ -570,7 +639,7 @@ int extract_addresses(struct dns_header - cache_start_insert(); - - /* find_soa is needed for dns_doctor side effects, so don't call it lazily if there are any. */ -- if (daemon->doctors || option_bool(OPT_DNSSEC_VALID)) -+ if (daemon->doctors || option_bool(OPT_DNSSEC_VALID) || ubus_dns_notify_prepare()) - { - searched_soa = 1; - ttl = find_soa(header, qlen, doctored); + return done; /* bad packet */ +diff --git a/src/ubus.c b/src/ubus.c +index a5758e7..f2a75a8 100644 --- a/src/ubus.c +++ b/src/ubus.c -@@ -72,6 +72,13 @@ static struct ubus_object ubus_object = +@@ -72,6 +72,13 @@ static struct ubus_object ubus_object = { .subscribe_cb = ubus_subscribe_cb, }; @@ -176,7 +192,7 @@ static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) { (void)ctx; -@@ -105,13 +112,21 @@ static void ubus_disconnect_cb(struct ub +@@ -105,13 +112,21 @@ static void ubus_disconnect_cb(struct ubus_context *ubus) char *ubus_init() { struct ubus_context *ubus = NULL; @@ -216,15 +232,18 @@ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) -@@ -328,6 +354,50 @@ fail: +@@ -328,6 +354,53 @@ fail: } \ } while (0) ++int ubus_dns_notify_has_subscribers(void) ++{ ++ return (daemon->ubus && ubus_dns_object.has_subscribers); ++} ++ +struct blob_buf *ubus_dns_notify_prepare(void) +{ -+ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; -+ -+ if (!ubus || !ubus_dns_object.has_subscribers) ++ if (!ubus_dns_notify_has_subscribers()) + return NULL; + + blob_buf_init(&b, 0); @@ -267,16 +286,3 @@ void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface) { struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -2003,6 +2003,10 @@ static void check_dns_listeners(time_t n - daemon->pipe_to_parent = pipefd[1]; - } - -+#ifdef HAVE_UBUS -+ drop_ubus_listeners(); -+#endif -+ - /* start with no upstream connections. */ - for (s = daemon->servers; s; s = s->next) - s->tcpfd = -1; From 97eb3bf76c17328f80554e6a3603de00d835e4c5 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 15:57:28 +0100 Subject: [PATCH 021/108] lldpd: fix -k 'lldp_no_version' row Supplementary fix for PR #14193 and commit b67182008fd124706be0ec3ce67347447554ffd5 Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index f90b4a237c..d4642238a3 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -290,7 +290,7 @@ start_service() { fi [ $readonly_mode -gt 0 ] && procd_append_param command '-r' - [ $lldp_no_version -gt 0 ] && procd_append_param commanpackage/network/services/lldpd/Makefile package/network/services/lldpd/files/lldpd.initd '-k' + [ $lldp_no_version -gt 0 ] && procd_append_param command '-k' [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ] && [ $lldpmed_no_inventory -gt 0 ] && procd_append_param command '-i' [ -n "$lldp_class" ] && procd_append_param command -M "$lldp_class" [ "$CONFIG_LLDPD_WITH_SNMP" == "y" ] && [ -n "$agentxsocket" ] && procd_append_param command -x -X "$agentxsocket" From 1909b6f8835c1381f859c85394defe993e016edd Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 15:59:27 +0100 Subject: [PATCH 022/108] lldpd: spell fixes Supplementary fix for PR #14193 Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index d4642238a3..c6d7b82c2c 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -261,7 +261,7 @@ start_service() { if [ "$CONFIG_LLDPD_WITH_FDP" == "y" ] && [ $enable_fdp -gt 0 ]; then if [ $force_fdp -gt 0 ]; then - # FDP enbled and forced + # FDP enabled and forced procd_append_param command '-ff' else # FDP enabled @@ -281,10 +281,10 @@ start_service() { if [ "$CONFIG_LLDPD_WITH_EDP" == "y" ] && [ $enable_edp -gt 0 ]; then if [ $force_edp -gt 0 ]; then - # EDP enbled and forced + # EDP enabled and forced procd_append_param command '-ee' else - # EDP enbled + # EDP enabled procd_append_param command '-e' fi fi From 4fb8fea6de363aeeeca029ed9801b85cdbf45f0c Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 20:26:13 +0100 Subject: [PATCH 023/108] lldpd: fix a paste error from commit 1be2088a5247b2cfabe8be991c1e52ddaf780a16 The original PR #13018 did not exhibit this. Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index c6d7b82c2c..fc24b9f7cd 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -75,7 +75,8 @@ get_config_restart_hash() { } get_config_cid_ifaces() { - local _ifacesCONFIG_LLDPD_WITH_FDP + local _ifaces + config_get _ifaces 'config' 'cid_interface' local _iface _ifnames="" for _iface in $_ifaces; do From 20a4dddeb0366a56c14f9128392ffe8d0b62e32d Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:31:57 +0100 Subject: [PATCH 024/108] lldpd: remove unneeded quotes and variable quoting from commit 24176a6bdd8f26040a97960868fd0d9ee968d695 Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index fc24b9f7cd..47354f3c4e 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -148,7 +148,7 @@ write_lldpd_conf() [ -n "$lldp_syscapabilities" ] && echo "configure system capabilities enabled" "\"$lldp_syscapabilities\"" >> "$LLDPD_CONF" if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ] && [ $lldpmed_fast_start -gt 0 ]; then if [ $lldpmed_fast_start_tx_interval -gt 0 ]; then - echo "configure med fast-start tx-interval" "\"$lldpmed_fast_start_tx_interval\"" >> "$LLDPD_CONF" + echo "configure med fast-start tx-interval $lldpmed_fast_start_tx_interval" >> "$LLDPD_CONF" else echo "configure med fast-start" "enable" >> "$LLDPD_CONF" fi From 82ec853284e44fb85ad702879d18857bd566c7db Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:31:29 +0100 Subject: [PATCH 025/108] lldpd: remove unneeded quotes from commit 3ce909914a12647bec52bcee0a162dd6d158a4f6 Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 47354f3c4e..6af15691e7 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -150,7 +150,7 @@ write_lldpd_conf() if [ $lldpmed_fast_start_tx_interval -gt 0 ]; then echo "configure med fast-start tx-interval $lldpmed_fast_start_tx_interval" >> "$LLDPD_CONF" else - echo "configure med fast-start" "enable" >> "$LLDPD_CONF" + echo "configure med fast-start enable" >> "$LLDPD_CONF" fi fi [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF" From b039641071b1e9ee9654513ef3229bb97cc379af Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:29:37 +0100 Subject: [PATCH 026/108] lldpd: remove unneeded quotes and variable quoting from commit 3ce909914a12647bec52bcee0a162dd6d158a4f6 'capabilities enabled x' where x is a string of CSV Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 6af15691e7..3fc47bb3e3 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -145,7 +145,7 @@ write_lldpd_conf() [ -n "$lldp_description" ] && echo "configure system description" "\"$lldp_description\"" >> "$LLDPD_CONF" [ -n "$lldp_hostname" ] && echo "configure system hostname" "\"$lldp_hostname\"" >> "$LLDPD_CONF" [ -n "$lldp_mgmt_ip" ] && echo "configure system ip management pattern" "\"$lldp_mgmt_ip\"" >> "$LLDPD_CONF" - [ -n "$lldp_syscapabilities" ] && echo "configure system capabilities enabled" "\"$lldp_syscapabilities\"" >> "$LLDPD_CONF" + [ -n "$lldp_syscapabilities" ] && echo "configure system capabilities enabled $lldp_syscapabilities" >> "$LLDPD_CONF" if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ] && [ $lldpmed_fast_start -gt 0 ]; then if [ $lldpmed_fast_start_tx_interval -gt 0 ]; then echo "configure med fast-start tx-interval $lldpmed_fast_start_tx_interval" >> "$LLDPD_CONF" From 24a4da527f7e70d9916439a78298de2f4e4af653 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:42:11 +0100 Subject: [PATCH 027/108] lldpd: remove unneeded quotes and variable quoting from commit c98ee4dbb3db0f064d990941cdd82e872da76946 agent-type takes 1 of 3 possible keywords which do not require quoting: configure lldp agent-type nearest-bridge | nearest-non-tpmr-bridge | nearest-customer-bridge Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 3fc47bb3e3..243a32c937 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -153,7 +153,7 @@ write_lldpd_conf() echo "configure med fast-start enable" >> "$LLDPD_CONF" fi fi - [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF" + [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type $lldp_agenttype" >> "$LLDPD_CONF" [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype" "\"$lldp_portidsubtype\"" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" [ $lldp_tx_interval -gt 0 ] && echo "configure lldp tx-interval" "$lldp_tx_interval" >> "$LLDPD_CONF" From bd1b17d589bc622408cebdd9fa0f43386cc3ef5a Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:44:56 +0100 Subject: [PATCH 028/108] lldpd: remove unneeded quotes and variable quoting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit from commit ac771313ebedd2c4bfda8adef47650d45d77c32d portidsubtype takes 1 of 2 possible keywords which do not need quoting: configure lldp portidsubtype ifname | macaddress The third keyword 'local' is used in the syntax when individual ports are being defined: configure [ports ethX [,…]] lldp portidsubtype local value When this syntax is used, quoting is useful (see test cases for lldpd). In the init file, the 'local' syntax is unused. Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 243a32c937..5d06e13aa5 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -154,7 +154,7 @@ write_lldpd_conf() fi fi [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type $lldp_agenttype" >> "$LLDPD_CONF" - [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype" "\"$lldp_portidsubtype\"" >> "$LLDPD_CONF" + [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype $lldp_portidsubtype" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" [ $lldp_tx_interval -gt 0 ] && echo "configure lldp tx-interval" "$lldp_tx_interval" >> "$LLDPD_CONF" [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold" "$lldp_tx_hold" >> "$LLDPD_CONF" From 4dcece46a7b4ede7d05d8fb9d31d62406bca74d0 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 21:54:35 +0100 Subject: [PATCH 029/108] lldpd: remove unneeded quotes from commit a5f715da713304972467612d6934130ce3aa2837 Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 5d06e13aa5..4841027432 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -156,8 +156,8 @@ write_lldpd_conf() [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type $lldp_agenttype" >> "$LLDPD_CONF" [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype $lldp_portidsubtype" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" - [ $lldp_tx_interval -gt 0 ] && echo "configure lldp tx-interval" "$lldp_tx_interval" >> "$LLDPD_CONF" - [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold" "$lldp_tx_hold" >> "$LLDPD_CONF" + [ $lldp_tx_interval -gt 0 ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" + [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF" # Since lldpd's sysconfdir is /tmp, we'll symlink /etc/lldpd.d to /tmp/$LLDPD_CONFS_DIR [ -e $LLDPD_CONFS_DIR ] || ln -s /etc/lldpd.d $LLDPD_CONFS_DIR From 228d4e7f1b759c11897043dc73ef3c576bc13f7f Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 22:05:11 +0100 Subject: [PATCH 030/108] lldpd: refactor out ifaces derivation; reuse function from commit 909f0630663d7ae1471c76154516e3299992a150 Now pass two params to get_config_cid_ifaces() for: cid_interface interface Each of which is a CSV of interfaces. Tested on 22.03.5 Signed-off-by: Paul Donald --- .../network/services/lldpd/files/lldpd.init | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 4841027432..e13128e2d6 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -76,7 +76,7 @@ get_config_restart_hash() { get_config_cid_ifaces() { local _ifaces - config_get _ifaces 'config' 'cid_interface' + config_get _ifaces 'config' "$2" local _iface _ifnames="" for _iface in $_ifaces; do @@ -99,16 +99,8 @@ write_lldpd_conf() local lldp_hostname config_get lldp_hostname 'config' 'lldp_hostname' "$(cat /proc/sys/kernel/hostname)" - local ifaces - config_get ifaces 'config' 'interface' - - local iface ifnames="" - for iface in $ifaces; do - local ifname="" - if network_get_device ifname "$iface" || [ -e "/sys/class/net/$iface" ]; then - append ifnames "${ifname:-$iface}" "," - fi - done + local ifnames + get_config_cid_ifaces ifnames "interface" local lldp_mgmt_ip config_get lldp_mgmt_ip 'config' 'lldp_mgmt_ip' @@ -141,7 +133,7 @@ write_lldpd_conf() # Clear out the config file first echo -n > "$LLDPD_CONF" - [ -n "$ifnames" ] && echo "configure system interface pattern" "$ifnames" >> "$LLDPD_CONF" + [ -n "$ifnames" ] && echo "configure system interface pattern $ifnames" >> "$LLDPD_CONF" [ -n "$lldp_description" ] && echo "configure system description" "\"$lldp_description\"" >> "$LLDPD_CONF" [ -n "$lldp_hostname" ] && echo "configure system hostname" "\"$lldp_hostname\"" >> "$LLDPD_CONF" [ -n "$lldp_mgmt_ip" ] && echo "configure system ip management pattern" "\"$lldp_mgmt_ip\"" >> "$LLDPD_CONF" @@ -299,7 +291,8 @@ start_service() { # ChassisID interfaces local ifnames - get_config_cid_ifaces ifnames + get_config_cid_ifaces ifnames "cid_interface" + [ -n "$ifnames" ] && procd_append_param command -C "$ifnames" # Overwrite default configuration locations processed by lldpcli at start From 79ee4cb0397eb9eae34369e33d66b5a1d837a652 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 23:37:13 +0100 Subject: [PATCH 031/108] lldpd: fix error "sh: XXXms: bad number" from commit 3ce909914a12647bec52bcee0a162dd6d158a4f6 The lldpd man page says that "configure lldp tx-interval" can specify an interval value in milliseconds by appending a "ms" suffix to the figure. Thus mandating string handling, and not integer comparison. Tested on 22.03.5 Signed-off-by: Paul Donald --- package/network/services/lldpd/files/lldpd.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index e13128e2d6..97c572d347 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -148,7 +148,7 @@ write_lldpd_conf() [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type $lldp_agenttype" >> "$LLDPD_CONF" [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype $lldp_portidsubtype" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" - [ $lldp_tx_interval -gt 0 ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" + [ -n $lldp_tx_interval ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF" # Since lldpd's sysconfdir is /tmp, we'll symlink /etc/lldpd.d to /tmp/$LLDPD_CONFS_DIR From 53252eeb3b6177b77e23235436b04818a88eafe0 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 19:15:55 +0100 Subject: [PATCH 032/108] lldpd: Implement location parameter Previously only partially implemented. After commit 5007f488bb5e1b556052ef246bd3822fed8d09d2 lldp_location was never removed Now, add the value of lldp_location to the generated config. The location param has a few syntaxes, so the config acquires the first usage from the man page: 'address country EU' Supplementary fix for PR #14193 (this param was included in the original PR #13018 but the lldp_location fixes were absent from PR #14193). Tested on 22.03.5, 22.03.6 Signed-off-by: Paul Donald --- .../network/services/lldpd/files/lldpd.config | 2 +- package/network/services/lldpd/files/lldpd.init | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/package/network/services/lldpd/files/lldpd.config b/package/network/services/lldpd/files/lldpd.config index 5e7c51ba7e..fa9fe2b4f8 100644 --- a/package/network/services/lldpd/files/lldpd.config +++ b/package/network/services/lldpd/files/lldpd.config @@ -7,7 +7,7 @@ config lldpd config option agentxsocket /var/run/agentx.sock option lldp_class 4 - option lldp_location "2:FR:6:Commercial Rd:3:Roseville:19:4" + option lldp_location "address country EU" # if empty, the distribution description is sent #option lldp_description "OpenWrt System" diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 97c572d347..498c9e615e 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -114,6 +114,10 @@ write_lldpd_conf() local lldpmed_fast_start_tx_interval config_get lldpmed_fast_start_tx_interval 'config' 'lldpmed_fast_start_tx_interval' 0 + + local lldp_location + config_get lldp_location 'config' 'lldp_location' + fi local lldp_agenttype @@ -145,8 +149,15 @@ write_lldpd_conf() echo "configure med fast-start enable" >> "$LLDPD_CONF" fi fi - [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type $lldp_agenttype" >> "$LLDPD_CONF" - [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype $lldp_portidsubtype" >> "$LLDPD_CONF" + if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then + # other 'configure med xxx' statements go here + + [ -n "$lldp_location" ] && echo "configure med location" "$lldp_location" >> "$LLDPD_CONF" + + fi + + [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF" + [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype" "\"$lldp_portidsubtype\"" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" [ -n $lldp_tx_interval ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF" @@ -170,7 +181,6 @@ start_service() { local enable_edp local force_edp local lldp_class - local lldp_location local lldp_no_version local lldpmed_no_inventory local readonly_mode @@ -199,7 +209,6 @@ start_service() { config_get_bool force_edp 'config' 'force_edp' 0 fi config_get lldp_class 'config' 'lldp_class' - config_get lldp_location 'config' 'lldp_location' config_get_bool lldp_no_version 'config' 'lldp_no_version' 0 if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then config_get_bool lldpmed_no_inventory 'config' 'lldpmed_no_inventory' 0 From 2302a7c5ad9c894d0530b7700409b2f4ea4bcc91 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 10 Mar 2024 13:29:14 +0000 Subject: [PATCH 033/108] uboot-mediatek: fix patch order Make sure patch sequence number is unique by moving patch 440-add-jdcloud_re-cp-03.patch -> 441-add-jdcloud_re-cp-03.patch Signed-off-by: Daniel Golle --- ...-add-jdcloud_re-cp-03.patch => 441-add-jdcloud_re-cp-03.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename package/boot/uboot-mediatek/patches/{440-add-jdcloud_re-cp-03.patch => 441-add-jdcloud_re-cp-03.patch} (100%) diff --git a/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch b/package/boot/uboot-mediatek/patches/441-add-jdcloud_re-cp-03.patch similarity index 100% rename from package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch rename to package/boot/uboot-mediatek/patches/441-add-jdcloud_re-cp-03.patch From 5f230cd0b1f141def141da1f70440a7428b5af55 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 10 Mar 2024 13:49:45 +0000 Subject: [PATCH 034/108] uboot-mediatek: fix typo patch filename 311-mt7986-select-roodisk.patch -> 311-mt7986-select-rootdisk.patch Signed-off-by: Daniel Golle --- ...7986-select-roodisk.patch => 311-mt7986-select-rootdisk.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename package/boot/uboot-mediatek/patches/{311-mt7986-select-roodisk.patch => 311-mt7986-select-rootdisk.patch} (100%) diff --git a/package/boot/uboot-mediatek/patches/311-mt7986-select-roodisk.patch b/package/boot/uboot-mediatek/patches/311-mt7986-select-rootdisk.patch similarity index 100% rename from package/boot/uboot-mediatek/patches/311-mt7986-select-roodisk.patch rename to package/boot/uboot-mediatek/patches/311-mt7986-select-rootdisk.patch From 45a2109353fa18701b65aefe2323ec06391da543 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 10 Mar 2024 23:14:33 +0000 Subject: [PATCH 035/108] mediatek: mt7622: linksys-e8450: set driving strength for SPI-NAND Set 12mA driving strength for SPI-NAND pins like the stock firmware's bootloader does as well. Signed-off-by: Daniel Golle --- target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi index be216d972c..bd686073cb 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi @@ -1,8 +1,9 @@ // SPDX-License-Identifier: (GPL-2.0-only OR MIT) /dts-v1/; -#include #include +#include +#include #include "mt7622.dtsi" #include "mt6380.dtsi" @@ -271,6 +272,11 @@ function = "flash"; groups = "snfi"; }; + + conf { + groups = "snfi"; + drive-strength = ; + }; }; spic0_pins: spic0-pins { From faa5f17fe2d45a95049b202c2de0aeeb0c9a64db Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 11 Mar 2024 18:26:55 +0000 Subject: [PATCH 036/108] kernel: mtk_eth_soc: release MAC_MCR_FORCE_LINK only when MAC is up Clearing bit MAC_MCR_FORCE_LINK which forces the link down too early can result in MAC ending up in a broken/blocked state. Fix this by handling this bit in the .mac_link_up and .mac_link_down calls instead of in .mac_finish. Suggested-by: Mason-cw Chang Signed-off-by: Daniel Golle --- ..._eth_soc-release-MAC_MCR_FORCE_LINK-.patch | 50 +++++++++++++++++++ ..._eth_soc-add-paths-and-SerDes-modes-.patch | 41 +++++++-------- 2 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 target/linux/generic/pending-6.1/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch diff --git a/target/linux/generic/pending-6.1/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch b/target/linux/generic/pending-6.1/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch new file mode 100644 index 0000000000..2f7d29b84d --- /dev/null +++ b/target/linux/generic/pending-6.1/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch @@ -0,0 +1,50 @@ +From ef5976ae4e117fae9a61bb3c0f8319a917a425ea Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 11 Mar 2024 17:43:28 +0000 +Subject: [PATCH] net: mediatek: mtk_eth_soc: release MAC_MCR_FORCE_LINK only when MAC is up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Clearing bit MAC_MCR_FORCE_LINK which forces the link down too early +can result in MAC ending up in a broken/blocked state. + +Fix this by handling this bit in the .mac_link_up and .mac_link_down +calls instead of in .mac_finish. + +Fixes: b8fc9f30821ec ("net: ethernet: mediatek: Add basic PHYLINK support") +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -662,8 +662,7 @@ static int mtk_mac_finish(struct phylink + mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr_new = mcr_cur; + mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | +- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK | +- MAC_MCR_RX_FIFO_CLR_DIS; ++ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_RX_FIFO_CLR_DIS; + + /* Only update control register when needed! */ + if (mcr_new != mcr_cur) +@@ -679,7 +678,7 @@ static void mtk_mac_link_down(struct phy + phylink_config); + u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); ++ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + +@@ -788,7 +787,7 @@ static void mtk_mac_link_up(struct phyli + if (rx_pause) + mcr |= MAC_MCR_FORCE_RX_FC; + +- mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN; ++ mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + diff --git a/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index afe561ab31..2b379c9158 100644 --- a/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -1,4 +1,4 @@ -From 91bda2f441f9e37273922028ffc48ce8e91bf5bd Mon Sep 17 00:00:00 2001 +From d5e337e7aecc2e1cc9e96768062610adb95f8f72 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 12 Dec 2023 03:51:14 +0000 Subject: [PATCH] net: ethernet: mtk_eth_soc: add paths and SerDes modes for @@ -19,9 +19,9 @@ modes. Signed-off-by: Daniel Golle --- drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 291 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 292 +++++++++++++++++-- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++- - 3 files changed, 469 insertions(+), 51 deletions(-) + 3 files changed, 470 insertions(+), 51 deletions(-) --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -390,24 +390,25 @@ Signed-off-by: Daniel Golle /* Enable SGMII */ if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) -@@ -677,10 +762,13 @@ static void mtk_mac_link_down(struct phy +@@ -676,10 +761,14 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); - u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + if (!mtk_interface_mode_is_xgmii(interface)) { -+ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); -+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); -+ } else if (mac->id != MTK_GMAC1_ID) { ++ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, MTK_MAC_MCR(mac->id)); ++ if (mtk_is_netsys_v3_or_greater(mac->hw)) ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); ++ } else if (mtk_is_netsys_v3_or_greater(mac->hw) && mac->id != MTK_GMAC1_ID) { + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id)); + } } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -752,13 +840,11 @@ static void mtk_set_queue_speed(struct m +@@ -751,13 +840,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -425,7 +426,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -792,9 +878,63 @@ static void mtk_mac_link_up(struct phyli +@@ -791,9 +878,63 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -470,7 +471,7 @@ Signed-off-by: Daniel Golle + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); + -+ if (mtk_interface_mode_is_xgmii(interface)) ++ if (mtk_is_netsys_v3_or_greater(mac->hw) && mtk_interface_mode_is_xgmii(interface)) + mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); + else @@ -489,7 +490,7 @@ Signed-off-by: Daniel Golle .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, .mac_link_up = mtk_mac_link_up, -@@ -3373,6 +3513,9 @@ static int mtk_open(struct net_device *d +@@ -3372,6 +3513,9 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -499,7 +500,7 @@ Signed-off-by: Daniel Golle err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3501,6 +3644,9 @@ static int mtk_stop(struct net_device *d +@@ -3500,6 +3644,9 @@ static int mtk_stop(struct net_device *d for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) mtk_ppe_stop(eth->ppe[i]); @@ -509,7 +510,7 @@ Signed-off-by: Daniel Golle return 0; } -@@ -4498,6 +4644,7 @@ static const struct net_device_ops mtk_n +@@ -4497,6 +4644,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { const __be32 *_id = of_get_property(np, "reg", NULL); @@ -517,7 +518,7 @@ Signed-off-by: Daniel Golle phy_interface_t phy_mode; struct phylink *phylink; struct mtk_mac *mac; -@@ -4533,16 +4680,41 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4532,16 +4680,41 @@ static int mtk_add_mac(struct mtk_eth *e mac->id = id; mac->hw = eth; mac->of_node = np; @@ -567,7 +568,7 @@ Signed-off-by: Daniel Golle } memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); -@@ -4616,8 +4788,21 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4615,8 +4788,21 @@ static int mtk_add_mac(struct mtk_eth *e phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); @@ -589,7 +590,7 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4662,6 +4847,26 @@ free_netdev: +@@ -4661,6 +4847,26 @@ free_netdev: return err; } @@ -616,7 +617,7 @@ Signed-off-by: Daniel Golle void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) { struct net_device *dev, *tmp; -@@ -4805,7 +5010,8 @@ static int mtk_probe(struct platform_dev +@@ -4804,7 +5010,8 @@ static int mtk_probe(struct platform_dev regmap_write(cci, 0, 3); } @@ -626,7 +627,7 @@ Signed-off-by: Daniel Golle err = mtk_sgmii_init(eth); if (err) -@@ -4916,6 +5122,24 @@ static int mtk_probe(struct platform_dev +@@ -4915,6 +5122,24 @@ static int mtk_probe(struct platform_dev } } @@ -651,7 +652,7 @@ Signed-off-by: Daniel Golle if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, -@@ -5018,6 +5242,11 @@ static int mtk_remove(struct platform_de +@@ -5017,6 +5242,11 @@ static int mtk_remove(struct platform_de mtk_stop(eth->netdev[i]); mac = netdev_priv(eth->netdev[i]); phylink_disconnect_phy(mac->phylink); From ecc9d0195b2411bd38c5deae38f255026c20c970 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 11 Mar 2024 18:32:38 +0000 Subject: [PATCH 037/108] mediatek: mt7988: fix clk for 2nd PCIe port Due to what seems to be an undocumented oddity in MediaTek's MT7988 SoC design the CLK_INFRA_PCIE_PERI_26M_CK_P2 clock requires CLK_INFRA_PCIE_PERI_26M_CK_P3 to be enabled. This currently leads to PCIe port 2 not working in Linux. Reflect the apparent relationship in the clk driver to make sure PCIe port 2 of the MT7988 SoC works. Signed-off-by: Daniel Golle --- ...988-infracfg-fix-clocks-for-2nd-PCIe.patch | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 target/linux/mediatek/patches-6.1/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch diff --git a/target/linux/mediatek/patches-6.1/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch b/target/linux/mediatek/patches-6.1/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch new file mode 100644 index 0000000000..c4760b9eff --- /dev/null +++ b/target/linux/mediatek/patches-6.1/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch @@ -0,0 +1,31 @@ +From c202f510bbaa34ab5d65a69a61e0e72761374b17 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 11 Mar 2024 17:14:19 +0000 +Subject: [PATCH] clk: mediatek: mt7988-infracfg: fix clocks for 2nd PCIe port + +Due to what seems to be an undocumented oddity in MediaTek's MT7988 +SoC design the CLK_INFRA_PCIE_PERI_26M_CK_P2 clock requires +CLK_INFRA_PCIE_PERI_26M_CK_P3 to be enabled. + +This currently leads to PCIe port 2 not working in Linux. + +Reflect the apparent relationship in the clk driver to make sure PCIe +port 2 of the MT7988 SoC works. + +Suggested-by: Sam Shih +Signed-off-by: Daniel Golle +--- + drivers/clk/mediatek/clk-mt7988-infracfg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/mediatek/clk-mt7988-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c +@@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[ + 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), ++ "infra_pcie_peri_ck_26m_ck_p3", 9), + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3", + "csw_infra_f26m_sel", 10), + /* INFRA1 */ From 53e3851646f872a08010709c6503d4bc838b5a0b Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 9 Jan 2024 23:20:18 +0800 Subject: [PATCH 038/108] tools: add util-linux since kernel 6.4, commit bca2f3a9406b ("efi/zboot: Add BSS padding before compression") introduces the use of hexdump to padding the EFI kernel binary before compression. util-linux which containing hexdump should then be compiled as a host tool to guarantee not breaking the kernel build process. Signed-off-by: Weijie Gao --- tools/Makefile | 2 + tools/util-linux/Makefile | 132 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 tools/util-linux/Makefile diff --git a/tools/Makefile b/tools/Makefile index bc169d7a95..7607e84481 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -66,6 +66,7 @@ tools-y += pkgconf tools-y += quilt tools-y += squashfs4 tools-y += sstrip +tools-y += util-linux tools-y += zip tools-y += zlib tools-y += zstd @@ -128,6 +129,7 @@ $(curdir)/quilt/compile := $(curdir)/autoconf/compile $(curdir)/findutils/compil $(curdir)/sdcc/compile := $(curdir)/bison/compile $(curdir)/squashfs3-lzma/compile := $(curdir)/lzma-old/compile $(curdir)/squashfs4/compile := $(curdir)/xz/compile $(curdir)/zlib/compile +$(curdir)/util-linux/compile := $(curdir)/bison/compile $(curdir)/zstd/compile := $(curdir)/meson/compile ifneq ($(HOST_OS),Linux) diff --git a/tools/util-linux/Makefile b/tools/util-linux/Makefile new file mode 100644 index 0000000000..acd819e38b --- /dev/null +++ b/tools/util-linux/Makefile @@ -0,0 +1,132 @@ +# +# Copyright (C) 2006-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +PKG_NAME:=util-linux +PKG_VERSION:=2.39.3 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.39 +PKG_HASH:=7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f +PKG_CPE_ID:=cpe:/a:kernel:util-linux + +HOST_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/host-build.mk + +HOST_CONFIGURE_ARGS += \ + --disable-poman \ + --disable-nls \ + --disable-asciidoc \ + --disable-poman \ + --disable-libuuid \ + --disable-libblkid \ + --disable-libmount \ + --disable-libsmartcols \ + --disable-libfdisk \ + --disable-fdisks \ + --disable-mount \ + --disable-losetup \ + --disable-zramctl \ + --disable-fsck \ + --disable-partx \ + --disable-uuidd \ + --disable-uuidgen \ + --disable-blkid \ + --disable-wipefs \ + --disable-mountpoint \ + --disable-fallocate \ + --disable-unshare \ + --disable-nsenter \ + --disable-setpriv \ + --disable-hardlink \ + --disable-eject \ + --disable-agetty \ + --disable-cramfs \ + --disable-bfs \ + --disable-minix \ + --disable-hwclock \ + --disable-mkfs \ + --disable-fstrim \ + --disable-swapon \ + --disable-lscpu \ + --disable-lsfd \ + --disable-lslogins \ + --disable-wdctl \ + --disable-cal \ + --disable-logger \ + --disable-whereis \ + --disable-pipesz \ + --disable-waitpid \ + --disable-switch_root \ + --disable-pivot_root \ + --disable-lsmem \ + --disable-chmem \ + --disable-ipcmk \ + --disable-ipcrm \ + --disable-ipcs \ + --disable-irqtop \ + --disable-lsirq \ + --disable-lsns \ + --disable-rfkill \ + --disable-scriptutils \ + --disable-tunelp \ + --disable-kill \ + --disable-last \ + --disable-utmpdump \ + --disable-line \ + --disable-mesg \ + --disable-raw \ + --disable-rename \ + --disable-vipw \ + --disable-newgrp \ + --disable-chfn-chsh \ + --disable-login \ + --disable-nologin \ + --disable-sulogin \ + --disable-su \ + --disable-runuser \ + --disable-ul \ + --disable-more \ + --disable-pg \ + --disable-setterm \ + --disable-schedutils \ + --disable-wall \ + --disable-write \ + --disable-bash-completion \ + --disable-pylibmount \ + --disable-pg-bell \ + --without-util \ + --without-selinux \ + --without-audit \ + --without-udev \ + --without-ncursesw \ + --without-ncurses \ + --without-slang \ + --without-tinfo \ + --without-readline \ + --without-utempter \ + --without-cap-ng \ + --without-libz \ + --without-libmagic \ + --without-user \ + --without-btrfs \ + --without-systemd \ + --without-smack \ + --without-econf \ + --without-python \ + --without-cryptsetup + +define Host/Install + $(INSTALL_BIN) $(HOST_BUILD_DIR)/hexdump $(STAGING_DIR_HOST)/bin/ +endef + +define Host/Uninstall + rm -f $(STAGING_DIR_HOST)/bin/hexdump +endef + +$(eval $(call HostBuild)) From 71360660e68bbc5bdc9cde89fd66ba5104e59106 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 02:14:53 +0800 Subject: [PATCH 039/108] kernel: add define for kernel 6.6 Add define for kernel 6.6. Signed-off-by: Weijie Gao --- include/kernel-6.6 | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 include/kernel-6.6 diff --git a/include/kernel-6.6 b/include/kernel-6.6 new file mode 100644 index 0000000000..53132d2ae5 --- /dev/null +++ b/include/kernel-6.6 @@ -0,0 +1,2 @@ +LINUX_VERSION-6.6 = .20 +LINUX_KERNEL_HASH-6.6.20 = e2f6c7f39b304248193370f8c5755553ab73ad5672e92dae994a344084d8dd22 From 8a9273d51ede02fe66816ad2132198d592b1491e Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Jan 2024 19:57:28 +0800 Subject: [PATCH 040/108] generic: copy backport, hack, pending patch and config from 6.1 to 6.6 Copy backport, hack, pending patch and config from 6.1 to 6.6. Signed-off-by: Weijie Gao --- ...i-gen-LRU-rename-lru_gen_struct-to-l.patch | 352 + ...i-gen-LRU-remove-eviction-fairness-s.patch | 192 + ...i-gen-LRU-remove-aging-fairness-safe.patch | 294 + ...lti-gen-LRU-shuffle-should_run_aging.patch | 166 + ...i-gen-LRU-per-node-lru_gen_folio-lis.patch | 876 ++ ...i-gen-LRU-clarify-scan_control-flags.patch | 202 + ...i-gen-LRU-simplify-arch_has_hw_pte_y.patch | 38 + ...m-multi-gen-LRU-avoid-futile-retries.patch | 92 + ...3-10-UPSTREAM-mm-add-vma_has_recency.patch | 191 + ...STREAM-mm-support-POSIX_FADV_NOREUSE.patch | 129 + ...i-gen-LRU-section-for-working-set-pr.patch | 67 + ...i-gen-LRU-section-for-rmap-PT-walk-f.patch | 57 + ...ti-gen-LRU-section-for-Bloom-filters.patch | 243 + ...-multi-gen-LRU-section-for-memcg-LRU.patch | 427 + ...i-gen-LRU-improve-lru_gen_exit_memcg.patch | 40 + ...multi-gen-LRU-improve-walk_pmd_range.patch | 135 + ...i-gen-LRU-simplify-lru_gen_look_arou.patch | 148 + ...i-gen-LRU-remove-wait_event_killable.patch | 273 + ...0-v6.3-bitfield-add-FIELD_PREP_CONST.patch | 58 + ...-some-linker-warnings-in-recent-link.patch | 63 + ...y-a-bit-code-find-partition-matching.patch | 65 + ...find-OF-node-for-every-MTD-partition.patch | 84 + ...T_DEV-for-partitions-marked-as-rootf.patch | 47 + ...TP-Link-SafeLoader-partitions-table-.patch | 229 + ...onix-use-scratch-buffer-for-DMA-oper.patch | 35 + ....3-mtd-ubi-wire-up-parent-MTD-device.patch | 33 + ...-mtd-ubi-block-wire-up-device-parent.patch | 49 + ...-mtd_otp_nvmem_add-to-handle-EPROBE_.patch | 47 + ...611-v6.3-net-add-helper-eth_addr_add.patch | 41 + ...uirk-for-Fiberstone-GPON-ONU-34-20BI.patch | 32 + ...-aquantia-move-to-separate-directory.patch | 2306 +++++ ...antia-move-MMD_VEND-define-to-header.patch | 183 + ...y-aquantia-add-firmware-load-support.patch | 504 ++ ...edicated-C45-API-to-MDIO-bus-drivers.patch | 326 + ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 + ...eplace-of_gpio.h-with-what-indeed-is.patch | 32 + ...upport-qca8081-genphy_c45_pma_read_a.patch | 70 + ...3x-merge-qca8081-slave-seed-function.patch | 73 + ...nable-qca8081-slave-seed-conditional.patch | 76 + ...-at803x-support-qca8081-1G-chip-type.patch | 48 + ...emove-qca8081-1G-fast-retrain-and-sl.patch | 98 + ...dd-qca8081-fifo-reset-on-the-link-ch.patch | 55 + ...ove-disable-WOL-to-specific-at8031-p.patch | 69 + ...aname-hw_stats-functions-to-qca83xx-.patch | 129 + ...ove-qca83xx-specific-check-in-dedica.patch | 155 + ...ove-specific-DT-option-for-at8031-to.patch | 94 + ...ove-specific-at8031-probe-mode-check.patch | 78 + ...ove-specific-at8031-config_init-to-d.patch | 86 + ...ove-specific-at8031-WOL-bits-to-dedi.patch | 92 + ...ove-specific-at8031-config_intr-to-d.patch | 78 + ...ake-at8031-related-DT-functions-name.patch | 78 + ...ove-at8031-functions-in-dedicated-se.patch | 297 + ...ove-at8035-specific-DT-parse-to-dedi.patch | 114 + ...rop-specific-PHY-ID-check-from-cable.patch | 219 + ...ove-specific-qca808x-config_aneg-to-.patch | 116 + ...ake-read-specific-status-function-mo.patch | 97 + ...at803x-remove-extra-space-after-cast.patch | 27 + ...x-replace-msleep-1-with-usleep_range.patch | 38 + ...etter-align-function-varibles-to-ope.patch | 152 + ...generalize-cdt-fault-length-function.patch | 62 + ...efactor-qca808x-cable-test-get-statu.patch | 118 + ...dd-support-for-cdt-cross-short-test-.patch | 182 + ...at803x-make-read_status-more-generic.patch | 62 + ...y-at803x-add-LED-support-for-qca808x.patch | 408 + ...03x-PHY-driver-to-dedicated-director.patch | 5598 ++++++++++++ ...ate-and-move-functions-to-shared-lib.patch | 243 + ...eatch-qca83xx-PHY-driver-from-at803x.patch | 638 ++ ...e-additional-functions-to-shared-lib.patch | 1014 +++ ...etach-qca808x-PHY-driver-from-at803x.patch | 1936 ++++ ...cs-add-driver-for-MediaTek-SGMII-PCS.patch | 394 + ...r-type-u8-in-phy_package_shared-stru.patch | 28 + ...HY-package-API-to-support-multiple-g.patch | 341 + ...ure-__phy_write-read_mmd-to-helper-a.patch | 116 + ...pport-for-PHY-package-MMD-read-write.patch | 196 + ....2-net-fman-memac-Add-serdes-support.patch | 103 + ...2-net-fman-memac-Use-lynx-pcs-driver.patch | 384 + ...-03-v6.2-net-dpaa-Convert-to-phylink.patch | 2451 +++++ ...ide-phylink_validate_mask_caps-helpe.patch | 93 + ...valid-state-argument-to-phylink_vali.patch | 39 + ...add-phylink_get_link_timer_ns-helper.patch | 48 + ...cit-phylink_generic_validate-referen.patch | 250 + ..._bus_find_fwnode-take-a-const-fwnode.patch | 48 + ...-t-print-an_enabled-in-pcs_get_state.patch | 31 + ...e-Autoneg-bit-rather-than-an_enabled.patch | 32 + ...ort-validated-pause-and-autoneg-in-f.patch | 64 + ...2-v6.4-net-phylink-remove-an_enabled.patch | 177 + ...et-phylink-constify-fwnode-arguments.patch | 88 + ...-fwnode_get_phy_node-fwnode-argument.patch | 38 + ...ylink-fix-ksettings_set-ethtool-call.patch | 44 + ...-support-for-setting-signalling-rate.patch | 149 + ...hy-add-helpers-for-comparing-phy-IDs.patch | 147 + ...ire-supported_interfaces-to-be-fille.patch | 71 + ...ve-duplicated-linkmode-pause-resolut.patch | 64 + ...function-to-resolve-clause-73-negoti.patch | 76 + ...ide-phylink_pcs_config-and-phylink_p.patch | 100 + ...ually-fix-ksettings_set-ethtool-call.patch | 55 + ...net-phylink-add-PCS-negotiation-mode.patch | 324 + ...ert-phylink_mii_c22_pcs_config-to-ne.patch | 45 + ...-neg_mode-into-phylink_mii_c22_pcs_c.patch | 187 + ...xi-update-PCS-driver-to-use-neg_mode.patch | 101 + ...e-Autoneg-bit-rather-than-an_enabled.patch | 55 + ...s-fix-incorrect-number-of-interfaces.patch | 30 + ...808x-fix-logic-error-in-LED-brightne.patch | 36 + ...808x-default-to-LED-active-High-if-n.patch | 41 + ...ort-for-scanning-PHY-in-PHY-packages.patch | 211 + ...-add-devm-of_phy_package_join-helper.patch | 185 + ...move-more-function-to-shared-library.patch | 583 ++ ...whether-link-has-changed-in-c37_read.patch | 100 + ...m-add-support-for-QCA807x-PHY-Family.patch | 668 ++ ...e-common-qca808x-LED-define-to-share.patch | 179 + ...eneralize-some-qca808x-LED-functions.patch | 172 + ...07x-add-support-for-configurable-LED.patch | 326 + ...move-interface-mode-check-to-.config.patch | 51 + ...-add-support-for-clock-frequency-pro.patch | 205 + ...-drop-wrong-endianness-conversion-fo.patch | 92 + ..._eth_soc-enable-flow-offloading-supp.patch | 26 + ...et-mtk_wed-introduce-wed-mcu-support.patch | 591 ++ ...net-mtk_wed-introduce-wed-wo-support.patch | 737 ++ ..._wed-rename-tx_wdma-array-in-rx_wdma.patch | 79 + ...mtk_wed-add-configure-wed-wo-support.patch | 1521 ++++ ...ethernet-mtk_wed-add-rx-mib-counters.patch | 149 + ..._eth_soc-remove-cpu_relax-in-mtk_pen.patch | 36 + ..._wed-add-wcid-overwritten-support-fo.patch | 80 + ..._wed-return-status-value-in-mtk_wdma.patch | 85 + ..._wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch | 52 + ...ethernet-mtk_wed-update-mtk_wed_stop.patch | 98 + ...mtk_wed-add-mtk_wed_rx_reset-routine.patch | 309 + ..._wed-add-reset-to-tx_ring_setup-call.patch | 103 + ..._wed-fix-sleep-while-atomic-in-mtk_w.patch | 103 + ..._wed-get-rid-of-queue-lock-for-rx-qu.patch | 52 + ..._wed-get-rid-of-queue-lock-for-tx-qu.patch | 75 + ..._eth_soc-introduce-mtk_hw_reset-util.patch | 70 + ..._eth_soc-introduce-mtk_hw_warm_reset.patch | 107 + ..._eth_soc-align-reset-procedure-to-ve.patch | 262 + ..._eth_soc-add-dma-checks-to-mtk_hw_re.patch | 249 + ..._wed-add-reset-reset_complete-callba.patch | 124 + ..._wed-add-reset-to-rx_ring_setup-call.patch | 106 + ..._eth_soc-account-for-vlan-in-rx-head.patch | 22 + ..._eth_soc-increase-tx-ring-side-for-Q.patch | 143 + ..._eth_soc-avoid-port_mg-assignment-on.patch | 52 + ..._eth_soc-implement-multi-queue-suppo.patch | 654 ++ ...t-dsa-tag_mtk-assign-per-port-queues.patch | 20 + ...iatek-ppe-assign-per-port-queues-for.patch | 93 + ...ort-for-DSA-rx-offloading-via-metada.patch | 72 + ..._eth_soc-fix-VLAN-rx-hardware-accele.patch | 192 + ..._eth_soc-disable-hardware-DSA-untagg.patch | 42 + ..._eth_soc-enable-special-tag-when-any.patch | 54 + ..._eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch | 129 + ..._wed-No-need-to-clear-memory-after-a.patch | 26 + ..._wed-fix-some-possible-NULL-pointer-.patch | 61 + ..._wed-fix-possible-deadlock-if-mtk_we.patch | 58 + ..._eth_soc-fix-tx-throughput-regressio.patch | 31 + ...-mtk_eth_soc-add-definitions-for-PCS.patch | 55 + ...eliminate-unnecessary-error-handling.patch | 74 + ...soc-add-pcs_get_state-implementation.patch | 46 + ...convert-mtk_sgmii-to-use-regmap_upda.patch | 130 + ...add-out-of-band-forcing-of-speed-and.patch | 52 + ...07-net-mtk_eth_soc-move-PHY-power-up.patch | 48 + ...h_soc-move-interface-speed-selection.patch | 48 + ...th_soc-add-advertisement-programming.patch | 52 + ...move-and-correct-link-timer-programm.patch | 63 + ...add-support-for-in-band-802.3z-negot.patch | 132 + ...ii-ensure-the-SGMII-PHY-is-powered-d.patch | 119 + ...iatek-sgmii-fix-duplex-configuration.patch | 52 + ...enable-PCS-polling-to-allow-SFP-work.patch | 33 + ...ethernet-mtk_eth_soc-reset-PCS-state.patch | 48 + ..._eth_soc-only-write-values-if-needed.patch | 103 + ...t-mtk_eth_soc-add-support-for-MT7981.patch | 206 + ..._eth_soc-set-MDIO-bus-clock-frequenc.patch | 76 + ..._eth_soc-switch-to-external-PCS-driv.patch | 512 ++ ...k_eth_soc-use-WO-firmware-for-MT7981.patch | 46 + ..._eth_soc-fix-NULL-pointer-dereferenc.patch | 28 + ..._eth_soc-ppe-add-support-for-flow-ac.patch | 403 + ...iatek-fix-ppe-flow-accounting-for-v1.patch | 58 + ..._eth_soc-drop-generic-vlan-rx-offloa.patch | 201 + ..._eth_soc-always-mtk_get_ib1_pkt_type.patch | 31 + ..._ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch | 78 + ..._eth_soc-remove-incorrect-PLL-config.patch | 141 + ..._eth_soc-remove-mac_pcs_get_state-an.patch | 81 + ..._eth_soc-add-version-in-mtk_soc_data.patch | 550 ++ ...t-mtk_eth_soc-increase-MAX_DEVS-to-3.patch | 29 + ..._eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch | 186 + ..._eth_soc-add-NETSYS_V3-version-suppo.patch | 307 + ..._eth_soc-convert-caps-in-mtk_soc_dat.patch | 193 + ..._eth_soc-convert-clock-bitmap-to-u64.patch | 132 + ..._eth_soc-add-basic-support-for-MT798.patch | 477 + ..._eth_soc-enable-page_pool-support-fo.patch | 27 + ..._eth_soc-enable-nft-hw-flowtable_off.patch | 135 + ..._eth_soc-support-per-flow-accounting.patch | 78 + ..._eth_soc-fix-NULL-pointer-on-hw-rese.patch | 52 + ..._eth_soc-fix-register-definitions-fo.patch | 44 + ...tk_eth_soc-add-reset-bits-for-MT7988.patch | 188 + ..._eth_soc-add-support-for-in-SoC-SRAM.patch | 254 + ..._eth_soc-support-36-bit-DMA-addressi.patch | 166 + ...k_eth_soc-fix-uninitialized-variable.patch | 44 + ..._eth_soc-fix-pse_port-configuration-.patch | 33 + ..._eth_soc-add-code-for-offloading-flo.patch | 271 + ...iatek-mtk_ppe-prefer-newly-added-l2-.patch | 37 + ..._eth_soc-improve-keeping-track-of-of.patch | 334 + ...iatek-fix-ppe-flow-accounting-for-L2.patch | 342 + ..._wed-add-some-more-info-in-wed_txinf.patch | 45 + ..._wed-minor-change-in-wed_-tx-rx-info.patch | 47 + ..._eth_soc-rely-on-mtk_pse_port-defini.patch | 29 + ..._wed-check-update_wo_rx_stats-in-mtk.patch | 26 + ..._wed-do-not-assume-offload-callbacks.patch | 68 + ..._wed-introduce-versioning-utility-ro.patch | 232 + ..._wed-do-not-configure-rx-offload-if-.patch | 234 + ..._wed-rename-mtk_rxbm_desc-in-mtk_wed.patch | 52 + ..._wed-introduce-mtk_wed_buf-structure.patch | 87 + ..._wed-move-mem_region-array-out-of-mt.patch | 88 + ...-mtk_wed-make-memory-region-optional.patch | 71 + ...k_wed-add-mtk_wed_soc_data-structure.patch | 217 + ..._wed-introduce-WED-support-for-MT798.patch | 1280 +++ ..._wed-refactor-mtk_wed_check_wfdma_rx.patch | 95 + ..._wed-introduce-partial-AMSDU-offload.patch | 465 + ..._wed-introduce-hw_rro-support-for-MT.patch | 483 + ..._wed-debugfs-move-wed_v2-specific-re.patch | 78 + ..._wed-debugfs-add-WED-3.0-debugfs-ent.patch | 432 + ...et-mtk_wed-add-wed-3.0-reset-support.patch | 587 ++ ...antia-add-AQR111-and-AQR111B0-PHY-ID.patch | 102 + ...9-net-phy-aquantia-add-AQR113-PHY-ID.patch | 60 + ...9-net-phy-aquantia-add-AQR813-PHY-ID.patch | 59 + ...t-introduce-napi_is_scheduled-helper.patch | 96 + ...et-stmmac-improve-TX-timer-arm-logic.patch | 77 + ...c-move-TX-timer-arm-after-DMA-enable.patch | 96 + ...ac-increase-TX-coalesce-timer-to-5ms.patch | 38 + ...ntroduce-single-mii-read-write-lo-hi.patch | 150 + ...prove-mdio-master-read-write-by-usin.patch | 73 + ...d-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch | 63 + ...a8k-convert-to-regmap-read-write-API.patch | 261 + ...-enable-use_single_write-for-qca8xxx.patch | 78 + ...ke-learning-configurable-and-keep-of.patch | 146 + ...mit-user-ports-access-to-the-first-C.patch | 53 + ...ve-qca8xxx-hol-fixup-to-separate-fun.patch | 111 + ...e-dsa_for_each-macro-instead-of-for-.patch | 158 + ...x-regmap-bulk-read-write-methods-on-.patch | 61 + ...t-dsa-mt7530-use-external-PCS-driver.patch | 514 ++ ...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 | 54 + ...t7530-introduce-separate-MDIO-driver.patch | 691 ++ ...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 | 1724 ++++ ...fix-yt8521-duplicated-argument-to-or.patch | 49 + ...net-phy-add-Motorcomm-YT8531S-phy-id.patch | 140 + ...fix-the-spelling-problem-of-Sentinel.patch | 26 + ...nge-the-phy-id-of-yt8521-and-yt8531s.patch | 29 + ...-for-Motorcomm-yt8521-yt8531-gigabit.patch | 107 + ...support-for-Motorcomm-yt8521-gigabit.patch | 343 + ...upport-for-Motorcomm-yt8531s-gigabit.patch | 100 + ...or-Motorcomm-yt8531-gigabit-ethernet.patch | 302 + ...motorcomm-uninitialized-variables-in.patch | 34 + ...m-Add-pad-drive-strength-cfg-support.patch | 170 + ...k-add-pcs_enable-pcs_disable-methods.patch | 173 + ...t-pcs-lynxi-implement-pcs_disable-op.patch | 44 + ...ive-renaming-when-an-interface-is-up.patch | 136 + ...-need-to-blacklist-any-r8152-devices.patch | 158 + ...-control-transfer-of-rtl8152_get_ver.patch | 46 + ...-Add-__GFP_NOWARN-to-big-allocations.patch | 55 + ...52-adjust-generic_ocp_write-function.patch | 70 + .../795-v6.6-09-r8152-set-bp-in-bulk.patch | 129 + ...eth-r8152-try-to-use-a-normal-budget.patch | 39 + ...re-register-access-if-register-acces.patch | 398 + ...he-loop-when-the-budget-is-exhausted.patch | 83 + ..._ether-add-u-blox-0x1313-composition.patch | 47 + ...795-v6.7-16-r8152-use-napi_gro_frags.patch | 122 + ...it_default_state_get-to-the-global-h.patch | 39 + ...a8k-move-qca8k_port_to_phy-to-header.patch | 67 + ...net-dsa-qca8k-add-LEDs-basic-support.patch | 435 + ...dsa-qca8k-add-LEDs-blink_set-support.patch | 74 + ...bs-for-when-CLASS_LED-NEW_LEDS-are-d.patch | 59 + ...5-net-phy-Add-a-binding-for-PHY-LEDs.patch | 191 + ...ce-Call-into-the-PHY-driver-to-set-L.patch | 97 + ...ell-Add-software-control-of-the-LEDs.patch | 112 + ...ce-Call-into-the-PHY-driver-to-set-L.patch | 73 + ...-phy-marvell-Implement-led_blink_set.patch | 104 + ...Fix-inconsistent-indenting-in-led_bl.patch | 38 + ...dev-Drop-NETDEV_LED_MODE_LINKUP-from.patch | 87 + ...dev-Rename-add-namespace-to-netdev-t.patch | 149 + ...-netdev-Convert-device-attr-to-macro.patch | 82 + ...etdev-Use-mutex-instead-of-spinlocks.patch | 106 + ...01-leds-add-APIs-for-LEDs-hw-control.patch | 74 + ...get-attached-device-for-LED-hw-contr.patch | 37 + ...ds-leds-class-Document-new-Hardware-.patch | 113 + ...dev-refactor-code-setting-device-nam.patch | 69 + ...dev-introduce-check-for-possible-hw-.patch | 54 + ...dev-add-basic-check-for-hw-control-s.patch | 42 + ...dev-reject-interval-store-for-hw_con.patch | 28 + ...etdev-add-support-for-LED-hw-control.patch | 107 + ...er-netdev-validate-configured-netdev.patch | 58 + ...dev-init-mode-if-hw-control-already-.patch | 53 + ...dev-expose-netdev-trigger-modes-in-l.patch | 54 + ...t-dsa-qca8k-implement-hw_control-ops.patch | 200 + ...dsa-qca8k-add-op-to-get-ports-netdev.patch | 70 + ...dev-add-additional-specific-link-spe.patch | 242 + ...dev-add-additional-specific-link-dup.patch | 138 + ...dev-expose-hw_control-status-via-sys.patch | 45 + ...d-support-for-additional-modes-for-n.patch | 64 + ...x-pass-directly-chip-structure-to-mv.patch | 64 + ...x-use-mv88e6xxx_phy_is_internal-in-m.patch | 31 + ...x-add-field-to-specify-internal-phys.patch | 69 + ...x-fix-88E6393X-family-internal-phys-.patch | 52 + ...x-pass-mv88e6xxx_chip-structure-to-p.patch | 110 + ...xx-enable-support-for-88E6361-switch.patch | 153 + ...e-STM32MP15_BSEC_NUM_LOWER-in-config.patch | 82 + ...-warning-when-upper-OTPs-are-updated.patch | 34 + ...nvmem-stm32-add-nvmem-type-attribute.patch | 26 + ...m-stm32-fix-spelling-typo-in-comment.patch | 27 + ...x-spelling-mistake-controlls-control.patch | 27 + ...boot-env-add-Broadcom-format-support.patch | 67 + ...mem-core-remove-spurious-white-space.patch | 26 + ...e-add-an-index-parameter-to-the-cell.patch | 180 + ...struct-nvmem_cell_info-to-nvmem-prov.patch | 78 + ...the-removal-of-the-cells-in-nvmem_ad.patch | 65 + ...05-nvmem-core-add-nvmem_add_one_cell.patch | 122 + ...vmem_add_one_cell-in-nvmem_add_cells.patch | 93 + ...32-add-OP-TEE-support-for-STM32MP13x.patch | 562 ++ ...ect-bsec-pta-presence-for-STM32MP15x.patch | 85 + ...eprm-fix-kernel-doc-bad-line-warning.patch | 32 + ...mi-sdam-register-at-device-init-time.patch | 43 + ...011-nvmem-stm32-fix-OPTEE-dependency.patch | 46 + ...ount-to-list.h-as-list_count_nodes-f.patch | 75 + ...001-nvmem-xilinx-zynqmp-make-modular.patch | 35 + ...2-nvmem-core-introduce-NVMEM-layouts.patch | 387 + ...ndle-the-absence-of-expected-layouts.patch | 61 + ...-core-request-layout-modules-loading.patch | 52 + ...em-core-add-per-cell-post-processing.patch | 86 + ...ow-to-modify-a-cell-before-adding-it.patch | 59 + ...replace-global-post-processing-with-.patch | 81 + ...m-cell-drop-global-cell_post_process.patch | 68 + ...de-own-priv-pointer-in-post-process-.patch | 76 + ...ayouts-sl28vpd-Add-new-layout-driver.patch | 215 + ...youts-onie-tlv-Add-new-layout-driver.patch | 306 + ...m-mark-OF-related-data-as-maybe-unus.patch | 32 + ...Support-postprocessing-for-GPU-speed.patch | 120 + ...p-Use-devm_platform_ioremap_resource.patch | 39 + ...tp-Use-devm_platform_ioremap_resourc.patch | 39 + ...p-Use-devm_platform_get_and_ioremap_.patch | 32 + ...rt-specifying-both-cell-raw-data-pos.patch | 115 + ...nv-post-process-ethaddr-env-variable.patch | 81 + ...cro-to-register-nvmem-layout-drivers.patch | 42 + ...28vpd-Use-module_nvmem_layout_driver.patch | 39 + ...ie-tlv-Use-module_nvmem_layout_drive.patch | 39 + ...uts-onie-tlv-Drop-wrong-module-alias.patch | 24 + ...28vpd-set-varaiable-sl28vpd_layout-s.patch | 31 + ...-bcm47xx-support-init-from-IO-memory.patch | 100 + ...set-varaiable-imx_ocotp_layout-stora.patch | 31 + ...Reverse-MAC-addresses-on-all-i.MX-de.patch | 71 + ...vram-add-.read_post_process-for-MACs.patch | 81 + ...tp-Add-clks-and-reg_read-to-rockchip.patch | 166 + ...tp-Generalize-rockchip_otp_wait_stat.patch | 62 + ...tp-Use-devm_reset_control_array_get_.patch | 31 + ...hip-otp-Improve-probe-error-handling.patch | 71 + ...-rockchip-otp-Add-support-for-RK3588.patch | 129 + ...-Switch-xilinx.com-emails-to-amd.com.patch | 26 + ...-0010-nvmem-imx-support-i.MX93-OCOTP.patch | 230 + ...e-add-support-for-fixed-cells-layout.patch | 96 + ...Convert-to-devm_platform_ioremap_res.patch | 36 + ...-Use-devm_platform_get_and_ioremap_r.patch | 30 + ...p-Convert-to-devm_platform_ioremap_r.patch | 34 + ...fuse-Convert-to-devm_platform_iorema.patch | 36 + ...fuse-Use-devm_platform_get_and_iorem.patch | 31 + ...m-Use-devm_platform_get_and_ioremap_.patch | 30 + ....6-0007-nvmem-qfprom-do-some-cleanup.patch | 59 + ...se-devm_platform_get_and_ioremap_res.patch | 29 + ...nvmem-add-new-NXP-QorIQ-eFuse-driver.patch | 133 + ...-nvmem-Kconfig-Fix-typo-drive-driver.patch | 37 + ...m-Add-Qualcomm-secure-QFPROM-support.patch | 152 + ...-Replace-zero-length-array-with-DECL.patch | 30 + ...e-all-cells-before-adding-the-nvmem-.patch | 40 + ...n-NULL-when-no-nvmem-layout-is-found.patch | 35 + ...-Do-not-open-code-existing-functions.patch | 29 + ...tify-when-a-new-layout-is-registered.patch | 44 + ...ia-Use-sysfs_emit-instead-of-sprintf.patch | 29 + ...a-Make-set_brightness-more-efficient.patch | 207 + ...a-Support-HW-controlled-mode-via-pri.patch | 202 + ...a-Add-support-for-enabling-disabling.patch | 244 + ...a-Fix-brightness-setting-and-trigger.patch | 167 + ...mem-qfprom-Mark-core-clk-as-optional.patch | 37 + ...it-config-option-to-read-old-syntax-.patch | 330 + ...0003-nvmem-Use-device_get_match_data.patch | 77 + ...4-Revert-nvmem-add-new-config-option.patch | 77 + ...ect-fixed-layouts-to-grab-a-layout-d.patch | 45 + ..._nvram-store-a-copy-of-NVRAM-content.patch | 261 + ...-device-Export-of_device_make_bus_id.patch | 140 + ...mem_layout_get_container-in-another-.patch | 95 + ...Create-a-header-for-internal-sharing.patch | 91 + ...03-nvmem-Simplify-the-add_cells-hook.patch | 79 + ...vmem-Move-and-rename-fixup_cell_info.patch | 169 + ...rk-layouts-to-become-regular-devices.patch | 763 ++ ...vmem-core-Expose-cells-through-sysfs.patch | 240 + ...support-for-STM32MP25-BSEC-to-contro.patch | 65 + ...factor-.add_cells-callback-arguments.patch | 94 + ...mem-drop-nvmem_layout_get_match_data.patch | 72 + ...nvmem-core-add-nvmem_dev_size-helper.patch | 53 + ...-use-nvmem_add_one_cell-nvmem-subsys.patch | 126 + ...-u-boot-env-use-nvmem-device-helpers.patch | 81 + ...vmem-u-boot-env-improve-coding-style.patch | 62 + ...fix-circular-LEDS_CLASS-dependencies.patch | 65 + ...net-phy-Fix-reading-LED-reg-property.patch | 43 + ...emove-LEDs-to-ensure-correct-orderin.patch | 67 + ...dev-Remove-NULL-check-before-dev_-pu.patch | 44 + ...dev-uninitialized-variable-in-netdev.patch | 31 + ...netdev-Fix-requesting-offload-device.patch | 57 + ...ce-Call-into-the-PHY-driver-to-set-L.patch | 149 + ...Add-support-for-offloading-LED-blink.patch | 344 + ...-Disable-offload-on-deactivation-of-.patch | 31 + ...-of_parse_phandle_with_optional_args.patch | 58 + ...ke-.-cells-optional-for-simple-props.patch | 34 + ...operty-add-nvmem-cell-cells-property.patch | 30 + ...vice-Ignore-modalias-of-reused-nodes.patch | 37 + ...-ignore-error-code-in-of_device_ueve.patch | 29 + ...002-of-Update-of_device_get_modalias.patch | 103 + ...v6.4-0003-of-Rename-of_modalias_node.patch | 173 + ...0004-of-Move-of_modalias-to-module.c.patch | 160 + ...uest-module-helper-logic-to-module.c.patch | 131 + ...qcom-document-qcom-msm-id-and-qcom-b.patch | 207 + ...-move-SMEM-item-struct-and-defines-t.patch | 171 + ...com-smem-Switch-to-EXPORT_SYMBOL_GPL.patch | 55 + ...-smem-introduce-qcom_smem_get_soc_id.patch | 70 + ...com-nvmem-use-SoC-ID-s-from-bindings.patch | 51 + ...-nvmem-use-helper-to-get-SMEM-SoC-ID.patch | 109 + ...tc-rtc7301-Support-byte-addressed-IO.patch | 93 + ...t-phy-amd-Support-the-Altima-AMI101L.patch | 82 + ...ors-from-DT-bindings-to-led_co.patch.patch | 29 + ...igger-netdev-Extend-speeds-up-to-10G.patch | 111 + ...-support-for-PHY-LEDs-polarity-modes.patch | 98 + ...dev-fix-RTNL-handling-to-prevent-pot.patch | 170 + ....4-net-phy-hide-the-PHYLIB_LEDS-knob.patch | 43 + ...dev-Fix-kernel-panic-on-interface-re.patch | 55 + ...-spinand-winbond-fix-flash-detection.patch | 40 + ...6.2-mtd-spinand-winbond-add-W25N02KV.patch | 106 + ...d-spinand-winbond-Fix-ecc_get_status.patch | 49 + ...8-net-ethtool-implement-ethtool_puts.patch | 139 + target/linux/generic/config-6.6 | 7936 +++++++++++++++++ .../generic/hack-6.6/204-module_strip.patch | 210 + ...-abort-configuration-on-unset-symbol.patch | 41 + .../hack-6.6/210-darwin_scripts_include.patch | 3053 +++++++ .../211-darwin-uuid-typedef-clash.patch | 22 + .../hack-6.6/212-tools_portability.patch | 342 + .../hack-6.6/214-spidev_h_portability.patch | 24 + .../hack-6.6/220-arm-gc_sections.patch | 123 + .../generic/hack-6.6/221-module_exports.patch | 126 + .../hack-6.6/230-openwrt_lzma_options.patch | 38 + .../hack-6.6/250-netfilter_depends.patch | 27 + .../linux/generic/hack-6.6/251-kconfig.patch | 157 + .../generic/hack-6.6/253-ksmbd-config.patch | 32 + .../generic/hack-6.6/259-regmap_dynamic.patch | 144 + .../260-crypto_test_dependencies.patch | 52 + .../hack-6.6/261-lib-arc4-unhide.patch | 24 + .../generic/hack-6.6/280-rfkill-stubs.patch | 84 + ...cache-use-more-efficient-cache-blast.patch | 64 + ...rans-call-add-disks-after-mtd-device.patch | 112 + ...upport-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch | 24 + ...ers-add-nvmem-support-to-cmdlinepart.patch | 120 + .../hack-6.6/430-mtk-bmt-support.patch | 33 + ...lter-connmark-introduce-set-dscpmark.patch | 214 + ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 803 ++ .../hack-6.6/651-wireless_mesh_header.patch | 24 + .../hack-6.6/660-fq_codel_defaults.patch | 27 + ...t-size-the-hashtable-more-adequately.patch | 25 + .../700-swconfig_switch_drivers.patch | 131 + ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 21 + .../721-net-add-packet-mangeling.patch | 167 + ...hy-aquantia-enable-AQR112-and-AQR412.patch | 148 + ...aquantia-fix-system-side-protocol-mi.patch | 34 + ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 63 + ...mtk-lynxi-workaround-2500BaseX-no-an.patch | 53 + ...-r8152-add-LED-configuration-from-OF.patch | 74 + ...et-add-RTL8152-binding-documentation.patch | 54 + .../765-mxl-gpy-control-LED-reg-from-DT.patch | 105 + ...k-ge-add-LED-configuration-interface.patch | 72 + .../hack-6.6/773-bgmac-add-srab-switch.patch | 98 + .../780-usb-net-MeigLink_modem_support.patch | 69 + .../781-usb-net-rndis-support-asr.patch | 56 + .../790-SFP-GE-T-ignore-TX_FAULT.patch | 63 + .../800-GPIO-add-named-gpio-exports.patch | 190 + .../810-bcma-ssb-fallback-sprom.patch | 187 + .../hack-6.6/901-debloat_sock_diag.patch | 174 + .../generic/hack-6.6/902-debloat_proc.patch | 419 + .../hack-6.6/904-debloat_dma_buf.patch | 93 + .../generic/hack-6.6/910-kobject_uevent.patch | 32 + .../911-kobject_add_broadcast_uevent.patch | 76 + .../hack-6.6/920-device_tree_cmdline.patch | 21 + ...vert-driver-core-Set-fw_devlink-on-b.patch | 30 + ...include-asm-rwonce.h-for-kernel-code.patch | 29 + ...s-negative-stack-offsets-on-stack-tr.patch | 57 + .../103-kbuild-export-SUBARCH.patch | 21 + ...ilicon-Labs-EM3581-device-compatible.patch | 32 + ...ilicon-Labs-SI3210-device-compatible.patch | 32 + ..._wdt-Add-support-for-specifying-WDI-.patch | 75 + ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 82 + ...ame2-and-add-RENAME_WHITEOUT-support.patch | 81 + ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 73 + .../142-jffs2-add-splice-ops.patch | 20 + ...ge_allow_receiption_on_disabled_port.patch | 45 + ...t-send-arp-replies-if-src-and-target.patch | 37 + ...-rs5c372-support_alarms_up_to_1_week.patch | 94 + ...he_alarm_to_be_used_as_wakeup_source.patch | 71 + .../203-kallsyms_uncompressed.patch | 118 + .../205-backtrace_module_info.patch | 41 + ...e-filenames-from-deps_initramfs-list.patch | 30 + ...able_wilink_platform_without_drivers.patch | 20 + .../270-platform-mikrotik-build-bits.patch | 31 + .../300-mips_expose_boot_raw.patch | 40 + ...rriers-between-dcache-icache-flushes.patch | 71 + .../302-mips_no_branch_likely.patch | 22 + .../pending-6.6/305-mips_module_reloc.patch | 370 + .../pending-6.6/308-mips32r2_tune.patch | 22 + .../310-arm_module_unresolved_weak_sym.patch | 22 + ...t-command-line-parameters-from-users.patch | 282 + .../332-arc-add-OWRTDTB-section.patch | 84 + ...able-unaligned-access-in-kernel-mode.patch | 24 + ...ernel-XZ-compression-option-on-PPC_8.patch | 25 + ...ip-bcm-6345-l1-request-memory-region.patch | 113 + .../400-mtd-mtdsplit-support.patch | 328 + ...er-NVMEM-devices-for-partitions-with.patch | 48 + ...support-for-minor-aligned-partitions.patch | 245 + .../pending-6.6/420-mtd-redboot_space.patch | 41 + ...30-mtd-add-myloader-partition-parser.patch | 229 + ...check-for-bad-blocks-when-calculatin.patch | 68 + ...bcm47xxpart-detect-T_Meter-partition.patch | 37 + ...mtd-add-routerbootpart-parser-config.patch | 38 + ...dings-mtd-add-basic-bindings-for-UBI.patch | 121 + ...ubi-volume-allow-UBI-volumes-to-prov.patch | 48 + ...e-notifier-to-create-ubiblock-from-p.patch | 225 + ...0-04-mtd-ubi-attach-from-device-tree.patch | 264 + ...e-pre-removal-notification-for-UBI-v.patch | 226 + ...6-mtd-ubi-populate-ubi-volume-fwnode.patch | 65 + ...provide-NVMEM-layer-over-UBI-volumes.patch | 246 + ...k-add-basic-bindings-for-block-devic.patch | 120 + ...-09-block-partitions-populate-fwnode.patch | 77 + ...ck-add-new-genhd-flag-GENHD_FL_NVMEM.patch | 29 + ...50-11-block-implement-NVMEM-provider.patch | 235 + ...-mmc-mmc-card-add-block-device-nodes.patch | 74 + ...0-13-mmc-core-set-card-fwnode_handle.patch | 23 + ...mmc-block-set-fwnode-of-disk-devices.patch | 39 + .../450-15-mmc-block-set-GENHD_FL_NVMEM.patch | 22 + ...mtd-cfi_cmdset_0002-no-erase_suspend.patch | 25 + ...et_0002-add-buffer-write-cmd-timeout.patch | 17 + ...25p80-mx-disable-software-protection.patch | 18 + .../476-mtd-spi-nor-add-eon-en25q128.patch | 19 + .../477-mtd-spi-nor-add-eon-en25qx128a.patch | 21 + .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 81 + ...r-add-support-for-Gigadevice-GD25D05.patch | 23 + .../482-mtd-spi-nor-add-gd25q512.patch | 23 + .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 24 + .../485-mtd-spi-nor-add-xmc-xm25qh128c.patch | 25 + ...nand-add-support-for-ESMT-F50x1G41LB.patch | 143 + ...nd-Add-support-for-Etron-EM73D044VCx.patch | 168 + .../488-mtd-spi-nor-add-xmc-xm25qh64c.patch | 23 + ...mtd-device-named-ubi-or-data-on-boot.patch | 98 + ...to-create-ubiblock-device-for-rootfs.patch | 77 + ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 53 + ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 34 + .../494-mtd-ubi-add-EOF-marker-support.patch | 60 + ...-add-bindings-for-mtd-concat-devices.patch | 52 + ...cat-add-dt-driver-for-concat-devices.patch | 216 + ...i-nor-locking-support-for-MX25L6405D.patch | 32 + ...i-nor-disable-16-bit-sr-for-macronix.patch | 30 + .../500-fs_cdrom_dependencies.patch | 52 + ...add-uImage.FIT-subimage-block-driver.patch | 733 ++ ...ass-device-lookup-for-dev-fit-rootfs.patch | 25 + .../530-jffs2_make_lzma_available.patch | 5180 +++++++++++ .../pending-6.6/532-jffs2_eofdetect.patch | 65 + .../600-netfilter_conntrack_flush.patch | 90 + ...etfilter_match_bypass_default_checks.patch | 110 + ...netfilter_match_bypass_default_table.patch | 106 + ...netfilter_match_reduce_memory_access.patch | 22 + ...del-do-not-defer-queue-length-update.patch | 86 + .../pending-6.6/630-packet_socket_type.patch | 138 + .../pending-6.6/655-increase_skb_pad.patch | 20 + ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 511 ++ ...ng-with-source-address-failed-policy.patch | 263 + ...nes-for-_POLICY_FAILED-until-all-cod.patch | 50 + ...T-skip-GRO-for-foreign-MAC-addresses.patch | 151 + ...83-of_net-add-mac-address-to-of-tree.patch | 75 + ...ow_offload-handle-netdevice-events-f.patch | 110 + ...les-ignore-EOPNOTSUPP-on-flowtable-d.patch | 29 + ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 21 + ...detach-callback-to-struct-phy_driver.patch | 38 + ...les-fix-bidirectional-offload-regres.patch | 24 + ...a-tag_mtk-add-padding-for-tx-packets.patch | 28 + ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 174 + ...-qca8k-implement-lag_fdb_add-del-ops.patch | 86 + ...a8k-enable-flooding-to-both-CPU-port.patch | 37 + ...k-add-support-for-port_change_master.patch | 158 + ...enable-assisted-learning-on-CPU-port.patch | 57 + ...pq8074-add-clock-frequency-to-MDIO-n.patch | 25 + ...rtl8221-allow-to-configure-SERDES-mo.patch | 106 + ...support-switching-between-SGMII-and-.patch | 61 + ...e-all-MACs-are-powered-down-before-r.patch | 28 + ...-use-genphy_soft_reset-for-2.5G-PHYs.patch | 65 + ...sable-SGMII-in-band-AN-for-2-5G-PHYs.patch | 43 + ...make-sure-paged-read-is-protected-by.patch | 35 + ...use-inline-functions-for-10GbE-adver.patch | 60 + ...check-validity-of-10GbE-link-partner.patch | 28 + ...-phy-realtek-introduce-rtl822x_probe.patch | 84 + ...tek-detect-early-version-of-RTL8221B.patch | 63 + ...0211_ptr-even-with-no-CFG82111-suppo.patch | 59 + ..._eth_soc-compile-out-netsys-v2-code-.patch | 44 + ..._eth_soc-work-around-issue-with-send.patch | 94 + ...rnet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch | 21 + ..._eth_soc-fix-remaining-throughput-re.patch | 42 + ..._eth_soc-ppe-fix-L2-offloading-with-.patch | 33 + ..._eth_soc-add-paths-and-SerDes-modes-.patch | 935 ++ ..._eth_soc-set-coherent-mask-to-get-PP.patch | 46 + ...y-mediatek-xfi-tphy-add-new-bindings.patch | 136 + ...hy-add-driver-for-MediaTek-XFI-T-PHY.patch | 497 ++ ...lynxi-add-platform-driver-for-MT7988.patch | 371 + ...pcs-add-bindings-for-MediaTek-USXGMI.patch | 81 + ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 547 ++ ...et-phy-motorcomm-Add-missing-include.patch | 22 + ...ealtek-support-interrupt-of-RTL8221B.patch | 63 + ...ha-Add-the-Airoha-EN8811H-PHY-driver.patch | 1115 +++ ...ional-threading-for-backlog-processi.patch | 227 + ...equest-assisted-learning-on-CPU-port.patch | 27 + ...a-b53-add-support-for-BCM63xx-RGMIIs.patch | 174 + ...-net-dsa-b53-mmap-add-more-63xx-SoCs.patch | 108 + ...dsa-b53-mmap-allow-passing-a-chip-ID.patch | 195 + ...b53-add-BCM63268-RGMII-configuration.patch | 123 + ...sa-b53-mdio-add-support-for-BCM53134.patch | 189 + ...8-net-l2tp-drop-flow-hash-on-forward.patch | 31 + ...-t-learn-non-unicast-L2-destinations.patch | 30 + ...-missing-linux-if_ether.h-for-ETH_AL.patch | 61 + ...-bus-mhi-core-add-SBL-state-callback.patch | 48 + ...gister-OF-node-for-internal-MDIO-bus.patch | 43 + ...-fix-10M-100M-speed-on-MT7988-switch.patch | 45 + ...ice-struct-copy-its-DMA-params-to-th.patch | 73 + ...pio-cascade-add-generic-GPIO-cascade.patch | 222 + ...e-old-opp-to-config_clks-on-_set_opp.patch | 108 + ...env-align-endianness-of-crc32-values.patch | 47 + ...-support-mac-base-fixed-layout-cells.patch | 124 + .../810-pci_disable_common_quirks.patch | 62 + .../811-pci_disable_usb_common_quirks.patch | 115 + ...problem-with-platfom-data-in-w1-gpio.patch | 26 + .../pending-6.6/834-ledtrig-libata.patch | 149 + ...40-hwrng-bcm2835-set-quality-to-1000.patch | 26 + ...e-main-irq_chip-structure-a-static-d.patch | 102 + ...add-BCM63268-timer-clock-definitions.patch | 114 + ...add-BCM63268-timer-reset-definitions.patch | 107 + ...CM63268-timer-clock-and-reset-driver.patch | 345 + ...rack-busclk-state-to-avoid-bus-error.patch | 61 + ...-nxp-imx7d-pico-add-cpu-supply-nodes.patch | 43 + .../pending-6.6/920-mangle_bootargs.patch | 71 + ...on-Fix-compilation-warning-for-wrong.patch | 51 + 654 files changed, 112195 insertions(+) create mode 100644 target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch create mode 100644 target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch create mode 100644 target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch create mode 100644 target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch create mode 100644 target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch create mode 100644 target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch create mode 100644 target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch create mode 100644 target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch create mode 100644 target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch create mode 100644 target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch create mode 100644 target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch create mode 100644 target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch create mode 100644 target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch create mode 100644 target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch create mode 100644 target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch create mode 100644 target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch create mode 100644 target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch create mode 100644 target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch create mode 100644 target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch create mode 100644 target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch create mode 100644 target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch create mode 100644 target/linux/generic/backport-6.6/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch create mode 100644 target/linux/generic/backport-6.6/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch create mode 100644 target/linux/generic/backport-6.6/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch create mode 100644 target/linux/generic/backport-6.6/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch create mode 100644 target/linux/generic/backport-6.6/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch create mode 100644 target/linux/generic/backport-6.6/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch create mode 100644 target/linux/generic/backport-6.6/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch create mode 100644 target/linux/generic/backport-6.6/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch create mode 100644 target/linux/generic/backport-6.6/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch create mode 100644 target/linux/generic/backport-6.6/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch create mode 100644 target/linux/generic/backport-6.6/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch create mode 100644 target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch create mode 100644 target/linux/generic/backport-6.6/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch create mode 100644 target/linux/generic/backport-6.6/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch create mode 100644 target/linux/generic/backport-6.6/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch create mode 100644 target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch create mode 100644 target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch create mode 100644 target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch create mode 100644 target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch create mode 100644 target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch create mode 100644 target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch create mode 100644 target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch create mode 100644 target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch create mode 100644 target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch create mode 100644 target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch create mode 100644 target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch create mode 100644 target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch create mode 100644 target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch create mode 100644 target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch create mode 100644 target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch create mode 100644 target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch create mode 100644 target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch create mode 100644 target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch create mode 100644 target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch create mode 100644 target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch create mode 100644 target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch create mode 100644 target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch create mode 100644 target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch create mode 100644 target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch create mode 100644 target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch create mode 100644 target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch create mode 100644 target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch create mode 100644 target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch create mode 100644 target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch create mode 100644 target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch create mode 100644 target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch create mode 100644 target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch create mode 100644 target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch create mode 100644 target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch create mode 100644 target/linux/generic/backport-6.6/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch create mode 100644 target/linux/generic/backport-6.6/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch create mode 100644 target/linux/generic/backport-6.6/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch create mode 100644 target/linux/generic/backport-6.6/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch create mode 100644 target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch create mode 100644 target/linux/generic/backport-6.6/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch create mode 100644 target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch create mode 100644 target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch create mode 100644 target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch create mode 100644 target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch create mode 100644 target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch create mode 100644 target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch create mode 100644 target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch create mode 100644 target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch create mode 100644 target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch create mode 100644 target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch create mode 100644 target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch create mode 100644 target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch create mode 100644 target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch create mode 100644 target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch create mode 100644 target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch create mode 100644 target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch create mode 100644 target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch create mode 100644 target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch create mode 100644 target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch create mode 100644 target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch create mode 100644 target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch create mode 100644 target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch create mode 100644 target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch create mode 100644 target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch create mode 100644 target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch create mode 100644 target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch create mode 100644 target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch create mode 100644 target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch create mode 100644 target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch create mode 100644 target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch create mode 100644 target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch create mode 100644 target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch create mode 100644 target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch create mode 100644 target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch create mode 100644 target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch create mode 100644 target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch create mode 100644 target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch create mode 100644 target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch create mode 100644 target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch create mode 100644 target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch create mode 100644 target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch create mode 100644 target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch create mode 100644 target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch create mode 100644 target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch create mode 100644 target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch create mode 100644 target/linux/generic/backport-6.6/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch create mode 100644 target/linux/generic/backport-6.6/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch create mode 100644 target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch create mode 100644 target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch create mode 100644 target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch create mode 100644 target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch create mode 100644 target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch create mode 100644 target/linux/generic/backport-6.6/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch create mode 100644 target/linux/generic/backport-6.6/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch create mode 100644 target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch create mode 100644 target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch create mode 100644 target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch create mode 100644 target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch create mode 100644 target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch create mode 100644 target/linux/generic/backport-6.6/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch create mode 100644 target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch create mode 100644 target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch create mode 100644 target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch create mode 100644 target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch create mode 100644 target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch create mode 100644 target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch create mode 100644 target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch create mode 100644 target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch create mode 100644 target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch create mode 100644 target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch create mode 100644 target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch create mode 100644 target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch create mode 100644 target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch create mode 100644 target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch create mode 100644 target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch create mode 100644 target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch create mode 100644 target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch create mode 100644 target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch create mode 100644 target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch create mode 100644 target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch create mode 100644 target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch create mode 100644 target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch create mode 100644 target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch create mode 100644 target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch create mode 100644 target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch create mode 100644 target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch create mode 100644 target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch create mode 100644 target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch create mode 100644 target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch create mode 100644 target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch create mode 100644 target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch create mode 100644 target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch create mode 100644 target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch create mode 100644 target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch create mode 100644 target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch create mode 100644 target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch create mode 100644 target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch create mode 100644 target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch create mode 100644 target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch create mode 100644 target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch create mode 100644 target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch create mode 100644 target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch create mode 100644 target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch create mode 100644 target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch create mode 100644 target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch create mode 100644 target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch create mode 100644 target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch create mode 100644 target/linux/generic/backport-6.6/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch create mode 100644 target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch create mode 100644 target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch create mode 100644 target/linux/generic/backport-6.6/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0003-nvmem-Use-device_get_match_data.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch create mode 100644 target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch create mode 100644 target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch create mode 100644 target/linux/generic/backport-6.6/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch create mode 100644 target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch create mode 100644 target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch create mode 100644 target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch create mode 100644 target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch create mode 100644 target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch create mode 100644 target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch create mode 100644 target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch create mode 100644 target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch create mode 100644 target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch create mode 100644 target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch create mode 100644 target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch create mode 100644 target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch create mode 100644 target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch create mode 100644 target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch create mode 100644 target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch create mode 100644 target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch create mode 100644 target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch create mode 100644 target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch create mode 100644 target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch create mode 100644 target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch create mode 100644 target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch create mode 100644 target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch create mode 100644 target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch create mode 100644 target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch create mode 100644 target/linux/generic/backport-6.6/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch create mode 100644 target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch create mode 100644 target/linux/generic/backport-6.6/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch create mode 100644 target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch create mode 100644 target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch create mode 100644 target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch create mode 100644 target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch create mode 100644 target/linux/generic/backport-6.6/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch create mode 100644 target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch create mode 100644 target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch create mode 100644 target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch create mode 100644 target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch create mode 100644 target/linux/generic/config-6.6 create mode 100644 target/linux/generic/hack-6.6/204-module_strip.patch create mode 100644 target/linux/generic/hack-6.6/205-kconfig-abort-configuration-on-unset-symbol.patch create mode 100644 target/linux/generic/hack-6.6/210-darwin_scripts_include.patch create mode 100644 target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch create mode 100644 target/linux/generic/hack-6.6/212-tools_portability.patch create mode 100644 target/linux/generic/hack-6.6/214-spidev_h_portability.patch create mode 100644 target/linux/generic/hack-6.6/220-arm-gc_sections.patch create mode 100644 target/linux/generic/hack-6.6/221-module_exports.patch create mode 100644 target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch create mode 100644 target/linux/generic/hack-6.6/250-netfilter_depends.patch create mode 100644 target/linux/generic/hack-6.6/251-kconfig.patch create mode 100644 target/linux/generic/hack-6.6/253-ksmbd-config.patch create mode 100644 target/linux/generic/hack-6.6/259-regmap_dynamic.patch create mode 100644 target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch create mode 100644 target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch create mode 100644 target/linux/generic/hack-6.6/280-rfkill-stubs.patch create mode 100644 target/linux/generic/hack-6.6/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch create mode 100644 target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch create mode 100644 target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch create mode 100644 target/linux/generic/hack-6.6/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch create mode 100644 target/linux/generic/hack-6.6/430-mtk-bmt-support.patch create mode 100644 target/linux/generic/hack-6.6/645-netfilter-connmark-introduce-set-dscpmark.patch create mode 100644 target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch create mode 100644 target/linux/generic/hack-6.6/651-wireless_mesh_header.patch create mode 100644 target/linux/generic/hack-6.6/660-fq_codel_defaults.patch create mode 100644 target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch create mode 100644 target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch create mode 100644 target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch create mode 100644 target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch create mode 100644 target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch create mode 100644 target/linux/generic/hack-6.6/723-net-phy-aquantia-fix-system-side-protocol-mi.patch create mode 100644 target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch create mode 100644 target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch create mode 100644 target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch create mode 100644 target/linux/generic/hack-6.6/761-dt-bindings-net-add-RTL8152-binding-documentation.patch create mode 100644 target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch create mode 100644 target/linux/generic/hack-6.6/766-net-phy-mediatek-ge-add-LED-configuration-interface.patch create mode 100644 target/linux/generic/hack-6.6/773-bgmac-add-srab-switch.patch create mode 100644 target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch create mode 100644 target/linux/generic/hack-6.6/781-usb-net-rndis-support-asr.patch create mode 100644 target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch create mode 100644 target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch create mode 100644 target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch create mode 100644 target/linux/generic/hack-6.6/901-debloat_sock_diag.patch create mode 100644 target/linux/generic/hack-6.6/902-debloat_proc.patch create mode 100644 target/linux/generic/hack-6.6/904-debloat_dma_buf.patch create mode 100644 target/linux/generic/hack-6.6/910-kobject_uevent.patch create mode 100644 target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch create mode 100644 target/linux/generic/hack-6.6/920-device_tree_cmdline.patch create mode 100644 target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch create mode 100644 target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch create mode 100644 target/linux/generic/pending-6.6/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch create mode 100644 target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch create mode 100644 target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch create mode 100644 target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch create mode 100644 target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch create mode 100644 target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch create mode 100644 target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch create mode 100644 target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch create mode 100644 target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch create mode 100644 target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch create mode 100644 target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch create mode 100644 target/linux/generic/pending-6.6/190-rtc-rs5c372-support_alarms_up_to_1_week.patch create mode 100644 target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch create mode 100644 target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch create mode 100644 target/linux/generic/pending-6.6/205-backtrace_module_info.patch create mode 100644 target/linux/generic/pending-6.6/240-remove-unsane-filenames-from-deps_initramfs-list.patch create mode 100644 target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch create mode 100644 target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch create mode 100644 target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch create mode 100644 target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch create mode 100644 target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch create mode 100644 target/linux/generic/pending-6.6/305-mips_module_reloc.patch create mode 100644 target/linux/generic/pending-6.6/308-mips32r2_tune.patch create mode 100644 target/linux/generic/pending-6.6/310-arm_module_unresolved_weak_sym.patch create mode 100644 target/linux/generic/pending-6.6/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch create mode 100644 target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch create mode 100644 target/linux/generic/pending-6.6/333-arc-enable-unaligned-access-in-kernel-mode.patch create mode 100644 target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch create mode 100644 target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch create mode 100644 target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch create mode 100644 target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch create mode 100644 target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch create mode 100644 target/linux/generic/pending-6.6/420-mtd-redboot_space.patch create mode 100644 target/linux/generic/pending-6.6/430-mtd-add-myloader-partition-parser.patch create mode 100644 target/linux/generic/pending-6.6/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch create mode 100644 target/linux/generic/pending-6.6/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch create mode 100644 target/linux/generic/pending-6.6/435-mtd-add-routerbootpart-parser-config.patch create mode 100644 target/linux/generic/pending-6.6/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch create mode 100644 target/linux/generic/pending-6.6/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch create mode 100644 target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch create mode 100644 target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch create mode 100644 target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch create mode 100644 target/linux/generic/pending-6.6/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch create mode 100644 target/linux/generic/pending-6.6/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch create mode 100644 target/linux/generic/pending-6.6/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch create mode 100644 target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch create mode 100644 target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch create mode 100644 target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch create mode 100644 target/linux/generic/pending-6.6/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch create mode 100644 target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch create mode 100644 target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch create mode 100644 target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch create mode 100644 target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch create mode 100644 target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch create mode 100644 target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch create mode 100644 target/linux/generic/pending-6.6/476-mtd-spi-nor-add-eon-en25q128.patch create mode 100644 target/linux/generic/pending-6.6/477-mtd-spi-nor-add-eon-en25qx128a.patch create mode 100644 target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch create mode 100644 target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch create mode 100644 target/linux/generic/pending-6.6/482-mtd-spi-nor-add-gd25q512.patch create mode 100644 target/linux/generic/pending-6.6/484-mtd-spi-nor-add-esmt-f25l16pa.patch create mode 100644 target/linux/generic/pending-6.6/485-mtd-spi-nor-add-xmc-xm25qh128c.patch create mode 100644 target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch create mode 100644 target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch create mode 100644 target/linux/generic/pending-6.6/488-mtd-spi-nor-add-xmc-xm25qh64c.patch create mode 100644 target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch create mode 100644 target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch create mode 100644 target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch create mode 100644 target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch create mode 100644 target/linux/generic/pending-6.6/494-mtd-ubi-add-EOF-marker-support.patch create mode 100644 target/linux/generic/pending-6.6/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch create mode 100644 target/linux/generic/pending-6.6/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch create mode 100644 target/linux/generic/pending-6.6/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch create mode 100644 target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch create mode 100644 target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch create mode 100644 target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch create mode 100644 target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch create mode 100644 target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch create mode 100644 target/linux/generic/pending-6.6/532-jffs2_eofdetect.patch create mode 100644 target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch create mode 100644 target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch create mode 100644 target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch create mode 100644 target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch create mode 100644 target/linux/generic/pending-6.6/620-net_sched-codel-do-not-defer-queue-length-update.patch create mode 100644 target/linux/generic/pending-6.6/630-packet_socket_type.patch create mode 100644 target/linux/generic/pending-6.6/655-increase_skb_pad.patch create mode 100644 target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch create mode 100644 target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch create mode 100644 target/linux/generic/pending-6.6/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch create mode 100644 target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch create mode 100644 target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch create mode 100644 target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch create mode 100644 target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch create mode 100644 target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch create mode 100644 target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch create mode 100644 target/linux/generic/pending-6.6/704-netfilter-nf_tables-fix-bidirectional-offload-regres.patch create mode 100644 target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch create mode 100644 target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch create mode 100644 target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch create mode 100644 target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch create mode 100644 target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch create mode 100644 target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch create mode 100644 target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch create mode 100644 target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch create mode 100644 target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch create mode 100644 target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch create mode 100644 target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch create mode 100644 target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch create mode 100644 target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch create mode 100644 target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch create mode 100644 target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch create mode 100644 target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch create mode 100644 target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch create mode 100644 target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch create mode 100644 target/linux/generic/pending-6.6/732-00-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch create mode 100644 target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch create mode 100644 target/linux/generic/pending-6.6/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch create mode 100644 target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch create mode 100644 target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch create mode 100644 target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch create mode 100644 target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch create mode 100644 target/linux/generic/pending-6.6/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch create mode 100644 target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch create mode 100644 target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch create mode 100644 target/linux/generic/pending-6.6/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch create mode 100644 target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch create mode 100644 target/linux/generic/pending-6.6/740-net-phy-motorcomm-Add-missing-include.patch create mode 100644 target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch create mode 100644 target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch create mode 100644 target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch create mode 100644 target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch create mode 100644 target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch create mode 100644 target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch create mode 100644 target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch create mode 100644 target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch create mode 100644 target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch create mode 100644 target/linux/generic/pending-6.6/778-net-l2tp-drop-flow-hash-on-forward.patch create mode 100644 target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch create mode 100644 target/linux/generic/pending-6.6/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch create mode 100644 target/linux/generic/pending-6.6/790-bus-mhi-core-add-SBL-state-callback.patch create mode 100644 target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch create mode 100644 target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch create mode 100644 target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch create mode 100644 target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch create mode 100644 target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch create mode 100644 target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch create mode 100644 target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch create mode 100644 target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch create mode 100644 target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch create mode 100644 target/linux/generic/pending-6.6/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch create mode 100644 target/linux/generic/pending-6.6/834-ledtrig-libata.patch create mode 100644 target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch create mode 100644 target/linux/generic/pending-6.6/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch create mode 100644 target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch create mode 100644 target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch create mode 100644 target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch create mode 100644 target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch create mode 100644 target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch create mode 100644 target/linux/generic/pending-6.6/920-mangle_bootargs.patch create mode 100644 target/linux/generic/pending-6.6/980-tools-thermal-tmon-Fix-compilation-warning-for-wrong.patch diff --git a/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch b/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch new file mode 100644 index 0000000000..fe32acc985 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch @@ -0,0 +1,352 @@ +From 8c20e2eb5f2a0175b774134685e4d7bd93e85ff8 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:18:59 -0700 +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. + +Overview +======== + +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 reclaim is currently out of scope. + +Its memory bloat is a pointer to each lruvec and negligible to each +pglist_data. 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 in contrast to the current linear complexity. + +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. + +The commit message in patch 6 details the workflow: +https://lore.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com/ + +The following is a simple test to quickly verify its effectiveness. + + Test design: + 1. Create multiple memcgs. + 2. Each memcg contains a job (fio). + 3. All jobs access the same amount of memory randomly. + 4. The system does not experience global memory pressure. + 5. Periodically write to the root memory.reclaim. + + Desired outcome: + 1. All memcgs have similar pgsteal counts, i.e., stddev(pgsteal) + over mean(pgsteal) is close to 0%. + 2. The total pgsteal is close to the total requested through + memory.reclaim, i.e., sum(pgsteal) over sum(requested) is close + to 100%. + + Actual outcome [1]: + MGLRU off MGLRU on + stddev(pgsteal) / mean(pgsteal) 75% 20% + sum(pgsteal) / sum(requested) 425% 95% + + #################################################################### + MEMCGS=128 + + for ((memcg = 0; memcg < $MEMCGS; memcg++)); do + mkdir /sys/fs/cgroup/memcg$memcg + done + + start() { + echo $BASHPID > /sys/fs/cgroup/memcg$memcg/cgroup.procs + + fio -name=memcg$memcg --numjobs=1 --ioengine=mmap \ + --filename=/dev/zero --size=1920M --rw=randrw \ + --rate=64m,64m --random_distribution=random \ + --fadvise_hint=0 --time_based --runtime=10h \ + --group_reporting --minimal + } + + for ((memcg = 0; memcg < $MEMCGS; memcg++)); do + start & + done + + sleep 600 + + for ((i = 0; i < 600; i++)); do + echo 256m >/sys/fs/cgroup/memory.reclaim + sleep 6 + done + + for ((memcg = 0; memcg < $MEMCGS; memcg++)); do + grep "pgsteal " /sys/fs/cgroup/memcg$memcg/memory.stat + done + #################################################################### + +[1]: This was obtained from running the above script (touches less + than 256GB memory) on an EPYC 7B13 with 512GB DRAM for over an + hour. + +This patch (of 8): + +The new name lru_gen_folio will be more distinct from the coming +lru_gen_memcg. + +Link: https://lkml.kernel.org/r/20221222041905.2431096-1-yuzhao@google.com +Link: https://lkml.kernel.org/r/20221222041905.2431096-2-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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 +++--- + mm/vmscan.c | 34 +++++++++++++++++----------------- + mm/workingset.c | 4 ++-- + 4 files changed, 24 insertions(+), 24 deletions(-) + +--- a/include/linux/mm_inline.h ++++ b/include/linux/mm_inline.h +@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(s + int zone = folio_zonenum(folio); + int delta = folio_nr_pages(folio); + enum lru_list lru = type * LRU_INACTIVE_FILE; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + 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 + int gen = folio_lru_gen(folio); + int type = folio_is_file_lru(folio); + int zone = folio_zonenum(folio); +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE_FOLIO(gen != -1, folio); + +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -404,7 +404,7 @@ enum { + * The number of pages in each generation is eventually consistent and therefore + * can be transiently negative when reset_batch_size() is pending. + */ +-struct lru_gen_struct { ++struct lru_gen_folio { + /* the aging increments the youngest generation number */ + unsigned long max_seq; + /* the eviction increments the oldest generation numbers */ +@@ -461,7 +461,7 @@ struct lru_gen_mm_state { + struct lru_gen_mm_walk { + /* the lruvec under reclaim */ + struct lruvec *lruvec; +- /* unstable max_seq from lru_gen_struct */ ++ /* unstable max_seq from lru_gen_folio */ + unsigned long max_seq; + /* the next address within an mm to scan */ + unsigned long next_addr; +@@ -524,7 +524,7 @@ struct lruvec { + unsigned long flags; + #ifdef CONFIG_LRU_GEN + /* evictable pages divided into generations */ +- struct lru_gen_struct lrugen; ++ struct lru_gen_folio lrugen; + /* to concurrently iterate lru_gen_mm_list */ + struct lru_gen_mm_state mm_state; + #endif +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lr + + static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) + { +- /* see the comment on lru_gen_struct */ ++ /* see the comment on lru_gen_folio */ + return get_nr_gens(lruvec, LRU_GEN_FILE) >= MIN_NR_GENS && + get_nr_gens(lruvec, LRU_GEN_FILE) <= get_nr_gens(lruvec, LRU_GEN_ANON) && + get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; +@@ -3596,7 +3596,7 @@ struct ctrl_pos { + static void read_ctrl_pos(struct lruvec *lruvec, int type, int tier, int gain, + struct ctrl_pos *pos) + { +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + 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 + static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) + { + int hist, tier; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + 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 + static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclaiming) + { + int type = folio_is_file_lru(folio); +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + 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 + static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) + { + int gen, type, zone; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + walk->batched = 0; + +@@ -4250,7 +4250,7 @@ static bool inc_min_seq(struct lruvec *l + { + int zone; + int remaining = MAX_LRU_BATCH; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); + + if (type == LRU_GEN_ANON && !can_swap) +@@ -4286,7 +4286,7 @@ static bool try_to_inc_min_seq(struct lr + { + int gen, type, zone; + bool success = false; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + DEFINE_MIN_SEQ(lruvec); + + VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); +@@ -4307,7 +4307,7 @@ next: + ; + } + +- /* see the comment on lru_gen_struct */ ++ /* see the comment on lru_gen_folio */ + 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]); +@@ -4329,7 +4329,7 @@ static void inc_max_seq(struct lruvec *l + { + int prev, next; + int type, zone; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + restart: + spin_lock_irq(&lruvec->lru_lock); +@@ -4389,7 +4389,7 @@ static bool try_to_inc_max_seq(struct lr + bool success; + struct lru_gen_mm_walk *walk; + struct mm_struct *mm = NULL; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); + +@@ -4454,7 +4454,7 @@ static bool should_run_aging(struct lruv + unsigned long old = 0; + unsigned long young = 0; + unsigned long total = 0; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + 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 + int delta = folio_nr_pages(folio); + int refs = folio_lru_refs(folio); + int tier = lru_tier_from_refs(refs); +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio); + +@@ -4848,7 +4848,7 @@ static int scan_folios(struct lruvec *lr + int scanned = 0; + int isolated = 0; + int remaining = MAX_LRU_BATCH; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + + VM_WARN_ON_ONCE(!list_empty(list)); +@@ -5249,7 +5249,7 @@ done: + + static bool __maybe_unused state_is_valid(struct lruvec *lruvec) + { +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + if (lrugen->enabled) { + enum lru_list lru; +@@ -5531,7 +5531,7 @@ static void lru_gen_seq_show_full(struct + int i; + int type, tier; + int hist = lru_hist_from_seq(seq); +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + for (tier = 0; tier < MAX_NR_TIERS; tier++) { + seq_printf(m, " %10d", tier); +@@ -5581,7 +5581,7 @@ static int lru_gen_seq_show(struct seq_f + unsigned long seq; + bool full = !debugfs_real_fops(m->file)->write; + struct lruvec *lruvec = v; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + int nid = lruvec_pgdat(lruvec)->node_id; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); +@@ -5835,7 +5835,7 @@ void lru_gen_init_lruvec(struct lruvec * + { + int i; + int gen, type, zone; +- struct lru_gen_struct *lrugen = &lruvec->lrugen; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + + lrugen->max_seq = MIN_NR_GENS + 1; + lrugen->enabled = lru_gen_enabled(); +--- a/mm/workingset.c ++++ b/mm/workingset.c +@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct fol + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; +- struct lru_gen_struct *lrugen; ++ struct lru_gen_folio *lrugen; + 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 + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; +- struct lru_gen_struct *lrugen; ++ struct lru_gen_folio *lrugen; + struct mem_cgroup *memcg; + struct pglist_data *pgdat; + int type = folio_is_file_lru(folio); diff --git a/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch b/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch new file mode 100644 index 0000000000..e5ad78b61d --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch @@ -0,0 +1,192 @@ +From 14f9a7a15f3d1af351f30e0438fd747b7ac253b0 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:01 -0700 +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 +reclaims the rest; then it increments lrugen->min_seq. + +The current eviction fairness safeguard for global reclaim has a +dilemma: when there are multiple eligible memcgs, should it continue +or stop upon meeting the reclaim goal? If it continues, it overshoots +and increases direct reclaim latency; if it stops, it loses fairness +between memcgs it has taken memory away from and those it has yet to. + +With memcg LRU, the eviction, while ensuring eventual fairness, will +stop upon meeting its goal. Therefore the current eviction fairness +safeguard for global reclaim will not be needed. + +Note that memcg LRU only applies to global reclaim. For memcg reclaim, +the eviction will continue, even if it is overshooting. This becomes +unconditional due to code simplification. + +Link: https://lkml.kernel.org/r/20221222041905.2431096-4-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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 | 81 +++++++++++++++-------------------------------------- + 1 file changed, 23 insertions(+), 58 deletions(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_c + return sc->target_mem_cgroup; + } + ++static bool global_reclaim(struct scan_control *sc) ++{ ++ return !sc->target_mem_cgroup || mem_cgroup_is_root(sc->target_mem_cgroup); ++} ++ + /** + * 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 + return false; + } + ++static bool global_reclaim(struct scan_control *sc) ++{ ++ return true; ++} ++ + static bool writeback_throttling_sane(struct scan_control *sc) + { + return true; +@@ -5005,8 +5015,7 @@ static int isolate_folios(struct lruvec + return scanned; + } + +-static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness, +- bool *need_swapping) ++static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness) + { + int type; + int scanned; +@@ -5095,9 +5104,6 @@ retry: + goto retry; + } + +- if (need_swapping && type == LRU_GEN_ANON) +- *need_swapping = true; +- + return scanned; + } + +@@ -5136,67 +5142,26 @@ done: + return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; + } + +-static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq, +- struct scan_control *sc, bool need_swapping) ++static unsigned long get_nr_to_reclaim(struct scan_control *sc) + { +- int i; +- DEFINE_MAX_SEQ(lruvec); +- +- if (!current_is_kswapd()) { +- /* age each memcg at most once to ensure fairness */ +- if (max_seq - seq > 1) +- return true; +- +- /* over-swapping can increase allocation latency */ +- if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping) +- return true; +- +- /* give this thread a chance to exit and free its memory */ +- if (fatal_signal_pending(current)) { +- sc->nr_reclaimed += MIN_LRU_BATCH; +- return true; +- } +- +- if (cgroup_reclaim(sc)) +- return false; +- } else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim) +- return false; +- +- /* keep scanning at low priorities to ensure fairness */ +- if (sc->priority > DEF_PRIORITY - 2) +- return false; +- +- /* +- * A minimum amount of work was done under global memory pressure. For +- * kswapd, it may be overshooting. For direct reclaim, the allocation +- * may succeed if all suitable zones are somewhat safe. In either case, +- * it's better to stop now, and restart later if necessary. +- */ +- for (i = 0; i <= sc->reclaim_idx; i++) { +- unsigned long wmark; +- struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i; +- +- if (!managed_zone(zone)) +- continue; +- +- wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone); +- if (wmark > zone_page_state(zone, NR_FREE_PAGES)) +- return false; +- } ++ /* don't abort memcg reclaim to ensure fairness */ ++ if (!global_reclaim(sc)) ++ return -1; + +- sc->nr_reclaimed += MIN_LRU_BATCH; ++ /* discount the previous progress for kswapd */ ++ if (current_is_kswapd()) ++ return sc->nr_to_reclaim + sc->last_reclaimed; + +- return true; ++ return max(sc->nr_to_reclaim, compact_gap(sc->order)); + } + + static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + { + struct blk_plug plug; + bool need_aging = false; +- bool need_swapping = false; + unsigned long scanned = 0; + unsigned long reclaimed = sc->nr_reclaimed; +- DEFINE_MAX_SEQ(lruvec); ++ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); + + lru_add_drain(); + +@@ -5220,7 +5185,7 @@ static void lru_gen_shrink_lruvec(struct + if (!nr_to_scan) + goto done; + +- delta = evict_folios(lruvec, sc, swappiness, &need_swapping); ++ delta = evict_folios(lruvec, sc, swappiness); + if (!delta) + goto done; + +@@ -5228,7 +5193,7 @@ static void lru_gen_shrink_lruvec(struct + if (scanned >= nr_to_scan) + break; + +- if (should_abort_scan(lruvec, max_seq, sc, need_swapping)) ++ if (sc->nr_reclaimed >= nr_to_reclaim) + break; + + cond_resched(); +@@ -5678,7 +5643,7 @@ static int run_eviction(struct lruvec *l + if (sc->nr_reclaimed >= nr_to_reclaim) + return 0; + +- if (!evict_folios(lruvec, sc, swappiness, NULL)) ++ if (!evict_folios(lruvec, sc, swappiness)) + return 0; + + cond_resched(); diff --git a/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch b/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch new file mode 100644 index 0000000000..cb349abcdb --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch @@ -0,0 +1,294 @@ +From f3c93d2e37a3c56593d7ccf4f4bcf1b58426fdd8 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:02 -0700 +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 +lrugen->max_seq. + +The current aging fairness safeguard for kswapd uses two passes to +ensure the fairness to multiple eligible memcgs. On the first pass, +which is shared with the eviction, it checks whether all eligible +memcgs are low on cold folios. If so, it requires a second pass, on +which it ages all those memcgs at the same time. + +With memcg LRU, the aging, while ensuring eventual fairness, will run +when necessary. Therefore the current aging fairness safeguard for +kswapd will not be needed. + +Note that memcg LRU only applies to global reclaim. For memcg reclaim, +the aging can be unfair to different memcgs, i.e., their +lrugen->max_seq can be incremented at different paces. + +Link: https://lkml.kernel.org/r/20221222041905.2431096-5-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -136,7 +136,6 @@ struct scan_control { + + #ifdef CONFIG_LRU_GEN + /* help kswapd make better choices among multiple memcgs */ +- unsigned int memcgs_need_aging:1; + unsigned long last_reclaimed; + #endif + +@@ -4457,7 +4456,7 @@ done: + return true; + } + +-static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, ++static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, + struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) + { + int gen, type, zone; +@@ -4466,6 +4465,13 @@ static bool should_run_aging(struct lruv + unsigned long total = 0; + struct lru_gen_folio *lrugen = &lruvec->lrugen; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); ++ DEFINE_MIN_SEQ(lruvec); ++ ++ /* whether this lruvec is completely out of cold folios */ ++ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { ++ *nr_to_scan = 0; ++ return true; ++ } + + for (type = !can_swap; type < ANON_AND_FILE; type++) { + unsigned long seq; +@@ -4494,8 +4500,6 @@ static bool should_run_aging(struct lruv + * stalls when the number of generations reaches MIN_NR_GENS. Hence, the + * ideal number of generations is MIN_NR_GENS+1. + */ +- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) +- return true; + if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) + return false; + +@@ -4514,40 +4518,54 @@ static bool should_run_aging(struct lruv + return false; + } + +-static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned long min_ttl) ++static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) + { +- bool need_aging; +- unsigned long nr_to_scan; +- int swappiness = get_swappiness(lruvec, sc); ++ int gen, type, zone; ++ unsigned long total = 0; ++ bool can_swap = get_swappiness(lruvec, sc); ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + +- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); ++ for (type = !can_swap; type < ANON_AND_FILE; type++) { ++ unsigned long seq; + +- mem_cgroup_calculate_protection(NULL, memcg); ++ for (seq = min_seq[type]; seq <= max_seq; seq++) { ++ gen = lru_gen_from_seq(seq); + +- if (mem_cgroup_below_min(memcg)) +- return false; ++ for (zone = 0; zone < MAX_NR_ZONES; zone++) ++ total += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); ++ } ++ } + +- need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); ++ /* whether the size is big enough to be helpful */ ++ return mem_cgroup_online(memcg) ? (total >> sc->priority) : total; ++} + +- if (min_ttl) { +- int gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); +- unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); ++static bool lruvec_is_reclaimable(struct lruvec *lruvec, struct scan_control *sc, ++ unsigned long min_ttl) ++{ ++ int gen; ++ unsigned long birth; ++ struct mem_cgroup *memcg = lruvec_memcg(lruvec); ++ DEFINE_MIN_SEQ(lruvec); + +- if (time_is_after_jiffies(birth + min_ttl)) +- return false; ++ VM_WARN_ON_ONCE(sc->memcg_low_reclaim); + +- /* the size is likely too small to be helpful */ +- if (!nr_to_scan && sc->priority != DEF_PRIORITY) +- return false; +- } ++ /* see the comment on lru_gen_folio */ ++ gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); ++ birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); + +- if (need_aging) +- try_to_inc_max_seq(lruvec, max_seq, sc, swappiness, false); ++ if (time_is_after_jiffies(birth + min_ttl)) ++ return false; + +- return true; ++ if (!lruvec_is_sizable(lruvec, sc)) ++ return false; ++ ++ mem_cgroup_calculate_protection(NULL, memcg); ++ ++ return !mem_cgroup_below_min(memcg); + } + + /* to protect the working set of the last N jiffies */ +@@ -4556,46 +4574,32 @@ static unsigned long lru_gen_min_ttl __r + static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) + { + struct mem_cgroup *memcg; +- bool success = false; + unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); + + VM_WARN_ON_ONCE(!current_is_kswapd()); + + sc->last_reclaimed = sc->nr_reclaimed; + +- /* +- * To reduce the chance of going into the aging path, which can be +- * costly, optimistically skip it if the flag below was cleared in the +- * eviction path. This improves the overall performance when multiple +- * memcgs are available. +- */ +- if (!sc->memcgs_need_aging) { +- sc->memcgs_need_aging = true; ++ /* check the order to exclude compaction-induced reclaim */ ++ if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) + return; +- } +- +- set_mm_walk(pgdat); + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); + +- if (age_lruvec(lruvec, sc, min_ttl)) +- success = true; ++ if (lruvec_is_reclaimable(lruvec, sc, min_ttl)) { ++ mem_cgroup_iter_break(NULL, memcg); ++ return; ++ } + + cond_resched(); + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); + +- clear_mm_walk(); +- +- /* check the order to exclude compaction-induced reclaim */ +- if (success || !min_ttl || sc->order) +- return; +- + /* + * The main goal is to OOM kill if every generation from all memcgs is + * younger than min_ttl. However, another possibility is all memcgs are +- * either below min or empty. ++ * either too small or below min. + */ + if (mutex_trylock(&oom_lock)) { + struct oom_control oc = { +@@ -5113,33 +5117,27 @@ retry: + * reclaim. + */ + static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, +- bool can_swap, bool *need_aging) ++ bool can_swap) + { + unsigned long nr_to_scan; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); +- DEFINE_MIN_SEQ(lruvec); + + if (mem_cgroup_below_min(memcg) || + (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) + return 0; + +- *need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); +- if (!*need_aging) ++ if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) + return nr_to_scan; + + /* skip the aging path at the default priority */ + if (sc->priority == DEF_PRIORITY) +- goto done; ++ return nr_to_scan; + +- /* leave the work to lru_gen_age_node() */ +- if (current_is_kswapd()) +- return 0; ++ try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); + +- if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false)) +- return nr_to_scan; +-done: +- return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; ++ /* skip this lruvec as it's low on cold folios */ ++ return 0; + } + + static unsigned long get_nr_to_reclaim(struct scan_control *sc) +@@ -5158,9 +5156,7 @@ static unsigned long get_nr_to_reclaim(s + static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + { + struct blk_plug plug; +- bool need_aging = false; + unsigned long scanned = 0; +- unsigned long reclaimed = sc->nr_reclaimed; + unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); + + lru_add_drain(); +@@ -5181,13 +5177,13 @@ static void lru_gen_shrink_lruvec(struct + else + swappiness = 0; + +- nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness, &need_aging); ++ nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); + if (!nr_to_scan) +- goto done; ++ break; + + delta = evict_folios(lruvec, sc, swappiness); + if (!delta) +- goto done; ++ break; + + scanned += delta; + if (scanned >= nr_to_scan) +@@ -5199,10 +5195,6 @@ static void lru_gen_shrink_lruvec(struct + cond_resched(); + } + +- /* see the comment in lru_gen_age_node() */ +- if (sc->nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging) +- sc->memcgs_need_aging = false; +-done: + clear_mm_walk(); + + blk_finish_plug(&plug); diff --git a/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch b/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch new file mode 100644 index 0000000000..42caab7c37 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch @@ -0,0 +1,166 @@ +From eca3858631e0cbad2ca6e40f788892749428e4cb Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:03 -0700 +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 +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4456,68 +4456,6 @@ done: + return true; + } + +-static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, +- struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) +-{ +- int gen, type, zone; +- unsigned long old = 0; +- unsigned long young = 0; +- unsigned long total = 0; +- struct lru_gen_folio *lrugen = &lruvec->lrugen; +- struct mem_cgroup *memcg = lruvec_memcg(lruvec); +- DEFINE_MIN_SEQ(lruvec); +- +- /* whether this lruvec is completely out of cold folios */ +- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { +- *nr_to_scan = 0; +- return true; +- } +- +- for (type = !can_swap; type < ANON_AND_FILE; type++) { +- unsigned long seq; +- +- for (seq = min_seq[type]; seq <= max_seq; seq++) { +- unsigned long size = 0; +- +- gen = lru_gen_from_seq(seq); +- +- for (zone = 0; zone < MAX_NR_ZONES; zone++) +- size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); +- +- total += size; +- if (seq == max_seq) +- young += size; +- else if (seq + MIN_NR_GENS == max_seq) +- old += size; +- } +- } +- +- /* try to scrape all its memory if this memcg was deleted */ +- *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; +- +- /* +- * The aging tries to be lazy to reduce the overhead, while the eviction +- * stalls when the number of generations reaches MIN_NR_GENS. Hence, the +- * ideal number of generations is MIN_NR_GENS+1. +- */ +- if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) +- return false; +- +- /* +- * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) +- * of the total number of pages for each generation. A reasonable range +- * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The +- * aging cares about the upper bound of hot pages, while the eviction +- * cares about the lower bound of cold pages. +- */ +- if (young * MIN_NR_GENS > total) +- return true; +- if (old * (MIN_NR_GENS + 2) < total) +- return true; +- +- return false; +-} +- + static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) + { + int gen, type, zone; +@@ -5111,6 +5049,68 @@ retry: + return scanned; + } + ++static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, ++ struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) ++{ ++ int gen, type, zone; ++ unsigned long old = 0; ++ unsigned long young = 0; ++ unsigned long total = 0; ++ struct lru_gen_folio *lrugen = &lruvec->lrugen; ++ struct mem_cgroup *memcg = lruvec_memcg(lruvec); ++ DEFINE_MIN_SEQ(lruvec); ++ ++ /* whether this lruvec is completely out of cold folios */ ++ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { ++ *nr_to_scan = 0; ++ return true; ++ } ++ ++ for (type = !can_swap; type < ANON_AND_FILE; type++) { ++ unsigned long seq; ++ ++ for (seq = min_seq[type]; seq <= max_seq; seq++) { ++ unsigned long size = 0; ++ ++ gen = lru_gen_from_seq(seq); ++ ++ for (zone = 0; zone < MAX_NR_ZONES; zone++) ++ size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); ++ ++ total += size; ++ if (seq == max_seq) ++ young += size; ++ else if (seq + MIN_NR_GENS == max_seq) ++ old += size; ++ } ++ } ++ ++ /* try to scrape all its memory if this memcg was deleted */ ++ *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; ++ ++ /* ++ * The aging tries to be lazy to reduce the overhead, while the eviction ++ * stalls when the number of generations reaches MIN_NR_GENS. Hence, the ++ * ideal number of generations is MIN_NR_GENS+1. ++ */ ++ if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) ++ return false; ++ ++ /* ++ * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) ++ * of the total number of pages for each generation. A reasonable range ++ * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The ++ * aging cares about the upper bound of hot pages, while the eviction ++ * cares about the lower bound of cold pages. ++ */ ++ if (young * MIN_NR_GENS > total) ++ return true; ++ if (old * (MIN_NR_GENS + 2) < total) ++ return true; ++ ++ return false; ++} ++ + /* + * For future optimizations: + * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg diff --git a/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch b/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch new file mode 100644 index 0000000000..99ec42fe48 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch @@ -0,0 +1,876 @@ +From 8ee8571e47aa75221e5fbd4c9c7802fc4244c346 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:04 -0700 +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 +multiple bins to improve scalability. For each bin, an RCU hlist_nulls +is virtually divided into three segments: the head, the tail and the +default. + +An onlining memcg is added to the tail of a random bin in the old +generation. The eviction starts at the head of a random bin in the old +generation. The per-node memcg generation counter, whose reminder (mod +2) indexes the old generation, is incremented when all its bins become +empty. + +There are four operations: +1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in + its current generation (old or young) and updates its "seg" to + "head"; +2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in + its current generation (old or young) and updates its "seg" to + "tail"; +3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in + the old generation, updates its "gen" to "old" and resets its "seg" + to "default"; +4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin + in the young generation, updates its "gen" to "young" and resets + its "seg" to "default". + +The events that trigger the above operations are: +1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; +2. The first attempt to reclaim an memcg below low, which triggers + MEMCG_LRU_TAIL; +3. The first attempt to reclaim an memcg below reclaimable size + threshold, which triggers MEMCG_LRU_TAIL; +4. The second attempt to reclaim an memcg below reclaimable size + threshold, which triggers MEMCG_LRU_YOUNG; +5. Attempting to reclaim an memcg below min, which triggers + MEMCG_LRU_YOUNG; +6. Finishing the aging on the eviction path, which triggers + MEMCG_LRU_YOUNG; +7. Offlining an memcg, which triggers MEMCG_LRU_OLD. + +Note that memcg LRU only applies to global reclaim, and the +round-robin incrementing of their max_seq counters ensures the +eventual fairness to all eligible memcgs. For memcg reclaim, it still +relies on mem_cgroup_iter(). + +Link: https://lkml.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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/page_alloc.c | 1 + + mm/vmscan.c | 374 +++++++++++++++++++++++++++++++++---- + 6 files changed, 500 insertions(+), 35 deletions(-) + +--- a/include/linux/memcontrol.h ++++ b/include/linux/memcontrol.h +@@ -795,6 +795,11 @@ static inline void obj_cgroup_put(struct + percpu_ref_put(&objcg->refcnt); + } + ++static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) ++{ ++ return !memcg || css_tryget(&memcg->css); ++} ++ + static inline void mem_cgroup_put(struct mem_cgroup *memcg) + { + if (memcg) +@@ -1295,6 +1300,11 @@ static inline void obj_cgroup_put(struct + { + } + ++static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) ++{ ++ return true; ++} ++ + static inline void mem_cgroup_put(struct mem_cgroup *memcg) + { + } +--- a/include/linux/mm_inline.h ++++ b/include/linux/mm_inline.h +@@ -122,6 +122,18 @@ 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; +@@ -302,6 +314,11 @@ 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; +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -367,6 +368,15 @@ 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 { +@@ -426,6 +436,14 @@ struct lru_gen_folio { + atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; + /* whether the multi-gen LRU is enabled */ + bool enabled; ++#ifdef CONFIG_MEMCG ++ /* the memcg generation this lru_gen_folio belongs to */ ++ u8 gen; ++ /* the list segment this lru_gen_folio belongs to */ ++ u8 seg; ++ /* per-node lru_gen_folio list for global reclaim */ ++ struct hlist_nulls_node list; ++#endif + }; + + enum { +@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec * + void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); + + #ifdef CONFIG_MEMCG ++ ++/* ++ * For each node, memcgs are divided into two generations: the old and the ++ * young. For each generation, memcgs are randomly sharded into multiple bins ++ * to improve scalability. For each bin, the hlist_nulls is virtually divided ++ * into three segments: the head, the tail and the default. ++ * ++ * An onlining memcg is added to the tail of a random bin in the old generation. ++ * The eviction starts at the head of a random bin in the old generation. The ++ * per-node memcg generation counter, whose reminder (mod MEMCG_NR_GENS) indexes ++ * the old generation, is incremented when all its bins become empty. ++ * ++ * There are four operations: ++ * 1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in its ++ * current generation (old or young) and updates its "seg" to "head"; ++ * 2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in its ++ * current generation (old or young) and updates its "seg" to "tail"; ++ * 3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in the old ++ * generation, updates its "gen" to "old" and resets its "seg" to "default"; ++ * 4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin in the ++ * young generation, updates its "gen" to "young" and resets its "seg" to ++ * "default". ++ * ++ * The events that trigger the above operations are: ++ * 1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; ++ * 2. The first attempt to reclaim an memcg below low, which triggers ++ * MEMCG_LRU_TAIL; ++ * 3. The first attempt to reclaim an memcg below reclaimable size threshold, ++ * which triggers MEMCG_LRU_TAIL; ++ * 4. The second attempt to reclaim an memcg below reclaimable size threshold, ++ * which triggers MEMCG_LRU_YOUNG; ++ * 5. Attempting to reclaim an memcg below min, which triggers MEMCG_LRU_YOUNG; ++ * 6. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG; ++ * 7. Offlining an memcg, which triggers MEMCG_LRU_OLD. ++ * ++ * Note that memcg LRU only applies to global reclaim, and the round-robin ++ * incrementing of their max_seq counters ensures the eventual fairness to all ++ * eligible memcgs. For memcg reclaim, it still relies on mem_cgroup_iter(). ++ */ ++#define MEMCG_NR_GENS 2 ++#define MEMCG_NR_BINS 8 ++ ++struct lru_gen_memcg { ++ /* the per-node memcg generation counter */ ++ unsigned long seq; ++ /* each memcg has one lru_gen_folio per node */ ++ unsigned long nr_memcgs[MEMCG_NR_GENS]; ++ /* per-node lru_gen_folio list for global reclaim */ ++ struct hlist_nulls_head fifo[MEMCG_NR_GENS][MEMCG_NR_BINS]; ++ /* protects the above */ ++ spinlock_t lock; ++}; ++ ++void lru_gen_init_pgdat(struct pglist_data *pgdat); ++ + void lru_gen_init_memcg(struct mem_cgroup *memcg); + void lru_gen_exit_memcg(struct mem_cgroup *memcg); +-#endif ++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); ++ ++#else /* !CONFIG_MEMCG */ ++ ++#define MEMCG_NR_GENS 1 ++ ++struct lru_gen_memcg { ++}; ++ ++static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) ++{ ++} ++ ++#endif /* CONFIG_MEMCG */ + + #else /* !CONFIG_LRU_GEN */ + ++static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) ++{ ++} ++ + static inline void lru_gen_init_lruvec(struct lruvec *lruvec) + { + } +@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(s + } + + #ifdef CONFIG_MEMCG ++ + static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) + { + } +@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(st + static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) + { + } +-#endif ++ ++static inline void lru_gen_online_memcg(struct mem_cgroup *memcg) ++{ ++} ++ ++static inline void lru_gen_offline_memcg(struct mem_cgroup *memcg) ++{ ++} ++ ++static inline void lru_gen_release_memcg(struct mem_cgroup *memcg) ++{ ++} ++ ++static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) ++{ ++} ++ ++#endif /* CONFIG_MEMCG */ + + #endif /* CONFIG_LRU_GEN */ + +@@ -1219,6 +1330,8 @@ typedef struct pglist_data { + #ifdef CONFIG_LRU_GEN + /* kswap mm walk data */ + struct lru_gen_mm_walk mm_walk; ++ /* lru_gen_folio list */ ++ struct lru_gen_memcg memcg_lru; + #endif + + CACHELINE_PADDING(_pad2_); +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struc + struct mem_cgroup_per_node *mz; + 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); ++ ++ return; ++ } ++ + mctz = soft_limit_tree.rb_tree_per_node[nid]; + if (!mctz) + return; +@@ -3524,6 +3534,9 @@ unsigned long mem_cgroup_soft_limit_recl + struct mem_cgroup_tree_per_node *mctz; + unsigned long excess; + ++ if (lru_gen_enabled()) ++ return 0; ++ + if (order > 0) + return 0; + +@@ -5387,6 +5400,7 @@ static int mem_cgroup_css_online(struct + if (unlikely(mem_cgroup_is_root(memcg))) + queue_delayed_work(system_unbound_wq, &stats_flush_dwork, + 2UL*HZ); ++ lru_gen_online_memcg(memcg); + return 0; + offline_kmem: + memcg_offline_kmem(memcg); +@@ -5418,6 +5432,7 @@ static void mem_cgroup_css_offline(struc + memcg_offline_kmem(memcg); + reparent_shrinker_deferred(memcg); + wb_memcg_offline(memcg); ++ lru_gen_offline_memcg(memcg); + + drain_all_stock(memcg); + +@@ -5429,6 +5444,7 @@ static void mem_cgroup_css_released(stru + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + + invalidate_reclaim_iterators(memcg); ++ lru_gen_release_memcg(memcg); + } + + static void mem_cgroup_css_free(struct cgroup_subsys_state *css) +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7943,6 +7943,7 @@ static void __init free_area_init_node(i + pgdat_set_deferred_range(pgdat); + + free_area_init_core(pgdat); ++ lru_gen_init_pgdat(pgdat); + } + + static void __init free_area_init_memoryless_node(int nid) +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -54,6 +54,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -134,11 +136,6 @@ struct scan_control { + /* Always discard instead of demoting to lower tier memory */ + unsigned int no_demotion:1; + +-#ifdef CONFIG_LRU_GEN +- /* help kswapd make better choices among multiple memcgs */ +- unsigned long last_reclaimed; +-#endif +- + /* Allocation order */ + s8 order; + +@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_ca + for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ + for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) + ++#define get_memcg_gen(seq) ((seq) % MEMCG_NR_GENS) ++#define get_memcg_bin(bin) ((bin) % MEMCG_NR_BINS) ++ + static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) + { + struct pglist_data *pgdat = NODE_DATA(nid); +@@ -4442,8 +4442,7 @@ done: + if (sc->priority <= DEF_PRIORITY - 2) + wait_event_killable(lruvec->mm_state.wait, + max_seq < READ_ONCE(lrugen->max_seq)); +- +- return max_seq < READ_ONCE(lrugen->max_seq); ++ return false; + } + + VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); +@@ -4516,8 +4515,6 @@ static void lru_gen_age_node(struct pgli + + VM_WARN_ON_ONCE(!current_is_kswapd()); + +- sc->last_reclaimed = sc->nr_reclaimed; +- + /* check the order to exclude compaction-induced reclaim */ + if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) + return; +@@ -5116,8 +5113,7 @@ static bool should_run_aging(struct lruv + * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg + * reclaim. + */ +-static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, +- bool can_swap) ++static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool can_swap) + { + unsigned long nr_to_scan; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); +@@ -5134,10 +5130,8 @@ static unsigned long get_nr_to_scan(stru + if (sc->priority == DEF_PRIORITY) + return nr_to_scan; + +- try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); +- + /* skip this lruvec as it's low on cold folios */ +- return 0; ++ return try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false) ? -1 : 0; + } + + static unsigned long get_nr_to_reclaim(struct scan_control *sc) +@@ -5146,29 +5140,18 @@ static unsigned long get_nr_to_reclaim(s + if (!global_reclaim(sc)) + return -1; + +- /* discount the previous progress for kswapd */ +- if (current_is_kswapd()) +- return sc->nr_to_reclaim + sc->last_reclaimed; +- + return max(sc->nr_to_reclaim, compact_gap(sc->order)); + } + +-static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) ++static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + { +- struct blk_plug plug; ++ long nr_to_scan; + unsigned long scanned = 0; + unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); + +- lru_add_drain(); +- +- blk_start_plug(&plug); +- +- set_mm_walk(lruvec_pgdat(lruvec)); +- + while (true) { + int delta; + int swappiness; +- unsigned long nr_to_scan; + + if (sc->may_swap) + swappiness = get_swappiness(lruvec, sc); +@@ -5178,7 +5161,7 @@ static void lru_gen_shrink_lruvec(struct + swappiness = 0; + + nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); +- if (!nr_to_scan) ++ if (nr_to_scan <= 0) + break; + + delta = evict_folios(lruvec, sc, swappiness); +@@ -5195,10 +5178,251 @@ static void lru_gen_shrink_lruvec(struct + cond_resched(); + } + ++ /* whether try_to_inc_max_seq() was successful */ ++ return nr_to_scan < 0; ++} ++ ++static int shrink_one(struct lruvec *lruvec, struct scan_control *sc) ++{ ++ bool success; ++ unsigned long scanned = sc->nr_scanned; ++ unsigned long reclaimed = sc->nr_reclaimed; ++ int seg = lru_gen_memcg_seg(lruvec); ++ struct mem_cgroup *memcg = lruvec_memcg(lruvec); ++ struct pglist_data *pgdat = lruvec_pgdat(lruvec); ++ ++ /* see the comment on MEMCG_NR_GENS */ ++ if (!lruvec_is_sizable(lruvec, sc)) ++ return seg != MEMCG_LRU_TAIL ? MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG; ++ ++ mem_cgroup_calculate_protection(NULL, memcg); ++ ++ if (mem_cgroup_below_min(memcg)) ++ return MEMCG_LRU_YOUNG; ++ ++ if (mem_cgroup_below_low(memcg)) { ++ /* see the comment on MEMCG_NR_GENS */ ++ if (seg != MEMCG_LRU_TAIL) ++ return MEMCG_LRU_TAIL; ++ ++ memcg_memory_event(memcg, MEMCG_LOW); ++ } ++ ++ success = try_to_shrink_lruvec(lruvec, sc); ++ ++ shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); ++ ++ 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; ++ ++ return success ? MEMCG_LRU_YOUNG : 0; ++} ++ ++#ifdef CONFIG_MEMCG ++ ++static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++ int gen; ++ int bin; ++ int first_bin; ++ struct lruvec *lruvec; ++ struct lru_gen_folio *lrugen; ++ const struct hlist_nulls_node *pos; ++ int op = 0; ++ struct mem_cgroup *memcg = NULL; ++ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); ++ ++ bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); ++restart: ++ gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); ++ ++ rcu_read_lock(); ++ ++ hlist_nulls_for_each_entry_rcu(lrugen, pos, &pgdat->memcg_lru.fifo[gen][bin], list) { ++ if (op) ++ lru_gen_rotate_memcg(lruvec, op); ++ ++ mem_cgroup_put(memcg); ++ ++ lruvec = container_of(lrugen, struct lruvec, lrugen); ++ memcg = lruvec_memcg(lruvec); ++ ++ if (!mem_cgroup_tryget(memcg)) { ++ op = 0; ++ memcg = NULL; ++ continue; ++ } ++ ++ rcu_read_unlock(); ++ ++ op = shrink_one(lruvec, sc); ++ ++ if (sc->nr_reclaimed >= nr_to_reclaim) ++ goto success; ++ ++ rcu_read_lock(); ++ } ++ ++ rcu_read_unlock(); ++ ++ /* restart if raced with lru_gen_rotate_memcg() */ ++ if (gen != get_nulls_value(pos)) ++ goto restart; ++ ++ /* try the rest of the bins of the current generation */ ++ bin = get_memcg_bin(bin + 1); ++ if (bin != first_bin) ++ goto restart; ++success: ++ if (op) ++ lru_gen_rotate_memcg(lruvec, op); ++ ++ mem_cgroup_put(memcg); ++} ++ ++static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) ++{ ++ struct blk_plug plug; ++ ++ VM_WARN_ON_ONCE(global_reclaim(sc)); ++ ++ lru_add_drain(); ++ ++ blk_start_plug(&plug); ++ ++ set_mm_walk(lruvec_pgdat(lruvec)); ++ ++ if (try_to_shrink_lruvec(lruvec, sc)) ++ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); ++ ++ clear_mm_walk(); ++ ++ blk_finish_plug(&plug); ++} ++ ++#else /* !CONFIG_MEMCG */ ++ ++static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++ BUILD_BUG(); ++} ++ ++static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) ++{ ++ BUILD_BUG(); ++} ++ ++#endif ++ ++static void set_initial_priority(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++ int priority; ++ unsigned long reclaimable; ++ struct lruvec *lruvec = mem_cgroup_lruvec(NULL, pgdat); ++ ++ if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH) ++ return; ++ /* ++ * Determine the initial priority based on ((total / MEMCG_NR_GENS) >> ++ * priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, where the ++ * estimated reclaimed_to_scanned_ratio = inactive / total. ++ */ ++ reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE); ++ if (get_swappiness(lruvec, sc)) ++ reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON); ++ ++ reclaimable /= MEMCG_NR_GENS; ++ ++ /* round down reclaimable and round up sc->nr_to_reclaim */ ++ priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1); ++ ++ sc->priority = clamp(priority, 0, DEF_PRIORITY); ++} ++ ++static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++ struct blk_plug plug; ++ unsigned long reclaimed = sc->nr_reclaimed; ++ ++ VM_WARN_ON_ONCE(!global_reclaim(sc)); ++ ++ lru_add_drain(); ++ ++ blk_start_plug(&plug); ++ ++ set_mm_walk(pgdat); ++ ++ set_initial_priority(pgdat, sc); ++ ++ if (current_is_kswapd()) ++ sc->nr_reclaimed = 0; ++ ++ if (mem_cgroup_disabled()) ++ shrink_one(&pgdat->__lruvec, sc); ++ else ++ shrink_many(pgdat, sc); ++ ++ if (current_is_kswapd()) ++ sc->nr_reclaimed += reclaimed; ++ + clear_mm_walk(); + + blk_finish_plug(&plug); ++ ++ /* kswapd should never fail */ ++ 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 +@@ -5656,11 +5880,11 @@ static int run_cmd(char cmd, int memcg_i + + if (!mem_cgroup_disabled()) { + rcu_read_lock(); ++ + memcg = mem_cgroup_from_id(memcg_id); +-#ifdef CONFIG_MEMCG +- if (memcg && !css_tryget(&memcg->css)) ++ if (!mem_cgroup_tryget(memcg)) + memcg = NULL; +-#endif ++ + rcu_read_unlock(); + + if (!memcg) +@@ -5808,6 +6032,19 @@ void lru_gen_init_lruvec(struct lruvec * + } + + #ifdef CONFIG_MEMCG ++ ++void lru_gen_init_pgdat(struct pglist_data *pgdat) ++{ ++ int i, j; ++ ++ spin_lock_init(&pgdat->memcg_lru.lock); ++ ++ for (i = 0; i < MEMCG_NR_GENS; i++) { ++ for (j = 0; j < MEMCG_NR_BINS; j++) ++ INIT_HLIST_NULLS_HEAD(&pgdat->memcg_lru.fifo[i][j], i); ++ } ++} ++ + void lru_gen_init_memcg(struct mem_cgroup *memcg) + { + INIT_LIST_HEAD(&memcg->mm_list.fifo); +@@ -5831,7 +6068,69 @@ void lru_gen_exit_memcg(struct mem_cgrou + } + } + } +-#endif ++ ++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) + { +@@ -5858,6 +6157,10 @@ static void lru_gen_shrink_lruvec(struct + { + } + ++static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++} ++ + #endif /* CONFIG_LRU_GEN */ + + static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) +@@ -5871,7 +6174,7 @@ static void shrink_lruvec(struct lruvec + bool proportional_reclaim; + struct blk_plug plug; + +- if (lru_gen_enabled()) { ++ if (lru_gen_enabled() && !global_reclaim(sc)) { + lru_gen_shrink_lruvec(lruvec, sc); + return; + } +@@ -6114,6 +6417,11 @@ static void shrink_node(pg_data_t *pgdat + struct lruvec *target_lruvec; + bool reclaimable = false; + ++ if (lru_gen_enabled() && global_reclaim(sc)) { ++ lru_gen_shrink_node(pgdat, sc); ++ return; ++ } ++ + target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat); + + again: diff --git a/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch b/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch new file mode 100644 index 0000000000..d60ddb9dcc --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch @@ -0,0 +1,202 @@ +From 11b14ee8cbbbebd8204609076a9327a1171cd253 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:05 -0700 +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 + supported as usual. +2. sc->proactive, which indicates reclaim by memory.reclaim, may not + opportunistically skip the aging path, since it is considered less + latency sensitive. +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_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. + +The rest are handled by the existing code. + +Link: https://lkml.kernel.org/r/20221222041905.2431096-8-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + ++ if (!sc->may_swap) ++ return 0; ++ + if (!can_demote(pgdat->node_id, sc) && + mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) + return 0; +@@ -4223,7 +4226,7 @@ static void walk_mm(struct lruvec *lruve + } while (err == -EAGAIN); + } + +-static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) ++static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat, bool force_alloc) + { + struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; + +@@ -4231,7 +4234,7 @@ static struct lru_gen_mm_walk *set_mm_wa + VM_WARN_ON_ONCE(walk); + + walk = &pgdat->mm_walk; +- } else if (!pgdat && !walk) { ++ } else if (!walk && force_alloc) { + VM_WARN_ON_ONCE(current_is_kswapd()); + + walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); +@@ -4419,7 +4422,7 @@ static bool try_to_inc_max_seq(struct lr + goto done; + } + +- walk = set_mm_walk(NULL); ++ walk = set_mm_walk(NULL, true); + if (!walk) { + success = iterate_mm_list_nowalk(lruvec, max_seq); + goto done; +@@ -4488,8 +4491,6 @@ static bool lruvec_is_reclaimable(struct + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MIN_SEQ(lruvec); + +- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); +- + /* see the comment on lru_gen_folio */ + gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); + birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); +@@ -4753,12 +4754,8 @@ static bool isolate_folio(struct lruvec + { + bool success; + +- /* unmapping inhibited */ +- if (!sc->may_unmap && folio_mapped(folio)) +- return false; +- + /* swapping inhibited */ +- if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && ++ if (!(sc->gfp_mask & __GFP_IO) && + (folio_test_dirty(folio) || + (folio_test_anon(folio) && !folio_test_swapcache(folio)))) + return false; +@@ -4857,9 +4854,8 @@ static int scan_folios(struct lruvec *lr + __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 folios due to reclaim_idx. Check the ++ * remaining to prevent livelock if it's not making progress. + */ + return isolated || !remaining ? scanned : 0; + } +@@ -5119,8 +5115,7 @@ static long get_nr_to_scan(struct lruvec + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + +- if (mem_cgroup_below_min(memcg) || +- (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) ++ if (mem_cgroup_below_min(memcg)) + return 0; + + if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) +@@ -5148,17 +5143,14 @@ static bool try_to_shrink_lruvec(struct + long nr_to_scan; + unsigned long scanned = 0; + unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); ++ int swappiness = get_swappiness(lruvec, sc); ++ ++ /* clean file folios are more likely to exist */ ++ if (swappiness && !(sc->gfp_mask & __GFP_IO)) ++ swappiness = 1; + + while (true) { + int delta; +- int swappiness; +- +- if (sc->may_swap) +- swappiness = get_swappiness(lruvec, sc); +- else if (!cgroup_reclaim(sc) && get_swappiness(lruvec, sc)) +- swappiness = 1; +- else +- swappiness = 0; + + nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); + if (nr_to_scan <= 0) +@@ -5289,12 +5281,13 @@ static void lru_gen_shrink_lruvec(struct + struct blk_plug plug; + + VM_WARN_ON_ONCE(global_reclaim(sc)); ++ VM_WARN_ON_ONCE(!sc->may_writepage || !sc->may_unmap); + + lru_add_drain(); + + blk_start_plug(&plug); + +- set_mm_walk(lruvec_pgdat(lruvec)); ++ set_mm_walk(NULL, sc->proactive); + + if (try_to_shrink_lruvec(lruvec, sc)) + lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); +@@ -5350,11 +5343,19 @@ static void lru_gen_shrink_node(struct p + + VM_WARN_ON_ONCE(!global_reclaim(sc)); + ++ /* ++ * 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. ++ */ ++ if (!sc->may_writepage || !sc->may_unmap) ++ goto done; ++ + lru_add_drain(); + + blk_start_plug(&plug); + +- set_mm_walk(pgdat); ++ set_mm_walk(pgdat, sc->proactive); + + set_initial_priority(pgdat, sc); + +@@ -5372,7 +5373,7 @@ static void lru_gen_shrink_node(struct p + clear_mm_walk(); + + blk_finish_plug(&plug); +- ++done: + /* kswapd should never fail */ + pgdat->kswapd_failures = 0; + } +@@ -5944,7 +5945,7 @@ static ssize_t lru_gen_seq_write(struct + set_task_reclaim_state(current, &sc.reclaim_state); + flags = memalloc_noreclaim_save(); + blk_start_plug(&plug); +- if (!set_mm_walk(NULL)) { ++ if (!set_mm_walk(NULL, true)) { + err = -ENOMEM; + goto done; + } diff --git a/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch b/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch new file mode 100644 index 0000000000..3cbc84f8b8 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch @@ -0,0 +1,38 @@ +From 25887d48dff860751a06caa4188bfaf6bfb6e4b2 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 21 Dec 2022 21:19:06 -0700 +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. + +Link: https://lkml.kernel.org/r/20221222041905.2431096-9-yuzhao@google.com +Signed-off-by: Yu Zhao +Cc: Johannes Weiner +Cc: Jonathan Corbet +Cc: Michael Larabel +Cc: Michal Hocko +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4417,7 +4417,7 @@ static bool try_to_inc_max_seq(struct lr + * handful of PTEs. Spreading the work out over a period of time usually + * is less efficient, but it avoids bursty page faults. + */ +- if (!force_scan && !(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { ++ if (!arch_has_hw_pte_young() || !get_cap(LRU_GEN_MM_WALK)) { + success = iterate_mm_list_nowalk(lruvec, max_seq); + goto done; + } diff --git a/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch b/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch new file mode 100644 index 0000000000..c1ad1c538e --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch @@ -0,0 +1,92 @@ +From 620b0ee94455e48d124414cd06d8a53f69fb6453 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Mon, 13 Feb 2023 00:53:22 -0700 +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. +Each generation is also sharded into multiple bins to improve scalability. +A reclaimer starts with a random bin (in the old generation) and, if it +fails, it will retry, i.e., to try the rest of the bins. + +If a reclaimer fails with the last memcg, it should move this memcg to the +young generation first, which causes the generations to alternate, and +then retry. Otherwise, the retries will be futile because all other bins +are empty. + +Link: https://lkml.kernel.org/r/20230213075322.1416966-1-yuzhao@google.com +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -5218,18 +5218,20 @@ static int shrink_one(struct lruvec *lru + + static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) + { ++ int op; + int gen; + int bin; + int first_bin; + struct lruvec *lruvec; + struct lru_gen_folio *lrugen; ++ struct mem_cgroup *memcg; + const struct hlist_nulls_node *pos; +- int op = 0; +- struct mem_cgroup *memcg = NULL; + unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); + + 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(); +@@ -5253,14 +5255,22 @@ restart: + + op = shrink_one(lruvec, sc); + +- if (sc->nr_reclaimed >= nr_to_reclaim) +- goto success; +- + rcu_read_lock(); ++ ++ if (sc->nr_reclaimed >= nr_to_reclaim) ++ break; + } + + rcu_read_unlock(); + ++ if (op) ++ lru_gen_rotate_memcg(lruvec, op); ++ ++ mem_cgroup_put(memcg); ++ ++ if (sc->nr_reclaimed >= nr_to_reclaim) ++ return; ++ + /* restart if raced with lru_gen_rotate_memcg() */ + if (gen != get_nulls_value(pos)) + goto restart; +@@ -5269,11 +5279,6 @@ restart: + bin = get_memcg_bin(bin + 1); + if (bin != first_bin) + goto restart; +-success: +- if (op) +- lru_gen_rotate_memcg(lruvec, op); +- +- mem_cgroup_put(memcg); + } + + static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) diff --git a/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch b/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch new file mode 100644 index 0000000000..67fe4f96ec --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch @@ -0,0 +1,191 @@ +From 70d216c71ff5c5b17dd1da6294f97b91fb6aba7a Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Fri, 30 Dec 2022 14:52:51 -0700 +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. + +This function returns false for VMAs marked by VM_SEQ_READ or +VM_RAND_READ. While the former flag indicates linear access, i.e., a +special case of spatial locality, both flags indicate a lack of temporal +locality, i.e., the reuse of an area within a relatively small duration. + +"Recency" is chosen over "locality" to avoid confusion between temporal +and spatial localities. + +Before this patch, the active/inactive LRU only ignored the accessed bit +from VMAs marked by VM_SEQ_READ. After this patch, the active/inactive +LRU and MGLRU share the same logic: they both ignore the accessed bit if +vma_has_recency() returns false. + +For the active/inactive LRU, the following fio test showed a [6, 8]% +increase in IOPS when randomly accessing mapped files under memory +pressure. + + kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) + kb=$((kb - 8*1024*1024)) + + modprobe brd rd_nr=1 rd_size=$kb + dd if=/dev/zero of=/dev/ram0 bs=1M + + mkfs.ext4 /dev/ram0 + mount /dev/ram0 /mnt/ + swapoff -a + + fio --name=test --directory=/mnt/ --ioengine=mmap --numjobs=8 \ + --size=8G --rw=randrw --time_based --runtime=10m \ + --group_reporting + +The discussion that led to this patch is here [1]. Additional test +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 | 8 ++++++++ + mm/memory.c | 7 +++---- + mm/rmap.c | 42 +++++++++++++++++---------------------- + mm/vmscan.c | 5 ++++- + 4 files changed, 33 insertions(+), 29 deletions(-) + +--- a/include/linux/mm_inline.h ++++ b/include/linux/mm_inline.h +@@ -600,4 +600,12 @@ pte_install_uffd_wp_if_needed(struct vm_ + #endif + } + ++static inline bool vma_has_recency(struct vm_area_struct *vma) ++{ ++ if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) ++ return false; ++ ++ return true; ++} ++ + #endif +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1445,8 +1445,7 @@ again: + force_flush = 1; + set_page_dirty(page); + } +- if (pte_young(ptent) && +- likely(!(vma->vm_flags & VM_SEQ_READ))) ++ if (pte_young(ptent) && likely(vma_has_recency(vma))) + mark_page_accessed(page); + } + rss[mm_counter(page)]--; +@@ -5219,8 +5218,8 @@ static inline void mm_account_fault(stru + #ifdef CONFIG_LRU_GEN + static void lru_gen_enter_fault(struct vm_area_struct *vma) + { +- /* the LRU algorithm doesn't apply to sequential or random reads */ +- current->in_lru_fault = !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)); ++ /* the LRU algorithm only applies to accesses with recency */ ++ current->in_lru_fault = vma_has_recency(vma); + } + + static void lru_gen_exit_fault(void) +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct + } + + if (pvmw.pte) { +- if (lru_gen_enabled() && pte_young(*pvmw.pte) && +- !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))) { ++ if (lru_gen_enabled() && pte_young(*pvmw.pte)) { + lru_gen_look_around(&pvmw); + referenced++; + } + + if (ptep_clear_flush_young_notify(vma, address, +- pvmw.pte)) { +- /* +- * Don't treat a reference through +- * a sequentially read mapping as such. +- * If the 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 folio. +- */ +- if (likely(!(vma->vm_flags & VM_SEQ_READ))) +- referenced++; +- } ++ pvmw.pte)) ++ referenced++; + } 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 + 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 ++ * 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 folio in zap_pte_range(). ++ */ ++ if (!vma_has_recency(vma)) ++ return true; ++ ++ /* ++ * If we are reclaiming on behalf of a cgroup, skip counting on behalf ++ * of references from different cgroups. ++ */ ++ if (memcg && !mm_match_cgroup(vma->vm_mm, memcg)) + return true; + + return false; +@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio + .arg = (void *)&pra, + .anon_lock = folio_lock_anon_vma_read, + .try_lock = true, ++ .invalid_vma = invalid_folio_referenced_vma, + }; + + *vm_flags = 0; +@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio + return 1; + } + +- /* +- * If we are reclaiming on behalf of a cgroup, skip +- * counting on behalf of references from different +- * cgroups +- */ +- if (memcg) { +- rwc.invalid_vma = invalid_folio_referenced_vma; +- } +- + rmap_walk(folio, &rwc); + *vm_flags = pra.vm_flags; + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3778,7 +3778,10 @@ static int should_skip_vma(unsigned long + if (is_vm_hugetlb_page(vma)) + return true; + +- if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_SEQ_READ | VM_RAND_READ)) ++ if (!vma_has_recency(vma)) ++ return true; ++ ++ if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) + return true; + + if (vma == get_gate_vma(vma->vm_mm)) diff --git a/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch b/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch new file mode 100644 index 0000000000..f9c39be920 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch @@ -0,0 +1,129 @@ +From 9ca4e437a24dfc4ec6c362f319eb9850b9eca497 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Fri, 30 Dec 2022 14:52:52 -0700 +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. + +The advantages of POSIX_FADV_NOREUSE are: +1. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not alter the + default readahead behavior. +2. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not split VMAs and + therefore does not take mmap_lock. +3. Unlike MADV_COLD, setting it has a negligible cost, regardless of + how many pages it affects. + +Its limitations are: +1. Like POSIX_FADV_RANDOM and POSIX_FADV_SEQUENTIAL, it currently does + not support range. IOW, its scope is the entire file. +2. It currently does not ignore access through file descriptors. + Specifically, for the active/inactive LRU, given a file page shared + 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 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]. +This time the goal is to fill a niche: a few desktop applications, e.g., +large file transferring and video encoding/decoding, want fast file +streaming with mmap() rather than direct IO. Among those applications, an +SVT-AV1 regression was reported when running with MGLRU [2]. The +following test can reproduce that regression. + + kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) + kb=$((kb - 8*1024*1024)) + + modprobe brd rd_nr=1 rd_size=$kb + dd if=/dev/zero of=/dev/ram0 bs=1M + + mkfs.ext4 /dev/ram0 + mount /dev/ram0 /mnt/ + swapoff -a + + fallocate -l 8G /mnt/swapfile + mkswap /mnt/swapfile + swapon /mnt/swapfile + + wget http://ultravideo.cs.tut.fi/video/Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z + 7z e -o/mnt/ Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z + SvtAv1EncApp --preset 12 -w 3840 -h 2160 \ + -i /mnt/Bosphorus_3840x2160.y4m + +For MGLRU, the following change showed a [9-11]% increase in FPS, +which makes it on par with the active/inactive LRU. + + patch Source/App/EncApp/EbAppMain.c < #include + 35d35 + < #include /* _O_BINARY */ + 117a118 + > posix_fadvise(config->mmap.fd, 0, 0, POSIX_FADV_NOREUSE); + EOF + +[1] https://lore.kernel.org/r/1308923350-7932-1-git-send-email-andrea@betterlinux.com/ +[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(-) + +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb + /* File supports DIRECT IO */ + #define FMODE_CAN_ODIRECT ((__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) + +--- a/include/linux/mm_inline.h ++++ b/include/linux/mm_inline.h +@@ -605,6 +605,9 @@ static inline bool vma_has_recency(struc + if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) + return false; + ++ if (vma->vm_file && (vma->vm_file->f_mode & FMODE_NOREUSE)) ++ return false; ++ + return true; + } + +--- a/mm/fadvise.c ++++ b/mm/fadvise.c +@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, l + case POSIX_FADV_NORMAL: + file->f_ra.ra_pages = bdi->ra_pages; + spin_lock(&file->f_lock); +- file->f_mode &= ~FMODE_RANDOM; ++ file->f_mode &= ~(FMODE_RANDOM | FMODE_NOREUSE); + spin_unlock(&file->f_lock); + break; + case POSIX_FADV_RANDOM: +@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, l + force_page_cache_readahead(mapping, file, start_index, nrpages); + break; + case POSIX_FADV_NOREUSE: ++ spin_lock(&file->f_lock); ++ file->f_mode |= FMODE_NOREUSE; ++ spin_unlock(&file->f_lock); + break; + case POSIX_FADV_DONTNEED: + __filemap_fdatawrite_range(mapping, offset, endbyte, diff --git a/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch b/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch new file mode 100644 index 0000000000..bac2e3e344 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch @@ -0,0 +1,67 @@ +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(+) + +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -141,6 +141,21 @@ loop has detected outlying refaults from + 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: +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4461,6 +4461,10 @@ done: + return true; + } + ++/****************************************************************************** ++ * working set protection ++ ******************************************************************************/ ++ + static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) + { + int gen, type, zone; diff --git a/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch b/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch new file mode 100644 index 0000000000..c28a1c5d5b --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch @@ -0,0 +1,57 @@ +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(+) + +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -156,6 +156,20 @@ This time-based approach has the followi + 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: +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4555,6 +4555,10 @@ static void lru_gen_age_node(struct pgli + } + } + ++/****************************************************************************** ++ * 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 diff --git a/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch b/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch new file mode 100644 index 0000000000..a7dfb5ffe7 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch @@ -0,0 +1,243 @@ +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(-) + +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -170,6 +170,22 @@ promotes hot pages. If the scan was done + 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: +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3209,6 +3209,98 @@ static bool __maybe_unused seq_is_valid( + } + + /****************************************************************************** ++ * 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 + } + #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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch b/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch new file mode 100644 index 0000000000..101a0a3757 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch @@ -0,0 +1,427 @@ +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(-) + +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -186,9 +186,40 @@ is false positive, the cost is an additi + 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 +--- 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; +@@ -314,11 +302,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; +--- 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_cgrou + 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 + { + } + +-static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) ++static inline void lru_gen_soft_reclaim(struct lruvec *lruvec) + { + } + +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -478,12 +478,8 @@ static void mem_cgroup_update_tree(struc + 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; + } + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4692,6 +4692,148 @@ void lru_gen_look_around(struct page_vma + } + + /****************************************************************************** ++ * 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 + ******************************************************************************/ + +@@ -5398,53 +5540,6 @@ done: + 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 + ******************************************************************************/ +@@ -6090,67 +6185,6 @@ void lru_gen_exit_memcg(struct mem_cgrou + } + } + +-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) diff --git a/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch b/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch new file mode 100644 index 0000000000..1ee766f861 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch @@ -0,0 +1,40 @@ +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(+) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -6172,12 +6172,17 @@ void lru_gen_exit_memcg(struct mem_cgrou + 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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch b/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch new file mode 100644 index 0000000000..2273977dc9 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch @@ -0,0 +1,135 @@ +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3980,8 +3980,8 @@ restart: + } + + #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 + 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 + 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 @@ next: + 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, u + 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 @@ restart: + 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 @@ restart: + 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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch b/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch new file mode 100644 index 0000000000..856199574a --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch @@ -0,0 +1,148 @@ +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(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4573,13 +4573,12 @@ static void lru_gen_age_node(struct pgli + 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); +@@ -4596,25 +4595,28 @@ void lru_gen_look_around(struct page_vma + /* 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; + +@@ -4639,56 +4641,27 @@ void lru_gen_look_around(struct page_vma + !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(); + } + + /****************************************************************************** diff --git a/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch b/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch new file mode 100644 index 0000000000..1b0459cdb9 --- /dev/null +++ b/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch @@ -0,0 +1,273 @@ +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(-) + +--- 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 { +--- 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 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); + +@@ -3567,9 +3548,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; +@@ -4172,10 +4153,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; +@@ -4208,8 +4185,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; ++ + /* folio_update_gen() requires stable folio_memcg() */ + if (!mem_cgroup_trylock_pages(memcg)) + break; +@@ -4444,25 +4427,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; + } + + /****************************************************************************** +@@ -6117,7 +6087,6 @@ void lru_gen_init_lruvec(struct 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 +@@ -6150,7 +6119,6 @@ void lru_gen_exit_memcg(struct mem_cgrou + 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))); + diff --git a/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch b/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch new file mode 100644 index 0000000000..2e6d881fe9 --- /dev/null +++ b/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch @@ -0,0 +1,58 @@ +From e2192de59e457aef8d1f055a452131f0b3e5d097 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 18 Jan 2023 14:26:53 +0100 +Subject: [PATCH] bitfield: add FIELD_PREP_CONST() + +Neither FIELD_PREP() nor *_encode_bits() can be used +in constant contexts (such as initializers), but we +don't want to define shift constants for all masks +just for use in initializers, and having checks that +the values fit is also useful. + +Therefore, add FIELD_PREP_CONST() which is a smaller +version of FIELD_PREP() that can only take constant +arguments and has less friendly (but not less strict) +error checks, and expands to a constant value. + +Signed-off-by: Johannes Berg +Link: https://lore.kernel.org/r/20230118142652.53f20593504b.Iaeea0aee77a6493d70e573b4aa55c91c00e01e4b@changeid +Signed-off-by: Johannes Berg +--- + include/linux/bitfield.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/include/linux/bitfield.h ++++ b/include/linux/bitfield.h +@@ -115,6 +115,32 @@ + ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ + }) + ++#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) ++ ++/** ++ * FIELD_PREP_CONST() - prepare a constant bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to put in the field ++ * ++ * FIELD_PREP_CONST() masks and shifts up the value. The result should ++ * be combined with other fields of the bitfield using logical OR. ++ * ++ * Unlike FIELD_PREP() this is a constant expression and can therefore ++ * be used in initializers. Error checking is less comfortable for this ++ * version, and non-constant masks cannot be used. ++ */ ++#define FIELD_PREP_CONST(_mask, _val) \ ++ ( \ ++ /* mask must be non-zero */ \ ++ BUILD_BUG_ON_ZERO((_mask) == 0) + \ ++ /* check if value fits */ \ ++ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ ++ /* check if mask is contiguous */ \ ++ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \ ++ /* and create the value */ \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \ ++ ) ++ + /** + * FIELD_GET() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position diff --git a/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch b/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch new file mode 100644 index 0000000000..d8d0cf9555 --- /dev/null +++ b/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch @@ -0,0 +1,63 @@ +From 579aee9fc594af94c242068c011b0233563d4bbf Mon Sep 17 00:00:00 2001 +From: Stephen Rothwell +Date: Mon, 10 Oct 2022 16:57:21 +1100 +Subject: [PATCH] powerpc: suppress some linker warnings in recent linker + versions + +This is a follow on from commit + + 0d362be5b142 ("Makefile: link with -z noexecstack --no-warn-rwx-segments") + +for arch/powerpc/boot to address wanrings like: + + ld: warning: opal-calls.o: missing .note.GNU-stack section implies executable stack + ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker + ld: warning: arch/powerpc/boot/zImage.epapr has a LOAD segment with RWX permissions + +This fixes issue https://github.com/linuxppc/issues/issues/417 + +Signed-off-by: Stephen Rothwell +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221010165721.106267e6@canb.auug.org.au +--- + arch/powerpc/boot/wrapper | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/boot/wrapper ++++ b/arch/powerpc/boot/wrapper +@@ -215,6 +215,11 @@ ld_version() + }' + } + ++ld_is_lld() ++{ ++ ${CROSS}ld -V 2>&1 | grep -q LLD ++} ++ + # Do not include PT_INTERP segment when linking pie. Non-pie linking + # just ignores this option. + LD_VERSION=$(${CROSS}ld --version | ld_version) +@@ -223,6 +228,14 @@ if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VE + nodl="--no-dynamic-linker" + fi + ++# suppress some warnings in recent ld versions ++nowarn="-z noexecstack" ++if ! ld_is_lld; then ++ if [ "$LD_VERSION" -ge "$(echo 2.39 | ld_version)" ]; then ++ nowarn="$nowarn --no-warn-rwx-segments" ++ fi ++fi ++ + platformo=$object/"$platform".o + lds=$object/zImage.lds + ext=strip +@@ -504,7 +517,7 @@ if [ "$platform" != "miboot" ]; then + text_start="-Ttext $link_address" + fi + #link everything +- ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $rodynamic $notext -o "$ofile" $map \ ++ ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $nowarn $rodynamic $notext -o "$ofile" $map \ + $platformo $tmp $object/wrapper.a + rm $tmp + fi diff --git a/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch b/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch new file mode 100644 index 0000000000..eb6be5ed00 --- /dev/null +++ b/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch @@ -0,0 +1,65 @@ +From 63db0cb35e1cb3b3c134906d1062f65513fdda2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 4 Oct 2022 10:37:09 +0200 +Subject: [PATCH] mtd: core: simplify (a bit) code find partition-matching + dynamic OF node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Don't hardcode "partition-" string twice +2. Use simpler logic & use ->name to avoid of_property_read_string() +3. Use mtd_get_of_node() helper + +Cc: Christian Marangi +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-1-zajec5@gmail.com +--- + drivers/mtd/mtdcore.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -551,18 +551,16 @@ static void mtd_check_of_node(struct mtd + struct device_node *partitions, *parent_dn, *mtd_dn = NULL; + const char *pname, *prefix = "partition-"; + int plen, mtd_name_len, offset, prefix_len; +- struct mtd_info *parent; + bool found = false; + + /* Check if MTD already has a device node */ +- if (dev_of_node(&mtd->dev)) ++ if (mtd_get_of_node(mtd)) + return; + + /* Check if a partitions node exist */ + if (!mtd_is_partition(mtd)) + return; +- parent = mtd->parent; +- parent_dn = of_node_get(dev_of_node(&parent->dev)); ++ parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); + if (!parent_dn) + return; + +@@ -575,15 +573,15 @@ static void mtd_check_of_node(struct mtd + + /* Search if a partition is defined with the same name */ + for_each_child_of_node(partitions, mtd_dn) { +- offset = 0; +- + /* Skip partition with no/wrong prefix */ +- if (!of_node_name_prefix(mtd_dn, "partition-")) ++ if (!of_node_name_prefix(mtd_dn, prefix)) + continue; + + /* Label have priority. Check that first */ +- if (of_property_read_string(mtd_dn, "label", &pname)) { +- of_property_read_string(mtd_dn, "name", &pname); ++ if (!of_property_read_string(mtd_dn, "label", &pname)) { ++ offset = 0; ++ } else { ++ pname = mtd_dn->name; + offset = prefix_len; + } + diff --git a/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch b/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch new file mode 100644 index 0000000000..f8d3a370d4 --- /dev/null +++ b/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch @@ -0,0 +1,84 @@ +From ddb8cefb7af288950447ca6eeeafb09977dab56f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 4 Oct 2022 10:37:10 +0200 +Subject: [PATCH] mtd: core: try to find OF node for every MTD partition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So far this feature was limited to the top-level "nvmem-cells" node. +There are multiple parsers creating partitions and subpartitions +dynamically. Extend that code to handle them too. + +This allows finding partition-* node for every MTD (sub)partition. + +Random example: + +partitions { + compatible = "brcm,bcm947xx-cfe-partitions"; + + partition-firmware { + compatible = "brcm,trx"; + + partition-loader { + }; + }; +}; + +Cc: Christian Marangi +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-2-zajec5@gmail.com +--- + drivers/mtd/mtdcore.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -551,20 +551,22 @@ static void mtd_check_of_node(struct mtd + struct device_node *partitions, *parent_dn, *mtd_dn = NULL; + const char *pname, *prefix = "partition-"; + int plen, mtd_name_len, offset, prefix_len; +- bool found = false; + + /* Check if MTD already has a device node */ + if (mtd_get_of_node(mtd)) + return; + +- /* Check if a partitions node exist */ + if (!mtd_is_partition(mtd)) + return; ++ + parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); + if (!parent_dn) + return; + +- partitions = of_get_child_by_name(parent_dn, "partitions"); ++ if (mtd_is_partition(mtd->parent)) ++ partitions = of_node_get(parent_dn); ++ else ++ partitions = of_get_child_by_name(parent_dn, "partitions"); + if (!partitions) + goto exit_parent; + +@@ -588,19 +590,11 @@ static void mtd_check_of_node(struct mtd + plen = strlen(pname) - offset; + if (plen == mtd_name_len && + !strncmp(mtd->name, pname + offset, plen)) { +- found = true; ++ mtd_set_of_node(mtd, mtd_dn); + break; + } + } + +- if (!found) +- goto exit_partitions; +- +- /* Set of_node only for nvmem */ +- if (of_device_is_compatible(mtd_dn, "nvmem-cells")) +- mtd_set_of_node(mtd, mtd_dn); +- +-exit_partitions: + of_node_put(partitions); + exit_parent: + of_node_put(parent_dn); diff --git a/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch b/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch new file mode 100644 index 0000000000..5a5e11c8f7 --- /dev/null +++ b/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch @@ -0,0 +1,47 @@ +From 26422ac78e9d8767bd4aabfbae616b15edbf6a1b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 22 Oct 2022 23:13:18 +0200 +Subject: [PATCH] mtd: core: set ROOT_DEV for partitions marked as rootfs in DT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds support for "linux,rootfs" binding that is used to mark flash +partition containing rootfs. It's useful for devices using device tree +that don't have bootloader passing root info in cmdline. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221022211318.32009-2-zajec5@gmail.com +--- + drivers/mtd/mtdcore.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -737,6 +738,17 @@ int add_mtd_device(struct mtd_info *mtd) + not->add(mtd); + + mutex_unlock(&mtd_table_mutex); ++ ++ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) { ++ if (IS_BUILTIN(CONFIG_MTD)) { ++ pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); ++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); ++ } else { ++ pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", ++ mtd->index, mtd->name); ++ } ++ } ++ + /* We _know_ we aren't being removed, because + our caller is still holding us here. So none + of this try_ nonsense, and no bitching about it diff --git a/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch b/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch new file mode 100644 index 0000000000..e570564a0b --- /dev/null +++ b/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch @@ -0,0 +1,229 @@ +From aec4d5f5ffd0f0092bd9dc21ea90e0bc237d4b74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 15 Oct 2022 11:29:50 +0200 +Subject: [PATCH] mtd: parsers: add TP-Link SafeLoader partitions table parser +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This parser deals with most TP-Link home routers. It reads info about +partitions and registers them in the MTD subsystem. + +Example from TP-Link Archer C5 V2: + +spi-nor spi0.0: s25fl128s1 (16384 Kbytes) +15 tplink-safeloader partitions found on MTD device spi0.0 +Creating 15 MTD partitions on "spi0.0": +0x000000000000-0x000000040000 : "fs-uboot" +0x000000040000-0x000000440000 : "os-image" +0x000000440000-0x000000e40000 : "rootfs" +0x000000e40000-0x000000e40200 : "default-mac" +0x000000e40200-0x000000e40400 : "pin" +0x000000e40400-0x000000e40600 : "product-info" +0x000000e50000-0x000000e60000 : "partition-table" +0x000000e60000-0x000000e60200 : "soft-version" +0x000000e61000-0x000000e70000 : "support-list" +0x000000e70000-0x000000e80000 : "profile" +0x000000e80000-0x000000e90000 : "default-config" +0x000000e90000-0x000000ee0000 : "user-config" +0x000000ee0000-0x000000fe0000 : "log" +0x000000fe0000-0x000000ff0000 : "radio_bk" +0x000000ff0000-0x000001000000 : "radio" + +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221015092950.27467-2-zajec5@gmail.com +--- + drivers/mtd/parsers/Kconfig | 15 +++ + drivers/mtd/parsers/Makefile | 1 + + drivers/mtd/parsers/tplink_safeloader.c | 150 ++++++++++++++++++++++++ + 3 files changed, 166 insertions(+) + create mode 100644 drivers/mtd/parsers/tplink_safeloader.c + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -123,6 +123,21 @@ config MTD_AFS_PARTS + for your particular device. It won't happen automatically. The + 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. + ++config MTD_PARSER_TPLINK_SAFELOADER ++ tristate "TP-Link Safeloader partitions parser" ++ depends on MTD && (ARCH_BCM_5301X || ATH79 || SOC_MT7620 || SOC_MT7621 || COMPILE_TEST) ++ help ++ TP-Link home routers use flash partitions to store various data. Info ++ about flash space layout is stored in a partitions table using a ++ custom ASCII-based format. ++ ++ That format was first found in devices with SafeLoader bootloader and ++ was named after it. Later it was adapted to CFE and U-Boot ++ bootloaders. ++ ++ This driver reads partitions table, parses it and creates MTD ++ partitions. ++ + config MTD_PARSER_TRX + tristate "Parser for TRX format partitions" + depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST) +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += + ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o + obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o ++obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o + obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o + obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o + obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o +--- /dev/null ++++ b/drivers/mtd/parsers/tplink_safeloader.c +@@ -0,0 +1,150 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright © 2022 Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TPLINK_SAFELOADER_DATA_OFFSET 4 ++#define TPLINK_SAFELOADER_MAX_PARTS 32 ++ ++struct safeloader_cmn_header { ++ __be32 size; ++ uint32_t unused; ++} __packed; ++ ++static void *mtd_parser_tplink_safeloader_read_table(struct mtd_info *mtd) ++{ ++ struct safeloader_cmn_header hdr; ++ struct device_node *np; ++ size_t bytes_read; ++ size_t offset; ++ size_t size; ++ char *buf; ++ int err; ++ ++ np = mtd_get_of_node(mtd); ++ if (mtd_is_partition(mtd)) ++ of_node_get(np); ++ else ++ np = of_get_child_by_name(np, "partitions"); ++ ++ if (of_property_read_u32(np, "partitions-table-offset", (u32 *)&offset)) { ++ pr_err("Failed to get partitions table offset\n"); ++ goto err_put; ++ } ++ ++ err = mtd_read(mtd, offset, sizeof(hdr), &bytes_read, (uint8_t *)&hdr); ++ if (err && !mtd_is_bitflip(err)) { ++ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset); ++ goto err_put; ++ } ++ ++ size = be32_to_cpu(hdr.size); ++ ++ buf = kmalloc(size + 1, GFP_KERNEL); ++ if (!buf) ++ goto err_put; ++ ++ err = mtd_read(mtd, offset + sizeof(hdr), size, &bytes_read, buf); ++ if (err && !mtd_is_bitflip(err)) { ++ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset + sizeof(hdr)); ++ goto err_kfree; ++ } ++ ++ buf[size] = '\0'; ++ ++ of_node_put(np); ++ ++ return buf; ++ ++err_kfree: ++ kfree(buf); ++err_put: ++ of_node_put(np); ++ return NULL; ++} ++ ++static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct mtd_partition *parts; ++ char name[65]; ++ size_t offset; ++ size_t bytes; ++ char *buf; ++ int idx; ++ int err; ++ ++ parts = kcalloc(TPLINK_SAFELOADER_MAX_PARTS, sizeof(*parts), GFP_KERNEL); ++ if (!parts) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ buf = mtd_parser_tplink_safeloader_read_table(mtd); ++ if (!buf) { ++ err = -ENOENT; ++ goto err_out; ++ } ++ ++ for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET; ++ idx < TPLINK_SAFELOADER_MAX_PARTS && ++ sscanf(buf + offset, "partition %64s base 0x%llx size 0x%llx%zn\n", ++ name, &parts[idx].offset, &parts[idx].size, &bytes) == 3; ++ idx++, offset += bytes + 1) { ++ parts[idx].name = kstrdup(name, GFP_KERNEL); ++ if (!parts[idx].name) { ++ err = -ENOMEM; ++ goto err_free; ++ } ++ } ++ ++ if (idx == TPLINK_SAFELOADER_MAX_PARTS) ++ pr_warn("Reached maximum number of partitions!\n"); ++ ++ kfree(buf); ++ ++ *pparts = parts; ++ ++ return idx; ++ ++err_free: ++ for (idx -= 1; idx >= 0; idx--) ++ kfree(parts[idx].name); ++err_out: ++ return err; ++}; ++ ++static void mtd_parser_tplink_safeloader_cleanup(const struct mtd_partition *pparts, ++ int nr_parts) ++{ ++ int i; ++ ++ for (i = 0; i < nr_parts; i++) ++ kfree(pparts[i].name); ++ ++ kfree(pparts); ++} ++ ++static const struct of_device_id mtd_parser_tplink_safeloader_of_match_table[] = { ++ { .compatible = "tplink,safeloader-partitions" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mtd_parser_tplink_safeloader_of_match_table); ++ ++static struct mtd_part_parser mtd_parser_tplink_safeloader = { ++ .parse_fn = mtd_parser_tplink_safeloader_parse, ++ .cleanup = mtd_parser_tplink_safeloader_cleanup, ++ .name = "tplink-safeloader", ++ .of_match_table = mtd_parser_tplink_safeloader_of_match_table, ++}; ++module_mtd_part_parser(mtd_parser_tplink_safeloader); ++ ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch b/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch new file mode 100644 index 0000000000..7dbc271725 --- /dev/null +++ b/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch @@ -0,0 +1,35 @@ +From ebed787a0becb9354f0a23620a5130cccd6c730c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 19 Jan 2023 03:45:43 +0000 +Subject: [PATCH] mtd: spinand: macronix: use scratch buffer for DMA operation + +The mx35lf1ge4ab_get_eccsr() function uses an SPI DMA operation to +read the eccsr, hence the buffer should not be on stack. Since commit +380583227c0c7f ("spi: spi-mem: Add extra sanity checks on the op param") +the kernel emmits a warning and blocks such operations. + +Use the scratch buffer to get eccsr instead of trying to directly read +into a stack-allocated variable. + +Signed-off-by: Daniel Golle +Reviewed-by: Dhruva Gole +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/Y8i85zM0u4XdM46z@makrotopia.org +--- + drivers/mtd/nand/spi/macronix.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/nand/spi/macronix.c ++++ b/drivers/mtd/nand/spi/macronix.c +@@ -83,9 +83,10 @@ static int mx35lf1ge4ab_ecc_get_status(s + * in order to avoid forcing the wear-leveling layer to move + * data around if it's not necessary. + */ +- if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) ++ if (mx35lf1ge4ab_get_eccsr(spinand, spinand->scratchbuf)) + return nanddev_get_ecc_conf(nand)->strength; + ++ eccsr = *spinand->scratchbuf; + if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || + !eccsr)) + return nanddev_get_ecc_conf(nand)->strength; diff --git a/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch b/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch new file mode 100644 index 0000000000..657404196d --- /dev/null +++ b/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch @@ -0,0 +1,33 @@ +From 1ecf9e390452e73a362ea7fbde8f3f0db83de856 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 22 Dec 2022 19:33:04 +0000 +Subject: [PATCH] mtd: ubi: wire-up parent MTD device + +Wire up the device parent pointer of UBI devices to their lower MTD +device, typically an MTD partition or whole-chip device. + +The most noticeable change is that in sysfs, previously ubi devices +would be could in /sys/devices/virtual/ubi while after this change they +would be correctly attached to their parent MTD device, e.g. + +/sys/devices/platform/1100d000.spi/spi_master/spi1/spi1.0/mtd/mtd2/ubi0. + +Locating UBI devices using /sys/class/ubi/ of course still works as +well. + +Signed-off-by: Daniel Golle +Signed-off-by: Richard Weinberger +--- + drivers/mtd/ubi/build.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -929,6 +929,7 @@ int ubi_attach_mtd_dev(struct mtd_info * + ubi->dev.release = dev_release; + ubi->dev.class = &ubi_class; + ubi->dev.groups = ubi_dev_groups; ++ ubi->dev.parent = &mtd->dev; + + ubi->mtd = mtd; + ubi->ubi_num = ubi_num; diff --git a/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch b/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch new file mode 100644 index 0000000000..48bf986118 --- /dev/null +++ b/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch @@ -0,0 +1,49 @@ +From 05b8773ca33253ea562be145cf3145b05ef19f86 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 22 Dec 2022 19:33:31 +0000 +Subject: [PATCH] mtd: ubi: block: wire-up device parent + +ubiblock devices were previously only identifyable by their name, but +not connected to their parent UBI volume device e.g. in sysfs. +Properly parent ubiblock device as descendant of a UBI volume device +to reflect device model hierachy. + +Signed-off-by: Daniel Golle +Signed-off-by: Richard Weinberger +--- + drivers/mtd/ubi/block.c | 2 +- + drivers/mtd/ubi/kapi.c | 1 + + include/linux/mtd/ubi.h | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -452,7 +452,7 @@ int ubiblock_create(struct ubi_volume_in + list_add_tail(&dev->list, &ubiblock_devices); + + /* Must be the last step: anyone can call file ops from now on */ +- ret = add_disk(dev->gd); ++ ret = device_add_disk(vi->dev, dev->gd, NULL); + if (ret) + goto out_destroy_wq; + +--- a/drivers/mtd/ubi/kapi.c ++++ b/drivers/mtd/ubi/kapi.c +@@ -79,6 +79,7 @@ void ubi_do_get_volume_info(struct ubi_d + vi->name_len = vol->name_len; + vi->name = vol->name; + vi->cdev = vol->cdev.dev; ++ vi->dev = &vol->dev; + } + + /** +--- a/include/linux/mtd/ubi.h ++++ b/include/linux/mtd/ubi.h +@@ -110,6 +110,7 @@ struct ubi_volume_info { + int name_len; + const char *name; + dev_t cdev; ++ struct device *dev; + }; + + /** diff --git a/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch b/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch new file mode 100644 index 0000000000..9ddda420ac --- /dev/null +++ b/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch @@ -0,0 +1,47 @@ +From 281f7a6c1a33fffcde32001bacbb4f672140fbf9 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Wed, 8 Mar 2023 09:20:21 +0100 +Subject: [PATCH] mtd: core: prepare mtd_otp_nvmem_add() to handle + -EPROBE_DEFER + +NVMEM soon will get the ability for nvmem layouts and these might +not be ready when nvmem_register() is called and thus it might +return -EPROBE_DEFER. Don't print the error message in this case. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-4-michael@walle.cc +--- + drivers/mtd/mtdcore.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -953,8 +953,8 @@ static int mtd_otp_nvmem_add(struct mtd_ + nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, + mtd_nvmem_user_otp_reg_read); + if (IS_ERR(nvmem)) { +- dev_err(dev, "Failed to register OTP NVMEM device\n"); +- return PTR_ERR(nvmem); ++ err = PTR_ERR(nvmem); ++ goto err; + } + mtd->otp_user_nvmem = nvmem; + } +@@ -971,7 +971,6 @@ static int mtd_otp_nvmem_add(struct mtd_ + nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, + mtd_nvmem_fact_otp_reg_read); + if (IS_ERR(nvmem)) { +- dev_err(dev, "Failed to register OTP NVMEM device\n"); + err = PTR_ERR(nvmem); + goto err; + } +@@ -983,7 +982,7 @@ static int mtd_otp_nvmem_add(struct mtd_ + + err: + nvmem_unregister(mtd->otp_user_nvmem); +- return err; ++ return dev_err_probe(dev, err, "Failed to register OTP NVMEM device\n"); + } + + /** diff --git a/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch b/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch new file mode 100644 index 0000000000..28b7b4383e --- /dev/null +++ b/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch @@ -0,0 +1,41 @@ +From 7390609b0121a1b982c5ecdfcd72dc328e5784ee Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:42 +0000 +Subject: [PATCH] net: add helper eth_addr_add() + +Add a helper to add an offset to a ethernet address. This comes in handy +if you have a base ethernet address for multiple interfaces. + +Signed-off-by: Michael Walle +Reviewed-by: Andrew Lunn +Acked-by: Jakub Kicinski +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/etherdevice.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/include/linux/etherdevice.h ++++ b/include/linux/etherdevice.h +@@ -508,6 +508,20 @@ static inline void eth_addr_inc(u8 *addr + } + + /** ++ * eth_addr_add() - Add (or subtract) an offset to/from the given MAC address. ++ * ++ * @offset: Offset to add. ++ * @addr: Pointer to a six-byte array containing Ethernet address to increment. ++ */ ++static inline void eth_addr_add(u8 *addr, long offset) ++{ ++ u64 u = ether_addr_to_u64(addr); ++ ++ u += offset; ++ u64_to_ether_addr(u, addr); ++} ++ ++/** + * is_etherdev_addr - Tell if given Ethernet address belongs to the device. + * @dev: Pointer to a device structure + * @addr: Pointer to a six-byte array containing the Ethernet address diff --git a/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch b/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch new file mode 100644 index 0000000000..56e14c5c0a --- /dev/null +++ b/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch @@ -0,0 +1,32 @@ +From d387e34fec407f881fdf165b5d7ec128ebff362f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 19 Sep 2023 14:47:20 +0200 +Subject: [PATCH] net: sfp: add quirk for Fiberstone GPON-ONU-34-20BI + +Fiberstone GPON-ONU-34-20B can operate at 2500base-X, but report 1.2GBd +NRZ in their EEPROM. + +The module also require the ignore tx fault fixup similar to Huawei MA5671A +as it gets disabled on error messages with serial redirection enabled. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20230919124720.8210-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/sfp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -393,6 +393,11 @@ static const struct sfp_quirk sfp_quirks + SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, + sfp_fixup_long_startup), + ++ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd ++ // NRZ in their EEPROM ++ SFP_QUIRK("FS", "GPON-ONU-34-20BI", sfp_quirk_2500basex, ++ sfp_fixup_ignore_tx_fault), ++ + SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp), + + // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports diff --git a/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch b/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch new file mode 100644 index 0000000000..0cad6c53d4 --- /dev/null +++ b/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch @@ -0,0 +1,2306 @@ +From d2213db3f49bce8e7a87c8de05b9a091f78f654e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:41 +0100 +Subject: [PATCH 1/3] net: phy: aquantia: move to separate directory + +Move aquantia PHY driver to separate driectory in preparation for +firmware loading support to keep things tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 +---- + drivers/net/phy/Makefile | 6 +----- + drivers/net/phy/aquantia/Kconfig | 5 +++++ + drivers/net/phy/aquantia/Makefile | 6 ++++++ + drivers/net/phy/{ => aquantia}/aquantia.h | 0 + drivers/net/phy/{ => aquantia}/aquantia_hwmon.c | 0 + drivers/net/phy/{ => aquantia}/aquantia_main.c | 0 + 7 files changed, 13 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/phy/aquantia/Kconfig + create mode 100644 drivers/net/phy/aquantia/Makefile + rename drivers/net/phy/{ => aquantia}/aquantia.h (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_hwmon.c (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_main.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -90,10 +90,7 @@ config ADIN1100_PHY + Currently supports the: + - ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY + +-config AQUANTIA_PHY +- tristate "Aquantia PHYs" +- help +- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 ++source "drivers/net/phy/aquantia/Kconfig" + + config AX88796B_PHY + tristate "Asix PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -33,11 +33,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AMD_PHY) += amd.o +-aquantia-objs += aquantia_main.o +-ifdef CONFIG_HWMON +-aquantia-objs += aquantia_hwmon.o +-endif +-obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o +--- /dev/null ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AQUANTIA_PHY ++ tristate "Aquantia PHYs" ++ help ++ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- /dev/null ++++ b/drivers/net/phy/aquantia/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++aquantia-objs += aquantia_main.o ++ifdef CONFIG_HWMON ++aquantia-objs += aquantia_hwmon.o ++endif ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +--- a/drivers/net/phy/aquantia.h ++++ /dev/null +@@ -1,16 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +- +-#if IS_REACHABLE(CONFIG_HWMON) +-int aqr_hwmon_probe(struct phy_device *phydev); +-#else +-static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } +-#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++int aqr_hwmon_probe(struct phy_device *phydev); ++#else ++static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -0,0 +1,250 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++ ++static umode_t aqr_hwmon_is_visible(const void *data, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ if (type != hwmon_temp) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ case hwmon_temp_min_alarm: ++ case hwmon_temp_max_alarm: ++ case hwmon_temp_lcrit_alarm: ++ case hwmon_temp_crit_alarm: ++ return 0444; ++ case hwmon_temp_min: ++ case hwmon_temp_max: ++ case hwmon_temp_lcrit: ++ case hwmon_temp_crit: ++ return 0644; ++ default: ++ return 0; ++ } ++} ++ ++static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) ++{ ++ int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (temp < 0) ++ return temp; ++ ++ /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ ++ *value = (s16)temp * 1000 / 256; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) ++{ ++ int temp; ++ ++ if (value >= 128000 || value < -128000) ++ return -ERANGE; ++ ++ temp = value * 256 / 1000; ++ ++ /* temp is in s16 range and we're interested in lower 16 bits only */ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); ++} ++ ++static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) ++{ ++ int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (val < 0) ++ return val; ++ ++ return !!(val & bit); ++} ++ ++static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) ++{ ++ int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); ++ ++ if (val < 0) ++ return val; ++ ++ *value = val; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ int reg; ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, ++ VEND1_THERMAL_STAT2_VALID); ++ if (reg < 0) ++ return reg; ++ if (!reg) ++ return -EBUSY; ++ ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); ++ ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ case hwmon_temp_lcrit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static const struct hwmon_ops aqr_hwmon_ops = { ++ .is_visible = aqr_hwmon_is_visible, ++ .read = aqr_hwmon_read, ++ .write = aqr_hwmon_write, ++}; ++ ++static u32 aqr_hwmon_chip_config[] = { ++ HWMON_C_REGISTER_TZ, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_chip = { ++ .type = hwmon_chip, ++ .config = aqr_hwmon_chip_config, ++}; ++ ++static u32 aqr_hwmon_temp_config[] = { ++ HWMON_T_INPUT | ++ HWMON_T_MAX | HWMON_T_MIN | ++ HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | ++ HWMON_T_CRIT | HWMON_T_LCRIT | ++ HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_temp = { ++ .type = hwmon_temp, ++ .config = aqr_hwmon_temp_config, ++}; ++ ++static const struct hwmon_channel_info *aqr_hwmon_info[] = { ++ &aqr_hwmon_chip, ++ &aqr_hwmon_temp, ++ NULL, ++}; ++ ++static const struct hwmon_chip_info aqr_hwmon_chip_info = { ++ .ops = &aqr_hwmon_ops, ++ .info = aqr_hwmon_info, ++}; ++ ++int aqr_hwmon_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct device *hwmon_dev; ++ char *hwmon_name; ++ int i, j; ++ ++ hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); ++ if (!hwmon_name) ++ return -ENOMEM; ++ ++ for (i = j = 0; hwmon_name[i]; i++) { ++ if (isalnum(hwmon_name[i])) { ++ if (i != j) ++ hwmon_name[j] = hwmon_name[i]; ++ j++; ++ } ++ } ++ hwmon_name[j] = '\0'; ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, ++ phydev, &aqr_hwmon_chip_info, NULL); ++ ++ return PTR_ERR_OR_ZERO(hwmon_dev); ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -0,0 +1,842 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Aquantia PHY ++ * ++ * Author: Shaohui Xie ++ * ++ * Copyright 2015 Freescale Semiconductor, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++#define PHY_ID_AQ1202 0x03a1b445 ++#define PHY_ID_AQ2104 0x03a1b460 ++#define PHY_ID_AQR105 0x03a1b4a2 ++#define PHY_ID_AQR106 0x03a1b4d0 ++#define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQCS109 0x03a1b5c2 ++#define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 ++ ++#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 ++ ++#define MDIO_AN_VEND_PROV 0xc400 ++#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) ++#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) ++#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) ++#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 ++ ++#define MDIO_AN_TX_VEND_STATUS1 0xc800 ++#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) ++#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 ++#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 ++#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 ++#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 ++#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 ++#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 ++#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 ++#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 ++#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 ++#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) ++ ++#define MDIO_AN_RX_LP_STAT1 0xe820 ++#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) ++#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) ++#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) ++#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) ++#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) ++ ++#define MDIO_AN_RX_LP_STAT4 0xe823 ++#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) ++#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) ++ ++#define MDIO_AN_RX_VEND_STAT3 0xe832 ++#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) ++ ++/* MDIO_MMD_C22EXT */ ++#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 ++#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 ++#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 ++#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 ++#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 ++#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 ++#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 ++#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 ++#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a ++#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b ++ ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ ++/* Sleep and timeout for checking if the Processor-Intensive ++ * MDIO operation is finished ++ */ ++#define AQR107_OP_IN_PROG_SLEEP 1000 ++#define AQR107_OP_IN_PROG_TIMEOUT 100000 ++ ++struct aqr107_hw_stat { ++ const char *name; ++ int reg; ++ int size; ++}; ++ ++#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } ++static const struct aqr107_hw_stat aqr107_hw_stats[] = { ++ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), ++ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), ++}; ++#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) ++ ++struct aqr107_priv { ++ u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; ++}; ++ ++static int aqr107_get_sset_count(struct phy_device *phydev) ++{ ++ return AQR107_SGMII_STAT_SZ; ++} ++ ++static void aqr107_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) ++ strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, ++ ETH_GSTRING_LEN); ++} ++ ++static u64 aqr107_get_stat(struct phy_device *phydev, int index) ++{ ++ const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; ++ int len_l = min(stat->size, 16); ++ int len_h = stat->size - len_l; ++ u64 ret; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret = val & GENMASK(len_l - 1, 0); ++ if (len_h) { ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret += (val & GENMASK(len_h - 1, 0)) << 16; ++ } ++ ++ return ret; ++} ++ ++static void aqr107_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ struct aqr107_priv *priv = phydev->priv; ++ u64 val; ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { ++ val = aqr107_get_stat(phydev, i); ++ if (val == U64_MAX) ++ phydev_err(phydev, "Reading HW Statistics failed for %s\n", ++ aqr107_hw_stats[i].name); ++ else ++ priv->sgmii_stats[i] += val; ++ ++ data[i] = priv->sgmii_stats[i]; ++ } ++} ++ ++static int aqr_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ u16 reg; ++ int ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ return genphy_c45_pma_setup_forced(phydev); ++ ++ ret = genphy_c45_an_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ /* Clause 45 has no standardized support for 1000BaseT, therefore ++ * use vendor registers for this mode. ++ */ ++ reg = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; ++ ++ /* Handle the case when the 2.5G and 5G speeds are not advertised */ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_1000BASET_HALF | ++ MDIO_AN_VEND_PROV_1000BASET_FULL | ++ MDIO_AN_VEND_PROV_2500BASET_FULL | ++ MDIO_AN_VEND_PROV_5000BASET_FULL, reg); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return genphy_c45_check_and_restart_aneg(phydev, changed); ++} ++ ++static int aqr_config_intr(struct phy_device *phydev) ++{ ++ bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; ++ int err; ++ ++ if (en) { ++ /* Clear any pending interrupts before enabling them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, ++ en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, ++ en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, ++ en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | ++ VEND1_GLOBAL_INT_VEND_MASK_AN : 0); ++ if (err < 0) ++ return err; ++ ++ if (!en) { ++ /* Clear any pending interrupts after we have disabled them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, ++ MDIO_AN_TX_VEND_INT_STATUS2); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int aqr_read_status(struct phy_device *phydev) ++{ ++ int val; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); ++ } ++ ++ return genphy_c45_read_status(phydev); ++} ++ ++static int aqr107_read_rate(struct phy_device *phydev) ++{ ++ u32 config_reg; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); ++ if (val < 0) ++ return val; ++ ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { ++ case MDIO_AN_TX_VEND_STATUS1_10BASET: ++ phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_100BASETX: ++ phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_1000BASET: ++ phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_2500BASET: ++ phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_5000BASET: ++ phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_10GBASET: ++ phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; ++ break; ++ default: ++ phydev->speed = SPEED_UNKNOWN; ++ return 0; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ else ++ phydev->rate_matching = RATE_MATCH_NONE; ++ ++ return 0; ++} ++ ++static int aqr107_read_status(struct phy_device *phydev) ++{ ++ int val, ret; ++ ++ ret = aqr_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) ++ return 0; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); ++ if (val < 0) ++ return val; ++ ++ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: ++ phydev->interface = PHY_INTERFACE_MODE_10GKR; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: ++ phydev->interface = PHY_INTERFACE_MODE_10GBASER; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: ++ phydev->interface = PHY_INTERFACE_MODE_USXGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ default: ++ phydev->interface = PHY_INTERFACE_MODE_NA; ++ break; ++ } ++ ++ /* Read possibly downshifted rate from vendor register */ ++ return aqr107_read_rate(phydev); ++} ++ ++static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) ++{ ++ int val, cnt, enable; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); ++ if (val < 0) ++ return val; ++ ++ enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); ++ cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++ ++ *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ int val = 0; ++ ++ if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) ++ return -E2BIG; ++ ++ if (cnt != DOWNSHIFT_DEV_DISABLE) { ++ val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; ++ val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_DOWNSHIFT_EN | ++ MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++} ++ ++static int aqr107_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr107_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++/* If we configure settings whilst firmware is still initializing the chip, ++ * then these settings may be overwritten. Therefore make sure chip ++ * initialization has completed. Use presence of the firmware ID as ++ * indicator for initialization having completed. ++ * The chip also provides a "reset completed" bit, but it's cleared after ++ * read. Therefore function would time out if called again. ++ */ ++static int aqr107_wait_reset_complete(struct phy_device *phydev) ++{ ++ int val; ++ ++ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_FW_ID, val, val != 0, ++ 20000, 2000000, false); ++} ++ ++static void aqr107_chip_info(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor, build_id, prov_id; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); ++ fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); ++ if (val < 0) ++ return; ++ ++ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); ++ prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); ++ ++ phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", ++ fw_major, fw_minor, build_id, prov_id); ++} ++ ++static int aqr107_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_XGMII && ++ phydev->interface != PHY_INTERFACE_MODE_USXGMII && ++ phydev->interface != PHY_INTERFACE_MODE_10GKR && ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) ++ return -ENODEV; ++ ++ WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, ++ "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static int aqcs109_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX) ++ return -ENODEV; ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ /* AQCS109 belongs to a chip family partially supporting 10G and 5G. ++ * PMA speed ability bits are the same for all members of the family, ++ * AQCS109 however supports speeds up to 2.5G only. ++ */ ++ phy_set_max_speed(phydev, SPEED_2500); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static void aqr107_link_change_notify(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor; ++ bool downshift, short_reach, afr; ++ int mode, val; ++ ++ if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) ++ return; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ /* call failed or link partner is no Aquantia PHY */ ++ if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) ++ return; ++ ++ short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; ++ downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); ++ fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); ++ if (val < 0) ++ return; ++ ++ afr = val & MDIO_AN_RX_VEND_STAT3_AFR; ++ ++ phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", ++ fw_major, fw_minor, ++ short_reach ? ", short reach mode" : "", ++ downshift ? ", fast-retrain downshift advertised" : "", ++ afr ? ", fast reframe advertised" : ""); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); ++ if (val < 0) ++ return; ++ ++ mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); ++ if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) ++ phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); ++} ++ ++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) ++{ ++ int val, err; ++ ++ /* The datasheet notes to wait at least 1ms after issuing a ++ * processor intensive operation before checking. ++ * We cannot use the 'sleep_before_read' parameter of read_poll_timeout ++ * because that just determines the maximum time slept, not the minimum. ++ */ ++ usleep_range(1000, 5000); ++ ++ err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_GEN_STAT2, val, ++ !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), ++ AQR107_OP_IN_PROG_SLEEP, ++ AQR107_OP_IN_PROG_TIMEOUT, false); ++ if (err) { ++ phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ ++static int aqr107_suspend(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_resume(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_probe(struct phy_device *phydev) ++{ ++ phydev->priv = devm_kzalloc(&phydev->mdio.dev, ++ sizeof(struct aqr107_priv), GFP_KERNEL); ++ if (!phydev->priv) ++ return -ENOMEM; ++ ++ return aqr_hwmon_probe(phydev); ++} ++ ++static struct phy_driver aqr_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), ++ .name = "Aquantia AQ1202", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), ++ .name = "Aquantia AQ2104", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR105), ++ .name = "Aquantia AQR105", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR106), ++ .name = "Aquantia AQR106", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR107), ++ .name = "Aquantia AQR107", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), ++ .name = "Aquantia AQCS109", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqcs109_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR405), ++ .name = "Aquantia AQR405", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++}; ++ ++module_phy_driver(aqr_driver); ++ ++static struct mdio_device_id __maybe_unused aqr_tbl[] = { ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, aqr_tbl); ++ ++MODULE_DESCRIPTION("Aquantia PHY driver"); ++MODULE_AUTHOR("Shaohui Xie "); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/phy/aquantia_hwmon.c ++++ /dev/null +@@ -1,250 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- +-#if IS_REACHABLE(CONFIG_HWMON) +- +-static umode_t aqr_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- case hwmon_temp_min_alarm: +- case hwmon_temp_max_alarm: +- case hwmon_temp_lcrit_alarm: +- case hwmon_temp_crit_alarm: +- return 0444; +- case hwmon_temp_min: +- case hwmon_temp_max: +- case hwmon_temp_lcrit: +- case hwmon_temp_crit: +- return 0644; +- default: +- return 0; +- } +-} +- +-static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) +-{ +- int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (temp < 0) +- return temp; +- +- /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ +- *value = (s16)temp * 1000 / 256; +- +- return 0; +-} +- +-static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) +-{ +- int temp; +- +- if (value >= 128000 || value < -128000) +- return -ERANGE; +- +- temp = value * 256 / 1000; +- +- /* temp is in s16 range and we're interested in lower 16 bits only */ +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); +-} +- +-static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) +-{ +- int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (val < 0) +- return val; +- +- return !!(val & bit); +-} +- +-static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) +-{ +- int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); +- +- if (val < 0) +- return val; +- +- *value = val; +- +- return 0; +-} +- +-static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long *value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int reg; +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_input: +- reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, +- VEND1_THERMAL_STAT2_VALID); +- if (reg < 0) +- return reg; +- if (!reg) +- return -EBUSY; +- +- return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); +- +- case hwmon_temp_lcrit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- case hwmon_temp_lcrit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_lcrit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static const struct hwmon_ops aqr_hwmon_ops = { +- .is_visible = aqr_hwmon_is_visible, +- .read = aqr_hwmon_read, +- .write = aqr_hwmon_write, +-}; +- +-static u32 aqr_hwmon_chip_config[] = { +- HWMON_C_REGISTER_TZ, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_chip = { +- .type = hwmon_chip, +- .config = aqr_hwmon_chip_config, +-}; +- +-static u32 aqr_hwmon_temp_config[] = { +- HWMON_T_INPUT | +- HWMON_T_MAX | HWMON_T_MIN | +- HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | +- HWMON_T_CRIT | HWMON_T_LCRIT | +- HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_temp = { +- .type = hwmon_temp, +- .config = aqr_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *aqr_hwmon_info[] = { +- &aqr_hwmon_chip, +- &aqr_hwmon_temp, +- NULL, +-}; +- +-static const struct hwmon_chip_info aqr_hwmon_chip_info = { +- .ops = &aqr_hwmon_ops, +- .info = aqr_hwmon_info, +-}; +- +-int aqr_hwmon_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct device *hwmon_dev; +- char *hwmon_name; +- int i, j; +- +- hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); +- if (!hwmon_name) +- return -ENOMEM; +- +- for (i = j = 0; hwmon_name[i]; i++) { +- if (isalnum(hwmon_name[i])) { +- if (i != j) +- hwmon_name[j] = hwmon_name[i]; +- j++; +- } +- } +- hwmon_name[j] = '\0'; +- +- hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, +- phydev, &aqr_hwmon_chip_info, NULL); +- +- return PTR_ERR_OR_ZERO(hwmon_dev); +-} +- +-#endif +--- a/drivers/net/phy/aquantia_main.c ++++ /dev/null +@@ -1,842 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Driver for Aquantia PHY +- * +- * Author: Shaohui Xie +- * +- * Copyright 2015 Freescale Semiconductor, Inc. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-#define PHY_ID_AQ1202 0x03a1b445 +-#define PHY_ID_AQ2104 0x03a1b460 +-#define PHY_ID_AQR105 0x03a1b4a2 +-#define PHY_ID_AQR106 0x03a1b4d0 +-#define PHY_ID_AQR107 0x03a1b4e0 +-#define PHY_ID_AQCS109 0x03a1b5c2 +-#define PHY_ID_AQR405 0x03a1b4b0 +-#define PHY_ID_AQR113C 0x31c31c12 +- +-#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 +- +-#define MDIO_AN_VEND_PROV 0xc400 +-#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +-#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) +-#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) +-#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 +- +-#define MDIO_AN_TX_VEND_STATUS1 0xc800 +-#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) +-#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 +-#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 +-#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 +-#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 +-#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 +-#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 +-#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 +-#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) +- +-#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 +-#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +-#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) +- +-#define MDIO_AN_RX_LP_STAT1 0xe820 +-#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +-#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) +-#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) +-#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) +-#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) +- +-#define MDIO_AN_RX_LP_STAT4 0xe823 +-#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) +-#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) +- +-#define MDIO_AN_RX_VEND_STAT3 0xe832 +-#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) +- +-/* MDIO_MMD_C22EXT */ +-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 +-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 +-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 +-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 +-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 +-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 +-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 +-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 +-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a +-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b +- +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- +-/* Sleep and timeout for checking if the Processor-Intensive +- * MDIO operation is finished +- */ +-#define AQR107_OP_IN_PROG_SLEEP 1000 +-#define AQR107_OP_IN_PROG_TIMEOUT 100000 +- +-struct aqr107_hw_stat { +- const char *name; +- int reg; +- int size; +-}; +- +-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } +-static const struct aqr107_hw_stat aqr107_hw_stats[] = { +- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), +- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), +-}; +-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) +- +-struct aqr107_priv { +- u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; +-}; +- +-static int aqr107_get_sset_count(struct phy_device *phydev) +-{ +- return AQR107_SGMII_STAT_SZ; +-} +- +-static void aqr107_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) +- strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, +- ETH_GSTRING_LEN); +-} +- +-static u64 aqr107_get_stat(struct phy_device *phydev, int index) +-{ +- const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; +- int len_l = min(stat->size, 16); +- int len_h = stat->size - len_l; +- u64 ret; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); +- if (val < 0) +- return U64_MAX; +- +- ret = val & GENMASK(len_l - 1, 0); +- if (len_h) { +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); +- if (val < 0) +- return U64_MAX; +- +- ret += (val & GENMASK(len_h - 1, 0)) << 16; +- } +- +- return ret; +-} +- +-static void aqr107_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- struct aqr107_priv *priv = phydev->priv; +- u64 val; +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { +- val = aqr107_get_stat(phydev, i); +- if (val == U64_MAX) +- phydev_err(phydev, "Reading HW Statistics failed for %s\n", +- aqr107_hw_stats[i].name); +- else +- priv->sgmii_stats[i] += val; +- +- data[i] = priv->sgmii_stats[i]; +- } +-} +- +-static int aqr_config_aneg(struct phy_device *phydev) +-{ +- bool changed = false; +- u16 reg; +- int ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE) +- return genphy_c45_pma_setup_forced(phydev); +- +- ret = genphy_c45_an_config_aneg(phydev); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- /* Clause 45 has no standardized support for 1000BaseT, therefore +- * use vendor registers for this mode. +- */ +- reg = 0; +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; +- +- /* Handle the case when the 2.5G and 5G speeds are not advertised */ +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_1000BASET_HALF | +- MDIO_AN_VEND_PROV_1000BASET_FULL | +- MDIO_AN_VEND_PROV_2500BASET_FULL | +- MDIO_AN_VEND_PROV_5000BASET_FULL, reg); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- return genphy_c45_check_and_restart_aneg(phydev, changed); +-} +- +-static int aqr_config_intr(struct phy_device *phydev) +-{ +- bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +- int err; +- +- if (en) { +- /* Clear any pending interrupts before enabling them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, +- en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, +- en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, +- en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | +- VEND1_GLOBAL_INT_VEND_MASK_AN : 0); +- if (err < 0) +- return err; +- +- if (!en) { +- /* Clear any pending interrupts after we have disabled them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- return 0; +-} +- +-static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, +- MDIO_AN_TX_VEND_INT_STATUS2); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static int aqr_read_status(struct phy_device *phydev) +-{ +- int val; +- +- if (phydev->autoneg == AUTONEG_ENABLE) { +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- if (val < 0) +- return val; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); +- } +- +- return genphy_c45_read_status(phydev); +-} +- +-static int aqr107_read_rate(struct phy_device *phydev) +-{ +- u32 config_reg; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); +- if (val < 0) +- return val; +- +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { +- case MDIO_AN_TX_VEND_STATUS1_10BASET: +- phydev->speed = SPEED_10; +- config_reg = VEND1_GLOBAL_CFG_10M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_100BASETX: +- phydev->speed = SPEED_100; +- config_reg = VEND1_GLOBAL_CFG_100M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_1000BASET: +- phydev->speed = SPEED_1000; +- config_reg = VEND1_GLOBAL_CFG_1G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_2500BASET: +- phydev->speed = SPEED_2500; +- config_reg = VEND1_GLOBAL_CFG_2_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_5000BASET: +- phydev->speed = SPEED_5000; +- config_reg = VEND1_GLOBAL_CFG_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_10GBASET: +- phydev->speed = SPEED_10000; +- config_reg = VEND1_GLOBAL_CFG_10G; +- break; +- default: +- phydev->speed = SPEED_UNKNOWN; +- return 0; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); +- if (val < 0) +- return val; +- +- if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == +- VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) +- phydev->rate_matching = RATE_MATCH_PAUSE; +- else +- phydev->rate_matching = RATE_MATCH_NONE; +- +- return 0; +-} +- +-static int aqr107_read_status(struct phy_device *phydev) +-{ +- int val, ret; +- +- ret = aqr_read_status(phydev); +- if (ret) +- return ret; +- +- if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) +- return 0; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); +- if (val < 0) +- return val; +- +- switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: +- phydev->interface = PHY_INTERFACE_MODE_10GKR; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: +- phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: +- phydev->interface = PHY_INTERFACE_MODE_10GBASER; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: +- phydev->interface = PHY_INTERFACE_MODE_USXGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: +- phydev->interface = PHY_INTERFACE_MODE_XAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: +- phydev->interface = PHY_INTERFACE_MODE_RXAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- break; +- default: +- phydev->interface = PHY_INTERFACE_MODE_NA; +- break; +- } +- +- /* Read possibly downshifted rate from vendor register */ +- return aqr107_read_rate(phydev); +-} +- +-static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) +-{ +- int val, cnt, enable; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); +- if (val < 0) +- return val; +- +- enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); +- cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +- +- *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- int val = 0; +- +- if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) +- return -E2BIG; +- +- if (cnt != DOWNSHIFT_DEV_DISABLE) { +- val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; +- val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); +- } +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_DOWNSHIFT_EN | +- MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +-} +- +-static int aqr107_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr107_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-/* If we configure settings whilst firmware is still initializing the chip, +- * then these settings may be overwritten. Therefore make sure chip +- * initialization has completed. Use presence of the firmware ID as +- * indicator for initialization having completed. +- * The chip also provides a "reset completed" bit, but it's cleared after +- * read. Therefore function would time out if called again. +- */ +-static int aqr107_wait_reset_complete(struct phy_device *phydev) +-{ +- int val; +- +- return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_FW_ID, val, val != 0, +- 20000, 2000000, false); +-} +- +-static void aqr107_chip_info(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor, build_id, prov_id; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); +- fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); +- if (val < 0) +- return; +- +- build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); +- prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); +- +- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", +- fw_major, fw_minor, build_id, prov_id); +-} +- +-static int aqr107_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX && +- phydev->interface != PHY_INTERFACE_MODE_XGMII && +- phydev->interface != PHY_INTERFACE_MODE_USXGMII && +- phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER && +- phydev->interface != PHY_INTERFACE_MODE_XAUI && +- phydev->interface != PHY_INTERFACE_MODE_RXAUI) +- return -ENODEV; +- +- WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, +- "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static int aqcs109_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX) +- return -ENODEV; +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- /* AQCS109 belongs to a chip family partially supporting 10G and 5G. +- * PMA speed ability bits are the same for all members of the family, +- * AQCS109 however supports speeds up to 2.5G only. +- */ +- phy_set_max_speed(phydev, SPEED_2500); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static void aqr107_link_change_notify(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor; +- bool downshift, short_reach, afr; +- int mode, val; +- +- if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) +- return; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- /* call failed or link partner is no Aquantia PHY */ +- if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) +- return; +- +- short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; +- downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); +- fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); +- if (val < 0) +- return; +- +- afr = val & MDIO_AN_RX_VEND_STAT3_AFR; +- +- phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", +- fw_major, fw_minor, +- short_reach ? ", short reach mode" : "", +- downshift ? ", fast-retrain downshift advertised" : "", +- afr ? ", fast reframe advertised" : ""); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); +- if (val < 0) +- return; +- +- mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); +- if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) +- phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); +-} +- +-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) +-{ +- int val, err; +- +- /* The datasheet notes to wait at least 1ms after issuing a +- * processor intensive operation before checking. +- * We cannot use the 'sleep_before_read' parameter of read_poll_timeout +- * because that just determines the maximum time slept, not the minimum. +- */ +- usleep_range(1000, 5000); +- +- err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_GEN_STAT2, val, +- !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), +- AQR107_OP_IN_PROG_SLEEP, +- AQR107_OP_IN_PROG_TIMEOUT, false); +- if (err) { +- phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); +- return err; +- } +- +- return 0; +-} +- +-static int aqr107_get_rate_matching(struct phy_device *phydev, +- phy_interface_t iface) +-{ +- if (iface == PHY_INTERFACE_MODE_10GBASER || +- iface == PHY_INTERFACE_MODE_2500BASEX || +- iface == PHY_INTERFACE_MODE_NA) +- return RATE_MATCH_PAUSE; +- return RATE_MATCH_NONE; +-} +- +-static int aqr107_suspend(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_resume(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_probe(struct phy_device *phydev) +-{ +- phydev->priv = devm_kzalloc(&phydev->mdio.dev, +- sizeof(struct aqr107_priv), GFP_KERNEL); +- if (!phydev->priv) +- return -ENOMEM; +- +- return aqr_hwmon_probe(phydev); +-} +- +-static struct phy_driver aqr_driver[] = { +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +- .name = "Aquantia AQ1202", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), +- .name = "Aquantia AQ2104", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR105), +- .name = "Aquantia AQR105", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR106), +- .name = "Aquantia AQR106", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR107), +- .name = "Aquantia AQR107", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), +- .name = "Aquantia AQCS109", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqcs109_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR405), +- .name = "Aquantia AQR405", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), +- .name = "Aquantia AQR113C", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-}; +- +-module_phy_driver(aqr_driver); +- +-static struct mdio_device_id __maybe_unused aqr_tbl[] = { +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, aqr_tbl); +- +-MODULE_DESCRIPTION("Aquantia PHY driver"); +-MODULE_AUTHOR("Shaohui Xie "); +-MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch b/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch new file mode 100644 index 0000000000..2b94522723 --- /dev/null +++ b/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch @@ -0,0 +1,183 @@ +From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:42 +0100 +Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header + +Move MMD_VEND define to header to clean things up and in preparation for +firmware loading support that require some define placed in +aquantia_main. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_hwmon.c | 14 ----- + drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------ + 3 files changed, 69 insertions(+), 69 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -9,6 +9,75 @@ + #include + #include + ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ + #if IS_REACHABLE(CONFIG_HWMON) + int aqr_hwmon_probe(struct phy_device *phydev); + #else +--- a/drivers/net/phy/aquantia/aquantia_hwmon.c ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -13,20 +13,6 @@ + + #include "aquantia.h" + +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- + #if IS_REACHABLE(CONFIG_HWMON) + + static umode_t aqr_hwmon_is_visible(const void *data, +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -89,61 +89,6 @@ + #define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a + #define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b + +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- + /* Sleep and timeout for checking if the Processor-Intensive + * MDIO operation is finished + */ diff --git a/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch b/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch new file mode 100644 index 0000000000..aa52b3baa6 --- /dev/null +++ b/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch @@ -0,0 +1,504 @@ +From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 14 Nov 2023 15:08:43 +0100 +Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support + +Aquantia PHY-s require firmware to be loaded before they start operating. +It can be automatically loaded in case when there is a SPI-NOR connected +to Aquantia PHY-s or can be loaded from the host via MDIO. + +This patch adds support for loading the firmware via MDIO as in most cases +there is no SPI-NOR being used to save on cost. +Firmware loading code itself is ported from mainline U-boot with cleanups. + +The firmware has mixed values both in big and little endian. +PHY core itself is big-endian but it expects values to be in little-endian. +The firmware is little-endian but CRC-16 value for it is stored at the end +of firmware in big-endian. + +It seems the PHY does the conversion internally from firmware that is +little-endian to the PHY that is big-endian on using the mailbox +but mailbox returns a big-endian CRC-16 to verify the written data +integrity. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/Kconfig | 1 + + drivers/net/phy/aquantia/Makefile | 2 +- + drivers/net/phy/aquantia/aquantia.h | 32 ++ + drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 6 + + 5 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c + +--- a/drivers/net/phy/aquantia/Kconfig ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config AQUANTIA_PHY + tristate "Aquantia PHYs" ++ select CRC_CCITT + help + Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- a/drivers/net/phy/aquantia/Makefile ++++ b/drivers/net/phy/aquantia/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-aquantia-objs += aquantia_main.o ++aquantia-objs += aquantia_main.o aquantia_firmware.o + ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -10,10 +10,35 @@ + #include + + /* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_SC 0x0 ++#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15) ++#define VEND1_GLOBAL_SC_LOW_POWER BIT(11) ++ + #define VEND1_GLOBAL_FW_ID 0x0020 + #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) + #define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) + ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x)) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x)) ++ + /* The following registers all have similar layouts; first the registers... */ + #define VEND1_GLOBAL_CFG_10M 0x0310 + #define VEND1_GLOBAL_CFG_100M 0x031b +@@ -28,6 +53,11 @@ + #define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 + + /* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_GLOBAL_CONTROL2 0xc001 ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0) ++ + #define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 + #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 + #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p + #else + static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } + #endif ++ ++int aqr_firmware_load(struct phy_device *phydev); +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "aquantia.h" ++ ++#define UP_RESET_SLEEP 100 ++ ++/* addresses of memory segments in the phy */ ++#define DRAM_BASE_ADDR 0x3FFE0000 ++#define IRAM_BASE_ADDR 0x40000000 ++ ++/* firmware image format constants */ ++#define VERSION_STRING_SIZE 0x40 ++#define VERSION_STRING_OFFSET 0x0200 ++/* primary offset is written at an offset from the start of the fw blob */ ++#define PRIMARY_OFFSET_OFFSET 0x8 ++/* primary offset needs to be then added to a base offset */ ++#define PRIMARY_OFFSET_SHIFT 12 ++#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT) ++#define HEADER_OFFSET 0x300 ++ ++struct aqr_fw_header { ++ u32 padding; ++ u8 iram_offset[3]; ++ u8 iram_size[3]; ++ u8 dram_offset[3]; ++ u8 dram_size[3]; ++} __packed; ++ ++enum aqr_fw_src { ++ AQR_FW_SRC_NVMEM = 0, ++ AQR_FW_SRC_FS, ++}; ++ ++static const char * const aqr_fw_src_string[] = { ++ [AQR_FW_SRC_NVMEM] = "NVMEM", ++ [AQR_FW_SRC_FS] = "FS", ++}; ++ ++/* AQR firmware doesn't have fixed offsets for iram and dram section ++ * but instead provide an header with the offset to use on reading ++ * and parsing the firmware. ++ * ++ * AQR firmware can't be trusted and each offset is validated to be ++ * not negative and be in the size of the firmware itself. ++ */ ++static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size) ++{ ++ return offset + get_size <= size; ++} ++ ++static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_be16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_le16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3)) ++ return -EINVAL; ++ ++ *value = get_unaligned_le24(data + offset); ++ ++ return 0; ++} ++ ++/* load data into the phy's memory */ ++static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr, ++ const u8 *data, size_t len) ++{ ++ u16 crc = 0, up_crc; ++ size_t pos; ++ ++ /* PHY expect addr in LE */ ++ addr = (__force u32)cpu_to_le32(addr); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr)); ++ ++ /* We assume and enforce the size to be word aligned. ++ * If a firmware that is not word aligned is found, please report upstream. ++ */ ++ for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u32 word; ++ ++ /* FW data is always stored in little-endian */ ++ word = get_unaligned((const u32 *)(data + pos)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, ++ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6, ++ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); ++ ++ /* calculate CRC as we load data to the mailbox. ++ * We convert word to big-endian as PHY is BE and mailbox will ++ * return a BE CRC. ++ */ ++ word = (__force u32)cpu_to_be32(word); ++ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); ++ } ++ ++ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ if (crc != up_crc) { ++ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", ++ crc, up_crc); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size, ++ enum aqr_fw_src fw_src) ++{ ++ u16 calculated_crc, read_crc, read_primary_offset; ++ u32 iram_offset = 0, iram_size = 0; ++ u32 dram_offset = 0, dram_size = 0; ++ char version[VERSION_STRING_SIZE]; ++ u32 primary_offset = 0; ++ int ret; ++ ++ /* extract saved CRC at the end of the fw ++ * CRC is saved in big-endian as PHY is BE ++ */ ++ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc); ++ if (ret) { ++ phydev_err(phydev, "bad firmware CRC in firmware\n"); ++ return ret; ++ } ++ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16)); ++ if (read_crc != calculated_crc) { ++ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n", ++ read_crc, calculated_crc); ++ return -EINVAL; ++ } ++ ++ /* Get the primary offset to extract DRAM and IRAM sections. */ ++ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset); ++ if (ret) { ++ phydev_err(phydev, "bad primary offset in firmware\n"); ++ return ret; ++ } ++ primary_offset = PRIMARY_OFFSET(read_primary_offset); ++ ++ /* Find the DRAM and IRAM sections within the firmware file. ++ * Make sure the fw_header is correctly in the firmware. ++ */ ++ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET, ++ sizeof(struct aqr_fw_header))) { ++ phydev_err(phydev, "bad fw_header in firmware\n"); ++ return -EINVAL; ++ } ++ ++ /* offset are in LE and values needs to be converted to cpu endian */ ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_offset), ++ size, &iram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad iram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_size), ++ size, &iram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid iram size in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_offset), ++ size, &dram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad dram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_size), ++ size, &dram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid dram size in firmware\n"); ++ return ret; ++ } ++ ++ /* Increment the offset with the primary offset. ++ * Validate iram/dram offset and size. ++ */ ++ iram_offset += primary_offset; ++ if (iram_size % sizeof(u32)) { ++ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ dram_offset += primary_offset; ++ if (dram_size % sizeof(u32)) { ++ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n", ++ primary_offset, iram_offset, iram_size, dram_offset, dram_size); ++ ++ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE)) { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE); ++ if (version[0] == '\0') { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version, ++ aqr_fw_src_string[fw_src]); ++ ++ /* stall the microcprocessor */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n", ++ DRAM_BASE_ADDR, dram_offset, dram_size); ++ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset, ++ dram_size); ++ if (ret) ++ return ret; ++ ++ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n", ++ IRAM_BASE_ADDR, iram_offset, iram_size); ++ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset, ++ iram_size); ++ if (ret) ++ return ret; ++ ++ /* make sure soft reset and low power mode are clear */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC, ++ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER); ++ ++ /* Release the microprocessor. UP_RESET must be held for 100 usec. */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST); ++ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ return 0; ++} ++ ++static int aqr_firmware_load_nvmem(struct phy_device *phydev) ++{ ++ struct nvmem_cell *cell; ++ size_t size; ++ u8 *buf; ++ int ret; ++ ++ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ buf = nvmem_cell_read(cell, &size); ++ if (IS_ERR(buf)) { ++ ret = PTR_ERR(buf); ++ goto exit; ++ } ++ ++ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ kfree(buf); ++exit: ++ nvmem_cell_put(cell); ++ ++ return ret; ++} ++ ++static int aqr_firmware_load_fs(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw; ++ const char *fw_name; ++ int ret; ++ ++ ret = of_property_read_string(dev->of_node, "firmware-name", ++ &fw_name); ++ if (ret) ++ return ret; ++ ++ ret = request_firmware(&fw, fw_name, dev); ++ if (ret) { ++ phydev_err(phydev, "failed to find FW file %s (%d)\n", ++ fw_name, ret); ++ return ret; ++ } ++ ++ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++int aqr_firmware_load(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check if the firmware is not already loaded by pooling ++ * the current version returned by the PHY. If 0 is returned, ++ * no firmware is loaded. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (ret > 0) ++ goto exit; ++ ++ ret = aqr_firmware_load_nvmem(phydev); ++ if (!ret) ++ goto exit; ++ ++ ret = aqr_firmware_load_fs(phydev); ++ if (ret) ++ return ret; ++ ++exit: ++ return 0; ++} +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -656,11 +656,17 @@ static int aqr107_resume(struct phy_devi + + static int aqr107_probe(struct phy_device *phydev) + { ++ int ret; ++ + phydev->priv = devm_kzalloc(&phydev->mdio.dev, + sizeof(struct aqr107_priv), GFP_KERNEL); + if (!phydev->priv) + return -ENOMEM; + ++ ret = aqr_firmware_load(phydev); ++ if (ret) ++ return ret; ++ + return aqr_hwmon_probe(phydev); + } + diff --git a/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch new file mode 100644 index 0000000000..ff186742ba --- /dev/null +++ b/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch @@ -0,0 +1,326 @@ +From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 9 Jan 2023 16:30:41 +0100 +Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers + +Currently C22 and C45 transactions are mixed over a combined API calls +which make use of a special bit in the reg address to indicate if a +C45 transaction should be performed. This makes it impossible to know +if the bus driver actually supports C45. Additionally, many C22 only +drivers don't return -EOPNOTSUPP when asked to perform a C45 +transaction, they mistaking perform a C22 transaction. + +This is the first step to cleanly separate C22 from C45. To maintain +backwards compatibility until all drivers which are capable of +performing C45 are converted to this new API, the helper functions +will fall back to the older API if the new API is not +supported. Eventually this fallback will be removed. + +Signed-off-by: Andrew Lunn +Signed-off-by: Michael Walle +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ + include/linux/mdio.h | 39 ++++---- + include/linux/phy.h | 5 + + 3 files changed, 214 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ + EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); + + /** ++ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * Read a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->read_c45) ++ retval = bus->read_c45(bus, addr, devad, regnum); ++ else ++ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); ++ ++ trace_mdio_access(bus, 1, addr, regnum, retval, retval); ++ mdiobus_stats_acct(&bus->stats[addr], true, retval); ++ ++ return retval; ++} ++EXPORT_SYMBOL(__mdiobus_c45_read); ++ ++/** ++ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * Write a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->write_c45) ++ err = bus->write_c45(bus, addr, devad, regnum, val); ++ else ++ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), ++ val); ++ ++ trace_mdio_access(bus, 0, addr, regnum, val, err); ++ mdiobus_stats_acct(&bus->stats[addr], false, err); ++ ++ return err; ++} ++EXPORT_SYMBOL(__mdiobus_c45_write); ++ ++/** ++ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to modify ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Read, modify, and if any change, write the register value back to the ++ * device. Any error returns a negative number. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, ++ int devad, u32 regnum, u16 mask, ++ u16 set) ++{ ++ int new, ret; ++ ++ ret = __mdiobus_c45_read(bus, addr, devad, regnum); ++ if (ret < 0) ++ return ret; ++ ++ new = (ret & ~mask) | set; ++ if (new == ret) ++ return 0; ++ ++ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); ++ ++ return ret < 0 ? ret : 1; ++} ++ ++/** + * mdiobus_read_nested - Nested version of the mdiobus_read function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in + EXPORT_SYMBOL(mdiobus_read); + + /** ++ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ mutex_lock(&bus->mdio_lock); ++ retval = __mdiobus_c45_read(bus, addr, devad, regnum); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return retval; ++} ++EXPORT_SYMBOL(mdiobus_c45_read); ++ ++/** + * mdiobus_write_nested - Nested version of the mdiobus_write function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i + EXPORT_SYMBOL(mdiobus_write); + + /** ++ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(mdiobus_c45_write); ++ ++/** + * mdiobus_modify - Convenience function for modifying a given mdio device + * register + * @bus: the mii_bus struct +@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, + EXPORT_SYMBOL_GPL(mdiobus_modify); + + /** ++ * mdiobus_c45_modify - Convenience function for modifying a given mdio device ++ * register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, ++ mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err < 0 ? err : 0; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify); ++ ++/** + * mdiobus_modify_changed - Convenience function for modifying a given mdio + * device register and returning if it changed + * @bus: the mii_bus struct +@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu + EXPORT_SYMBOL_GPL(mdiobus_modify_changed); + + /** ++ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio ++ * device register and returning if it changed ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, ++ u32 regnum, u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); ++ ++/** + * mdio_bus_match - determine if given MDIO driver supports the given + * MDIO device + * @dev: target MDIO device +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, + u16 set); + int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, + u16 mask, u16 set); ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set); ++ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, ++ u32 regnum, u16 mask, u16 set); + + static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) + { +@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 + return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); + } + +-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) +-{ +- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); +-} +- +-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) +-{ +- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), +- val); +-} +- +-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) ++static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, ++ u32 regnum, u16 mask, u16 set) + { +- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); ++ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, ++ mask, set); + } + +-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) ++static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, ++ int devad, u32 regnum, u16 mask, ++ u16 set) + { +- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); ++ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, ++ regnum, mask, set); + } + + int mdiobus_register_device(struct mdio_device *mdiodev); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -364,6 +364,11 @@ struct mii_bus { + int (*read)(struct mii_bus *bus, int addr, int regnum); + /** @write: Perform a write transfer on the bus */ + int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); ++ /** @read_c45: Perform a C45 read transfer on the bus */ ++ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); ++ /** @write_c45: Perform a C45 write transfer on the bus */ ++ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, ++ int regnum, u16 val); + /** @reset: Perform a reset of the bus */ + int (*reset)(struct mii_bus *bus); + diff --git a/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch new file mode 100644 index 0000000000..80210e6da1 --- /dev/null +++ b/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch @@ -0,0 +1,105 @@ +From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 11 Aug 2023 13:10:07 +0200 +Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode + +The PSGMII interface is similar to QSGMII. The main difference +is that the PSGMII interface combines five SGMII lines into a +single link while in QSGMII only four lines are combined. + +Similarly to the QSGMII, this interface mode might also needs +special handling within the MAC driver. + +It is commonly used by Qualcomm with their QCA807x PHY series and +modern WiSoC-s. + +Add definitions for the PHY layer to allow to express this type +of connection between the MAC and PHY. + +Signed-off-by: Gabor Juhos +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 4 ++++ + drivers/net/phy/phy-core.c | 2 ++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 4 files changed, 13 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -323,6 +323,10 @@ Some of the interface modes are describe + contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this + interface mode has different autonegotiation and only supports full duplex. + ++``PHY_INTERFACE_MODE_PSGMII`` ++ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 ++ SGMII lines into a single link compared to 4 on QSGMII. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + return 4; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return 5; + case PHY_INTERFACE_MODE_MAX: + WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); + return 0; +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy + + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_RGMII: +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface + * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax ++ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII + * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX +@@ -140,6 +141,7 @@ typedef enum { + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_PSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, +@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return "psgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch new file mode 100644 index 0000000000..7cacb71b18 --- /dev/null +++ b/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch @@ -0,0 +1,32 @@ +From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 16 Mar 2023 14:08:26 +0200 +Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used + +of_gpio.h in this driver is solely used as a proxy to other headers. +This is incorrect usage of the of_gpio.h. Replace it .h with what +indeed is used in the code. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -13,12 +13,11 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include ++#include + #include + #include + #include diff --git a/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch new file mode 100644 index 0000000000..dab4928960 --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch @@ -0,0 +1,70 @@ +From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:19 +0800 +Subject: [PATCH 1/6] net: phy: at803x: support qca8081 + genphy_c45_pma_read_abilities + +qca8081 PHY supports to use genphy_c45_pma_read_abilities for +getting the PHY features supported except for the autoneg ability + +but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it +manually after calling genphy_c45_pma_read_abilities. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph + if (err) + return err; + +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); +- if (err < 0) +- return err; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, +- err & MDIO_PMA_NG_EXTABLE_2_5GBT); +- } +- + if (phydev->drv->phy_id != ATH8031_PHY_ID) + return 0; + +@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status + return 0; + } + ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] + .set_tunable = at803x_set_tunable, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, +- .get_features = at803x_get_features, ++ .get_features = qca808x_get_features, + .config_aneg = at803x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, diff --git a/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch new file mode 100644 index 0000000000..28874068ce --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch @@ -0,0 +1,73 @@ +From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:20 +0800 +Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function + +merge the seed enablement and seed value configuration into +one function, since the random seed value is needed to be +configured when the seed is enabled. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf + return 0; + } + +-static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) +-{ +- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); +-} +- + static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) + { +- u16 seed_enable = 0; ++ u16 seed_value; + +- if (enable) +- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + + static int qca808x_config_init(struct phy_device *phydev) +@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_random_seed_set(phydev); +- if (ret) +- return ret; +- +- /* Enable seed */ ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; +@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { +- qca808x_phy_ms_random_seed_set(phydev); + qca808x_phy_ms_seed_enable(phydev, true); + } + } diff --git a/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch new file mode 100644 index 0000000000..b91d2cab30 --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch @@ -0,0 +1,76 @@ +From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:21 +0800 +Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally + +qca8081 is the single port PHY, the slave prefer mode is used +by default. + +if the phy master perfer mode is configured, the slave seed +configuration should not be enabled, since the slave seed +enablement is for making PHY linked as slave mode easily. + +disable slave seed if the master mode is preferred. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st + QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) + return ret; + ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); +@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph + phydev->interface = PHY_INTERFACE_MODE_SGMII; + } else { + /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected. ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * + * the reason for not putting this code into the function link_change_notify is + * the corner case where the link partner is also the qca8081 PHY and the seed + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); diff --git a/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch new file mode 100644 index 0000000000..b8db89d853 --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch @@ -0,0 +1,48 @@ +From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:22 +0800 +Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type + +The qca8081 1G chip version does not support 2.5 capability, which +is distinguished from qca8081 2.5G chip according to the bit0 of +register mmd7.0x901d, the 1G version chip also has the same PHY ID +as the normal qca8081 2.5G chip. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -272,6 +272,10 @@ + #define QCA808X_CDT_STATUS_STAT_OPEN 2 + #define QCA808X_CDT_STATUS_STAT_SHORT 3 + ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch new file mode 100644 index 0000000000..b54a86e5f5 --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch @@ -0,0 +1,98 @@ +From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:23 +0800 +Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and + slave seed config + +The fast retrain and slave seed configs are only applicable when the 2.5G +ability is supported. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str + (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); + } + ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); + if (ret) + return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } + } + + /* Configure adc threshold as 100mv for the link 10M */ +@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } + } + } + +@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy + if (ret < 0) + return ret; + +- return qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; + } + + static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch new file mode 100644 index 0000000000..e382cf7876 --- /dev/null +++ b/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch @@ -0,0 +1,55 @@ +From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:24 +0800 +Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link + changed + +The qca8081 sgmii fifo needs to be reset on link down and +released on the link up in case of any abnormal issue +such as the packet blocked on the PHY. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -276,6 +276,9 @@ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) + ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p + return 0; + } + ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] + .soft_reset = qca808x_soft_reset, + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.6/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch b/target/linux/generic/backport-6.6/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch new file mode 100644 index 0000000000..eb9172b1cc --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch @@ -0,0 +1,69 @@ +From 6a3b8c573b5a152a6aa7a0b54c5e18b84c6ba6f5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:49 +0100 +Subject: [PATCH 02/13] net: phy: at803x: move disable WOL to specific at8031 + probe + +Move the WOL disable call to specific at8031 probe to make at803x_probe +more generic and drop extra check for PHY ID. + +Keep the same previous behaviour by first calling at803x_probe and then +disabling WOL. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -886,15 +886,6 @@ static int at803x_probe(struct phy_devic + priv->is_fiber = true; + break; + } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; + } + + return 0; +@@ -1591,6 +1582,22 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2092,7 +2099,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8031_probe, + .config_init = at803x_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, diff --git a/target/linux/generic/backport-6.6/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch b/target/linux/generic/backport-6.6/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch new file mode 100644 index 0000000000..5a9d1764f1 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch @@ -0,0 +1,129 @@ +From 07b1ad83b9ed6db1735ba10baf67b7a565ac0cef Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:50 +0100 +Subject: [PATCH 03/13] net: phy: at803x: raname hw_stats functions to qca83xx + specific name + +The function and the struct related to hw_stats were specific to qca83xx +PHY but were called following the convention in the driver of calling +everything with at803x prefix. + +To better organize the code, rename these function a more specific name +to better describe that they are specific to 83xx PHY family. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 44 ++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -295,7 +295,7 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + +-static struct at803x_hw_stat at803x_hw_stats[] = { ++static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +@@ -311,7 +311,7 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(at803x_hw_stats)]; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + }; + + struct at803x_context { +@@ -529,24 +529,24 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int at803x_get_sset_count(struct phy_device *phydev) ++static int qca83xx_get_sset_count(struct phy_device *phydev) + { +- return ARRAY_SIZE(at803x_hw_stats); ++ return ARRAY_SIZE(qca83xx_hw_stats); + } + +-static void at803x_get_strings(struct phy_device *phydev, u8 *data) ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { + strscpy(data + i * ETH_GSTRING_LEN, +- at803x_hw_stats[i].string, ETH_GSTRING_LEN); ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); + } + } + +-static u64 at803x_get_stat(struct phy_device *phydev, int i) ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) + { +- struct at803x_hw_stat stat = at803x_hw_stats[i]; ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; + struct at803x_priv *priv = phydev->priv; + int val; + u64 ret; +@@ -567,13 +567,13 @@ static u64 at803x_get_stat(struct phy_de + return ret; + } + +-static void at803x_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) +- data[i] = at803x_get_stat(phydev, i); ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); + } + + static int at803x_suspend(struct phy_device *phydev) +@@ -2175,9 +2175,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2191,9 +2191,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2207,9 +2207,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { diff --git a/target/linux/generic/backport-6.6/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch b/target/linux/generic/backport-6.6/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch new file mode 100644 index 0000000000..f09142c5ed --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch @@ -0,0 +1,155 @@ +From d43cff3f82336c0bd965ea552232d9f4ddac71a6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:51 +0100 +Subject: [PATCH 04/13] net: phy: at803x: move qca83xx specific check in + dedicated functions + +Rework qca83xx specific check to dedicated function to tidy things up +and drop useless phy_id check. + +Also drop an useless link_change_notify for QCA8337 as it did nothing an +returned early. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 68 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1623,27 +1623,26 @@ static int qca83xx_config_init(struct ph + break; + } + ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ + /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. + * Disable on init and enable only with 100m speed following + * qca original source code. + */ +- if (phydev->drv->phy_id == QCA8327_A_PHY_ID || +- phydev->drv->phy_id == QCA8327_B_PHY_ID) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); + +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; ++ return qca83xx_config_init(phydev); + } + + static void qca83xx_link_change_notify(struct phy_device *phydev) + { +- /* QCA8337 doesn't require DAC Amplitude adjustement */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) +- return; +- + /* Set DAC Amplitude adjustment to +6% for 100m on link running */ + if (phydev->state == PHY_RUNNING) { + if (phydev->speed == SPEED_100) +@@ -1686,19 +1685,6 @@ static int qca83xx_resume(struct phy_dev + + static int qca83xx_suspend(struct phy_device *phydev) + { +- u16 mask = 0; +- +- /* Only QCA8337 support actual suspend. +- * QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) { +- genphy_suspend(phydev); +- } else { +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- } +- + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, + AT803X_DEBUG_GATE_CLK_IN1000, 0); + +@@ -1709,6 +1695,27 @@ static int qca83xx_suspend(struct phy_de + return 0; + } + ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2170,7 +2177,6 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -2178,7 +2184,7 @@ static struct phy_driver at803x_driver[] + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8337_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ +@@ -2189,12 +2195,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ +@@ -2205,12 +2211,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* Qualcomm QCA8081 */ diff --git a/target/linux/generic/backport-6.6/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch b/target/linux/generic/backport-6.6/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch new file mode 100644 index 0000000000..a5cc67a8c8 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch @@ -0,0 +1,94 @@ +From 900eef75cc5018e149c52fe305c9c3fe424c52a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:52 +0100 +Subject: [PATCH 05/13] net: phy: at803x: move specific DT option for at8031 to + specific probe + +Move specific DT options for at8031 to specific probe to tidy things up +and make at803x_parse_dt more generic. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 55 ++++++++++++++++++++++------------------ + 1 file changed, 31 insertions(+), 24 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -825,30 +825,6 @@ static int at803x_parse_dt(struct phy_de + } + } + +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- ret = phy_sfp_probe(phydev, &at803x_sfp_ops); +- if (ret < 0) +- return ret; +- } +- + return 0; + } + +@@ -1582,6 +1558,30 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at803x_sfp_ops); ++} ++ + static int at8031_probe(struct phy_device *phydev) + { + int ret; +@@ -1590,6 +1590,13 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.6/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch b/target/linux/generic/backport-6.6/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch new file mode 100644 index 0000000000..9e10e000e5 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch @@ -0,0 +1,78 @@ +From 25d2ba94005fac18fe68878cddff59a67e115554 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:53 +0100 +Subject: [PATCH 06/13] net: phy: at803x: move specific at8031 probe mode check + to dedicated probe + +Move specific at8031 probe mode check to dedicated probe to make +at803x_probe more generic and keep code tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -844,26 +844,6 @@ static int at803x_probe(struct phy_devic + if (ret) + return ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- int mode_cfg; +- +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- } +- + return 0; + } + +@@ -1584,6 +1564,9 @@ static int at8031_parse_dt(struct phy_de + + static int at8031_probe(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; + int ret; + + ret = at803x_probe(phydev); +@@ -1597,6 +1580,22 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.6/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch b/target/linux/generic/backport-6.6/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch new file mode 100644 index 0000000000..c9ef6df827 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch @@ -0,0 +1,86 @@ +From 3ae3bc426eaf57ca8f53d75777d9a5ef779bc7b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:54 +0100 +Subject: [PATCH 07/13] net: phy: at803x: move specific at8031 config_init to + dedicated function + +Move specific at8031 config_init to dedicated function to make +at803x_config_init more generic and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 45 ++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -951,27 +951,8 @@ static int at803x_hibernation_mode_confi + + static int at803x_config_init(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- } +- + /* The RX and TX delay default is: + * after HW reset: RX delay enabled and TX delay disabled + * after SW reset: RX delay enabled, while TX delay retains the +@@ -1604,6 +1585,30 @@ static int at8031_probe(struct phy_devic + AT803X_WOL_EN, 0); + } + ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2113,7 +2118,7 @@ static struct phy_driver at803x_driver[] + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, + .probe = at8031_probe, +- .config_init = at803x_config_init, ++ .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.6/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch b/target/linux/generic/backport-6.6/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch new file mode 100644 index 0000000000..6746a4d43c --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch @@ -0,0 +1,92 @@ +From 27b89c9dc1b0393090d68d651b82f30ad2696baa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:55 +0100 +Subject: [PATCH 08/13] net: phy: at803x: move specific at8031 WOL bits to + dedicated function + +Move specific at8031 WOL enable/disable to dedicated function to make +at803x_set_wol more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to toggle WOL settings. + +In this new implementation WOL module in at8031 is enabled after the +generic interrupt is setup. This should not cause any problem as the +WOL_INT has a separate implementation and only relay on MAC bits. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 42 ++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -466,27 +466,11 @@ static int at803x_set_wol(struct phy_dev + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + +- /* Enable WOL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- if (ret) +- return ret; +- } + /* Enable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); + if (ret) + return ret; + } else { +- /* Disable WoL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; +- } + /* Disable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); + if (ret) +@@ -1609,6 +1593,30 @@ static int at8031_config_init(struct phy + return at803x_config_init(phydev); + } + ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2121,7 +2129,7 @@ static struct phy_driver at803x_driver[] + .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, ++ .set_wol = at8031_set_wol, + .get_wol = at803x_get_wol, + .suspend = at803x_suspend, + .resume = at803x_resume, diff --git a/target/linux/generic/backport-6.6/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch b/target/linux/generic/backport-6.6/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch new file mode 100644 index 0000000000..0d284c3d24 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch @@ -0,0 +1,78 @@ +From 30dd62191d3dd97c08f7f9dc9ce77ffab457e4fb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:56 +0100 +Subject: [PATCH 09/13] net: phy: at803x: move specific at8031 config_intr to + dedicated function + +Move specific at8031 config_intr bits to dedicated function to make +at803x_config_initr more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to setup interrupts. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -990,7 +990,6 @@ static int at803x_ack_interrupt(struct p + + static int at803x_config_intr(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int err; + int value; + +@@ -1007,10 +1006,6 @@ static int at803x_config_intr(struct phy + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; + value |= AT803X_INTR_ENABLE_LINK_FAIL; + value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- if (priv->is_fiber) { +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- } + + err = phy_write(phydev, AT803X_INTR_ENABLE, value); + } else { +@@ -1617,6 +1612,29 @@ static int at8031_set_wol(struct phy_dev + return ret; + } + ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2137,7 +2155,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, ++ .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, diff --git a/target/linux/generic/backport-6.6/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch b/target/linux/generic/backport-6.6/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch new file mode 100644 index 0000000000..210949ea81 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch @@ -0,0 +1,78 @@ +From a5ab9d8e7ae0da8328ac1637a9755311508dc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:57 +0100 +Subject: [PATCH 10/13] net: phy: at803x: make at8031 related DT functions name + more specific + +Rename at8031 related DT function name to a more specific name +referencing they are only related to at8031 and not to the generic +at803x PHY family. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,7 +583,7 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); +@@ -596,7 +596,7 @@ static int at803x_rgmii_reg_set_voltage_ + AT803X_DEBUG_RGMII_1V8, 0); + } + +-static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); + int val; +@@ -610,8 +610,8 @@ static int at803x_rgmii_reg_get_voltage_ + + static const struct regulator_ops vddio_regulator_ops = { + .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, + }; + + static const unsigned int vddio_voltage_table[] = { +@@ -666,7 +666,7 @@ static int at8031_register_regulators(st + return 0; + } + +-static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) + { + struct phy_device *phydev = upstream; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +@@ -710,10 +710,10 @@ static int at803x_sfp_insert(void *upstr + return 0; + } + +-static const struct sfp_upstream_ops at803x_sfp_ops = { ++static const struct sfp_upstream_ops at8031_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, +- .module_insert = at803x_sfp_insert, ++ .module_insert = at8031_sfp_insert, + }; + + static int at803x_parse_dt(struct phy_device *phydev) +@@ -1519,7 +1519,7 @@ static int at8031_parse_dt(struct phy_de + } + + /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at803x_sfp_ops); ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); + } + + static int at8031_probe(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.6/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch b/target/linux/generic/backport-6.6/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch new file mode 100644 index 0000000000..5856b59751 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch @@ -0,0 +1,297 @@ +From f932a6dc8bae0dae9645b5b1b4c65aed8a8acb2a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:58 +0100 +Subject: [PATCH 11/13] net: phy: at803x: move at8031 functions in dedicated + section + +Move at8031 functions in dedicated section with dedicated at8031 +parse_dt and probe. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 266 +++++++++++++++++++-------------------- + 1 file changed, 133 insertions(+), 133 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,139 +583,6 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- + static int at803x_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; +@@ -1498,6 +1365,139 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ + static int at8031_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; diff --git a/target/linux/generic/backport-6.6/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch b/target/linux/generic/backport-6.6/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch new file mode 100644 index 0000000000..0a822c6d37 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch @@ -0,0 +1,114 @@ +From 21a2802a8365cfa82cc02187c1f95136d85592ad Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:59 +0100 +Subject: [PATCH 12/13] net: phy: at803x: move at8035 specific DT parse to + dedicated probe + +Move at8035 specific DT parse for clock out frequency to dedicated probe +to make at803x probe function more generic. + +This is to tidy code and no behaviour change are intended. + +Detection logic is changed, we check if the clk 25m mask is set and if +it's not zero, we assume the qca,clk-out-frequency property is set. + +The property is checked in the generic at803x_parse_dt called by +at803x_probe. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 60 +++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -638,23 +638,6 @@ static int at803x_parse_dt(struct phy_de + + priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); + priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- if (phydev->drv->phy_id == ATH8030_PHY_ID || +- phydev->drv->phy_id == ATH8035_PHY_ID) { +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } + } + + ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +@@ -1635,6 +1618,45 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2107,7 +2129,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), + .name = "Qualcomm Atheros AR8035", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_aneg = at803x_config_aneg, + .config_init = at803x_config_init, + .soft_reset = genphy_soft_reset, +@@ -2128,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .phy_id = ATH8030_PHY_ID, + .name = "Qualcomm Atheros AR8030", + .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_init = at803x_config_init, + .link_change_notify = at803x_link_change_notify, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.6/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch b/target/linux/generic/backport-6.6/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch new file mode 100644 index 0000000000..e1ba6ec2d0 --- /dev/null +++ b/target/linux/generic/backport-6.6/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch @@ -0,0 +1,219 @@ +From ef9df47b449e32e06501a11272809be49019bdb6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:52:00 +0100 +Subject: [PATCH 13/13] net: phy: at803x: drop specific PHY ID check from cable + test functions + +Drop specific PHY ID check for cable test functions for at803x. This is +done to make functions more generic. While at it better describe what +the functions does by using more symbolic function names. + +PHYs that requires to set additional reg are moved to specific function +calling the more generic one. + +cdt_start and cdt_wait_for_completion are changed to take an additional +arg to pass specific values specific to the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 95 +++++++++++++++++++++------------------- + 1 file changed, 50 insertions(+), 45 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1222,31 +1222,16 @@ static int at803x_cdt_fault_length(u16 s + return (dt * 824) / 10; + } + +-static int at803x_cdt_start(struct phy_device *phydev, int pair) ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) + { +- u16 cdt; +- +- /* qca8081 takes the different bit 15 to enable CDT test */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; +- else +- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- +- return phy_write(phydev, AT803X_CDT, cdt); ++ return phy_write(phydev, AT803X_CDT, cdt_start); + } + +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev) ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) + { + int val, ret; +- u16 cdt_en; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt_en = QCA808X_CDT_ENABLE_TEST; +- else +- cdt_en = AT803X_CDT_ENABLE_TEST; + + /* One test run takes about 25ms */ + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +@@ -1266,11 +1251,13 @@ static int at803x_cable_test_one_pair(st + }; + int ret, val; + +- ret = at803x_cdt_start(phydev, pair); ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -1292,19 +1279,11 @@ static int at803x_cable_test_one_pair(st + } + + static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished) ++ bool *finished, unsigned long pair_mask) + { +- unsigned long pair_mask; + int retries = 20; + int pair, ret; + +- if (phydev->phy_id == ATH9331_PHY_ID || +- phydev->phy_id == ATH8032_PHY_ID || +- phydev->phy_id == QCA9561_PHY_ID) +- pair_mask = 0x3; +- else +- pair_mask = 0xf; +- + *finished = false; + + /* According to the datasheet the CDT can be performed when +@@ -1331,7 +1310,7 @@ static int at803x_cable_test_get_status( + return 0; + } + +-static int at803x_cable_test_start(struct phy_device *phydev) ++static void at803x_cable_test_autoneg(struct phy_device *phydev) + { + /* Enable auto-negotiation, but advertise no capabilities, no link + * will be established. A restart of the auto-negotiation is not +@@ -1339,11 +1318,11 @@ static int at803x_cable_test_start(struc + */ + phy_write(phydev, MII_BMCR, BMCR_ANENABLE); + phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +- if (phydev->phy_id != ATH9331_PHY_ID && +- phydev->phy_id != ATH8032_PHY_ID && +- phydev->phy_id != QCA9561_PHY_ID) +- phy_write(phydev, MII_CTRL1000, 0); ++} + ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); + /* we do all the (time consuming) work later */ + return 0; + } +@@ -1618,6 +1597,29 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ + static int at8035_parse_dt(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -2041,11 +2043,14 @@ static int qca808x_cable_test_get_status + + *finished = false; + +- ret = at803x_cdt_start(phydev, 0); ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT | ++ QCA808X_CDT_INTER_CHECK_DIS; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -2143,8 +2148,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8030 */ + .phy_id = ATH8030_PHY_ID, +@@ -2181,8 +2186,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8032 */ + PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +@@ -2197,7 +2202,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + }, { + /* ATHEROS AR9331 */ + PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +@@ -2210,7 +2215,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +@@ -2226,7 +2231,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, diff --git a/target/linux/generic/backport-6.6/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch b/target/linux/generic/backport-6.6/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch new file mode 100644 index 0000000000..0bb3673c02 --- /dev/null +++ b/target/linux/generic/backport-6.6/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch @@ -0,0 +1,116 @@ +From 8e732f1c6f2dc5e18f766d0f1b11df9db2dd044a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:31 +0100 +Subject: [PATCH 1/2] net: phy: at803x: move specific qca808x config_aneg to + dedicated function + +Move specific qca808x config_aneg to dedicated function to permit easier +split of qca808x portion from at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 66 ++++++++++++++++++++++++---------------- + 1 file changed, 40 insertions(+), 26 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1045,9 +1045,8 @@ static int at803x_config_mdix(struct phy + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); + } + +-static int at803x_config_aneg(struct phy_device *phydev) ++static int at803x_prepare_config_aneg(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +@@ -1064,33 +1063,22 @@ static int at803x_config_aneg(struct phy + return ret; + } + +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- /* Do not restart auto-negotiation by setting ret to 0 defautly, +- * when calling __genphy_config_aneg later. +- */ +- ret = 0; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- int phy_ctrl = 0; ++ return 0; ++} + +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; + +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; + +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- } ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); + +- return __genphy_config_aneg(phydev, ret); ++ return genphy_config_aneg(phydev); + } + + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +@@ -2118,6 +2106,32 @@ static int qca808x_get_features(struct p + return 0; + } + ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ + static void qca808x_link_change_notify(struct phy_device *phydev) + { + /* Assert interface sgmii fifo on link down, deassert it on link up, +@@ -2295,7 +2309,7 @@ static struct phy_driver at803x_driver[] + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .get_features = qca808x_get_features, +- .config_aneg = at803x_config_aneg, ++ .config_aneg = qca808x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_status = qca808x_read_status, diff --git a/target/linux/generic/backport-6.6/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch b/target/linux/generic/backport-6.6/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch new file mode 100644 index 0000000000..54ca3bdfc8 --- /dev/null +++ b/target/linux/generic/backport-6.6/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch @@ -0,0 +1,97 @@ +From 38eb804e8458ba181a03a0498ce4bf84eebd1931 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:32 +0100 +Subject: [PATCH 2/2] net: phy: at803x: make read specific status function more + generic + +Rework read specific status function to be more generic. The function +apply different speed mask based on the PHY ID. Make it more generic by +adding an additional arg to pass the specific speed (ss) mask and use +the provided mask to parse the speed value. + +This is needed to permit an easier deatch of qca808x code from the +at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,11 @@ static struct at803x_hw_stat qca83xx_hw_ + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -921,7 +926,8 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev) ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) + { + int ss; + +@@ -940,11 +946,8 @@ static int at803x_read_specific_status(s + if (sfc < 0) + return sfc; + +- /* qca8081 takes the different bits for speed value from at803x */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss); +- else +- speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss); ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; + + switch (speed) { + case AT803X_SS_SPEED_10: +@@ -989,6 +992,7 @@ static int at803x_read_specific_status(s + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + + if (priv->is_1000basex) +@@ -1012,7 +1016,9 @@ static int at803x_read_status(struct phy + if (err < 0) + return err; + +- err = at803x_read_specific_status(phydev); ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); + if (err < 0) + return err; + +@@ -1869,6 +1875,7 @@ static int qca808x_config_init(struct ph + + static int qca808x_read_status(struct phy_device *phydev) + { ++ struct at803x_ss_mask ss_mask = { 0 }; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +@@ -1882,7 +1889,10 @@ static int qca808x_read_status(struct ph + if (ret) + return ret; + +- ret = at803x_read_specific_status(phydev); ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); + if (ret < 0) + return ret; + diff --git a/target/linux/generic/backport-6.6/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch b/target/linux/generic/backport-6.6/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch new file mode 100644 index 0000000000..8097a33e49 --- /dev/null +++ b/target/linux/generic/backport-6.6/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch @@ -0,0 +1,27 @@ +From fc9d7264ddc32eaa647d6bfcdc25cdf9f786fde0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:27:39 +0100 +Subject: [PATCH 1/2] net: phy: at803x: remove extra space after cast + +Remove extra space after cast as reported by checkpatch to keep code +clean. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232739.27065-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -462,7 +462,7 @@ static int at803x_set_wol(struct phy_dev + if (!ndev) + return -ENODEV; + +- mac = (const u8 *) ndev->dev_addr; ++ mac = (const u8 *)ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return -EINVAL; diff --git a/target/linux/generic/backport-6.6/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch b/target/linux/generic/backport-6.6/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch new file mode 100644 index 0000000000..b8d4591087 --- /dev/null +++ b/target/linux/generic/backport-6.6/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch @@ -0,0 +1,38 @@ +From 3ab5720881a924fb6405d9e6a3b09f1026467c47 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:25:08 +0100 +Subject: [PATCH 2/2] net: phy: at803x: replace msleep(1) with usleep_range + +Replace msleep(1) with usleep_range as suggested by timers-howto guide. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232508.26470-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -916,9 +916,9 @@ static void at803x_link_change_notify(st + at803x_context_save(phydev, &context); + + phy_device_reset(phydev, 1); +- msleep(1); ++ usleep_range(1000, 2000); + phy_device_reset(phydev, 0); +- msleep(1); ++ usleep_range(1000, 2000); + + at803x_context_restore(phydev, &context); + +@@ -1733,7 +1733,7 @@ static int qca83xx_resume(struct phy_dev + if (ret) + return ret; + +- msleep(1); ++ usleep_range(1000, 2000); + + return 0; + } diff --git a/target/linux/generic/backport-6.6/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch b/target/linux/generic/backport-6.6/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch new file mode 100644 index 0000000000..776b7bb43f --- /dev/null +++ b/target/linux/generic/backport-6.6/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch @@ -0,0 +1,152 @@ +From 7961ef1fa10ec35ad6923fb5751877116e4b035b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 19 Dec 2023 21:21:24 +0100 +Subject: [PATCH] net: phy: at803x: better align function varibles to open + parenthesis + +Better align function variables to open parenthesis as suggested by +checkpatch script for qca808x function to make code cleaner. + +For cable_test_get_status function some additional rework was needed to +handle too long functions. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 67 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 30 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1781,27 +1781,27 @@ static int qca808x_phy_fast_retrain_conf + return ret; + + phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); ++ QCA808X_TOP_OPTION1_DATA); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); ++ QCA808X_MMD3_DEBUG_1_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); ++ QCA808X_MMD3_DEBUG_4_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); ++ QCA808X_MMD3_DEBUG_5_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); ++ QCA808X_MMD3_DEBUG_3_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); ++ QCA808X_MMD3_DEBUG_6_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); ++ QCA808X_MMD3_DEBUG_2_VALUE); + + return 0; + } +@@ -1838,13 +1838,14 @@ static int qca808x_config_init(struct ph + + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); + if (ret) + return ret; + + /* Adjust the threshold on 802.3az for the link 1000M */ + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL); ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); + if (ret) + return ret; + +@@ -1870,7 +1871,8 @@ static int qca808x_config_init(struct ph + + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); + } + + static int qca808x_read_status(struct phy_device *phydev) +@@ -1883,7 +1885,7 @@ static int qca808x_read_status(struct ph + return ret; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); + + ret = genphy_read_status(phydev); + if (ret) +@@ -1913,7 +1915,7 @@ static int qca808x_read_status(struct ph + */ + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); +@@ -2070,18 +2072,22 @@ static int qca808x_cable_test_get_status + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cable_test_result_trans(pair_d)); + +- if (qca808x_cdt_fault_length_valid(pair_a)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A)); +- if (qca808x_cdt_fault_length_valid(pair_b)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B)); +- if (qca808x_cdt_fault_length_valid(pair_c)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C)); +- if (qca808x_cdt_fault_length_valid(pair_d)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D)); ++ if (qca808x_cdt_fault_length_valid(pair_a)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_b)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_c)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_d)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ } + + *finished = true; + +@@ -2148,8 +2154,9 @@ static void qca808x_link_change_notify(s + * the interface device address is always phy address added by 1. + */ + mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + + static struct phy_driver at803x_driver[] = { diff --git a/target/linux/generic/backport-6.6/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch b/target/linux/generic/backport-6.6/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch new file mode 100644 index 0000000000..d7196da46e --- /dev/null +++ b/target/linux/generic/backport-6.6/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch @@ -0,0 +1,62 @@ +From 22eb276098da820d9440fad22901f9b74ed4d659 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:38 +0100 +Subject: [PATCH 1/4] net: phy: at803x: generalize cdt fault length function + +Generalize cable test fault length function since they all base on the +same magic values (already reverse engineered to understand the meaning +of it) to have consistenct values on every PHY. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1192,10 +1192,8 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(u16 status) ++static int at803x_cdt_fault_length(int dt) + { +- int dt; +- + /* According to the datasheet the distance to the fault is + * DELTA_TIME * 0.824 meters. + * +@@ -1211,8 +1209,6 @@ static int at803x_cdt_fault_length(u16 s + * With a VF of 0.69 we get the factor 0.824 mentioned in the + * datasheet. + */ +- dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status); +- + return (dt * 824) / 10; + } + +@@ -1265,9 +1261,11 @@ static int at803x_cable_test_one_pair(st + ethnl_cable_test_result(phydev, ethtool_pair[pair], + at803x_cable_test_result_trans(val)); + +- if (at803x_cdt_fault_length_valid(val)) ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); + ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], + at803x_cdt_fault_length(val)); ++ } + + return 1; + } +@@ -1992,7 +1990,8 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10; ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ return at803x_cdt_fault_length(val); + } + + static int qca808x_cable_test_start(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.6/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch b/target/linux/generic/backport-6.6/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch new file mode 100644 index 0000000000..5d38fe7e91 --- /dev/null +++ b/target/linux/generic/backport-6.6/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch @@ -0,0 +1,118 @@ +From e0e9ada1df6133513249861c1d91c1dbefd9383b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:39 +0100 +Subject: [PATCH 2/4] net: phy: at803x: refactor qca808x cable test get status + function + +Refactor qca808x cable test get status function to remove code +duplication and clean things up. + +The same logic is applied to each pair hence it can be generalized and +moved to a common function. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 80 ++++++++++++++++++++++++---------------- + 1 file changed, 49 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2035,10 +2035,43 @@ static int qca808x_cable_test_start(stru + return 0; + } + ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ u16 pair_code; ++ int length; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ethnl_cable_test_result(phydev, pair, ++ qca808x_cable_test_result_trans(pair_code)); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ + static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) + { + int ret, val; +- int pair_a, pair_b, pair_c, pair_d; + + *finished = false; + +@@ -2057,36 +2090,21 @@ static int qca808x_cable_test_get_status + if (val < 0) + return val; + +- pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val); +- pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val); +- pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val); +- pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val); +- +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cable_test_result_trans(pair_a)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cable_test_result_trans(pair_b)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cable_test_result_trans(pair_c)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cable_test_result_trans(pair_d)); +- +- if (qca808x_cdt_fault_length_valid(pair_a)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_b)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_c)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_d)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- } ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; + + *finished = true; + diff --git a/target/linux/generic/backport-6.6/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch b/target/linux/generic/backport-6.6/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch new file mode 100644 index 0000000000..d5793860a9 --- /dev/null +++ b/target/linux/generic/backport-6.6/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch @@ -0,0 +1,182 @@ +From ea73e5ea442ee2aade67b1fb1233ccb3cbea2ceb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:40 +0100 +Subject: [PATCH 3/4] net: phy: at803x: add support for cdt cross short test + for qca808x + +QCA808x PHY Family supports Cable Diagnostic Test also for Cross Pair +Short. + +Add all the define to make enable and support these additional tests. + +Cross Short test was previously disabled by default, this is now changed +and enabled by default. In this mode, the mask changed a bit and length +is shifted based on the fault condition. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 86 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -254,6 +254,7 @@ + + #define QCA808X_CDT_ENABLE_TEST BIT(15) + #define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) + #define QCA808X_CDT_LENGTH_UNIT BIT(10) + + #define QCA808X_MMD3_CDT_STATUS 0x8064 +@@ -261,16 +262,44 @@ + #define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 + #define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 + #define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0) ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) + + #define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) + #define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) + #define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) + #define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL 0 +-#define QCA808X_CDT_STATUS_STAT_NORMAL 1 +-#define QCA808X_CDT_STATUS_STAT_OPEN 2 +-#define QCA808X_CDT_STATUS_STAT_SHORT 3 ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +@@ -1941,8 +1970,17 @@ static int qca808x_soft_reset(struct phy + static bool qca808x_cdt_fault_length_valid(int cdt_code) + { + switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SHORT: +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return true; + default: + return false; +@@ -1954,17 +1992,28 @@ static int qca808x_cable_test_result_tra + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_NORMAL: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + case QCA808X_CDT_STATUS_STAT_FAIL: + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } + } + +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair) ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) + { + int val; + u32 cdt_length_reg = 0; +@@ -1990,7 +2039,11 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ + return at803x_cdt_fault_length(val); + } + +@@ -2038,8 +2091,8 @@ static int qca808x_cable_test_start(stru + static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, + u16 status) + { ++ int length, result; + u16 pair_code; +- int length; + + switch (pair) { + case ETHTOOL_A_CABLE_PAIR_A: +@@ -2058,11 +2111,11 @@ static int qca808x_cable_test_get_pair_s + return -EINVAL; + } + +- ethnl_cable_test_result(phydev, pair, +- qca808x_cable_test_result_trans(pair_code)); ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); + + if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair); ++ length = qca808x_cdt_fault_length(phydev, pair, result); + ethnl_cable_test_fault_length(phydev, pair, length); + } + +@@ -2076,8 +2129,7 @@ static int qca808x_cable_test_get_status + *finished = false; + + val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; ++ QCA808X_CDT_LENGTH_UNIT; + ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; diff --git a/target/linux/generic/backport-6.6/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch b/target/linux/generic/backport-6.6/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch new file mode 100644 index 0000000000..c146e502fe --- /dev/null +++ b/target/linux/generic/backport-6.6/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch @@ -0,0 +1,62 @@ +From c34d9452d4e5d98a655d7b625e85466320885416 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:41 +0100 +Subject: [PATCH 4/4] net: phy: at803x: make read_status more generic + +Make read_status more generic in preparation on moving it to shared +library as other PHY Family Driver will have the exact same +implementation. + +The only specific part was a check for AR8031/33 if 1000basex was used. +The check is moved to a dedicated function specific for those PHYs. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1020,13 +1020,9 @@ static int at803x_read_specific_status(s + + static int at803x_read_status(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) +@@ -1618,6 +1614,17 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ + /* AR8031 and AR8035 share the same cable test get status reg */ + static int at8031_cable_test_get_status(struct phy_device *phydev, + bool *finished) +@@ -2281,7 +2288,7 @@ static struct phy_driver at803x_driver[] + .read_page = at803x_read_page, + .write_page = at803x_write_page, + .get_features = at803x_get_features, +- .read_status = at803x_read_status, ++ .read_status = at8031_read_status, + .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, diff --git a/target/linux/generic/backport-6.6/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch b/target/linux/generic/backport-6.6/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch new file mode 100644 index 0000000000..36675e7588 --- /dev/null +++ b/target/linux/generic/backport-6.6/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch @@ -0,0 +1,408 @@ +From 7196062b64ee470b91015f3d2e82d225948258ea Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 25 Jan 2024 21:37:01 +0100 +Subject: [PATCH 5/5] net: phy: at803x: add LED support for qca808x + +Add LED support for QCA8081 PHY. + +Documentation for this LEDs PHY is very scarce even with NDA access +to Documentation for OEMs. Only the blink pattern are documented and are +very confusing most of the time. No documentation is present about +forcing the LED on/off or to always blink. + +Those settings were reversed by poking the regs and trying to find the +correct bits to trigger these modes. Some bits mode are not clear and +maybe the documentation option are not 100% correct. For the sake of LED +support the reversed option are enough to add support for current LED +APIs. + +Supported HW control modes are: +- tx +- rx +- link_10 +- link_100 +- link_1000 +- link_2500 +- half_duplex +- full_duplex + +Also add support for LED polarity set to set LED polarity to active +high or low. QSDK sets this value to high by default but PHY reset value +doesn't have this enabled by default. + +QSDK also sets 2 additional bits but their usage is not clear, info about +this is added in the header. It was verified that for correct function +of the LED if active high is needed, only BIT 6 is needed. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240125203702.4552-6-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/at803x.c | 327 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 327 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,87 @@ + /* Added for reference of existence but should be handled by wait_for_completion already */ + #define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +@@ -346,6 +427,7 @@ struct at803x_priv { + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; + u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++ int led_polarity_mode; + }; + + struct at803x_context { +@@ -706,6 +788,9 @@ static int at803x_probe(struct phy_devic + if (!priv) + return -ENOMEM; + ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ + phydev->priv = priv; + + ret = at803x_parse_dt(phydev); +@@ -2235,6 +2320,242 @@ static void qca808x_link_change_notify(s + phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2411,6 +2732,12 @@ static struct phy_driver at803x_driver[] + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, + .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch b/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch new file mode 100644 index 0000000000..8c9babea7b --- /dev/null +++ b/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch @@ -0,0 +1,5598 @@ +From 9e56ff53b4115875667760445b028357848b4748 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:19 +0100 +Subject: [PATCH 1/5] net: phy: move at803x PHY driver to dedicated directory + +In preparation for addition of other Qcom PHY and to tidy things up, +move the at803x PHY driver to dedicated directory. + +The same order in the Kconfig selection is saved. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-2-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/Kconfig | 7 +------ + drivers/net/phy/Makefile | 2 +- + drivers/net/phy/qcom/Kconfig | 7 +++++++ + drivers/net/phy/qcom/Makefile | 2 ++ + drivers/net/phy/{ => qcom}/at803x.c | 0 + 5 files changed, 11 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/phy/qcom/Kconfig + create mode 100644 drivers/net/phy/qcom/Makefile + rename drivers/net/phy/{ => qcom}/at803x.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -277,12 +277,7 @@ config NXP_TJA11XX_PHY + help + Currently supports the NXP TJA1100 and TJA1101 PHY. + +-config AT803X_PHY +- tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" +- depends on REGULATOR +- help +- Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +- QCA8337(Internal qca8k PHY) model ++source "drivers/net/phy/qcom/Kconfig" + + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -34,7 +34,6 @@ obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ +-obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o + obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o +@@ -75,6 +74,7 @@ obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm + obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o ++obj-y += qcom/ + obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o +--- /dev/null ++++ b/drivers/net/phy/qcom/Kconfig +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AT803X_PHY ++ tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ depends on REGULATOR ++ help ++ Currently supports the AR8030, AR8031, AR8033, AR8035 and internal ++ QCA8337(Internal qca8k PHY) model +--- /dev/null ++++ b/drivers/net/phy/qcom/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_AT803X_PHY) += at803x.o +--- a/drivers/net/phy/at803x.c ++++ /dev/null +@@ -1,2759 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0+ +-/* +- * drivers/net/phy/at803x.c +- * +- * Driver for Qualcomm Atheros AR803x PHY +- * +- * Author: Matus Ujhelyi +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 +-#define AT803X_SFC_ASSERT_CRS BIT(11) +-#define AT803X_SFC_FORCE_LINK BIT(10) +-#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) +-#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 +-#define AT803X_SFC_MANUAL_MDIX 0x1 +-#define AT803X_SFC_MANUAL_MDI 0x0 +-#define AT803X_SFC_SQE_TEST BIT(2) +-#define AT803X_SFC_POLARITY_REVERSAL BIT(1) +-#define AT803X_SFC_DISABLE_JABBER BIT(0) +- +-#define AT803X_SPECIFIC_STATUS 0x11 +-#define AT803X_SS_SPEED_MASK GENMASK(15, 14) +-#define AT803X_SS_SPEED_1000 2 +-#define AT803X_SS_SPEED_100 1 +-#define AT803X_SS_SPEED_10 0 +-#define AT803X_SS_DUPLEX BIT(13) +-#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) +-#define AT803X_SS_MDIX BIT(6) +- +-#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) +-#define QCA808X_SS_SPEED_2500 4 +- +-#define AT803X_INTR_ENABLE 0x12 +-#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) +-#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) +-#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) +-#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) +-#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) +-#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) +-#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) +-#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) +-#define AT803X_INTR_ENABLE_WOL BIT(0) +- +-#define AT803X_INTR_STATUS 0x13 +- +-#define AT803X_SMART_SPEED 0x14 +-#define AT803X_SMART_SPEED_ENABLE BIT(5) +-#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) +-#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) +-#define AT803X_CDT 0x16 +-#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) +-#define AT803X_CDT_ENABLE_TEST BIT(0) +-#define AT803X_CDT_STATUS 0x1c +-#define AT803X_CDT_STATUS_STAT_NORMAL 0 +-#define AT803X_CDT_STATUS_STAT_SHORT 1 +-#define AT803X_CDT_STATUS_STAT_OPEN 2 +-#define AT803X_CDT_STATUS_STAT_FAIL 3 +-#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) +-#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) +-#define AT803X_LED_CONTROL 0x18 +- +-#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 +-#define AT803X_WOL_EN BIT(5) +-#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +-#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +-#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +-#define AT803X_REG_CHIP_CONFIG 0x1f +-#define AT803X_BT_BX_REG_SEL 0x8000 +- +-#define AT803X_DEBUG_ADDR 0x1D +-#define AT803X_DEBUG_DATA 0x1E +- +-#define AT803X_MODE_CFG_MASK 0x0F +-#define AT803X_MODE_CFG_BASET_RGMII 0x00 +-#define AT803X_MODE_CFG_BASET_SGMII 0x01 +-#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02 +-#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03 +-#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04 +-#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05 +-#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06 +-#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07 +-#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B +-#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E +-#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F +- +-#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ +-#define AT803X_PSSR_MR_AN_COMPLETE 0x0200 +- +-#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 +-#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) +-#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) +-#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) +- +-#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 +-#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) +- +-#define AT803X_DEBUG_REG_HIB_CTRL 0x0b +-#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) +-#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) +-#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) +- +-#define AT803X_DEBUG_REG_3C 0x3C +- +-#define AT803X_DEBUG_REG_GREEN 0x3D +-#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) +- +-#define AT803X_DEBUG_REG_1F 0x1F +-#define AT803X_DEBUG_PLL_ON BIT(2) +-#define AT803X_DEBUG_RGMII_1V8 BIT(3) +- +-#define MDIO_AZ_DEBUG 0x800D +- +-/* AT803x supports either the XTAL input pad, an internal PLL or the +- * DSP as clock reference for the clock output pad. The XTAL reference +- * is only used for 25 MHz output, all other frequencies need the PLL. +- * The DSP as a clock reference is used in synchronous ethernet +- * applications. +- * +- * By default the PLL is only enabled if there is a link. Otherwise +- * the PHY will go into low power state and disabled the PLL. You can +- * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always +- * enabled. +- */ +-#define AT803X_MMD7_CLK25M 0x8016 +-#define AT803X_CLK_OUT_MASK GENMASK(4, 2) +-#define AT803X_CLK_OUT_25MHZ_XTAL 0 +-#define AT803X_CLK_OUT_25MHZ_DSP 1 +-#define AT803X_CLK_OUT_50MHZ_PLL 2 +-#define AT803X_CLK_OUT_50MHZ_DSP 3 +-#define AT803X_CLK_OUT_62_5MHZ_PLL 4 +-#define AT803X_CLK_OUT_62_5MHZ_DSP 5 +-#define AT803X_CLK_OUT_125MHZ_PLL 6 +-#define AT803X_CLK_OUT_125MHZ_DSP 7 +- +-/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask +- * but doesn't support choosing between XTAL/PLL and DSP. +- */ +-#define AT8035_CLK_OUT_MASK GENMASK(4, 3) +- +-#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7) +-#define AT803X_CLK_OUT_STRENGTH_FULL 0 +-#define AT803X_CLK_OUT_STRENGTH_HALF 1 +-#define AT803X_CLK_OUT_STRENGTH_QUARTER 2 +- +-#define AT803X_DEFAULT_DOWNSHIFT 5 +-#define AT803X_MIN_DOWNSHIFT 2 +-#define AT803X_MAX_DOWNSHIFT 9 +- +-#define AT803X_MMD3_SMARTEEE_CTL1 0x805b +-#define AT803X_MMD3_SMARTEEE_CTL2 0x805c +-#define AT803X_MMD3_SMARTEEE_CTL3 0x805d +-#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8) +- +-#define ATH9331_PHY_ID 0x004dd041 +-#define ATH8030_PHY_ID 0x004dd076 +-#define ATH8031_PHY_ID 0x004dd074 +-#define ATH8032_PHY_ID 0x004dd023 +-#define ATH8035_PHY_ID 0x004dd072 +-#define AT8030_PHY_ID_MASK 0xffffffef +- +-#define QCA8081_PHY_ID 0x004dd101 +- +-#define QCA8327_A_PHY_ID 0x004dd033 +-#define QCA8327_B_PHY_ID 0x004dd034 +-#define QCA8337_PHY_ID 0x004dd036 +-#define QCA9561_PHY_ID 0x004dd042 +-#define QCA8K_PHY_ID_MASK 0xffffffff +- +-#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) +- +-#define AT803X_PAGE_FIBER 0 +-#define AT803X_PAGE_COPPER 1 +- +-/* don't turn off internal PLL */ +-#define AT803X_KEEP_PLL_ENABLED BIT(0) +-#define AT803X_DISABLE_SMARTEEE BIT(1) +- +-/* disable hibernation mode */ +-#define AT803X_DISABLE_HIBERNATION_MODE BIT(2) +- +-/* ADC threshold */ +-#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 +-#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) +-#define QCA808X_ADC_THRESHOLD_80MV 0 +-#define QCA808X_ADC_THRESHOLD_100MV 0xf0 +-#define QCA808X_ADC_THRESHOLD_200MV 0x0f +-#define QCA808X_ADC_THRESHOLD_300MV 0xff +- +-/* CLD control */ +-#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 +-#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) +-#define QCA808X_8023AZ_AFE_EN 0x90 +- +-/* AZ control */ +-#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 +-#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 +-#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E +-#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E +-#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 +-#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c +-#define QCA808X_TOP_OPTION1_DATA 0x0 +- +-#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 +-#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 +-#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 +-#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad +-#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 +-#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 +-#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 +-#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 +-#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 +-#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 +-#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 +-#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 +- +-/* master/slave seed config */ +-#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 +-#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) +-#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) +-#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 +- +-/* Hibernation yields lower power consumpiton in contrast with normal operation mode. +- * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. +- */ +-#define QCA808X_DBG_AN_TEST 0xb +-#define QCA808X_HIBERNATION_EN BIT(15) +- +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- +-#define QCA808X_MMD7_LED2_CTRL 0x8074 +-#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 +-#define QCA808X_MMD7_LED1_CTRL 0x8076 +-#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 +-#define QCA808X_MMD7_LED0_CTRL 0x8078 +-#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) +- +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- +-#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 +-#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) +- +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- +-#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a +-/* QSDK sets by default 0x46 to this reg that sets BIT 6 for +- * LED to active high. It's not clear what BIT 3 and BIT 4 does. +- */ +-#define QCA808X_LED_ACTIVE_HIGH BIT(6) +- +-/* QCA808X 1G chip type */ +-#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +-#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +- +-#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 +-#define QCA8081_PHY_FIFO_RSTN BIT(11) +- +-MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); +-MODULE_AUTHOR("Matus Ujhelyi"); +-MODULE_LICENSE("GPL"); +- +-enum stat_access_type { +- PHY, +- MMD +-}; +- +-struct at803x_hw_stat { +- const char *string; +- u8 reg; +- u32 mask; +- enum stat_access_type access_type; +-}; +- +-static struct at803x_hw_stat qca83xx_hw_stats[] = { +- { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, +- { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +- { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +-}; +- +-struct at803x_ss_mask { +- u16 speed_mask; +- u8 speed_shift; +-}; +- +-struct at803x_priv { +- int flags; +- u16 clk_25m_reg; +- u16 clk_25m_mask; +- u8 smarteee_lpi_tw_1g; +- u8 smarteee_lpi_tw_100m; +- bool is_fiber; +- bool is_1000basex; +- struct regulator_dev *vddio_rdev; +- struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; +- int led_polarity_mode; +-}; +- +-struct at803x_context { +- u16 bmcr; +- u16 advertise; +- u16 control1000; +- u16 int_enable; +- u16 smart_speed; +- u16 led_control; +-}; +- +-static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, data); +-} +- +-static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_read(phydev, AT803X_DEBUG_DATA); +-} +- +-static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, +- u16 clear, u16 set) +-{ +- u16 val; +- int ret; +- +- ret = at803x_debug_reg_read(phydev, reg); +- if (ret < 0) +- return ret; +- +- val = ret & 0xffff; +- val &= ~clear; +- val |= set; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, val); +-} +- +-static int at803x_write_page(struct phy_device *phydev, int page) +-{ +- int mask; +- int set; +- +- if (page == AT803X_PAGE_COPPER) { +- set = AT803X_BT_BX_REG_SEL; +- mask = 0; +- } else { +- set = 0; +- mask = AT803X_BT_BX_REG_SEL; +- } +- +- return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); +-} +- +-static int at803x_read_page(struct phy_device *phydev) +-{ +- int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- +- if (ccr < 0) +- return ccr; +- +- if (ccr & AT803X_BT_BX_REG_SEL) +- return AT803X_PAGE_COPPER; +- +- return AT803X_PAGE_FIBER; +-} +- +-static int at803x_enable_rx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0, +- AT803X_DEBUG_RX_CLK_DLY_EN); +-} +- +-static int at803x_enable_tx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0, +- AT803X_DEBUG_TX_CLK_DLY_EN); +-} +- +-static int at803x_disable_rx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- AT803X_DEBUG_RX_CLK_DLY_EN, 0); +-} +- +-static int at803x_disable_tx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, +- AT803X_DEBUG_TX_CLK_DLY_EN, 0); +-} +- +-/* save relevant PHY registers to private copy */ +-static void at803x_context_save(struct phy_device *phydev, +- struct at803x_context *context) +-{ +- context->bmcr = phy_read(phydev, MII_BMCR); +- context->advertise = phy_read(phydev, MII_ADVERTISE); +- context->control1000 = phy_read(phydev, MII_CTRL1000); +- context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE); +- context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED); +- context->led_control = phy_read(phydev, AT803X_LED_CONTROL); +-} +- +-/* restore relevant PHY registers from private copy */ +-static void at803x_context_restore(struct phy_device *phydev, +- const struct at803x_context *context) +-{ +- phy_write(phydev, MII_BMCR, context->bmcr); +- phy_write(phydev, MII_ADVERTISE, context->advertise); +- phy_write(phydev, MII_CTRL1000, context->control1000); +- phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable); +- phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed); +- phy_write(phydev, AT803X_LED_CONTROL, context->led_control); +-} +- +-static int at803x_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret, irq_enabled; +- +- if (wol->wolopts & WAKE_MAGIC) { +- struct net_device *ndev = phydev->attached_dev; +- const u8 *mac; +- unsigned int i; +- static const unsigned int offsets[] = { +- AT803X_LOC_MAC_ADDR_32_47_OFFSET, +- AT803X_LOC_MAC_ADDR_16_31_OFFSET, +- AT803X_LOC_MAC_ADDR_0_15_OFFSET, +- }; +- +- if (!ndev) +- return -ENODEV; +- +- mac = (const u8 *)ndev->dev_addr; +- +- if (!is_valid_ether_addr(mac)) +- return -EINVAL; +- +- for (i = 0; i < 3; i++) +- phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], +- mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); +- +- /* Enable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); +- if (ret) +- return ret; +- } else { +- /* Disable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); +- if (ret) +- return ret; +- } +- +- /* Clear WOL status */ +- ret = phy_read(phydev, AT803X_INTR_STATUS); +- if (ret < 0) +- return ret; +- +- /* Check if there are other interrupts except for WOL triggered when PHY is +- * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can +- * be passed up to the interrupt PIN. +- */ +- irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (irq_enabled < 0) +- return irq_enabled; +- +- irq_enabled &= ~AT803X_INTR_ENABLE_WOL; +- if (ret & irq_enabled && !phy_polling_mode(phydev)) +- phy_trigger_machine(phydev); +- +- return 0; +-} +- +-static void at803x_get_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int value; +- +- wol->supported = WAKE_MAGIC; +- wol->wolopts = 0; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- if (value < 0) +- return; +- +- if (value & AT803X_INTR_ENABLE_WOL) +- wol->wolopts |= WAKE_MAGIC; +-} +- +-static int qca83xx_get_sset_count(struct phy_device *phydev) +-{ +- return ARRAY_SIZE(qca83xx_hw_stats); +-} +- +-static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { +- strscpy(data + i * ETH_GSTRING_LEN, +- qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); +- } +-} +- +-static u64 qca83xx_get_stat(struct phy_device *phydev, int i) +-{ +- struct at803x_hw_stat stat = qca83xx_hw_stats[i]; +- struct at803x_priv *priv = phydev->priv; +- int val; +- u64 ret; +- +- if (stat.access_type == MMD) +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); +- else +- val = phy_read(phydev, stat.reg); +- +- if (val < 0) { +- ret = U64_MAX; +- } else { +- val = val & stat.mask; +- priv->stats[i] += val; +- ret = priv->stats[i]; +- } +- +- return ret; +-} +- +-static void qca83xx_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) +- data[i] = qca83xx_get_stat(phydev, i); +-} +- +-static int at803x_suspend(struct phy_device *phydev) +-{ +- int value; +- int wol_enabled; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- wol_enabled = value & AT803X_INTR_ENABLE_WOL; +- +- if (wol_enabled) +- value = BMCR_ISOLATE; +- else +- value = BMCR_PDOWN; +- +- phy_modify(phydev, MII_BMCR, 0, value); +- +- return 0; +-} +- +-static int at803x_resume(struct phy_device *phydev) +-{ +- return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); +-} +- +-static int at803x_parse_dt(struct phy_device *phydev) +-{ +- struct device_node *node = phydev->mdio.dev.of_node; +- struct at803x_priv *priv = phydev->priv; +- u32 freq, strength, tw; +- unsigned int sel; +- int ret; +- +- if (!IS_ENABLED(CONFIG_OF_MDIO)) +- return 0; +- +- if (of_property_read_bool(node, "qca,disable-smarteee")) +- priv->flags |= AT803X_DISABLE_SMARTEEE; +- +- if (of_property_read_bool(node, "qca,disable-hibernation-mode")) +- priv->flags |= AT803X_DISABLE_HIBERNATION_MODE; +- +- if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) { +- if (!tw || tw > 255) { +- phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n"); +- return -EINVAL; +- } +- priv->smarteee_lpi_tw_1g = tw; +- } +- +- if (!of_property_read_u32(node, "qca,smarteee-tw-us-100m", &tw)) { +- if (!tw || tw > 255) { +- phydev_err(phydev, "invalid qca,smarteee-tw-us-100m\n"); +- return -EINVAL; +- } +- priv->smarteee_lpi_tw_100m = tw; +- } +- +- ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq); +- if (!ret) { +- switch (freq) { +- case 25000000: +- sel = AT803X_CLK_OUT_25MHZ_XTAL; +- break; +- case 50000000: +- sel = AT803X_CLK_OUT_50MHZ_PLL; +- break; +- case 62500000: +- sel = AT803X_CLK_OUT_62_5MHZ_PLL; +- break; +- case 125000000: +- sel = AT803X_CLK_OUT_125MHZ_PLL; +- break; +- default: +- phydev_err(phydev, "invalid qca,clk-out-frequency\n"); +- return -EINVAL; +- } +- +- priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); +- priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- } +- +- ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +- if (!ret) { +- priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK; +- switch (strength) { +- case AR803X_STRENGTH_FULL: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL; +- break; +- case AR803X_STRENGTH_HALF: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF; +- break; +- case AR803X_STRENGTH_QUARTER: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER; +- break; +- default: +- phydev_err(phydev, "invalid qca,clk-out-strength\n"); +- return -EINVAL; +- } +- } +- +- return 0; +-} +- +-static int at803x_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct at803x_priv *priv; +- int ret; +- +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- /* Init LED polarity mode to -1 */ +- priv->led_polarity_mode = -1; +- +- phydev->priv = priv; +- +- ret = at803x_parse_dt(phydev); +- if (ret) +- return ret; +- +- return 0; +-} +- +-static int at803x_get_features(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int err; +- +- err = genphy_read_abilities(phydev); +- if (err) +- return err; +- +- if (phydev->drv->phy_id != ATH8031_PHY_ID) +- return 0; +- +- /* AR8031/AR8033 have different status registers +- * for copper and fiber operation. However, the +- * extended status register is the same for both +- * operation modes. +- * +- * As a result of that, ESTATUS_1000_XFULL is set +- * to 1 even when operating in copper TP mode. +- * +- * Remove this mode from the supported link modes +- * when not operating in 1000BaseX mode. +- */ +- if (!priv->is_1000basex) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, +- phydev->supported); +- +- return 0; +-} +- +-static int at803x_smarteee_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- u16 mask = 0, val = 0; +- int ret; +- +- if (priv->flags & AT803X_DISABLE_SMARTEEE) +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_MMD3_SMARTEEE_CTL3, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0); +- +- if (priv->smarteee_lpi_tw_1g) { +- mask |= 0xff00; +- val |= priv->smarteee_lpi_tw_1g << 8; +- } +- if (priv->smarteee_lpi_tw_100m) { +- mask |= 0x00ff; +- val |= priv->smarteee_lpi_tw_100m; +- } +- if (!mask) +- return 0; +- +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1, +- mask, val); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN); +-} +- +-static int at803x_clk_out_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- if (!priv->clk_25m_mask) +- return 0; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, +- priv->clk_25m_mask, priv->clk_25m_reg); +-} +- +-static int at8031_pll_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* The default after hardware reset is PLL OFF. After a soft reset, the +- * values are retained. +- */ +- if (priv->flags & AT803X_KEEP_PLL_ENABLED) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_PLL_ON); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_PLL_ON, 0); +-} +- +-static int at803x_hibernation_mode_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* The default after hardware reset is hibernation mode enabled. After +- * software reset, the value is retained. +- */ +- if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE)) +- return 0; +- +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0); +-} +- +-static int at803x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* The RX and TX delay default is: +- * after HW reset: RX delay enabled and TX delay disabled +- * after SW reset: RX delay enabled, while TX delay retains the +- * value before reset. +- */ +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) +- ret = at803x_enable_rx_delay(phydev); +- else +- ret = at803x_disable_rx_delay(phydev); +- if (ret < 0) +- return ret; +- +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- ret = at803x_enable_tx_delay(phydev); +- else +- ret = at803x_disable_tx_delay(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_smarteee_config(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_clk_out_config(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_hibernation_mode_config(phydev); +- if (ret < 0) +- return ret; +- +- /* Ar803x extended next page bit is enabled by default. Cisco +- * multigig switches read this bit and attempt to negotiate 10Gbps +- * rates even if the next page bit is disabled. This is incorrect +- * behaviour but we still need to accommodate it. XNP is only needed +- * for 10Gbps support, so disable XNP. +- */ +- return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); +-} +- +-static int at803x_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, AT803X_INTR_STATUS); +- +- return (err < 0) ? err : 0; +-} +- +-static int at803x_config_intr(struct phy_device *phydev) +-{ +- int err; +- int value; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_AUTONEG_ERR; +- value |= AT803X_INTR_ENABLE_SPEED_CHANGED; +- value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; +- value |= AT803X_INTR_ENABLE_LINK_FAIL; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- +- err = phy_write(phydev, AT803X_INTR_ENABLE, value); +- } else { +- err = phy_write(phydev, AT803X_INTR_ENABLE, 0); +- if (err) +- return err; +- +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status, int_enabled; +- +- irq_status = phy_read(phydev, AT803X_INTR_STATUS); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* Read the current enabled interrupts */ +- int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (int_enabled < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* See if this was one of our enabled interrupts */ +- if (!(irq_status & int_enabled)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static void at803x_link_change_notify(struct phy_device *phydev) +-{ +- /* +- * Conduct a hardware reset for AT8030 every time a link loss is +- * signalled. This is necessary to circumvent a hardware bug that +- * occurs when the cable is unplugged while TX packets are pending +- * in the FIFO. In such cases, the FIFO enters an error mode it +- * cannot recover from by software. +- */ +- if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) { +- struct at803x_context context; +- +- at803x_context_save(phydev, &context); +- +- phy_device_reset(phydev, 1); +- usleep_range(1000, 2000); +- phy_device_reset(phydev, 0); +- usleep_range(1000, 2000); +- +- at803x_context_restore(phydev, &context); +- +- phydev_dbg(phydev, "%s(): phy was reset\n", __func__); +- } +-} +- +-static int at803x_read_specific_status(struct phy_device *phydev, +- struct at803x_ss_mask ss_mask) +-{ +- int ss; +- +- /* Read the AT8035 PHY-Specific Status register, which indicates the +- * speed and duplex that the PHY is actually using, irrespective of +- * whether we are in autoneg mode or not. +- */ +- ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); +- if (ss < 0) +- return ss; +- +- if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { +- int sfc, speed; +- +- sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); +- if (sfc < 0) +- return sfc; +- +- speed = ss & ss_mask.speed_mask; +- speed >>= ss_mask.speed_shift; +- +- switch (speed) { +- case AT803X_SS_SPEED_10: +- phydev->speed = SPEED_10; +- break; +- case AT803X_SS_SPEED_100: +- phydev->speed = SPEED_100; +- break; +- case AT803X_SS_SPEED_1000: +- phydev->speed = SPEED_1000; +- break; +- case QCA808X_SS_SPEED_2500: +- phydev->speed = SPEED_2500; +- break; +- } +- if (ss & AT803X_SS_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- if (ss & AT803X_SS_MDIX) +- phydev->mdix = ETH_TP_MDI_X; +- else +- phydev->mdix = ETH_TP_MDI; +- +- switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { +- case AT803X_SFC_MANUAL_MDI: +- phydev->mdix_ctrl = ETH_TP_MDI; +- break; +- case AT803X_SFC_MANUAL_MDIX: +- phydev->mdix_ctrl = ETH_TP_MDI_X; +- break; +- case AT803X_SFC_AUTOMATIC_CROSSOVER: +- phydev->mdix_ctrl = ETH_TP_MDI_AUTO; +- break; +- } +- } +- +- return 0; +-} +- +-static int at803x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int err, old_link = phydev->link; +- +- /* Update the link, but return if there was an error */ +- err = genphy_update_link(phydev); +- if (err) +- return err; +- +- /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) +- return 0; +- +- phydev->speed = SPEED_UNKNOWN; +- phydev->duplex = DUPLEX_UNKNOWN; +- phydev->pause = 0; +- phydev->asym_pause = 0; +- +- err = genphy_read_lpa(phydev); +- if (err < 0) +- return err; +- +- ss_mask.speed_mask = AT803X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); +- err = at803x_read_specific_status(phydev, ss_mask); +- if (err < 0) +- return err; +- +- if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) +- phy_resolve_aneg_pause(phydev); +- +- return 0; +-} +- +-static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) +-{ +- u16 val; +- +- switch (ctrl) { +- case ETH_TP_MDI: +- val = AT803X_SFC_MANUAL_MDI; +- break; +- case ETH_TP_MDI_X: +- val = AT803X_SFC_MANUAL_MDIX; +- break; +- case ETH_TP_MDI_AUTO: +- val = AT803X_SFC_AUTOMATIC_CROSSOVER; +- break; +- default: +- return 0; +- } +- +- return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, +- AT803X_SFC_MDI_CROSSOVER_MODE_M, +- FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); +-} +- +-static int at803x_prepare_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +- if (ret < 0) +- return ret; +- +- /* Changes of the midx bits are disruptive to the normal operation; +- * therefore any changes to these registers must be followed by a +- * software reset to take effect. +- */ +- if (ret == 1) { +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- +-static int at803x_config_aneg(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- return genphy_config_aneg(phydev); +-} +- +-static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +-{ +- int val; +- +- val = phy_read(phydev, AT803X_SMART_SPEED); +- if (val < 0) +- return val; +- +- if (val & AT803X_SMART_SPEED_ENABLE) +- *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; +- else +- *d = DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- u16 mask, set; +- int ret; +- +- switch (cnt) { +- case DOWNSHIFT_DEV_DEFAULT_COUNT: +- cnt = AT803X_DEFAULT_DOWNSHIFT; +- fallthrough; +- case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: +- set = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER | +- FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); +- mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; +- break; +- case DOWNSHIFT_DEV_DISABLE: +- set = 0; +- mask = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER; +- break; +- default: +- return -EINVAL; +- } +- +- ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); +- +- /* After changing the smart speed settings, we need to perform a +- * software reset, use phy_init_hw() to make sure we set the +- * reapply any values which might got lost during software reset. +- */ +- if (ret == 1) +- ret = phy_init_hw(phydev); +- +- return ret; +-} +- +-static int at803x_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_cable_test_result_trans(u16 status) +-{ +- switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +- case AT803X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case AT803X_CDT_STATUS_STAT_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case AT803X_CDT_STATUS_STAT_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case AT803X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static bool at803x_cdt_test_failed(u16 status) +-{ +- return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) == +- AT803X_CDT_STATUS_STAT_FAIL; +-} +- +-static bool at803x_cdt_fault_length_valid(u16 status) +-{ +- switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +- case AT803X_CDT_STATUS_STAT_OPEN: +- case AT803X_CDT_STATUS_STAT_SHORT: +- return true; +- } +- return false; +-} +- +-static int at803x_cdt_fault_length(int dt) +-{ +- /* According to the datasheet the distance to the fault is +- * DELTA_TIME * 0.824 meters. +- * +- * The author suspect the correct formula is: +- * +- * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 +- * +- * where c is the speed of light, VF is the velocity factor of +- * the twisted pair cable, 125MHz the counter frequency and +- * we need to divide by 2 because the hardware will measure the +- * round trip time to the fault and back to the PHY. +- * +- * With a VF of 0.69 we get the factor 0.824 mentioned in the +- * datasheet. +- */ +- return (dt * 824) / 10; +-} +- +-static int at803x_cdt_start(struct phy_device *phydev, +- u32 cdt_start) +-{ +- return phy_write(phydev, AT803X_CDT, cdt_start); +-} +- +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev, +- u32 cdt_en) +-{ +- int val, ret; +- +- /* One test run takes about 25ms */ +- ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +- !(val & cdt_en), +- 30000, 100000, true); +- +- return ret < 0 ? ret : 0; +-} +- +-static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) +-{ +- static const int ethtool_pair[] = { +- ETHTOOL_A_CABLE_PAIR_A, +- ETHTOOL_A_CABLE_PAIR_B, +- ETHTOOL_A_CABLE_PAIR_C, +- ETHTOOL_A_CABLE_PAIR_D, +- }; +- int ret, val; +- +- val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read(phydev, AT803X_CDT_STATUS); +- if (val < 0) +- return val; +- +- if (at803x_cdt_test_failed(val)) +- return 0; +- +- ethnl_cable_test_result(phydev, ethtool_pair[pair], +- at803x_cable_test_result_trans(val)); +- +- if (at803x_cdt_fault_length_valid(val)) { +- val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); +- ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], +- at803x_cdt_fault_length(val)); +- } +- +- return 1; +-} +- +-static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished, unsigned long pair_mask) +-{ +- int retries = 20; +- int pair, ret; +- +- *finished = false; +- +- /* According to the datasheet the CDT can be performed when +- * there is no link partner or when the link partner is +- * auto-negotiating. Starting the test will restart the AN +- * automatically. It seems that doing this repeatedly we will +- * get a slot where our link partner won't disturb our +- * measurement. +- */ +- while (pair_mask && retries--) { +- for_each_set_bit(pair, &pair_mask, 4) { +- ret = at803x_cable_test_one_pair(phydev, pair); +- if (ret < 0) +- return ret; +- if (ret) +- clear_bit(pair, &pair_mask); +- } +- if (pair_mask) +- msleep(250); +- } +- +- *finished = true; +- +- return 0; +-} +- +-static void at803x_cable_test_autoneg(struct phy_device *phydev) +-{ +- /* Enable auto-negotiation, but advertise no capabilities, no link +- * will be established. A restart of the auto-negotiation is not +- * required, because the cable test will automatically break the link. +- */ +- phy_write(phydev, MII_BMCR, BMCR_ANENABLE); +- phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +-} +- +-static int at803x_cable_test_start(struct phy_device *phydev) +-{ +- at803x_cable_test_autoneg(phydev); +- /* we do all the (time consuming) work later */ +- return 0; +-} +- +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- +-static int at8031_parse_dt(struct phy_device *phydev) +-{ +- struct device_node *node = phydev->mdio.dev.of_node; +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at8031_sfp_ops); +-} +- +-static int at8031_probe(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int mode_cfg; +- int ccr; +- int ret; +- +- ret = at803x_probe(phydev); +- if (ret) +- return ret; +- +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- ret = at8031_parse_dt(phydev); +- if (ret) +- return ret; +- +- ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +-} +- +-static int at8031_config_init(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- +- return at803x_config_init(phydev); +-} +- +-static int at8031_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret; +- +- /* First setup MAC address and enable WOL interrupt */ +- ret = at803x_set_wol(phydev, wol); +- if (ret) +- return ret; +- +- if (wol->wolopts & WAKE_MAGIC) +- /* Enable WOL function for 1588 */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- else +- /* Disable WoL function for 1588 */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- +- return ret; +-} +- +-static int at8031_config_intr(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int err, value = 0; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED && +- priv->is_fiber) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- +- err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); +- if (err) +- return err; +- } +- +- return at803x_config_intr(phydev); +-} +- +-/* AR8031 and AR8033 share the same read status logic */ +-static int at8031_read_status(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- +- return at803x_read_status(phydev); +-} +- +-/* AR8031 and AR8035 share the same cable test get status reg */ +-static int at8031_cable_test_get_status(struct phy_device *phydev, +- bool *finished) +-{ +- return at803x_cable_test_get_status(phydev, finished, 0xf); +-} +- +-/* AR8031 and AR8035 share the same cable test start logic */ +-static int at8031_cable_test_start(struct phy_device *phydev) +-{ +- at803x_cable_test_autoneg(phydev); +- phy_write(phydev, MII_CTRL1000, 0); +- /* we do all the (time consuming) work later */ +- return 0; +-} +- +-/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ +-static int at8032_cable_test_get_status(struct phy_device *phydev, +- bool *finished) +-{ +- return at803x_cable_test_get_status(phydev, finished, 0x3); +-} +- +-static int at8035_parse_dt(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* Mask is set by the generic at803x_parse_dt +- * if property is set. Assume property is set +- * with the mask not zero. +- */ +- if (priv->clk_25m_mask) { +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } +- +- return 0; +-} +- +-/* AR8030 and AR8035 shared the same special mask for clk_25m */ +-static int at8035_probe(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_probe(phydev); +- if (ret) +- return ret; +- +- return at8035_parse_dt(phydev); +-} +- +-static int qca83xx_config_init(struct phy_device *phydev) +-{ +- u8 switch_revision; +- +- switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; +- +- switch (switch_revision) { +- case 1: +- /* For 100M waveform */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); +- /* Turn on Gigabit clock */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); +- break; +- +- case 2: +- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); +- fallthrough; +- case 4: +- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); +- break; +- } +- +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; +-} +- +-static int qca8327_config_init(struct phy_device *phydev) +-{ +- /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. +- * Disable on init and enable only with 100m speed following +- * qca original source code. +- */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- +- return qca83xx_config_init(phydev); +-} +- +-static void qca83xx_link_change_notify(struct phy_device *phydev) +-{ +- /* Set DAC Amplitude adjustment to +6% for 100m on link running */ +- if (phydev->state == PHY_RUNNING) { +- if (phydev->speed == SPEED_100) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, +- QCA8327_DEBUG_MANU_CTRL_EN); +- } else { +- /* Reset DAC Amplitude adjustment */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- } +-} +- +-static int qca83xx_resume(struct phy_device *phydev) +-{ +- int ret, val; +- +- /* Skip reset if not suspended */ +- if (!phydev->suspended) +- return 0; +- +- /* Reinit the port, reset values set by suspend */ +- qca83xx_config_init(phydev); +- +- /* Reset the port on port resume */ +- phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- +- /* On resume from suspend the switch execute a reset and +- * restart auto-negotiation. Wait for reset to complete. +- */ +- ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), +- 50000, 600000, true); +- if (ret) +- return ret; +- +- usleep_range(1000, 2000); +- +- return 0; +-} +- +-static int qca83xx_suspend(struct phy_device *phydev) +-{ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, +- AT803X_DEBUG_GATE_CLK_IN1000, 0); +- +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | +- AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); +- +- return 0; +-} +- +-static int qca8337_suspend(struct phy_device *phydev) +-{ +- /* Only QCA8337 support actual suspend. */ +- genphy_suspend(phydev); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca8327_suspend(struct phy_device *phydev) +-{ +- u16 mask = 0; +- +- /* QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) +-{ +- int ret; +- +- /* Enable fast retrain */ +- ret = genphy_c45_fast_retrain(phydev, true); +- if (ret) +- return ret; +- +- phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); +- +- return 0; +-} +- +-static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) +-{ +- u16 seed_value; +- +- if (!enable) +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); +- +- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | +- QCA808X_MASTER_SLAVE_SEED_ENABLE); +-} +- +-static bool qca808x_is_prefer_master(struct phy_device *phydev) +-{ +- return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || +- (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); +-} +- +-static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) +-{ +- return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +-} +- +-static int qca808x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Active adc&vga on 802.3az for the link 1000M and 100M */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); +- if (ret) +- return ret; +- +- /* Adjust the threshold on 802.3az for the link 1000M */ +- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, +- QCA808X_MMD3_AZ_TRAINING_VAL); +- if (ret) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy +- * linked as slave mode. +- */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) +- return ret; +- } +- } +- +- /* Configure adc threshold as 100mv for the link 10M */ +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, +- QCA808X_ADC_THRESHOLD_100MV); +-} +- +-static int qca808x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int ret; +- +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +- if (ret < 0) +- return ret; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); +- +- ret = genphy_read_status(phydev); +- if (ret) +- return ret; +- +- /* qca8081 takes the different bits for speed value from at803x */ +- ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); +- ret = at803x_read_specific_status(phydev, ss_mask); +- if (ret < 0) +- return ret; +- +- if (phydev->link) { +- if (phydev->speed == SPEED_2500) +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- else +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- } else { +- /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected or the master mode +- * preferred. +- * +- * the reason for not putting this code into the function link_change_notify is +- * the corner case where the link partner is also the qca8081 PHY and the seed +- * value is configured as the same value, the link can't be up and no link change +- * occurs. +- */ +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); +- } +- } +- } +- +- return 0; +-} +- +-static int qca808x_soft_reset(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- +- return ret; +-} +- +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- +-static int qca808x_cable_test_start(struct phy_device *phydev) +-{ +- int ret; +- +- /* perform CDT with the following configs: +- * 1. disable hibernation. +- * 2. force PHY working in MDI mode. +- * 3. for PHY working in 1000BaseT. +- * 4. configure the threshold. +- */ +- +- ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); +- if (ret < 0) +- return ret; +- +- ret = at803x_config_mdix(phydev, ETH_TP_MDI); +- if (ret < 0) +- return ret; +- +- /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ +- phydev->duplex = DUPLEX_FULL; +- phydev->speed = SPEED_1000; +- ret = genphy_c45_pma_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- ret = genphy_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- /* configure the thresholds for open, short, pair ok test */ +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); +- +- return 0; +-} +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} +- +-static int qca808x_get_features(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_c45_pma_read_abilities(phydev); +- if (ret) +- return ret; +- +- /* The autoneg ability is not existed in bit3 of MMD7.1, +- * but it is supported by qca808x PHY, so we add it here +- * manually. +- */ +- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); +- +- /* As for the qca8081 1G version chip, the 2500baseT ability is also +- * existed in the bit0 of MMD1.21, we need to remove it manually if +- * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. +- */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +- +- return 0; +-} +- +-static int qca808x_config_aneg(struct phy_device *phydev) +-{ +- int phy_ctrl = 0; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- +- return __genphy_config_aneg(phydev, ret); +-} +- +-static void qca808x_link_change_notify(struct phy_device *phydev) +-{ +- /* Assert interface sgmii fifo on link down, deassert it on link up, +- * the interface device address is always phy address added by 1. +- */ +- mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, +- phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); +-} +- +-static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, +- u16 *offload_trigger) +-{ +- /* Parsing specific to netdev trigger */ +- if (test_bit(TRIGGER_NETDEV_TX, &rules)) +- *offload_trigger |= QCA808X_LED_TX_BLINK; +- if (test_bit(TRIGGER_NETDEV_RX, &rules)) +- *offload_trigger |= QCA808X_LED_RX_BLINK; +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED10_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED100_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED1000_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED2500_ON; +- if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; +- if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; +- +- if (rules && !*offload_trigger) +- return -EOPNOTSUPP; +- +- /* Enable BLINK_CHECK_BYPASS by default to make the LED +- * blink even with duplex or speed mode not enabled. +- */ +- *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; +- +- return 0; +-} +- +-static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 offload_trigger = 0; +- +- if (index > 2) +- return -EINVAL; +- +- return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +-} +- +-static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 reg, offload_trigger = 0; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +- if (ret) +- return ret; +- +- ret = qca808x_led_hw_control_enable(phydev, index); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK, +- offload_trigger); +-} +- +-static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return false; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +- unsigned long *rules) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return -EINVAL; +- +- /* Check if we have hw control enabled */ +- if (qca808x_led_hw_control_status(phydev, index)) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- if (val & QCA808X_LED_TX_BLINK) +- set_bit(TRIGGER_NETDEV_TX, rules); +- if (val & QCA808X_LED_RX_BLINK) +- set_bit(TRIGGER_NETDEV_RX, rules); +- if (val & QCA808X_LED_SPEED10_ON) +- set_bit(TRIGGER_NETDEV_LINK_10, rules); +- if (val & QCA808X_LED_SPEED100_ON) +- set_bit(TRIGGER_NETDEV_LINK_100, rules); +- if (val & QCA808X_LED_SPEED1000_ON) +- set_bit(TRIGGER_NETDEV_LINK_1000, rules); +- if (val & QCA808X_LED_SPEED2500_ON) +- set_bit(TRIGGER_NETDEV_LINK_2500, rules); +- if (val & QCA808X_LED_HALF_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); +- if (val & QCA808X_LED_FULL_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); +- +- return 0; +-} +- +-static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK); +-} +- +-static int qca808x_led_brightness_set(struct phy_device *phydev, +- u8 index, enum led_brightness value) +-{ +- u16 reg; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- if (!value) { +- ret = qca808x_led_hw_control_reset(phydev, index); +- if (ret) +- return ret; +- } +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); +-} +- +-static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, +- unsigned long *delay_on, +- unsigned long *delay_off) +-{ +- int ret; +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; +-} +- +-static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +- unsigned long modes) +-{ +- struct at803x_priv *priv = phydev->priv; +- bool active_low = false; +- u32 mode; +- +- for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { +- switch (mode) { +- case PHY_LED_ACTIVE_LOW: +- active_low = true; +- break; +- default: +- return -EINVAL; +- } +- } +- +- /* PHY polarity is global and can't be set per LED. +- * To detect this, check if last requested polarity mode +- * match the new one. +- */ +- if (priv->led_polarity_mode >= 0 && +- priv->led_polarity_mode != active_low) { +- phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); +- return -EINVAL; +- } +- +- /* Save the last PHY polarity mode */ +- priv->led_polarity_mode = active_low; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, +- QCA808X_MMD7_LED_POLARITY_CTRL, +- QCA808X_LED_ACTIVE_HIGH, +- active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); +-} +- +-static struct phy_driver at803x_driver[] = { +-{ +- /* Qualcomm Atheros AR8035 */ +- PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), +- .name = "Qualcomm Atheros AR8035", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at8035_probe, +- .config_aneg = at803x_config_aneg, +- .config_init = at803x_config_init, +- .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_GBIT_FEATURES */ +- .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .cable_test_start = at8031_cable_test_start, +- .cable_test_get_status = at8031_cable_test_get_status, +-}, { +- /* Qualcomm Atheros AR8030 */ +- .phy_id = ATH8030_PHY_ID, +- .name = "Qualcomm Atheros AR8030", +- .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at8035_probe, +- .config_init = at803x_config_init, +- .link_change_notify = at803x_link_change_notify, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +-}, { +- /* Qualcomm Atheros AR8031/AR8033 */ +- PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), +- .name = "Qualcomm Atheros AR8031/AR8033", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at8031_probe, +- .config_init = at8031_config_init, +- .config_aneg = at803x_config_aneg, +- .soft_reset = genphy_soft_reset, +- .set_wol = at8031_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .read_page = at803x_read_page, +- .write_page = at803x_write_page, +- .get_features = at803x_get_features, +- .read_status = at8031_read_status, +- .config_intr = at8031_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .cable_test_start = at8031_cable_test_start, +- .cable_test_get_status = at8031_cable_test_get_status, +-}, { +- /* Qualcomm Atheros AR8032 */ +- PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +- .name = "Qualcomm Atheros AR8032", +- .probe = at803x_probe, +- .flags = PHY_POLL_CABLE_TEST, +- .config_init = at803x_config_init, +- .link_change_notify = at803x_link_change_notify, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +-}, { +- /* ATHEROS AR9331 */ +- PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +- .name = "Qualcomm Atheros AR9331 built-in PHY", +- .probe = at803x_probe, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .flags = PHY_POLL_CABLE_TEST, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +- .read_status = at803x_read_status, +- .soft_reset = genphy_soft_reset, +- .config_aneg = at803x_config_aneg, +-}, { +- /* Qualcomm Atheros QCA9561 */ +- PHY_ID_MATCH_EXACT(QCA9561_PHY_ID), +- .name = "Qualcomm Atheros QCA9561 built-in PHY", +- .probe = at803x_probe, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .flags = PHY_POLL_CABLE_TEST, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +- .read_status = at803x_read_status, +- .soft_reset = genphy_soft_reset, +- .config_aneg = at803x_config_aneg, +-}, { +- /* QCA8337 */ +- .phy_id = QCA8337_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8337 internal PHY", +- /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8337_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-A from switch QCA8327-AL1A */ +- .phy_id = QCA8327_A_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-A internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-B from switch QCA8327-BL1A */ +- .phy_id = QCA8327_B_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-B internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* Qualcomm QCA8081 */ +- PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), +- .name = "Qualcomm QCA8081", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .get_features = qca808x_get_features, +- .config_aneg = qca808x_config_aneg, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_status = qca808x_read_status, +- .config_init = qca808x_config_init, +- .soft_reset = qca808x_soft_reset, +- .cable_test_start = qca808x_cable_test_start, +- .cable_test_get_status = qca808x_cable_test_get_status, +- .link_change_notify = qca808x_link_change_notify, +- .led_brightness_set = qca808x_led_brightness_set, +- .led_blink_set = qca808x_led_blink_set, +- .led_hw_is_supported = qca808x_led_hw_is_supported, +- .led_hw_control_set = qca808x_led_hw_control_set, +- .led_hw_control_get = qca808x_led_hw_control_get, +- .led_polarity_set = qca808x_led_polarity_set, +-}, }; +- +-module_phy_driver(at803x_driver); +- +-static struct mdio_device_id __maybe_unused atheros_tbl[] = { +- { ATH8030_PHY_ID, AT8030_PHY_ID_MASK }, +- { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, atheros_tbl); +--- /dev/null ++++ b/drivers/net/phy/qcom/at803x.c +@@ -0,0 +1,2759 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * drivers/net/phy/at803x.c ++ * ++ * Driver for Qualcomm Atheros AR803x PHY ++ * ++ * Author: Matus Ujhelyi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 ++#define AT803X_SFC_ASSERT_CRS BIT(11) ++#define AT803X_SFC_FORCE_LINK BIT(10) ++#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) ++#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 ++#define AT803X_SFC_MANUAL_MDIX 0x1 ++#define AT803X_SFC_MANUAL_MDI 0x0 ++#define AT803X_SFC_SQE_TEST BIT(2) ++#define AT803X_SFC_POLARITY_REVERSAL BIT(1) ++#define AT803X_SFC_DISABLE_JABBER BIT(0) ++ ++#define AT803X_SPECIFIC_STATUS 0x11 ++#define AT803X_SS_SPEED_MASK GENMASK(15, 14) ++#define AT803X_SS_SPEED_1000 2 ++#define AT803X_SS_SPEED_100 1 ++#define AT803X_SS_SPEED_10 0 ++#define AT803X_SS_DUPLEX BIT(13) ++#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) ++#define AT803X_SS_MDIX BIT(6) ++ ++#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) ++#define QCA808X_SS_SPEED_2500 4 ++ ++#define AT803X_INTR_ENABLE 0x12 ++#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) ++#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) ++#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) ++#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) ++#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) ++#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) ++#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) ++#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) ++#define AT803X_INTR_ENABLE_WOL BIT(0) ++ ++#define AT803X_INTR_STATUS 0x13 ++ ++#define AT803X_SMART_SPEED 0x14 ++#define AT803X_SMART_SPEED_ENABLE BIT(5) ++#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) ++#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) ++#define AT803X_CDT 0x16 ++#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) ++#define AT803X_CDT_ENABLE_TEST BIT(0) ++#define AT803X_CDT_STATUS 0x1c ++#define AT803X_CDT_STATUS_STAT_NORMAL 0 ++#define AT803X_CDT_STATUS_STAT_SHORT 1 ++#define AT803X_CDT_STATUS_STAT_OPEN 2 ++#define AT803X_CDT_STATUS_STAT_FAIL 3 ++#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) ++#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) ++#define AT803X_LED_CONTROL 0x18 ++ ++#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 ++#define AT803X_WOL_EN BIT(5) ++#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C ++#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B ++#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++#define AT803X_REG_CHIP_CONFIG 0x1f ++#define AT803X_BT_BX_REG_SEL 0x8000 ++ ++#define AT803X_DEBUG_ADDR 0x1D ++#define AT803X_DEBUG_DATA 0x1E ++ ++#define AT803X_MODE_CFG_MASK 0x0F ++#define AT803X_MODE_CFG_BASET_RGMII 0x00 ++#define AT803X_MODE_CFG_BASET_SGMII 0x01 ++#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02 ++#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03 ++#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04 ++#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05 ++#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06 ++#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07 ++#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B ++#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E ++#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F ++ ++#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ ++#define AT803X_PSSR_MR_AN_COMPLETE 0x0200 ++ ++#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 ++#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) ++#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) ++#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) ++ ++#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 ++#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) ++ ++#define AT803X_DEBUG_REG_HIB_CTRL 0x0b ++#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) ++#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) ++#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) ++ ++#define AT803X_DEBUG_REG_3C 0x3C ++ ++#define AT803X_DEBUG_REG_GREEN 0x3D ++#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) ++ ++#define AT803X_DEBUG_REG_1F 0x1F ++#define AT803X_DEBUG_PLL_ON BIT(2) ++#define AT803X_DEBUG_RGMII_1V8 BIT(3) ++ ++#define MDIO_AZ_DEBUG 0x800D ++ ++/* AT803x supports either the XTAL input pad, an internal PLL or the ++ * DSP as clock reference for the clock output pad. The XTAL reference ++ * is only used for 25 MHz output, all other frequencies need the PLL. ++ * The DSP as a clock reference is used in synchronous ethernet ++ * applications. ++ * ++ * By default the PLL is only enabled if there is a link. Otherwise ++ * the PHY will go into low power state and disabled the PLL. You can ++ * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always ++ * enabled. ++ */ ++#define AT803X_MMD7_CLK25M 0x8016 ++#define AT803X_CLK_OUT_MASK GENMASK(4, 2) ++#define AT803X_CLK_OUT_25MHZ_XTAL 0 ++#define AT803X_CLK_OUT_25MHZ_DSP 1 ++#define AT803X_CLK_OUT_50MHZ_PLL 2 ++#define AT803X_CLK_OUT_50MHZ_DSP 3 ++#define AT803X_CLK_OUT_62_5MHZ_PLL 4 ++#define AT803X_CLK_OUT_62_5MHZ_DSP 5 ++#define AT803X_CLK_OUT_125MHZ_PLL 6 ++#define AT803X_CLK_OUT_125MHZ_DSP 7 ++ ++/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask ++ * but doesn't support choosing between XTAL/PLL and DSP. ++ */ ++#define AT8035_CLK_OUT_MASK GENMASK(4, 3) ++ ++#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7) ++#define AT803X_CLK_OUT_STRENGTH_FULL 0 ++#define AT803X_CLK_OUT_STRENGTH_HALF 1 ++#define AT803X_CLK_OUT_STRENGTH_QUARTER 2 ++ ++#define AT803X_DEFAULT_DOWNSHIFT 5 ++#define AT803X_MIN_DOWNSHIFT 2 ++#define AT803X_MAX_DOWNSHIFT 9 ++ ++#define AT803X_MMD3_SMARTEEE_CTL1 0x805b ++#define AT803X_MMD3_SMARTEEE_CTL2 0x805c ++#define AT803X_MMD3_SMARTEEE_CTL3 0x805d ++#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8) ++ ++#define ATH9331_PHY_ID 0x004dd041 ++#define ATH8030_PHY_ID 0x004dd076 ++#define ATH8031_PHY_ID 0x004dd074 ++#define ATH8032_PHY_ID 0x004dd023 ++#define ATH8035_PHY_ID 0x004dd072 ++#define AT8030_PHY_ID_MASK 0xffffffef ++ ++#define QCA8081_PHY_ID 0x004dd101 ++ ++#define QCA8327_A_PHY_ID 0x004dd033 ++#define QCA8327_B_PHY_ID 0x004dd034 ++#define QCA8337_PHY_ID 0x004dd036 ++#define QCA9561_PHY_ID 0x004dd042 ++#define QCA8K_PHY_ID_MASK 0xffffffff ++ ++#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) ++ ++#define AT803X_PAGE_FIBER 0 ++#define AT803X_PAGE_COPPER 1 ++ ++/* don't turn off internal PLL */ ++#define AT803X_KEEP_PLL_ENABLED BIT(0) ++#define AT803X_DISABLE_SMARTEEE BIT(1) ++ ++/* disable hibernation mode */ ++#define AT803X_DISABLE_HIBERNATION_MODE BIT(2) ++ ++/* ADC threshold */ ++#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 ++#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) ++#define QCA808X_ADC_THRESHOLD_80MV 0 ++#define QCA808X_ADC_THRESHOLD_100MV 0xf0 ++#define QCA808X_ADC_THRESHOLD_200MV 0x0f ++#define QCA808X_ADC_THRESHOLD_300MV 0xff ++ ++/* CLD control */ ++#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 ++#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) ++#define QCA808X_8023AZ_AFE_EN 0x90 ++ ++/* AZ control */ ++#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 ++#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 ++#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E ++#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E ++#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 ++#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c ++#define QCA808X_TOP_OPTION1_DATA 0x0 ++ ++#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 ++#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 ++#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 ++#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad ++#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 ++#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 ++#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 ++#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 ++#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 ++#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 ++#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 ++#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 ++ ++/* master/slave seed config */ ++#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 ++#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) ++#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) ++#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 ++ ++/* Hibernation yields lower power consumpiton in contrast with normal operation mode. ++ * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. ++ */ ++#define QCA808X_DBG_AN_TEST 0xb ++#define QCA808X_HIBERNATION_EN BIT(15) ++ ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ ++MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_LICENSE("GPL"); ++ ++enum stat_access_type { ++ PHY, ++ MMD ++}; ++ ++struct at803x_hw_stat { ++ const char *string; ++ u8 reg; ++ u32 mask; ++ enum stat_access_type access_type; ++}; ++ ++static struct at803x_hw_stat qca83xx_hw_stats[] = { ++ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, ++ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, ++ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, ++}; ++ ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ ++struct at803x_priv { ++ int flags; ++ u16 clk_25m_reg; ++ u16 clk_25m_mask; ++ u8 smarteee_lpi_tw_1g; ++ u8 smarteee_lpi_tw_100m; ++ bool is_fiber; ++ bool is_1000basex; ++ struct regulator_dev *vddio_rdev; ++ struct regulator_dev *vddh_rdev; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++ int led_polarity_mode; ++}; ++ ++struct at803x_context { ++ u16 bmcr; ++ u16 advertise; ++ u16 control1000; ++ u16 int_enable; ++ u16 smart_speed; ++ u16 led_control; ++}; ++ ++static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, data); ++} ++ ++static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_read(phydev, AT803X_DEBUG_DATA); ++} ++ ++static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set) ++{ ++ u16 val; ++ int ret; ++ ++ ret = at803x_debug_reg_read(phydev, reg); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~clear; ++ val |= set; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, val); ++} ++ ++static int at803x_write_page(struct phy_device *phydev, int page) ++{ ++ int mask; ++ int set; ++ ++ if (page == AT803X_PAGE_COPPER) { ++ set = AT803X_BT_BX_REG_SEL; ++ mask = 0; ++ } else { ++ set = 0; ++ mask = AT803X_BT_BX_REG_SEL; ++ } ++ ++ return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); ++} ++ ++static int at803x_read_page(struct phy_device *phydev) ++{ ++ int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ ++ if (ccr < 0) ++ return ccr; ++ ++ if (ccr & AT803X_BT_BX_REG_SEL) ++ return AT803X_PAGE_COPPER; ++ ++ return AT803X_PAGE_FIBER; ++} ++ ++static int at803x_enable_rx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0, ++ AT803X_DEBUG_RX_CLK_DLY_EN); ++} ++ ++static int at803x_enable_tx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0, ++ AT803X_DEBUG_TX_CLK_DLY_EN); ++} ++ ++static int at803x_disable_rx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ AT803X_DEBUG_RX_CLK_DLY_EN, 0); ++} ++ ++static int at803x_disable_tx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, ++ AT803X_DEBUG_TX_CLK_DLY_EN, 0); ++} ++ ++/* save relevant PHY registers to private copy */ ++static void at803x_context_save(struct phy_device *phydev, ++ struct at803x_context *context) ++{ ++ context->bmcr = phy_read(phydev, MII_BMCR); ++ context->advertise = phy_read(phydev, MII_ADVERTISE); ++ context->control1000 = phy_read(phydev, MII_CTRL1000); ++ context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE); ++ context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED); ++ context->led_control = phy_read(phydev, AT803X_LED_CONTROL); ++} ++ ++/* restore relevant PHY registers from private copy */ ++static void at803x_context_restore(struct phy_device *phydev, ++ const struct at803x_context *context) ++{ ++ phy_write(phydev, MII_BMCR, context->bmcr); ++ phy_write(phydev, MII_ADVERTISE, context->advertise); ++ phy_write(phydev, MII_CTRL1000, context->control1000); ++ phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable); ++ phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed); ++ phy_write(phydev, AT803X_LED_CONTROL, context->led_control); ++} ++ ++static int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret, irq_enabled; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ struct net_device *ndev = phydev->attached_dev; ++ const u8 *mac; ++ unsigned int i; ++ static const unsigned int offsets[] = { ++ AT803X_LOC_MAC_ADDR_32_47_OFFSET, ++ AT803X_LOC_MAC_ADDR_16_31_OFFSET, ++ AT803X_LOC_MAC_ADDR_0_15_OFFSET, ++ }; ++ ++ if (!ndev) ++ return -ENODEV; ++ ++ mac = (const u8 *)ndev->dev_addr; ++ ++ if (!is_valid_ether_addr(mac)) ++ return -EINVAL; ++ ++ for (i = 0; i < 3; i++) ++ phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], ++ mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); ++ ++ /* Enable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); ++ if (ret) ++ return ret; ++ } else { ++ /* Disable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear WOL status */ ++ ret = phy_read(phydev, AT803X_INTR_STATUS); ++ if (ret < 0) ++ return ret; ++ ++ /* Check if there are other interrupts except for WOL triggered when PHY is ++ * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can ++ * be passed up to the interrupt PIN. ++ */ ++ irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (irq_enabled < 0) ++ return irq_enabled; ++ ++ irq_enabled &= ~AT803X_INTR_ENABLE_WOL; ++ if (ret & irq_enabled && !phy_polling_mode(phydev)) ++ phy_trigger_machine(phydev); ++ ++ return 0; ++} ++ ++static void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int value; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (value < 0) ++ return; ++ ++ if (value & AT803X_INTR_ENABLE_WOL) ++ wol->wolopts |= WAKE_MAGIC; ++} ++ ++static int qca83xx_get_sset_count(struct phy_device *phydev) ++{ ++ return ARRAY_SIZE(qca83xx_hw_stats); ++} ++ ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { ++ strscpy(data + i * ETH_GSTRING_LEN, ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) ++{ ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; ++ struct at803x_priv *priv = phydev->priv; ++ int val; ++ u64 ret; ++ ++ if (stat.access_type == MMD) ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); ++ else ++ val = phy_read(phydev, stat.reg); ++ ++ if (val < 0) { ++ ret = U64_MAX; ++ } else { ++ val = val & stat.mask; ++ priv->stats[i] += val; ++ ret = priv->stats[i]; ++ } ++ ++ return ret; ++} ++ ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); ++} ++ ++static int at803x_suspend(struct phy_device *phydev) ++{ ++ int value; ++ int wol_enabled; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ wol_enabled = value & AT803X_INTR_ENABLE_WOL; ++ ++ if (wol_enabled) ++ value = BMCR_ISOLATE; ++ else ++ value = BMCR_PDOWN; ++ ++ phy_modify(phydev, MII_BMCR, 0, value); ++ ++ return 0; ++} ++ ++static int at803x_resume(struct phy_device *phydev) ++{ ++ return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); ++} ++ ++static int at803x_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ u32 freq, strength, tw; ++ unsigned int sel; ++ int ret; ++ ++ if (!IS_ENABLED(CONFIG_OF_MDIO)) ++ return 0; ++ ++ if (of_property_read_bool(node, "qca,disable-smarteee")) ++ priv->flags |= AT803X_DISABLE_SMARTEEE; ++ ++ if (of_property_read_bool(node, "qca,disable-hibernation-mode")) ++ priv->flags |= AT803X_DISABLE_HIBERNATION_MODE; ++ ++ if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) { ++ if (!tw || tw > 255) { ++ phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n"); ++ return -EINVAL; ++ } ++ priv->smarteee_lpi_tw_1g = tw; ++ } ++ ++ if (!of_property_read_u32(node, "qca,smarteee-tw-us-100m", &tw)) { ++ if (!tw || tw > 255) { ++ phydev_err(phydev, "invalid qca,smarteee-tw-us-100m\n"); ++ return -EINVAL; ++ } ++ priv->smarteee_lpi_tw_100m = tw; ++ } ++ ++ ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq); ++ if (!ret) { ++ switch (freq) { ++ case 25000000: ++ sel = AT803X_CLK_OUT_25MHZ_XTAL; ++ break; ++ case 50000000: ++ sel = AT803X_CLK_OUT_50MHZ_PLL; ++ break; ++ case 62500000: ++ sel = AT803X_CLK_OUT_62_5MHZ_PLL; ++ break; ++ case 125000000: ++ sel = AT803X_CLK_OUT_125MHZ_PLL; ++ break; ++ default: ++ phydev_err(phydev, "invalid qca,clk-out-frequency\n"); ++ return -EINVAL; ++ } ++ ++ priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); ++ priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; ++ } ++ ++ ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); ++ if (!ret) { ++ priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK; ++ switch (strength) { ++ case AR803X_STRENGTH_FULL: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL; ++ break; ++ case AR803X_STRENGTH_HALF: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF; ++ break; ++ case AR803X_STRENGTH_QUARTER: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER; ++ break; ++ default: ++ phydev_err(phydev, "invalid qca,clk-out-strength\n"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static int at803x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct at803x_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ ++ phydev->priv = priv; ++ ++ ret = at803x_parse_dt(phydev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int at803x_get_features(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err; ++ ++ err = genphy_read_abilities(phydev); ++ if (err) ++ return err; ++ ++ if (phydev->drv->phy_id != ATH8031_PHY_ID) ++ return 0; ++ ++ /* AR8031/AR8033 have different status registers ++ * for copper and fiber operation. However, the ++ * extended status register is the same for both ++ * operation modes. ++ * ++ * As a result of that, ESTATUS_1000_XFULL is set ++ * to 1 even when operating in copper TP mode. ++ * ++ * Remove this mode from the supported link modes ++ * when not operating in 1000BaseX mode. ++ */ ++ if (!priv->is_1000basex) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->supported); ++ ++ return 0; ++} ++ ++static int at803x_smarteee_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ u16 mask = 0, val = 0; ++ int ret; ++ ++ if (priv->flags & AT803X_DISABLE_SMARTEEE) ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_MMD3_SMARTEEE_CTL3, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0); ++ ++ if (priv->smarteee_lpi_tw_1g) { ++ mask |= 0xff00; ++ val |= priv->smarteee_lpi_tw_1g << 8; ++ } ++ if (priv->smarteee_lpi_tw_100m) { ++ mask |= 0x00ff; ++ val |= priv->smarteee_lpi_tw_100m; ++ } ++ if (!mask) ++ return 0; ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1, ++ mask, val); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN); ++} ++ ++static int at803x_clk_out_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (!priv->clk_25m_mask) ++ return 0; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, ++ priv->clk_25m_mask, priv->clk_25m_reg); ++} ++ ++static int at8031_pll_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* The default after hardware reset is PLL OFF. After a soft reset, the ++ * values are retained. ++ */ ++ if (priv->flags & AT803X_KEEP_PLL_ENABLED) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_PLL_ON); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_PLL_ON, 0); ++} ++ ++static int at803x_hibernation_mode_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* The default after hardware reset is hibernation mode enabled. After ++ * software reset, the value is retained. ++ */ ++ if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE)) ++ return 0; ++ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0); ++} ++ ++static int at803x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* The RX and TX delay default is: ++ * after HW reset: RX delay enabled and TX delay disabled ++ * after SW reset: RX delay enabled, while TX delay retains the ++ * value before reset. ++ */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ++ ret = at803x_enable_rx_delay(phydev); ++ else ++ ret = at803x_disable_rx_delay(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ++ ret = at803x_enable_tx_delay(phydev); ++ else ++ ret = at803x_disable_tx_delay(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_smarteee_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_clk_out_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_hibernation_mode_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Ar803x extended next page bit is enabled by default. Cisco ++ * multigig switches read this bit and attempt to negotiate 10Gbps ++ * rates even if the next page bit is disabled. This is incorrect ++ * behaviour but we still need to accommodate it. XNP is only needed ++ * for 10Gbps support, so disable XNP. ++ */ ++ return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); ++} ++ ++static int at803x_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, AT803X_INTR_STATUS); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int at803x_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ int value; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_AUTONEG_ERR; ++ value |= AT803X_INTR_ENABLE_SPEED_CHANGED; ++ value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; ++ value |= AT803X_INTR_ENABLE_LINK_FAIL; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS; ++ ++ err = phy_write(phydev, AT803X_INTR_ENABLE, value); ++ } else { ++ err = phy_write(phydev, AT803X_INTR_ENABLE, 0); ++ if (err) ++ return err; ++ ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status, int_enabled; ++ ++ irq_status = phy_read(phydev, AT803X_INTR_STATUS); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* Read the current enabled interrupts */ ++ int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (int_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* See if this was one of our enabled interrupts */ ++ if (!(irq_status & int_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static void at803x_link_change_notify(struct phy_device *phydev) ++{ ++ /* ++ * Conduct a hardware reset for AT8030 every time a link loss is ++ * signalled. This is necessary to circumvent a hardware bug that ++ * occurs when the cable is unplugged while TX packets are pending ++ * in the FIFO. In such cases, the FIFO enters an error mode it ++ * cannot recover from by software. ++ */ ++ if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) { ++ struct at803x_context context; ++ ++ at803x_context_save(phydev, &context); ++ ++ phy_device_reset(phydev, 1); ++ usleep_range(1000, 2000); ++ phy_device_reset(phydev, 0); ++ usleep_range(1000, 2000); ++ ++ at803x_context_restore(phydev, &context); ++ ++ phydev_dbg(phydev, "%s(): phy was reset\n", __func__); ++ } ++} ++ ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) ++{ ++ int ss; ++ ++ /* Read the AT8035 PHY-Specific Status register, which indicates the ++ * speed and duplex that the PHY is actually using, irrespective of ++ * whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ int sfc, speed; ++ ++ sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); ++ if (sfc < 0) ++ return sfc; ++ ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; ++ ++ switch (speed) { ++ case AT803X_SS_SPEED_10: ++ phydev->speed = SPEED_10; ++ break; ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case QCA808X_SS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ } ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ if (ss & AT803X_SS_MDIX) ++ phydev->mdix = ETH_TP_MDI_X; ++ else ++ phydev->mdix = ETH_TP_MDI; ++ ++ switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { ++ case AT803X_SFC_MANUAL_MDI: ++ phydev->mdix_ctrl = ETH_TP_MDI; ++ break; ++ case AT803X_SFC_MANUAL_MDIX: ++ phydev->mdix_ctrl = ETH_TP_MDI_X; ++ break; ++ case AT803X_SFC_AUTOMATIC_CROSSOVER: ++ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int at803x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int err, old_link = phydev->link; ++ ++ /* Update the link, but return if there was an error */ ++ err = genphy_update_link(phydev); ++ if (err) ++ return err; ++ ++ /* why bother the PHY if nothing can have changed */ ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ return 0; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ err = genphy_read_lpa(phydev); ++ if (err < 0) ++ return err; ++ ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); ++ if (err < 0) ++ return err; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ return 0; ++} ++ ++static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) ++{ ++ u16 val; ++ ++ switch (ctrl) { ++ case ETH_TP_MDI: ++ val = AT803X_SFC_MANUAL_MDI; ++ break; ++ case ETH_TP_MDI_X: ++ val = AT803X_SFC_MANUAL_MDIX; ++ break; ++ case ETH_TP_MDI_AUTO: ++ val = AT803X_SFC_AUTOMATIC_CROSSOVER; ++ break; ++ default: ++ return 0; ++ } ++ ++ return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, ++ AT803X_SFC_MDI_CROSSOVER_MODE_M, ++ FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); ++} ++ ++static int at803x_prepare_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ /* Changes of the midx bits are disruptive to the normal operation; ++ * therefore any changes to these registers must be followed by a ++ * software reset to take effect. ++ */ ++ if (ret == 1) { ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); ++ ++ return genphy_config_aneg(phydev); ++} ++ ++static int at803x_get_downshift(struct phy_device *phydev, u8 *d) ++{ ++ int val; ++ ++ val = phy_read(phydev, AT803X_SMART_SPEED); ++ if (val < 0) ++ return val; ++ ++ if (val & AT803X_SMART_SPEED_ENABLE) ++ *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; ++ else ++ *d = DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ u16 mask, set; ++ int ret; ++ ++ switch (cnt) { ++ case DOWNSHIFT_DEV_DEFAULT_COUNT: ++ cnt = AT803X_DEFAULT_DOWNSHIFT; ++ fallthrough; ++ case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: ++ set = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER | ++ FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); ++ mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; ++ break; ++ case DOWNSHIFT_DEV_DISABLE: ++ set = 0; ++ mask = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); ++ ++ /* After changing the smart speed settings, we need to perform a ++ * software reset, use phy_init_hw() to make sure we set the ++ * reapply any values which might got lost during software reset. ++ */ ++ if (ret == 1) ++ ret = phy_init_hw(phydev); ++ ++ return ret; ++} ++ ++static int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int at803x_cable_test_result_trans(u16 status) ++{ ++ switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { ++ case AT803X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case AT803X_CDT_STATUS_STAT_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case AT803X_CDT_STATUS_STAT_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case AT803X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static bool at803x_cdt_test_failed(u16 status) ++{ ++ return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) == ++ AT803X_CDT_STATUS_STAT_FAIL; ++} ++ ++static bool at803x_cdt_fault_length_valid(u16 status) ++{ ++ switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { ++ case AT803X_CDT_STATUS_STAT_OPEN: ++ case AT803X_CDT_STATUS_STAT_SHORT: ++ return true; ++ } ++ return false; ++} ++ ++static int at803x_cdt_fault_length(int dt) ++{ ++ /* According to the datasheet the distance to the fault is ++ * DELTA_TIME * 0.824 meters. ++ * ++ * The author suspect the correct formula is: ++ * ++ * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 ++ * ++ * where c is the speed of light, VF is the velocity factor of ++ * the twisted pair cable, 125MHz the counter frequency and ++ * we need to divide by 2 because the hardware will measure the ++ * round trip time to the fault and back to the PHY. ++ * ++ * With a VF of 0.69 we get the factor 0.824 mentioned in the ++ * datasheet. ++ */ ++ return (dt * 824) / 10; ++} ++ ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) ++{ ++ return phy_write(phydev, AT803X_CDT, cdt_start); ++} ++ ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) ++{ ++ int val, ret; ++ ++ /* One test run takes about 25ms */ ++ ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, ++ !(val & cdt_en), ++ 30000, 100000, true); ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) ++{ ++ static const int ethtool_pair[] = { ++ ETHTOOL_A_CABLE_PAIR_A, ++ ETHTOOL_A_CABLE_PAIR_B, ++ ETHTOOL_A_CABLE_PAIR_C, ++ ETHTOOL_A_CABLE_PAIR_D, ++ }; ++ int ret, val; ++ ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read(phydev, AT803X_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ if (at803x_cdt_test_failed(val)) ++ return 0; ++ ++ ethnl_cable_test_result(phydev, ethtool_pair[pair], ++ at803x_cable_test_result_trans(val)); ++ ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); ++ ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], ++ at803x_cdt_fault_length(val)); ++ } ++ ++ return 1; ++} ++ ++static int at803x_cable_test_get_status(struct phy_device *phydev, ++ bool *finished, unsigned long pair_mask) ++{ ++ int retries = 20; ++ int pair, ret; ++ ++ *finished = false; ++ ++ /* According to the datasheet the CDT can be performed when ++ * there is no link partner or when the link partner is ++ * auto-negotiating. Starting the test will restart the AN ++ * automatically. It seems that doing this repeatedly we will ++ * get a slot where our link partner won't disturb our ++ * measurement. ++ */ ++ while (pair_mask && retries--) { ++ for_each_set_bit(pair, &pair_mask, 4) { ++ ret = at803x_cable_test_one_pair(phydev, pair); ++ if (ret < 0) ++ return ret; ++ if (ret) ++ clear_bit(pair, &pair_mask); ++ } ++ if (pair_mask) ++ msleep(250); ++ } ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static void at803x_cable_test_autoneg(struct phy_device *phydev) ++{ ++ /* Enable auto-negotiation, but advertise no capabilities, no link ++ * will be established. A restart of the auto-negotiation is not ++ * required, because the cable test will automatically break the link. ++ */ ++ phy_write(phydev, MII_BMCR, BMCR_ANENABLE); ++ phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); ++} ++ ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); ++} ++ ++static int at8031_probe(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ ++static int qca83xx_config_init(struct phy_device *phydev) ++{ ++ u8 switch_revision; ++ ++ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; ++ ++ switch (switch_revision) { ++ case 1: ++ /* For 100M waveform */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); ++ /* Turn on Gigabit clock */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); ++ break; ++ ++ case 2: ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); ++ fallthrough; ++ case 4: ++ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); ++ break; ++ } ++ ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ ++ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. ++ * Disable on init and enable only with 100m speed following ++ * qca original source code. ++ */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ ++ return qca83xx_config_init(phydev); ++} ++ ++static void qca83xx_link_change_notify(struct phy_device *phydev) ++{ ++ /* Set DAC Amplitude adjustment to +6% for 100m on link running */ ++ if (phydev->state == PHY_RUNNING) { ++ if (phydev->speed == SPEED_100) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, ++ QCA8327_DEBUG_MANU_CTRL_EN); ++ } else { ++ /* Reset DAC Amplitude adjustment */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ } ++} ++ ++static int qca83xx_resume(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ /* Skip reset if not suspended */ ++ if (!phydev->suspended) ++ return 0; ++ ++ /* Reinit the port, reset values set by suspend */ ++ qca83xx_config_init(phydev); ++ ++ /* Reset the port on port resume */ ++ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ++ /* On resume from suspend the switch execute a reset and ++ * restart auto-negotiation. Wait for reset to complete. ++ */ ++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), ++ 50000, 600000, true); ++ if (ret) ++ return ret; ++ ++ usleep_range(1000, 2000); ++ ++ return 0; ++} ++ ++static int qca83xx_suspend(struct phy_device *phydev) ++{ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, ++ AT803X_DEBUG_GATE_CLK_IN1000, 0); ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | ++ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); ++ ++ return 0; ++} ++ ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Enable fast retrain */ ++ ret = genphy_c45_fast_retrain(phydev, true); ++ if (ret) ++ return ret; ++ ++ phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, ++ QCA808X_TOP_OPTION1_DATA); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, ++ QCA808X_MMD3_DEBUG_1_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, ++ QCA808X_MMD3_DEBUG_4_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, ++ QCA808X_MMD3_DEBUG_5_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, ++ QCA808X_MMD3_DEBUG_3_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, ++ QCA808X_MMD3_DEBUG_6_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, ++ QCA808X_MMD3_DEBUG_2_VALUE); ++ ++ return 0; ++} ++ ++static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) ++{ ++ u16 seed_value; ++ ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); ++ ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); ++} ++ ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ ++static int qca808x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Active adc&vga on 802.3az for the link 1000M and 100M */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ if (ret) ++ return ret; ++ ++ /* Adjust the threshold on 802.3az for the link 1000M */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); ++ if (ret) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); ++ if (ret) ++ return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Configure adc threshold as 100mv for the link 10M */ ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); ++} ++ ++static int qca808x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); ++ if (ret < 0) ++ return ret; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ ret = genphy_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->link) { ++ if (phydev->speed == SPEED_2500) ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ else ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ } else { ++ /* generate seed as a lower random value to make PHY linked as SLAVE easily, ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * ++ * the reason for not putting this code into the function link_change_notify is ++ * the corner case where the link partner is also the qca8081 PHY and the seed ++ * value is configured as the same value, the link can't be up and no link change ++ * occurs. ++ */ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int qca808x_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; ++} ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_start(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* perform CDT with the following configs: ++ * 1. disable hibernation. ++ * 2. force PHY working in MDI mode. ++ * 3. for PHY working in 1000BaseT. ++ * 4. configure the threshold. ++ */ ++ ++ ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_config_mdix(phydev, ETH_TP_MDI); ++ if (ret < 0) ++ return ret; ++ ++ /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ ++ phydev->duplex = DUPLEX_FULL; ++ phydev->speed = SPEED_1000; ++ ret = genphy_c45_pma_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* configure the thresholds for open, short, pair ok test */ ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ ++ return 0; ++} ++ ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ ++static struct phy_driver at803x_driver[] = { ++{ ++ /* Qualcomm Atheros AR8035 */ ++ PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), ++ .name = "Qualcomm Atheros AR8035", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at8035_probe, ++ .config_aneg = at803x_config_aneg, ++ .config_init = at803x_config_init, ++ .soft_reset = genphy_soft_reset, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_GBIT_FEATURES */ ++ .read_status = at803x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, ++}, { ++ /* Qualcomm Atheros AR8030 */ ++ .phy_id = ATH8030_PHY_ID, ++ .name = "Qualcomm Atheros AR8030", ++ .phy_id_mask = AT8030_PHY_ID_MASK, ++ .probe = at8035_probe, ++ .config_init = at803x_config_init, ++ .link_change_notify = at803x_link_change_notify, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++}, { ++ /* Qualcomm Atheros AR8031/AR8033 */ ++ PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), ++ .name = "Qualcomm Atheros AR8031/AR8033", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at8031_probe, ++ .config_init = at8031_config_init, ++ .config_aneg = at803x_config_aneg, ++ .soft_reset = genphy_soft_reset, ++ .set_wol = at8031_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .read_page = at803x_read_page, ++ .write_page = at803x_write_page, ++ .get_features = at803x_get_features, ++ .read_status = at8031_read_status, ++ .config_intr = at8031_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, ++}, { ++ /* Qualcomm Atheros AR8032 */ ++ PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), ++ .name = "Qualcomm Atheros AR8032", ++ .probe = at803x_probe, ++ .flags = PHY_POLL_CABLE_TEST, ++ .config_init = at803x_config_init, ++ .link_change_notify = at803x_link_change_notify, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++}, { ++ /* ATHEROS AR9331 */ ++ PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), ++ .name = "Qualcomm Atheros AR9331 built-in PHY", ++ .probe = at803x_probe, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++ .read_status = at803x_read_status, ++ .soft_reset = genphy_soft_reset, ++ .config_aneg = at803x_config_aneg, ++}, { ++ /* Qualcomm Atheros QCA9561 */ ++ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID), ++ .name = "Qualcomm Atheros QCA9561 built-in PHY", ++ .probe = at803x_probe, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++ .read_status = at803x_read_status, ++ .soft_reset = genphy_soft_reset, ++ .config_aneg = at803x_config_aneg, ++}, { ++ /* QCA8337 */ ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8337 internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8337_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-A from switch QCA8327-AL1A */ ++ .phy_id = QCA8327_A_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-A internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-B from switch QCA8327-BL1A */ ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-B internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* Qualcomm QCA8081 */ ++ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), ++ .name = "Qualcomm QCA8081", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at803x_probe, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .get_features = qca808x_get_features, ++ .config_aneg = qca808x_config_aneg, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_status = qca808x_read_status, ++ .config_init = qca808x_config_init, ++ .soft_reset = qca808x_soft_reset, ++ .cable_test_start = qca808x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, ++}, }; ++ ++module_phy_driver(at803x_driver); ++ ++static struct mdio_device_id __maybe_unused atheros_tbl[] = { ++ { ATH8030_PHY_ID, AT8030_PHY_ID_MASK }, ++ { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, atheros_tbl); diff --git a/target/linux/generic/backport-6.6/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch b/target/linux/generic/backport-6.6/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch new file mode 100644 index 0000000000..7d0e1f4a28 --- /dev/null +++ b/target/linux/generic/backport-6.6/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch @@ -0,0 +1,243 @@ +From 6fb760972c49490b03f3db2ad64cf30bdd28c54a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:20 +0100 +Subject: [PATCH 2/5] net: phy: qcom: create and move functions to shared + library + +Create and move functions to shared library in preparation for qca83xx +PHY Family to be detached from at803x driver. + +Only the shared defines are moved to the shared qcom.h header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-3-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 4 ++ + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 69 +---------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 53 ++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 34 ++++++++++++++ + 5 files changed, 94 insertions(+), 67 deletions(-) + create mode 100644 drivers/net/phy/qcom/qcom-phy-lib.c + create mode 100644 drivers/net/phy/qcom/qcom.h + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -1,6 +1,10 @@ + # SPDX-License-Identifier: GPL-2.0-only ++config QCOM_NET_PHYLIB ++ tristate ++ + config AT803X_PHY + tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ select QCOM_NET_PHYLIB + depends on REGULATOR + help + Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -1,2 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -22,6 +22,8 @@ + #include + #include + ++#include "qcom.h" ++ + #define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 + #define AT803X_SFC_ASSERT_CRS BIT(11) + #define AT803X_SFC_FORCE_LINK BIT(10) +@@ -84,9 +86,6 @@ + #define AT803X_REG_CHIP_CONFIG 0x1f + #define AT803X_BT_BX_REG_SEL 0x8000 + +-#define AT803X_DEBUG_ADDR 0x1D +-#define AT803X_DEBUG_DATA 0x1E +- + #define AT803X_MODE_CFG_MASK 0x0F + #define AT803X_MODE_CFG_BASET_RGMII 0x00 + #define AT803X_MODE_CFG_BASET_SGMII 0x01 +@@ -103,19 +102,6 @@ + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + +-#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 +-#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) +-#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) +-#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) +- +-#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 +-#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) +- +-#define AT803X_DEBUG_REG_HIB_CTRL 0x0b +-#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) +-#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) +-#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) +- + #define AT803X_DEBUG_REG_3C 0x3C + + #define AT803X_DEBUG_REG_GREEN 0x3D +@@ -393,18 +379,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-enum stat_access_type { +- PHY, +- MMD +-}; +- +-struct at803x_hw_stat { +- const char *string; +- u8 reg; +- u32 mask; +- enum stat_access_type access_type; +-}; +- + static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +@@ -439,45 +413,6 @@ struct at803x_context { + u16 led_control; + }; + +-static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, data); +-} +- +-static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_read(phydev, AT803X_DEBUG_DATA); +-} +- +-static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, +- u16 clear, u16 set) +-{ +- u16 val; +- int ret; +- +- ret = at803x_debug_reg_read(phydev, reg); +- if (ret < 0) +- return ret; +- +- val = ret & 0xffff; +- val &= ~clear; +- val |= set; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, val); +-} +- + static int at803x_write_page(struct phy_device *phydev, int page) + { + int mask; +--- /dev/null ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++ ++#include "qcom.h" ++ ++MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++ ++int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_read(phydev, AT803X_DEBUG_DATA); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_read); ++ ++int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set) ++{ ++ u16 val; ++ int ret; ++ ++ ret = at803x_debug_reg_read(phydev, reg); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~clear; ++ val |= set; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, val); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_mask); ++ ++int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, data); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_write); +--- /dev/null ++++ b/drivers/net/phy/qcom/qcom.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#define AT803X_DEBUG_ADDR 0x1D ++#define AT803X_DEBUG_DATA 0x1E ++ ++#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 ++#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) ++#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) ++#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) ++ ++#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 ++#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) ++ ++#define AT803X_DEBUG_REG_HIB_CTRL 0x0b ++#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) ++#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) ++#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) ++ ++enum stat_access_type { ++ PHY, ++ MMD ++}; ++ ++struct at803x_hw_stat { ++ const char *string; ++ u8 reg; ++ u32 mask; ++ enum stat_access_type access_type; ++}; ++ ++int at803x_debug_reg_read(struct phy_device *phydev, u16 reg); ++int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set); ++int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data); diff --git a/target/linux/generic/backport-6.6/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch b/target/linux/generic/backport-6.6/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch new file mode 100644 index 0000000000..6ac09dcb9a --- /dev/null +++ b/target/linux/generic/backport-6.6/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch @@ -0,0 +1,638 @@ +From 2e45d404d99d43bb7127b74b5dea8818df64996c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:21 +0100 +Subject: [PATCH 3/5] net: phy: qcom: deatch qca83xx PHY driver from at803x + +Deatch qca83xx PHY driver from at803x. + +The QCA83xx PHYs implement specific function and doesn't use generic +at803x so it can be detached from the driver and moved to a dedicated +one. + +Probe function and priv struct is reimplemented to allocate and use +only the qca83xx specific data. Unused data from at803x PHY driver +are dropped from at803x priv struct. + +This is to make slimmer PHY drivers instead of including lots of bloat +that would never be used in specific SoC. + +A new Kconfig flag QCA83XX_PHY is introduced to compile the new +introduced PHY driver. + +As the Kconfig name starts with Qualcomm the same order is kept. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-4-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 11 +- + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 235 ---------------------------- + drivers/net/phy/qcom/qca83xx.c | 275 +++++++++++++++++++++++++++++++++ + 4 files changed, 284 insertions(+), 238 deletions(-) + create mode 100644 drivers/net/phy/qcom/qca83xx.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -3,9 +3,14 @@ config QCOM_NET_PHYLIB + tristate + + config AT803X_PHY +- tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ tristate "Qualcomm Atheros AR803X PHYs" + select QCOM_NET_PHYLIB + depends on REGULATOR + help +- Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +- QCA8337(Internal qca8k PHY) model ++ Currently supports the AR8030, AR8031, AR8033, AR8035 model ++ ++config QCA83XX_PHY ++ tristate "Qualcomm Atheros QCA833x PHYs" ++ select QCOM_NET_PHYLIB ++ help ++ Currently supports the internal QCA8337(Internal qca8k PHY) model +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o ++obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -102,17 +102,10 @@ + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + +-#define AT803X_DEBUG_REG_3C 0x3C +- +-#define AT803X_DEBUG_REG_GREEN 0x3D +-#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) +- + #define AT803X_DEBUG_REG_1F 0x1F + #define AT803X_DEBUG_PLL_ON BIT(2) + #define AT803X_DEBUG_RGMII_1V8 BIT(3) + +-#define MDIO_AZ_DEBUG 0x800D +- + /* AT803x supports either the XTAL input pad, an internal PLL or the + * DSP as clock reference for the clock output pad. The XTAL reference + * is only used for 25 MHz output, all other frequencies need the PLL. +@@ -163,13 +156,7 @@ + + #define QCA8081_PHY_ID 0x004dd101 + +-#define QCA8327_A_PHY_ID 0x004dd033 +-#define QCA8327_B_PHY_ID 0x004dd034 +-#define QCA8337_PHY_ID 0x004dd036 + #define QCA9561_PHY_ID 0x004dd042 +-#define QCA8K_PHY_ID_MASK 0xffffffff +- +-#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) + + #define AT803X_PAGE_FIBER 0 + #define AT803X_PAGE_COPPER 1 +@@ -379,12 +366,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-static struct at803x_hw_stat qca83xx_hw_stats[] = { +- { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, +- { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +- { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +-}; +- + struct at803x_ss_mask { + u16 speed_mask; + u8 speed_shift; +@@ -400,7 +381,6 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + int led_polarity_mode; + }; + +@@ -564,53 +544,6 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int qca83xx_get_sset_count(struct phy_device *phydev) +-{ +- return ARRAY_SIZE(qca83xx_hw_stats); +-} +- +-static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { +- strscpy(data + i * ETH_GSTRING_LEN, +- qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); +- } +-} +- +-static u64 qca83xx_get_stat(struct phy_device *phydev, int i) +-{ +- struct at803x_hw_stat stat = qca83xx_hw_stats[i]; +- struct at803x_priv *priv = phydev->priv; +- int val; +- u64 ret; +- +- if (stat.access_type == MMD) +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); +- else +- val = phy_read(phydev, stat.reg); +- +- if (val < 0) { +- ret = U64_MAX; +- } else { +- val = val & stat.mask; +- priv->stats[i] += val; +- ret = priv->stats[i]; +- } +- +- return ret; +-} +- +-static void qca83xx_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) +- data[i] = qca83xx_get_stat(phydev, i); +-} +- + static int at803x_suspend(struct phy_device *phydev) + { + int value; +@@ -1707,124 +1640,6 @@ static int at8035_probe(struct phy_devic + return at8035_parse_dt(phydev); + } + +-static int qca83xx_config_init(struct phy_device *phydev) +-{ +- u8 switch_revision; +- +- switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; +- +- switch (switch_revision) { +- case 1: +- /* For 100M waveform */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); +- /* Turn on Gigabit clock */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); +- break; +- +- case 2: +- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); +- fallthrough; +- case 4: +- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); +- break; +- } +- +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; +-} +- +-static int qca8327_config_init(struct phy_device *phydev) +-{ +- /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. +- * Disable on init and enable only with 100m speed following +- * qca original source code. +- */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- +- return qca83xx_config_init(phydev); +-} +- +-static void qca83xx_link_change_notify(struct phy_device *phydev) +-{ +- /* Set DAC Amplitude adjustment to +6% for 100m on link running */ +- if (phydev->state == PHY_RUNNING) { +- if (phydev->speed == SPEED_100) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, +- QCA8327_DEBUG_MANU_CTRL_EN); +- } else { +- /* Reset DAC Amplitude adjustment */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- } +-} +- +-static int qca83xx_resume(struct phy_device *phydev) +-{ +- int ret, val; +- +- /* Skip reset if not suspended */ +- if (!phydev->suspended) +- return 0; +- +- /* Reinit the port, reset values set by suspend */ +- qca83xx_config_init(phydev); +- +- /* Reset the port on port resume */ +- phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- +- /* On resume from suspend the switch execute a reset and +- * restart auto-negotiation. Wait for reset to complete. +- */ +- ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), +- 50000, 600000, true); +- if (ret) +- return ret; +- +- usleep_range(1000, 2000); +- +- return 0; +-} +- +-static int qca83xx_suspend(struct phy_device *phydev) +-{ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, +- AT803X_DEBUG_GATE_CLK_IN1000, 0); +- +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | +- AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); +- +- return 0; +-} +- +-static int qca8337_suspend(struct phy_device *phydev) +-{ +- /* Only QCA8337 support actual suspend. */ +- genphy_suspend(phydev); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca8327_suspend(struct phy_device *phydev) +-{ +- u16 mask = 0; +- +- /* QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- +- return qca83xx_suspend(phydev); +-} +- + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2599,53 +2414,6 @@ static struct phy_driver at803x_driver[] + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, + }, { +- /* QCA8337 */ +- .phy_id = QCA8337_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8337 internal PHY", +- /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8337_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-A from switch QCA8327-AL1A */ +- .phy_id = QCA8327_A_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-A internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-B from switch QCA8327-BL1A */ +- .phy_id = QCA8327_B_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-B internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { + /* Qualcomm QCA8081 */ + PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), + .name = "Qualcomm QCA8081", +@@ -2683,9 +2451,6 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, + { } +--- /dev/null ++++ b/drivers/net/phy/qcom/qca83xx.c +@@ -0,0 +1,275 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include ++#include ++ ++#include "qcom.h" ++ ++#define AT803X_DEBUG_REG_3C 0x3C ++ ++#define AT803X_DEBUG_REG_GREEN 0x3D ++#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) ++ ++#define MDIO_AZ_DEBUG 0x800D ++ ++#define QCA8327_A_PHY_ID 0x004dd033 ++#define QCA8327_B_PHY_ID 0x004dd034 ++#define QCA8337_PHY_ID 0x004dd036 ++#define QCA8K_PHY_ID_MASK 0xffffffff ++ ++#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) ++ ++static struct at803x_hw_stat qca83xx_hw_stats[] = { ++ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, ++ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, ++ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, ++}; ++ ++struct qca83xx_priv { ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++}; ++ ++MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++ ++static int qca83xx_get_sset_count(struct phy_device *phydev) ++{ ++ return ARRAY_SIZE(qca83xx_hw_stats); ++} ++ ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { ++ strscpy(data + i * ETH_GSTRING_LEN, ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) ++{ ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; ++ struct qca83xx_priv *priv = phydev->priv; ++ int val; ++ u64 ret; ++ ++ if (stat.access_type == MMD) ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); ++ else ++ val = phy_read(phydev, stat.reg); ++ ++ if (val < 0) { ++ ret = U64_MAX; ++ } else { ++ val = val & stat.mask; ++ priv->stats[i] += val; ++ ret = priv->stats[i]; ++ } ++ ++ return ret; ++} ++ ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); ++} ++ ++static int qca83xx_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca83xx_priv *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca83xx_config_init(struct phy_device *phydev) ++{ ++ u8 switch_revision; ++ ++ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; ++ ++ switch (switch_revision) { ++ case 1: ++ /* For 100M waveform */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); ++ /* Turn on Gigabit clock */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); ++ break; ++ ++ case 2: ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); ++ fallthrough; ++ case 4: ++ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); ++ break; ++ } ++ ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ ++ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. ++ * Disable on init and enable only with 100m speed following ++ * qca original source code. ++ */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ ++ return qca83xx_config_init(phydev); ++} ++ ++static void qca83xx_link_change_notify(struct phy_device *phydev) ++{ ++ /* Set DAC Amplitude adjustment to +6% for 100m on link running */ ++ if (phydev->state == PHY_RUNNING) { ++ if (phydev->speed == SPEED_100) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, ++ QCA8327_DEBUG_MANU_CTRL_EN); ++ } else { ++ /* Reset DAC Amplitude adjustment */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ } ++} ++ ++static int qca83xx_resume(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ /* Skip reset if not suspended */ ++ if (!phydev->suspended) ++ return 0; ++ ++ /* Reinit the port, reset values set by suspend */ ++ qca83xx_config_init(phydev); ++ ++ /* Reset the port on port resume */ ++ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ++ /* On resume from suspend the switch execute a reset and ++ * restart auto-negotiation. Wait for reset to complete. ++ */ ++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), ++ 50000, 600000, true); ++ if (ret) ++ return ret; ++ ++ usleep_range(1000, 2000); ++ ++ return 0; ++} ++ ++static int qca83xx_suspend(struct phy_device *phydev) ++{ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, ++ AT803X_DEBUG_GATE_CLK_IN1000, 0); ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | ++ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); ++ ++ return 0; ++} ++ ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static struct phy_driver qca83xx_driver[] = { ++{ ++ /* QCA8337 */ ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8337 internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8337_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-A from switch QCA8327-AL1A */ ++ .phy_id = QCA8327_A_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-A internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-B from switch QCA8327-BL1A */ ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-B internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, }; ++ ++module_phy_driver(qca83xx_driver); ++ ++static struct mdio_device_id __maybe_unused qca83xx_tbl[] = { ++ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, qca83xx_tbl); diff --git a/target/linux/generic/backport-6.6/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch b/target/linux/generic/backport-6.6/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch new file mode 100644 index 0000000000..9c43ad13b4 --- /dev/null +++ b/target/linux/generic/backport-6.6/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch @@ -0,0 +1,1014 @@ +From 249d2b80e4db0e38503ed0ec2af6c7401bc099b9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:22 +0100 +Subject: [PATCH 4/5] net: phy: qcom: move additional functions to shared + library + +Move additional functions to shared library in preparation for qca808x +PHY Family to be detached from at803x driver. + +Only the shared defines are moved to the shared qcom.h header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-5-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/at803x.c | 426 +--------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 376 ++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 86 ++++++ + 3 files changed, 463 insertions(+), 425 deletions(-) + +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -24,65 +24,11 @@ + + #include "qcom.h" + +-#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 +-#define AT803X_SFC_ASSERT_CRS BIT(11) +-#define AT803X_SFC_FORCE_LINK BIT(10) +-#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) +-#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 +-#define AT803X_SFC_MANUAL_MDIX 0x1 +-#define AT803X_SFC_MANUAL_MDI 0x0 +-#define AT803X_SFC_SQE_TEST BIT(2) +-#define AT803X_SFC_POLARITY_REVERSAL BIT(1) +-#define AT803X_SFC_DISABLE_JABBER BIT(0) +- +-#define AT803X_SPECIFIC_STATUS 0x11 +-#define AT803X_SS_SPEED_MASK GENMASK(15, 14) +-#define AT803X_SS_SPEED_1000 2 +-#define AT803X_SS_SPEED_100 1 +-#define AT803X_SS_SPEED_10 0 +-#define AT803X_SS_DUPLEX BIT(13) +-#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) +-#define AT803X_SS_MDIX BIT(6) +- +-#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) +-#define QCA808X_SS_SPEED_2500 4 +- +-#define AT803X_INTR_ENABLE 0x12 +-#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) +-#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) +-#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) +-#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) +-#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) +-#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) +-#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) +-#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) +-#define AT803X_INTR_ENABLE_WOL BIT(0) +- +-#define AT803X_INTR_STATUS 0x13 +- +-#define AT803X_SMART_SPEED 0x14 +-#define AT803X_SMART_SPEED_ENABLE BIT(5) +-#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) +-#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) +-#define AT803X_CDT 0x16 +-#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) +-#define AT803X_CDT_ENABLE_TEST BIT(0) +-#define AT803X_CDT_STATUS 0x1c +-#define AT803X_CDT_STATUS_STAT_NORMAL 0 +-#define AT803X_CDT_STATUS_STAT_SHORT 1 +-#define AT803X_CDT_STATUS_STAT_OPEN 2 +-#define AT803X_CDT_STATUS_STAT_FAIL 3 +-#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) +-#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) + #define AT803X_LED_CONTROL 0x18 + + #define AT803X_PHY_MMD3_WOL_CTRL 0x8012 + #define AT803X_WOL_EN BIT(5) +-#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +-#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +-#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++ + #define AT803X_REG_CHIP_CONFIG 0x1f + #define AT803X_BT_BX_REG_SEL 0x8000 + +@@ -138,10 +84,6 @@ + #define AT803X_CLK_OUT_STRENGTH_HALF 1 + #define AT803X_CLK_OUT_STRENGTH_QUARTER 2 + +-#define AT803X_DEFAULT_DOWNSHIFT 5 +-#define AT803X_MIN_DOWNSHIFT 2 +-#define AT803X_MAX_DOWNSHIFT 9 +- + #define AT803X_MMD3_SMARTEEE_CTL1 0x805b + #define AT803X_MMD3_SMARTEEE_CTL2 0x805c + #define AT803X_MMD3_SMARTEEE_CTL3 0x805d +@@ -366,11 +308,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-struct at803x_ss_mask { +- u16 speed_mask; +- u8 speed_shift; +-}; +- + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -470,80 +407,6 @@ static void at803x_context_restore(struc + phy_write(phydev, AT803X_LED_CONTROL, context->led_control); + } + +-static int at803x_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret, irq_enabled; +- +- if (wol->wolopts & WAKE_MAGIC) { +- struct net_device *ndev = phydev->attached_dev; +- const u8 *mac; +- unsigned int i; +- static const unsigned int offsets[] = { +- AT803X_LOC_MAC_ADDR_32_47_OFFSET, +- AT803X_LOC_MAC_ADDR_16_31_OFFSET, +- AT803X_LOC_MAC_ADDR_0_15_OFFSET, +- }; +- +- if (!ndev) +- return -ENODEV; +- +- mac = (const u8 *)ndev->dev_addr; +- +- if (!is_valid_ether_addr(mac)) +- return -EINVAL; +- +- for (i = 0; i < 3; i++) +- phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], +- mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); +- +- /* Enable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); +- if (ret) +- return ret; +- } else { +- /* Disable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); +- if (ret) +- return ret; +- } +- +- /* Clear WOL status */ +- ret = phy_read(phydev, AT803X_INTR_STATUS); +- if (ret < 0) +- return ret; +- +- /* Check if there are other interrupts except for WOL triggered when PHY is +- * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can +- * be passed up to the interrupt PIN. +- */ +- irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (irq_enabled < 0) +- return irq_enabled; +- +- irq_enabled &= ~AT803X_INTR_ENABLE_WOL; +- if (ret & irq_enabled && !phy_polling_mode(phydev)) +- phy_trigger_machine(phydev); +- +- return 0; +-} +- +-static void at803x_get_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int value; +- +- wol->supported = WAKE_MAGIC; +- wol->wolopts = 0; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- if (value < 0) +- return; +- +- if (value & AT803X_INTR_ENABLE_WOL) +- wol->wolopts |= WAKE_MAGIC; +-} +- + static int at803x_suspend(struct phy_device *phydev) + { + int value; +@@ -816,73 +679,6 @@ static int at803x_config_init(struct phy + return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); + } + +-static int at803x_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, AT803X_INTR_STATUS); +- +- return (err < 0) ? err : 0; +-} +- +-static int at803x_config_intr(struct phy_device *phydev) +-{ +- int err; +- int value; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_AUTONEG_ERR; +- value |= AT803X_INTR_ENABLE_SPEED_CHANGED; +- value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; +- value |= AT803X_INTR_ENABLE_LINK_FAIL; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- +- err = phy_write(phydev, AT803X_INTR_ENABLE, value); +- } else { +- err = phy_write(phydev, AT803X_INTR_ENABLE, 0); +- if (err) +- return err; +- +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status, int_enabled; +- +- irq_status = phy_read(phydev, AT803X_INTR_STATUS); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* Read the current enabled interrupts */ +- int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (int_enabled < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* See if this was one of our enabled interrupts */ +- if (!(irq_status & int_enabled)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- + static void at803x_link_change_notify(struct phy_device *phydev) + { + /* +@@ -908,69 +704,6 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev, +- struct at803x_ss_mask ss_mask) +-{ +- int ss; +- +- /* Read the AT8035 PHY-Specific Status register, which indicates the +- * speed and duplex that the PHY is actually using, irrespective of +- * whether we are in autoneg mode or not. +- */ +- ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); +- if (ss < 0) +- return ss; +- +- if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { +- int sfc, speed; +- +- sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); +- if (sfc < 0) +- return sfc; +- +- speed = ss & ss_mask.speed_mask; +- speed >>= ss_mask.speed_shift; +- +- switch (speed) { +- case AT803X_SS_SPEED_10: +- phydev->speed = SPEED_10; +- break; +- case AT803X_SS_SPEED_100: +- phydev->speed = SPEED_100; +- break; +- case AT803X_SS_SPEED_1000: +- phydev->speed = SPEED_1000; +- break; +- case QCA808X_SS_SPEED_2500: +- phydev->speed = SPEED_2500; +- break; +- } +- if (ss & AT803X_SS_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- if (ss & AT803X_SS_MDIX) +- phydev->mdix = ETH_TP_MDI_X; +- else +- phydev->mdix = ETH_TP_MDI; +- +- switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { +- case AT803X_SFC_MANUAL_MDI: +- phydev->mdix_ctrl = ETH_TP_MDI; +- break; +- case AT803X_SFC_MANUAL_MDIX: +- phydev->mdix_ctrl = ETH_TP_MDI_X; +- break; +- case AT803X_SFC_AUTOMATIC_CROSSOVER: +- phydev->mdix_ctrl = ETH_TP_MDI_AUTO; +- break; +- } +- } +- +- return 0; +-} +- + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_ss_mask ss_mask = { 0 }; +@@ -1006,50 +739,6 @@ static int at803x_read_status(struct phy + return 0; + } + +-static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) +-{ +- u16 val; +- +- switch (ctrl) { +- case ETH_TP_MDI: +- val = AT803X_SFC_MANUAL_MDI; +- break; +- case ETH_TP_MDI_X: +- val = AT803X_SFC_MANUAL_MDIX; +- break; +- case ETH_TP_MDI_AUTO: +- val = AT803X_SFC_AUTOMATIC_CROSSOVER; +- break; +- default: +- return 0; +- } +- +- return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, +- AT803X_SFC_MDI_CROSSOVER_MODE_M, +- FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); +-} +- +-static int at803x_prepare_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +- if (ret < 0) +- return ret; +- +- /* Changes of the midx bits are disruptive to the normal operation; +- * therefore any changes to these registers must be followed by a +- * software reset to take effect. +- */ +- if (ret == 1) { +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- + static int at803x_config_aneg(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -1065,80 +754,6 @@ static int at803x_config_aneg(struct phy + return genphy_config_aneg(phydev); + } + +-static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +-{ +- int val; +- +- val = phy_read(phydev, AT803X_SMART_SPEED); +- if (val < 0) +- return val; +- +- if (val & AT803X_SMART_SPEED_ENABLE) +- *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; +- else +- *d = DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- u16 mask, set; +- int ret; +- +- switch (cnt) { +- case DOWNSHIFT_DEV_DEFAULT_COUNT: +- cnt = AT803X_DEFAULT_DOWNSHIFT; +- fallthrough; +- case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: +- set = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER | +- FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); +- mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; +- break; +- case DOWNSHIFT_DEV_DISABLE: +- set = 0; +- mask = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER; +- break; +- default: +- return -EINVAL; +- } +- +- ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); +- +- /* After changing the smart speed settings, we need to perform a +- * software reset, use phy_init_hw() to make sure we set the +- * reapply any values which might got lost during software reset. +- */ +- if (ret == 1) +- ret = phy_init_hw(phydev); +- +- return ret; +-} +- +-static int at803x_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- + static int at803x_cable_test_result_trans(u16 status) + { + switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +@@ -1170,45 +785,6 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(int dt) +-{ +- /* According to the datasheet the distance to the fault is +- * DELTA_TIME * 0.824 meters. +- * +- * The author suspect the correct formula is: +- * +- * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 +- * +- * where c is the speed of light, VF is the velocity factor of +- * the twisted pair cable, 125MHz the counter frequency and +- * we need to divide by 2 because the hardware will measure the +- * round trip time to the fault and back to the PHY. +- * +- * With a VF of 0.69 we get the factor 0.824 mentioned in the +- * datasheet. +- */ +- return (dt * 824) / 10; +-} +- +-static int at803x_cdt_start(struct phy_device *phydev, +- u32 cdt_start) +-{ +- return phy_write(phydev, AT803X_CDT, cdt_start); +-} +- +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev, +- u32 cdt_en) +-{ +- int val, ret; +- +- /* One test run takes about 25ms */ +- ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +- !(val & cdt_en), +- 30000, 100000, true); +- +- return ret < 0 ? ret : 0; +-} +- + static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) + { + static const int ethtool_pair[] = { +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -3,6 +3,9 @@ + #include + #include + ++#include ++#include ++ + #include "qcom.h" + + MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions"); +@@ -51,3 +54,376 @@ int at803x_debug_reg_write(struct phy_de + return phy_write(phydev, AT803X_DEBUG_DATA, data); + } + EXPORT_SYMBOL_GPL(at803x_debug_reg_write); ++ ++int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret, irq_enabled; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ struct net_device *ndev = phydev->attached_dev; ++ const u8 *mac; ++ unsigned int i; ++ static const unsigned int offsets[] = { ++ AT803X_LOC_MAC_ADDR_32_47_OFFSET, ++ AT803X_LOC_MAC_ADDR_16_31_OFFSET, ++ AT803X_LOC_MAC_ADDR_0_15_OFFSET, ++ }; ++ ++ if (!ndev) ++ return -ENODEV; ++ ++ mac = (const u8 *)ndev->dev_addr; ++ ++ if (!is_valid_ether_addr(mac)) ++ return -EINVAL; ++ ++ for (i = 0; i < 3; i++) ++ phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], ++ mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); ++ ++ /* Enable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); ++ if (ret) ++ return ret; ++ } else { ++ /* Disable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear WOL status */ ++ ret = phy_read(phydev, AT803X_INTR_STATUS); ++ if (ret < 0) ++ return ret; ++ ++ /* Check if there are other interrupts except for WOL triggered when PHY is ++ * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can ++ * be passed up to the interrupt PIN. ++ */ ++ irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (irq_enabled < 0) ++ return irq_enabled; ++ ++ irq_enabled &= ~AT803X_INTR_ENABLE_WOL; ++ if (ret & irq_enabled && !phy_polling_mode(phydev)) ++ phy_trigger_machine(phydev); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_set_wol); ++ ++void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int value; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (value < 0) ++ return; ++ ++ if (value & AT803X_INTR_ENABLE_WOL) ++ wol->wolopts |= WAKE_MAGIC; ++} ++EXPORT_SYMBOL_GPL(at803x_get_wol); ++ ++int at803x_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, AT803X_INTR_STATUS); ++ ++ return (err < 0) ? err : 0; ++} ++EXPORT_SYMBOL_GPL(at803x_ack_interrupt); ++ ++int at803x_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ int value; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_AUTONEG_ERR; ++ value |= AT803X_INTR_ENABLE_SPEED_CHANGED; ++ value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; ++ value |= AT803X_INTR_ENABLE_LINK_FAIL; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS; ++ ++ err = phy_write(phydev, AT803X_INTR_ENABLE, value); ++ } else { ++ err = phy_write(phydev, AT803X_INTR_ENABLE, 0); ++ if (err) ++ return err; ++ ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(at803x_config_intr); ++ ++irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status, int_enabled; ++ ++ irq_status = phy_read(phydev, AT803X_INTR_STATUS); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* Read the current enabled interrupts */ ++ int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (int_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* See if this was one of our enabled interrupts */ ++ if (!(irq_status & int_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++EXPORT_SYMBOL_GPL(at803x_handle_interrupt); ++ ++int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) ++{ ++ int ss; ++ ++ /* Read the AT8035 PHY-Specific Status register, which indicates the ++ * speed and duplex that the PHY is actually using, irrespective of ++ * whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ int sfc, speed; ++ ++ sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); ++ if (sfc < 0) ++ return sfc; ++ ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; ++ ++ switch (speed) { ++ case AT803X_SS_SPEED_10: ++ phydev->speed = SPEED_10; ++ break; ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case QCA808X_SS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ } ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ if (ss & AT803X_SS_MDIX) ++ phydev->mdix = ETH_TP_MDI_X; ++ else ++ phydev->mdix = ETH_TP_MDI; ++ ++ switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { ++ case AT803X_SFC_MANUAL_MDI: ++ phydev->mdix_ctrl = ETH_TP_MDI; ++ break; ++ case AT803X_SFC_MANUAL_MDIX: ++ phydev->mdix_ctrl = ETH_TP_MDI_X; ++ break; ++ case AT803X_SFC_AUTOMATIC_CROSSOVER: ++ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; ++ break; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_read_specific_status); ++ ++int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) ++{ ++ u16 val; ++ ++ switch (ctrl) { ++ case ETH_TP_MDI: ++ val = AT803X_SFC_MANUAL_MDI; ++ break; ++ case ETH_TP_MDI_X: ++ val = AT803X_SFC_MANUAL_MDIX; ++ break; ++ case ETH_TP_MDI_AUTO: ++ val = AT803X_SFC_AUTOMATIC_CROSSOVER; ++ break; ++ default: ++ return 0; ++ } ++ ++ return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, ++ AT803X_SFC_MDI_CROSSOVER_MODE_M, ++ FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); ++} ++EXPORT_SYMBOL_GPL(at803x_config_mdix); ++ ++int at803x_prepare_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ /* Changes of the midx bits are disruptive to the normal operation; ++ * therefore any changes to these registers must be followed by a ++ * software reset to take effect. ++ */ ++ if (ret == 1) { ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg); ++ ++static int at803x_get_downshift(struct phy_device *phydev, u8 *d) ++{ ++ int val; ++ ++ val = phy_read(phydev, AT803X_SMART_SPEED); ++ if (val < 0) ++ return val; ++ ++ if (val & AT803X_SMART_SPEED_ENABLE) ++ *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; ++ else ++ *d = DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ u16 mask, set; ++ int ret; ++ ++ switch (cnt) { ++ case DOWNSHIFT_DEV_DEFAULT_COUNT: ++ cnt = AT803X_DEFAULT_DOWNSHIFT; ++ fallthrough; ++ case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: ++ set = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER | ++ FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); ++ mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; ++ break; ++ case DOWNSHIFT_DEV_DISABLE: ++ set = 0; ++ mask = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); ++ ++ /* After changing the smart speed settings, we need to perform a ++ * software reset, use phy_init_hw() to make sure we set the ++ * reapply any values which might got lost during software reset. ++ */ ++ if (ret == 1) ++ ret = phy_init_hw(phydev); ++ ++ return ret; ++} ++ ++int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++EXPORT_SYMBOL_GPL(at803x_get_tunable); ++ ++int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++EXPORT_SYMBOL_GPL(at803x_set_tunable); ++ ++int at803x_cdt_fault_length(int dt) ++{ ++ /* According to the datasheet the distance to the fault is ++ * DELTA_TIME * 0.824 meters. ++ * ++ * The author suspect the correct formula is: ++ * ++ * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 ++ * ++ * where c is the speed of light, VF is the velocity factor of ++ * the twisted pair cable, 125MHz the counter frequency and ++ * we need to divide by 2 because the hardware will measure the ++ * round trip time to the fault and back to the PHY. ++ * ++ * With a VF of 0.69 we get the factor 0.824 mentioned in the ++ * datasheet. ++ */ ++ return (dt * 824) / 10; ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_fault_length); ++ ++int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start) ++{ ++ return phy_write(phydev, AT803X_CDT, cdt_start); ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_start); ++ ++int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) ++{ ++ int val, ret; ++ ++ /* One test run takes about 25ms */ ++ ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, ++ !(val & cdt_en), ++ 30000, 100000, true); ++ ++ return ret < 0 ? ret : 0; ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -1,5 +1,63 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 ++#define AT803X_SFC_ASSERT_CRS BIT(11) ++#define AT803X_SFC_FORCE_LINK BIT(10) ++#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) ++#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 ++#define AT803X_SFC_MANUAL_MDIX 0x1 ++#define AT803X_SFC_MANUAL_MDI 0x0 ++#define AT803X_SFC_SQE_TEST BIT(2) ++#define AT803X_SFC_POLARITY_REVERSAL BIT(1) ++#define AT803X_SFC_DISABLE_JABBER BIT(0) ++ ++#define AT803X_SPECIFIC_STATUS 0x11 ++#define AT803X_SS_SPEED_MASK GENMASK(15, 14) ++#define AT803X_SS_SPEED_1000 2 ++#define AT803X_SS_SPEED_100 1 ++#define AT803X_SS_SPEED_10 0 ++#define AT803X_SS_DUPLEX BIT(13) ++#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) ++#define AT803X_SS_MDIX BIT(6) ++ ++#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) ++#define QCA808X_SS_SPEED_2500 4 ++ ++#define AT803X_INTR_ENABLE 0x12 ++#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) ++#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) ++#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) ++#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) ++#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) ++#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) ++#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) ++#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) ++#define AT803X_INTR_ENABLE_WOL BIT(0) ++ ++#define AT803X_INTR_STATUS 0x13 ++ ++#define AT803X_SMART_SPEED 0x14 ++#define AT803X_SMART_SPEED_ENABLE BIT(5) ++#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) ++#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) ++ ++#define AT803X_CDT 0x16 ++#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) ++#define AT803X_CDT_ENABLE_TEST BIT(0) ++#define AT803X_CDT_STATUS 0x1c ++#define AT803X_CDT_STATUS_STAT_NORMAL 0 ++#define AT803X_CDT_STATUS_STAT_SHORT 1 ++#define AT803X_CDT_STATUS_STAT_OPEN 2 ++#define AT803X_CDT_STATUS_STAT_FAIL 3 ++#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) ++#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) ++ ++#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C ++#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B ++#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++ + #define AT803X_DEBUG_ADDR 0x1D + #define AT803X_DEBUG_DATA 0x1E + +@@ -16,6 +74,10 @@ + #define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) + #define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) + ++#define AT803X_DEFAULT_DOWNSHIFT 5 ++#define AT803X_MIN_DOWNSHIFT 2 ++#define AT803X_MAX_DOWNSHIFT 9 ++ + enum stat_access_type { + PHY, + MMD +@@ -28,7 +90,31 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + int at803x_debug_reg_read(struct phy_device *phydev, u16 reg); + int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, + u16 clear, u16 set); + int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data); ++int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol); ++void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol); ++int at803x_ack_interrupt(struct phy_device *phydev); ++int at803x_config_intr(struct phy_device *phydev); ++irqreturn_t at803x_handle_interrupt(struct phy_device *phydev); ++int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask); ++int at803x_config_mdix(struct phy_device *phydev, u8 ctrl); ++int at803x_prepare_config_aneg(struct phy_device *phydev); ++int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data); ++int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data); ++int at803x_cdt_fault_length(int dt); ++int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start); ++int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en); diff --git a/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch b/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch new file mode 100644 index 0000000000..597dcea4c0 --- /dev/null +++ b/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch @@ -0,0 +1,1936 @@ +From c89414adf2ec7cd9e7080c419aa5847f1db1009c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:23 +0100 +Subject: [PATCH 5/5] net: phy: qcom: detach qca808x PHY driver from at803x + +Almost all the QCA8081 PHY driver OPs are specific and only some of them +use the generic at803x. + +To make the at803x code slimmer, move all the specific qca808x regs and +functions to a dedicated PHY driver. + +Probe function and priv struct is reworked to allocate and use only the +qca808x specific data. Unused data from at803x PHY driver are dropped +from at803x priv struct. + +Also a new Kconfig is introduced QCA808X_PHY, to compile the newly +introduced PHY driver for QCA8081 PHY. + +As the Kconfig name starts with Qualcomm the same order is kept. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-6-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 6 + + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 897 +------------------------------ + drivers/net/phy/qcom/qca808x.c | 934 +++++++++++++++++++++++++++++++++ + 4 files changed, 942 insertions(+), 896 deletions(-) + create mode 100644 drivers/net/phy/qcom/qca808x.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -14,3 +14,9 @@ config QCA83XX_PHY + select QCOM_NET_PHYLIB + help + Currently supports the internal QCA8337(Internal qca8k PHY) model ++ ++config QCA808X_PHY ++ tristate "Qualcomm QCA808x PHYs" ++ select QCOM_NET_PHYLIB ++ help ++ Currently supports the QCA8081 model +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -2,3 +2,4 @@ + obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o ++obj-$(CONFIG_QCA808X_PHY) += qca808x.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -96,8 +96,6 @@ + #define ATH8035_PHY_ID 0x004dd072 + #define AT8030_PHY_ID_MASK 0xffffffef + +-#define QCA8081_PHY_ID 0x004dd101 +- + #define QCA9561_PHY_ID 0x004dd042 + + #define AT803X_PAGE_FIBER 0 +@@ -110,201 +108,7 @@ + /* disable hibernation mode */ + #define AT803X_DISABLE_HIBERNATION_MODE BIT(2) + +-/* ADC threshold */ +-#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 +-#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) +-#define QCA808X_ADC_THRESHOLD_80MV 0 +-#define QCA808X_ADC_THRESHOLD_100MV 0xf0 +-#define QCA808X_ADC_THRESHOLD_200MV 0x0f +-#define QCA808X_ADC_THRESHOLD_300MV 0xff +- +-/* CLD control */ +-#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 +-#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) +-#define QCA808X_8023AZ_AFE_EN 0x90 +- +-/* AZ control */ +-#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 +-#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 +-#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E +-#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E +-#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 +-#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c +-#define QCA808X_TOP_OPTION1_DATA 0x0 +- +-#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 +-#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 +-#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 +-#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad +-#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 +-#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 +-#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 +-#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 +-#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 +-#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 +-#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 +-#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 +- +-/* master/slave seed config */ +-#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 +-#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) +-#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) +-#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 +- +-/* Hibernation yields lower power consumpiton in contrast with normal operation mode. +- * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. +- */ +-#define QCA808X_DBG_AN_TEST 0xb +-#define QCA808X_HIBERNATION_EN BIT(15) +- +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- +-#define QCA808X_MMD7_LED2_CTRL 0x8074 +-#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 +-#define QCA808X_MMD7_LED1_CTRL 0x8076 +-#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 +-#define QCA808X_MMD7_LED0_CTRL 0x8078 +-#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) +- +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- +-#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 +-#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) +- +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- +-#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a +-/* QSDK sets by default 0x46 to this reg that sets BIT 6 for +- * LED to active high. It's not clear what BIT 3 and BIT 4 does. +- */ +-#define QCA808X_LED_ACTIVE_HIGH BIT(6) +- +-/* QCA808X 1G chip type */ +-#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +-#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +- +-#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 +-#define QCA8081_PHY_FIFO_RSTN BIT(11) +- +-MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); ++MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +@@ -318,7 +122,6 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- int led_polarity_mode; + }; + + struct at803x_context { +@@ -519,9 +322,6 @@ static int at803x_probe(struct phy_devic + if (!priv) + return -ENOMEM; + +- /* Init LED polarity mode to -1 */ +- priv->led_polarity_mode = -1; +- + phydev->priv = priv; + + ret = at803x_parse_dt(phydev); +@@ -1216,672 +1016,6 @@ static int at8035_probe(struct phy_devic + return at8035_parse_dt(phydev); + } + +-static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) +-{ +- int ret; +- +- /* Enable fast retrain */ +- ret = genphy_c45_fast_retrain(phydev, true); +- if (ret) +- return ret; +- +- phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); +- +- return 0; +-} +- +-static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) +-{ +- u16 seed_value; +- +- if (!enable) +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); +- +- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | +- QCA808X_MASTER_SLAVE_SEED_ENABLE); +-} +- +-static bool qca808x_is_prefer_master(struct phy_device *phydev) +-{ +- return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || +- (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); +-} +- +-static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) +-{ +- return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +-} +- +-static int qca808x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Active adc&vga on 802.3az for the link 1000M and 100M */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); +- if (ret) +- return ret; +- +- /* Adjust the threshold on 802.3az for the link 1000M */ +- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, +- QCA808X_MMD3_AZ_TRAINING_VAL); +- if (ret) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy +- * linked as slave mode. +- */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) +- return ret; +- } +- } +- +- /* Configure adc threshold as 100mv for the link 10M */ +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, +- QCA808X_ADC_THRESHOLD_100MV); +-} +- +-static int qca808x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int ret; +- +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +- if (ret < 0) +- return ret; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); +- +- ret = genphy_read_status(phydev); +- if (ret) +- return ret; +- +- /* qca8081 takes the different bits for speed value from at803x */ +- ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); +- ret = at803x_read_specific_status(phydev, ss_mask); +- if (ret < 0) +- return ret; +- +- if (phydev->link) { +- if (phydev->speed == SPEED_2500) +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- else +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- } else { +- /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected or the master mode +- * preferred. +- * +- * the reason for not putting this code into the function link_change_notify is +- * the corner case where the link partner is also the qca8081 PHY and the seed +- * value is configured as the same value, the link can't be up and no link change +- * occurs. +- */ +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); +- } +- } +- } +- +- return 0; +-} +- +-static int qca808x_soft_reset(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- +- return ret; +-} +- +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- +-static int qca808x_cable_test_start(struct phy_device *phydev) +-{ +- int ret; +- +- /* perform CDT with the following configs: +- * 1. disable hibernation. +- * 2. force PHY working in MDI mode. +- * 3. for PHY working in 1000BaseT. +- * 4. configure the threshold. +- */ +- +- ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); +- if (ret < 0) +- return ret; +- +- ret = at803x_config_mdix(phydev, ETH_TP_MDI); +- if (ret < 0) +- return ret; +- +- /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ +- phydev->duplex = DUPLEX_FULL; +- phydev->speed = SPEED_1000; +- ret = genphy_c45_pma_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- ret = genphy_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- /* configure the thresholds for open, short, pair ok test */ +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); +- +- return 0; +-} +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} +- +-static int qca808x_get_features(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_c45_pma_read_abilities(phydev); +- if (ret) +- return ret; +- +- /* The autoneg ability is not existed in bit3 of MMD7.1, +- * but it is supported by qca808x PHY, so we add it here +- * manually. +- */ +- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); +- +- /* As for the qca8081 1G version chip, the 2500baseT ability is also +- * existed in the bit0 of MMD1.21, we need to remove it manually if +- * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. +- */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +- +- return 0; +-} +- +-static int qca808x_config_aneg(struct phy_device *phydev) +-{ +- int phy_ctrl = 0; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- +- return __genphy_config_aneg(phydev, ret); +-} +- +-static void qca808x_link_change_notify(struct phy_device *phydev) +-{ +- /* Assert interface sgmii fifo on link down, deassert it on link up, +- * the interface device address is always phy address added by 1. +- */ +- mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, +- phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); +-} +- +-static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, +- u16 *offload_trigger) +-{ +- /* Parsing specific to netdev trigger */ +- if (test_bit(TRIGGER_NETDEV_TX, &rules)) +- *offload_trigger |= QCA808X_LED_TX_BLINK; +- if (test_bit(TRIGGER_NETDEV_RX, &rules)) +- *offload_trigger |= QCA808X_LED_RX_BLINK; +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED10_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED100_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED1000_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED2500_ON; +- if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; +- if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; +- +- if (rules && !*offload_trigger) +- return -EOPNOTSUPP; +- +- /* Enable BLINK_CHECK_BYPASS by default to make the LED +- * blink even with duplex or speed mode not enabled. +- */ +- *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; +- +- return 0; +-} +- +-static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 offload_trigger = 0; +- +- if (index > 2) +- return -EINVAL; +- +- return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +-} +- +-static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 reg, offload_trigger = 0; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +- if (ret) +- return ret; +- +- ret = qca808x_led_hw_control_enable(phydev, index); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK, +- offload_trigger); +-} +- +-static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return false; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +- unsigned long *rules) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return -EINVAL; +- +- /* Check if we have hw control enabled */ +- if (qca808x_led_hw_control_status(phydev, index)) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- if (val & QCA808X_LED_TX_BLINK) +- set_bit(TRIGGER_NETDEV_TX, rules); +- if (val & QCA808X_LED_RX_BLINK) +- set_bit(TRIGGER_NETDEV_RX, rules); +- if (val & QCA808X_LED_SPEED10_ON) +- set_bit(TRIGGER_NETDEV_LINK_10, rules); +- if (val & QCA808X_LED_SPEED100_ON) +- set_bit(TRIGGER_NETDEV_LINK_100, rules); +- if (val & QCA808X_LED_SPEED1000_ON) +- set_bit(TRIGGER_NETDEV_LINK_1000, rules); +- if (val & QCA808X_LED_SPEED2500_ON) +- set_bit(TRIGGER_NETDEV_LINK_2500, rules); +- if (val & QCA808X_LED_HALF_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); +- if (val & QCA808X_LED_FULL_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); +- +- return 0; +-} +- +-static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK); +-} +- +-static int qca808x_led_brightness_set(struct phy_device *phydev, +- u8 index, enum led_brightness value) +-{ +- u16 reg; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- if (!value) { +- ret = qca808x_led_hw_control_reset(phydev, index); +- if (ret) +- return ret; +- } +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); +-} +- +-static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, +- unsigned long *delay_on, +- unsigned long *delay_off) +-{ +- int ret; +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; +-} +- +-static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +- unsigned long modes) +-{ +- struct at803x_priv *priv = phydev->priv; +- bool active_low = false; +- u32 mode; +- +- for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { +- switch (mode) { +- case PHY_LED_ACTIVE_LOW: +- active_low = true; +- break; +- default: +- return -EINVAL; +- } +- } +- +- /* PHY polarity is global and can't be set per LED. +- * To detect this, check if last requested polarity mode +- * match the new one. +- */ +- if (priv->led_polarity_mode >= 0 && +- priv->led_polarity_mode != active_low) { +- phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); +- return -EINVAL; +- } +- +- /* Save the last PHY polarity mode */ +- priv->led_polarity_mode = active_low; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, +- QCA808X_MMD7_LED_POLARITY_CTRL, +- QCA808X_LED_ACTIVE_HIGH, +- active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); +-} +- + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -1989,34 +1123,6 @@ static struct phy_driver at803x_driver[] + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +-}, { +- /* Qualcomm QCA8081 */ +- PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), +- .name = "Qualcomm QCA8081", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .get_features = qca808x_get_features, +- .config_aneg = qca808x_config_aneg, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_status = qca808x_read_status, +- .config_init = qca808x_config_init, +- .soft_reset = qca808x_soft_reset, +- .cable_test_start = qca808x_cable_test_start, +- .cable_test_get_status = qca808x_cable_test_get_status, +- .link_change_notify = qca808x_link_change_notify, +- .led_brightness_set = qca808x_led_brightness_set, +- .led_blink_set = qca808x_led_blink_set, +- .led_hw_is_supported = qca808x_led_hw_is_supported, +- .led_hw_control_set = qca808x_led_hw_control_set, +- .led_hw_control_get = qca808x_led_hw_control_get, +- .led_polarity_set = qca808x_led_polarity_set, + }, }; + + module_phy_driver(at803x_driver); +@@ -2028,7 +1134,6 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, + { } + }; + +--- /dev/null ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -0,0 +1,934 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include ++#include ++#include ++ ++#include "qcom.h" ++ ++/* ADC threshold */ ++#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 ++#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) ++#define QCA808X_ADC_THRESHOLD_80MV 0 ++#define QCA808X_ADC_THRESHOLD_100MV 0xf0 ++#define QCA808X_ADC_THRESHOLD_200MV 0x0f ++#define QCA808X_ADC_THRESHOLD_300MV 0xff ++ ++/* CLD control */ ++#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 ++#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) ++#define QCA808X_8023AZ_AFE_EN 0x90 ++ ++/* AZ control */ ++#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 ++#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 ++#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E ++#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E ++#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 ++#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c ++#define QCA808X_TOP_OPTION1_DATA 0x0 ++ ++#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 ++#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 ++#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 ++#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad ++#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 ++#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 ++#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 ++#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 ++#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 ++#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 ++#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 ++#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 ++ ++/* master/slave seed config */ ++#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 ++#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) ++#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) ++#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 ++ ++/* Hibernation yields lower power consumpiton in contrast with normal operation mode. ++ * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. ++ */ ++#define QCA808X_DBG_AN_TEST 0xb ++#define QCA808X_HIBERNATION_EN BIT(15) ++ ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ ++#define QCA8081_PHY_ID 0x004dd101 ++ ++MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_LICENSE("GPL"); ++ ++struct qca808x_priv { ++ int led_polarity_mode; ++}; ++ ++static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Enable fast retrain */ ++ ret = genphy_c45_fast_retrain(phydev, true); ++ if (ret) ++ return ret; ++ ++ phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, ++ QCA808X_TOP_OPTION1_DATA); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, ++ QCA808X_MMD3_DEBUG_1_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, ++ QCA808X_MMD3_DEBUG_4_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, ++ QCA808X_MMD3_DEBUG_5_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, ++ QCA808X_MMD3_DEBUG_3_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, ++ QCA808X_MMD3_DEBUG_6_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, ++ QCA808X_MMD3_DEBUG_2_VALUE); ++ ++ return 0; ++} ++ ++static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) ++{ ++ u16 seed_value; ++ ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); ++ ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); ++} ++ ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ ++static int qca808x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca808x_priv *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca808x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Active adc&vga on 802.3az for the link 1000M and 100M */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ if (ret) ++ return ret; ++ ++ /* Adjust the threshold on 802.3az for the link 1000M */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); ++ if (ret) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); ++ if (ret) ++ return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Configure adc threshold as 100mv for the link 10M */ ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); ++} ++ ++static int qca808x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); ++ if (ret < 0) ++ return ret; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ ret = genphy_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->link) { ++ if (phydev->speed == SPEED_2500) ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ else ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ } else { ++ /* generate seed as a lower random value to make PHY linked as SLAVE easily, ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * ++ * the reason for not putting this code into the function link_change_notify is ++ * the corner case where the link partner is also the qca8081 PHY and the seed ++ * value is configured as the same value, the link can't be up and no link change ++ * occurs. ++ */ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int qca808x_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; ++} ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_start(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* perform CDT with the following configs: ++ * 1. disable hibernation. ++ * 2. force PHY working in MDI mode. ++ * 3. for PHY working in 1000BaseT. ++ * 4. configure the threshold. ++ */ ++ ++ ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_config_mdix(phydev, ETH_TP_MDI); ++ if (ret < 0) ++ return ret; ++ ++ /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ ++ phydev->duplex = DUPLEX_FULL; ++ phydev->speed = SPEED_1000; ++ ret = genphy_c45_pma_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* configure the thresholds for open, short, pair ok test */ ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ ++ return 0; ++} ++ ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct qca808x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ ++static struct phy_driver qca808x_driver[] = { ++{ ++ /* Qualcomm QCA8081 */ ++ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), ++ .name = "Qualcomm QCA8081", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = qca808x_probe, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .get_features = qca808x_get_features, ++ .config_aneg = qca808x_config_aneg, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_status = qca808x_read_status, ++ .config_init = qca808x_config_init, ++ .soft_reset = qca808x_soft_reset, ++ .cable_test_start = qca808x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, ++}, }; ++ ++module_phy_driver(qca808x_driver); ++ ++static struct mdio_device_id __maybe_unused qca808x_tbl[] = { ++ { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, qca808x_tbl); diff --git a/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch new file mode 100644 index 0000000000..d56a142451 --- /dev/null +++ b/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch @@ -0,0 +1,394 @@ +From 4765a9722e09765866e131ec31f7b9cf4c1f4854 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:57:50 +0000 +Subject: [PATCH] net: pcs: add driver for MediaTek SGMII PCS + +The SGMII core found in several MediaTek SoCs is identical to what can +also be found in MediaTek's MT7531 Ethernet switch IC. +As this has not always been clear, both drivers developed different +implementations to deal with the PCS. +Recently Alexander Couzens pointed out this fact which lead to the +development of this shared driver. + +Add a dedicated driver, mostly by copying the code now found in the +Ethernet driver. The now redundant code will be removed by a follow-up +commit. + +Suggested-by: Alexander Couzens +Suggested-by: Russell King (Oracle) +Signed-off-by: Daniel Golle +Tested-by: Frank Wunderlich +Reviewed-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + MAINTAINERS | 8 + + drivers/net/pcs/Kconfig | 7 + + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs-mtk-lynxi.c | 305 ++++++++++++++++++++++++++++++ + include/linux/pcs/pcs-mtk-lynxi.h | 13 ++ + 5 files changed, 334 insertions(+) + create mode 100644 drivers/net/pcs/pcs-mtk-lynxi.c + create mode 100644 include/linux/pcs/pcs-mtk-lynxi.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/ethernet/mediatek/ + ++MEDIATEK ETHERNET PCS DRIVER ++M: Alexander Couzens ++M: Daniel Golle ++L: netdev@vger.kernel.org ++S: Maintained ++F: drivers/net/pcs/pcs-mtk-lynxi.c ++F: include/linux/pcs/pcs-mtk-lynxi.h ++ + MEDIATEK I2C CONTROLLER DRIVER + M: Qii Wang + L: linux-i2c@vger.kernel.org +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -32,4 +32,11 @@ config PCS_ALTERA_TSE + This module provides helper functions for the Altera Triple Speed + Ethernet SGMII PCS, that can be found on the Intel Socfpga family. + ++config PCS_MTK_LYNXI ++ tristate ++ select REGMAP ++ help ++ This module provides helpers to phylink for managing the LynxI PCS ++ which is part of MediaTek's SoC and Ethernet switch ICs. ++ + endmenu +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o + obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o + obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o ++obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o +--- /dev/null ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -0,0 +1,305 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2018-2019 MediaTek Inc. ++/* A library for MediaTek SGMII circuit ++ * ++ * Author: Sean Wang ++ * Author: Alexander Couzens ++ * Author: Daniel Golle ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* SGMII subsystem config registers */ ++/* BMCR (low 16) BMSR (high 16) */ ++#define SGMSYS_PCS_CONTROL_1 0x0 ++#define SGMII_BMCR GENMASK(15, 0) ++#define SGMII_BMSR GENMASK(31, 16) ++ ++#define SGMSYS_PCS_DEVICE_ID 0x4 ++#define SGMII_LYNXI_DEV_ID 0x4d544950 ++ ++#define SGMSYS_PCS_ADVERTISE 0x8 ++#define SGMII_ADVERTISE GENMASK(15, 0) ++#define SGMII_LPA GENMASK(31, 16) ++ ++#define SGMSYS_PCS_SCRATCH 0x14 ++#define SGMII_DEV_VERSION GENMASK(31, 16) ++ ++/* Register to programmable link timer, the unit in 2 * 8ns */ ++#define SGMSYS_PCS_LINK_TIMER 0x18 ++#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) ++#define SGMII_LINK_TIMER_VAL(ns) FIELD_PREP(SGMII_LINK_TIMER_MASK, \ ++ ((ns) / 2 / 8)) ++ ++/* Register to control remote fault */ ++#define SGMSYS_SGMII_MODE 0x20 ++#define SGMII_IF_MODE_SGMII BIT(0) ++#define SGMII_SPEED_DUPLEX_AN BIT(1) ++#define SGMII_SPEED_MASK GENMASK(3, 2) ++#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) ++#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) ++#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) ++#define SGMII_DUPLEX_HALF BIT(4) ++#define SGMII_REMOTE_FAULT_DIS BIT(8) ++ ++/* Register to reset SGMII design */ ++#define SGMSYS_RESERVED_0 0x34 ++#define SGMII_SW_RESET BIT(0) ++ ++/* Register to set SGMII speed, ANA RG_ Control Signals III */ ++#define SGMII_PHY_SPEED_MASK GENMASK(3, 2) ++#define SGMII_PHY_SPEED_1_25G FIELD_PREP(SGMII_PHY_SPEED_MASK, 0) ++#define SGMII_PHY_SPEED_3_125G FIELD_PREP(SGMII_PHY_SPEED_MASK, 1) ++ ++/* Register to power up QPHY */ ++#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 ++#define SGMII_PHYA_PWD BIT(4) ++ ++/* Register to QPHY wrapper control */ ++#define SGMSYS_QPHY_WRAP_CTRL 0xec ++#define SGMII_PN_SWAP_MASK GENMASK(1, 0) ++#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) ++ ++/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated ++ * data ++ * @regmap: The register map pointing at the range used to setup ++ * SGMII modes ++ * @dev: Pointer to device owning the PCS ++ * @ana_rgc3: The offset of register ANA_RGC3 relative to regmap ++ * @interface: Currently configured interface mode ++ * @pcs: Phylink PCS structure ++ * @flags: Flags indicating hardware properties ++ */ ++struct mtk_pcs_lynxi { ++ struct regmap *regmap; ++ u32 ana_rgc3; ++ phy_interface_t interface; ++ struct phylink_pcs pcs; ++ u32 flags; ++}; ++ ++static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mtk_pcs_lynxi, pcs); ++} ++ ++static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ unsigned int bm, adv; ++ ++ /* Read the BMSR and LPA */ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); ++ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); ++ ++ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), ++ FIELD_GET(SGMII_LPA, adv)); ++} ++ ++static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ bool mode_changed = false, changed, use_an; ++ unsigned int rgc3, sgm_mode, bmcr; ++ int advertise, link_timer; ++ ++ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, ++ advertising); ++ if (advertise < 0) ++ return advertise; ++ ++ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and ++ * we assume that fixes it's speed at bitrate = line rate (in ++ * other words, 1000Mbps or 2500Mbps). ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ sgm_mode = SGMII_IF_MODE_SGMII; ++ if (phylink_autoneg_inband(mode)) { ++ sgm_mode |= SGMII_REMOTE_FAULT_DIS | ++ SGMII_SPEED_DUPLEX_AN; ++ use_an = true; ++ } else { ++ use_an = false; ++ } ++ } else if (phylink_autoneg_inband(mode)) { ++ /* 1000base-X or 2500base-X autoneg */ ++ sgm_mode = SGMII_REMOTE_FAULT_DIS; ++ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ advertising); ++ } else { ++ /* 1000base-X or 2500base-X without autoneg */ ++ sgm_mode = 0; ++ use_an = false; ++ } ++ ++ if (use_an) ++ bmcr = BMCR_ANENABLE; ++ else ++ bmcr = 0; ++ ++ if (mpcs->interface != interface) { ++ link_timer = phylink_get_link_timer_ns(interface); ++ if (link_timer < 0) ++ return link_timer; ++ ++ /* PHYA power down */ ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, ++ SGMII_PHYA_PWD); ++ ++ /* Reset SGMII PCS state */ ++ regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, ++ SGMII_SW_RESET); ++ ++ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, ++ SGMII_PN_SWAP_MASK, ++ SGMII_PN_SWAP_TX_RX); ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ rgc3 = SGMII_PHY_SPEED_3_125G; ++ else ++ rgc3 = SGMII_PHY_SPEED_1_25G; ++ ++ /* Configure the underlying interface speed */ ++ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, ++ SGMII_PHY_SPEED_MASK, rgc3); ++ ++ /* Setup the link timer */ ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, ++ SGMII_LINK_TIMER_VAL(link_timer)); ++ ++ mpcs->interface = interface; ++ mode_changed = true; ++ } ++ ++ /* Update the advertisement, noting whether it has changed */ ++ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, ++ SGMII_ADVERTISE, advertise, &changed); ++ ++ /* Update the sgmsys mode register */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | ++ SGMII_IF_MODE_SGMII, sgm_mode); ++ ++ /* Update the BMCR */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, ++ BMCR_ANENABLE, bmcr); ++ ++ /* Release PHYA power down state ++ * Only removing bit SGMII_PHYA_PWD isn't enough. ++ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which ++ * prevents SGMII from working. The SGMII still shows link but no traffic ++ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was ++ * taken from a good working state of the SGMII interface. ++ * Unknown how much the QPHY needs but it is racy without a sleep. ++ * Tested on mt7622 & mt7986. ++ */ ++ usleep_range(50, 100); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); ++ ++ return changed || mode_changed; ++} ++ ++static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ ++ regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); ++} ++ ++static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, int speed, ++ int duplex) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ unsigned int sgm_mode; ++ ++ if (!phylink_autoneg_inband(mode)) { ++ /* Force the speed and duplex setting */ ++ if (speed == SPEED_10) ++ sgm_mode = SGMII_SPEED_10; ++ else if (speed == SPEED_100) ++ sgm_mode = SGMII_SPEED_100; ++ else ++ sgm_mode = SGMII_SPEED_1000; ++ ++ if (duplex != DUPLEX_FULL) ++ sgm_mode |= SGMII_DUPLEX_HALF; ++ ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, ++ sgm_mode); ++ } ++} ++ ++static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { ++ .pcs_get_state = mtk_pcs_lynxi_get_state, ++ .pcs_config = mtk_pcs_lynxi_config, ++ .pcs_an_restart = mtk_pcs_lynxi_restart_an, ++ .pcs_link_up = mtk_pcs_lynxi_link_up, ++}; ++ ++struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, ++ struct regmap *regmap, u32 ana_rgc3, ++ u32 flags) ++{ ++ struct mtk_pcs_lynxi *mpcs; ++ u32 id, ver; ++ int ret; ++ ++ ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); ++ if (ret < 0) ++ return NULL; ++ ++ if (id != SGMII_LYNXI_DEV_ID) { ++ dev_err(dev, "unknown PCS device id %08x\n", id); ++ return NULL; ++ } ++ ++ ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); ++ if (ret < 0) ++ return NULL; ++ ++ ver = FIELD_GET(SGMII_DEV_VERSION, ver); ++ if (ver != 0x1) { ++ dev_err(dev, "unknown PCS device version %04x\n", ver); ++ return NULL; ++ } ++ ++ dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, ++ ver); ++ ++ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return NULL; ++ ++ mpcs->ana_rgc3 = ana_rgc3; ++ mpcs->regmap = regmap; ++ mpcs->flags = flags; ++ mpcs->pcs.ops = &mtk_pcs_lynxi_ops; ++ mpcs->pcs.poll = true; ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ ++ return &mpcs->pcs; ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_create); ++ ++void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs) ++{ ++ if (!pcs) ++ return; ++ ++ kfree(pcs_to_mtk_pcs_lynxi(pcs)); ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); ++ ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/pcs/pcs-mtk-lynxi.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __LINUX_PCS_MTK_LYNXI_H ++#define __LINUX_PCS_MTK_LYNXI_H ++ ++#include ++#include ++ ++#define MTK_SGMII_FLAG_PN_SWAP BIT(0) ++struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, ++ struct regmap *regmap, ++ u32 ana_rgc3, u32 flags); ++void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); ++#endif diff --git a/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch b/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch new file mode 100644 index 0000000000..6decc3430b --- /dev/null +++ b/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch @@ -0,0 +1,28 @@ +From ebb30ccbbdbd6fae5177b676da4f4ac92bb4f635 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:31 +0100 +Subject: [PATCH 1/4] net: phy: make addr type u8 in phy_package_shared struct + +Switch addr type in phy_package_shared struct to u8. + +The value is already checked to be non negative and to be less than +PHY_MAX_ADDR, hence u8 is better suited than using int. + +Signed-off-by: Christian Marangi +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + include/linux/phy.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -330,7 +330,7 @@ struct mdio_bus_stats { + * phy_package_leave(). + */ + struct phy_package_shared { +- int addr; ++ u8 addr; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; diff --git a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch new file mode 100644 index 0000000000..0cf01df3d3 --- /dev/null +++ b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch @@ -0,0 +1,341 @@ +From 9eea577eb1155fe4a183bc5e7bf269b0b2e7a6ba Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:32 +0100 +Subject: [PATCH 2/4] net: phy: extend PHY package API to support multiple + global address + +Current API for PHY package are limited to single address to configure +global settings for the PHY package. + +It was found that some PHY package (for example the qca807x, a PHY +package that is shipped with a bundle of 5 PHY) requires multiple PHY +address to configure global settings. An example scenario is a PHY that +have a dedicated PHY for PSGMII/serdes calibrarion and have a specific +PHY in the package where the global PHY mode is set and affects every +other PHY in the package. + +Change the API in the following way: +- Change phy_package_join() to take the base addr of the PHY package + instead of the global PHY addr. +- Make __/phy_package_write/read() require an additional arg that + select what global PHY address to use by passing the offset from the + base addr passed on phy_package_join(). + +Each user of this API is updated to follow this new implementation +following a pattern where an enum is defined to declare the offset of the +addr. + +We also drop the check if shared is defined as any user of the +phy_package_read/write is expected to use phy_package_join first. Misuse +of this will correctly trigger a kernel panic for NULL pointer +exception. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/bcm54140.c | 16 ++++++-- + drivers/net/phy/mscc/mscc.h | 5 +++ + drivers/net/phy/mscc/mscc_main.c | 4 +- + drivers/net/phy/phy_device.c | 35 +++++++++-------- + include/linux/phy.h | 64 +++++++++++++++++++++----------- + 5 files changed, 80 insertions(+), 44 deletions(-) + +--- a/drivers/net/phy/bcm54140.c ++++ b/drivers/net/phy/bcm54140.c +@@ -128,6 +128,10 @@ + #define BCM54140_DEFAULT_DOWNSHIFT 5 + #define BCM54140_MAX_DOWNSHIFT 9 + ++enum bcm54140_global_phy { ++ BCM54140_BASE_ADDR = 0, ++}; ++ + struct bcm54140_priv { + int port; + int base_addr; +@@ -429,11 +433,13 @@ static int bcm54140_base_read_rdb(struct + int ret; + + phy_lock_mdio_bus(phydev); +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_ADDR, rdb); + if (ret < 0) + goto out; + +- ret = __phy_package_read(phydev, MII_BCM54XX_RDB_DATA); ++ ret = __phy_package_read(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_DATA); + + out: + phy_unlock_mdio_bus(phydev); +@@ -446,11 +452,13 @@ static int bcm54140_base_write_rdb(struc + int ret; + + phy_lock_mdio_bus(phydev); +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_ADDR, rdb); + if (ret < 0) + goto out; + +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_DATA, val); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_DATA, val); + + out: + phy_unlock_mdio_bus(phydev); +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -414,6 +414,11 @@ struct vsc8531_private { + * gpio_lock: used for PHC operations. Common for all PHYs as the load/save GPIO + * is shared. + */ ++ ++enum vsc85xx_global_phy { ++ VSC88XX_BASE_ADDR = 0, ++}; ++ + struct vsc85xx_shared_private { + struct mutex gpio_lock; + }; +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -700,7 +700,7 @@ int phy_base_write(struct phy_device *ph + dump_stack(); + } + +- return __phy_package_write(phydev, regnum, val); ++ return __phy_package_write(phydev, VSC88XX_BASE_ADDR, regnum, val); + } + + /* phydev->bus->mdio_lock should be locked when using this function */ +@@ -711,7 +711,7 @@ int phy_base_read(struct phy_device *phy + dump_stack(); + } + +- return __phy_package_read(phydev, regnum); ++ return __phy_package_read(phydev, VSC88XX_BASE_ADDR, regnum); + } + + u32 vsc85xx_csr_read(struct phy_device *phydev, +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1602,20 +1602,22 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 + /** + * phy_package_join - join a common PHY group + * @phydev: target phy_device struct +- * @addr: cookie and PHY address for global register access ++ * @base_addr: cookie and base PHY address of PHY package for offset ++ * calculation of global register access + * @priv_size: if non-zero allocate this amount of bytes for private data + * + * This joins a PHY group and provides a shared storage for all phydevs in + * this group. This is intended to be used for packages which contain + * more than one PHY, for example a quad PHY transceiver. + * +- * The addr parameter serves as a cookie which has to have the same value +- * for all members of one group and as a PHY address to access generic +- * registers of a PHY package. Usually, one of the PHY addresses of the +- * different PHYs in the package provides access to these global registers. ++ * The base_addr parameter serves as cookie which has to have the same values ++ * for all members of one group and as the base PHY address of the PHY package ++ * for offset calculation to access generic registers of a PHY package. ++ * Usually, one of the PHY addresses of the different PHYs in the package ++ * provides access to these global registers. + * The address which is given here, will be used in the phy_package_read() +- * and phy_package_write() convenience functions. If your PHY doesn't have +- * global registers you can just pick any of the PHY addresses. ++ * and phy_package_write() convenience functions as base and added to the ++ * passed offset in those functions. + * + * This will set the shared pointer of the phydev to the shared storage. + * If this is the first call for a this cookie the shared storage will be +@@ -1625,17 +1627,17 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 + * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() + * with the same cookie but a different priv_size is an error. + */ +-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size) ++int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) + { + struct mii_bus *bus = phydev->mdio.bus; + struct phy_package_shared *shared; + int ret; + +- if (addr < 0 || addr >= PHY_MAX_ADDR) ++ if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) + return -EINVAL; + + mutex_lock(&bus->shared_lock); +- shared = bus->shared[addr]; ++ shared = bus->shared[base_addr]; + if (!shared) { + ret = -ENOMEM; + shared = kzalloc(sizeof(*shared), GFP_KERNEL); +@@ -1647,9 +1649,9 @@ int phy_package_join(struct phy_device * + goto err_free; + shared->priv_size = priv_size; + } +- shared->addr = addr; ++ shared->base_addr = base_addr; + refcount_set(&shared->refcnt, 1); +- bus->shared[addr] = shared; ++ bus->shared[base_addr] = shared; + } else { + ret = -EINVAL; + if (priv_size && priv_size != shared->priv_size) +@@ -1687,7 +1689,7 @@ void phy_package_leave(struct phy_device + return; + + if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { +- bus->shared[shared->addr] = NULL; ++ bus->shared[shared->base_addr] = NULL; + mutex_unlock(&bus->shared_lock); + kfree(shared->priv); + kfree(shared); +@@ -1706,7 +1708,8 @@ static void devm_phy_package_leave(struc + * devm_phy_package_join - resource managed phy_package_join() + * @dev: device that is registering this PHY package + * @phydev: target phy_device struct +- * @addr: cookie and PHY address for global register access ++ * @base_addr: cookie and base PHY address of PHY package for offset ++ * calculation of global register access + * @priv_size: if non-zero allocate this amount of bytes for private data + * + * Managed phy_package_join(). Shared storage fetched by this function, +@@ -1714,7 +1717,7 @@ static void devm_phy_package_leave(struc + * phy_package_join() for more information. + */ + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, +- int addr, size_t priv_size) ++ int base_addr, size_t priv_size) + { + struct phy_device **ptr; + int ret; +@@ -1724,7 +1727,7 @@ int devm_phy_package_join(struct device + if (!ptr) + return -ENOMEM; + +- ret = phy_package_join(phydev, addr, priv_size); ++ ret = phy_package_join(phydev, base_addr, priv_size); + + if (!ret) { + *ptr = phydev; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -319,7 +319,8 @@ struct mdio_bus_stats { + + /** + * struct phy_package_shared - Shared information in PHY packages +- * @addr: Common PHY address used to combine PHYs in one package ++ * @base_addr: Base PHY address of PHY package used to combine PHYs ++ * in one package and for offset calculation of phy_package_read/write + * @refcnt: Number of PHYs connected to this shared data + * @flags: Initialization of PHY package + * @priv_size: Size of the shared private data @priv +@@ -330,7 +331,7 @@ struct mdio_bus_stats { + * phy_package_leave(). + */ + struct phy_package_shared { +- u8 addr; ++ u8 base_addr; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; +@@ -1763,10 +1764,10 @@ int phy_ethtool_get_link_ksettings(struc + int phy_ethtool_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd); + int phy_ethtool_nway_reset(struct net_device *ndev); +-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size); ++int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size); + void phy_package_leave(struct phy_device *phydev); + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, +- int addr, size_t priv_size); ++ int base_addr, size_t priv_size); + + #if IS_ENABLED(CONFIG_PHYLIB) + int __init mdio_bus_init(void); +@@ -1778,46 +1779,65 @@ int phy_ethtool_get_sset_count(struct ph + int phy_ethtool_get_stats(struct phy_device *phydev, + struct ethtool_stats *stats, u64 *data); + +-static inline int phy_package_read(struct phy_device *phydev, u32 regnum) ++static inline int phy_package_address(struct phy_device *phydev, ++ unsigned int addr_offset) + { + struct phy_package_shared *shared = phydev->shared; ++ u8 base_addr = shared->base_addr; + +- if (!shared) ++ if (addr_offset >= PHY_MAX_ADDR - base_addr) + return -EIO; + +- return mdiobus_read(phydev->mdio.bus, shared->addr, regnum); ++ /* we know that addr will be in the range 0..31 and thus the ++ * implicit cast to a signed int is not a problem. ++ */ ++ return base_addr + addr_offset; + } + +-static inline int __phy_package_read(struct phy_device *phydev, u32 regnum) ++static inline int phy_package_read(struct phy_device *phydev, ++ unsigned int addr_offset, u32 regnum) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; ++ ++ return mdiobus_read(phydev->mdio.bus, addr, regnum); ++} ++ ++static inline int __phy_package_read(struct phy_device *phydev, ++ unsigned int addr_offset, u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; + +- return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum); ++ return __mdiobus_read(phydev->mdio.bus, addr, regnum); + } + + static inline int phy_package_write(struct phy_device *phydev, +- u32 regnum, u16 val) ++ unsigned int addr_offset, u32 regnum, ++ u16 val) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; + +- return mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); ++ return mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + + static inline int __phy_package_write(struct phy_device *phydev, +- u32 regnum, u16 val) ++ unsigned int addr_offset, u32 regnum, ++ u16 val) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; + +- return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); ++ return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + + static inline bool __phy_package_set_once(struct phy_device *phydev, diff --git a/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch b/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch new file mode 100644 index 0000000000..4a17d46453 --- /dev/null +++ b/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch @@ -0,0 +1,116 @@ +From 028672bd1d73cf65249a420c1de75e8d2acd2f6a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:33 +0100 +Subject: [PATCH 3/4] net: phy: restructure __phy_write/read_mmd to helper and + phydev user + +Restructure phy_write_mmd and phy_read_mmd to implement generic helper +for direct mdiobus access for mmd and use these helper for phydev user. + +This is needed in preparation of PHY package API that requires generic +access to the mdiobus and are deatched from phydev struct but instead +access them based on PHY package base_addr and offsets. + +Signed-off-by: Christian Marangi +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 64 ++++++++++++++++++-------------------- + 1 file changed, 30 insertions(+), 34 deletions(-) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -528,6 +528,28 @@ static void mmd_phy_indirect(struct mii_ + devad | MII_MMD_CTRL_NOINCR); + } + ++static int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, ++ int devad, u32 regnum) ++{ ++ if (is_c45) ++ return __mdiobus_c45_read(bus, phy_addr, devad, regnum); ++ ++ mmd_phy_indirect(bus, phy_addr, devad, regnum); ++ /* Read the content of the MMD's selected register */ ++ return __mdiobus_read(bus, phy_addr, MII_MMD_DATA); ++} ++ ++static int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, ++ int devad, u32 regnum, u16 val) ++{ ++ if (is_c45) ++ return __mdiobus_c45_write(bus, phy_addr, devad, regnum, val); ++ ++ mmd_phy_indirect(bus, phy_addr, devad, regnum); ++ /* Write the data into MMD's selected register */ ++ return __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); ++} ++ + /** + * __phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. +@@ -539,26 +561,14 @@ static void mmd_phy_indirect(struct mii_ + */ + int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) + { +- int val; +- + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + +- if (phydev->drv && phydev->drv->read_mmd) { +- val = phydev->drv->read_mmd(phydev, devad, regnum); +- } else if (phydev->is_c45) { +- val = __mdiobus_c45_read(phydev->mdio.bus, phydev->mdio.addr, +- devad, regnum); +- } else { +- struct mii_bus *bus = phydev->mdio.bus; +- int phy_addr = phydev->mdio.addr; +- +- mmd_phy_indirect(bus, phy_addr, devad, regnum); +- +- /* Read the content of the MMD's selected register */ +- val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA); +- } +- return val; ++ if (phydev->drv && phydev->drv->read_mmd) ++ return phydev->drv->read_mmd(phydev, devad, regnum); ++ ++ return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr, ++ phydev->is_c45, devad, regnum); + } + EXPORT_SYMBOL(__phy_read_mmd); + +@@ -595,28 +605,14 @@ EXPORT_SYMBOL(phy_read_mmd); + */ + int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) + { +- int ret; +- + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + +- if (phydev->drv && phydev->drv->write_mmd) { +- ret = phydev->drv->write_mmd(phydev, devad, regnum, val); +- } else if (phydev->is_c45) { +- ret = __mdiobus_c45_write(phydev->mdio.bus, phydev->mdio.addr, +- devad, regnum, val); +- } else { +- struct mii_bus *bus = phydev->mdio.bus; +- int phy_addr = phydev->mdio.addr; ++ if (phydev->drv && phydev->drv->write_mmd) ++ return phydev->drv->write_mmd(phydev, devad, regnum, val); + +- mmd_phy_indirect(bus, phy_addr, devad, regnum); +- +- /* Write the data into MMD's selected register */ +- __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); +- +- ret = 0; +- } +- return ret; ++ return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr, ++ phydev->is_c45, devad, regnum, val); + } + EXPORT_SYMBOL(__phy_write_mmd); + diff --git a/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch new file mode 100644 index 0000000000..a628a37929 --- /dev/null +++ b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch @@ -0,0 +1,196 @@ +From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:34 +0100 +Subject: [PATCH 4/4] net: phy: add support for PHY package MMD read/write + +Some PHY in PHY package may require to read/write MMD regs to correctly +configure the PHY package. + +Add support for these additional required function in both lock and no +lock variant. + +It's assumed that the entire PHY package is either C22 or C45. We use +C22 or C45 way of writing/reading to mmd regs based on the passed phydev +whether it's C22 or C45. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 140 +++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 16 +++++ + 2 files changed, 156 insertions(+) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -639,6 +639,146 @@ int phy_write_mmd(struct phy_device *phy + EXPORT_SYMBOL(phy_write_mmd); + + /** ++ * __phy_package_read_mmd - read MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to read from ++ * @regnum: The register on the MMD to read ++ * ++ * Convenience helper for reading a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for __phy_read(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int __phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum); ++} ++EXPORT_SYMBOL(__phy_package_read_mmd); ++ ++/** ++ * phy_package_read_mmd - read MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to read from ++ * @regnum: The register on the MMD to read ++ * ++ * Convenience helper for reading a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for phy_read(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ int val; ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ phy_lock_mdio_bus(phydev); ++ val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum); ++ phy_unlock_mdio_bus(phydev); ++ ++ return val; ++} ++EXPORT_SYMBOL(phy_package_read_mmd); ++ ++/** ++ * __phy_package_write_mmd - write MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to write to ++ * @regnum: The register on the MMD to write ++ * @val: value to write to @regnum ++ * ++ * Convenience helper for writing a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for __phy_write(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int __phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum, val); ++} ++EXPORT_SYMBOL(__phy_package_write_mmd); ++ ++/** ++ * phy_package_write_mmd - write MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to write to ++ * @regnum: The register on the MMD to write ++ * @val: value to write to @regnum ++ * ++ * Convenience helper for writing a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for phy_write(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ int ret; ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum, val); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++EXPORT_SYMBOL(phy_package_write_mmd); ++ ++/** + * phy_modify_changed - Function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1840,6 +1840,22 @@ static inline int __phy_package_write(st + return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + ++int __phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum); ++ ++int phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum); ++ ++int __phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val); ++ ++int phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val); ++ + static inline bool __phy_package_set_once(struct phy_device *phydev, + unsigned int b) + { diff --git a/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch b/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch new file mode 100644 index 0000000000..2886123f2d --- /dev/null +++ b/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch @@ -0,0 +1,103 @@ +From affa013f494486079c3c5ad2d00cebc41a3d7445 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:36 -0400 +Subject: [PATCH 01/21] net: fman: memac: Add serdes support + +This adds support for using a serdes which has to be configured. This is +primarly in preparation for phylink conversion, which will then change the +serdes mode dynamically. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + .../net/ethernet/freescale/fman/fman_memac.c | 49 ++++++++++++++++++- + 1 file changed, 47 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + /* PCS registers */ +@@ -324,6 +325,7 @@ struct fman_mac { + void *fm; + struct fman_rev_info fm_rev_info; + bool basex_if; ++ struct phy *serdes; + struct phy_device *pcsphy; + bool allmulti_enabled; + }; +@@ -1203,17 +1205,56 @@ int memac_initialization(struct mac_devi + } + } + ++ memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); ++ err = PTR_ERR(memac->serdes); ++ if (err == -ENODEV || err == -ENOSYS) { ++ dev_dbg(mac_dev->dev, "could not get (optional) serdes\n"); ++ memac->serdes = NULL; ++ } else if (IS_ERR(memac->serdes)) { ++ dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); ++ goto _return_fm_mac_free; ++ } else { ++ err = phy_init(memac->serdes); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not initialize serdes\n"); ++ goto _return_fm_mac_free; ++ } ++ ++ err = phy_power_on(memac->serdes); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not power on serdes\n"); ++ goto _return_phy_exit; ++ } ++ ++ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || ++ memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || ++ memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || ++ memac->phy_if == PHY_INTERFACE_MODE_QSGMII || ++ memac->phy_if == PHY_INTERFACE_MODE_XGMII) { ++ err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, ++ memac->phy_if); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not set serdes mode to %s\n", ++ phy_modes(memac->phy_if)); ++ goto _return_phy_power_off; ++ } ++ } ++ } ++ + if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { + struct phy_device *phy; + + err = of_phy_register_fixed_link(mac_node); + if (err) +- goto _return_fm_mac_free; ++ goto _return_phy_power_off; + + fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); + if (!fixed_link) { + err = -ENOMEM; +- goto _return_fm_mac_free; ++ goto _return_phy_power_off; + } + + mac_dev->phy_node = of_node_get(mac_node); +@@ -1242,6 +1283,10 @@ int memac_initialization(struct mac_devi + + goto _return; + ++_return_phy_power_off: ++ phy_power_off(memac->serdes); ++_return_phy_exit: ++ phy_exit(memac->serdes); + _return_fixed_link_free: + kfree(fixed_link); + _return_fm_mac_free: diff --git a/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch b/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch new file mode 100644 index 0000000000..873debc080 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch @@ -0,0 +1,384 @@ +From fe60e7154d3a35af975c5e6570d6ec31aab9a731 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:37 -0400 +Subject: [PATCH 02/21] net: fman: memac: Use lynx pcs driver + +Although not stated in the datasheet, as far as I can tell PCS for mEMACs +is a "Lynx." By reusing the existing driver, we can remove the PCS +management code from the memac driver. This requires calling some PCS +functions manually which phylink would usually do for us, but we will let +it do that soon. + +One problem is that we don't actually have a PCS for QSGMII. We pretend +that each mEMAC's MDIO bus has four QSGMII PCSs, but this is not the case. +Only the "base" mEMAC's MDIO bus has the four QSGMII PCSs. This is not an +issue yet, because we never get the PCS state. However, it will be once the +conversion to phylink is complete, since the links will appear to never +come up. To get around this, we allow specifying multiple PCSs in pcsphy. +This breaks backwards compatibility with old device trees, but only for +QSGMII. IMO this is the only reasonable way to figure out what the actual +QSGMII PCS is. + +Additionally, we now also support a separate XFI PCS. This can allow the +SerDes driver to set different addresses for the SGMII and XFI PCSs so they +can be accessed at the same time. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/freescale/fman/Kconfig | 3 + + .../net/ethernet/freescale/fman/fman_memac.c | 258 +++++++----------- + 2 files changed, 105 insertions(+), 156 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/Kconfig ++++ b/drivers/net/ethernet/freescale/fman/Kconfig +@@ -4,6 +4,9 @@ config FSL_FMAN + depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST + select GENERIC_ALLOCATOR + select PHYLIB ++ select PHYLINK ++ select PCS ++ select PCS_LYNX + select CRC32 + default n + help +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -11,43 +11,12 @@ + + #include + #include ++#include + #include + #include + #include + #include + +-/* PCS registers */ +-#define MDIO_SGMII_CR 0x00 +-#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 +-#define MDIO_SGMII_LINK_TMR_L 0x12 +-#define MDIO_SGMII_LINK_TMR_H 0x13 +-#define MDIO_SGMII_IF_MODE 0x14 +- +-/* SGMII Control defines */ +-#define SGMII_CR_AN_EN 0x1000 +-#define SGMII_CR_RESTART_AN 0x0200 +-#define SGMII_CR_FD 0x0100 +-#define SGMII_CR_SPEED_SEL1_1G 0x0040 +-#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ +- SGMII_CR_SPEED_SEL1_1G) +- +-/* SGMII Device Ability for SGMII defines */ +-#define MDIO_SGMII_DEV_ABIL_SGMII_MODE 0x4001 +-#define MDIO_SGMII_DEV_ABIL_BASEX_MODE 0x01A0 +- +-/* Link timer define */ +-#define LINK_TMR_L 0xa120 +-#define LINK_TMR_H 0x0007 +-#define LINK_TMR_L_BASEX 0xaf08 +-#define LINK_TMR_H_BASEX 0x002f +- +-/* SGMII IF Mode defines */ +-#define IF_MODE_USE_SGMII_AN 0x0002 +-#define IF_MODE_SGMII_EN 0x0001 +-#define IF_MODE_SGMII_SPEED_100M 0x0004 +-#define IF_MODE_SGMII_SPEED_1G 0x0008 +-#define IF_MODE_SGMII_DUPLEX_HALF 0x0010 +- + /* Num of additional exact match MAC adr regs */ + #define MEMAC_NUM_OF_PADDRS 7 + +@@ -326,7 +295,9 @@ struct fman_mac { + struct fman_rev_info fm_rev_info; + bool basex_if; + struct phy *serdes; +- struct phy_device *pcsphy; ++ struct phylink_pcs *sgmii_pcs; ++ struct phylink_pcs *qsgmii_pcs; ++ struct phylink_pcs *xfi_pcs; + bool allmulti_enabled; + }; + +@@ -487,91 +458,22 @@ static u32 get_mac_addr_hash_code(u64 et + return xor_val; + } + +-static void setup_sgmii_internal_phy(struct fman_mac *memac, +- struct fixed_phy_status *fixed_link) +-{ +- u16 tmp_reg16; +- +- if (WARN_ON(!memac->pcsphy)) +- return; +- +- /* SGMII mode */ +- tmp_reg16 = IF_MODE_SGMII_EN; +- if (!fixed_link) +- /* AN enable */ +- tmp_reg16 |= IF_MODE_USE_SGMII_AN; +- else { +- switch (fixed_link->speed) { +- case 10: +- /* For 10M: IF_MODE[SPEED_10M] = 0 */ +- break; +- case 100: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; +- break; +- case 1000: +- default: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; +- break; +- } +- if (!fixed_link->duplex) +- tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF; +- } +- phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16); +- +- /* Device ability according to SGMII specification */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * According to Cisco SGMII specification the timer should be 1.6 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L); +- +- if (!fixed_link) +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; ++static void setup_sgmii_internal(struct fman_mac *memac, ++ struct phylink_pcs *pcs, ++ struct fixed_phy_status *fixed_link) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); ++ phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : ++ PHY_INTERFACE_MODE_SGMII; ++ unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; ++ ++ linkmode_set_pause(advertising, true, true); ++ pcs->ops->pcs_config(pcs, mode, iface, advertising, true); ++ if (fixed_link) ++ pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, ++ fixed_link->duplex); + else +- /* AN disabled */ +- tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); +-} +- +-static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac) +-{ +- u16 tmp_reg16; +- +- /* AN Device capability */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX); +- +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); ++ pcs->ops->pcs_an_restart(pcs); + } + + static int check_init_parameters(struct fman_mac *memac) +@@ -983,7 +885,6 @@ static int memac_set_exception(struct fm + static int memac_init(struct fman_mac *memac) + { + struct memac_cfg *memac_drv_param; +- u8 i; + enet_addr_t eth_addr; + bool slow_10g_if = false; + struct fixed_phy_status *fixed_link = NULL; +@@ -1036,32 +937,10 @@ static int memac_init(struct fman_mac *m + iowrite32be(reg32, &memac->regs->command_config); + } + +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) { +- /* Configure internal SGMII PHY */ +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- } else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- /* Configure 4 internal SGMII PHYs */ +- for (i = 0; i < 4; i++) { +- u8 qsmgii_phy_addr, phy_addr; +- /* QSGMII PHY address occupies 3 upper bits of 5-bit +- * phy_address; the lower 2 bits are used to extend +- * register address space and access each one of 4 +- * ports inside QSGMII. +- */ +- phy_addr = memac->pcsphy->mdio.addr; +- qsmgii_phy_addr = (u8)((phy_addr << 2) | i); +- memac->pcsphy->mdio.addr = qsmgii_phy_addr; +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- +- memac->pcsphy->mdio.addr = phy_addr; +- } +- } ++ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) ++ setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); ++ else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) ++ setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); + + /* Max Frame Length */ + err = fman_set_mac_max_frame(memac->fm, memac->mac_id, +@@ -1097,12 +976,25 @@ static int memac_init(struct fman_mac *m + return 0; + } + ++static void pcs_put(struct phylink_pcs *pcs) ++{ ++ struct mdio_device *mdiodev; ++ ++ if (IS_ERR_OR_NULL(pcs)) ++ return; ++ ++ mdiodev = lynx_get_mdio_device(pcs); ++ lynx_pcs_destroy(pcs); ++ mdio_device_free(mdiodev); ++} ++ + static int memac_free(struct fman_mac *memac) + { + free_init_resources(memac); + +- if (memac->pcsphy) +- put_device(&memac->pcsphy->mdio.dev); ++ pcs_put(memac->sgmii_pcs); ++ pcs_put(memac->qsgmii_pcs); ++ pcs_put(memac->xfi_pcs); + + kfree(memac->memac_drv_param); + kfree(memac); +@@ -1153,12 +1045,31 @@ static struct fman_mac *memac_config(str + return memac; + } + ++static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, ++ int index) ++{ ++ struct device_node *node; ++ struct mdio_device *mdiodev = NULL; ++ struct phylink_pcs *pcs; ++ ++ node = of_parse_phandle(mac_node, "pcsphy-handle", index); ++ if (node && of_device_is_available(node)) ++ mdiodev = of_mdio_find_device(node); ++ of_node_put(node); ++ ++ if (!mdiodev) ++ return ERR_PTR(-EPROBE_DEFER); ++ ++ pcs = lynx_pcs_create(mdiodev); ++ return pcs; ++} ++ + int memac_initialization(struct mac_device *mac_dev, + struct device_node *mac_node, + struct fman_mac_params *params) + { + int err; +- struct device_node *phy_node; ++ struct phylink_pcs *pcs; + struct fixed_phy_status *fixed_link; + struct fman_mac *memac; + +@@ -1188,23 +1099,58 @@ int memac_initialization(struct mac_devi + memac = mac_dev->fman_mac; + memac->memac_drv_param->max_frame_length = fman_get_max_frm(); + memac->memac_drv_param->reset_on_init = true; +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || +- memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); +- if (!phy_node) { +- pr_err("PCS PHY node is not available\n"); +- err = -EINVAL; ++ ++ err = of_property_match_string(mac_node, "pcs-handle-names", "xfi"); ++ if (err >= 0) { ++ memac->xfi_pcs = memac_pcs_create(mac_node, err); ++ if (IS_ERR(memac->xfi_pcs)) { ++ err = PTR_ERR(memac->xfi_pcs); ++ dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n"); + goto _return_fm_mac_free; + } ++ } else if (err != -EINVAL && err != -ENODATA) { ++ goto _return_fm_mac_free; ++ } + +- memac->pcsphy = of_phy_find_device(phy_node); +- if (!memac->pcsphy) { +- pr_err("of_phy_find_device (PCS PHY) failed\n"); +- err = -EINVAL; ++ err = of_property_match_string(mac_node, "pcs-handle-names", "qsgmii"); ++ if (err >= 0) { ++ memac->qsgmii_pcs = memac_pcs_create(mac_node, err); ++ if (IS_ERR(memac->qsgmii_pcs)) { ++ err = PTR_ERR(memac->qsgmii_pcs); ++ dev_err_probe(mac_dev->dev, err, ++ "missing qsgmii pcs\n"); + goto _return_fm_mac_free; + } ++ } else if (err != -EINVAL && err != -ENODATA) { ++ goto _return_fm_mac_free; ++ } ++ ++ /* For compatibility, if pcs-handle-names is missing, we assume this ++ * phy is the first one in pcsphy-handle ++ */ ++ err = of_property_match_string(mac_node, "pcs-handle-names", "sgmii"); ++ if (err == -EINVAL || err == -ENODATA) ++ pcs = memac_pcs_create(mac_node, 0); ++ else if (err < 0) ++ goto _return_fm_mac_free; ++ else ++ pcs = memac_pcs_create(mac_node, err); ++ ++ if (!pcs) { ++ dev_err(mac_dev->dev, "missing pcs\n"); ++ err = -ENOENT; ++ goto _return_fm_mac_free; + } + ++ /* If err is set here, it means that pcs-handle-names was missing above ++ * (and therefore that xfi_pcs cannot be set). If we are defaulting to ++ * XGMII, assume this is for XFI. Otherwise, assume it is for SGMII. ++ */ ++ if (err && mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ memac->xfi_pcs = pcs; ++ else ++ memac->sgmii_pcs = pcs; ++ + memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); + err = PTR_ERR(memac->serdes); + if (err == -ENODEV || err == -ENOSYS) { diff --git a/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch b/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch new file mode 100644 index 0000000000..63b651bb2d --- /dev/null +++ b/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch @@ -0,0 +1,2451 @@ +From 38e50fc3d43882a43115b4f1ca3eb88255163c5b Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:38 -0400 +Subject: [PATCH 03/21] net: dpaa: Convert to phylink + +This converts DPAA to phylink. All macs are converted. This should work +with no device tree modifications (including those made in this series), +except for QSGMII (as noted previously). + +The mEMAC configuration is one of the tricker areas. I have tried to +capture all the restrictions across the various models. Most of the time, +we assume that if the serdes supports a mode or the phy-interface-mode +specifies it, then we support it. The only place we can't do this is +(RG)MII, since there's no serdes. In that case, we rely on a (new) +devicetree property. There are also several cases where half-duplex is +broken. Unfortunately, only a single compatible is used for the MAC, so we +have to use the board compatible instead. + +The 10GEC conversion is very straightforward, since it only supports XAUI. +There is generally nothing to configure. + +The dTSEC conversion is broadly similar to mEMAC, but is simpler because we +don't support configuring the SerDes (though this can be easily added) and +we don't have multiple PCSs. From what I can tell, there's nothing +different in the driver or documentation between SGMII and 1000BASE-X +except for the advertising. Similarly, I couldn't find anything about +2500BASE-X. In both cases, I treat them like SGMII. These modes aren't used +by any in-tree boards. Similarly, despite being mentioned in the driver, I +couldn't find any documented SoCs which supported QSGMII. I have left it +unimplemented for now. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/freescale/dpaa/Kconfig | 4 +- + .../net/ethernet/freescale/dpaa/dpaa_eth.c | 89 +-- + .../ethernet/freescale/dpaa/dpaa_ethtool.c | 90 +-- + drivers/net/ethernet/freescale/fman/Kconfig | 1 - + .../net/ethernet/freescale/fman/fman_dtsec.c | 458 +++++++-------- + .../net/ethernet/freescale/fman/fman_mac.h | 10 - + .../net/ethernet/freescale/fman/fman_memac.c | 547 +++++++++--------- + .../net/ethernet/freescale/fman/fman_tgec.c | 131 ++--- + drivers/net/ethernet/freescale/fman/mac.c | 168 +----- + drivers/net/ethernet/freescale/fman/mac.h | 23 +- + 10 files changed, 612 insertions(+), 909 deletions(-) + +--- a/drivers/net/ethernet/freescale/dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/dpaa/Kconfig +@@ -2,8 +2,8 @@ + menuconfig FSL_DPAA_ETH + tristate "DPAA Ethernet" + depends on FSL_DPAA && FSL_FMAN +- select PHYLIB +- select FIXED_PHY ++ select PHYLINK ++ select PCS_LYNX + help + Data Path Acceleration Architecture Ethernet driver, + supporting the Freescale QorIQ chips. +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +@@ -264,8 +264,19 @@ static int dpaa_netdev_init(struct net_d + net_dev->needed_headroom = priv->tx_headroom; + net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); + +- mac_dev->net_dev = net_dev; ++ /* The rest of the config is filled in by the mac device already */ ++ mac_dev->phylink_config.dev = &net_dev->dev; ++ mac_dev->phylink_config.type = PHYLINK_NETDEV; + mac_dev->update_speed = dpaa_eth_cgr_set_speed; ++ mac_dev->phylink = phylink_create(&mac_dev->phylink_config, ++ dev_fwnode(mac_dev->dev), ++ mac_dev->phy_if, ++ mac_dev->phylink_ops); ++ if (IS_ERR(mac_dev->phylink)) { ++ err = PTR_ERR(mac_dev->phylink); ++ dev_err_probe(dev, err, "Could not create phylink\n"); ++ return err; ++ } + + /* start without the RUNNING flag, phylib controls it later */ + netif_carrier_off(net_dev); +@@ -273,6 +284,7 @@ static int dpaa_netdev_init(struct net_d + err = register_netdev(net_dev); + if (err < 0) { + dev_err(dev, "register_netdev() = %d\n", err); ++ phylink_destroy(mac_dev->phylink); + return err; + } + +@@ -295,8 +307,7 @@ static int dpaa_stop(struct net_device * + */ + msleep(200); + +- if (mac_dev->phy_dev) +- phy_stop(mac_dev->phy_dev); ++ phylink_stop(mac_dev->phylink); + mac_dev->disable(mac_dev->fman_mac); + + for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { +@@ -305,8 +316,7 @@ static int dpaa_stop(struct net_device * + err = error; + } + +- if (net_dev->phydev) +- phy_disconnect(net_dev->phydev); ++ phylink_disconnect_phy(mac_dev->phylink); + net_dev->phydev = NULL; + + msleep(200); +@@ -834,10 +844,10 @@ static int dpaa_eth_cgr_init(struct dpaa + + /* Set different thresholds based on the configured MAC speed. + * This may turn suboptimal if the MAC is reconfigured at another +- * speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link ++ * speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up + * callback. + */ +- if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) ++ if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD) + cs_th = DPAA_CS_THRESHOLD_10G; + else + cs_th = DPAA_CS_THRESHOLD_1G; +@@ -866,7 +876,7 @@ out_error: + + static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed) + { +- struct net_device *net_dev = mac_dev->net_dev; ++ struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev); + struct dpaa_priv *priv = netdev_priv(net_dev); + struct qm_mcc_initcgr opts = { }; + u32 cs_th; +@@ -2905,58 +2915,6 @@ static void dpaa_eth_napi_disable(struct + } + } + +-static void dpaa_adjust_link(struct net_device *net_dev) +-{ +- struct mac_device *mac_dev; +- struct dpaa_priv *priv; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- mac_dev->adjust_link(mac_dev); +-} +- +-/* The Aquantia PHYs are capable of performing rate adaptation */ +-#define PHY_VEND_AQUANTIA 0x03a1b400 +-#define PHY_VEND_AQUANTIA2 0x31c31c00 +- +-static int dpaa_phy_init(struct net_device *net_dev) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; +- struct mac_device *mac_dev; +- struct phy_device *phy_dev; +- struct dpaa_priv *priv; +- u32 phy_vendor; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, +- &dpaa_adjust_link, 0, +- mac_dev->phy_if); +- if (!phy_dev) { +- netif_err(priv, ifup, net_dev, "init_phy() failed\n"); +- return -ENODEV; +- } +- +- phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10); +- /* Unless the PHY is capable of rate adaptation */ +- if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII || +- (phy_vendor != PHY_VEND_AQUANTIA && +- phy_vendor != PHY_VEND_AQUANTIA2)) { +- /* remove any features not supported by the controller */ +- ethtool_convert_legacy_u32_to_link_mode(mask, +- mac_dev->if_support); +- linkmode_and(phy_dev->supported, phy_dev->supported, mask); +- } +- +- phy_support_asym_pause(phy_dev); +- +- mac_dev->phy_dev = phy_dev; +- net_dev->phydev = phy_dev; +- +- return 0; +-} +- + static int dpaa_open(struct net_device *net_dev) + { + struct mac_device *mac_dev; +@@ -2967,7 +2925,8 @@ static int dpaa_open(struct net_device * + mac_dev = priv->mac_dev; + dpaa_eth_napi_enable(priv); + +- err = dpaa_phy_init(net_dev); ++ err = phylink_of_phy_connect(mac_dev->phylink, ++ mac_dev->dev->of_node, 0); + if (err) + goto phy_init_failed; + +@@ -2982,7 +2941,7 @@ static int dpaa_open(struct net_device * + netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err); + goto mac_start_failed; + } +- phy_start(priv->mac_dev->phy_dev); ++ phylink_start(mac_dev->phylink); + + netif_tx_start_all_queues(net_dev); + +@@ -2991,6 +2950,7 @@ static int dpaa_open(struct net_device * + mac_start_failed: + for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) + fman_port_disable(mac_dev->port[i]); ++ phylink_disconnect_phy(mac_dev->phylink); + + phy_init_failed: + dpaa_eth_napi_disable(priv); +@@ -3146,10 +3106,12 @@ static int dpaa_ts_ioctl(struct net_devi + static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) + { + int ret = -EINVAL; ++ struct dpaa_priv *priv = netdev_priv(net_dev); + + if (cmd == SIOCGMIIREG) { + if (net_dev->phydev) +- return phy_mii_ioctl(net_dev->phydev, rq, cmd); ++ return phylink_mii_ioctl(priv->mac_dev->phylink, rq, ++ cmd); + } + + if (cmd == SIOCSHWTSTAMP) +@@ -3552,6 +3514,7 @@ static int dpaa_remove(struct platform_d + + dev_set_drvdata(dev, NULL); + unregister_netdev(net_dev); ++ phylink_destroy(priv->mac_dev->phylink); + + err = dpaa_fq_free(dev, &priv->dpaa_fq_list); + +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +@@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTR + static int dpaa_get_link_ksettings(struct net_device *net_dev, + struct ethtool_link_ksettings *cmd) + { +- if (!net_dev->phydev) +- return 0; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- phy_ethtool_ksettings_get(net_dev->phydev, cmd); +- +- return 0; ++ return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd); + } + + static int dpaa_set_link_ksettings(struct net_device *net_dev, + const struct ethtool_link_ksettings *cmd) + { +- int err; +- +- if (!net_dev->phydev) +- return -ENODEV; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- err = phy_ethtool_ksettings_set(net_dev->phydev, cmd); +- if (err < 0) +- netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err); +- +- return err; ++ return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd); + } + + static void dpaa_get_drvinfo(struct net_device *net_dev, +@@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net + + static int dpaa_nway_reset(struct net_device *net_dev) + { +- int err; +- +- if (!net_dev->phydev) +- return -ENODEV; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- err = 0; +- if (net_dev->phydev->autoneg) { +- err = phy_start_aneg(net_dev->phydev); +- if (err < 0) +- netdev_err(net_dev, "phy_start_aneg() = %d\n", +- err); +- } +- +- return err; ++ return phylink_ethtool_nway_reset(mac_dev->phylink); + } + + static void dpaa_get_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *epause) + { +- struct mac_device *mac_dev; +- struct dpaa_priv *priv; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- if (!net_dev->phydev) +- return; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- epause->autoneg = mac_dev->autoneg_pause; +- epause->rx_pause = mac_dev->rx_pause_active; +- epause->tx_pause = mac_dev->tx_pause_active; ++ phylink_ethtool_get_pauseparam(mac_dev->phylink, epause); + } + + static int dpaa_set_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *epause) + { +- struct mac_device *mac_dev; +- struct phy_device *phydev; +- bool rx_pause, tx_pause; +- struct dpaa_priv *priv; +- int err; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- phydev = net_dev->phydev; +- if (!phydev) { +- netdev_err(net_dev, "phy device not initialized\n"); +- return -ENODEV; +- } +- +- if (!phy_validate_pause(phydev, epause)) +- return -EINVAL; +- +- /* The MAC should know how to handle PAUSE frame autonegotiation before +- * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE +- * settings. +- */ +- mac_dev->autoneg_pause = !!epause->autoneg; +- mac_dev->rx_pause_req = !!epause->rx_pause; +- mac_dev->tx_pause_req = !!epause->tx_pause; +- +- /* Determine the sym/asym advertised PAUSE capabilities from the desired +- * rx/tx pause settings. +- */ +- +- phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause); +- +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- netdev_err(net_dev, "set_mac_active_pause() = %d\n", err); ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- return err; ++ return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause); + } + + static int dpaa_get_sset_count(struct net_device *net_dev, int type) +--- a/drivers/net/ethernet/freescale/fman/Kconfig ++++ b/drivers/net/ethernet/freescale/fman/Kconfig +@@ -3,7 +3,6 @@ config FSL_FMAN + tristate "FMan support" + depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST + select GENERIC_ALLOCATOR +- select PHYLIB + select PHYLINK + select PCS + select PCS_LYNX +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + /* TBI register addresses */ + #define MII_TBICON 0x11 +@@ -29,9 +30,6 @@ + #define TBICON_CLK_SELECT 0x0020 /* Clock select */ + #define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ + +-#define TBIANA_SGMII 0x4001 +-#define TBIANA_1000X 0x01a0 +- + /* Interrupt Mask Register (IMASK) */ + #define DTSEC_IMASK_BREN 0x80000000 + #define DTSEC_IMASK_RXCEN 0x40000000 +@@ -92,9 +90,10 @@ + + #define DTSEC_ECNTRL_GMIIM 0x00000040 + #define DTSEC_ECNTRL_TBIM 0x00000020 +-#define DTSEC_ECNTRL_SGMIIM 0x00000002 + #define DTSEC_ECNTRL_RPM 0x00000010 + #define DTSEC_ECNTRL_R100M 0x00000008 ++#define DTSEC_ECNTRL_RMM 0x00000004 ++#define DTSEC_ECNTRL_SGMIIM 0x00000002 + #define DTSEC_ECNTRL_QSGMIIM 0x00000001 + + #define TCTRL_TTSE 0x00000040 +@@ -318,7 +317,8 @@ struct fman_mac { + void *fm; + struct fman_rev_info fm_rev_info; + bool basex_if; +- struct phy_device *tbiphy; ++ struct mdio_device *tbidev; ++ struct phylink_pcs pcs; + }; + + static void set_dflts(struct dtsec_cfg *cfg) +@@ -356,56 +356,14 @@ static int init(struct dtsec_regs __iome + phy_interface_t iface, u16 iface_speed, u64 addr, + u32 exception_mask, u8 tbi_addr) + { +- bool is_rgmii, is_sgmii, is_qsgmii; + enet_addr_t eth_addr; +- u32 tmp; ++ u32 tmp = 0; + int i; + + /* Soft reset */ + iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); + iowrite32be(0, ®s->maccfg1); + +- /* dtsec_id2 */ +- tmp = ioread32be(®s->tsec_id2); +- +- /* check RGMII support */ +- if (iface == PHY_INTERFACE_MODE_RGMII || +- iface == PHY_INTERFACE_MODE_RGMII_ID || +- iface == PHY_INTERFACE_MODE_RGMII_RXID || +- iface == PHY_INTERFACE_MODE_RGMII_TXID || +- iface == PHY_INTERFACE_MODE_RMII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- if (iface == PHY_INTERFACE_MODE_SGMII || +- iface == PHY_INTERFACE_MODE_MII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- is_rgmii = iface == PHY_INTERFACE_MODE_RGMII || +- iface == PHY_INTERFACE_MODE_RGMII_ID || +- iface == PHY_INTERFACE_MODE_RGMII_RXID || +- iface == PHY_INTERFACE_MODE_RGMII_TXID; +- is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; +- is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; +- +- tmp = 0; +- if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) +- tmp |= DTSEC_ECNTRL_GMIIM; +- if (is_sgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); +- if (is_qsgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | +- DTSEC_ECNTRL_QSGMIIM); +- if (is_rgmii) +- tmp |= DTSEC_ECNTRL_RPM; +- if (iface_speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- +- iowrite32be(tmp, ®s->ecntrl); +- +- tmp = 0; +- + if (cfg->tx_pause_time) + tmp |= cfg->tx_pause_time; + if (cfg->tx_pause_time_extd) +@@ -446,17 +404,10 @@ static int init(struct dtsec_regs __iome + + tmp = 0; + +- if (iface_speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (iface_speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- + tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & + MACCFG2_PREAMBLE_LENGTH_MASK; + if (cfg->tx_pad_crc) + tmp |= MACCFG2_PAD_CRC_EN; +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; + iowrite32be(tmp, ®s->maccfg2); + + tmp = (((cfg->non_back_to_back_ipg1 << +@@ -525,10 +476,6 @@ static void set_bucket(struct dtsec_regs + + static int check_init_parameters(struct fman_mac *dtsec) + { +- if (dtsec->max_speed >= SPEED_10000) { +- pr_err("1G MAC driver supports 1G or lower speeds\n"); +- return -EINVAL; +- } + if ((dtsec->dtsec_drv_param)->rx_prepend > + MAX_PACKET_ALIGNMENT) { + pr_err("packetAlignmentPadding can't be > than %d\n", +@@ -630,22 +577,10 @@ static int get_exception_flag(enum fman_ + return bit_mask; + } + +-static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) +-{ +- /* Checks if dTSEC driver parameters were initialized */ +- if (!dtsec_drv_params) +- return true; +- +- return false; +-} +- + static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) + { + struct dtsec_regs __iomem *regs = dtsec->regs; + +- if (is_init_done(dtsec->dtsec_drv_param)) +- return 0; +- + return (u16)ioread32be(®s->maxfrm); + } + +@@ -682,6 +617,7 @@ static void dtsec_isr(void *handle) + dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); + if (event & DTSEC_IMASK_XFUNEN) { + /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ ++ /* FIXME: This races with the rest of the driver! */ + if (dtsec->fm_rev_info.major == 2) { + u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; + /* a. Write 0x00E0_0C00 to DTSEC_ID +@@ -814,6 +750,43 @@ static void free_init_resources(struct f + dtsec->unicast_addr_hash = NULL; + } + ++static struct fman_mac *pcs_to_dtsec(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct fman_mac, pcs); ++} ++ ++static void dtsec_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); ++} ++ ++static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, ++ advertising); ++} ++ ++static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ phylink_mii_c22_pcs_an_restart(dtsec->tbidev); ++} ++ ++static const struct phylink_pcs_ops dtsec_pcs_ops = { ++ .pcs_get_state = dtsec_pcs_get_state, ++ .pcs_config = dtsec_pcs_config, ++ .pcs_an_restart = dtsec_pcs_an_restart, ++}; ++ + static void graceful_start(struct fman_mac *dtsec) + { + struct dtsec_regs __iomem *regs = dtsec->regs; +@@ -854,36 +827,11 @@ static void graceful_stop(struct fman_ma + + static int dtsec_enable(struct fman_mac *dtsec) + { +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Enable */ +- tmp = ioread32be(®s->maccfg1); +- tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; +- iowrite32be(tmp, ®s->maccfg1); +- +- /* Graceful start - clear the graceful Rx/Tx stop bit */ +- graceful_start(dtsec); +- + return 0; + } + + static void dtsec_disable(struct fman_mac *dtsec) + { +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(dtsec->dtsec_drv_param)); +- +- /* Graceful stop - Assert the graceful Rx/Tx stop bit */ +- graceful_stop(dtsec); +- +- tmp = ioread32be(®s->maccfg1); +- tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); +- iowrite32be(tmp, ®s->maccfg1); + } + + static int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, +@@ -894,11 +842,6 @@ static int dtsec_set_tx_pause_frames(str + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 ptv = 0; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- + if (pause_time) { + /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ + if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { +@@ -919,8 +862,6 @@ static int dtsec_set_tx_pause_frames(str + iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, + ®s->maccfg1); + +- graceful_start(dtsec); +- + return 0; + } + +@@ -929,11 +870,6 @@ static int dtsec_accept_rx_pause_frames( + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 tmp; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- + tmp = ioread32be(®s->maccfg1); + if (en) + tmp |= MACCFG1_RX_FLOW; +@@ -941,17 +877,125 @@ static int dtsec_accept_rx_pause_frames( + tmp &= ~MACCFG1_RX_FLOW; + iowrite32be(tmp, ®s->maccfg1); + ++ return 0; ++} ++ ++static struct phylink_pcs *dtsec_select_pcs(struct phylink_config *config, ++ phy_interface_t iface) ++{ ++ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return &dtsec->pcs; ++ default: ++ return NULL; ++ } ++} ++ ++static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; ++ u32 tmp; ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_RMII: ++ tmp = DTSEC_ECNTRL_RMM; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ break; ++ default: ++ dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", ++ phy_modes(state->interface)); ++ return; ++ } ++ ++ iowrite32be(tmp, ®s->ecntrl); ++} ++ ++static void dtsec_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 mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *dtsec = mac_dev->fman_mac; ++ struct dtsec_regs __iomem *regs = dtsec->regs; ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ u32 tmp; ++ ++ dtsec_set_tx_pause_frames(dtsec, 0, pause_time, 0); ++ dtsec_accept_rx_pause_frames(dtsec, rx_pause); ++ ++ tmp = ioread32be(®s->ecntrl); ++ if (speed == SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ else ++ tmp &= ~DTSEC_ECNTRL_R100M; ++ iowrite32be(tmp, ®s->ecntrl); ++ ++ tmp = ioread32be(®s->maccfg2); ++ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE | MACCFG2_FULL_DUPLEX); ++ if (speed >= SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ else ++ tmp |= MACCFG2_NIBBLE_MODE; ++ ++ if (duplex == DUPLEX_FULL) ++ tmp |= MACCFG2_FULL_DUPLEX; ++ ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ mac_dev->update_speed(mac_dev, speed); ++ ++ /* Enable */ ++ tmp = ioread32be(®s->maccfg1); ++ tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; ++ iowrite32be(tmp, ®s->maccfg1); ++ ++ /* Graceful start - clear the graceful Rx/Tx stop bit */ + graceful_start(dtsec); ++} + +- return 0; ++static void dtsec_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; ++ struct dtsec_regs __iomem *regs = dtsec->regs; ++ u32 tmp; ++ ++ /* Graceful stop - Assert the graceful Rx/Tx stop bit */ ++ graceful_stop(dtsec); ++ ++ tmp = ioread32be(®s->maccfg1); ++ tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); ++ iowrite32be(tmp, ®s->maccfg1); + } + ++static const struct phylink_mac_ops dtsec_mac_ops = { ++ .validate = phylink_generic_validate, ++ .mac_select_pcs = dtsec_select_pcs, ++ .mac_config = dtsec_mac_config, ++ .mac_link_up = dtsec_link_up, ++ .mac_link_down = dtsec_link_down, ++}; ++ + static int dtsec_modify_mac_address(struct fman_mac *dtsec, + const enet_addr_t *enet_addr) + { +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + graceful_stop(dtsec); + + /* Initialize MAC Station Address registers (1 & 2) +@@ -975,9 +1019,6 @@ static int dtsec_add_hash_mac_address(st + u32 crc = 0xFFFFFFFF; + bool mcast, ghtx; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +@@ -1037,9 +1078,6 @@ static int dtsec_set_allmulti(struct fma + u32 tmp; + struct dtsec_regs __iomem *regs = dtsec->regs; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->rctrl); + if (enable) + tmp |= RCTRL_MPROM; +@@ -1056,9 +1094,6 @@ static int dtsec_set_tstamp(struct fman_ + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 rctrl, tctrl; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + rctrl = ioread32be(®s->rctrl); + tctrl = ioread32be(®s->tctrl); + +@@ -1087,9 +1122,6 @@ static int dtsec_del_hash_mac_address(st + u32 crc = 0xFFFFFFFF; + bool mcast, ghtx; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +@@ -1153,9 +1185,6 @@ static int dtsec_set_promiscuous(struct + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 tmp; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + /* Set unicast promiscuous */ + tmp = ioread32be(®s->rctrl); + if (new_val) +@@ -1177,90 +1206,12 @@ static int dtsec_set_promiscuous(struct + return 0; + } + +-static int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- +- tmp = ioread32be(®s->maccfg2); +- +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; +- +- tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); +- if (speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- iowrite32be(tmp, ®s->maccfg2); +- +- tmp = ioread32be(®s->ecntrl); +- if (speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- else +- tmp &= ~DTSEC_ECNTRL_R100M; +- iowrite32be(tmp, ®s->ecntrl); +- +- graceful_start(dtsec); +- +- return 0; +-} +- +-static int dtsec_restart_autoneg(struct fman_mac *dtsec) +-{ +- u16 tmp_reg16; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); +- +- tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); +- tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- return 0; +-} +- +-static void adjust_link_dtsec(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- if (!phy_dev->link) { +- dtsec_restart_autoneg(fman_mac); +- +- return; +- } +- +- dtsec_adjust_link(fman_mac, phy_dev->speed); +- mac_dev->update_speed(mac_dev, phy_dev->speed); +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", +- err); +-} +- + static int dtsec_set_exception(struct fman_mac *dtsec, + enum fman_mac_exceptions exception, bool enable) + { + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 bit_mask = 0; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { + bit_mask = get_exception_flag(exception); + if (bit_mask) { +@@ -1310,12 +1261,9 @@ static int dtsec_init(struct fman_mac *d + { + struct dtsec_regs __iomem *regs = dtsec->regs; + struct dtsec_cfg *dtsec_drv_param; +- u16 max_frm_ln; ++ u16 max_frm_ln, tbicon; + int err; + +- if (is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + if (DEFAULT_RESET_ON_INIT && + (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { + pr_err("Can't reset MAC!\n"); +@@ -1330,38 +1278,19 @@ static int dtsec_init(struct fman_mac *d + + err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, + dtsec->max_speed, dtsec->addr, dtsec->exceptions, +- dtsec->tbiphy->mdio.addr); ++ dtsec->tbidev->addr); + if (err) { + free_init_resources(dtsec); + pr_err("DTSEC version doesn't support this i/f mode\n"); + return err; + } + +- if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { +- u16 tmp_reg16; +- +- /* Configure the TBI PHY Control Register */ +- tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = TBICON_CLK_SELECT; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- if (dtsec->basex_if) +- tmp_reg16 = TBIANA_1000X; +- else +- tmp_reg16 = TBIANA_SGMII; +- phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); ++ /* Configure the TBI PHY Control Register */ ++ tbicon = TBICON_CLK_SELECT | TBICON_SOFT_RESET; ++ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); + +- tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- } ++ tbicon = TBICON_CLK_SELECT; ++ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); + + /* Max Frame Length */ + max_frm_ln = (u16)ioread32be(®s->maxfrm); +@@ -1406,6 +1335,8 @@ static int dtsec_free(struct fman_mac *d + + kfree(dtsec->dtsec_drv_param); + dtsec->dtsec_drv_param = NULL; ++ if (!IS_ERR_OR_NULL(dtsec->tbidev)) ++ put_device(&dtsec->tbidev->dev); + kfree(dtsec); + + return 0; +@@ -1434,7 +1365,6 @@ static struct fman_mac *dtsec_config(str + + dtsec->regs = mac_dev->vaddr; + dtsec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); +- dtsec->max_speed = params->max_speed; + dtsec->phy_if = mac_dev->phy_if; + dtsec->mac_id = params->mac_id; + dtsec->exceptions = (DTSEC_IMASK_BREN | +@@ -1457,7 +1387,6 @@ static struct fman_mac *dtsec_config(str + dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en; + + dtsec->fm = params->fm; +- dtsec->basex_if = params->basex_if; + + /* Save FMan revision */ + fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); +@@ -1476,18 +1405,18 @@ int dtsec_initialization(struct mac_devi + int err; + struct fman_mac *dtsec; + struct device_node *phy_node; ++ unsigned long capabilities; ++ unsigned long *supported; + ++ mac_dev->phylink_ops = &dtsec_mac_ops; + mac_dev->set_promisc = dtsec_set_promiscuous; + mac_dev->change_addr = dtsec_modify_mac_address; + mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; +- mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; +- mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; + mac_dev->set_exception = dtsec_set_exception; + mac_dev->set_allmulti = dtsec_set_allmulti; + mac_dev->set_tstamp = dtsec_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = adjust_link_dtsec; + mac_dev->enable = dtsec_enable; + mac_dev->disable = dtsec_disable; + +@@ -1502,19 +1431,56 @@ int dtsec_initialization(struct mac_devi + dtsec->dtsec_drv_param->tx_pad_crc = true; + + phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); +- if (!phy_node) { +- pr_err("TBI PHY node is not available\n"); ++ if (!phy_node || of_device_is_available(phy_node)) { ++ of_node_put(phy_node); + err = -EINVAL; ++ dev_err_probe(mac_dev->dev, err, ++ "TBI PCS node is not available\n"); + goto _return_fm_mac_free; + } + +- dtsec->tbiphy = of_phy_find_device(phy_node); +- if (!dtsec->tbiphy) { +- pr_err("of_phy_find_device (TBI PHY) failed\n"); +- err = -EINVAL; ++ dtsec->tbidev = of_mdio_find_device(phy_node); ++ of_node_put(phy_node); ++ if (!dtsec->tbidev) { ++ err = -EPROBE_DEFER; ++ dev_err_probe(mac_dev->dev, err, ++ "could not find mdiodev for PCS\n"); + goto _return_fm_mac_free; + } +- put_device(&dtsec->tbiphy->mdio.dev); ++ dtsec->pcs.ops = &dtsec_pcs_ops; ++ dtsec->pcs.poll = true; ++ ++ supported = mac_dev->phylink_config.supported_interfaces; ++ ++ /* FIXME: Can we use DTSEC_ID2_INT_FULL_OFF to determine if these are ++ * supported? If not, we can determine support via the phy if SerDes ++ * support is added. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII || ++ mac_dev->phy_if == PHY_INTERFACE_MODE_1000BASEX) { ++ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); ++ } else if (mac_dev->phy_if == PHY_INTERFACE_MODE_2500BASEX) { ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); ++ } ++ ++ if (!(ioread32be(&dtsec->regs->tsec_id2) & DTSEC_ID2_INT_REDUCED_OFF)) { ++ phy_interface_set_rgmii(supported); ++ ++ /* DTSEC_ID2_INT_REDUCED_OFF indicates that the dTSEC supports ++ * RMII and RGMII. However, the only SoCs which support RMII ++ * are the P1017 and P1023. Avoid advertising this mode on ++ * other SoCs. This is a bit of a moot point, since there's no ++ * in-tree support for ethernet on these platforms... ++ */ ++ if (of_machine_is_compatible("fsl,P1023") || ++ of_machine_is_compatible("fsl,P1023RDB")) ++ __set_bit(PHY_INTERFACE_MODE_RMII, supported); ++ } ++ ++ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; ++ capabilities |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; ++ mac_dev->phylink_config.mac_capabilities = capabilities; + + err = dtsec_init(dtsec); + if (err < 0) +--- a/drivers/net/ethernet/freescale/fman/fman_mac.h ++++ b/drivers/net/ethernet/freescale/fman/fman_mac.h +@@ -170,20 +170,10 @@ struct fman_mac_params { + * 0 - FM_MAX_NUM_OF_10G_MACS + */ + u8 mac_id; +- /* Note that the speed should indicate the maximum rate that +- * this MAC should support rather than the actual speed; +- */ +- u16 max_speed; + /* A handle to the FM object this port related to */ + void *fm; + fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ + fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ +- /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC +- * and phy or backplane; Note: 1000BaseX auto-negotiation relates only +- * to interface between MAC and phy/backplane, SGMII phy can still +- * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps +- */ +- bool basex_if; + }; + + struct eth_hash_t { +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -278,9 +278,6 @@ struct fman_mac { + struct memac_regs __iomem *regs; + /* MAC address of device */ + u64 addr; +- /* Ethernet physical interface */ +- phy_interface_t phy_if; +- u16 max_speed; + struct mac_device *dev_id; /* device cookie used by the exception cbs */ + fman_mac_exception_cb *exception_cb; + fman_mac_exception_cb *event_cb; +@@ -293,12 +290,12 @@ struct fman_mac { + struct memac_cfg *memac_drv_param; + void *fm; + struct fman_rev_info fm_rev_info; +- bool basex_if; + struct phy *serdes; + struct phylink_pcs *sgmii_pcs; + struct phylink_pcs *qsgmii_pcs; + struct phylink_pcs *xfi_pcs; + bool allmulti_enabled; ++ bool rgmii_no_half_duplex; + }; + + static void add_addr_in_paddr(struct memac_regs __iomem *regs, const u8 *adr, +@@ -356,7 +353,6 @@ static void set_exception(struct memac_r + } + + static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, +- phy_interface_t phy_if, u16 speed, bool slow_10g_if, + u32 exceptions) + { + u32 tmp; +@@ -384,41 +380,6 @@ static int init(struct memac_regs __iome + iowrite32be((u32)cfg->pause_quanta, ®s->pause_quanta[0]); + iowrite32be((u32)0, ®s->pause_thresh[0]); + +- /* IF_MODE */ +- tmp = 0; +- switch (phy_if) { +- case PHY_INTERFACE_MODE_XGMII: +- tmp |= IF_MODE_10G; +- break; +- case PHY_INTERFACE_MODE_MII: +- tmp |= IF_MODE_MII; +- break; +- default: +- tmp |= IF_MODE_GMII; +- if (phy_if == PHY_INTERFACE_MODE_RGMII || +- phy_if == PHY_INTERFACE_MODE_RGMII_ID || +- phy_if == PHY_INTERFACE_MODE_RGMII_RXID || +- phy_if == PHY_INTERFACE_MODE_RGMII_TXID) +- tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; +- } +- iowrite32be(tmp, ®s->if_mode); +- +- /* TX_FIFO_SECTIONS */ +- tmp = 0; +- if (phy_if == PHY_INTERFACE_MODE_XGMII) { +- if (slow_10g_if) { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); +- } +- iowrite32be(tmp, ®s->tx_fifo_sections); +- + /* clear all pending events and set-up interrupts */ + iowrite32be(0xffffffff, ®s->ievent); + set_exception(regs, exceptions, true); +@@ -458,24 +419,6 @@ static u32 get_mac_addr_hash_code(u64 et + return xor_val; + } + +-static void setup_sgmii_internal(struct fman_mac *memac, +- struct phylink_pcs *pcs, +- struct fixed_phy_status *fixed_link) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); +- phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : +- PHY_INTERFACE_MODE_SGMII; +- unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; +- +- linkmode_set_pause(advertising, true, true); +- pcs->ops->pcs_config(pcs, mode, iface, advertising, true); +- if (fixed_link) +- pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, +- fixed_link->duplex); +- else +- pcs->ops->pcs_an_restart(pcs); +-} +- + static int check_init_parameters(struct fman_mac *memac) + { + if (!memac->exception_cb) { +@@ -581,41 +524,31 @@ static void free_init_resources(struct f + memac->unicast_addr_hash = NULL; + } + +-static bool is_init_done(struct memac_cfg *memac_drv_params) +-{ +- /* Checks if mEMAC driver parameters were initialized */ +- if (!memac_drv_params) +- return true; +- +- return false; +-} +- + static int memac_enable(struct fman_mac *memac) + { +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; ++ int ret; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; ++ ret = phy_init(memac->serdes); ++ if (ret) { ++ dev_err(memac->dev_id->dev, ++ "could not initialize serdes: %pe\n", ERR_PTR(ret)); ++ return ret; ++ } + +- tmp = ioread32be(®s->command_config); +- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); ++ ret = phy_power_on(memac->serdes); ++ if (ret) { ++ dev_err(memac->dev_id->dev, ++ "could not power on serdes: %pe\n", ERR_PTR(ret)); ++ phy_exit(memac->serdes); ++ } + +- return 0; ++ return ret; + } + + static void memac_disable(struct fman_mac *memac) +- + { +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(memac->memac_drv_param)); +- +- tmp = ioread32be(®s->command_config); +- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); +- iowrite32be(tmp, ®s->command_config); ++ phy_power_off(memac->serdes); ++ phy_exit(memac->serdes); + } + + static int memac_set_promiscuous(struct fman_mac *memac, bool new_val) +@@ -623,9 +556,6 @@ static int memac_set_promiscuous(struct + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (new_val) + tmp |= CMD_CFG_PROMIS_EN; +@@ -637,73 +567,12 @@ static int memac_set_promiscuous(struct + return 0; + } + +-static int memac_adjust_link(struct fman_mac *memac, u16 speed) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->if_mode); +- +- /* Set full duplex */ +- tmp &= ~IF_MODE_HD; +- +- if (phy_interface_mode_is_rgmii(memac->phy_if)) { +- /* Configure RGMII in manual mode */ +- tmp &= ~IF_MODE_RGMII_AUTO; +- tmp &= ~IF_MODE_RGMII_SP_MASK; +- /* Full duplex */ +- tmp |= IF_MODE_RGMII_FD; +- +- switch (speed) { +- case SPEED_1000: +- tmp |= IF_MODE_RGMII_1000; +- break; +- case SPEED_100: +- tmp |= IF_MODE_RGMII_100; +- break; +- case SPEED_10: +- tmp |= IF_MODE_RGMII_10; +- break; +- default: +- break; +- } +- } +- +- iowrite32be(tmp, ®s->if_mode); +- +- return 0; +-} +- +-static void adjust_link_memac(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- memac_adjust_link(fman_mac, phy_dev->speed); +- mac_dev->update_speed(mac_dev, phy_dev->speed); +- +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", +- err); +-} +- + static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, + u16 pause_time, u16 thresh_time) + { + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->tx_fifo_sections); + + GET_TX_EMPTY_DEFAULT_VALUE(tmp); +@@ -738,9 +607,6 @@ static int memac_accept_rx_pause_frames( + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (en) + tmp &= ~CMD_CFG_PAUSE_IGNORE; +@@ -752,12 +618,175 @@ static int memac_accept_rx_pause_frames( + return 0; + } + ++static void memac_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ unsigned long caps = config->mac_capabilities; ++ ++ if (phy_interface_mode_is_rgmii(state->interface) && ++ memac->rgmii_no_half_duplex) ++ caps &= ~(MAC_10HD | MAC_100HD); ++ ++ phylink_validate_mask_caps(supported, state, caps); ++} ++ ++/** ++ * memac_if_mode() - Convert an interface mode into an IF_MODE config ++ * @interface: A phy interface mode ++ * ++ * Return: A configuration word, suitable for programming into the lower bits ++ * of %IF_MODE. ++ */ ++static u32 memac_if_mode(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_MII: ++ return IF_MODE_MII; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ return IF_MODE_GMII | IF_MODE_RGMII; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return IF_MODE_GMII; ++ case PHY_INTERFACE_MODE_10GBASER: ++ return IF_MODE_10G; ++ default: ++ WARN_ON_ONCE(1); ++ return 0; ++ } ++} ++ ++static struct phylink_pcs *memac_select_pcs(struct phylink_config *config, ++ phy_interface_t iface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ return memac->sgmii_pcs; ++ case PHY_INTERFACE_MODE_QSGMII: ++ return memac->qsgmii_pcs; ++ case PHY_INTERFACE_MODE_10GBASER: ++ return memac->xfi_pcs; ++ default: ++ return NULL; ++ } ++} ++ ++static int memac_prepare(struct phylink_config *config, unsigned int mode, ++ phy_interface_t iface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, ++ iface); ++ default: ++ return 0; ++ } ++} ++ ++static void memac_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct memac_regs __iomem *regs = mac_dev->fman_mac->regs; ++ u32 tmp = ioread32be(®s->if_mode); ++ ++ tmp &= ~(IF_MODE_MASK | IF_MODE_RGMII); ++ tmp |= memac_if_mode(state->interface); ++ if (phylink_autoneg_inband(mode)) ++ tmp |= IF_MODE_RGMII_AUTO; ++ iowrite32be(tmp, ®s->if_mode); ++} ++ ++static void memac_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 mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *memac = mac_dev->fman_mac; ++ struct memac_regs __iomem *regs = memac->regs; ++ u32 tmp = memac_if_mode(interface); ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ ++ memac_set_tx_pause_frames(memac, 0, pause_time, 0); ++ memac_accept_rx_pause_frames(memac, rx_pause); ++ ++ if (duplex == DUPLEX_HALF) ++ tmp |= IF_MODE_HD; ++ ++ switch (speed) { ++ case SPEED_1000: ++ tmp |= IF_MODE_RGMII_1000; ++ break; ++ case SPEED_100: ++ tmp |= IF_MODE_RGMII_100; ++ break; ++ case SPEED_10: ++ tmp |= IF_MODE_RGMII_10; ++ break; ++ } ++ iowrite32be(tmp, ®s->if_mode); ++ ++ /* TODO: EEE? */ ++ ++ if (speed == SPEED_10000) { ++ if (memac->fm_rev_info.major == 6 && ++ memac->fm_rev_info.minor == 4) ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G; ++ else ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_10G; ++ tmp |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G; ++ } else { ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_1G | ++ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G; ++ } ++ iowrite32be(tmp, ®s->tx_fifo_sections); ++ ++ mac_dev->update_speed(mac_dev, speed); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static void memac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ struct memac_regs __iomem *regs = memac->regs; ++ u32 tmp; ++ ++ /* TODO: graceful */ ++ tmp = ioread32be(®s->command_config); ++ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static const struct phylink_mac_ops memac_mac_ops = { ++ .validate = memac_validate, ++ .mac_select_pcs = memac_select_pcs, ++ .mac_prepare = memac_prepare, ++ .mac_config = memac_mac_config, ++ .mac_link_up = memac_link_up, ++ .mac_link_down = memac_link_down, ++}; ++ + static int memac_modify_mac_address(struct fman_mac *memac, + const enet_addr_t *enet_addr) + { +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0); + + return 0; +@@ -771,9 +800,6 @@ static int memac_add_hash_mac_address(st + u32 hash; + u64 addr; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + if (!(addr & GROUP_ADDRESS)) { +@@ -802,9 +828,6 @@ static int memac_set_allmulti(struct fma + u32 entry; + struct memac_regs __iomem *regs = memac->regs; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + if (enable) { + for (entry = 0; entry < HASH_TABLE_SIZE; entry++) + iowrite32be(entry | HASH_CTRL_MCAST_EN, +@@ -834,9 +857,6 @@ static int memac_del_hash_mac_address(st + u32 hash; + u64 addr; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; +@@ -864,9 +884,6 @@ static int memac_set_exception(struct fm + { + u32 bit_mask = 0; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + bit_mask = get_exception_flag(exception); + if (bit_mask) { + if (enable) +@@ -886,23 +903,15 @@ static int memac_init(struct fman_mac *m + { + struct memac_cfg *memac_drv_param; + enet_addr_t eth_addr; +- bool slow_10g_if = false; +- struct fixed_phy_status *fixed_link = NULL; + int err; + u32 reg32 = 0; + +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + err = check_init_parameters(memac); + if (err) + return err; + + memac_drv_param = memac->memac_drv_param; + +- if (memac->fm_rev_info.major == 6 && memac->fm_rev_info.minor == 4) +- slow_10g_if = true; +- + /* First, reset the MAC if desired. */ + if (memac_drv_param->reset_on_init) { + err = reset(memac->regs); +@@ -918,10 +927,7 @@ static int memac_init(struct fman_mac *m + add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0); + } + +- fixed_link = memac_drv_param->fixed_link; +- +- init(memac->regs, memac->memac_drv_param, memac->phy_if, +- memac->max_speed, slow_10g_if, memac->exceptions); ++ init(memac->regs, memac->memac_drv_param, memac->exceptions); + + /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround + * Exists only in FMan 6.0 and 6.3. +@@ -937,11 +943,6 @@ static int memac_init(struct fman_mac *m + iowrite32be(reg32, &memac->regs->command_config); + } + +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) +- setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); +- else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) +- setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); +- + /* Max Frame Length */ + err = fman_set_mac_max_frame(memac->fm, memac->mac_id, + memac_drv_param->max_frame_length); +@@ -970,9 +971,6 @@ static int memac_init(struct fman_mac *m + fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, + FMAN_INTR_TYPE_NORMAL, memac_exception, memac); + +- kfree(memac_drv_param); +- memac->memac_drv_param = NULL; +- + return 0; + } + +@@ -995,7 +993,6 @@ static int memac_free(struct fman_mac *m + pcs_put(memac->sgmii_pcs); + pcs_put(memac->qsgmii_pcs); + pcs_put(memac->xfi_pcs); +- + kfree(memac->memac_drv_param); + kfree(memac); + +@@ -1028,8 +1025,6 @@ static struct fman_mac *memac_config(str + memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); + + memac->regs = mac_dev->vaddr; +- memac->max_speed = params->max_speed; +- memac->phy_if = mac_dev->phy_if; + memac->mac_id = params->mac_id; + memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | + MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI); +@@ -1037,7 +1032,6 @@ static struct fman_mac *memac_config(str + memac->event_cb = params->event_cb; + memac->dev_id = mac_dev; + memac->fm = params->fm; +- memac->basex_if = params->basex_if; + + /* Save FMan revision */ + fman_get_revision(memac->fm, &memac->fm_rev_info); +@@ -1064,37 +1058,44 @@ static struct phylink_pcs *memac_pcs_cre + return pcs; + } + ++static bool memac_supports(struct mac_device *mac_dev, phy_interface_t iface) ++{ ++ /* If there's no serdes device, assume that it's been configured for ++ * whatever the default interface mode is. ++ */ ++ if (!mac_dev->fman_mac->serdes) ++ return mac_dev->phy_if == iface; ++ /* Otherwise, ask the serdes */ ++ return !phy_validate(mac_dev->fman_mac->serdes, PHY_MODE_ETHERNET, ++ iface, NULL); ++} ++ + int memac_initialization(struct mac_device *mac_dev, + struct device_node *mac_node, + struct fman_mac_params *params) + { + int err; ++ struct device_node *fixed; + struct phylink_pcs *pcs; +- struct fixed_phy_status *fixed_link; + struct fman_mac *memac; ++ unsigned long capabilities; ++ unsigned long *supported; + ++ mac_dev->phylink_ops = &memac_mac_ops; + mac_dev->set_promisc = memac_set_promiscuous; + mac_dev->change_addr = memac_modify_mac_address; + mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = memac_del_hash_mac_address; +- mac_dev->set_tx_pause = memac_set_tx_pause_frames; +- mac_dev->set_rx_pause = memac_accept_rx_pause_frames; + mac_dev->set_exception = memac_set_exception; + mac_dev->set_allmulti = memac_set_allmulti; + mac_dev->set_tstamp = memac_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = adjust_link_memac; + mac_dev->enable = memac_enable; + mac_dev->disable = memac_disable; + +- if (params->max_speed == SPEED_10000) +- mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII; +- + mac_dev->fman_mac = memac_config(mac_dev, params); +- if (!mac_dev->fman_mac) { +- err = -EINVAL; +- goto _return; +- } ++ if (!mac_dev->fman_mac) ++ return -EINVAL; + + memac = mac_dev->fman_mac; + memac->memac_drv_param->max_frame_length = fman_get_max_frm(); +@@ -1136,9 +1137,9 @@ int memac_initialization(struct mac_devi + else + pcs = memac_pcs_create(mac_node, err); + +- if (!pcs) { +- dev_err(mac_dev->dev, "missing pcs\n"); +- err = -ENOENT; ++ if (IS_ERR(pcs)) { ++ err = PTR_ERR(pcs); ++ dev_err_probe(mac_dev->dev, err, "missing pcs\n"); + goto _return_fm_mac_free; + } + +@@ -1159,84 +1160,100 @@ int memac_initialization(struct mac_devi + } else if (IS_ERR(memac->serdes)) { + dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); + goto _return_fm_mac_free; +- } else { +- err = phy_init(memac->serdes); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not initialize serdes\n"); +- goto _return_fm_mac_free; +- } +- +- err = phy_power_on(memac->serdes); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not power on serdes\n"); +- goto _return_phy_exit; +- } +- +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || +- memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || +- memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || +- memac->phy_if == PHY_INTERFACE_MODE_QSGMII || +- memac->phy_if == PHY_INTERFACE_MODE_XGMII) { +- err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, +- memac->phy_if); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not set serdes mode to %s\n", +- phy_modes(memac->phy_if)); +- goto _return_phy_power_off; +- } +- } + } + +- if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { +- struct phy_device *phy; +- +- err = of_phy_register_fixed_link(mac_node); +- if (err) +- goto _return_phy_power_off; +- +- fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); +- if (!fixed_link) { +- err = -ENOMEM; +- goto _return_phy_power_off; +- } ++ /* The internal connection to the serdes is XGMII, but this isn't ++ * really correct for the phy mode (which is the external connection). ++ * However, this is how all older device trees say that they want ++ * 10GBASE-R (aka XFI), so just convert it for them. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ mac_dev->phy_if = PHY_INTERFACE_MODE_10GBASER; + +- mac_dev->phy_node = of_node_get(mac_node); +- phy = of_phy_find_device(mac_dev->phy_node); +- if (!phy) { +- err = -EINVAL; +- of_node_put(mac_dev->phy_node); +- goto _return_fixed_link_free; +- } ++ /* TODO: The following interface modes are supported by (some) hardware ++ * but not by this driver: ++ * - 1000BASE-KX ++ * - 10GBASE-KR ++ * - XAUI/HiGig ++ */ ++ supported = mac_dev->phylink_config.supported_interfaces; + +- fixed_link->link = phy->link; +- fixed_link->speed = phy->speed; +- fixed_link->duplex = phy->duplex; +- fixed_link->pause = phy->pause; +- fixed_link->asym_pause = phy->asym_pause; ++ /* Note that half duplex is only supported on 10/100M interfaces. */ + +- put_device(&phy->mdio.dev); +- memac->memac_drv_param->fixed_link = fixed_link; ++ if (memac->sgmii_pcs && ++ (memac_supports(mac_dev, PHY_INTERFACE_MODE_SGMII) || ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_1000BASEX))) { ++ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); ++ } ++ ++ if (memac->sgmii_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_2500BASEX)) ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); ++ ++ if (memac->qsgmii_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_QSGMII)) ++ __set_bit(PHY_INTERFACE_MODE_QSGMII, supported); ++ else if (mac_dev->phy_if == PHY_INTERFACE_MODE_QSGMII) ++ dev_warn(mac_dev->dev, "no QSGMII pcs specified\n"); ++ ++ if (memac->xfi_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_10GBASER)) { ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ } else { ++ /* From what I can tell, no 10g macs support RGMII. */ ++ phy_interface_set_rgmii(supported); ++ __set_bit(PHY_INTERFACE_MODE_MII, supported); + } + ++ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100; ++ capabilities |= MAC_1000FD | MAC_2500FD | MAC_10000FD; ++ ++ /* These SoCs don't support half duplex at all; there's no different ++ * FMan version or compatible, so we just have to check the machine ++ * compatible instead ++ */ ++ if (of_machine_is_compatible("fsl,ls1043a") || ++ of_machine_is_compatible("fsl,ls1046a") || ++ of_machine_is_compatible("fsl,B4QDS")) ++ capabilities &= ~(MAC_10HD | MAC_100HD); ++ ++ mac_dev->phylink_config.mac_capabilities = capabilities; ++ ++ /* The T2080 and T4240 don't support half duplex RGMII. There is no ++ * other way to identify these SoCs, so just use the machine ++ * compatible. ++ */ ++ if (of_machine_is_compatible("fsl,T2080QDS") || ++ of_machine_is_compatible("fsl,T2080RDB") || ++ of_machine_is_compatible("fsl,T2081QDS") || ++ of_machine_is_compatible("fsl,T4240QDS") || ++ of_machine_is_compatible("fsl,T4240RDB")) ++ memac->rgmii_no_half_duplex = true; ++ ++ /* Most boards should use MLO_AN_INBAND, but existing boards don't have ++ * a managed property. Default to MLO_AN_INBAND if nothing else is ++ * specified. We need to be careful and not enable this if we have a ++ * fixed link or if we are using MII or RGMII, since those ++ * configurations modes don't use in-band autonegotiation. ++ */ ++ fixed = of_get_child_by_name(mac_node, "fixed-link"); ++ if (!fixed && !of_property_read_bool(mac_node, "fixed-link") && ++ !of_property_read_bool(mac_node, "managed") && ++ mac_dev->phy_if != PHY_INTERFACE_MODE_MII && ++ !phy_interface_mode_is_rgmii(mac_dev->phy_if)) ++ mac_dev->phylink_config.ovr_an_inband = true; ++ of_node_put(fixed); ++ + err = memac_init(mac_dev->fman_mac); + if (err < 0) +- goto _return_fixed_link_free; ++ goto _return_fm_mac_free; + + dev_info(mac_dev->dev, "FMan MEMAC\n"); + +- goto _return; ++ return 0; + +-_return_phy_power_off: +- phy_power_off(memac->serdes); +-_return_phy_exit: +- phy_exit(memac->serdes); +-_return_fixed_link_free: +- kfree(fixed_link); + _return_fm_mac_free: + memac_free(mac_dev->fman_mac); +-_return: + return err; + } +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + /* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ + #define TGEC_TX_IPG_LENGTH_MASK 0x000003ff +@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem + + static int check_init_parameters(struct fman_mac *tgec) + { +- if (tgec->max_speed < SPEED_10000) { +- pr_err("10G MAC driver only support 10G speed\n"); +- return -EINVAL; +- } + if (!tgec->exception_cb) { + pr_err("uninitialized exception_cb\n"); + return -EINVAL; +@@ -384,40 +381,13 @@ static void free_init_resources(struct f + tgec->unicast_addr_hash = NULL; + } + +-static bool is_init_done(struct tgec_cfg *cfg) +-{ +- /* Checks if tGEC driver parameters were initialized */ +- if (!cfg) +- return true; +- +- return false; +-} +- + static int tgec_enable(struct fman_mac *tgec) + { +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); +- + return 0; + } + + static void tgec_disable(struct fman_mac *tgec) + { +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(tgec->cfg)); +- +- tmp = ioread32be(®s->command_config); +- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); +- iowrite32be(tmp, ®s->command_config); + } + + static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val) +@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct f + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (new_val) + tmp |= CMD_CFG_PROMIS_EN; +@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(stru + { + struct tgec_regs __iomem *regs = tgec->regs; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + iowrite32be((u32)pause_time, ®s->pause_quant); + + return 0; +@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(s + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (!en) + tmp |= CMD_CFG_PAUSE_IGNORE; +@@ -470,12 +431,53 @@ static int tgec_accept_rx_pause_frames(s + return 0; + } + ++static void tgec_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void tgec_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 mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *tgec = mac_dev->fman_mac; ++ struct tgec_regs __iomem *regs = tgec->regs; ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ u32 tmp; ++ ++ tgec_set_tx_pause_frames(tgec, 0, pause_time, 0); ++ tgec_accept_rx_pause_frames(tgec, rx_pause); ++ mac_dev->update_speed(mac_dev, speed); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static void tgec_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac; ++ struct tgec_regs __iomem *regs = tgec->regs; ++ u32 tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static const struct phylink_mac_ops tgec_mac_ops = { ++ .validate = phylink_generic_validate, ++ .mac_config = tgec_mac_config, ++ .mac_link_up = tgec_link_up, ++ .mac_link_down = tgec_link_down, ++}; ++ + static int tgec_modify_mac_address(struct fman_mac *tgec, + const enet_addr_t *p_enet_addr) + { +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); + set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr)); + +@@ -490,9 +492,6 @@ static int tgec_add_hash_mac_address(str + u32 crc = 0xFFFFFFFF, hash; + u64 addr; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + if (!(addr & GROUP_ADDRESS)) { +@@ -525,9 +524,6 @@ static int tgec_set_allmulti(struct fman + u32 entry; + struct tgec_regs __iomem *regs = tgec->regs; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + if (enable) { + for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++) + iowrite32be(entry | TGEC_HASH_MCAST_EN, +@@ -548,9 +544,6 @@ static int tgec_set_tstamp(struct fman_m + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + + if (enable) +@@ -572,9 +565,6 @@ static int tgec_del_hash_mac_address(str + u32 crc = 0xFFFFFFFF, hash; + u64 addr; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + addr = ((*(u64 *)eth_addr) >> 16); + + /* CRC calculation */ +@@ -601,22 +591,12 @@ static int tgec_del_hash_mac_address(str + return 0; + } + +-static void tgec_adjust_link(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- +- mac_dev->update_speed(mac_dev, phy_dev->speed); +-} +- + static int tgec_set_exception(struct fman_mac *tgec, + enum fman_mac_exceptions exception, bool enable) + { + struct tgec_regs __iomem *regs = tgec->regs; + u32 bit_mask = 0; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + bit_mask = get_exception_flag(exception); + if (bit_mask) { + if (enable) +@@ -641,9 +621,6 @@ static int tgec_init(struct fman_mac *tg + enet_addr_t eth_addr; + int err; + +- if (is_init_done(tgec->cfg)) +- return -EINVAL; +- + if (DEFAULT_RESET_ON_INIT && + (fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) { + pr_err("Can't reset MAC!\n"); +@@ -753,7 +730,6 @@ static struct fman_mac *tgec_config(stru + + tgec->regs = mac_dev->vaddr; + tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); +- tgec->max_speed = params->max_speed; + tgec->mac_id = params->mac_id; + tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT | + TGEC_IMASK_REM_FAULT | +@@ -788,17 +764,15 @@ int tgec_initialization(struct mac_devic + int err; + struct fman_mac *tgec; + ++ mac_dev->phylink_ops = &tgec_mac_ops; + mac_dev->set_promisc = tgec_set_promiscuous; + mac_dev->change_addr = tgec_modify_mac_address; + mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address; +- mac_dev->set_tx_pause = tgec_set_tx_pause_frames; +- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames; + mac_dev->set_exception = tgec_set_exception; + mac_dev->set_allmulti = tgec_set_allmulti; + mac_dev->set_tstamp = tgec_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = tgec_adjust_link; + mac_dev->enable = tgec_enable; + mac_dev->disable = tgec_disable; + +@@ -808,6 +782,19 @@ int tgec_initialization(struct mac_devic + goto _return; + } + ++ /* The internal connection to the serdes is XGMII, but this isn't ++ * really correct for the phy mode (which is the external connection). ++ * However, this is how all older device trees say that they want ++ * XAUI, so just convert it for them. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI; ++ ++ __set_bit(PHY_INTERFACE_MODE_XAUI, ++ mac_dev->phylink_config.supported_interfaces); ++ mac_dev->phylink_config.mac_capabilities = ++ MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD; ++ + tgec = mac_dev->fman_mac; + tgec->cfg->max_frame_length = fman_get_max_frm(); + err = tgec_init(tgec); +--- a/drivers/net/ethernet/freescale/fman/mac.c ++++ b/drivers/net/ethernet/freescale/fman/mac.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -93,130 +94,8 @@ int fman_set_multi(struct net_device *ne + return 0; + } + +-/** +- * fman_set_mac_active_pause +- * @mac_dev: A pointer to the MAC device +- * @rx: Pause frame setting for RX +- * @tx: Pause frame setting for TX +- * +- * Set the MAC RX/TX PAUSE frames settings +- * +- * Avoid redundant calls to FMD, if the MAC driver already contains the desired +- * active PAUSE settings. Otherwise, the new active settings should be reflected +- * in FMan. +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) +-{ +- struct fman_mac *fman_mac = mac_dev->fman_mac; +- int err = 0; +- +- if (rx != mac_dev->rx_pause_active) { +- err = mac_dev->set_rx_pause(fman_mac, rx); +- if (likely(err == 0)) +- mac_dev->rx_pause_active = rx; +- } +- +- if (tx != mac_dev->tx_pause_active) { +- u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE : +- FSL_FM_PAUSE_TIME_DISABLE); +- +- err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0); +- +- if (likely(err == 0)) +- mac_dev->tx_pause_active = tx; +- } +- +- return err; +-} +-EXPORT_SYMBOL(fman_set_mac_active_pause); +- +-/** +- * fman_get_pause_cfg +- * @mac_dev: A pointer to the MAC device +- * @rx_pause: Return value for RX setting +- * @tx_pause: Return value for TX setting +- * +- * Determine the MAC RX/TX PAUSE frames settings based on PHY +- * autonegotiation or values set by eththool. +- * +- * Return: Pointer to FMan device. +- */ +-void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, +- bool *tx_pause) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- u16 lcl_adv, rmt_adv; +- u8 flowctrl; +- +- *rx_pause = *tx_pause = false; +- +- if (!phy_dev->duplex) +- return; +- +- /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings +- * are those set by ethtool. +- */ +- if (!mac_dev->autoneg_pause) { +- *rx_pause = mac_dev->rx_pause_req; +- *tx_pause = mac_dev->tx_pause_req; +- return; +- } +- +- /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE +- * settings depend on the result of the link negotiation. +- */ +- +- /* get local capabilities */ +- lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising); +- +- /* get link partner capabilities */ +- rmt_adv = 0; +- if (phy_dev->pause) +- rmt_adv |= LPA_PAUSE_CAP; +- if (phy_dev->asym_pause) +- rmt_adv |= LPA_PAUSE_ASYM; +- +- /* Calculate TX/RX settings based on local and peer advertised +- * symmetric/asymmetric PAUSE capabilities. +- */ +- flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); +- if (flowctrl & FLOW_CTRL_RX) +- *rx_pause = true; +- if (flowctrl & FLOW_CTRL_TX) +- *tx_pause = true; +-} +-EXPORT_SYMBOL(fman_get_pause_cfg); +- +-#define DTSEC_SUPPORTED \ +- (SUPPORTED_10baseT_Half \ +- | SUPPORTED_10baseT_Full \ +- | SUPPORTED_100baseT_Half \ +- | SUPPORTED_100baseT_Full \ +- | SUPPORTED_Autoneg \ +- | SUPPORTED_Pause \ +- | SUPPORTED_Asym_Pause \ +- | SUPPORTED_FIBRE \ +- | SUPPORTED_MII) +- + static DEFINE_MUTEX(eth_lock); + +-static const u16 phy2speed[] = { +- [PHY_INTERFACE_MODE_MII] = SPEED_100, +- [PHY_INTERFACE_MODE_GMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_TBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_RMII] = SPEED_100, +- [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 +-}; +- + static struct platform_device *dpaa_eth_add_device(int fman_id, + struct mac_device *mac_dev) + { +@@ -263,8 +142,8 @@ no_mem: + } + + static const struct of_device_id mac_match[] = { +- { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, +- { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, ++ { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, ++ { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, + { .compatible = "fsl,fman-memac", .data = memac_initialization }, + {} + }; +@@ -295,6 +174,7 @@ static int mac_probe(struct platform_dev + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ platform_set_drvdata(_of_dev, mac_dev); + + /* Save private information */ + mac_dev->priv = priv; +@@ -424,57 +304,21 @@ static int mac_probe(struct platform_dev + } + mac_dev->phy_if = phy_if; + +- priv->speed = phy2speed[mac_dev->phy_if]; +- params.max_speed = priv->speed; +- mac_dev->if_support = DTSEC_SUPPORTED; +- /* We don't support half-duplex in SGMII mode */ +- if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) +- mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | +- SUPPORTED_100baseT_Half); +- +- /* Gigabit support (no half-duplex) */ +- if (params.max_speed == 1000) +- mac_dev->if_support |= SUPPORTED_1000baseT_Full; +- +- /* The 10G interface only supports one mode */ +- if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) +- mac_dev->if_support = SUPPORTED_10000baseT_Full; +- +- /* Get the rest of the PHY information */ +- mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); +- +- params.basex_if = false; + params.mac_id = priv->cell_index; + params.fm = (void *)priv->fman; + params.exception_cb = mac_exception; + params.event_cb = mac_exception; + + err = init(mac_dev, mac_node, ¶ms); +- if (err < 0) { +- dev_err(dev, "mac_dev->init() = %d\n", err); +- of_node_put(mac_dev->phy_node); +- return err; +- } +- +- /* pause frame autonegotiation enabled */ +- mac_dev->autoneg_pause = true; +- +- /* By intializing the values to false, force FMD to enable PAUSE frames +- * on RX and TX +- */ +- mac_dev->rx_pause_req = true; +- mac_dev->tx_pause_req = true; +- mac_dev->rx_pause_active = false; +- mac_dev->tx_pause_active = false; +- err = fman_set_mac_active_pause(mac_dev, true, true); + if (err < 0) +- dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); ++ return err; + + if (!is_zero_ether_addr(mac_dev->addr)) + dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); + + priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); + if (IS_ERR(priv->eth_dev)) { ++ err = PTR_ERR(priv->eth_dev); + dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", + priv->cell_index); + priv->eth_dev = NULL; +--- a/drivers/net/ethernet/freescale/fman/mac.h ++++ b/drivers/net/ethernet/freescale/fman/mac.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #include "fman_port.h" +@@ -24,32 +25,22 @@ struct mac_device { + struct resource *res; + u8 addr[ETH_ALEN]; + struct fman_port *port[2]; +- u32 if_support; +- struct phy_device *phy_dev; ++ struct phylink *phylink; ++ struct phylink_config phylink_config; + phy_interface_t phy_if; +- struct device_node *phy_node; +- struct net_device *net_dev; + +- bool autoneg_pause; +- bool rx_pause_req; +- bool tx_pause_req; +- bool rx_pause_active; +- bool tx_pause_active; + bool promisc; + bool allmulti; + ++ const struct phylink_mac_ops *phylink_ops; + int (*enable)(struct fman_mac *mac_dev); + void (*disable)(struct fman_mac *mac_dev); +- void (*adjust_link)(struct mac_device *mac_dev); + int (*set_promisc)(struct fman_mac *mac_dev, bool enable); + int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr); + int (*set_allmulti)(struct fman_mac *mac_dev, bool enable); + int (*set_tstamp)(struct fman_mac *mac_dev, bool enable); + int (*set_multi)(struct net_device *net_dev, + struct mac_device *mac_dev); +- int (*set_rx_pause)(struct fman_mac *mac_dev, bool en); +- int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority, +- u16 pause_time, u16 thresh_time); + int (*set_exception)(struct fman_mac *mac_dev, + enum fman_mac_exceptions exception, bool enable); + int (*add_hash_mac_addr)(struct fman_mac *mac_dev, +@@ -63,6 +54,12 @@ struct mac_device { + struct mac_priv_s *priv; + }; + ++static inline struct mac_device ++*fman_config_to_mac(struct phylink_config *config) ++{ ++ return container_of(config, struct mac_device, phylink_config); ++} ++ + struct dpaa_eth_data { + struct mac_device *mac_dev; + int mac_hw_id; diff --git a/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch b/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch new file mode 100644 index 0000000000..06c348b1cd --- /dev/null +++ b/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch @@ -0,0 +1,93 @@ +From bf4de031052fe7c5309e8956c342d4e5ce79038e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 17 Oct 2022 16:22:35 -0400 +Subject: [PATCH 04/21] net: phylink: provide phylink_validate_mask_caps() + helper + +Provide a helper that restricts the link modes according to the +phylink capabilities. + +Signed-off-by: Russell King (Oracle) +[rebased on net-next/master and added documentation] +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 41 +++++++++++++++++++++++++++------------ + include/linux/phylink.h | 3 +++ + 2 files changed, 32 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -564,31 +564,48 @@ unsigned long phylink_get_capabilities(p + EXPORT_SYMBOL_GPL(phylink_get_capabilities); + + /** +- * phylink_generic_validate() - generic validate() callback implementation +- * @config: a pointer to a &struct phylink_config. ++ * phylink_validate_mask_caps() - Restrict link modes based on caps + * @supported: ethtool bitmask for supported link modes. +- * @state: a pointer to a &struct phylink_link_state. ++ * @state: an (optional) pointer to a &struct phylink_link_state. ++ * @mac_capabilities: bitmask of MAC capabilities + * +- * Generic implementation of the validate() callback that MAC drivers can +- * use when they pass the range of supported interfaces and MAC capabilities. +- * This makes use of phylink_get_linkmodes(). ++ * Calculate the supported link modes based on @mac_capabilities, and restrict ++ * @supported and @state based on that. Use this function if your capabiliies ++ * aren't constant, such as if they vary depending on the interface. + */ +-void phylink_generic_validate(struct phylink_config *config, +- unsigned long *supported, +- struct phylink_link_state *state) ++void phylink_validate_mask_caps(unsigned long *supported, ++ struct phylink_link_state *state, ++ unsigned long mac_capabilities) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + unsigned long caps; + + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); +- caps = phylink_get_capabilities(state->interface, +- config->mac_capabilities, ++ caps = phylink_get_capabilities(state->interface, mac_capabilities, + state->rate_matching); + phylink_caps_to_linkmodes(mask, caps); + + linkmode_and(supported, supported, mask); +- linkmode_and(state->advertising, state->advertising, mask); ++ if (state) ++ linkmode_and(state->advertising, state->advertising, mask); ++} ++EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); ++ ++/** ++ * phylink_generic_validate() - generic validate() callback implementation ++ * @config: a pointer to a &struct phylink_config. ++ * @supported: ethtool bitmask for supported link modes. ++ * @state: a pointer to a &struct phylink_link_state. ++ * ++ * Generic implementation of the validate() callback that MAC drivers can ++ * use when they pass the range of supported interfaces and MAC capabilities. ++ */ ++void phylink_generic_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ phylink_validate_mask_caps(supported, state, config->mac_capabilities); + } + EXPORT_SYMBOL_GPL(phylink_generic_validate); + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -558,6 +558,9 @@ void phylink_caps_to_linkmodes(unsigned + unsigned long phylink_get_capabilities(phy_interface_t interface, + unsigned long mac_capabilities, + int rate_matching); ++void phylink_validate_mask_caps(unsigned long *supported, ++ struct phylink_link_state *state, ++ unsigned long caps); + void phylink_generic_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch b/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch new file mode 100644 index 0000000000..e3a1dda688 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch @@ -0,0 +1,39 @@ +From 2bf7e4a68c42eed909f3c29582e1fb85cb157e35 Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Tue, 25 Oct 2022 11:51:26 -0700 +Subject: [PATCH 05/21] phylink: require valid state argument to + phylink_validate_mask_caps() + +state is deferenced earlier in the function, the NULL check +is pointless. Since we don't have any crash reports presumably +it's safe to assume state is not NULL. + +Fixes: f392a1846489 ("net: phylink: provide phylink_validate_mask_caps() helper") +Reviewed-by: Sean Anderson +Link: https://lore.kernel.org/r/20221025185126.1720553-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -566,7 +566,7 @@ EXPORT_SYMBOL_GPL(phylink_get_capabiliti + /** + * phylink_validate_mask_caps() - Restrict link modes based on caps + * @supported: ethtool bitmask for supported link modes. +- * @state: an (optional) pointer to a &struct phylink_link_state. ++ * @state: pointer to a &struct phylink_link_state. + * @mac_capabilities: bitmask of MAC capabilities + * + * Calculate the supported link modes based on @mac_capabilities, and restrict +@@ -587,8 +587,7 @@ void phylink_validate_mask_caps(unsigned + phylink_caps_to_linkmodes(mask, caps); + + linkmode_and(supported, supported, mask); +- if (state) +- linkmode_and(state->advertising, state->advertising, mask); ++ linkmode_and(state->advertising, state->advertising, mask); + } + EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); + diff --git a/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch b/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch new file mode 100644 index 0000000000..c217ed87b5 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch @@ -0,0 +1,48 @@ +From f8fc363bf0c023e4736a0328174b4a24b44ab23a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:10:37 +0100 +Subject: [PATCH 06/21] net: phylink: add phylink_get_link_timer_ns() helper + +Add a helper to convert the PHY interface mode to the required link +timer setting as stated by the appropriate standard. Inappropriate +interface modes return an error. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + include/linux/phylink.h | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -617,6 +617,30 @@ int phylink_speed_up(struct phylink *pl) + + void phylink_set_port_modes(unsigned long *bits); + ++/** ++ * phylink_get_link_timer_ns - return the PCS link timer value ++ * @interface: link &typedef phy_interface_t mode ++ * ++ * Return the PCS link timer setting in nanoseconds for the PHY @interface ++ * mode, or -EINVAL if not appropriate. ++ */ ++static inline int phylink_get_link_timer_ns(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ return 1600000; ++ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return 10000000; ++ ++ default: ++ return -EINVAL; ++ } ++} ++ + void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, + u16 bmsr, u16 lpa); + void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, diff --git a/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch b/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch new file mode 100644 index 0000000000..28154af920 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch @@ -0,0 +1,250 @@ +From b45b773a96b0e9e8d51e5d005485f4e376d6ce9a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 4 Nov 2022 17:13:01 +0000 +Subject: [PATCH 07/21] net: remove explicit phylink_generic_validate() + references + +Virtually all conventional network drivers are now converted to use +phylink_generic_validate() - only DSA drivers and fman_memac remain, +so lets remove the necessity for network drivers to explicitly set +this member, and default to phylink_generic_validate() when unset. +This is possible as .validate must currently be set. + +Any remaining instances that have not been addressed by this patch can +be fixed up later. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/E1or0FZ-001tRa-DI@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/altera/altera_tse_main.c | 1 - + drivers/net/ethernet/atheros/ag71xx.c | 1 - + drivers/net/ethernet/cadence/macb_main.c | 1 - + drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 1 - + drivers/net/ethernet/freescale/enetc/enetc_pf.c | 1 - + drivers/net/ethernet/freescale/fman/fman_dtsec.c | 1 - + drivers/net/ethernet/freescale/fman/fman_tgec.c | 1 - + drivers/net/ethernet/marvell/mvneta.c | 1 - + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 - + drivers/net/ethernet/marvell/prestera/prestera_main.c | 1 - + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - + drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c | 1 - + drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c | 1 - + drivers/net/ethernet/mscc/ocelot_net.c | 1 - + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 - + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 - + drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 - + drivers/net/phy/phylink.c | 5 ++++- + drivers/net/usb/asix_devices.c | 1 - + include/linux/phylink.h | 5 +++++ + 20 files changed, 9 insertions(+), 19 deletions(-) + +--- a/drivers/net/ethernet/altera/altera_tse_main.c ++++ b/drivers/net/ethernet/altera/altera_tse_main.c +@@ -1096,7 +1096,6 @@ static struct phylink_pcs *alt_tse_selec + } + + static const struct phylink_mac_ops alt_tse_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_an_restart = alt_tse_mac_an_restart, + .mac_config = alt_tse_mac_config, + .mac_link_down = alt_tse_mac_link_down, +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1086,7 +1086,6 @@ static void ag71xx_mac_link_up(struct ph + } + + static const struct phylink_mac_ops ag71xx_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = ag71xx_mac_config, + .mac_link_down = ag71xx_mac_link_down, + .mac_link_up = ag71xx_mac_link_up, +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -752,7 +752,6 @@ static struct phylink_pcs *macb_mac_sele + } + + static const struct phylink_mac_ops macb_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = macb_mac_select_pcs, + .mac_config = macb_mac_config, + .mac_link_down = macb_mac_link_down, +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +@@ -235,7 +235,6 @@ static void dpaa2_mac_link_down(struct p + } + + static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = dpaa2_mac_select_pcs, + .mac_config = dpaa2_mac_config, + .mac_link_up = dpaa2_mac_link_up, +--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +@@ -1111,7 +1111,6 @@ static void enetc_pl_mac_link_down(struc + } + + static const struct phylink_mac_ops enetc_mac_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = enetc_pl_mac_select_pcs, + .mac_config = enetc_pl_mac_config, + .mac_link_up = enetc_pl_mac_link_up, +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -986,7 +986,6 @@ static void dtsec_link_down(struct phyli + } + + static const struct phylink_mac_ops dtsec_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = dtsec_select_pcs, + .mac_config = dtsec_mac_config, + .mac_link_up = dtsec_link_up, +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c +@@ -469,7 +469,6 @@ static void tgec_link_down(struct phylin + } + + static const struct phylink_mac_ops tgec_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = tgec_mac_config, + .mac_link_up = tgec_link_up, + .mac_link_down = tgec_link_down, +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4228,7 +4228,6 @@ static void mvneta_mac_link_up(struct ph + } + + static const struct phylink_mac_ops mvneta_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mvneta_mac_select_pcs, + .mac_prepare = mvneta_mac_prepare, + .mac_config = mvneta_mac_config, +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6633,7 +6633,6 @@ static void mvpp2_mac_link_down(struct p + } + + static const struct phylink_mac_ops mvpp2_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mvpp2_select_pcs, + .mac_prepare = mvpp2_mac_prepare, + .mac_config = mvpp2_mac_config, +--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c +@@ -360,7 +360,6 @@ static void prestera_pcs_an_restart(stru + } + + static const struct phylink_mac_ops prestera_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = prestera_mac_select_pcs, + .mac_config = prestera_mac_config, + .mac_link_down = prestera_mac_link_down, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -654,7 +654,6 @@ static void mtk_mac_link_up(struct phyli + } + + static const struct phylink_mac_ops mtk_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mtk_mac_select_pcs, + .mac_pcs_get_state = mtk_mac_pcs_get_state, + .mac_config = mtk_mac_config, +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c +@@ -125,7 +125,6 @@ static void lan966x_pcs_aneg_restart(str + } + + const struct phylink_mac_ops lan966x_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = lan966x_phylink_mac_select, + .mac_config = lan966x_phylink_mac_config, + .mac_prepare = lan966x_phylink_mac_prepare, +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c +@@ -138,7 +138,6 @@ const struct phylink_pcs_ops sparx5_phyl + }; + + const struct phylink_mac_ops sparx5_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = sparx5_phylink_mac_select_pcs, + .mac_config = sparx5_phylink_mac_config, + .mac_link_down = sparx5_phylink_mac_link_down, +--- a/drivers/net/ethernet/mscc/ocelot_net.c ++++ b/drivers/net/ethernet/mscc/ocelot_net.c +@@ -1737,7 +1737,6 @@ static void vsc7514_phylink_mac_link_up( + } + + static const struct phylink_mac_ops ocelot_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_config = vsc7514_phylink_mac_config, + .mac_link_down = vsc7514_phylink_mac_link_down, + .mac_link_up = vsc7514_phylink_mac_link_up, +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1090,7 +1090,6 @@ static void stmmac_mac_link_up(struct ph + } + + static const struct phylink_mac_ops stmmac_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = stmmac_mac_select_pcs, + .mac_config = stmmac_mac_config, + .mac_link_down = stmmac_mac_link_down, +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -1493,7 +1493,6 @@ static void am65_cpsw_nuss_mac_link_up(s + } + + static const struct phylink_mac_ops am65_cpsw_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = am65_cpsw_nuss_mac_config, + .mac_link_down = am65_cpsw_nuss_mac_link_down, + .mac_link_up = am65_cpsw_nuss_mac_link_up, +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1736,7 +1736,6 @@ static void axienet_mac_link_up(struct p + } + + static const struct phylink_mac_ops axienet_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = axienet_mac_select_pcs, + .mac_config = axienet_mac_config, + .mac_link_down = axienet_mac_link_down, +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -651,7 +651,10 @@ static int phylink_validate_mac_and_pcs( + } + + /* Then validate the link parameters with the MAC */ +- pl->mac_ops->validate(pl->config, supported, state); ++ if (pl->mac_ops->validate) ++ pl->mac_ops->validate(pl->config, supported, state); ++ else ++ phylink_generic_validate(pl->config, supported, state); + + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -787,7 +787,6 @@ static void ax88772_mac_link_up(struct p + } + + static const struct phylink_mac_ops ax88772_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = ax88772_mac_config, + .mac_link_down = ax88772_mac_link_down, + .mac_link_up = ax88772_mac_link_up, +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -207,6 +207,11 @@ struct phylink_mac_ops { + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. ++ * ++ * This member is optional; if not set, the generic validator will be ++ * used making use of @config->mac_capabilities and ++ * @config->supported_interfaces to determine which link modes are ++ * supported. + */ + void validate(struct phylink_config *config, unsigned long *supported, + struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch b/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch new file mode 100644 index 0000000000..37d82b2cd7 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch @@ -0,0 +1,48 @@ +From a90ac762d345890b40d88a1385a34a2449c2d75e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Mar 2023 09:23:42 +0000 +Subject: [PATCH] net: sfp: make sfp_bus_find_fwnode() take a const fwnode + +sfp_bus_find_fwnode() does not write to the fwnode, so let's make it +const. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/sfp-bus.c | 2 +- + include/linux/sfp.h | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -603,7 +603,7 @@ static void sfp_upstream_clear(struct sf + * - %-ENOMEM if we failed to allocate the bus. + * - an error from the upstream's connect_phy() method. + */ +-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) ++struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) + { + struct fwnode_reference_args ref; + struct sfp_bus *bus; +--- a/include/linux/sfp.h ++++ b/include/linux/sfp.h +@@ -548,7 +548,7 @@ int sfp_get_module_eeprom_by_page(struct + void sfp_upstream_start(struct sfp_bus *bus); + void sfp_upstream_stop(struct sfp_bus *bus); + void sfp_bus_put(struct sfp_bus *bus); +-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode); ++struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); + int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, + const struct sfp_upstream_ops *ops); + void sfp_bus_del_upstream(struct sfp_bus *bus); +@@ -610,7 +610,8 @@ static inline void sfp_bus_put(struct sf + { + } + +-static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) ++static inline struct sfp_bus * ++sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) + { + return NULL; + } diff --git a/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch b/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch new file mode 100644 index 0000000000..290cb8d161 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch @@ -0,0 +1,31 @@ +From ecec0ebbc6381a5a375f1cf10c4858f24e91e2ef Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 15 Mar 2023 14:46:49 +0000 +Subject: [PATCH] net: pcs: lynx: don't print an_enabled in pcs_get_state() + +an_enabled will be going away, and in any case, pcs_get_state() should +not be updating this member. Remove the print. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Steen Hegelund +Signed-off-by: David S. Miller +--- + drivers/net/pcs/pcs-lynx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -115,11 +115,11 @@ static void lynx_pcs_get_state(struct ph + } + + dev_dbg(&lynx->mdio->dev, +- "mode=%s/%s/%s link=%u an_enabled=%u an_complete=%u\n", ++ "mode=%s/%s/%s link=%u an_complete=%u\n", + phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), +- state->link, state->an_enabled, state->an_complete); ++ state->link, state->an_complete); + } + + static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, diff --git a/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch new file mode 100644 index 0000000000..38ea265476 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch @@ -0,0 +1,32 @@ +From 99d0f3a1095f4c938b1665025c29411edafe8a01 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:44 +0000 +Subject: [PATCH] net: dpaa2-mac: use Autoneg bit rather than an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. Thus, we will be removing state->an_enabled. + +Use the Autoneg bit in the advertising bitmap to indicate whether +autonegotiation should be used, rather than using the an_enabled +member which will be going away. This means we use the same condition +as phylink_mii_c22_pcs_config(). + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +@@ -158,7 +158,8 @@ static void dpaa2_mac_config(struct phyl + struct dpmac_link_state *dpmac_state = &mac->state; + int err; + +- if (state->an_enabled) ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; + else + dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; diff --git a/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch b/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch new file mode 100644 index 0000000000..cb9c411cfb --- /dev/null +++ b/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch @@ -0,0 +1,64 @@ +From 471c40bde606ec0b1ce8c616f7998739c7a783a6 Mon Sep 17 00:00:00 2001 +From: Ivan Bornyakov +Date: Fri, 10 Feb 2023 18:46:27 +0300 +Subject: [PATCH 10/21] net: phylink: support validated pause and autoneg in + fixed-link + +In fixed-link setup phylink_parse_fixedlink() unconditionally sets +Pause, Asym_Pause and Autoneg bits to "supported" bitmap, while MAC may +not support these. + +This leads to ethtool reporting: + + > Supported pause frame use: Symmetric Receive-only + > Supports auto-negotiation: Yes + +regardless of what is actually supported. + +Instead of unconditionally set Pause, Asym_Pause and Autoneg it is +sensible to set them according to validated "supported" bitmap, i.e. the +result of phylink_validate(). + +Signed-off-by: Ivan Bornyakov +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -709,6 +709,7 @@ static int phylink_parse_fixedlink(struc + struct fwnode_handle *fwnode) + { + struct fwnode_handle *fixed_node; ++ bool pause, asym_pause, autoneg; + const struct phy_setting *s; + struct gpio_desc *desc; + u32 speed; +@@ -781,13 +782,23 @@ static int phylink_parse_fixedlink(struc + linkmode_copy(pl->link_config.advertising, pl->supported); + phylink_validate(pl, pl->supported, &pl->link_config); + ++ pause = phylink_test(pl->supported, Pause); ++ asym_pause = phylink_test(pl->supported, Asym_Pause); ++ autoneg = phylink_test(pl->supported, Autoneg); + s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex, + pl->supported, true); + linkmode_zero(pl->supported); + phylink_set(pl->supported, MII); +- phylink_set(pl->supported, Pause); +- phylink_set(pl->supported, Asym_Pause); +- phylink_set(pl->supported, Autoneg); ++ ++ if (pause) ++ phylink_set(pl->supported, Pause); ++ ++ if (asym_pause) ++ phylink_set(pl->supported, Asym_Pause); ++ ++ if (autoneg) ++ phylink_set(pl->supported, Autoneg); ++ + if (s) { + __set_bit(s->bit, pl->supported); + __set_bit(s->bit, pl->link_config.lp_advertising); diff --git a/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch b/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch new file mode 100644 index 0000000000..03b4f9d0c4 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch @@ -0,0 +1,177 @@ +From 7211ffd70941933a7825a56cf480f07ee81c321c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:54 +0000 +Subject: [PATCH 11/21] net: phylink: remove an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. state->an_enabled is now no longer used by any +drivers, so lets kill this duplication. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 37 +++++++++++++++++-------------------- + include/linux/phylink.h | 2 -- + 2 files changed, 17 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -841,7 +841,6 @@ static int phylink_parse_mode(struct phy + phylink_set(pl->supported, Autoneg); + phylink_set(pl->supported, Asym_Pause); + phylink_set(pl->supported, Pause); +- pl->link_config.an_enabled = true; + pl->cfg_link_an_mode = MLO_AN_INBAND; + + switch (pl->link_config.interface) { +@@ -944,9 +943,6 @@ static int phylink_parse_mode(struct phy + "failed to validate link configuration for in-band status\n"); + return -EINVAL; + } +- +- /* Check if MAC/PCS also supports Autoneg. */ +- pl->link_config.an_enabled = phylink_test(pl->supported, Autoneg); + } + + return 0; +@@ -956,7 +952,8 @@ static void phylink_apply_manual_flow(st + struct phylink_link_state *state) + { + /* If autoneg is disabled, pause AN is also disabled */ +- if (!state->an_enabled) ++ if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + state->pause &= ~MLO_PAUSE_AN; + + /* Manual configuration of pause modes */ +@@ -996,21 +993,22 @@ static void phylink_mac_config(struct ph + const struct phylink_link_state *state) + { + phylink_dbg(pl, +- "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", ++ "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u\n", + __func__, phylink_an_mode_str(pl->cur_link_an_mode), + phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), + phy_rate_matching_to_str(state->rate_matching), + __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, +- state->pause, state->link, state->an_enabled); ++ state->pause, state->link); + + pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); + } + + static void phylink_mac_pcs_an_restart(struct phylink *pl) + { +- if (pl->link_config.an_enabled && ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ pl->link_config.advertising) && + phy_interface_mode_is_8023z(pl->link_config.interface) && + phylink_autoneg_inband(pl->cur_link_an_mode)) { + if (pl->pcs) +@@ -1137,9 +1135,9 @@ static void phylink_mac_pcs_get_state(st + linkmode_copy(state->advertising, pl->link_config.advertising); + linkmode_zero(state->lp_advertising); + state->interface = pl->link_config.interface; +- state->an_enabled = pl->link_config.an_enabled; + state->rate_matching = pl->link_config.rate_matching; +- if (state->an_enabled) { ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) { + state->speed = SPEED_UNKNOWN; + state->duplex = DUPLEX_UNKNOWN; + state->pause = MLO_PAUSE_NONE; +@@ -1531,7 +1529,6 @@ struct phylink *phylink_create(struct ph + pl->link_config.pause = MLO_PAUSE_AN; + pl->link_config.speed = SPEED_UNKNOWN; + pl->link_config.duplex = DUPLEX_UNKNOWN; +- pl->link_config.an_enabled = true; + pl->mac_ops = mac_ops; + __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); + timer_setup(&pl->link_poll, phylink_fixed_poll, 0); +@@ -2155,8 +2152,9 @@ static void phylink_get_ksettings(const + kset->base.speed = state->speed; + kset->base.duplex = state->duplex; + } +- kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE : +- AUTONEG_DISABLE; ++ kset->base.autoneg = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising) ? ++ AUTONEG_ENABLE : AUTONEG_DISABLE; + } + + /** +@@ -2303,9 +2301,8 @@ int phylink_ethtool_ksettings_set(struct + /* We have ruled out the case with a PHY attached, and the + * fixed-link cases. All that is left are in-band links. + */ +- config.an_enabled = kset->base.autoneg == AUTONEG_ENABLE; + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising, +- config.an_enabled); ++ kset->base.autoneg == AUTONEG_ENABLE); + + /* If this link is with an SFP, ensure that changes to advertised modes + * also cause the associated interface to be selected such that the +@@ -2339,13 +2336,14 @@ int phylink_ethtool_ksettings_set(struct + } + + /* If autonegotiation is enabled, we must have an advertisement */ +- if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ config.advertising) && ++ phylink_is_empty_linkmode(config.advertising)) + return -EINVAL; + + mutex_lock(&pl->state_mutex); + pl->link_config.speed = config.speed; + pl->link_config.duplex = config.duplex; +- pl->link_config.an_enabled = config.an_enabled; + + if (pl->link_config.interface != config.interface) { + /* The interface changed, e.g. 1000base-X <-> 2500base-X */ +@@ -2951,7 +2949,6 @@ static int phylink_sfp_config_phy(struct + config.speed = SPEED_UNKNOWN; + config.duplex = DUPLEX_UNKNOWN; + config.pause = MLO_PAUSE_AN; +- config.an_enabled = pl->link_config.an_enabled; + + /* Ignore errors if we're expecting a PHY to attach later */ + ret = phylink_validate(pl, support, &config); +@@ -3020,7 +3017,6 @@ static int phylink_sfp_config_optical(st + config.speed = SPEED_UNKNOWN; + config.duplex = DUPLEX_UNKNOWN; + config.pause = MLO_PAUSE_AN; +- config.an_enabled = true; + + /* For all the interfaces that are supported, reduce the sfp_support + * mask to only those link modes that can be supported. +@@ -3354,7 +3350,8 @@ void phylink_mii_c22_pcs_decode_state(st + /* If there is no link or autonegotiation is disabled, the LP advertisement + * data is not meaningful, so don't go any further. + */ +- if (!state->link || !state->an_enabled) ++ if (!state->link || !linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + return; + + switch (state->interface) { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -93,7 +93,6 @@ static inline bool phylink_autoneg_inban + * the medium link mode (@speed and @duplex) and the speed/duplex of the phy + * interface mode (@interface) are different. + * @link: true if the link is up. +- * @an_enabled: true if autonegotiation is enabled/desired. + * @an_complete: true if autonegotiation has completed. + */ + struct phylink_link_state { +@@ -105,7 +104,6 @@ struct phylink_link_state { + int pause; + int rate_matching; + unsigned int link:1; +- unsigned int an_enabled:1; + unsigned int an_complete:1; + }; + diff --git a/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch b/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch new file mode 100644 index 0000000000..c06a367b8b --- /dev/null +++ b/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch @@ -0,0 +1,88 @@ +From a3555d1f5c208f0a63eafee77381f68d304a0512 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 12 May 2023 17:58:37 +0100 +Subject: [PATCH 12/21] net: phylink: constify fwnode arguments + +Both phylink_create() and phylink_fwnode_phy_connect() do not modify +the fwnode argument that they are passed, so lets constify these. + +Reviewed-by: Simon Horman +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 11 ++++++----- + include/linux/phylink.h | 9 +++++---- + 2 files changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -706,7 +706,7 @@ static int phylink_validate(struct phyli + } + + static int phylink_parse_fixedlink(struct phylink *pl, +- struct fwnode_handle *fwnode) ++ const struct fwnode_handle *fwnode) + { + struct fwnode_handle *fixed_node; + bool pause, asym_pause, autoneg; +@@ -817,7 +817,8 @@ static int phylink_parse_fixedlink(struc + return 0; + } + +-static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) ++static int phylink_parse_mode(struct phylink *pl, ++ const struct fwnode_handle *fwnode) + { + struct fwnode_handle *dn; + const char *managed; +@@ -1440,7 +1441,7 @@ static void phylink_fixed_poll(struct ti + static const struct sfp_upstream_ops sfp_phylink_ops; + + static int phylink_register_sfp(struct phylink *pl, +- struct fwnode_handle *fwnode) ++ const struct fwnode_handle *fwnode) + { + struct sfp_bus *bus; + int ret; +@@ -1479,7 +1480,7 @@ static int phylink_register_sfp(struct p + * must use IS_ERR() to check for errors from this function. + */ + struct phylink *phylink_create(struct phylink_config *config, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + phy_interface_t iface, + const struct phylink_mac_ops *mac_ops) + { +@@ -1809,7 +1810,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect + * Returns 0 on success or a negative errno. + */ + int phylink_fwnode_phy_connect(struct phylink *pl, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + u32 flags) + { + struct fwnode_handle *phy_fwnode; +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -568,16 +568,17 @@ void phylink_generic_validate(struct phy + unsigned long *supported, + struct phylink_link_state *state); + +-struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, +- phy_interface_t iface, +- const struct phylink_mac_ops *mac_ops); ++struct phylink *phylink_create(struct phylink_config *, ++ const struct fwnode_handle *, ++ phy_interface_t, ++ const struct phylink_mac_ops *); + void phylink_destroy(struct phylink *); + bool phylink_expects_phy(struct phylink *pl); + + int phylink_connect_phy(struct phylink *, struct phy_device *); + int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); + int phylink_fwnode_phy_connect(struct phylink *pl, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + u32 flags); + void phylink_disconnect_phy(struct phylink *); + diff --git a/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch b/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch new file mode 100644 index 0000000000..2649634dc7 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch @@ -0,0 +1,38 @@ +From 4a0faa02d419a6728abef0f1d8a32d8c35ef95e6 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Mar 2023 09:23:53 +0000 +Subject: [PATCH] net: phy: constify fwnode_get_phy_node() fwnode argument + +fwnode_get_phy_node() does not motify the fwnode structure, so make +the argument const, + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 2 +- + include/linux/phy.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3003,7 +3003,7 @@ EXPORT_SYMBOL_GPL(device_phy_find_device + * and "phy-device" are not supported in ACPI. DT supports all the three + * named references to the phy node. + */ +-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode) ++struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode) + { + struct fwnode_handle *phy_node; + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1473,7 +1473,7 @@ int fwnode_get_phy_id(struct fwnode_hand + struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode); + struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode); + struct phy_device *device_phy_find_device(struct device *dev); +-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode); ++struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode); + struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); + int phy_device_register(struct phy_device *phy); + void phy_device_free(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch new file mode 100644 index 0000000000..5eba18b026 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch @@ -0,0 +1,44 @@ +From cc73de0411f7d3cdd157564a78f7a39058420ff8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 13 May 2023 22:03:45 +0100 +Subject: [PATCH 13/21] net: phylink: fix ksettings_set() ethtool call + +While testing a Fiberstore SFP-10G-T module (which uses 10GBASE-R with +rate adaption) in a Clearfog platform (which can't do that) it was +found that the PHYs advertisement was not limited according to the +hosts capabilities when using ethtool to change it. + +Fix this by ensuring that we mask the advertisement with the computed +support mask as the very first thing we do. + +Fixes: cbc1bb1e4689 ("net: phylink: simplify phy case for ksettings_set method") +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -2226,6 +2226,10 @@ int phylink_ethtool_ksettings_set(struct + + ASSERT_RTNL(); + ++ /* Mask out unsupported advertisements */ ++ linkmode_and(config.advertising, kset->link_modes.advertising, ++ pl->supported); ++ + if (pl->phydev) { + /* We can rely on phylib for this update; we also do not need + * to update the pl->link_config settings: +@@ -2250,10 +2254,6 @@ int phylink_ethtool_ksettings_set(struct + + config = pl->link_config; + +- /* Mask out unsupported advertisements */ +- linkmode_and(config.advertising, kset->link_modes.advertising, +- pl->supported); +- + /* FIXME: should we reject autoneg if phy/mac does not support it? */ + switch (kset->base.autoneg) { + case AUTONEG_DISABLE: diff --git a/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch b/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch new file mode 100644 index 0000000000..79de6122b7 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch @@ -0,0 +1,149 @@ +From 0100d1c5789018ba77bf2f4fab3bd91ecece7b3b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 17 May 2023 11:38:12 +0100 +Subject: [PATCH 14/21] net: sfp: add support for setting signalling rate + +Add support to the SFP layer to allow phylink to set the signalling +rate for a SFP module. The rate given will be in units of kilo-baud +(1000 baud). + +Reviewed-by: Simon Horman +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 24 ++++++++++++++++++++++++ + drivers/net/phy/sfp-bus.c | 20 ++++++++++++++++++++ + drivers/net/phy/sfp.c | 5 +++++ + drivers/net/phy/sfp.h | 1 + + include/linux/sfp.h | 6 ++++++ + 5 files changed, 56 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -156,6 +156,23 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static unsigned int phylink_interface_signal_rate(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */ ++ return 1250; ++ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */ ++ return 3125; ++ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */ ++ return 5156; ++ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */ ++ return 10313; ++ default: ++ return 0; ++ } ++} ++ + /** + * phylink_interface_max_speed() - get the maximum speed of a phy interface + * @interface: phy interface mode defined by &typedef phy_interface_t +@@ -1024,6 +1041,7 @@ static void phylink_major_config(struct + { + struct phylink_pcs *pcs = NULL; + bool pcs_changed = false; ++ unsigned int rate_kbd; + int err; + + phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); +@@ -1083,6 +1101,12 @@ static void phylink_major_config(struct + ERR_PTR(err)); + } + ++ if (pl->sfp_bus) { ++ rate_kbd = phylink_interface_signal_rate(state->interface); ++ if (rate_kbd) ++ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd); ++ } ++ + phylink_pcs_poll_start(pl); + } + +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -586,6 +586,26 @@ static void sfp_upstream_clear(struct sf + } + + /** ++ * sfp_upstream_set_signal_rate() - set data signalling rate ++ * @bus: a pointer to the &struct sfp_bus structure for the sfp module ++ * @rate_kbd: signalling rate in units of 1000 baud ++ * ++ * Configure the rate select settings on the SFP module for the signalling ++ * rate (not the same as the data rate). ++ * ++ * Locks that may be held: ++ * Phylink's state_mutex ++ * rtnl lock ++ * SFP's sm_mutex ++ */ ++void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) ++{ ++ if (bus->registered) ++ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); ++} ++EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); ++ ++/** + * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode + * @fwnode: firmware node for the parent device (MAC or PHY) + * +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -2474,6 +2474,10 @@ static void sfp_stop(struct sfp *sfp) + sfp_sm_event(sfp, SFP_E_DEV_DOWN); + } + ++static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd) ++{ ++} ++ + static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) + { + /* locking... and check module is present */ +@@ -2552,6 +2556,7 @@ static const struct sfp_socket_ops sfp_m + .detach = sfp_detach, + .start = sfp_start, + .stop = sfp_stop, ++ .set_signal_rate = sfp_set_signal_rate, + .module_info = sfp_module_info, + .module_eeprom = sfp_module_eeprom, + .module_eeprom_by_page = sfp_module_eeprom_by_page, +--- a/drivers/net/phy/sfp.h ++++ b/drivers/net/phy/sfp.h +@@ -19,6 +19,7 @@ struct sfp_socket_ops { + void (*detach)(struct sfp *sfp); + void (*start)(struct sfp *sfp); + void (*stop)(struct sfp *sfp); ++ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd); + int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); + int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, + u8 *data); +--- a/include/linux/sfp.h ++++ b/include/linux/sfp.h +@@ -547,6 +547,7 @@ int sfp_get_module_eeprom_by_page(struct + struct netlink_ext_ack *extack); + void sfp_upstream_start(struct sfp_bus *bus); + void sfp_upstream_stop(struct sfp_bus *bus); ++void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd); + void sfp_bus_put(struct sfp_bus *bus); + struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); + int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, +@@ -606,6 +607,11 @@ static inline void sfp_upstream_stop(str + { + } + ++static inline void sfp_upstream_set_signal_rate(struct sfp_bus *bus, ++ unsigned int rate_kbd) ++{ ++} ++ + static inline void sfp_bus_put(struct sfp_bus *bus) + { + } diff --git a/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch b/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch new file mode 100644 index 0000000000..8a694c86da --- /dev/null +++ b/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch @@ -0,0 +1,147 @@ +From b84acdb07222a701bfc6403b374249c86f97d18d Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 19 May 2023 14:03:59 +0100 +Subject: [PATCH 15/21] net: phy: add helpers for comparing phy IDs + +There are several places which open code comparing PHY IDs. Provide a +couple of helpers to assist with this, using a slightly simpler test +than the original: + +- phy_id_compare() compares two arbitary PHY IDs and a mask of the + significant bits in the ID. +- phydev_id_compare() compares the bound phydev with the specified + PHY ID, using the bound driver's mask. + +Signed-off-by: Russell King +Reviewed-by: Simon Horman +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/micrel.c | 6 +++--- + drivers/net/phy/phy_device.c | 16 +++++++--------- + drivers/net/phy/phylink.c | 4 ++-- + include/linux/phy.h | 28 ++++++++++++++++++++++++++++ + 4 files changed, 40 insertions(+), 14 deletions(-) + +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -620,7 +620,7 @@ static int ksz8051_ksz8795_match_phy_dev + { + int ret; + +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) ++ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) + return 0; + + ret = phy_read(phydev, MII_BMSR); +@@ -1455,7 +1455,7 @@ static int ksz9x31_cable_test_fault_leng + * + * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity + */ +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) ++ if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) + dt = clamp(dt - 22, 0, 255); + + return (dt * 400) / 10; +@@ -1887,7 +1887,7 @@ static __always_inline int ksz886x_cable + */ + dt = FIELD_GET(data_mask, status); + +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) ++ if (phydev_id_compare(phydev, PHY_ID_LAN8814)) + return ((dt - 22) * 800) / 10; + else + return (dt * 400) / 10; +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -422,8 +422,7 @@ int phy_unregister_fixup(const char *bus + fixup = list_entry(pos, struct phy_fixup, list); + + if ((!strcmp(fixup->bus_id, bus_id)) && +- ((fixup->phy_uid & phy_uid_mask) == +- (phy_uid & phy_uid_mask))) { ++ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { + list_del(&fixup->list); + kfree(fixup); + ret = 0; +@@ -459,8 +458,8 @@ static int phy_needs_fixup(struct phy_de + if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) + return 0; + +- if ((fixup->phy_uid & fixup->phy_uid_mask) != +- (phydev->phy_id & fixup->phy_uid_mask)) ++ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, ++ fixup->phy_uid_mask)) + if (fixup->phy_uid != PHY_ANY_UID) + return 0; + +@@ -507,15 +506,14 @@ static int phy_bus_match(struct device * + if (phydev->c45_ids.device_ids[i] == 0xffffffff) + continue; + +- if ((phydrv->phy_id & phydrv->phy_id_mask) == +- (phydev->c45_ids.device_ids[i] & +- phydrv->phy_id_mask)) ++ if (phy_id_compare(phydev->c45_ids.device_ids[i], ++ phydrv->phy_id, phydrv->phy_id_mask)) + return 1; + } + return 0; + } else { +- return (phydrv->phy_id & phydrv->phy_id_mask) == +- (phydev->phy_id & phydrv->phy_id_mask); ++ return phy_id_compare(phydev->phy_id, phydrv->phy_id, ++ phydrv->phy_id_mask); + } + } + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3151,8 +3151,8 @@ static void phylink_sfp_link_up(void *up + */ + static bool phylink_phy_no_inband(struct phy_device *phy) + { +- return phy->is_c45 && +- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; ++ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], ++ 0xae025150, 0xfffffff0); + } + + static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -993,6 +993,34 @@ struct phy_driver { + #define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) + #define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) + ++/** ++ * phy_id_compare - compare @id1 with @id2 taking account of @mask ++ * @id1: first PHY ID ++ * @id2: second PHY ID ++ * @mask: the PHY ID mask, set bits are significant in matching ++ * ++ * Return true if the bits from @id1 and @id2 specified by @mask match. ++ * This uses an equivalent test to (@id & @mask) == (@phy_id & @mask). ++ */ ++static inline bool phy_id_compare(u32 id1, u32 id2, u32 mask) ++{ ++ return !((id1 ^ id2) & mask); ++} ++ ++/** ++ * phydev_id_compare - compare @id with the PHY's Clause 22 ID ++ * @phydev: the PHY device ++ * @id: the PHY ID to be matched ++ * ++ * Compare the @phydev clause 22 ID with the provided @id and return true or ++ * false depending whether it matches, using the bound driver mask. The ++ * @phydev must be bound to a driver. ++ */ ++static inline bool phydev_id_compare(struct phy_device *phydev, u32 id) ++{ ++ return phy_id_compare(id, phydev->phy_id, phydev->drv->phy_id_mask); ++} ++ + /* A Structure for boards to register fixups with the PHY Lib */ + struct phy_fixup { + struct list_head list; diff --git a/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch b/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch new file mode 100644 index 0000000000..5970355a6c --- /dev/null +++ b/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch @@ -0,0 +1,71 @@ +From 441e1e44301fc5762a06737f8ec04bf1ce3fb039 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 20 May 2023 11:41:42 +0100 +Subject: [PATCH 16/21] net: phylink: require supported_interfaces to be filled + +We have been requiring the supported_interfaces bitmap to be filled in +by MAC drivers that have a mac_select_pcs() method. Now that all MAC +drivers fill in the supported_interfaces bitmap, it is time to enforce +this. We have already required supported_interfaces to be set in order +for optical SFPs to be configured in commit f81fa96d8a6c ("net: phylink: +use phy_interface_t bitmaps for optical modules"). + +Refuse phylink creation if supported_interfaces is empty, and remove +code to deal with cases where this mask is empty. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1q0K1u-006EIP-ET@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -710,14 +710,11 @@ static int phylink_validate(struct phyli + { + const unsigned long *interfaces = pl->config->supported_interfaces; + +- if (!phy_interface_empty(interfaces)) { +- if (state->interface == PHY_INTERFACE_MODE_NA) +- return phylink_validate_mask(pl, supported, state, +- interfaces); ++ if (state->interface == PHY_INTERFACE_MODE_NA) ++ return phylink_validate_mask(pl, supported, state, interfaces); + +- if (!test_bit(state->interface, interfaces)) +- return -EINVAL; +- } ++ if (!test_bit(state->interface, interfaces)) ++ return -EINVAL; + + return phylink_validate_mac_and_pcs(pl, supported, state); + } +@@ -1512,19 +1509,18 @@ struct phylink *phylink_create(struct ph + struct phylink *pl; + int ret; + +- if (mac_ops->mac_select_pcs && +- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != +- ERR_PTR(-EOPNOTSUPP)) +- using_mac_select_pcs = true; +- + /* Validate the supplied configuration */ +- if (using_mac_select_pcs && +- phy_interface_empty(config->supported_interfaces)) { ++ if (phy_interface_empty(config->supported_interfaces)) { + dev_err(config->dev, +- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); ++ "phylink: error: empty supported_interfaces\n"); + return ERR_PTR(-EINVAL); + } + ++ if (mac_ops->mac_select_pcs && ++ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != ++ ERR_PTR(-EOPNOTSUPP)) ++ using_mac_select_pcs = true; ++ + pl = kzalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return ERR_PTR(-ENOMEM); diff --git a/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch b/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch new file mode 100644 index 0000000000..3a26b4b600 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch @@ -0,0 +1,64 @@ +From 4b624a39f2ab523ca6a6ad9448fab1deb7b101e2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 11:15:53 +0100 +Subject: [PATCH 17/21] net: phylink: remove duplicated linkmode pause + resolution + +Phylink had two chunks of code virtually the same for resolving the +negotiated pause modes. Factor this down to one function. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -976,11 +976,10 @@ static void phylink_apply_manual_flow(st + state->pause = pl->link_config.pause; + } + +-static void phylink_resolve_flow(struct phylink_link_state *state) ++static void phylink_resolve_an_pause(struct phylink_link_state *state) + { + bool tx_pause, rx_pause; + +- state->pause = MLO_PAUSE_NONE; + if (state->duplex == DUPLEX_FULL) { + linkmode_resolve_pause(state->advertising, + state->lp_advertising, +@@ -1192,7 +1191,8 @@ static void phylink_get_fixed_state(stru + else if (pl->link_gpio) + state->link = !!gpiod_get_value_cansleep(pl->link_gpio); + +- phylink_resolve_flow(state); ++ state->pause = MLO_PAUSE_NONE; ++ phylink_resolve_an_pause(state); + } + + static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) +@@ -3215,7 +3215,6 @@ static const struct sfp_upstream_ops sfp + static void phylink_decode_c37_word(struct phylink_link_state *state, + uint16_t config_reg, int speed) + { +- bool tx_pause, rx_pause; + int fd_bit; + + if (speed == SPEED_2500) +@@ -3234,13 +3233,7 @@ static void phylink_decode_c37_word(stru + state->link = false; + } + +- linkmode_resolve_pause(state->advertising, state->lp_advertising, +- &tx_pause, &rx_pause); +- +- if (tx_pause) +- state->pause |= MLO_PAUSE_TX; +- if (rx_pause) +- state->pause |= MLO_PAUSE_RX; ++ phylink_resolve_an_pause(state); + } + + static void phylink_decode_sgmii_word(struct phylink_link_state *state, diff --git a/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch b/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch new file mode 100644 index 0000000000..2b2634f80c --- /dev/null +++ b/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch @@ -0,0 +1,76 @@ +From aa8b6bd2b1f235b262bd27f317a0516f196c2c6a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 11:15:58 +0100 +Subject: [PATCH 18/21] net: phylink: add function to resolve clause 73 + negotiation + +Add a function to resolve clause 73 negotiation according to the +priority resolution function described in clause 73.3.6. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 39 +++++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 2 ++ + 2 files changed, 41 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3212,6 +3212,45 @@ static const struct sfp_upstream_ops sfp + + /* Helpers for MAC drivers */ + ++static struct { ++ int bit; ++ int speed; ++} phylink_c73_priority_resolution[] = { ++ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, ++ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, ++ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ ++ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, ++ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, ++ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, ++ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, ++ /* 5GBASE-KR not supported */ ++ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, ++ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, ++}; ++ ++void phylink_resolve_c73(struct phylink_link_state *state) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { ++ int bit = phylink_c73_priority_resolution[i].bit; ++ if (linkmode_test_bit(bit, state->advertising) && ++ linkmode_test_bit(bit, state->lp_advertising)) ++ break; ++ } ++ ++ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { ++ state->speed = phylink_c73_priority_resolution[i].speed; ++ state->duplex = DUPLEX_FULL; ++ } else { ++ /* negotiation failure */ ++ state->link = false; ++ } ++ ++ phylink_resolve_an_pause(state); ++} ++EXPORT_SYMBOL_GPL(phylink_resolve_c73); ++ + static void phylink_decode_c37_word(struct phylink_link_state *state, + uint16_t config_reg, int speed) + { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -656,6 +656,8 @@ int phylink_mii_c22_pcs_config(struct md + const unsigned long *advertising); + void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); + ++void phylink_resolve_c73(struct phylink_link_state *state); ++ + void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, + struct phylink_link_state *state); + diff --git a/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch b/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch new file mode 100644 index 0000000000..eea99a5d78 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch @@ -0,0 +1,100 @@ +From 796d709363135a6bd6a8ccc07b509c939e5b855f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 16:31:50 +0100 +Subject: [PATCH 19/21] net: phylink: provide phylink_pcs_config() and + phylink_pcs_link_up() + +Add two helper functions for calling PCS methods. phylink_pcs_config() +allows us to handle PCS configuration specifics in one location, rather +than the two call sites. phylink_pcs_link_up() gives us consistency. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1q1TzK-007Exd-Rs@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 53 ++++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -991,6 +991,25 @@ static void phylink_resolve_an_pause(str + } + } + ++static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ const struct phylink_link_state *state, ++ bool permit_pause_to_mac) ++{ ++ if (!pcs) ++ return 0; ++ ++ return pcs->ops->pcs_config(pcs, mode, state->interface, ++ state->advertising, permit_pause_to_mac); ++} ++ ++static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, int speed, ++ int duplex) ++{ ++ if (pcs && pcs->ops->pcs_link_up) ++ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); ++} ++ + static void phylink_pcs_poll_stop(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_INBAND) +@@ -1074,18 +1093,15 @@ static void phylink_major_config(struct + + phylink_mac_config(pl, state); + +- if (pl->pcs) { +- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, +- state->interface, +- state->advertising, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); +- if (err < 0) +- phylink_err(pl, "pcs_config failed: %pe\n", +- ERR_PTR(err)); +- if (err > 0) +- restart = true; +- } ++ err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, ++ !!(pl->link_config.pause & ++ MLO_PAUSE_AN)); ++ if (err < 0) ++ phylink_err(pl, "pcs_config failed: %pe\n", ++ ERR_PTR(err)); ++ else if (err > 0) ++ restart = true; ++ + if (restart) + phylink_mac_pcs_an_restart(pl); + +@@ -1136,11 +1152,9 @@ static int phylink_change_inband_advert( + * restart negotiation if the pcs_config() helper indicates that + * the programmed advertisement has changed. + */ +- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, +- pl->link_config.interface, +- pl->link_config.advertising, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); ++ ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, ++ &pl->link_config, ++ !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (ret < 0) + return ret; + +@@ -1272,9 +1286,8 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- if (pl->pcs && pl->pcs->ops->pcs_link_up) +- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, +- pl->cur_interface, speed, duplex); ++ phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, ++ speed, duplex); + + pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, + pl->cur_interface, speed, duplex, diff --git a/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch new file mode 100644 index 0000000000..2f7f7a5737 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch @@ -0,0 +1,55 @@ +From 11933aa76865621d8e82553c8f3bc07796a5aaa2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 1 Jun 2023 10:12:06 +0100 +Subject: [PATCH 20/21] net: phylink: actually fix ksettings_set() ethtool call + +Raju Lakkaraju reported that the below commit caused a regression +with Lan743x drivers and a 2.5G SFP. Sadly, this is because the commit +was utterly wrong. Let's fix this properly by not moving the +linkmode_and(), but instead copying the link ksettings and then +modifying the advertising mask before passing the modified link +ksettings to phylib. + +Fixes: df0acdc59b09 ("net: phylink: fix ksettings_set() ethtool call") +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1q4eLm-00Ayxk-GZ@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -2259,11 +2259,13 @@ int phylink_ethtool_ksettings_set(struct + + ASSERT_RTNL(); + +- /* Mask out unsupported advertisements */ +- linkmode_and(config.advertising, kset->link_modes.advertising, +- pl->supported); +- + if (pl->phydev) { ++ struct ethtool_link_ksettings phy_kset = *kset; ++ ++ linkmode_and(phy_kset.link_modes.advertising, ++ phy_kset.link_modes.advertising, ++ pl->supported); ++ + /* We can rely on phylib for this update; we also do not need + * to update the pl->link_config settings: + * - the configuration returned via ksettings_get() will come +@@ -2282,10 +2284,13 @@ int phylink_ethtool_ksettings_set(struct + * the presence of a PHY, this should not be changed as that + * should be determined from the media side advertisement. + */ +- return phy_ethtool_ksettings_set(pl->phydev, kset); ++ return phy_ethtool_ksettings_set(pl->phydev, &phy_kset); + } + + config = pl->link_config; ++ /* Mask out unsupported advertisements */ ++ linkmode_and(config.advertising, kset->link_modes.advertising, ++ pl->supported); + + /* FIXME: should we reject autoneg if phy/mac does not support it? */ + switch (kset->base.autoneg) { diff --git a/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch b/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch new file mode 100644 index 0000000000..e1a8539aae --- /dev/null +++ b/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch @@ -0,0 +1,324 @@ +From 79b07c3e9c4a2272927be8848c26b372516e1958 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:22 +0100 +Subject: [PATCH 21/21] net: phylink: add PCS negotiation mode + +PCS have to work out whether they should enable PCS negotiation by +looking at the "mode" and "interface" arguments, and the Autoneg bit +in the advertising mask. + +This leads to some complex logic, so lets pull that out into phylink +and instead pass a "neg_mode" argument to the PCS configuration and +link up methods, instead of the "mode" argument. + +In order to transition drivers, add a "neg_mode" flag to the phylink +PCS structure to PCS can indicate whether they want to be passed the +neg_mode or the old mode argument. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8De-00EaFA-Ht@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 45 +++++++++++++---- + include/linux/phylink.h | 104 +++++++++++++++++++++++++++++++++++--- + 2 files changed, 132 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -71,6 +71,7 @@ struct phylink { + struct mutex state_mutex; + struct phylink_link_state phy_state; + struct work_struct resolve; ++ unsigned int pcs_neg_mode; + + bool mac_link_dropped; + bool using_mac_select_pcs; +@@ -991,23 +992,23 @@ static void phylink_resolve_an_pause(str + } + } + +-static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) + { + if (!pcs) + return 0; + +- return pcs->ops->pcs_config(pcs, mode, state->interface, ++ return pcs->ops->pcs_config(pcs, neg_mode, state->interface, + state->advertising, permit_pause_to_mac); + } + +-static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, + int duplex) + { + if (pcs && pcs->ops->pcs_link_up) +- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); ++ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); + } + + static void phylink_pcs_poll_stop(struct phylink *pl) +@@ -1057,10 +1058,15 @@ static void phylink_major_config(struct + struct phylink_pcs *pcs = NULL; + bool pcs_changed = false; + unsigned int rate_kbd; ++ unsigned int neg_mode; + int err; + + phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); + ++ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, ++ state->interface, ++ state->advertising); ++ + if (pl->using_mac_select_pcs) { + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); + if (IS_ERR(pcs)) { +@@ -1093,9 +1099,12 @@ static void phylink_major_config(struct + + phylink_mac_config(pl, state); + +- err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs && pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ ++ err = phylink_pcs_config(pl->pcs, neg_mode, state, ++ !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (err < 0) + phylink_err(pl, "pcs_config failed: %pe\n", + ERR_PTR(err)); +@@ -1130,6 +1139,7 @@ static void phylink_major_config(struct + */ + static int phylink_change_inband_advert(struct phylink *pl) + { ++ unsigned int neg_mode; + int ret; + + if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) +@@ -1148,12 +1158,20 @@ static int phylink_change_inband_advert( + __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, + pl->link_config.pause); + ++ /* Recompute the PCS neg mode */ ++ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, ++ pl->link_config.interface, ++ pl->link_config.advertising); ++ ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ + /* Modern PCS-based method; update the advert at the PCS, and + * restart negotiation if the pcs_config() helper indicates that + * the programmed advertisement has changed. + */ +- ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, +- &pl->link_config, ++ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config, + !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (ret < 0) + return ret; +@@ -1256,6 +1274,7 @@ static void phylink_link_up(struct phyli + struct phylink_link_state link_state) + { + struct net_device *ndev = pl->netdev; ++ unsigned int neg_mode; + int speed, duplex; + bool rx_pause; + +@@ -1286,8 +1305,12 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, +- speed, duplex); ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs && pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ ++ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, ++ duplex); + + pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, + pl->cur_interface, speed, duplex, +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -21,6 +21,24 @@ enum { + MLO_AN_FIXED, /* Fixed-link mode */ + MLO_AN_INBAND, /* In-band protocol */ + ++ /* PCS "negotiation" mode. ++ * PHYLINK_PCS_NEG_NONE - protocol has no inband capability ++ * PHYLINK_PCS_NEG_OUTBAND - some out of band or fixed link setting ++ * PHYLINK_PCS_NEG_INBAND_DISABLED - inband mode disabled, e.g. ++ * 1000base-X with autoneg off ++ * PHYLINK_PCS_NEG_INBAND_ENABLED - inband mode enabled ++ * Additionally, this can be tested using bitmasks: ++ * PHYLINK_PCS_NEG_INBAND - inband mode selected ++ * PHYLINK_PCS_NEG_ENABLED - negotiation mode enabled ++ */ ++ PHYLINK_PCS_NEG_NONE = 0, ++ PHYLINK_PCS_NEG_ENABLED = BIT(4), ++ PHYLINK_PCS_NEG_OUTBAND = BIT(5), ++ PHYLINK_PCS_NEG_INBAND = BIT(6), ++ PHYLINK_PCS_NEG_INBAND_DISABLED = PHYLINK_PCS_NEG_INBAND, ++ PHYLINK_PCS_NEG_INBAND_ENABLED = PHYLINK_PCS_NEG_INBAND | ++ PHYLINK_PCS_NEG_ENABLED, ++ + /* MAC_SYM_PAUSE and MAC_ASYM_PAUSE are used when configuring our + * autonegotiation advertisement. They correspond to the PAUSE and + * ASM_DIR bits defined by 802.3, respectively. +@@ -80,6 +98,70 @@ static inline bool phylink_autoneg_inban + } + + /** ++ * phylink_pcs_neg_mode() - helper to determine PCS inband mode ++ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @interface: interface mode to be used ++ * @advertising: adertisement ethtool link mode mask ++ * ++ * Determines the negotiation mode to be used by the PCS, and returns ++ * one of: ++ * %PHYLINK_PCS_NEG_NONE: interface mode does not support inband ++ * %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) ++ * will be used. ++ * %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg disabled ++ * %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled ++ * ++ * Note: this is for cases where the PCS itself is involved in negotiation ++ * (e.g. Clause 37, SGMII and similar) not Clause 73. ++ */ ++static inline unsigned int phylink_pcs_neg_mode(unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising) ++{ ++ unsigned int neg_mode; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ /* These protocols are designed for use with a PHY which ++ * communicates its negotiation result back to the MAC via ++ * inband communication. Note: there exist PHYs that run ++ * with SGMII but do not send the inband data. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ break; ++ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ /* 1000base-X is designed for use media-side for Fibre ++ * connections, and thus the Autoneg bit needs to be ++ * taken into account. We also do this for 2500base-X ++ * as well, but drivers may not support this, so may ++ * need to override this. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ advertising)) ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; ++ break; ++ ++ default: ++ neg_mode = PHYLINK_PCS_NEG_NONE; ++ break; ++ } ++ ++ return neg_mode; ++} ++ ++/** + * struct phylink_link_state - link state structure + * @advertising: ethtool bitmask containing advertised link modes + * @lp_advertising: ethtool bitmask containing link partner advertised link +@@ -436,6 +518,7 @@ struct phylink_pcs_ops; + /** + * struct phylink_pcs - PHYLINK PCS instance + * @ops: a pointer to the &struct phylink_pcs_ops structure ++ * @neg_mode: provide PCS neg mode via "mode" argument + * @poll: poll the PCS for link changes + * + * This structure is designed to be embedded within the PCS private data, +@@ -443,6 +526,7 @@ struct phylink_pcs_ops; + */ + struct phylink_pcs { + const struct phylink_pcs_ops *ops; ++ bool neg_mode; + bool poll; + }; + +@@ -460,12 +544,12 @@ struct phylink_pcs_ops { + const struct phylink_link_state *state); + void (*pcs_get_state)(struct phylink_pcs *pcs, + struct phylink_link_state *state); +- int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, ++ int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac); + void (*pcs_an_restart)(struct phylink_pcs *pcs); +- void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int mode, ++ void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); + }; + +@@ -508,7 +592,7 @@ void pcs_get_state(struct phylink_pcs *p + /** + * pcs_config() - Configure the PCS mode and advertisement + * @pcs: a pointer to a &struct phylink_pcs. +- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @neg_mode: link negotiation mode (see below) + * @interface: interface mode to be used + * @advertising: adertisement ethtool link mode mask + * @permit_pause_to_mac: permit forwarding pause resolution to MAC +@@ -526,8 +610,12 @@ void pcs_get_state(struct phylink_pcs *p + * For 1000BASE-X, the advertisement should be programmed into the PCS. + * + * For most 10GBASE-R, there is no advertisement. ++ * ++ * The %neg_mode argument should be tested via the phylink_mode_*() family of ++ * functions, or for PCS that set pcs->neg_mode true, should be tested ++ * against the %PHYLINK_PCS_NEG_* definitions. + */ +-int pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, const unsigned long *advertising, + bool permit_pause_to_mac); + +@@ -543,7 +631,7 @@ void pcs_an_restart(struct phylink_pcs * + /** + * pcs_link_up() - program the PCS for the resolved link configuration + * @pcs: a pointer to a &struct phylink_pcs. +- * @mode: link autonegotiation mode ++ * @neg_mode: link negotiation mode (see below) + * @interface: link &typedef phy_interface_t mode + * @speed: link speed + * @duplex: link duplex +@@ -552,8 +640,12 @@ void pcs_an_restart(struct phylink_pcs * + * the resolved link parameters. For example, a PCS operating in SGMII + * mode without in-band AN needs to be manually configured for the link + * and duplex setting. Otherwise, this should be a no-op. ++ * ++ * The %mode argument should be tested via the phylink_mode_*() family of ++ * functions, or for PCS that set pcs->neg_mode true, should be tested ++ * against the %PHYLINK_PCS_NEG_* definitions. + */ +-void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); + #endif + diff --git a/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch b/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch new file mode 100644 index 0000000000..473e9d5836 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch @@ -0,0 +1,45 @@ +From cdb08aa0473730315dbc088d5394e59622314034 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:27 +0100 +Subject: [PATCH 1/2] net: phylink: convert phylink_mii_c22_pcs_config() to + neg_mode + +Use phylink_pcs_neg_mode() for phylink_mii_c22_pcs_config(). This +results in no functional change. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Dj-00EaFG-Mt@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3558,6 +3558,7 @@ int phylink_mii_c22_pcs_config(struct md + phy_interface_t interface, + const unsigned long *advertising) + { ++ unsigned int neg_mode; + bool changed = 0; + u16 bmcr; + int ret, adv; +@@ -3571,15 +3572,13 @@ int phylink_mii_c22_pcs_config(struct md + changed = ret; + } + +- /* Ensure ISOLATE bit is disabled */ +- if (mode == MLO_AN_INBAND && +- (interface == PHY_INTERFACE_MODE_SGMII || +- interface == PHY_INTERFACE_MODE_QSGMII || +- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising))) ++ neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr = BMCR_ANENABLE; + else + bmcr = 0; + ++ /* Configure the inband state. Ensure ISOLATE bit is disabled */ + ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); + if (ret < 0) + return ret; diff --git a/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch b/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch new file mode 100644 index 0000000000..5572850e95 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch @@ -0,0 +1,187 @@ +From febf2aaf05641f3258cc30e072aff65cffc7c82c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:32 +0100 +Subject: [PATCH 2/2] net: phylink: pass neg_mode into + phylink_mii_c22_pcs_config() + +Convert fman_dtsec, xilinx_axienet and pcs-lynx to pass the neg_mode +into phylink_mii_c22_pcs_config(). Where appropriate, drivers are +updated to have neg_mode passed into their pcs_config() and +pcs_link_up() functions. For other drivers, we just hoist the call +to phylink_pcs_neg_mode() to their pcs_config() method out of +phylink_mii_c22_pcs_config(). + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Do-00EaFM-Ra@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 7 ++++--- + .../net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++-- + drivers/net/pcs/pcs-lynx.c | 18 ++++++++++++------ + drivers/net/phy/phylink.c | 9 ++++----- + include/linux/phylink.h | 5 +++-- + 5 files changed, 27 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct p + phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); + } + +-static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) + { + struct fman_mac *dtsec = pcs_to_dtsec(pcs); + +- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, +- advertising); ++ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface, ++ advertising, neg_mode); + } + + static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) +@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_devi + goto _return_fm_mac_free; + } + dtsec->pcs.ops = &dtsec_pcs_ops; ++ dtsec->pcs.neg_mode = true; + dtsec->pcs.poll = true; + + supported = mac_dev->phylink_config.supported_interfaces; +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struc + phylink_mii_c22_pcs_an_restart(pcs_phy); + } + +-static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phy + } + } + +- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising); ++ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising, ++ neg_mode); + if (ret < 0) + netdev_warn(ndev, "Failed to configure PCS: %d\n", ret); + +@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform + } + of_node_put(np); + lp->pcs.ops = &axienet_pcs_ops; ++ lp->pcs.neg_mode = true; + lp->pcs.poll = true; + } + +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -122,9 +122,10 @@ static void lynx_pcs_get_state(struct ph + state->link, state->an_complete); + } + +-static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, ++static int lynx_pcs_config_giga(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising) ++ const unsigned long *advertising, ++ unsigned int neg_mode) + { + u32 link_timer; + u16 if_mode; +@@ -137,8 +138,9 @@ static int lynx_pcs_config_giga(struct m + + if_mode = 0; + } else { ++ /* SGMII and QSGMII */ + if_mode = IF_MODE_SGMII_EN; +- if (mode == MLO_AN_INBAND) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + if_mode |= IF_MODE_USE_SGMII_AN; + + /* Adjust link timer for SGMII */ +@@ -154,7 +156,8 @@ static int lynx_pcs_config_giga(struct m + if (err) + return err; + +- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising); ++ return phylink_mii_c22_pcs_config(pcs, interface, advertising, ++ neg_mode); + } + + static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, +@@ -181,13 +184,16 @@ static int lynx_pcs_config(struct phylin + bool permit) + { + struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); ++ unsigned int neg_mode; ++ ++ neg_mode = phylink_pcs_neg_mode(mode, ifmode, advertising); + + switch (ifmode) { + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: +- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode, +- advertising); ++ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, ++ neg_mode); + case PHY_INTERFACE_MODE_2500BASEX: + if (phylink_autoneg_inband(mode)) { + dev_err(&lynx->mdio->dev, +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3545,20 +3545,20 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_en + /** + * phylink_mii_c22_pcs_config() - configure clause 22 PCS + * @pcs: a pointer to a &struct mdio_device. +- * @mode: link autonegotiation mode + * @interface: the PHY interface mode being configured + * @advertising: the ethtool advertisement mask ++ * @neg_mode: PCS negotiation mode + * + * Configure a Clause 22 PCS PHY with the appropriate negotiation + * parameters for the @mode, @interface and @advertising parameters. + * Returns negative error number on failure, zero if the advertisement + * has not changed, or positive if there is a change. + */ +-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, ++int phylink_mii_c22_pcs_config(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising) ++ const unsigned long *advertising, ++ unsigned int neg_mode) + { +- unsigned int neg_mode; + bool changed = 0; + u16 bmcr; + int ret, adv; +@@ -3572,7 +3572,6 @@ int phylink_mii_c22_pcs_config(struct md + changed = ret; + } + +- neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr = BMCR_ANENABLE; + else +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -743,9 +743,10 @@ void phylink_mii_c22_pcs_get_state(struc + struct phylink_link_state *state); + int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, + const unsigned long *advertising); +-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, ++int phylink_mii_c22_pcs_config(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising); ++ const unsigned long *advertising, ++ unsigned int neg_mode); + void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); + + void phylink_resolve_c73(struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch b/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch new file mode 100644 index 0000000000..5e0128766c --- /dev/null +++ b/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch @@ -0,0 +1,101 @@ +From 3b2de56a146f34e3f70a84cc3a1897064e445d16 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:43 +0100 +Subject: [PATCH] net: pcs: lynxi: update PCS driver to use neg_mode + +Update the Lynxi PCS driver to use neg_mode rather than the mode +argument. This ensures that the link_up() method will always program +the speed and duplex when negotiation is disabled. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Dz-00EaFY-5A@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 39 ++++++++++++++------------------- + 1 file changed, 16 insertions(+), 23 deletions(-) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(stru + FIELD_GET(SGMII_LPA, adv)); + } + +-static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, ++static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); +- bool mode_changed = false, changed, use_an; ++ bool mode_changed = false, changed; + unsigned int rgc3, sgm_mode, bmcr; + int advertise, link_timer; + +@@ -121,30 +121,22 @@ static int mtk_pcs_lynxi_config(struct p + * we assume that fixes it's speed at bitrate = line rate (in + * other words, 1000Mbps or 2500Mbps). + */ +- if (interface == PHY_INTERFACE_MODE_SGMII) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) + sgm_mode = SGMII_IF_MODE_SGMII; +- if (phylink_autoneg_inband(mode)) { +- sgm_mode |= SGMII_REMOTE_FAULT_DIS | +- SGMII_SPEED_DUPLEX_AN; +- use_an = true; +- } else { +- use_an = false; +- } +- } else if (phylink_autoneg_inband(mode)) { +- /* 1000base-X or 2500base-X autoneg */ +- sgm_mode = SGMII_REMOTE_FAULT_DIS; +- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, +- advertising); +- } else { ++ else + /* 1000base-X or 2500base-X without autoneg */ + sgm_mode = 0; +- use_an = false; +- } + +- if (use_an) ++ if (neg_mode & PHYLINK_PCS_NEG_INBAND) ++ sgm_mode |= SGMII_REMOTE_FAULT_DIS; ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) ++ sgm_mode |= SGMII_SPEED_DUPLEX_AN; + bmcr = BMCR_ANENABLE; +- else ++ } else { + bmcr = 0; ++ } + + if (mpcs->interface != interface) { + link_timer = phylink_get_link_timer_ns(interface); +@@ -216,14 +208,15 @@ static void mtk_pcs_lynxi_restart_an(str + regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); + } + +-static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, ++static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, ++ unsigned int neg_mode, + phy_interface_t interface, int speed, + int duplex) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + unsigned int sgm_mode; + +- if (!phylink_autoneg_inband(mode)) { ++ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { + /* Force the speed and duplex setting */ + if (speed == SPEED_10) + sgm_mode = SGMII_SPEED_10; +@@ -286,6 +279,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create + mpcs->regmap = regmap; + mpcs->flags = flags; + mpcs->pcs.ops = &mtk_pcs_lynxi_ops; ++ mpcs->pcs.neg_mode = true; + mpcs->pcs.poll = true; + mpcs->interface = PHY_INTERFACE_MODE_NA; + diff --git a/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch new file mode 100644 index 0000000000..3dd22d2916 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch @@ -0,0 +1,55 @@ +From 459fd2f11204c962e3153020f4f56748e0e10afb Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:49 +0000 +Subject: [PATCH] net: pcs: xpcs: use Autoneg bit rather than an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. Thus, we will be removing state->an_enabled. + +Use the Autoneg bit in the advertising bitmap to indicate whether +autonegotiation should be used, rather than using the an_enabled +member which will be going away. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-xpcs.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -931,6 +931,7 @@ static int xpcs_get_state_c73(struct dw_ + struct phylink_link_state *state, + const struct xpcs_compat *compat) + { ++ bool an_enabled; + int ret; + + /* Link needs to be read first ... */ +@@ -948,11 +949,13 @@ static int xpcs_get_state_c73(struct dw_ + return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); + } + +- if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { ++ an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising); ++ if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { + state->an_complete = true; + xpcs_read_lpa_c73(xpcs, state); + xpcs_resolve_lpa_c73(xpcs, state); +- } else if (state->an_enabled) { ++ } else if (an_enabled) { + state->link = 0; + } else if (state->link) { + xpcs_resolve_pma(xpcs, state); +@@ -1007,7 +1010,8 @@ static int xpcs_get_state_c37_1000basex( + { + int lpa, bmsr; + +- if (state->an_enabled) { ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) { + /* Reset link state */ + state->link = false; + diff --git a/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch b/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch new file mode 100644 index 0000000000..7cae8515fa --- /dev/null +++ b/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch @@ -0,0 +1,30 @@ +From 43fb622d91a9f408322735d2f736495c1009f575 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 9 May 2023 12:50:04 +0100 +Subject: [PATCH] net: pcs: xpcs: fix incorrect number of interfaces + +In synopsys_xpcs_compat[], the DW_XPCS_2500BASEX entry was setting +the number of interfaces using the xpcs_2500basex_features array +rather than xpcs_2500basex_interfaces. This causes us to overflow +the array of interfaces. Fix this. + +Fixes: f27abde3042a ("net: pcs: add 2500BASEX support for Intel mGbE controller") +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +--- + drivers/net/pcs/pcs-xpcs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -1211,7 +1211,7 @@ static const struct xpcs_compat synopsys + [DW_XPCS_2500BASEX] = { + .supported = xpcs_2500basex_features, + .interface = xpcs_2500basex_interfaces, +- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features), ++ .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces), + .an_mode = DW_2500BASEX, + }, + }; diff --git a/target/linux/generic/backport-6.6/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch b/target/linux/generic/backport-6.6/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch new file mode 100644 index 0000000000..0a7b5358f1 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch @@ -0,0 +1,36 @@ +From f2ec98566775dd4341ec1dcf93aa5859c60de826 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 1 Feb 2024 14:46:00 +0100 +Subject: [PATCH 1/2] net: phy: qcom: qca808x: fix logic error in LED + brightness set + +In switching to using phy_modify_mmd and a more short version of the +LED ON/OFF condition in later revision, it was made a logic error where + +value ? QCA808X_LED_FORCE_ON : QCA808X_LED_FORCE_OFF is always true as +value is always OR with QCA808X_LED_FORCE_EN due to missing () +resulting in the testing condition being QCA808X_LED_FORCE_EN | value. + +Add the () to apply the correct condition and restore correct +functionality of the brightness ON/OFF. + +Fixes: 7196062b64ee ("net: phy: at803x: add LED support for qca808x") +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -820,8 +820,8 @@ static int qca808x_led_brightness_set(st + + return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); ++ QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF)); + } + + static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, diff --git a/target/linux/generic/backport-6.6/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch b/target/linux/generic/backport-6.6/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch new file mode 100644 index 0000000000..e32ed7f777 --- /dev/null +++ b/target/linux/generic/backport-6.6/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch @@ -0,0 +1,41 @@ +From f203c8c77c7616c099647636f4c67d59a45fe8a2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 1 Feb 2024 14:46:01 +0100 +Subject: [PATCH 2/2] net: phy: qcom: qca808x: default to LED active High if + not set + +qca808x PHY provide support for the led_polarity_set OP to configure +and apply the active-low property but on PHY reset, the Active High bit +is not set resulting in the LED driven as active-low. + +To fix this, check if active-low is not set in DT and enable Active High +polarity by default to restore correct funcionality of the LED. + +Fixes: 7196062b64ee ("net: phy: at803x: add LED support for qca808x") +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -290,8 +290,18 @@ static int qca808x_probe(struct phy_devi + + static int qca808x_config_init(struct phy_device *phydev) + { ++ struct qca808x_priv *priv = phydev->priv; + int ret; + ++ /* Default to LED Active High if active-low not in DT */ ++ if (priv->led_polarity_mode == -1) { ++ ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH); ++ if (ret) ++ return ret; ++ } ++ + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, + QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); diff --git a/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch new file mode 100644 index 0000000000..b355031aa5 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch @@ -0,0 +1,211 @@ +From 385ef48f468696d6d172eb367656a3466fa0408d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:05 +0100 +Subject: [PATCH 02/10] net: phy: add support for scanning PHY in PHY packages + nodes + +Add support for scanning PHY in PHY package nodes. PHY packages nodes +are just container for actual PHY on the MDIO bus. + +Their PHY address defined in the PHY package node are absolute and +reflect the address on the MDIO bus. + +mdio_bus.c and of_mdio.c is updated to now support and parse also +PHY package subnode by checking if the node name match +"ethernet-phy-package". + +As PHY package reg is mandatory and each PHY in the PHY package must +have a reg, every invalid PHY Package node is ignored and will be +skipped by the autoscan fallback. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/mdio/of_mdio.c | 79 +++++++++++++++++++++++++++----------- + drivers/net/phy/mdio_bus.c | 44 +++++++++++++++++---- + 2 files changed, 92 insertions(+), 31 deletions(-) + +--- a/drivers/net/mdio/of_mdio.c ++++ b/drivers/net/mdio/of_mdio.c +@@ -138,6 +138,53 @@ bool of_mdiobus_child_is_phy(struct devi + } + EXPORT_SYMBOL(of_mdiobus_child_is_phy); + ++static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, ++ bool *scanphys) ++{ ++ struct device_node *child; ++ int addr, rc = 0; ++ ++ /* Loop over the child nodes and register a phy_device for each phy */ ++ for_each_available_child_of_node(np, child) { ++ if (of_node_name_eq(child, "ethernet-phy-package")) { ++ /* Ignore invalid ethernet-phy-package node */ ++ if (!of_find_property(child, "reg", NULL)) ++ continue; ++ ++ rc = __of_mdiobus_parse_phys(mdio, child, NULL); ++ if (rc && rc != -ENODEV) ++ goto exit; ++ ++ continue; ++ } ++ ++ addr = of_mdio_parse_addr(&mdio->dev, child); ++ if (addr < 0) { ++ /* Skip scanning for invalid ethernet-phy-package node */ ++ if (scanphys) ++ *scanphys = true; ++ continue; ++ } ++ ++ if (of_mdiobus_child_is_phy(child)) ++ rc = of_mdiobus_register_phy(mdio, child, addr); ++ else ++ rc = of_mdiobus_register_device(mdio, child, addr); ++ ++ if (rc == -ENODEV) ++ dev_err(&mdio->dev, ++ "MDIO device at address %d is missing.\n", ++ addr); ++ else if (rc) ++ goto exit; ++ } ++ ++ return 0; ++exit: ++ of_node_put(child); ++ return rc; ++} ++ + /** + * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * @mdio: pointer to mii_bus structure +@@ -179,33 +226,18 @@ int __of_mdiobus_register(struct mii_bus + return rc; + + /* Loop over the child nodes and register a phy_device for each phy */ +- for_each_available_child_of_node(np, child) { +- addr = of_mdio_parse_addr(&mdio->dev, child); +- if (addr < 0) { +- scanphys = true; +- continue; +- } +- +- if (of_mdiobus_child_is_phy(child)) +- rc = of_mdiobus_register_phy(mdio, child, addr); +- else +- rc = of_mdiobus_register_device(mdio, child, addr); +- +- if (rc == -ENODEV) +- dev_err(&mdio->dev, +- "MDIO device at address %d is missing.\n", +- addr); +- else if (rc) +- goto unregister; +- } ++ rc = __of_mdiobus_parse_phys(mdio, np, &scanphys); ++ if (rc) ++ goto unregister; + + if (!scanphys) + return 0; + + /* auto scan for PHYs with empty reg property */ + for_each_available_child_of_node(np, child) { +- /* Skip PHYs with reg property set */ +- if (of_find_property(child, "reg", NULL)) ++ /* Skip PHYs with reg property set or ethernet-phy-package node */ ++ if (of_find_property(child, "reg", NULL) || ++ of_node_name_eq(child, "ethernet-phy-package")) + continue; + + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { +@@ -226,15 +258,16 @@ int __of_mdiobus_register(struct mii_bus + if (!rc) + break; + if (rc != -ENODEV) +- goto unregister; ++ goto put_unregister; + } + } + } + + return 0; + +-unregister: ++put_unregister: + of_node_put(child); ++unregister: + mdiobus_unregister(mdio); + return rc; + } +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -448,19 +448,34 @@ EXPORT_SYMBOL(of_mdio_find_bus); + * found, set the of_node pointer for the mdio device. This allows + * auto-probed phy devices to be supplied with information passed in + * via DT. ++ * If a PHY package is found, PHY is searched also there. + */ +-static void of_mdiobus_link_mdiodev(struct mii_bus *bus, +- struct mdio_device *mdiodev) ++static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, ++ struct device_node *np) + { +- struct device *dev = &mdiodev->dev; + struct device_node *child; + +- if (dev->of_node || !bus->dev.of_node) +- return; +- +- for_each_available_child_of_node(bus->dev.of_node, child) { ++ for_each_available_child_of_node(np, child) { + int addr; + ++ if (of_node_name_eq(child, "ethernet-phy-package")) { ++ /* Validate PHY package reg presence */ ++ if (!of_find_property(child, "reg", NULL)) { ++ of_node_put(child); ++ return -EINVAL; ++ } ++ ++ if (!of_mdiobus_find_phy(dev, mdiodev, child)) { ++ /* The refcount for the PHY package will be ++ * incremented later when PHY join the Package. ++ */ ++ of_node_put(child); ++ return 0; ++ } ++ ++ continue; ++ } ++ + addr = of_mdio_parse_addr(dev, child); + if (addr < 0) + continue; +@@ -470,9 +485,22 @@ static void of_mdiobus_link_mdiodev(stru + /* The refcount on "child" is passed to the mdio + * device. Do _not_ use of_node_put(child) here. + */ +- return; ++ return 0; + } + } ++ ++ return -ENODEV; ++} ++ ++static void of_mdiobus_link_mdiodev(struct mii_bus *bus, ++ struct mdio_device *mdiodev) ++{ ++ struct device *dev = &mdiodev->dev; ++ ++ if (dev->of_node || !bus->dev.of_node) ++ return; ++ ++ of_mdiobus_find_phy(dev, mdiodev, bus->dev.of_node); + } + #else /* !IS_ENABLED(CONFIG_OF_MDIO) */ + static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio, diff --git a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch new file mode 100644 index 0000000000..3c7bf6c132 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch @@ -0,0 +1,185 @@ +From 471e8fd3afcef5a9f9089f0bd21965ad9ba35c91 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:06 +0100 +Subject: [PATCH 03/10] net: phy: add devm/of_phy_package_join helper + +Add devm/of_phy_package_join helper to join PHYs in a PHY package. These +are variant of the manual phy_package_join with the difference that +these will use DT nodes to derive the base_addr instead of manually +passing an hardcoded value. + +An additional value is added in phy_package_shared, "np" to reference +the PHY package node pointer in specific PHY driver probe_once and +config_init_once functions to make use of additional specific properties +defined in the PHY package node in DT. + +The np value is filled only with of_phy_package_join if a valid PHY +package node is found. A valid PHY package node must have the node name +set to "ethernet-phy-package". + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 96 ++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 6 +++ + 2 files changed, 102 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1648,6 +1648,7 @@ int phy_package_join(struct phy_device * + shared->priv_size = priv_size; + } + shared->base_addr = base_addr; ++ shared->np = NULL; + refcount_set(&shared->refcnt, 1); + bus->shared[base_addr] = shared; + } else { +@@ -1671,6 +1672,63 @@ err_unlock: + EXPORT_SYMBOL_GPL(phy_package_join); + + /** ++ * of_phy_package_join - join a common PHY group in PHY package ++ * @phydev: target phy_device struct ++ * @priv_size: if non-zero allocate this amount of bytes for private data ++ * ++ * This is a variant of phy_package_join for PHY package defined in DT. ++ * ++ * The parent node of the @phydev is checked as a valid PHY package node ++ * structure (by matching the node name "ethernet-phy-package") and the ++ * base_addr for the PHY package is passed to phy_package_join. ++ * ++ * With this configuration the shared struct will also have the np value ++ * filled to use additional DT defined properties in PHY specific ++ * probe_once and config_init_once PHY package OPs. ++ * ++ * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() ++ * with the same cookie but a different priv_size is an error. Or a parent ++ * node is not detected or is not valid or doesn't match the expected node ++ * name for PHY package. ++ */ ++int of_phy_package_join(struct phy_device *phydev, size_t priv_size) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct device_node *package_node; ++ u32 base_addr; ++ int ret; ++ ++ if (!node) ++ return -EINVAL; ++ ++ package_node = of_get_parent(node); ++ if (!package_node) ++ return -EINVAL; ++ ++ if (!of_node_name_eq(package_node, "ethernet-phy-package")) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (of_property_read_u32(package_node, "reg", &base_addr)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = phy_package_join(phydev, base_addr, priv_size); ++ if (ret) ++ goto exit; ++ ++ phydev->shared->np = package_node; ++ ++ return 0; ++exit: ++ of_node_put(package_node); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(of_phy_package_join); ++ ++/** + * phy_package_leave - leave a common PHY group + * @phydev: target phy_device struct + * +@@ -1686,6 +1744,10 @@ void phy_package_leave(struct phy_device + if (!shared) + return; + ++ /* Decrease the node refcount on leave if present */ ++ if (shared->np) ++ of_node_put(shared->np); ++ + if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { + bus->shared[shared->base_addr] = NULL; + mutex_unlock(&bus->shared_lock); +@@ -1739,6 +1801,40 @@ int devm_phy_package_join(struct device + EXPORT_SYMBOL_GPL(devm_phy_package_join); + + /** ++ * devm_of_phy_package_join - resource managed of_phy_package_join() ++ * @dev: device that is registering this PHY package ++ * @phydev: target phy_device struct ++ * @priv_size: if non-zero allocate this amount of bytes for private data ++ * ++ * Managed of_phy_package_join(). Shared storage fetched by this function, ++ * phy_package_leave() is automatically called on driver detach. See ++ * of_phy_package_join() for more information. ++ */ ++int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, ++ size_t priv_size) ++{ ++ struct phy_device **ptr; ++ int ret; ++ ++ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), ++ GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ ret = of_phy_package_join(phydev, priv_size); ++ ++ if (!ret) { ++ *ptr = phydev; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(devm_of_phy_package_join); ++ ++/** + * phy_detach - detach a PHY device from its network device + * @phydev: target phy_device struct + * +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -321,6 +321,7 @@ struct mdio_bus_stats { + * struct phy_package_shared - Shared information in PHY packages + * @base_addr: Base PHY address of PHY package used to combine PHYs + * in one package and for offset calculation of phy_package_read/write ++ * @np: Pointer to the Device Node if PHY package defined in DT + * @refcnt: Number of PHYs connected to this shared data + * @flags: Initialization of PHY package + * @priv_size: Size of the shared private data @priv +@@ -332,6 +333,8 @@ struct mdio_bus_stats { + */ + struct phy_package_shared { + u8 base_addr; ++ /* With PHY package defined in DT this points to the PHY package node */ ++ struct device_node *np; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; +@@ -1793,9 +1796,12 @@ int phy_ethtool_set_link_ksettings(struc + const struct ethtool_link_ksettings *cmd); + int phy_ethtool_nway_reset(struct net_device *ndev); + int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size); ++int of_phy_package_join(struct phy_device *phydev, size_t priv_size); + void phy_package_leave(struct phy_device *phydev); + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, + int base_addr, size_t priv_size); ++int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, ++ size_t priv_size); + + #if IS_ENABLED(CONFIG_PHYLIB) + int __init mdio_bus_init(void); diff --git a/target/linux/generic/backport-6.6/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch b/target/linux/generic/backport-6.6/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch new file mode 100644 index 0000000000..e935725630 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch @@ -0,0 +1,583 @@ +From 737eb75a815f9c08dcbb6631db57f4f4b0540a5b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:07 +0100 +Subject: [PATCH 04/10] net: phy: qcom: move more function to shared library + +Move more function to shared library in preparation for introduction of +new PHY Family qca807x that will make use of both functions from at803x +and qca808x as it's a transition PHY with some implementation of at803x +and some from the new qca808x. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/at803x.c | 35 ----- + drivers/net/phy/qcom/qca808x.c | 205 ---------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 193 ++++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 51 +++++++ + 4 files changed, 244 insertions(+), 240 deletions(-) + +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -504,41 +504,6 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int err, old_link = phydev->link; +- +- /* Update the link, but return if there was an error */ +- err = genphy_update_link(phydev); +- if (err) +- return err; +- +- /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) +- return 0; +- +- phydev->speed = SPEED_UNKNOWN; +- phydev->duplex = DUPLEX_UNKNOWN; +- phydev->pause = 0; +- phydev->asym_pause = 0; +- +- err = genphy_read_lpa(phydev); +- if (err < 0) +- return err; +- +- ss_mask.speed_mask = AT803X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); +- err = at803x_read_specific_status(phydev, ss_mask); +- if (err < 0) +- return err; +- +- if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) +- phy_resolve_aneg_pause(phydev); +- +- return 0; +-} +- + static int at803x_config_aneg(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -2,7 +2,6 @@ + + #include + #include +-#include + + #include "qcom.h" + +@@ -63,55 +62,6 @@ + #define QCA808X_DBG_AN_TEST 0xb + #define QCA808X_HIBERNATION_EN BIT(15) + +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- + #define QCA808X_MMD7_LED_GLOBAL 0x8073 + #define QCA808X_LED_BLINK_1 GENMASK(11, 6) + #define QCA808X_LED_BLINK_2 GENMASK(5, 0) +@@ -406,86 +356,6 @@ static int qca808x_soft_reset(struct phy + return ret; + } + +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- + static int qca808x_cable_test_start(struct phy_device *phydev) + { + int ret; +@@ -526,81 +396,6 @@ static int qca808x_cable_test_start(stru + + return 0; + } +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} + + static int qca808x_get_features(struct phy_device *phydev) + { +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + + #include "qcom.h" + +@@ -311,6 +312,42 @@ int at803x_prepare_config_aneg(struct ph + } + EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg); + ++int at803x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int err, old_link = phydev->link; ++ ++ /* Update the link, but return if there was an error */ ++ err = genphy_update_link(phydev); ++ if (err) ++ return err; ++ ++ /* why bother the PHY if nothing can have changed */ ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ return 0; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ err = genphy_read_lpa(phydev); ++ if (err < 0) ++ return err; ++ ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); ++ if (err < 0) ++ return err; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_read_status); ++ + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) + { + int val; +@@ -427,3 +464,159 @@ int at803x_cdt_wait_for_completion(struc + return ret < 0 ? ret : 0; + } + EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion); ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(qca808x_cable_test_get_status); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -54,6 +54,55 @@ + #define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) + #define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) + ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ + #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C + #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B + #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +@@ -110,6 +159,7 @@ int at803x_read_specific_status(struct p + struct at803x_ss_mask ss_mask); + int at803x_config_mdix(struct phy_device *phydev, u8 ctrl); + int at803x_prepare_config_aneg(struct phy_device *phydev); ++int at803x_read_status(struct phy_device *phydev); + int at803x_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, void *data); + int at803x_set_tunable(struct phy_device *phydev, +@@ -118,3 +168,4 @@ int at803x_cdt_fault_length(int dt); + int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start); + int at803x_cdt_wait_for_completion(struct phy_device *phydev, + u32 cdt_en); ++int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished); diff --git a/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch new file mode 100644 index 0000000000..acaa4a644e --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch @@ -0,0 +1,100 @@ +From 9b1d5e055508393561e26bd1720f4c2639b03b1a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:09 +0100 +Subject: [PATCH 06/10] net: phy: provide whether link has changed in + c37_read_status + +Some PHY driver might require additional regs call after +genphy_c37_read_status() is called. + +Expand genphy_c37_read_status to provide a bool wheather the link has +changed or not to permit PHY driver to skip additional regs call if +nothing has changed. + +Every user of genphy_c37_read_status() is updated with the new +additional bool. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/broadcom.c | 3 ++- + drivers/net/phy/phy_device.c | 11 +++++++++-- + drivers/net/phy/qcom/at803x.c | 3 ++- + include/linux/phy.h | 2 +- + 4 files changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -609,10 +609,11 @@ static int bcm54616s_config_aneg(struct + static int bcm54616s_read_status(struct phy_device *phydev) + { + struct bcm54616s_phy_priv *priv = phydev->priv; ++ bool changed; + int err; + + if (priv->mode_1000bx_en) +- err = genphy_c37_read_status(phydev); ++ err = genphy_c37_read_status(phydev, &changed); + else + err = genphy_read_status(phydev); + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -2549,12 +2549,15 @@ EXPORT_SYMBOL(genphy_read_status); + /** + * genphy_c37_read_status - check the link status and update current link state + * @phydev: target phy_device struct ++ * @changed: pointer where to store if link changed + * + * Description: Check the link, then figure out the current state + * by comparing what we advertise with what the link partner + * advertises. This function is for Clause 37 1000Base-X mode. ++ * ++ * If link has changed, @changed is set to true, false otherwise. + */ +-int genphy_c37_read_status(struct phy_device *phydev) ++int genphy_c37_read_status(struct phy_device *phydev, bool *changed) + { + int lpa, err, old_link = phydev->link; + +@@ -2564,9 +2567,13 @@ int genphy_c37_read_status(struct phy_de + return err; + + /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) { ++ *changed = false; + return 0; ++ } + ++ /* Signal link has changed */ ++ *changed = true; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -912,9 +912,10 @@ static int at8031_config_intr(struct phy + static int at8031_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ bool changed; + + if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); ++ return genphy_c37_read_status(phydev, &changed); + + return at803x_read_status(phydev); + } +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1688,7 +1688,7 @@ int genphy_write_mmd_unsupported(struct + + /* Clause 37 */ + int genphy_c37_config_aneg(struct phy_device *phydev); +-int genphy_c37_read_status(struct phy_device *phydev); ++int genphy_c37_read_status(struct phy_device *phydev, bool *changed); + + /* Clause 45 PHY */ + int genphy_c45_restart_aneg(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.6/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch b/target/linux/generic/backport-6.6/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch new file mode 100644 index 0000000000..bbf0f76d68 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch @@ -0,0 +1,668 @@ +From d1cb613efbd3cd7d0c000167816beb3f248f5eb8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 6 Feb 2024 18:31:10 +0100 +Subject: [PATCH 07/10] net: phy: qcom: add support for QCA807x PHY Family + +This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. + +They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, +100BASE-TX and 1000BASE-T PHY-s. + +They feature 2 SerDes, one for PSGMII or QSGMII connection with +MAC, while second one is SGMII for connection to MAC or fiber. + +Both models have a combo port that supports 1000BASE-X and +100BASE-FX fiber. + +PHY package can be configured in 3 mode following this table: + + First Serdes mode Second Serdes mode +Option 1 PSGMII for copper Disabled + ports 0-4 +Option 2 PSGMII for copper 1000BASE-X / 100BASE-FX + ports 0-4 +Option 3 QSGMII for copper SGMII for + ports 0-3 copper port 4 + +Each PHY inside of QCA807x series has 4 digitally controlled +output only pins that natively drive LED-s. +But some vendors used these to driver generic LED-s controlled +by userspace, so lets enable registering each PHY as GPIO +controller and add driver for it. + +These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x +boards. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/Kconfig | 8 + + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/qca807x.c | 597 +++++++++++++++++++++++++++++++++ + 3 files changed, 606 insertions(+) + create mode 100644 drivers/net/phy/qcom/qca807x.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -20,3 +20,11 @@ config QCA808X_PHY + select QCOM_NET_PHYLIB + help + Currently supports the QCA8081 model ++ ++config QCA807X_PHY ++ tristate "Qualcomm QCA807x PHYs" ++ select QCOM_NET_PHYLIB ++ depends on OF_MDIO ++ help ++ Currently supports the Qualcomm QCA8072, QCA8075 and the PSGMII ++ control PHY. +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -3,3 +3,4 @@ obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-ph + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o + obj-$(CONFIG_QCA808X_PHY) += qca808x.o ++obj-$(CONFIG_QCA807X_PHY) += qca807x.o +--- /dev/null ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -0,0 +1,597 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2023 Sartura Ltd. ++ * ++ * Author: Robert Marko ++ * Christian Marangi ++ * ++ * Qualcomm QCA8072 and QCA8075 PHY driver ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qcom.h" ++ ++#define QCA807X_CHIP_CONFIGURATION 0x1f ++#define QCA807X_BT_BX_REG_SEL BIT(15) ++#define QCA807X_BT_BX_REG_SEL_FIBER 0 ++#define QCA807X_BT_BX_REG_SEL_COPPER 1 ++#define QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK GENMASK(3, 0) ++#define QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII 4 ++#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER 3 ++#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER 0 ++ ++#define QCA807X_MEDIA_SELECT_STATUS 0x1a ++#define QCA807X_MEDIA_DETECTED_COPPER BIT(5) ++#define QCA807X_MEDIA_DETECTED_1000_BASE_X BIT(4) ++#define QCA807X_MEDIA_DETECTED_100_BASE_FX BIT(3) ++ ++#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION 0x807e ++#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN BIT(0) ++ ++#define QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH 0x801a ++#define QCA807X_CONTROL_DAC_MASK GENMASK(2, 0) ++/* List of tweaks enabled by this bit: ++ * - With both FULL amplitude and FULL bias current: bias current ++ * is set to half. ++ * - With only DSP amplitude: bias current is set to half and ++ * is set to 1/4 with cable < 10m. ++ * - With DSP bias current (included both DSP amplitude and ++ * DSP bias current): bias current is half the detected current ++ * with cable < 10m. ++ */ ++#define QCA807X_CONTROL_DAC_BIAS_CURRENT_TWEAK BIT(2) ++#define QCA807X_CONTROL_DAC_DSP_BIAS_CURRENT BIT(1) ++#define QCA807X_CONTROL_DAC_DSP_AMPLITUDE BIT(0) ++ ++#define QCA807X_MMD7_LED_100N_1 0x8074 ++#define QCA807X_MMD7_LED_100N_2 0x8075 ++#define QCA807X_MMD7_LED_1000N_1 0x8076 ++#define QCA807X_MMD7_LED_1000N_2 0x8077 ++ ++#define QCA807X_MMD7_LED_CTRL(x) (0x8074 + ((x) * 2)) ++#define QCA807X_MMD7_LED_FORCE_CTRL(x) (0x8075 + ((x) * 2)) ++ ++#define QCA807X_GPIO_FORCE_EN BIT(15) ++#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13) ++ ++#define QCA807X_FUNCTION_CONTROL 0x10 ++#define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5) ++#define QCA807X_FC_MDI_CROSSOVER_AUTO 3 ++#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX 1 ++#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI 0 ++ ++/* PQSGMII Analog PHY specific */ ++#define PQSGMII_CTRL_REG 0x0 ++#define PQSGMII_ANALOG_SW_RESET BIT(6) ++#define PQSGMII_DRIVE_CONTROL_1 0xb ++#define PQSGMII_TX_DRIVER_MASK GENMASK(7, 4) ++#define PQSGMII_TX_DRIVER_140MV 0x0 ++#define PQSGMII_TX_DRIVER_160MV 0x1 ++#define PQSGMII_TX_DRIVER_180MV 0x2 ++#define PQSGMII_TX_DRIVER_200MV 0x3 ++#define PQSGMII_TX_DRIVER_220MV 0x4 ++#define PQSGMII_TX_DRIVER_240MV 0x5 ++#define PQSGMII_TX_DRIVER_260MV 0x6 ++#define PQSGMII_TX_DRIVER_280MV 0x7 ++#define PQSGMII_TX_DRIVER_300MV 0x8 ++#define PQSGMII_TX_DRIVER_320MV 0x9 ++#define PQSGMII_TX_DRIVER_400MV 0xa ++#define PQSGMII_TX_DRIVER_500MV 0xb ++#define PQSGMII_TX_DRIVER_600MV 0xc ++#define PQSGMII_MODE_CTRL 0x6d ++#define PQSGMII_MODE_CTRL_AZ_WORKAROUND_MASK BIT(0) ++#define PQSGMII_MMD3_SERDES_CONTROL 0x805a ++ ++#define PHY_ID_QCA8072 0x004dd0b2 ++#define PHY_ID_QCA8075 0x004dd0b1 ++ ++#define QCA807X_COMBO_ADDR_OFFSET 4 ++#define QCA807X_PQSGMII_ADDR_OFFSET 5 ++#define SERDES_RESET_SLEEP 100 ++ ++enum qca807x_global_phy { ++ QCA807X_COMBO_ADDR = 4, ++ QCA807X_PQSGMII_ADDR = 5, ++}; ++ ++struct qca807x_shared_priv { ++ unsigned int package_mode; ++ u32 tx_drive_strength; ++}; ++ ++struct qca807x_gpio_priv { ++ struct phy_device *phy; ++}; ++ ++struct qca807x_priv { ++ bool dac_full_amplitude; ++ bool dac_full_bias_current; ++ bool dac_disable_bias_current_tweak; ++}; ++ ++static int qca807x_cable_test_start(struct phy_device *phydev) ++{ ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++#ifdef CONFIG_GPIOLIB ++static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ return GPIO_LINE_DIRECTION_OUT; ++} ++ ++static int qca807x_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); ++ u16 reg; ++ int val; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(offset); ++ val = phy_read_mmd(priv->phy, MDIO_MMD_AN, reg); ++ ++ return FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val); ++} ++ ++static void qca807x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); ++ u16 reg; ++ int val; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(offset); ++ ++ val = phy_read_mmd(priv->phy, MDIO_MMD_AN, reg); ++ val &= ~QCA807X_GPIO_FORCE_MODE_MASK; ++ val |= QCA807X_GPIO_FORCE_EN; ++ val |= FIELD_PREP(QCA807X_GPIO_FORCE_MODE_MASK, value); ++ ++ phy_write_mmd(priv->phy, MDIO_MMD_AN, reg, val); ++} ++ ++static int qca807x_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ qca807x_gpio_set(gc, offset, value); ++ ++ return 0; ++} ++ ++static int qca807x_gpio(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca807x_gpio_priv *priv; ++ struct gpio_chip *gc; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->phy = phydev; ++ ++ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); ++ if (!gc) ++ return -ENOMEM; ++ ++ gc->label = dev_name(dev); ++ gc->base = -1; ++ gc->ngpio = 2; ++ gc->parent = dev; ++ gc->owner = THIS_MODULE; ++ gc->can_sleep = true; ++ gc->get_direction = qca807x_gpio_get_direction; ++ gc->direction_output = qca807x_gpio_dir_out; ++ gc->get = qca807x_gpio_get; ++ gc->set = qca807x_gpio_set; ++ ++ return devm_gpiochip_add_data(dev, gc, priv); ++} ++#endif ++ ++static int qca807x_read_fiber_status(struct phy_device *phydev) ++{ ++ bool changed; ++ int ss, err; ++ ++ err = genphy_c37_read_status(phydev, &changed); ++ if (err || !changed) ++ return err; ++ ++ /* Read the QCA807x PHY-Specific Status register fiber page, ++ * which indicates the speed and duplex that the PHY is actually ++ * using, irrespective of whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ switch (FIELD_GET(AT803X_SS_SPEED_MASK, ss)) { ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ } ++ ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_read_status(struct phy_device *phydev) ++{ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { ++ switch (phydev->port) { ++ case PORT_FIBRE: ++ return qca807x_read_fiber_status(phydev); ++ case PORT_TP: ++ return at803x_read_status(phydev); ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return at803x_read_status(phydev); ++} ++ ++static int qca807x_phy_package_probe_once(struct phy_device *phydev) ++{ ++ struct phy_package_shared *shared = phydev->shared; ++ struct qca807x_shared_priv *priv = shared->priv; ++ unsigned int tx_drive_strength; ++ const char *package_mode_name; ++ ++ /* Default to 600mw if not defined */ ++ if (of_property_read_u32(shared->np, "qcom,tx-drive-strength-milliwatt", ++ &tx_drive_strength)) ++ tx_drive_strength = 600; ++ ++ switch (tx_drive_strength) { ++ case 140: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_140MV; ++ break; ++ case 160: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_160MV; ++ break; ++ case 180: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_180MV; ++ break; ++ case 200: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_200MV; ++ break; ++ case 220: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_220MV; ++ break; ++ case 240: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_240MV; ++ break; ++ case 260: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_260MV; ++ break; ++ case 280: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_280MV; ++ break; ++ case 300: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_300MV; ++ break; ++ case 320: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_320MV; ++ break; ++ case 400: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_400MV; ++ break; ++ case 500: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_500MV; ++ break; ++ case 600: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_600MV; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ priv->package_mode = PHY_INTERFACE_MODE_NA; ++ if (!of_property_read_string(shared->np, "qcom,package-mode", ++ &package_mode_name)) { ++ if (!strcasecmp(package_mode_name, ++ phy_modes(PHY_INTERFACE_MODE_PSGMII))) ++ priv->package_mode = PHY_INTERFACE_MODE_PSGMII; ++ else if (!strcasecmp(package_mode_name, ++ phy_modes(PHY_INTERFACE_MODE_QSGMII))) ++ priv->package_mode = PHY_INTERFACE_MODE_QSGMII; ++ else ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_phy_package_config_init_once(struct phy_device *phydev) ++{ ++ struct phy_package_shared *shared = phydev->shared; ++ struct qca807x_shared_priv *priv = shared->priv; ++ int val, ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ++ /* Set correct PHY package mode */ ++ val = __phy_package_read(phydev, QCA807X_COMBO_ADDR, ++ QCA807X_CHIP_CONFIGURATION); ++ val &= ~QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK; ++ /* package_mode can be QSGMII or PSGMII and we validate ++ * this in probe_once. ++ * With package_mode to NA, we default to PSGMII. ++ */ ++ switch (priv->package_mode) { ++ case PHY_INTERFACE_MODE_QSGMII: ++ val |= QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII; ++ break; ++ case PHY_INTERFACE_MODE_PSGMII: ++ default: ++ val |= QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER; ++ } ++ ret = __phy_package_write(phydev, QCA807X_COMBO_ADDR, ++ QCA807X_CHIP_CONFIGURATION, val); ++ if (ret) ++ goto exit; ++ ++ /* After mode change Serdes reset is required */ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG); ++ val &= ~PQSGMII_ANALOG_SW_RESET; ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG, val); ++ if (ret) ++ goto exit; ++ ++ msleep(SERDES_RESET_SLEEP); ++ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG); ++ val |= PQSGMII_ANALOG_SW_RESET; ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG, val); ++ if (ret) ++ goto exit; ++ ++ /* Workaround to enable AZ transmitting ability */ ++ val = __phy_package_read_mmd(phydev, QCA807X_PQSGMII_ADDR, ++ MDIO_MMD_PMAPMD, PQSGMII_MODE_CTRL); ++ val &= ~PQSGMII_MODE_CTRL_AZ_WORKAROUND_MASK; ++ ret = __phy_package_write_mmd(phydev, QCA807X_PQSGMII_ADDR, ++ MDIO_MMD_PMAPMD, PQSGMII_MODE_CTRL, val); ++ if (ret) ++ goto exit; ++ ++ /* Set PQSGMII TX AMP strength */ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_DRIVE_CONTROL_1); ++ val &= ~PQSGMII_TX_DRIVER_MASK; ++ val |= FIELD_PREP(PQSGMII_TX_DRIVER_MASK, priv->tx_drive_strength); ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_DRIVE_CONTROL_1, val); ++ if (ret) ++ goto exit; ++ ++ /* Prevent PSGMII going into hibernation via PSGMII self test */ ++ val = __phy_package_read_mmd(phydev, QCA807X_COMBO_ADDR, ++ MDIO_MMD_PCS, PQSGMII_MMD3_SERDES_CONTROL); ++ val &= ~BIT(1); ++ ret = __phy_package_write_mmd(phydev, QCA807X_COMBO_ADDR, ++ MDIO_MMD_PCS, PQSGMII_MMD3_SERDES_CONTROL, val); ++ ++exit: ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; ++ phy_interface_t iface; ++ int ret; ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ ++ sfp_parse_support(phydev->sfp_bus, id, support, interfaces); ++ iface = sfp_select_interface(phydev->sfp_bus, support); ++ ++ dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_100BASEX: ++ /* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */ ++ ret = phy_modify(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, ++ QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); ++ /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ ++ ret = phy_set_bits_mmd(phydev, ++ MDIO_MMD_AN, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN); ++ /* Select fiber page */ ++ ret = phy_clear_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_FIBRE; ++ break; ++ default: ++ dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static void qca807x_sfp_remove(void *upstream) ++{ ++ struct phy_device *phydev = upstream; ++ ++ /* Select copper page */ ++ phy_set_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_TP; ++} ++ ++static const struct sfp_upstream_ops qca807x_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = qca807x_sfp_insert, ++ .module_remove = qca807x_sfp_remove, ++}; ++ ++static int qca807x_probe(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct qca807x_shared_priv *shared_priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct phy_package_shared *shared; ++ struct qca807x_priv *priv; ++ int ret; ++ ++ ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv)); ++ if (ret) ++ return ret; ++ ++ if (phy_package_probe_once(phydev)) { ++ ret = qca807x_phy_package_probe_once(phydev); ++ if (ret) ++ return ret; ++ } ++ ++ shared = phydev->shared; ++ shared_priv = shared->priv; ++ ++ /* Make sure PHY follow PHY package mode if enforced */ ++ if (shared_priv->package_mode != PHY_INTERFACE_MODE_NA && ++ phydev->interface != shared_priv->package_mode) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dac_full_amplitude = of_property_read_bool(node, "qcom,dac-full-amplitude"); ++ priv->dac_full_bias_current = of_property_read_bool(node, "qcom,dac-full-bias-current"); ++ priv->dac_disable_bias_current_tweak = of_property_read_bool(node, ++ "qcom,dac-disable-bias-current-tweak"); ++ ++ if (IS_ENABLED(CONFIG_GPIOLIB)) { ++ /* Do not register a GPIO controller unless flagged for it */ ++ if (of_property_read_bool(node, "gpio-controller")) { ++ ret = qca807x_gpio(phydev); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Attach SFP bus on combo port*/ ++ if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { ++ ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); ++ if (ret) ++ return ret; ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); ++ } ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca807x_config_init(struct phy_device *phydev) ++{ ++ struct qca807x_priv *priv = phydev->priv; ++ u16 control_dac; ++ int ret; ++ ++ if (phy_package_init_once(phydev)) { ++ ret = qca807x_phy_package_config_init_once(phydev); ++ if (ret) ++ return ret; ++ } ++ ++ control_dac = phy_read_mmd(phydev, MDIO_MMD_AN, ++ QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH); ++ control_dac &= ~QCA807X_CONTROL_DAC_MASK; ++ if (!priv->dac_full_amplitude) ++ control_dac |= QCA807X_CONTROL_DAC_DSP_AMPLITUDE; ++ if (!priv->dac_full_amplitude) ++ control_dac |= QCA807X_CONTROL_DAC_DSP_BIAS_CURRENT; ++ if (!priv->dac_disable_bias_current_tweak) ++ control_dac |= QCA807X_CONTROL_DAC_BIAS_CURRENT_TWEAK; ++ return phy_write_mmd(phydev, MDIO_MMD_AN, ++ QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH, ++ control_dac); ++} ++ ++static struct phy_driver qca807x_drivers[] = { ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_QCA8072), ++ .name = "Qualcomm QCA8072", ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca807x_probe, ++ .config_init = qca807x_config_init, ++ .read_status = qca807x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .soft_reset = genphy_soft_reset, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, ++ .cable_test_start = qca807x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ }, ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), ++ .name = "Qualcomm QCA8075", ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca807x_probe, ++ .config_init = qca807x_config_init, ++ .read_status = qca807x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .soft_reset = genphy_soft_reset, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, ++ .cable_test_start = qca807x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ }, ++}; ++module_phy_driver(qca807x_drivers); ++ ++static struct mdio_device_id __maybe_unused qca807x_tbl[] = { ++ { PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) }, ++ { } ++}; ++ ++MODULE_AUTHOR("Robert Marko "); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Qualcomm QCA807x PHY driver"); ++MODULE_DEVICE_TABLE(mdio, qca807x_tbl); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch b/target/linux/generic/backport-6.6/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch new file mode 100644 index 0000000000..cf4d74e8c5 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch @@ -0,0 +1,179 @@ +From ee9d9807bee0e6af8ca2a4db6f0d1dc0e5b41f44 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:11 +0100 +Subject: [PATCH 08/10] net: phy: qcom: move common qca808x LED define to + shared header + +The LED implementation of qca808x and qca807x is the same but qca807x +supports also Fiber port and have different hw control bits for Fiber +port. + +In preparation for qca807x introduction, move all the common define to +shared header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 65 ---------------------------------- + drivers/net/phy/qcom/qcom.h | 65 ++++++++++++++++++++++++++++++++++ + 2 files changed, 65 insertions(+), 65 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -62,29 +62,6 @@ + #define QCA808X_DBG_AN_TEST 0xb + #define QCA808X_HIBERNATION_EN BIT(15) + +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- + #define QCA808X_MMD7_LED2_CTRL 0x8074 + #define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 + #define QCA808X_MMD7_LED1_CTRL 0x8076 +@@ -92,51 +69,9 @@ + #define QCA808X_MMD7_LED0_CTRL 0x8078 + #define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) + +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- + #define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 + #define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) + +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- + #define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a + /* QSDK sets by default 0x46 to this reg that sets BIT 6 for + * LED to active high. It's not clear what BIT 3 and BIT 4 does. +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -103,6 +103,71 @@ + /* Added for reference of existence but should be handled by wait_for_completion already */ + #define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ + #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C + #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B + #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A diff --git a/target/linux/generic/backport-6.6/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch b/target/linux/generic/backport-6.6/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch new file mode 100644 index 0000000000..da73c1d3b8 --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch @@ -0,0 +1,172 @@ +From 47b930d0dd437af927145dba50a2e2ea1ba97c67 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:12 +0100 +Subject: [PATCH 09/10] net: phy: qcom: generalize some qca808x LED functions + +Generalize some qca808x LED functions in preparation for qca807x LED +support. + +The LED implementation of qca808x and qca807x is the same but qca807x +supports also Fiber port and have different hw control bits for Fiber +port. To limit code duplication introduce micro functions that takes reg +instead of LED index to tweak all the supported LED modes. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 38 +++----------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 54 +++++++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 7 ++++ + 3 files changed, 65 insertions(+), 34 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -437,9 +437,7 @@ static int qca808x_led_hw_control_enable + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); ++ return qca808x_led_reg_hw_control_enable(phydev, reg); + } + + static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +@@ -480,16 +478,12 @@ static int qca808x_led_hw_control_set(st + static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) + { + u16 reg; +- int val; + + if (index > 2) + return false; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); ++ return qca808x_led_reg_hw_control_status(phydev, reg); + } + + static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +@@ -557,44 +551,20 @@ static int qca808x_led_brightness_set(st + } + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF)); ++ return qca808x_led_reg_brightness_set(phydev, reg, value); + } + + static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) + { +- int ret; + u16 reg; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; ++ return qca808x_led_reg_blink_set(phydev, reg, delay_on, delay_off); + } + + static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -620,3 +620,57 @@ int qca808x_cable_test_get_status(struct + return 0; + } + EXPORT_SYMBOL_GPL(qca808x_cable_test_get_status); ++ ++int qca808x_led_reg_hw_control_enable(struct phy_device *phydev, u16 reg) ++{ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_hw_control_enable); ++ ++bool qca808x_led_reg_hw_control_status(struct phy_device *phydev, u16 reg) ++{ ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_hw_control_status); ++ ++int qca808x_led_reg_brightness_set(struct phy_device *phydev, ++ u16 reg, enum led_brightness value) ++{ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF)); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_brightness_set); ++ ++int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_blink_set); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -234,3 +234,10 @@ int at803x_cdt_start(struct phy_device * + int at803x_cdt_wait_for_completion(struct phy_device *phydev, + u32 cdt_en); + int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished); ++int qca808x_led_reg_hw_control_enable(struct phy_device *phydev, u16 reg); ++bool qca808x_led_reg_hw_control_status(struct phy_device *phydev, u16 reg); ++int qca808x_led_reg_brightness_set(struct phy_device *phydev, ++ u16 reg, enum led_brightness value); ++int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg, ++ unsigned long *delay_on, ++ unsigned long *delay_off); diff --git a/target/linux/generic/backport-6.6/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch b/target/linux/generic/backport-6.6/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch new file mode 100644 index 0000000000..3bd36f6ffe --- /dev/null +++ b/target/linux/generic/backport-6.6/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch @@ -0,0 +1,326 @@ +From f508a226b517a6a8afd78a317de46bc83e3e3d51 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:13 +0100 +Subject: [PATCH 10/10] net: phy: qca807x: add support for configurable LED + +QCA8072/5 have up to 2 LEDs attached for PHY. + +LEDs can be configured to be ON/hw blink or be set to HW control. + +Hw blink mode is set to blink at 4Hz or 250ms. + +PHY can support both copper (TP) or fiber (FIBRE) kind and supports +different HW control modes based on the port type. + +HW control modes supported for netdev trigger for copper ports are: +- LINK_10 +- LINK_100 +- LINK_1000 +- TX +- RX +- FULL_DUPLEX +- HALF_DUPLEX + +HW control modes supported for netdev trigger for fiber ports are: +- LINK_100 +- LINK_1000 +- TX +- RX +- FULL_DUPLEX +- HALF_DUPLEX + +LED support conflicts with GPIO controller feature and must be disabled +if gpio-controller is used for the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca807x.c | 256 ++++++++++++++++++++++++++++++++- + 1 file changed, 254 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/qcom/qca807x.c ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -57,8 +57,18 @@ + #define QCA807X_MMD7_LED_CTRL(x) (0x8074 + ((x) * 2)) + #define QCA807X_MMD7_LED_FORCE_CTRL(x) (0x8075 + ((x) * 2)) + +-#define QCA807X_GPIO_FORCE_EN BIT(15) +-#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13) ++/* LED hw control pattern for fiber port */ ++#define QCA807X_LED_FIBER_PATTERN_MASK GENMASK(11, 1) ++#define QCA807X_LED_FIBER_TXACT_BLK_EN BIT(10) ++#define QCA807X_LED_FIBER_RXACT_BLK_EN BIT(9) ++#define QCA807X_LED_FIBER_FDX_ON_EN BIT(6) ++#define QCA807X_LED_FIBER_HDX_ON_EN BIT(5) ++#define QCA807X_LED_FIBER_1000BX_ON_EN BIT(2) ++#define QCA807X_LED_FIBER_100FX_ON_EN BIT(1) ++ ++/* Some device repurpose the LED as GPIO out */ ++#define QCA807X_GPIO_FORCE_EN QCA808X_LED_FORCE_EN ++#define QCA807X_GPIO_FORCE_MODE_MASK QCA808X_LED_FORCE_MODE_MASK + + #define QCA807X_FUNCTION_CONTROL 0x10 + #define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5) +@@ -121,6 +131,233 @@ static int qca807x_cable_test_start(stru + return 0; + } + ++static int qca807x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ switch (phydev->port) { ++ case PORT_TP: ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ break; ++ case PORT_FIBRE: ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_TXACT_BLK_EN; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_RXACT_BLK_EN; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_100FX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_1000BX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_HDX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_FDX_ON_EN; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ ++static int qca807x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_hw_control_enable(phydev, reg); ++} ++ ++static int qca807x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ return qca807x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca807x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, mask, offload_trigger = 0; ++ int ret; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ ret = qca807x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca807x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ mask = QCA808X_LED_PATTERN_MASK; ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ mask = QCA807X_LED_FIBER_PATTERN_MASK; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, mask, ++ offload_trigger); ++} ++ ++static bool qca807x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return false; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_hw_control_status(phydev, reg); ++} ++ ++static int qca807x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca807x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ /* Parsing specific to netdev trigger */ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA807X_LED_FIBER_TXACT_BLK_EN) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA807X_LED_FIBER_RXACT_BLK_EN) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA807X_LED_FIBER_100FX_ON_EN) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA807X_LED_FIBER_1000BX_ON_EN) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA807X_LED_FIBER_HDX_ON_EN) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA807X_LED_FIBER_FDX_ON_EN) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg, mask; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ mask = QCA808X_LED_PATTERN_MASK; ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ mask = QCA807X_LED_FIBER_PATTERN_MASK; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, mask); ++} ++ ++static int qca807x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ /* If we are setting off the LED reset any hw control rule */ ++ if (!value) { ++ ret = qca807x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_brightness_set(phydev, reg, value); ++} ++ ++static int qca807x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_blink_set(phydev, reg, delay_on, delay_off); ++} ++ + #ifdef CONFIG_GPIOLIB + static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) + { +@@ -496,6 +733,16 @@ static int qca807x_probe(struct phy_devi + "qcom,dac-disable-bias-current-tweak"); + + if (IS_ENABLED(CONFIG_GPIOLIB)) { ++ /* Make sure we don't have mixed leds node and gpio-controller ++ * to prevent registering leds and having gpio-controller usage ++ * conflicting with them. ++ */ ++ if (of_find_property(node, "leds", NULL) && ++ of_find_property(node, "gpio-controller", NULL)) { ++ phydev_err(phydev, "Invalid property detected. LEDs and gpio-controller are mutually exclusive."); ++ return -EINVAL; ++ } ++ + /* Do not register a GPIO controller unless flagged for it */ + if (of_property_read_bool(node, "gpio-controller")) { + ret = qca807x_gpio(phydev); +@@ -580,6 +827,11 @@ static struct phy_driver qca807x_drivers + .suspend = genphy_suspend, + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .led_brightness_set = qca807x_led_brightness_set, ++ .led_blink_set = qca807x_led_blink_set, ++ .led_hw_is_supported = qca807x_led_hw_is_supported, ++ .led_hw_control_set = qca807x_led_hw_control_set, ++ .led_hw_control_get = qca807x_led_hw_control_get, + }, + }; + module_phy_driver(qca807x_drivers); diff --git a/target/linux/generic/backport-6.6/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch b/target/linux/generic/backport-6.6/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch new file mode 100644 index 0000000000..53652c38fc --- /dev/null +++ b/target/linux/generic/backport-6.6/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch @@ -0,0 +1,51 @@ +From 3be0d950b62852a693182cb678948f481de02825 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 12 Feb 2024 12:49:34 +0100 +Subject: [PATCH] net: phy: qca807x: move interface mode check to + .config_init_once + +Currently, we are checking whether the PHY package mode matches the +individual PHY interface modes at PHY package probe time, but at that time +we only know the PHY package mode and not the individual PHY interface +modes as of_get_phy_mode() that populates it will only get called once the +netdev to which PHY-s are attached to is being probed and thus this check +will always fail and return -EINVAL. + +So, lets move this check to .config_init_once as at that point individual +PHY interface modes should be populated. + +Fixes: d1cb613efbd3 ("net: phy: qcom: add support for QCA807x PHY Family") +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240212115043.1725918-1-robimarko@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/qcom/qca807x.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/qcom/qca807x.c ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -562,6 +562,11 @@ static int qca807x_phy_package_config_in + struct qca807x_shared_priv *priv = shared->priv; + int val, ret; + ++ /* Make sure PHY follow PHY package mode if enforced */ ++ if (priv->package_mode != PHY_INTERFACE_MODE_NA && ++ phydev->interface != priv->package_mode) ++ return -EINVAL; ++ + phy_lock_mdio_bus(phydev); + + /* Set correct PHY package mode */ +@@ -718,11 +723,6 @@ static int qca807x_probe(struct phy_devi + shared = phydev->shared; + shared_priv = shared->priv; + +- /* Make sure PHY follow PHY package mode if enforced */ +- if (shared_priv->package_mode != PHY_INTERFACE_MODE_NA && +- phydev->interface != shared_priv->package_mode) +- return -EINVAL; +- + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; diff --git a/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch b/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch new file mode 100644 index 0000000000..e6a240dbda --- /dev/null +++ b/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch @@ -0,0 +1,205 @@ +From bdce82e960d1205d118662f575cec39379984e34 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 31 Jan 2024 03:26:04 +0100 +Subject: [PATCH] net: mdio: ipq4019: add support for clock-frequency property + +The IPQ4019 MDIO internally divide the clock feed by AHB based on the +MDIO_MODE reg. On reset or power up, the default value for the +divider is 0xff that reflect the divider set to /256. + +This makes the MDC run at a very low rate, that is, considering AHB is +always fixed to 100Mhz, a value of 390KHz. + +This hasn't have been a problem as MDIO wasn't used for time sensitive +operation, it is now that on IPQ807x is usually mounted with PHY that +requires MDIO to load their firmware (example Aquantia PHY). + +To handle this problem and permit to set the correct designed MDC +frequency for the SoC add support for the standard "clock-frequency" +property for the MDIO node. + +The divider supports value from /1 to /256 and the common value are to +set it to /16 to reflect 6.25Mhz or to /8 on newer platform to reflect +12.5Mhz. + +To scan if the requested rate is supported by the divider, loop with +each supported divider and stop when the requested rate match the final +rate with the current divider. An error is returned if the rate doesn't +match any value. + +On MDIO reset, the divider is restored to the requested value to prevent +any kind of downclocking caused by the divider reverting to a default +value. + +To follow 802.3 spec of 2.5MHz of default value, if divider is set at +/256 and "clock-frequency" is not set in DT, assume nobody set the +divider and try to find the closest MDC rate to 2.5MHz. (in the case of +AHB set to 100MHz, it's 1.5625MHz) + +While at is also document other bits of the MDIO_MODE reg to have a +clear idea of what is actually applied there. + +Documentation of some BITs is skipped as they are marked as reserved and +their usage is not clear (RES 11:9 GENPHY 16:13 RES1 19:17) + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/mdio/mdio-ipq4019.c | 109 ++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 6 deletions(-) + +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -14,6 +14,20 @@ + #include + + #define MDIO_MODE_REG 0x40 ++#define MDIO_MODE_MDC_MODE BIT(12) ++/* 0 = Clause 22, 1 = Clause 45 */ ++#define MDIO_MODE_C45 BIT(8) ++#define MDIO_MODE_DIV_MASK GENMASK(7, 0) ++#define MDIO_MODE_DIV(x) FIELD_PREP(MDIO_MODE_DIV_MASK, (x) - 1) ++#define MDIO_MODE_DIV_1 0x0 ++#define MDIO_MODE_DIV_2 0x1 ++#define MDIO_MODE_DIV_4 0x3 ++#define MDIO_MODE_DIV_8 0x7 ++#define MDIO_MODE_DIV_16 0xf ++#define MDIO_MODE_DIV_32 0x1f ++#define MDIO_MODE_DIV_64 0x3f ++#define MDIO_MODE_DIV_128 0x7f ++#define MDIO_MODE_DIV_256 0xff + #define MDIO_ADDR_REG 0x44 + #define MDIO_DATA_WRITE_REG 0x48 + #define MDIO_DATA_READ_REG 0x4c +@@ -26,9 +40,6 @@ + #define MDIO_CMD_ACCESS_CODE_C45_WRITE 1 + #define MDIO_CMD_ACCESS_CODE_C45_READ 2 + +-/* 0 = Clause 22, 1 = Clause 45 */ +-#define MDIO_MODE_C45 BIT(8) +- + #define IPQ4019_MDIO_TIMEOUT 10000 + #define IPQ4019_MDIO_SLEEP 10 + +@@ -41,6 +52,7 @@ struct ipq4019_mdio_data { + void __iomem *membase; + void __iomem *eth_ldo_rdy; + struct clk *mdio_clk; ++ unsigned int mdc_rate; + }; + + static int ipq4019_mdio_wait_busy(struct mii_bus *bus) +@@ -179,6 +191,38 @@ static int ipq4019_mdio_write(struct mii + return 0; + } + ++static int ipq4019_mdio_set_div(struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* MDC rate is ahb_rate/(MDIO_MODE_DIV + 1) ++ * While supported, internal documentation doesn't ++ * assure correct functionality of the MDIO bus ++ * with divider of 1, 2 or 4. ++ */ ++ for (div = 8; div <= 256; div *= 2) { ++ /* The requested rate is supported by the div */ ++ if (priv->mdc_rate == DIV_ROUND_UP(ahb_rate, div)) { ++ val = readl(priv->membase + MDIO_MODE_REG); ++ val &= ~MDIO_MODE_DIV_MASK; ++ val |= MDIO_MODE_DIV(div); ++ writel(val, priv->membase + MDIO_MODE_REG); ++ ++ return 0; ++ } ++ } ++ ++ /* The requested rate is not supported */ ++ return -EINVAL; ++} ++ + static int ipq_mdio_reset(struct mii_bus *bus) + { + struct ipq4019_mdio_data *priv = bus->priv; +@@ -201,10 +245,58 @@ static int ipq_mdio_reset(struct mii_bus + return ret; + + ret = clk_prepare_enable(priv->mdio_clk); +- if (ret == 0) +- mdelay(10); ++ if (ret) ++ return ret; ++ ++ mdelay(10); + +- return ret; ++ /* Restore MDC rate */ ++ return ipq4019_mdio_set_div(priv); ++} ++ ++static void ipq4019_mdio_select_mdc_rate(struct platform_device *pdev, ++ struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* MDC rate defined in DT, we don't have to decide a default value */ ++ if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &priv->mdc_rate)) ++ return; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* Check what is the current div set */ ++ val = readl(priv->membase + MDIO_MODE_REG); ++ div = FIELD_GET(MDIO_MODE_DIV_MASK, val); ++ ++ /* div is not set to the default value of /256 ++ * Probably someone changed that (bootloader, other drivers) ++ * Keep this and don't overwrite it. ++ */ ++ if (div != MDIO_MODE_DIV_256) { ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div + 1); ++ return; ++ } ++ ++ /* If div is /256 assume nobody have set this value and ++ * try to find one MDC rate that is close the 802.3 spec of ++ * 2.5MHz ++ */ ++ for (div = 256; div >= 8; div /= 2) { ++ /* Stop as soon as we found a divider that ++ * reached the closest value to 2.5MHz ++ */ ++ if (DIV_ROUND_UP(ahb_rate, div) > 2500000) ++ break; ++ ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div); ++ } + } + + static int ipq4019_mdio_probe(struct platform_device *pdev) +@@ -228,6 +320,11 @@ static int ipq4019_mdio_probe(struct pla + if (IS_ERR(priv->mdio_clk)) + return PTR_ERR(priv->mdio_clk); + ++ ipq4019_mdio_select_mdc_rate(pdev, priv); ++ ret = ipq4019_mdio_set_div(priv); ++ if (ret) ++ return ret; ++ + /* The platform resource is provided on the chipset IPQ5018 */ + /* This resource is optional */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/target/linux/generic/backport-6.6/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch b/target/linux/generic/backport-6.6/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch new file mode 100644 index 0000000000..d32a7edf93 --- /dev/null +++ b/target/linux/generic/backport-6.6/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch @@ -0,0 +1,92 @@ +From 7edce370d87a23e8ed46af5b76a9fef1e341b67b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 28 Nov 2023 14:59:28 +0100 +Subject: [PATCH] net: phy: aquantia: drop wrong endianness conversion for addr + and CRC + +On further testing on BE target with kernel test robot, it was notice +that the endianness conversion for addr and CRC in fw_load_memory was +wrong. + +Drop the cpu_to_le32 conversion for addr load as it's not needed. + +Use get_unaligned_le32 instead of get_unaligned for FW data word load to +correctly convert data in the correct order to follow system endian. + +Also drop the cpu_to_be32 for CRC calculation as it's wrong and would +cause different CRC on BE system. +The loaded word is swapped internally and MAILBOX calculates the CRC on +the swapped word. To correctly calculate the CRC to be later matched +with the one from MAILBOX, use an u8 struct and swap the word there to +keep the same order on both LE and BE for crc_ccitt_false function. +Also add additional comments on how the CRC verification for the loaded +section works. + +CRC is calculated as we load the section and verified with the MAILBOX +only after the entire section is loaded to skip additional slowdown by +loop the section data again. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202311210414.sEJZjlcD-lkp@intel.com/ +Fixes: e93984ebc1c8 ("net: phy: aquantia: add firmware load support") +Tested-by: Robert Marko # ipq8072 LE device +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20231128135928.9841-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/aquantia/aquantia_firmware.c | 24 ++++++++++++-------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia_firmware.c ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -93,9 +93,6 @@ static int aqr_fw_load_memory(struct phy + u16 crc = 0, up_crc; + size_t pos; + +- /* PHY expect addr in LE */ +- addr = (__force u32)cpu_to_le32(addr); +- + phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_MAILBOX_INTERFACE1, + VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); +@@ -110,10 +107,11 @@ static int aqr_fw_load_memory(struct phy + * If a firmware that is not word aligned is found, please report upstream. + */ + for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u8 crc_data[4]; + u32 word; + + /* FW data is always stored in little-endian */ +- word = get_unaligned((const u32 *)(data + pos)); ++ word = get_unaligned_le32((const u32 *)(data + pos)); + + phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, + VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); +@@ -124,15 +122,21 @@ static int aqr_fw_load_memory(struct phy + VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | + VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); + +- /* calculate CRC as we load data to the mailbox. +- * We convert word to big-endian as PHY is BE and mailbox will +- * return a BE CRC. ++ /* Word is swapped internally and MAILBOX CRC is calculated ++ * using big-endian order. Mimic what the PHY does to have a ++ * matching CRC... + */ +- word = (__force u32)cpu_to_be32(word); +- crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); +- } ++ crc_data[0] = word >> 24; ++ crc_data[1] = word >> 16; ++ crc_data[2] = word >> 8; ++ crc_data[3] = word; + ++ /* ...calculate CRC as we load data... */ ++ crc = crc_ccitt_false(crc, crc_data, sizeof(crc_data)); ++ } ++ /* ...gets CRC from MAILBOX after we have loaded the entire section... */ + up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ /* ...and make sure it does match our calculated CRC */ + if (crc != up_crc) { + phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", + crc, up_crc); diff --git a/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch b/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch new file mode 100644 index 0000000000..816aa67787 --- /dev/null +++ b/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch @@ -0,0 +1,26 @@ +From 1b9827ceab08450308f7971d6fd700ec88b6ce67 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 3 Dec 2022 14:20:37 +0100 +Subject: [PATCH 098/250] net: mtk_eth_soc: enable flow offload support for + MT7986 SoC + +Since Wireless Ethernet Dispatcher is now available for mt7986 in mt76, +enable hw flow support for MT7986 SoC. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/fdcaacd827938e6a8c4aa1ac2c13e46d2c08c821.1670072898.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4333,6 +4333,7 @@ static const struct mtk_soc_data mt7986_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7986_CLKS_BITMAP, + .required_pctl = false, ++ .offload_version = 2, + .hash_offset = 4, + .foe_entry_size = sizeof(struct mtk_foe_entry), + .txrx = { diff --git a/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch b/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch new file mode 100644 index 0000000000..c48613929d --- /dev/null +++ b/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch @@ -0,0 +1,591 @@ +From: Sujuan Chen +Date: Sat, 5 Nov 2022 23:36:18 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: introduce wed mcu support + +Introduce WED mcu support used to configure WED WO chip. +This is a preliminary patch in order to add RX Wireless +Ethernet Dispatch available on MT7986 SoC. + +Tested-by: Daniel Golle +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: David S. Miller +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h + +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -5,7 +5,7 @@ + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o + mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o +-mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o + ifdef CONFIG_DEBUG_FS + mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o + endif +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -0,0 +1,359 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2022 MediaTek Inc. ++ * ++ * Author: Lorenzo Bianconi ++ * Sujuan Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "mtk_wed_regs.h" ++#include "mtk_wed_wo.h" ++#include "mtk_wed.h" ++ ++static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) ++{ ++ return readl(wo->boot.addr + reg); ++} ++ ++static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) ++{ ++ writel(val, wo->boot.addr + reg); ++} ++ ++static struct sk_buff * ++mtk_wed_mcu_msg_alloc(const void *data, int data_len) ++{ ++ int length = sizeof(struct mtk_wed_mcu_hdr) + data_len; ++ struct sk_buff *skb; ++ ++ skb = alloc_skb(length, GFP_KERNEL); ++ if (!skb) ++ return NULL; ++ ++ memset(skb->head, 0, length); ++ skb_reserve(skb, sizeof(struct mtk_wed_mcu_hdr)); ++ if (data && data_len) ++ skb_put_data(skb, data, data_len); ++ ++ return skb; ++} ++ ++static struct sk_buff * ++mtk_wed_mcu_get_response(struct mtk_wed_wo *wo, unsigned long expires) ++{ ++ if (!time_is_after_jiffies(expires)) ++ return NULL; ++ ++ wait_event_timeout(wo->mcu.wait, !skb_queue_empty(&wo->mcu.res_q), ++ expires - jiffies); ++ return skb_dequeue(&wo->mcu.res_q); ++} ++ ++void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb) ++{ ++ skb_queue_tail(&wo->mcu.res_q, skb); ++ wake_up(&wo->mcu.wait); ++} ++ ++void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, ++ struct sk_buff *skb) ++{ ++ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ ++ switch (hdr->cmd) { ++ case MTK_WED_WO_EVT_LOG_DUMP: { ++ const char *msg = (const char *)(skb->data + sizeof(*hdr)); ++ ++ dev_notice(wo->hw->dev, "%s\n", msg); ++ break; ++ } ++ case MTK_WED_WO_EVT_PROFILING: { ++ struct mtk_wed_wo_log_info *info; ++ u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); ++ int i; ++ ++ info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); ++ for (i = 0 ; i < count ; i++) ++ dev_notice(wo->hw->dev, ++ "SN:%u latency: total=%u, rro:%u, mod:%u\n", ++ le32_to_cpu(info[i].sn), ++ le32_to_cpu(info[i].total), ++ le32_to_cpu(info[i].rro), ++ le32_to_cpu(info[i].mod)); ++ break; ++ } ++ case MTK_WED_WO_EVT_RXCNT_INFO: ++ break; ++ default: ++ break; ++ } ++ ++ dev_kfree_skb(skb); ++} ++ ++static int ++mtk_wed_mcu_skb_send_msg(struct mtk_wed_wo *wo, struct sk_buff *skb, ++ int id, int cmd, u16 *wait_seq, bool wait_resp) ++{ ++ struct mtk_wed_mcu_hdr *hdr; ++ ++ /* TODO: make it dynamic based on cmd */ ++ wo->mcu.timeout = 20 * HZ; ++ ++ hdr = (struct mtk_wed_mcu_hdr *)skb_push(skb, sizeof(*hdr)); ++ hdr->cmd = cmd; ++ hdr->length = cpu_to_le16(skb->len); ++ ++ if (wait_resp && wait_seq) { ++ u16 seq = ++wo->mcu.seq; ++ ++ if (!seq) ++ seq = ++wo->mcu.seq; ++ *wait_seq = seq; ++ ++ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_NEED_RSP); ++ hdr->seq = cpu_to_le16(seq); ++ } ++ if (id == MTK_WED_MODULE_ID_WO) ++ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); ++ ++ dev_kfree_skb(skb); ++ return 0; ++} ++ ++static int ++mtk_wed_mcu_parse_response(struct mtk_wed_wo *wo, struct sk_buff *skb, ++ int cmd, int seq) ++{ ++ struct mtk_wed_mcu_hdr *hdr; ++ ++ if (!skb) { ++ dev_err(wo->hw->dev, "Message %08x (seq %d) timeout\n", ++ cmd, seq); ++ return -ETIMEDOUT; ++ } ++ ++ hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ if (le16_to_cpu(hdr->seq) != seq) ++ return -EAGAIN; ++ ++ skb_pull(skb, sizeof(*hdr)); ++ switch (cmd) { ++ case MTK_WED_WO_CMD_RXCNT_INFO: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, ++ const void *data, int len, bool wait_resp) ++{ ++ unsigned long expires; ++ struct sk_buff *skb; ++ u16 seq; ++ int ret; ++ ++ skb = mtk_wed_mcu_msg_alloc(data, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ mutex_lock(&wo->mcu.mutex); ++ ++ ret = mtk_wed_mcu_skb_send_msg(wo, skb, id, cmd, &seq, wait_resp); ++ if (ret || !wait_resp) ++ goto unlock; ++ ++ expires = jiffies + wo->mcu.timeout; ++ do { ++ skb = mtk_wed_mcu_get_response(wo, expires); ++ ret = mtk_wed_mcu_parse_response(wo, skb, cmd, seq); ++ dev_kfree_skb(skb); ++ } while (ret == -EAGAIN); ++ ++unlock: ++ mutex_unlock(&wo->mcu.mutex); ++ ++ return ret; ++} ++ ++static int ++mtk_wed_get_memory_region(struct mtk_wed_wo *wo, ++ struct mtk_wed_wo_memory_region *region) ++{ ++ struct reserved_mem *rmem; ++ struct device_node *np; ++ int index; ++ ++ index = of_property_match_string(wo->hw->node, "memory-region-names", ++ region->name); ++ if (index < 0) ++ return index; ++ ++ np = of_parse_phandle(wo->hw->node, "memory-region", index); ++ if (!np) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(np); ++ of_node_put(np); ++ ++ if (!rmem) ++ return -ENODEV; ++ ++ region->phy_addr = rmem->base; ++ region->size = rmem->size; ++ region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); ++ ++ return !region->addr ? -EINVAL : 0; ++} ++ ++static int ++mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw, ++ struct mtk_wed_wo_memory_region *region) ++{ ++ const u8 *first_region_ptr, *region_ptr, *trailer_ptr, *ptr = fw->data; ++ const struct mtk_wed_fw_trailer *trailer; ++ const struct mtk_wed_fw_region *fw_region; ++ ++ trailer_ptr = fw->data + fw->size - sizeof(*trailer); ++ trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; ++ region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); ++ first_region_ptr = region_ptr; ++ ++ while (region_ptr < trailer_ptr) { ++ u32 length; ++ ++ fw_region = (const struct mtk_wed_fw_region *)region_ptr; ++ length = le32_to_cpu(fw_region->len); ++ ++ if (region->phy_addr != le32_to_cpu(fw_region->addr)) ++ goto next; ++ ++ if (region->size < length) ++ goto next; ++ ++ if (first_region_ptr < ptr + length) ++ goto next; ++ ++ if (region->shared && region->consumed) ++ return 0; ++ ++ if (!region->shared || !region->consumed) { ++ memcpy_toio(region->addr, ptr, length); ++ region->consumed = true; ++ return 0; ++ } ++next: ++ region_ptr += sizeof(*fw_region); ++ ptr += length; ++ } ++ ++ return -EINVAL; ++} ++ ++static int ++mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) ++{ ++ static struct mtk_wed_wo_memory_region mem_region[] = { ++ [MTK_WED_WO_REGION_EMI] = { ++ .name = "wo-emi", ++ }, ++ [MTK_WED_WO_REGION_ILM] = { ++ .name = "wo-ilm", ++ }, ++ [MTK_WED_WO_REGION_DATA] = { ++ .name = "wo-data", ++ .shared = true, ++ }, ++ }; ++ const struct mtk_wed_fw_trailer *trailer; ++ const struct firmware *fw; ++ const char *fw_name; ++ u32 val, boot_cr; ++ int ret, i; ++ ++ /* load firmware region metadata */ ++ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { ++ ret = mtk_wed_get_memory_region(wo, &mem_region[i]); ++ if (ret) ++ return ret; ++ } ++ ++ wo->boot.name = "wo-boot"; ++ ret = mtk_wed_get_memory_region(wo, &wo->boot); ++ if (ret) ++ return ret; ++ ++ /* set dummy cr */ ++ wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, ++ wo->hw->index + 1); ++ ++ /* load firmware */ ++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; ++ ret = request_firmware(&fw, fw_name, wo->hw->dev); ++ if (ret) ++ return ret; ++ ++ trailer = (void *)(fw->data + fw->size - ++ sizeof(struct mtk_wed_fw_trailer)); ++ dev_info(wo->hw->dev, ++ "MTK WED WO Firmware Version: %.10s, Build Time: %.15s\n", ++ trailer->fw_ver, trailer->build_date); ++ dev_info(wo->hw->dev, "MTK WED WO Chip ID %02x Region %d\n", ++ trailer->chip_id, trailer->num_region); ++ ++ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { ++ ret = mtk_wed_mcu_run_firmware(wo, fw, &mem_region[i]); ++ if (ret) ++ goto out; ++ } ++ ++ /* set the start address */ ++ boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR ++ : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; ++ wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); ++ /* wo firmware reset */ ++ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); ++ ++ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); ++ val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK ++ : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; ++ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); ++out: ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++static u32 ++mtk_wed_mcu_read_fw_dl(struct mtk_wed_wo *wo) ++{ ++ return wed_r32(wo->hw->wed_dev, ++ MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL); ++} ++ ++int mtk_wed_mcu_init(struct mtk_wed_wo *wo) ++{ ++ u32 val; ++ int ret; ++ ++ skb_queue_head_init(&wo->mcu.res_q); ++ init_waitqueue_head(&wo->mcu.wait); ++ mutex_init(&wo->mcu.mutex); ++ ++ ret = mtk_wed_mcu_load_firmware(wo); ++ if (ret) ++ return ret; ++ ++ return readx_poll_timeout(mtk_wed_mcu_read_fw_dl, wo, val, !val, ++ 100, MTK_FW_DL_TIMEOUT); ++} ++ ++MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); ++MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -152,6 +152,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) + ++#define MTK_WED_SCR0 0x3c0 + #define MTK_WED_WPDMA_INT_TRIGGER 0x504 + #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) + #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -0,0 +1,150 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Copyright (C) 2022 Lorenzo Bianconi */ ++ ++#ifndef __MTK_WED_WO_H ++#define __MTK_WED_WO_H ++ ++#include ++#include ++ ++struct mtk_wed_hw; ++ ++struct mtk_wed_mcu_hdr { ++ /* DW0 */ ++ u8 version; ++ u8 cmd; ++ __le16 length; ++ ++ /* DW1 */ ++ __le16 seq; ++ __le16 flag; ++ ++ /* DW2 */ ++ __le32 status; ++ ++ /* DW3 */ ++ u8 rsv[20]; ++}; ++ ++struct mtk_wed_wo_log_info { ++ __le32 sn; ++ __le32 total; ++ __le32 rro; ++ __le32 mod; ++}; ++ ++enum mtk_wed_wo_event { ++ MTK_WED_WO_EVT_LOG_DUMP = 0x1, ++ MTK_WED_WO_EVT_PROFILING = 0x2, ++ MTK_WED_WO_EVT_RXCNT_INFO = 0x3, ++}; ++ ++#define MTK_WED_MODULE_ID_WO 1 ++#define MTK_FW_DL_TIMEOUT 4000000 /* us */ ++#define MTK_WOCPU_TIMEOUT 2000000 /* us */ ++ ++enum { ++ MTK_WED_WARP_CMD_FLAG_RSP = BIT(0), ++ MTK_WED_WARP_CMD_FLAG_NEED_RSP = BIT(1), ++ MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), ++}; ++ ++enum { ++ MTK_WED_WO_REGION_EMI, ++ MTK_WED_WO_REGION_ILM, ++ MTK_WED_WO_REGION_DATA, ++ MTK_WED_WO_REGION_BOOT, ++ __MTK_WED_WO_REGION_MAX, ++}; ++ ++enum mtk_wed_dummy_cr_idx { ++ MTK_WED_DUMMY_CR_FWDL, ++ MTK_WED_DUMMY_CR_WO_STATUS, ++}; ++ ++#define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" ++#define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" ++ ++#define MTK_WO_MCU_CFG_LS_BASE 0 ++#define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) ++#define MTK_WO_MCU_CFG_LS_FW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x004) ++#define MTK_WO_MCU_CFG_LS_CFG_DBG1_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x00c) ++#define MTK_WO_MCU_CFG_LS_CFG_DBG2_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x010) ++#define MTK_WO_MCU_CFG_LS_WF_MCCR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x014) ++#define MTK_WO_MCU_CFG_LS_WF_MCCR_SET_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x018) ++#define MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x01c) ++#define MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x050) ++#define MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x060) ++#define MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x064) ++ ++#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) ++#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) ++ ++struct mtk_wed_wo_memory_region { ++ const char *name; ++ void __iomem *addr; ++ phys_addr_t phy_addr; ++ u32 size; ++ bool shared:1; ++ bool consumed:1; ++}; ++ ++struct mtk_wed_fw_region { ++ __le32 decomp_crc; ++ __le32 decomp_len; ++ __le32 decomp_blk_sz; ++ u8 rsv0[4]; ++ __le32 addr; ++ __le32 len; ++ u8 feature_set; ++ u8 rsv1[15]; ++} __packed; ++ ++struct mtk_wed_fw_trailer { ++ u8 chip_id; ++ u8 eco_code; ++ u8 num_region; ++ u8 format_ver; ++ u8 format_flag; ++ u8 rsv[2]; ++ char fw_ver[10]; ++ char build_date[15]; ++ u32 crc; ++}; ++ ++struct mtk_wed_wo { ++ struct mtk_wed_hw *hw; ++ struct mtk_wed_wo_memory_region boot; ++ ++ struct { ++ struct mutex mutex; ++ int timeout; ++ u16 seq; ++ ++ struct sk_buff_head res_q; ++ wait_queue_head_t wait; ++ } mcu; ++}; ++ ++static inline int ++mtk_wed_mcu_check_msg(struct mtk_wed_wo *wo, struct sk_buff *skb) ++{ ++ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ ++ if (hdr->version) ++ return -EINVAL; ++ ++ if (skb->len < sizeof(*hdr) || skb->len != le16_to_cpu(hdr->length)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb); ++void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, ++ struct sk_buff *skb); ++int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, ++ const void *data, int len, bool wait_resp); ++int mtk_wed_mcu_init(struct mtk_wed_wo *wo); ++ ++#endif /* __MTK_WED_WO_H */ +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -11,6 +11,35 @@ + struct mtk_wed_hw; + struct mtk_wdma_desc; + ++enum mtk_wed_wo_cmd { ++ MTK_WED_WO_CMD_WED_CFG, ++ MTK_WED_WO_CMD_WED_RX_STAT, ++ MTK_WED_WO_CMD_RRO_SER, ++ MTK_WED_WO_CMD_DBG_INFO, ++ MTK_WED_WO_CMD_DEV_INFO, ++ MTK_WED_WO_CMD_BSS_INFO, ++ MTK_WED_WO_CMD_STA_REC, ++ MTK_WED_WO_CMD_DEV_INFO_DUMP, ++ MTK_WED_WO_CMD_BSS_INFO_DUMP, ++ MTK_WED_WO_CMD_STA_REC_DUMP, ++ MTK_WED_WO_CMD_BA_INFO_DUMP, ++ MTK_WED_WO_CMD_FBCMD_Q_DUMP, ++ MTK_WED_WO_CMD_FW_LOG_CTRL, ++ MTK_WED_WO_CMD_LOG_FLUSH, ++ MTK_WED_WO_CMD_CHANGE_STATE, ++ MTK_WED_WO_CMD_CPU_STATS_ENABLE, ++ MTK_WED_WO_CMD_CPU_STATS_DUMP, ++ MTK_WED_WO_CMD_EXCEPTION_INIT, ++ MTK_WED_WO_CMD_PROF_CTRL, ++ MTK_WED_WO_CMD_STA_BA_DUMP, ++ MTK_WED_WO_CMD_BA_CTRL_DUMP, ++ MTK_WED_WO_CMD_RXCNT_CTRL, ++ MTK_WED_WO_CMD_RXCNT_INFO, ++ MTK_WED_WO_CMD_SET_CAP, ++ MTK_WED_WO_CMD_CCIF_RING_DUMP, ++ MTK_WED_WO_CMD_WED_END ++}; ++ + enum mtk_wed_bus_tye { + MTK_WED_BUS_PCIE, + MTK_WED_BUS_AXI, diff --git a/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch new file mode 100644 index 0000000000..fd5f45df2a --- /dev/null +++ b/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch @@ -0,0 +1,737 @@ +From: Lorenzo Bianconi +Date: Sat, 5 Nov 2022 23:36:19 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: introduce wed wo support + +Introduce WO chip support to mtk wed driver. MTK WED WO is used to +implement RX Wireless Ethernet Dispatch and offload traffic received by +wlan nic to the wired interface. + +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c + +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -5,7 +5,7 @@ + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o + mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o +-mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.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 + endif +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -16,6 +16,7 @@ + #include "mtk_wed_regs.h" + #include "mtk_wed.h" + #include "mtk_ppe.h" ++#include "mtk_wed_wo.h" + + #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) + +@@ -355,6 +356,8 @@ mtk_wed_detach(struct mtk_wed_device *de + + mtk_wed_free_buffer(dev); + mtk_wed_free_tx_rings(dev); ++ if (hw->version != 1) ++ mtk_wed_wo_deinit(hw); + + if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { + struct device_node *wlan_node; +@@ -878,9 +881,11 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (hw->hifsys) ++ if (hw->version == 1) + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); ++ else ++ ret = mtk_wed_wo_init(hw); + + out: + mutex_unlock(&hw_lock); +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -10,6 +10,7 @@ + #include + + struct mtk_eth; ++struct mtk_wed_wo; + + struct mtk_wed_hw { + struct device_node *node; +@@ -22,6 +23,7 @@ struct mtk_wed_hw { + struct regmap *mirror; + struct dentry *debugfs_dir; + struct mtk_wed_device *wed_dev; ++ struct mtk_wed_wo *wed_wo; + u32 debugfs_reg; + u32 num_flows; + u8 version; +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -122,8 +122,7 @@ mtk_wed_mcu_skb_send_msg(struct mtk_wed_ + if (id == MTK_WED_MODULE_ID_WO) + hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); + +- dev_kfree_skb(skb); +- return 0; ++ return mtk_wed_wo_queue_tx_skb(wo, &wo->q_tx, skb); + } + + static int +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c +@@ -0,0 +1,508 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2022 MediaTek Inc. ++ * ++ * Author: Lorenzo Bianconi ++ * Sujuan Chen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mtk_wed.h" ++#include "mtk_wed_regs.h" ++#include "mtk_wed_wo.h" ++ ++static u32 ++mtk_wed_mmio_r32(struct mtk_wed_wo *wo, u32 reg) ++{ ++ u32 val; ++ ++ if (regmap_read(wo->mmio.regs, reg, &val)) ++ val = ~0; ++ ++ return val; ++} ++ ++static void ++mtk_wed_mmio_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) ++{ ++ regmap_write(wo->mmio.regs, reg, val); ++} ++ ++static u32 ++mtk_wed_wo_get_isr(struct mtk_wed_wo *wo) ++{ ++ u32 val = mtk_wed_mmio_r32(wo, MTK_WED_WO_CCIF_RCHNUM); ++ ++ return val & MTK_WED_WO_CCIF_RCHNUM_MASK; ++} ++ ++static void ++mtk_wed_wo_set_isr(struct mtk_wed_wo *wo, u32 mask) ++{ ++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_IRQ0_MASK, mask); ++} ++ ++static void ++mtk_wed_wo_set_ack(struct mtk_wed_wo *wo, u32 mask) ++{ ++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_ACK, mask); ++} ++ ++static void ++mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, u32 mask, u32 val, bool set) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wo->mmio.lock, flags); ++ wo->mmio.irq_mask &= ~mask; ++ wo->mmio.irq_mask |= val; ++ if (set) ++ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); ++ spin_unlock_irqrestore(&wo->mmio.lock, flags); ++} ++ ++static void ++mtk_wed_wo_irq_enable(struct mtk_wed_wo *wo, u32 mask) ++{ ++ mtk_wed_wo_set_isr_mask(wo, 0, mask, false); ++ tasklet_schedule(&wo->mmio.irq_tasklet); ++} ++ ++static void ++mtk_wed_wo_irq_disable(struct mtk_wed_wo *wo, u32 mask) ++{ ++ mtk_wed_wo_set_isr_mask(wo, mask, 0, true); ++} ++ ++static void ++mtk_wed_wo_kickout(struct mtk_wed_wo *wo) ++{ ++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_BUSY, 1 << MTK_WED_WO_TXCH_NUM); ++ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_TCHNUM, MTK_WED_WO_TXCH_NUM); ++} ++ ++static void ++mtk_wed_wo_queue_kick(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, ++ u32 val) ++{ ++ wmb(); ++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, val); ++} ++ ++static void * ++mtk_wed_wo_dequeue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, u32 *len, ++ bool flush) ++{ ++ int buf_len = SKB_WITH_OVERHEAD(q->buf_size); ++ int index = (q->tail + 1) % q->n_desc; ++ struct mtk_wed_wo_queue_entry *entry; ++ struct mtk_wed_wo_queue_desc *desc; ++ void *buf; ++ ++ if (!q->queued) ++ return NULL; ++ ++ if (flush) ++ q->desc[index].ctrl |= cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE); ++ else if (!(q->desc[index].ctrl & cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE))) ++ return NULL; ++ ++ q->tail = index; ++ q->queued--; ++ ++ desc = &q->desc[index]; ++ entry = &q->entry[index]; ++ buf = entry->buf; ++ if (len) ++ *len = FIELD_GET(MTK_WED_WO_CTL_SD_LEN0, ++ le32_to_cpu(READ_ONCE(desc->ctrl))); ++ if (buf) ++ dma_unmap_single(wo->hw->dev, entry->addr, buf_len, ++ DMA_FROM_DEVICE); ++ entry->buf = NULL; ++ ++ return buf; ++} ++ ++static int ++mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, ++ gfp_t gfp, bool rx) ++{ ++ enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ int n_buf = 0; ++ ++ spin_lock_bh(&q->lock); ++ while (q->queued < q->n_desc) { ++ void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); ++ struct mtk_wed_wo_queue_entry *entry; ++ dma_addr_t addr; ++ ++ if (!buf) ++ break; ++ ++ addr = dma_map_single(wo->hw->dev, buf, q->buf_size, dir); ++ if (unlikely(dma_mapping_error(wo->hw->dev, addr))) { ++ skb_free_frag(buf); ++ break; ++ } ++ ++ q->head = (q->head + 1) % q->n_desc; ++ entry = &q->entry[q->head]; ++ entry->addr = addr; ++ entry->len = q->buf_size; ++ q->entry[q->head].buf = buf; ++ ++ if (rx) { ++ struct mtk_wed_wo_queue_desc *desc = &q->desc[q->head]; ++ u32 ctrl = MTK_WED_WO_CTL_LAST_SEC0 | ++ FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, ++ entry->len); ++ ++ WRITE_ONCE(desc->buf0, cpu_to_le32(addr)); ++ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); ++ } ++ q->queued++; ++ n_buf++; ++ } ++ spin_unlock_bh(&q->lock); ++ ++ return n_buf; ++} ++ ++static void ++mtk_wed_wo_rx_complete(struct mtk_wed_wo *wo) ++{ ++ mtk_wed_wo_set_ack(wo, MTK_WED_WO_RXCH_INT_MASK); ++ mtk_wed_wo_irq_enable(wo, MTK_WED_WO_RXCH_INT_MASK); ++} ++ ++static void ++mtk_wed_wo_rx_run_queue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) ++{ ++ for (;;) { ++ struct mtk_wed_mcu_hdr *hdr; ++ struct sk_buff *skb; ++ void *data; ++ u32 len; ++ ++ data = mtk_wed_wo_dequeue(wo, q, &len, false); ++ if (!data) ++ break; ++ ++ skb = build_skb(data, q->buf_size); ++ if (!skb) { ++ skb_free_frag(data); ++ continue; ++ } ++ ++ __skb_put(skb, len); ++ if (mtk_wed_mcu_check_msg(wo, skb)) { ++ dev_kfree_skb(skb); ++ continue; ++ } ++ ++ hdr = (struct mtk_wed_mcu_hdr *)skb->data; ++ if (hdr->flag & cpu_to_le16(MTK_WED_WARP_CMD_FLAG_RSP)) ++ mtk_wed_mcu_rx_event(wo, skb); ++ else ++ mtk_wed_mcu_rx_unsolicited_event(wo, skb); ++ } ++ ++ if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { ++ u32 index = (q->head - 1) % q->n_desc; ++ ++ mtk_wed_wo_queue_kick(wo, q, index); ++ } ++} ++ ++static irqreturn_t ++mtk_wed_wo_irq_handler(int irq, void *data) ++{ ++ struct mtk_wed_wo *wo = data; ++ ++ mtk_wed_wo_set_isr(wo, 0); ++ tasklet_schedule(&wo->mmio.irq_tasklet); ++ ++ return IRQ_HANDLED; ++} ++ ++static void mtk_wed_wo_irq_tasklet(struct tasklet_struct *t) ++{ ++ struct mtk_wed_wo *wo = from_tasklet(wo, t, mmio.irq_tasklet); ++ u32 intr, mask; ++ ++ /* disable interrupts */ ++ mtk_wed_wo_set_isr(wo, 0); ++ ++ intr = mtk_wed_wo_get_isr(wo); ++ intr &= wo->mmio.irq_mask; ++ mask = intr & (MTK_WED_WO_RXCH_INT_MASK | MTK_WED_WO_EXCEPTION_INT_MASK); ++ mtk_wed_wo_irq_disable(wo, mask); ++ ++ if (intr & MTK_WED_WO_RXCH_INT_MASK) { ++ mtk_wed_wo_rx_run_queue(wo, &wo->q_rx); ++ mtk_wed_wo_rx_complete(wo); ++ } ++} ++ ++/* mtk wed wo hw queues */ ++ ++static int ++mtk_wed_wo_queue_alloc(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, ++ int n_desc, int buf_size, int index, ++ struct mtk_wed_wo_queue_regs *regs) ++{ ++ spin_lock_init(&q->lock); ++ q->regs = *regs; ++ q->n_desc = n_desc; ++ q->buf_size = buf_size; ++ ++ q->desc = dmam_alloc_coherent(wo->hw->dev, n_desc * sizeof(*q->desc), ++ &q->desc_dma, GFP_KERNEL); ++ if (!q->desc) ++ return -ENOMEM; ++ ++ q->entry = devm_kzalloc(wo->hw->dev, n_desc * sizeof(*q->entry), ++ GFP_KERNEL); ++ if (!q->entry) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void ++mtk_wed_wo_queue_free(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) ++{ ++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); ++ dma_free_coherent(wo->hw->dev, q->n_desc * sizeof(*q->desc), q->desc, ++ q->desc_dma); ++} ++ ++static void ++mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) ++{ ++ struct page *page; ++ int i; ++ ++ spin_lock_bh(&q->lock); ++ for (i = 0; i < q->n_desc; i++) { ++ struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; ++ ++ dma_unmap_single(wo->hw->dev, entry->addr, entry->len, ++ DMA_TO_DEVICE); ++ skb_free_frag(entry->buf); ++ entry->buf = NULL; ++ } ++ spin_unlock_bh(&q->lock); ++ ++ if (!q->cache.va) ++ return; ++ ++ page = virt_to_page(q->cache.va); ++ __page_frag_cache_drain(page, q->cache.pagecnt_bias); ++ memset(&q->cache, 0, sizeof(q->cache)); ++} ++ ++static void ++mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) ++{ ++ struct page *page; ++ ++ spin_lock_bh(&q->lock); ++ for (;;) { ++ void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); ++ ++ if (!buf) ++ break; ++ ++ skb_free_frag(buf); ++ } ++ spin_unlock_bh(&q->lock); ++ ++ if (!q->cache.va) ++ return; ++ ++ page = virt_to_page(q->cache.va); ++ __page_frag_cache_drain(page, q->cache.pagecnt_bias); ++ memset(&q->cache, 0, sizeof(q->cache)); ++} ++ ++static void ++mtk_wed_wo_queue_reset(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) ++{ ++ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); ++ mtk_wed_mmio_w32(wo, q->regs.desc_base, q->desc_dma); ++ mtk_wed_mmio_w32(wo, q->regs.ring_size, q->n_desc); ++} ++ ++int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, ++ struct sk_buff *skb) ++{ ++ struct mtk_wed_wo_queue_entry *entry; ++ struct mtk_wed_wo_queue_desc *desc; ++ int ret = 0, index; ++ u32 ctrl; ++ ++ spin_lock_bh(&q->lock); ++ ++ q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); ++ index = (q->head + 1) % q->n_desc; ++ if (q->tail == index) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ entry = &q->entry[index]; ++ if (skb->len > entry->len) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ desc = &q->desc[index]; ++ q->head = index; ++ ++ dma_sync_single_for_cpu(wo->hw->dev, entry->addr, skb->len, ++ DMA_TO_DEVICE); ++ memcpy(entry->buf, skb->data, skb->len); ++ dma_sync_single_for_device(wo->hw->dev, entry->addr, skb->len, ++ DMA_TO_DEVICE); ++ ++ ctrl = FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, skb->len) | ++ MTK_WED_WO_CTL_LAST_SEC0 | MTK_WED_WO_CTL_DMA_DONE; ++ WRITE_ONCE(desc->buf0, cpu_to_le32(entry->addr)); ++ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); ++ ++ mtk_wed_wo_queue_kick(wo, q, q->head); ++ mtk_wed_wo_kickout(wo); ++out: ++ spin_unlock_bh(&q->lock); ++ ++ dev_kfree_skb(skb); ++ ++ return ret; ++} ++ ++static int ++mtk_wed_wo_exception_init(struct mtk_wed_wo *wo) ++{ ++ return 0; ++} ++ ++static int ++mtk_wed_wo_hardware_init(struct mtk_wed_wo *wo) ++{ ++ struct mtk_wed_wo_queue_regs regs; ++ struct device_node *np; ++ int ret; ++ ++ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ccif", 0); ++ if (!np) ++ return -ENODEV; ++ ++ wo->mmio.regs = syscon_regmap_lookup_by_phandle(np, NULL); ++ if (IS_ERR_OR_NULL(wo->mmio.regs)) ++ return PTR_ERR(wo->mmio.regs); ++ ++ wo->mmio.irq = irq_of_parse_and_map(np, 0); ++ wo->mmio.irq_mask = MTK_WED_WO_ALL_INT_MASK; ++ spin_lock_init(&wo->mmio.lock); ++ tasklet_setup(&wo->mmio.irq_tasklet, mtk_wed_wo_irq_tasklet); ++ ++ ret = devm_request_irq(wo->hw->dev, wo->mmio.irq, ++ mtk_wed_wo_irq_handler, IRQF_TRIGGER_HIGH, ++ KBUILD_MODNAME, wo); ++ if (ret) ++ goto error; ++ ++ regs.desc_base = MTK_WED_WO_CCIF_DUMMY1; ++ regs.ring_size = MTK_WED_WO_CCIF_DUMMY2; ++ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW4; ++ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY3; ++ ++ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_tx, MTK_WED_WO_RING_SIZE, ++ MTK_WED_WO_CMD_LEN, MTK_WED_WO_TXCH_NUM, ++ ®s); ++ if (ret) ++ goto error; ++ ++ mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); ++ mtk_wed_wo_queue_reset(wo, &wo->q_tx); ++ ++ regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; ++ regs.ring_size = MTK_WED_WO_CCIF_DUMMY6; ++ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW8; ++ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY7; ++ ++ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_rx, MTK_WED_WO_RING_SIZE, ++ MTK_WED_WO_CMD_LEN, MTK_WED_WO_RXCH_NUM, ++ ®s); ++ if (ret) ++ goto error; ++ ++ mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); ++ mtk_wed_wo_queue_reset(wo, &wo->q_rx); ++ ++ /* rx queue irqmask */ ++ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); ++ ++ return 0; ++ ++error: ++ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); ++ ++ return ret; ++} ++ ++static void ++mtk_wed_wo_hw_deinit(struct mtk_wed_wo *wo) ++{ ++ /* disable interrupts */ ++ mtk_wed_wo_set_isr(wo, 0); ++ ++ tasklet_disable(&wo->mmio.irq_tasklet); ++ ++ disable_irq(wo->mmio.irq); ++ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); ++ ++ mtk_wed_wo_queue_tx_clean(wo, &wo->q_tx); ++ mtk_wed_wo_queue_rx_clean(wo, &wo->q_rx); ++ mtk_wed_wo_queue_free(wo, &wo->q_tx); ++ mtk_wed_wo_queue_free(wo, &wo->q_rx); ++} ++ ++int mtk_wed_wo_init(struct mtk_wed_hw *hw) ++{ ++ struct mtk_wed_wo *wo; ++ int ret; ++ ++ wo = devm_kzalloc(hw->dev, sizeof(*wo), GFP_KERNEL); ++ if (!wo) ++ return -ENOMEM; ++ ++ hw->wed_wo = wo; ++ wo->hw = hw; ++ ++ ret = mtk_wed_wo_hardware_init(wo); ++ if (ret) ++ return ret; ++ ++ ret = mtk_wed_mcu_init(wo); ++ if (ret) ++ return ret; ++ ++ return mtk_wed_wo_exception_init(wo); ++} ++ ++void mtk_wed_wo_deinit(struct mtk_wed_hw *hw) ++{ ++ struct mtk_wed_wo *wo = hw->wed_wo; ++ ++ mtk_wed_wo_hw_deinit(wo); ++} +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -80,6 +80,54 @@ enum mtk_wed_dummy_cr_idx { + #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) + #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) + ++#define MTK_WED_WO_RING_SIZE 256 ++#define MTK_WED_WO_CMD_LEN 1504 ++ ++#define MTK_WED_WO_TXCH_NUM 0 ++#define MTK_WED_WO_RXCH_NUM 1 ++#define MTK_WED_WO_RXCH_WO_EXCEPTION 7 ++ ++#define MTK_WED_WO_TXCH_INT_MASK BIT(0) ++#define MTK_WED_WO_RXCH_INT_MASK BIT(1) ++#define MTK_WED_WO_EXCEPTION_INT_MASK BIT(7) ++#define MTK_WED_WO_ALL_INT_MASK (MTK_WED_WO_RXCH_INT_MASK | \ ++ MTK_WED_WO_EXCEPTION_INT_MASK) ++ ++#define MTK_WED_WO_CCIF_BUSY 0x004 ++#define MTK_WED_WO_CCIF_START 0x008 ++#define MTK_WED_WO_CCIF_TCHNUM 0x00c ++#define MTK_WED_WO_CCIF_RCHNUM 0x010 ++#define MTK_WED_WO_CCIF_RCHNUM_MASK GENMASK(7, 0) ++ ++#define MTK_WED_WO_CCIF_ACK 0x014 ++#define MTK_WED_WO_CCIF_IRQ0_MASK 0x018 ++#define MTK_WED_WO_CCIF_IRQ1_MASK 0x01c ++#define MTK_WED_WO_CCIF_DUMMY1 0x020 ++#define MTK_WED_WO_CCIF_DUMMY2 0x024 ++#define MTK_WED_WO_CCIF_DUMMY3 0x028 ++#define MTK_WED_WO_CCIF_DUMMY4 0x02c ++#define MTK_WED_WO_CCIF_SHADOW1 0x030 ++#define MTK_WED_WO_CCIF_SHADOW2 0x034 ++#define MTK_WED_WO_CCIF_SHADOW3 0x038 ++#define MTK_WED_WO_CCIF_SHADOW4 0x03c ++#define MTK_WED_WO_CCIF_DUMMY5 0x050 ++#define MTK_WED_WO_CCIF_DUMMY6 0x054 ++#define MTK_WED_WO_CCIF_DUMMY7 0x058 ++#define MTK_WED_WO_CCIF_DUMMY8 0x05c ++#define MTK_WED_WO_CCIF_SHADOW5 0x060 ++#define MTK_WED_WO_CCIF_SHADOW6 0x064 ++#define MTK_WED_WO_CCIF_SHADOW7 0x068 ++#define MTK_WED_WO_CCIF_SHADOW8 0x06c ++ ++#define MTK_WED_WO_CTL_SD_LEN1 GENMASK(13, 0) ++#define MTK_WED_WO_CTL_LAST_SEC1 BIT(14) ++#define MTK_WED_WO_CTL_BURST BIT(15) ++#define MTK_WED_WO_CTL_SD_LEN0_SHIFT 16 ++#define MTK_WED_WO_CTL_SD_LEN0 GENMASK(29, 16) ++#define MTK_WED_WO_CTL_LAST_SEC0 BIT(30) ++#define MTK_WED_WO_CTL_DMA_DONE BIT(31) ++#define MTK_WED_WO_INFO_WINFO GENMASK(15, 0) ++ + struct mtk_wed_wo_memory_region { + const char *name; + void __iomem *addr; +@@ -112,10 +160,53 @@ struct mtk_wed_fw_trailer { + u32 crc; + }; + ++struct mtk_wed_wo_queue_regs { ++ u32 desc_base; ++ u32 ring_size; ++ u32 cpu_idx; ++ u32 dma_idx; ++}; ++ ++struct mtk_wed_wo_queue_desc { ++ __le32 buf0; ++ __le32 ctrl; ++ __le32 buf1; ++ __le32 info; ++ __le32 reserved[4]; ++} __packed __aligned(32); ++ ++struct mtk_wed_wo_queue_entry { ++ dma_addr_t addr; ++ void *buf; ++ u32 len; ++}; ++ ++struct mtk_wed_wo_queue { ++ struct mtk_wed_wo_queue_regs regs; ++ ++ struct page_frag_cache cache; ++ spinlock_t lock; ++ ++ struct mtk_wed_wo_queue_desc *desc; ++ dma_addr_t desc_dma; ++ ++ struct mtk_wed_wo_queue_entry *entry; ++ ++ u16 head; ++ u16 tail; ++ int n_desc; ++ int queued; ++ int buf_size; ++ ++}; ++ + struct mtk_wed_wo { + struct mtk_wed_hw *hw; + struct mtk_wed_wo_memory_region boot; + ++ struct mtk_wed_wo_queue q_tx; ++ struct mtk_wed_wo_queue q_rx; ++ + struct { + struct mutex mutex; + int timeout; +@@ -124,6 +215,15 @@ struct mtk_wed_wo { + struct sk_buff_head res_q; + wait_queue_head_t wait; + } mcu; ++ ++ struct { ++ struct regmap *regs; ++ ++ spinlock_t lock; ++ struct tasklet_struct irq_tasklet; ++ int irq; ++ u32 irq_mask; ++ } mmio; + }; + + static inline int +@@ -146,5 +246,9 @@ void mtk_wed_mcu_rx_unsolicited_event(st + int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, + const void *data, int len, bool wait_resp); + int mtk_wed_mcu_init(struct mtk_wed_wo *wo); ++int mtk_wed_wo_init(struct mtk_wed_hw *hw); ++void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); ++int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *dev, struct mtk_wed_wo_queue *q, ++ struct sk_buff *skb); + + #endif /* __MTK_WED_WO_H */ diff --git a/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch b/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch new file mode 100644 index 0000000000..a002a5f851 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch @@ -0,0 +1,79 @@ +From: Lorenzo Bianconi +Date: Sat, 5 Nov 2022 23:36:20 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: rename tx_wdma array in rx_wdma + +Rename tx_wdma queue array in rx_wdma since this is rx side of wdma soc. +Moreover rename mtk_wed_wdma_ring_setup routine in +mtk_wed_wdma_rx_ring_setup() + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -253,8 +253,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_dev + + for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) + mtk_wed_free_ring(dev, &dev->tx_ring[i]); +- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) +- mtk_wed_free_ring(dev, &dev->tx_wdma[i]); ++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) ++ mtk_wed_free_ring(dev, &dev->rx_wdma[i]); + } + + static void +@@ -688,10 +688,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device + } + + static int +-mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) + { + u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; +- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; ++ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; + + if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) + return -ENOMEM; +@@ -805,9 +805,9 @@ mtk_wed_start(struct mtk_wed_device *dev + { + int i; + +- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) +- if (!dev->tx_wdma[i].desc) +- mtk_wed_wdma_ring_setup(dev, i, 16); ++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) ++ if (!dev->rx_wdma[i].desc) ++ mtk_wed_wdma_rx_ring_setup(dev, i, 16); + + mtk_wed_hw_init(dev); + mtk_wed_configure_irq(dev, irq_mask); +@@ -916,7 +916,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev + sizeof(*ring->desc))) + return -ENOMEM; + +- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) + return -ENOMEM; + + ring->reg_base = MTK_WED_RING_TX(idx); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -7,6 +7,7 @@ + #include + + #define MTK_WED_TX_QUEUES 2 ++#define MTK_WED_RX_QUEUES 2 + + struct mtk_wed_hw; + struct mtk_wdma_desc; +@@ -66,7 +67,7 @@ struct mtk_wed_device { + + struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; + struct mtk_wed_ring txfree_ring; +- struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; + + struct { + int size; diff --git a/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch new file mode 100644 index 0000000000..eca29739b4 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch @@ -0,0 +1,1521 @@ +From: Lorenzo Bianconi +Date: Sat, 5 Nov 2022 23:36:21 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add configure wed wo support + +Enable RX Wireless Ethernet Dispatch available on MT7986 Soc. + +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -23,6 +24,7 @@ + #define MTK_WED_PKT_SIZE 1900 + #define MTK_WED_BUF_SIZE 2048 + #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) ++#define MTK_WED_RX_RING_SIZE 1536 + + #define MTK_WED_TX_RING_SIZE 2048 + #define MTK_WED_WDMA_RING_SIZE 1024 +@@ -31,6 +33,10 @@ + #define MTK_WED_PER_GROUP_PKT 128 + + #define MTK_WED_FBUF_SIZE 128 ++#define MTK_WED_MIOD_CNT 16 ++#define MTK_WED_FB_CMD_CNT 1024 ++#define MTK_WED_RRO_QUE_CNT 8192 ++#define MTK_WED_MIOD_ENTRY_CNT 128 + + static struct mtk_wed_hw *hw_list[2]; + static DEFINE_MUTEX(hw_lock); +@@ -65,12 +71,76 @@ wdma_set(struct mtk_wed_device *dev, u32 + wdma_m32(dev, reg, 0, mask); + } + ++static void ++wdma_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ wdma_m32(dev, reg, mask, 0); ++} ++ ++static u32 ++wifi_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ return readl(dev->wlan.base + reg); ++} ++ ++static void ++wifi_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ writel(val, dev->wlan.base + reg); ++} ++ + static u32 + mtk_wed_read_reset(struct mtk_wed_device *dev) + { + return wed_r32(dev, MTK_WED_RESET); + } + ++static u32 ++mtk_wdma_read_reset(struct mtk_wed_device *dev) ++{ ++ return wdma_r32(dev, MTK_WDMA_GLO_CFG); ++} ++ ++static void ++mtk_wdma_rx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; ++ int i; ++ ++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); ++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, ++ !(status & mask), 0, 1000)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { ++ if (dev->rx_wdma[i].desc) ++ continue; ++ ++ wdma_w32(dev, ++ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ } ++} ++ ++static void ++mtk_wdma_tx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; ++ int i; ++ ++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); ++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, ++ !(status & mask), 0, 1000)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { ++ if (dev->tx_wdma[i].desc) ++ continue; ++ ++ wdma_w32(dev, ++ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ } ++} ++ + static void + mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) + { +@@ -82,6 +152,54 @@ mtk_wed_reset(struct mtk_wed_device *dev + WARN_ON_ONCE(1); + } + ++static u32 ++mtk_wed_wo_read_status(struct mtk_wed_device *dev) ++{ ++ return wed_r32(dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_WO_STATUS); ++} ++ ++static void ++mtk_wed_wo_reset(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_wo *wo = dev->hw->wed_wo; ++ u8 state = MTK_WED_WO_STATE_DISABLE; ++ void __iomem *reg; ++ u32 val; ++ ++ mtk_wdma_tx_reset(dev); ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ ++ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, ++ MTK_WED_WO_CMD_CHANGE_STATE, &state, ++ sizeof(state), false); ++ ++ if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, ++ val == MTK_WED_WOIF_DISABLE_DONE, ++ 100, MTK_WOCPU_TIMEOUT)) ++ dev_err(dev->hw->dev, "failed to disable wed-wo\n"); ++ ++ reg = ioremap(MTK_WED_WO_CPU_MCUSYS_RESET_ADDR, 4); ++ ++ val = readl(reg); ++ switch (dev->hw->index) { ++ case 0: ++ val |= MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; ++ writel(val, reg); ++ val &= ~MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; ++ writel(val, reg); ++ break; ++ case 1: ++ val |= MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; ++ writel(val, reg); ++ val &= ~MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; ++ writel(val, reg); ++ break; ++ default: ++ break; ++ } ++ iounmap(reg); ++} ++ + static struct mtk_wed_hw * + mtk_wed_assign(struct mtk_wed_device *dev) + { +@@ -116,7 +234,7 @@ out: + } + + static int +-mtk_wed_buffer_alloc(struct mtk_wed_device *dev) ++mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +@@ -133,16 +251,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi + if (!page_list) + return -ENOMEM; + +- dev->buf_ring.size = ring_size; +- dev->buf_ring.pages = page_list; ++ dev->tx_buf_ring.size = ring_size; ++ dev->tx_buf_ring.pages = page_list; + + desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), + &desc_phys, GFP_KERNEL); + if (!desc) + return -ENOMEM; + +- dev->buf_ring.desc = desc; +- dev->buf_ring.desc_phys = desc_phys; ++ dev->tx_buf_ring.desc = desc; ++ dev->tx_buf_ring.desc_phys = desc_phys; + + for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { + dma_addr_t page_phys, buf_phys; +@@ -203,10 +321,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi + } + + static void +-mtk_wed_free_buffer(struct mtk_wed_device *dev) ++mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) + { +- struct mtk_wdma_desc *desc = dev->buf_ring.desc; +- void **page_list = dev->buf_ring.pages; ++ struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; ++ void **page_list = dev->tx_buf_ring.pages; + int page_idx; + int i; + +@@ -216,7 +334,8 @@ mtk_wed_free_buffer(struct mtk_wed_devic + if (!desc) + goto free_pagelist; + +- for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { ++ for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; ++ i += MTK_WED_BUF_PER_PAGE) { + void *page = page_list[page_idx++]; + dma_addr_t buf_addr; + +@@ -229,13 +348,59 @@ mtk_wed_free_buffer(struct mtk_wed_devic + __free_page(page); + } + +- dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), +- desc, dev->buf_ring.desc_phys); ++ dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), ++ desc, dev->tx_buf_ring.desc_phys); + + free_pagelist: + kfree(page_list); + } + ++static int ++mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ struct mtk_rxbm_desc *desc; ++ dma_addr_t desc_phys; ++ ++ dev->rx_buf_ring.size = dev->wlan.rx_nbuf; ++ desc = dma_alloc_coherent(dev->hw->dev, ++ dev->wlan.rx_nbuf * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ dev->rx_buf_ring.desc = desc; ++ dev->rx_buf_ring.desc_phys = desc_phys; ++ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); ++ ++ return 0; ++} ++ ++static void ++mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; ++ ++ if (!desc) ++ return; ++ ++ dev->wlan.release_rx_buf(dev); ++ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), ++ desc, dev->rx_buf_ring.desc_phys); ++} ++ ++static void ++mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev) ++{ ++ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD, ++ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size)); ++ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys); ++ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL | ++ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt)); ++ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, ++ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++} ++ + static void + mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) + { +@@ -247,6 +412,13 @@ mtk_wed_free_ring(struct mtk_wed_device + } + + static void ++mtk_wed_free_rx_rings(struct mtk_wed_device *dev) ++{ ++ mtk_wed_free_rx_buffer(dev); ++ mtk_wed_free_ring(dev, &dev->rro.ring); ++} ++ ++static void + mtk_wed_free_tx_rings(struct mtk_wed_device *dev) + { + int i; +@@ -291,6 +463,38 @@ mtk_wed_set_512_support(struct mtk_wed_d + } + } + ++#define MTK_WFMDA_RX_DMA_EN BIT(2) ++static void ++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) ++{ ++ u32 val; ++ int i; ++ ++ if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) ++ return; /* queue is not configured by mt76 */ ++ ++ for (i = 0; i < 3; i++) { ++ u32 cur_idx; ++ ++ cur_idx = wed_r32(dev, ++ MTK_WED_WPDMA_RING_RX_DATA(idx) + ++ MTK_WED_RING_OFS_CPU_IDX); ++ if (cur_idx == MTK_WED_RX_RING_SIZE - 1) ++ break; ++ ++ usleep_range(100000, 200000); ++ } ++ ++ if (i == 3) { ++ dev_err(dev->hw->dev, "rx dma enable failed\n"); ++ return; ++ } ++ ++ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | ++ MTK_WFMDA_RX_DMA_EN; ++ wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); ++} ++ + static void + mtk_wed_dma_disable(struct mtk_wed_device *dev) + { +@@ -304,20 +508,25 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WED_GLO_CFG_TX_DMA_EN | + MTK_WED_GLO_CFG_RX_DMA_EN); + +- wdma_m32(dev, MTK_WDMA_GLO_CFG, ++ wdma_clr(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_TX_DMA_EN | + MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | +- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0); ++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); + + if (dev->hw->version == 1) { + regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); +- wdma_m32(dev, MTK_WDMA_GLO_CFG, +- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0); ++ wdma_clr(dev, MTK_WDMA_GLO_CFG, ++ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + } else { + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); + ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RX_DRV_EN); ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ + mtk_wed_set_512_support(dev, false); + } + } +@@ -338,6 +547,13 @@ mtk_wed_stop(struct mtk_wed_device *dev) + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); + wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); ++ ++ if (dev->hw->version == 1) ++ return; ++ ++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); ++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); + } + + static void +@@ -353,11 +569,21 @@ mtk_wed_detach(struct mtk_wed_device *de + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + + mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ if (mtk_wed_get_rx_capa(dev)) { ++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ } + +- mtk_wed_free_buffer(dev); ++ mtk_wed_free_tx_buffer(dev); + mtk_wed_free_tx_rings(dev); +- if (hw->version != 1) ++ ++ if (mtk_wed_get_rx_capa(dev)) { ++ mtk_wed_wo_reset(dev); ++ mtk_wed_free_rx_rings(dev); + mtk_wed_wo_deinit(hw); ++ mtk_wdma_rx_reset(dev); ++ } + + if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { + struct device_node *wlan_node; +@@ -434,10 +660,12 @@ mtk_wed_set_wpdma(struct mtk_wed_device + } else { + mtk_wed_bus_init(dev); + +- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); +- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); ++ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); ++ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); + } + } + +@@ -487,6 +715,132 @@ mtk_wed_hw_init_early(struct mtk_wed_dev + } + } + ++static int ++mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, ++ int size) ++{ ++ ring->desc = dma_alloc_coherent(dev->hw->dev, ++ size * sizeof(*ring->desc), ++ &ring->desc_phys, GFP_KERNEL); ++ if (!ring->desc) ++ return -ENOMEM; ++ ++ ring->desc_size = sizeof(*ring->desc); ++ ring->size = size; ++ memset(ring->desc, 0, size); ++ ++ return 0; ++} ++ ++#define MTK_WED_MIOD_COUNT (MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT) ++static int ++mtk_wed_rro_alloc(struct mtk_wed_device *dev) ++{ ++ struct reserved_mem *rmem; ++ struct device_node *np; ++ int index; ++ ++ index = of_property_match_string(dev->hw->node, "memory-region-names", ++ "wo-dlm"); ++ if (index < 0) ++ return index; ++ ++ np = of_parse_phandle(dev->hw->node, "memory-region", index); ++ if (!np) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(np); ++ of_node_put(np); ++ ++ if (!rmem) ++ return -ENODEV; ++ ++ dev->rro.miod_phys = rmem->base; ++ dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; ++ ++ return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, ++ MTK_WED_RRO_QUE_CNT); ++} ++ ++static int ++mtk_wed_rro_cfg(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_wo *wo = dev->hw->wed_wo; ++ struct { ++ struct { ++ __le32 base; ++ __le32 cnt; ++ __le32 unit; ++ } ring[2]; ++ __le32 wed; ++ u8 version; ++ } req = { ++ .ring[0] = { ++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE), ++ .cnt = cpu_to_le32(MTK_WED_MIOD_CNT), ++ .unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT), ++ }, ++ .ring[1] = { ++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE + ++ MTK_WED_MIOD_COUNT), ++ .cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT), ++ .unit = cpu_to_le32(4), ++ }, ++ }; ++ ++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, ++ MTK_WED_WO_CMD_WED_CFG, ++ &req, sizeof(req), true); ++} ++ ++static void ++mtk_wed_rro_hw_init(struct mtk_wed_device *dev) ++{ ++ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG, ++ FIELD_PREP(MTK_WED_RROQM_MIOD_MID_DW, 0x70 >> 2) | ++ FIELD_PREP(MTK_WED_RROQM_MIOD_MOD_DW, 0x10 >> 2) | ++ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW, ++ MTK_WED_MIOD_ENTRY_CNT >> 2)); ++ ++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys); ++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1, ++ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT)); ++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys); ++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1, ++ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT)); ++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0); ++ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys); ++ ++ wed_set(dev, MTK_WED_RROQM_RST_IDX, ++ MTK_WED_RROQM_RST_IDX_MIOD | ++ MTK_WED_RROQM_RST_IDX_FDBK); ++ ++ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); ++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL2, MTK_WED_MIOD_CNT - 1); ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); ++} ++ ++static void ++mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev) ++{ ++ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM); ++ ++ for (;;) { ++ usleep_range(100, 200); ++ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM)) ++ break; ++ } ++ ++ /* configure RX_ROUTE_QM */ ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, ++ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ /* enable RX_ROUTE_QM */ ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); ++} ++ + static void + mtk_wed_hw_init(struct mtk_wed_device *dev) + { +@@ -498,11 +852,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d + wed_w32(dev, MTK_WED_TX_BM_CTRL, + MTK_WED_TX_BM_CTRL_PAUSE | + FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, +- dev->buf_ring.size / 128) | ++ dev->tx_buf_ring.size / 128) | + FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, + MTK_WED_TX_RING_SIZE / 256)); + +- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); ++ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); + + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + +@@ -529,9 +883,9 @@ mtk_wed_hw_init(struct mtk_wed_device *d + wed_w32(dev, MTK_WED_TX_TKID_CTRL, + MTK_WED_TX_TKID_CTRL_PAUSE | + FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM, +- dev->buf_ring.size / 128) | ++ dev->tx_buf_ring.size / 128) | + FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, +- dev->buf_ring.size / 128)); ++ dev->tx_buf_ring.size / 128)); + wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, + FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | + MTK_WED_TX_TKID_DYN_THR_HI); +@@ -539,18 +893,28 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + +- if (dev->hw->version == 1) ++ if (dev->hw->version == 1) { + wed_set(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); +- else ++ } else { + wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); ++ /* rx hw init */ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ ++ mtk_wed_rx_buffer_hw_init(dev); ++ mtk_wed_rro_hw_init(dev); ++ mtk_wed_route_qm_hw_init(dev); ++ } + + wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); + } + + static void +-mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size) ++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx) + { + void *head = (void *)ring->desc; + int i; +@@ -560,7 +924,10 @@ mtk_wed_ring_reset(struct mtk_wed_ring * + + desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size); + desc->buf0 = 0; +- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ if (tx) ++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ else ++ desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST); + desc->buf1 = 0; + desc->info = 0; + } +@@ -616,7 +983,8 @@ mtk_wed_reset_dma(struct mtk_wed_device + if (!dev->tx_ring[i].desc) + continue; + +- mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE); ++ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE, ++ true); + } + + if (mtk_wed_poll_busy(dev)) +@@ -634,6 +1002,9 @@ mtk_wed_reset_dma(struct mtk_wed_device + wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + ++ if (mtk_wed_get_rx_capa(dev)) ++ mtk_wdma_rx_reset(dev); ++ + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); +@@ -668,12 +1039,11 @@ mtk_wed_reset_dma(struct mtk_wed_device + MTK_WED_WPDMA_RESET_IDX_RX); + wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); + } +- + } + + static int + mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, +- int size, u32 desc_size) ++ int size, u32 desc_size, bool tx) + { + ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size, + &ring->desc_phys, GFP_KERNEL); +@@ -682,7 +1052,7 @@ mtk_wed_ring_alloc(struct mtk_wed_device + + ring->desc_size = desc_size; + ring->size = size; +- mtk_wed_ring_reset(ring, size); ++ mtk_wed_ring_reset(ring, size, tx); + + return 0; + } +@@ -691,9 +1061,14 @@ static int + mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) + { + u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; +- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; ++ struct mtk_wed_ring *wdma; + +- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) ++ if (idx >= ARRAY_SIZE(dev->rx_wdma)) ++ return -EINVAL; ++ ++ wdma = &dev->rx_wdma[idx]; ++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, ++ true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, +@@ -710,6 +1085,60 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we + return 0; + } + ++static int ++mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++{ ++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; ++ struct mtk_wed_ring *wdma; ++ ++ if (idx >= ARRAY_SIZE(dev->tx_wdma)) ++ return -EINVAL; ++ ++ wdma = &dev->tx_wdma[idx]; ++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, ++ true)) ++ return -ENOMEM; ++ ++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, ++ size); ++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); ++ ++ if (!idx) { ++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT, ++ size); ++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX, ++ 0); ++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX, ++ 0); ++ } ++ ++ return 0; ++} ++ ++static void ++mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb, ++ u32 reason, u32 hash) ++{ ++ struct mtk_eth *eth = dev->hw->eth; ++ struct ethhdr *eh; ++ ++ if (!skb) ++ return; ++ ++ if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ return; ++ ++ skb_set_mac_header(skb, 0); ++ eh = eth_hdr(skb); ++ skb->protocol = eh->h_proto; ++ mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash); ++} ++ + static void + mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask) + { +@@ -732,6 +1161,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev + + wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); + } else { ++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, ++ GENMASK(1, 0)); + /* initail tx interrupt trigger */ + wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, + MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | +@@ -750,6 +1181,16 @@ mtk_wed_configure_irq(struct mtk_wed_dev + FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, + dev->wlan.txfree_tbit)); + ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, ++ MTK_WED_WPDMA_INT_CTRL_RX0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RX1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, ++ dev->wlan.rx_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, ++ dev->wlan.rx_tbit[1])); ++ + wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); + wed_set(dev, MTK_WED_WDMA_INT_CTRL, + FIELD_PREP(MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL, +@@ -787,9 +1228,15 @@ mtk_wed_dma_enable(struct mtk_wed_device + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + } else { ++ int i; ++ + wed_set(dev, MTK_WED_WPDMA_CTRL, + MTK_WED_WPDMA_CTRL_SDL1_FIXED); + ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ + wed_set(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); +@@ -797,6 +1244,15 @@ mtk_wed_dma_enable(struct mtk_wed_device + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | + MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); ++ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RX_DRV_EN | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, ++ 0x2)); ++ ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) ++ mtk_wed_check_wfdma_rx_fill(dev, i); + } + } + +@@ -822,7 +1278,19 @@ mtk_wed_start(struct mtk_wed_device *dev + val |= BIT(0) | (BIT(1) * !!dev->hw->index); + regmap_write(dev->hw->mirror, dev->hw->index * 4, val); + } else { +- mtk_wed_set_512_support(dev, true); ++ /* driver set mid ready and only once */ ++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, ++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); ++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, ++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); ++ ++ wed_r32(dev, MTK_WED_EXT_INT_MASK1); ++ wed_r32(dev, MTK_WED_EXT_INT_MASK2); ++ ++ if (mtk_wed_rro_cfg(dev)) ++ return; ++ ++ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); + } + + mtk_wed_dma_enable(dev); +@@ -856,7 +1324,7 @@ mtk_wed_attach(struct mtk_wed_device *de + if (!hw) { + module_put(THIS_MODULE); + ret = -ENODEV; +- goto out; ++ goto unlock; + } + + device = dev->wlan.bus_type == MTK_WED_BUS_PCIE +@@ -869,15 +1337,24 @@ mtk_wed_attach(struct mtk_wed_device *de + dev->dev = hw->dev; + dev->irq = hw->irq; + dev->wdma_idx = hw->index; ++ dev->version = hw->version; + + if (hw->eth->dma_dev == hw->eth->dev && + of_dma_is_coherent(hw->eth->dev->of_node)) + mtk_eth_set_dma_device(hw->eth, hw->dev); + +- ret = mtk_wed_buffer_alloc(dev); +- if (ret) { +- mtk_wed_detach(dev); ++ ret = mtk_wed_tx_buffer_alloc(dev); ++ if (ret) + goto out; ++ ++ if (mtk_wed_get_rx_capa(dev)) { ++ ret = mtk_wed_rx_buffer_alloc(dev); ++ if (ret) ++ goto out; ++ ++ ret = mtk_wed_rro_alloc(dev); ++ if (ret) ++ goto out; + } + + mtk_wed_hw_init_early(dev); +@@ -886,8 +1363,10 @@ mtk_wed_attach(struct mtk_wed_device *de + BIT(hw->index), 0); + else + ret = mtk_wed_wo_init(hw); +- + out: ++ if (ret) ++ mtk_wed_detach(dev); ++unlock: + mutex_unlock(&hw_lock); + + return ret; +@@ -910,10 +1389,11 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev + * WDMA RX. + */ + +- BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring)); ++ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) ++ return -EINVAL; + + if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, +- sizeof(*ring->desc))) ++ sizeof(*ring->desc), true)) + return -ENOMEM; + + if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) +@@ -960,6 +1440,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed + return 0; + } + ++static int ++mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->rx_ring[idx]; ++ ++ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) ++ return -EINVAL; ++ ++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, ++ sizeof(*ring->desc), false)) ++ return -ENOMEM; ++ ++ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ ring->reg_base = MTK_WED_RING_RX_DATA(idx); ++ ring->wpdma = regs; ++ ring->flags |= MTK_WED_RING_CONFIGURED; ++ ++ /* WPDMA -> WED */ ++ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); ++ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_RX_RING_SIZE); ++ ++ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_BASE, ++ ring->desc_phys); ++ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_COUNT, ++ MTK_WED_RX_RING_SIZE); ++ ++ return 0; ++} ++ + static u32 + mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) + { +@@ -1056,7 +1567,9 @@ void mtk_wed_add_hw(struct device_node * + static const struct mtk_wed_ops wed_ops = { + .attach = mtk_wed_attach, + .tx_ring_setup = mtk_wed_tx_ring_setup, ++ .rx_ring_setup = mtk_wed_rx_ring_setup, + .txfree_ring_setup = mtk_wed_txfree_ring_setup, ++ .msg_update = mtk_wed_mcu_msg_update, + .start = mtk_wed_start, + .stop = mtk_wed_stop, + .reset_dma = mtk_wed_reset_dma, +@@ -1065,6 +1578,7 @@ void mtk_wed_add_hw(struct device_node * + .irq_get = mtk_wed_irq_get, + .irq_set_mask = mtk_wed_irq_set_mask, + .detach = mtk_wed_detach, ++ .ppe_check = mtk_wed_ppe_check, + }; + struct device_node *eth_np = eth->dev->of_node; + struct platform_device *pdev; +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -87,6 +87,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, + } + + static inline u32 ++wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg) ++{ ++ if (!dev->rx_ring[ring].wpdma) ++ return 0; ++ ++ return readl(dev->rx_ring[ring].wpdma + reg); ++} ++ ++static inline void ++wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) ++{ ++ if (!dev->rx_ring[ring].wpdma) ++ return; ++ ++ writel(val, dev->rx_ring[ring].wpdma + reg); ++} ++ ++static inline u32 + wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) + { + if (!dev->txfree_ring.wpdma) +@@ -128,6 +146,7 @@ static inline int mtk_wed_flow_add(int i + static inline void mtk_wed_flow_remove(int index) + { + } ++ + #endif + + #ifdef CONFIG_DEBUG_FS +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "mtk_wed_regs.h" + #include "mtk_wed_wo.h" +@@ -60,24 +61,37 @@ void mtk_wed_mcu_rx_event(struct mtk_wed + wake_up(&wo->mcu.wait); + } + ++static void ++mtk_wed_update_rx_stats(struct mtk_wed_device *wed, struct sk_buff *skb) ++{ ++ u32 count = get_unaligned_le32(skb->data); ++ struct mtk_wed_wo_rx_stats *stats; ++ int i; ++ ++ if (count * sizeof(*stats) > skb->len - sizeof(u32)) ++ return; ++ ++ stats = (struct mtk_wed_wo_rx_stats *)(skb->data + sizeof(u32)); ++ for (i = 0 ; i < count ; i++) ++ wed->wlan.update_wo_rx_stats(wed, &stats[i]); ++} ++ + void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, + struct sk_buff *skb) + { + struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; + +- switch (hdr->cmd) { +- case MTK_WED_WO_EVT_LOG_DUMP: { +- const char *msg = (const char *)(skb->data + sizeof(*hdr)); ++ skb_pull(skb, sizeof(*hdr)); + +- dev_notice(wo->hw->dev, "%s\n", msg); ++ switch (hdr->cmd) { ++ case MTK_WED_WO_EVT_LOG_DUMP: ++ dev_notice(wo->hw->dev, "%s\n", skb->data); + break; +- } + case MTK_WED_WO_EVT_PROFILING: { +- struct mtk_wed_wo_log_info *info; +- u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); ++ struct mtk_wed_wo_log_info *info = (void *)skb->data; ++ u32 count = skb->len / sizeof(*info); + int i; + +- info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); + for (i = 0 ; i < count ; i++) + dev_notice(wo->hw->dev, + "SN:%u latency: total=%u, rro:%u, mod:%u\n", +@@ -88,6 +102,7 @@ void mtk_wed_mcu_rx_unsolicited_event(st + break; + } + case MTK_WED_WO_EVT_RXCNT_INFO: ++ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); + break; + default: + break; +@@ -144,6 +159,8 @@ mtk_wed_mcu_parse_response(struct mtk_we + skb_pull(skb, sizeof(*hdr)); + switch (cmd) { + case MTK_WED_WO_CMD_RXCNT_INFO: ++ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); ++ break; + default: + break; + } +@@ -182,6 +199,18 @@ unlock: + return ret; + } + ++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, ++ int len) ++{ ++ struct mtk_wed_wo *wo = dev->hw->wed_wo; ++ ++ if (dev->hw->version == 1) ++ return 0; ++ ++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, ++ true); ++} ++ + static int + mtk_wed_get_memory_region(struct mtk_wed_wo *wo, + struct mtk_wed_wo_memory_region *region) +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -4,6 +4,7 @@ + #ifndef __MTK_WED_REGS_H + #define __MTK_WED_REGS_H + ++#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8) + #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) + #define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0) + #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) +@@ -28,6 +29,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET_WED_TX_DMA BIT(12) + #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) + #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) ++#define MTK_WED_RESET_RX_RRO_QM BIT(20) ++#define MTK_WED_RESET_RX_ROUTE_QM BIT(21) + #define MTK_WED_RESET_WED BIT(31) + + #define MTK_WED_CTRL 0x00c +@@ -39,8 +42,12 @@ struct mtk_wdma_desc { + #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) + #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) + #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) +-#define MTK_WED_CTRL_RESERVE_EN BIT(12) +-#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) ++#define MTK_WED_CTRL_WED_RX_BM_EN BIT(12) ++#define MTK_WED_CTRL_WED_RX_BM_BUSY BIT(13) ++#define MTK_WED_CTRL_RX_RRO_QM_EN BIT(14) ++#define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) ++#define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) ++#define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) + #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) + #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) + #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) +@@ -62,6 +69,9 @@ struct mtk_wdma_desc { + #define MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR BIT(22) + #define MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR BIT(23) + #define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_GET_BM_DMAD_SKIP BIT(25) ++#define MTK_WED_EXT_INT_STATUS_WPDMA_RX_D_DRV_ERR BIT(26) ++#define MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY BIT(27) + #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ + MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ + MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ +@@ -71,6 +81,8 @@ struct mtk_wdma_desc { + MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR) + + #define MTK_WED_EXT_INT_MASK 0x028 ++#define MTK_WED_EXT_INT_MASK1 0x02c ++#define MTK_WED_EXT_INT_MASK2 0x030 + + #define MTK_WED_STATUS 0x060 + #define MTK_WED_STATUS_TX GENMASK(15, 8) +@@ -151,6 +163,7 @@ struct mtk_wdma_desc { + #define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) + + #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) ++#define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) + + #define MTK_WED_SCR0 0x3c0 + #define MTK_WED_WPDMA_INT_TRIGGER 0x504 +@@ -213,6 +226,12 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG GENMASK(14, 10) + + #define MTK_WED_WPDMA_INT_CTRL_RX 0x534 ++#define MTK_WED_WPDMA_INT_CTRL_RX0_EN BIT(0) ++#define MTK_WED_WPDMA_INT_CTRL_RX0_CLR BIT(1) ++#define MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG GENMASK(6, 2) ++#define MTK_WED_WPDMA_INT_CTRL_RX1_EN BIT(8) ++#define MTK_WED_WPDMA_INT_CTRL_RX1_CLR BIT(9) ++#define MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG GENMASK(14, 10) + + #define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538 + #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0) +@@ -242,11 +261,34 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) + #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) ++#define MTK_WED_WPDMA_RING_RX_DATA(_n) (0x730 + (_n) * 0x10) ++ ++#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c ++#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) ++#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) ++ ++#define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 ++#define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) ++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) ++ ++#define MTK_WED_WPDMA_RX_GLO_CFG 0x76c ++#define MTK_WED_WPDMA_RX_RING 0x770 ++ ++#define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c ++ ++#define MTK_WED_WDMA_RING_TX 0x800 ++ ++#define MTK_WED_WDMA_TX_MIB 0x810 ++ + #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) + #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) + + #define MTK_WED_WDMA_GLO_CFG 0xa04 + #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) ++#define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) + #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) + #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) + #define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) +@@ -291,6 +333,20 @@ struct mtk_wdma_desc { + #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) + #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) + ++#define MTK_WED_RX_BM_RX_DMAD 0xd80 ++#define MTK_WED_RX_BM_RX_DMAD_SDL0 GENMASK(13, 0) ++ ++#define MTK_WED_RX_BM_BASE 0xd84 ++#define MTK_WED_RX_BM_INIT_PTR 0xd88 ++#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0) ++#define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16) ++ ++#define MTK_WED_RX_PTR 0xd8c ++ ++#define MTK_WED_RX_BM_DYN_ALLOC_TH 0xdb4 ++#define MTK_WED_RX_BM_DYN_ALLOC_TH_H GENMASK(31, 16) ++#define MTK_WED_RX_BM_DYN_ALLOC_TH_L GENMASK(15, 0) ++ + #define MTK_WED_RING_OFS_BASE 0x00 + #define MTK_WED_RING_OFS_COUNT 0x04 + #define MTK_WED_RING_OFS_CPU_IDX 0x08 +@@ -301,7 +357,9 @@ struct mtk_wdma_desc { + + #define MTK_WDMA_GLO_CFG 0x204 + #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0) ++#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1) + #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2) ++#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3) + #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26) + #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27) + #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28) +@@ -330,4 +388,70 @@ struct mtk_wdma_desc { + /* DMA channel mapping */ + #define HIFSYS_DMA_AG_MAP 0x008 + ++#define MTK_WED_RTQM_GLO_CFG 0xb00 ++#define MTK_WED_RTQM_BUSY BIT(1) ++#define MTK_WED_RTQM_Q_RST BIT(2) ++#define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) ++#define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) ++ ++#define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) ++#define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) ++#define MTK_WED_RTQM_Q2N_MIB 0xb80 ++#define MTK_WED_RTQM_Q2H_MIB(_n) (0xb84 + (_n) * 0x4) ++ ++#define MTK_WED_RTQM_Q2B_MIB 0xb8c ++#define MTK_WED_RTQM_PFDBK_MIB 0xb90 ++ ++#define MTK_WED_RROQM_GLO_CFG 0xc04 ++#define MTK_WED_RROQM_RST_IDX 0xc08 ++#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) ++#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4) ++ ++#define MTK_WED_RROQM_MIOD_CTRL0 0xc40 ++#define MTK_WED_RROQM_MIOD_CTRL1 0xc44 ++#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0) ++ ++#define MTK_WED_RROQM_MIOD_CTRL2 0xc48 ++#define MTK_WED_RROQM_MIOD_CTRL3 0xc4c ++ ++#define MTK_WED_RROQM_FDBK_CTRL0 0xc50 ++#define MTK_WED_RROQM_FDBK_CTRL1 0xc54 ++#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0) ++ ++#define MTK_WED_RROQM_FDBK_CTRL2 0xc58 ++ ++#define MTK_WED_RROQ_BASE_L 0xc80 ++#define MTK_WED_RROQ_BASE_H 0xc84 ++ ++#define MTK_WED_RROQM_MIOD_CFG 0xc8c ++#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0) ++#define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8) ++#define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16) ++ ++#define MTK_WED_RROQM_MID_MIB 0xcc0 ++#define MTK_WED_RROQM_MOD_MIB 0xcc4 ++#define MTK_WED_RROQM_MOD_COHERENT_MIB 0xcc8 ++#define MTK_WED_RROQM_FDBK_MIB 0xcd0 ++#define MTK_WED_RROQM_FDBK_COHERENT_MIB 0xcd4 ++#define MTK_WED_RROQM_FDBK_IND_MIB 0xce0 ++#define MTK_WED_RROQM_FDBK_ENQ_MIB 0xce4 ++#define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8 ++#define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec ++ ++#define MTK_WED_RX_BM_RX_DMAD 0xd80 ++#define MTK_WED_RX_BM_BASE 0xd84 ++#define MTK_WED_RX_BM_INIT_PTR 0xd88 ++#define MTK_WED_RX_BM_PTR 0xd8c ++#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16) ++#define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0) ++ ++#define MTK_WED_RX_BM_BLEN 0xd90 ++#define MTK_WED_RX_BM_STS 0xd94 ++#define MTK_WED_RX_BM_INTF2 0xd98 ++#define MTK_WED_RX_BM_INTF 0xd9c ++#define MTK_WED_RX_BM_ERR_STS 0xda8 ++ ++#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 ++#define MTK_WED_PCIE_INT_MASK 0x0 ++ + #endif +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -49,6 +49,10 @@ enum { + MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), + }; + ++#define MTK_WED_WO_CPU_MCUSYS_RESET_ADDR 0x15194050 ++#define MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK 0x20 ++#define MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK 0x1 ++ + enum { + MTK_WED_WO_REGION_EMI, + MTK_WED_WO_REGION_ILM, +@@ -57,6 +61,28 @@ enum { + __MTK_WED_WO_REGION_MAX, + }; + ++enum mtk_wed_wo_state { ++ MTK_WED_WO_STATE_UNDEFINED, ++ MTK_WED_WO_STATE_INIT, ++ MTK_WED_WO_STATE_ENABLE, ++ MTK_WED_WO_STATE_DISABLE, ++ MTK_WED_WO_STATE_HALT, ++ MTK_WED_WO_STATE_GATING, ++ MTK_WED_WO_STATE_SER_RESET, ++ MTK_WED_WO_STATE_WF_RESET, ++}; ++ ++enum mtk_wed_wo_done_state { ++ MTK_WED_WOIF_UNDEFINED, ++ MTK_WED_WOIF_DISABLE_DONE, ++ MTK_WED_WOIF_TRIGGER_ENABLE, ++ MTK_WED_WOIF_ENABLE_DONE, ++ MTK_WED_WOIF_TRIGGER_GATING, ++ MTK_WED_WOIF_GATING_DONE, ++ MTK_WED_WOIF_TRIGGER_HALT, ++ MTK_WED_WOIF_HALT_DONE, ++}; ++ + enum mtk_wed_dummy_cr_idx { + MTK_WED_DUMMY_CR_FWDL, + MTK_WED_DUMMY_CR_WO_STATUS, +@@ -245,6 +271,8 @@ void mtk_wed_mcu_rx_unsolicited_event(st + struct sk_buff *skb); + int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, + const void *data, int len, bool wait_resp); ++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, ++ int len); + int mtk_wed_mcu_init(struct mtk_wed_wo *wo); + int mtk_wed_wo_init(struct mtk_wed_hw *hw); + void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -5,10 +5,13 @@ + #include + #include + #include ++#include + + #define MTK_WED_TX_QUEUES 2 + #define MTK_WED_RX_QUEUES 2 + ++#define WED_WO_STA_REC 0x6 ++ + struct mtk_wed_hw; + struct mtk_wdma_desc; + +@@ -41,21 +44,37 @@ enum mtk_wed_wo_cmd { + MTK_WED_WO_CMD_WED_END + }; + ++struct mtk_rxbm_desc { ++ __le32 buf0; ++ __le32 token; ++} __packed __aligned(4); ++ + enum mtk_wed_bus_tye { + MTK_WED_BUS_PCIE, + MTK_WED_BUS_AXI, + }; + ++#define MTK_WED_RING_CONFIGURED BIT(0) + struct mtk_wed_ring { + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; + u32 desc_size; + int size; ++ u32 flags; + + u32 reg_base; + void __iomem *wpdma; + }; + ++struct mtk_wed_wo_rx_stats { ++ __le16 wlan_idx; ++ __le16 tid; ++ __le32 rx_pkt_cnt; ++ __le32 rx_byte_cnt; ++ __le32 rx_err_cnt; ++ __le32 rx_drop_cnt; ++}; ++ + struct mtk_wed_device { + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + const struct mtk_wed_ops *ops; +@@ -64,9 +83,12 @@ struct mtk_wed_device { + bool init_done, running; + int wdma_idx; + int irq; ++ u8 version; + + struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; + struct mtk_wed_ring txfree_ring; ++ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; + struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; + + struct { +@@ -74,7 +96,20 @@ struct mtk_wed_device { + void **pages; + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +- } buf_ring; ++ } tx_buf_ring; ++ ++ struct { ++ int size; ++ struct page_frag_cache rx_page; ++ struct mtk_rxbm_desc *desc; ++ dma_addr_t desc_phys; ++ } rx_buf_ring; ++ ++ struct { ++ struct mtk_wed_ring ring; ++ dma_addr_t miod_phys; ++ dma_addr_t fdbk_phys; ++ } rro; + + /* filled by driver: */ + struct { +@@ -83,22 +118,36 @@ struct mtk_wed_device { + struct pci_dev *pci_dev; + }; + enum mtk_wed_bus_tye bus_type; ++ void __iomem *base; ++ u32 phy_base; + + u32 wpdma_phys; + u32 wpdma_int; + u32 wpdma_mask; + u32 wpdma_tx; + u32 wpdma_txfree; ++ u32 wpdma_rx_glo; ++ u32 wpdma_rx; ++ ++ bool wcid_512; + + u16 token_start; + unsigned int nbuf; ++ unsigned int rx_nbuf; ++ unsigned int rx_npkt; ++ unsigned int rx_size; + + u8 tx_tbit[MTK_WED_TX_QUEUES]; ++ u8 rx_tbit[MTK_WED_RX_QUEUES]; + u8 txfree_tbit; + + u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); + int (*offload_enable)(struct mtk_wed_device *wed); + void (*offload_disable)(struct mtk_wed_device *wed); ++ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size); ++ void (*release_rx_buf)(struct mtk_wed_device *wed); ++ void (*update_wo_rx_stats)(struct mtk_wed_device *wed, ++ struct mtk_wed_wo_rx_stats *stats); + } wlan; + #endif + }; +@@ -107,9 +156,15 @@ struct mtk_wed_ops { + int (*attach)(struct mtk_wed_device *dev); + int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, + void __iomem *regs); ++ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); + int (*txfree_ring_setup)(struct mtk_wed_device *dev, + void __iomem *regs); ++ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, ++ void *data, int len); + void (*detach)(struct mtk_wed_device *dev); ++ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb, ++ u32 reason, u32 hash); + + void (*stop)(struct mtk_wed_device *dev); + void (*start)(struct mtk_wed_device *dev, u32 irq_mask); +@@ -144,6 +199,16 @@ mtk_wed_device_attach(struct mtk_wed_dev + return ret; + } + ++static inline bool ++mtk_wed_get_rx_capa(struct mtk_wed_device *dev) ++{ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ return dev->version != 1; ++#else ++ return false; ++#endif ++} ++ + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + #define mtk_wed_device_active(_dev) !!(_dev)->ops + #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) +@@ -160,6 +225,12 @@ mtk_wed_device_attach(struct mtk_wed_dev + (_dev)->ops->irq_get(_dev, _mask) + #define mtk_wed_device_irq_set_mask(_dev, _mask) \ + (_dev)->ops->irq_set_mask(_dev, _mask) ++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ ++ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) ++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ ++ (_dev)->ops->msg_update(_dev, _id, _msg, _len) + #else + static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) + { +@@ -173,6 +244,9 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) + #define mtk_wed_device_irq_get(_dev, _mask) 0 + #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) ++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) ++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV + #endif + + #endif diff --git a/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch b/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch new file mode 100644 index 0000000000..bb1066dece --- /dev/null +++ b/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch @@ -0,0 +1,149 @@ +From: Lorenzo Bianconi +Date: Sat, 5 Nov 2022 23:36:22 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add rx mib counters + +Introduce WED RX MIB counters support available on MT7986a SoC. + +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2021 Felix Fietkau */ + + #include ++#include + #include "mtk_wed.h" + #include "mtk_wed_regs.h" + +@@ -18,6 +19,8 @@ enum { + DUMP_TYPE_WDMA, + DUMP_TYPE_WPDMA_TX, + DUMP_TYPE_WPDMA_TXFREE, ++ DUMP_TYPE_WPDMA_RX, ++ DUMP_TYPE_WED_RRO, + }; + + #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } +@@ -36,6 +39,9 @@ enum { + + #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) + #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) ++#define DUMP_WPDMA_RX_RING(_n) DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n) ++#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO) ++#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO) + + static void + print_reg_val(struct seq_file *s, const char *name, u32 val) +@@ -57,6 +63,7 @@ dump_wed_regs(struct seq_file *s, struct + cur > regs ? "\n" : "", + cur->name); + continue; ++ case DUMP_TYPE_WED_RRO: + case DUMP_TYPE_WED: + val = wed_r32(dev, cur->offset); + break; +@@ -69,6 +76,9 @@ dump_wed_regs(struct seq_file *s, struct + case DUMP_TYPE_WPDMA_TXFREE: + val = wpdma_txfree_r32(dev, cur->offset); + break; ++ case DUMP_TYPE_WPDMA_RX: ++ val = wpdma_rx_r32(dev, cur->base, cur->offset); ++ break; + } + print_reg_val(s, cur->name, val); + } +@@ -132,6 +142,80 @@ wed_txinfo_show(struct seq_file *s, void + } + DEFINE_SHOW_ATTRIBUTE(wed_txinfo); + ++static int ++wed_rxinfo_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WPDMA RX"), ++ DUMP_WPDMA_RX_RING(0), ++ DUMP_WPDMA_RX_RING(1), ++ ++ DUMP_STR("WPDMA RX"), ++ DUMP_WED(WED_WPDMA_RX_D_MIB(0)), ++ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)), ++ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)), ++ DUMP_WED(WED_WPDMA_RX_D_MIB(1)), ++ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)), ++ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)), ++ DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB), ++ ++ DUMP_STR("WED RX"), ++ DUMP_WED_RING(WED_RING_RX_DATA(0)), ++ DUMP_WED_RING(WED_RING_RX_DATA(1)), ++ ++ DUMP_STR("WED RRO"), ++ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), ++ DUMP_WED(WED_RROQM_MID_MIB), ++ DUMP_WED(WED_RROQM_MOD_MIB), ++ DUMP_WED(WED_RROQM_MOD_COHERENT_MIB), ++ DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0), ++ DUMP_WED(WED_RROQM_FDBK_IND_MIB), ++ DUMP_WED(WED_RROQM_FDBK_ENQ_MIB), ++ DUMP_WED(WED_RROQM_FDBK_ANC_MIB), ++ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), ++ ++ DUMP_STR("WED Route QM"), ++ DUMP_WED(WED_RTQM_R2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(0)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2H_MIB(1)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2N_MIB), ++ DUMP_WED(WED_RTQM_Q2B_MIB), ++ DUMP_WED(WED_RTQM_PFDBK_MIB), ++ ++ DUMP_STR("WED WDMA TX"), ++ DUMP_WED(WED_WDMA_TX_MIB), ++ DUMP_WED_RING(WED_WDMA_RING_TX), ++ ++ DUMP_STR("WDMA TX"), ++ DUMP_WDMA(WDMA_GLO_CFG), ++ DUMP_WDMA_RING(WDMA_RING_TX(0)), ++ DUMP_WDMA_RING(WDMA_RING_TX(1)), ++ ++ DUMP_STR("WED RX BM"), ++ DUMP_WED(WED_RX_BM_BASE), ++ DUMP_WED(WED_RX_BM_RX_DMAD), ++ DUMP_WED(WED_RX_BM_PTR), ++ DUMP_WED(WED_RX_BM_TKID_MIB), ++ DUMP_WED(WED_RX_BM_BLEN), ++ DUMP_WED(WED_RX_BM_STS), ++ DUMP_WED(WED_RX_BM_INTF2), ++ DUMP_WED(WED_RX_BM_INTF), ++ DUMP_WED(WED_RX_BM_ERR_STS), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (!dev) ++ return 0; ++ ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); + + static int + mtk_wed_reg_set(void *data, u64 val) +@@ -175,4 +259,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w + debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); + debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); ++ if (hw->version != 1) ++ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, ++ &wed_rxinfo_fops); + } diff --git a/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch b/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch new file mode 100644 index 0000000000..cefe1eefff --- /dev/null +++ b/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch @@ -0,0 +1,36 @@ +From: Lorenzo Bianconi +Date: Thu, 17 Nov 2022 00:58:46 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: remove cpu_relax in + mtk_pending_work + +Get rid of cpu_relax in mtk_pending_work routine since MTK_RESETTING is +set only in mtk_pending_work() and it runs holding rtnl lock + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3480,11 +3480,8 @@ static void mtk_pending_work(struct work + rtnl_lock(); + + dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); ++ set_bit(MTK_RESETTING, ð->state); + +- while (test_and_set_bit_lock(MTK_RESETTING, ð->state)) +- cpu_relax(); +- +- dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__); + /* stop all devices to make sure that dma is properly shut down */ + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!eth->netdev[i]) +@@ -3518,7 +3515,7 @@ static void mtk_pending_work(struct work + + dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); + +- clear_bit_unlock(MTK_RESETTING, ð->state); ++ clear_bit(MTK_RESETTING, ð->state); + + rtnl_unlock(); + } diff --git a/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch b/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch new file mode 100644 index 0000000000..117ccc0902 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch @@ -0,0 +1,80 @@ +From: Sujuan Chen +Date: Thu, 24 Nov 2022 11:18:14 +0800 +Subject: [PATCH] net: ethernet: mtk_wed: add wcid overwritten support for wed + v1 + +All wed versions should enable the wcid overwritten feature, +since the wcid size is controlled by the wlan driver. + +Tested-by: Sujuan Chen +Co-developed-by: Bo Jiao +Signed-off-by: Bo Jiao +Signed-off-by: Sujuan Chen +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -526,9 +526,9 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WED_WPDMA_RX_D_RX_DRV_EN); + wed_clr(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); +- +- mtk_wed_set_512_support(dev, false); + } ++ ++ mtk_wed_set_512_support(dev, false); + } + + static void +@@ -1290,9 +1290,10 @@ mtk_wed_start(struct mtk_wed_device *dev + if (mtk_wed_rro_cfg(dev)) + return; + +- mtk_wed_set_512_support(dev, dev->wlan.wcid_512); + } + ++ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); ++ + mtk_wed_dma_enable(dev); + dev->running = true; + } +@@ -1358,11 +1359,13 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (hw->version == 1) ++ if (hw->version == 1) { + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); +- else ++ } else { ++ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID); + ret = mtk_wed_wo_init(hw); ++ } + out: + if (ret) + mtk_wed_detach(dev); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -20,6 +20,8 @@ struct mtk_wdma_desc { + __le32 info; + } __packed __aligned(4); + ++#define MTK_WED_REV_ID 0x004 ++ + #define MTK_WED_RESET 0x008 + #define MTK_WED_RESET_TX_BM BIT(0) + #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -85,6 +85,9 @@ struct mtk_wed_device { + int irq; + u8 version; + ++ /* used by wlan driver */ ++ u32 rev_id; ++ + struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; + struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; + struct mtk_wed_ring txfree_ring; diff --git a/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch b/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch new file mode 100644 index 0000000000..ec58c3fc57 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch @@ -0,0 +1,85 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Nov 2022 16:22:51 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: return status value in + mtk_wdma_rx_reset + +Move MTK_WDMA_RESET_IDX configuration in mtk_wdma_rx_reset routine. +Increase poll timeout to 10ms in order to be aligned with vendor sdk. +This is a preliminary patch to add Wireless Ethernet Dispatcher reset +support. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -101,17 +101,21 @@ mtk_wdma_read_reset(struct mtk_wed_devic + return wdma_r32(dev, MTK_WDMA_GLO_CFG); + } + +-static void ++static int + mtk_wdma_rx_reset(struct mtk_wed_device *dev) + { + u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; +- int i; ++ int i, ret; + + wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); +- if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, +- !(status & mask), 0, 1000)) ++ ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status, ++ !(status & mask), 0, 10000); ++ if (ret) + dev_err(dev->hw->dev, "rx reset failed\n"); + ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ + for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { + if (dev->rx_wdma[i].desc) + continue; +@@ -119,6 +123,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device + wdma_w32(dev, + MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); + } ++ ++ return ret; + } + + static void +@@ -565,9 +571,7 @@ mtk_wed_detach(struct mtk_wed_device *de + + mtk_wed_stop(dev); + +- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); +- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); +- ++ mtk_wdma_rx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); + if (mtk_wed_get_rx_capa(dev)) { + wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); +@@ -582,7 +586,6 @@ mtk_wed_detach(struct mtk_wed_device *de + mtk_wed_wo_reset(dev); + mtk_wed_free_rx_rings(dev); + mtk_wed_wo_deinit(hw); +- mtk_wdma_rx_reset(dev); + } + + if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { +@@ -999,11 +1002,7 @@ mtk_wed_reset_dma(struct mtk_wed_device + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); +- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); +- +- if (mtk_wed_get_rx_capa(dev)) +- mtk_wdma_rx_reset(dev); ++ mtk_wdma_rx_reset(dev); + + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); diff --git a/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch b/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch new file mode 100644 index 0000000000..10c1732c96 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch @@ -0,0 +1,52 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Nov 2022 16:22:52 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: move MTK_WDMA_RESET_IDX_TX + configuration in mtk_wdma_tx_reset + +Remove duplicated code. Increase poll timeout to 10ms in order to be +aligned with vendor sdk. +This is a preliminary patch to add Wireless Ethernet Dispatcher reset +support. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -135,16 +135,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device + + wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); + if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, +- !(status & mask), 0, 1000)) ++ !(status & mask), 0, 10000)) + dev_err(dev->hw->dev, "tx reset failed\n"); + +- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { +- if (dev->tx_wdma[i].desc) +- continue; ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) + wdma_w32(dev, + MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); +- } + } + + static void +@@ -573,12 +572,6 @@ mtk_wed_detach(struct mtk_wed_device *de + + mtk_wdma_rx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); +- if (mtk_wed_get_rx_capa(dev)) { +- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); +- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); +- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); +- } +- + mtk_wed_free_tx_buffer(dev); + mtk_wed_free_tx_rings(dev); + diff --git a/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch b/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch new file mode 100644 index 0000000000..f4e842d515 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch @@ -0,0 +1,98 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Nov 2022 16:22:53 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: update mtk_wed_stop + +Update mtk_wed_stop routine and rename old mtk_wed_stop() to +mtk_wed_deinit(). This is a preliminary patch to add Wireless Ethernet +Dispatcher reset support. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -539,14 +539,8 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { +- mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + +- wed_clr(dev, MTK_WED_CTRL, +- MTK_WED_CTRL_WDMA_INT_AGENT_EN | +- MTK_WED_CTRL_WPDMA_INT_AGENT_EN | +- MTK_WED_CTRL_WED_TX_BM_EN | +- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); +@@ -558,7 +552,27 @@ mtk_wed_stop(struct mtk_wed_device *dev) + + wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); + wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); +- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++} ++ ++static void ++mtk_wed_deinit(struct mtk_wed_device *dev) ++{ ++ mtk_wed_stop(dev); ++ mtk_wed_dma_disable(dev); ++ ++ wed_clr(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ ++ if (dev->hw->version == 1) ++ return; ++ ++ wed_clr(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_RX_ROUTE_QM_EN | ++ MTK_WED_CTRL_WED_RX_BM_EN | ++ MTK_WED_CTRL_RX_RRO_QM_EN); + } + + static void +@@ -568,7 +582,7 @@ mtk_wed_detach(struct mtk_wed_device *de + + mutex_lock(&hw_lock); + +- mtk_wed_stop(dev); ++ mtk_wed_deinit(dev); + + mtk_wdma_rx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); +@@ -670,7 +684,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev + { + u32 mask, set; + +- mtk_wed_stop(dev); ++ mtk_wed_deinit(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); + mtk_wed_set_wpdma(dev); + +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -234,6 +234,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic + (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) + #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ + (_dev)->ops->msg_update(_dev, _id, _msg, _len) ++#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) ++#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) + #else + static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) + { +@@ -250,6 +252,8 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV + #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) + #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV ++#define mtk_wed_device_stop(_dev) do {} while (0) ++#define mtk_wed_device_dma_reset(_dev) do {} while (0) + #endif + + #endif diff --git a/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch b/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch new file mode 100644 index 0000000000..a0fc9da99e --- /dev/null +++ b/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch @@ -0,0 +1,309 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Nov 2022 16:22:54 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add mtk_wed_rx_reset routine + +Introduce mtk_wed_rx_reset routine in order to reset rx DMA for Wireless +Ethernet Dispatcher available on MT7986 SoC. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -944,42 +944,130 @@ mtk_wed_ring_reset(struct mtk_wed_ring * + } + + static u32 +-mtk_wed_check_busy(struct mtk_wed_device *dev) ++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) + { +- if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY) +- return true; +- +- if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) & +- MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY) +- return true; +- +- if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY) +- return true; +- +- if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) & +- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) +- return true; +- +- if (wdma_r32(dev, MTK_WDMA_GLO_CFG) & +- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) +- return true; +- +- if (wed_r32(dev, MTK_WED_CTRL) & +- (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY)) +- return true; +- +- return false; ++ return !!(wed_r32(dev, reg) & mask); + } + + static int +-mtk_wed_poll_busy(struct mtk_wed_device *dev) ++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) + { + int sleep = 15000; + int timeout = 100 * sleep; + u32 val; + + return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, +- timeout, false, dev); ++ timeout, false, dev, reg, mask); ++} ++ ++static int ++mtk_wed_rx_reset(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_wo *wo = dev->hw->wed_wo; ++ u8 val = MTK_WED_WO_STATE_SER_RESET; ++ int i, ret; ++ ++ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, ++ MTK_WED_WO_CMD_CHANGE_STATE, &val, ++ sizeof(val), true); ++ if (ret) ++ return ret; ++ ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN); ++ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY); ++ if (ret) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV); ++ } else { ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | ++ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | ++ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); ++ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ } ++ ++ /* reset rro qm */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); ++ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_RX_RRO_QM_BUSY); ++ if (ret) { ++ mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM); ++ } else { ++ wed_set(dev, MTK_WED_RROQM_RST_IDX, ++ MTK_WED_RROQM_RST_IDX_MIOD | ++ MTK_WED_RROQM_RST_IDX_FDBK); ++ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); ++ } ++ ++ /* reset route qm */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); ++ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_RX_ROUTE_QM_BUSY); ++ if (ret) ++ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); ++ else ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, ++ MTK_WED_RTQM_Q_RST); ++ ++ /* reset tx wdma */ ++ mtk_wdma_tx_reset(dev); ++ ++ /* reset tx wdma drv */ ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); ++ ++ /* reset wed rx dma */ ++ ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_RX_DMA_BUSY); ++ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN); ++ if (ret) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); ++ } else { ++ struct mtk_eth *eth = dev->hw->eth; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ wed_set(dev, MTK_WED_RESET_IDX, ++ MTK_WED_RESET_IDX_RX_V2); ++ else ++ wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_RESET_IDX, 0); ++ } ++ ++ /* reset rx bm */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_RX_BM_BUSY); ++ mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); ++ ++ /* wo change to enable state */ ++ val = MTK_WED_WO_STATE_ENABLE; ++ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, ++ MTK_WED_WO_CMD_CHANGE_STATE, &val, ++ sizeof(val), true); ++ if (ret) ++ return ret; ++ ++ /* wed_rx_ring_reset */ ++ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) { ++ if (!dev->rx_ring[i].desc) ++ continue; ++ ++ mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE, ++ false); ++ } ++ mtk_wed_free_rx_buffer(dev); ++ ++ return 0; + } + + static void +@@ -997,19 +1085,23 @@ mtk_wed_reset_dma(struct mtk_wed_device + true); + } + +- if (mtk_wed_poll_busy(dev)) +- busy = mtk_wed_check_busy(dev); +- ++ /* 1. reset WED tx DMA */ ++ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN); ++ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_TX_DMA_BUSY); + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); + } else { +- wed_w32(dev, MTK_WED_RESET_IDX, +- MTK_WED_RESET_IDX_TX | +- MTK_WED_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX); + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +- mtk_wdma_rx_reset(dev); ++ /* 2. reset WDMA rx DMA */ ++ busy = !!mtk_wdma_rx_reset(dev); ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ if (!busy) ++ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY); + + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); +@@ -1026,6 +1118,9 @@ mtk_wed_reset_dma(struct mtk_wed_device + MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); + } + ++ /* 3. reset WED WPDMA tx */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ + for (i = 0; i < 100; i++) { + val = wed_r32(dev, MTK_WED_TX_BM_INTF); + if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) +@@ -1033,8 +1128,19 @@ mtk_wed_reset_dma(struct mtk_wed_device + } + + mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT); ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN); + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + ++ /* 4. reset WED WPDMA tx */ ++ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY); ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ if (!busy) ++ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY); ++ + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); +@@ -1045,6 +1151,17 @@ mtk_wed_reset_dma(struct mtk_wed_device + MTK_WED_WPDMA_RESET_IDX_RX); + wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); + } ++ ++ dev->init_done = false; ++ if (dev->hw->version == 1) ++ return; ++ ++ if (!busy) { ++ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX); ++ wed_w32(dev, MTK_WED_RESET_IDX, 0); ++ } ++ ++ mtk_wed_rx_reset(dev); + } + + static int +@@ -1267,6 +1384,9 @@ mtk_wed_start(struct mtk_wed_device *dev + { + int i; + ++ if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev)) ++ return; ++ + for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) + if (!dev->rx_wdma[i].desc) + mtk_wed_wdma_rx_ring_setup(dev, i, 16); +@@ -1355,10 +1475,6 @@ mtk_wed_attach(struct mtk_wed_device *de + goto out; + + if (mtk_wed_get_rx_capa(dev)) { +- ret = mtk_wed_rx_buffer_alloc(dev); +- if (ret) +- goto out; +- + ret = mtk_wed_rro_alloc(dev); + if (ret) + goto out; +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -24,11 +24,15 @@ struct mtk_wdma_desc { + + #define MTK_WED_RESET 0x008 + #define MTK_WED_RESET_TX_BM BIT(0) ++#define MTK_WED_RESET_RX_BM BIT(1) + #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) + #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) + #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) ++#define MTK_WED_RESET_WPDMA_RX_D_DRV BIT(10) + #define MTK_WED_RESET_WPDMA_INT_AGENT BIT(11) + #define MTK_WED_RESET_WED_TX_DMA BIT(12) ++#define MTK_WED_RESET_WED_RX_DMA BIT(13) ++#define MTK_WED_RESET_WDMA_TX_DRV BIT(16) + #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) + #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) + #define MTK_WED_RESET_RX_RRO_QM BIT(20) +@@ -158,6 +162,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET_IDX 0x20c + #define MTK_WED_RESET_IDX_TX GENMASK(3, 0) + #define MTK_WED_RESET_IDX_RX GENMASK(17, 16) ++#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6) ++#define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30) + + #define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) + #define MTK_WED_RX_MIB(_n) (0x2e0 + (_n) * 4) +@@ -267,6 +273,9 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c + #define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_RX_DRV_BUSY BIT(1) ++#define MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE BIT(3) ++#define MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE BIT(4) + #define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) + #define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) + diff --git a/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch new file mode 100644 index 0000000000..4404971cc7 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch @@ -0,0 +1,103 @@ +From: Lorenzo Bianconi +Date: Thu, 24 Nov 2022 16:22:55 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add reset to tx_ring_setup callback + +Introduce reset parameter to mtk_wed_tx_ring_setup signature. +This is a preliminary patch to add Wireless Ethernet Dispatcher reset +support. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1181,7 +1181,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device + } + + static int +-mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, ++ bool reset) + { + u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; +@@ -1190,8 +1191,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we + return -EINVAL; + + wdma = &dev->rx_wdma[idx]; +- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, +- true)) ++ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, ++ desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1389,7 +1390,7 @@ mtk_wed_start(struct mtk_wed_device *dev + + for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) + if (!dev->rx_wdma[i].desc) +- mtk_wed_wdma_rx_ring_setup(dev, i, 16); ++ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false); + + mtk_wed_hw_init(dev); + mtk_wed_configure_irq(dev, irq_mask); +@@ -1498,7 +1499,8 @@ unlock: + } + + static int +-mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, ++ bool reset) + { + struct mtk_wed_ring *ring = &dev->tx_ring[idx]; + +@@ -1517,11 +1519,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev + if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) + return -EINVAL; + +- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, +- sizeof(*ring->desc), true)) ++ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, ++ sizeof(*ring->desc), true)) + return -ENOMEM; + +- if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, ++ reset)) + return -ENOMEM; + + ring->reg_base = MTK_WED_RING_TX(idx); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -158,7 +158,7 @@ struct mtk_wed_device { + struct mtk_wed_ops { + int (*attach)(struct mtk_wed_device *dev); + int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, +- void __iomem *regs); ++ void __iomem *regs, bool reset); + int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, + void __iomem *regs); + int (*txfree_ring_setup)(struct mtk_wed_device *dev, +@@ -216,8 +216,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic + #define mtk_wed_device_active(_dev) !!(_dev)->ops + #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) + #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask) +-#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \ +- (_dev)->ops->tx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \ ++ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset) + #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \ + (_dev)->ops->txfree_ring_setup(_dev, _regs) + #define mtk_wed_device_reg_read(_dev, _reg) \ +@@ -243,7 +243,7 @@ static inline bool mtk_wed_device_active + } + #define mtk_wed_device_detach(_dev) do {} while (0) + #define mtk_wed_device_start(_dev, _mask) do {} while (0) +-#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV + #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV + #define mtk_wed_device_reg_read(_dev, _reg) 0 + #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) diff --git a/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch b/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch new file mode 100644 index 0000000000..f9b11326b1 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch @@ -0,0 +1,103 @@ +From: Lorenzo Bianconi +Date: Thu, 1 Dec 2022 16:26:53 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: fix sleep while atomic in + mtk_wed_wo_queue_refill + +In order to fix the following sleep while atomic bug always alloc pages +with GFP_ATOMIC in mtk_wed_wo_queue_refill since page_frag_alloc runs in +spin_lock critical section. + +[ 9.049719] Hardware name: MediaTek MT7986a RFB (DT) +[ 9.054665] Call trace: +[ 9.057096] dump_backtrace+0x0/0x154 +[ 9.060751] show_stack+0x14/0x1c +[ 9.064052] dump_stack_lvl+0x64/0x7c +[ 9.067702] dump_stack+0x14/0x2c +[ 9.071001] ___might_sleep+0xec/0x120 +[ 9.074736] __might_sleep+0x4c/0x9c +[ 9.078296] __alloc_pages+0x184/0x2e4 +[ 9.082030] page_frag_alloc_align+0x98/0x1ac +[ 9.086369] mtk_wed_wo_queue_refill+0x134/0x234 +[ 9.090974] mtk_wed_wo_init+0x174/0x2c0 +[ 9.094881] mtk_wed_attach+0x7c8/0x7e0 +[ 9.098701] mt7915_mmio_wed_init+0x1f0/0x3a0 [mt7915e] +[ 9.103940] mt7915_pci_probe+0xec/0x3bc [mt7915e] +[ 9.108727] pci_device_probe+0xac/0x13c +[ 9.112638] really_probe.part.0+0x98/0x2f4 +[ 9.116807] __driver_probe_device+0x94/0x13c +[ 9.121147] driver_probe_device+0x40/0x114 +[ 9.125314] __driver_attach+0x7c/0x180 +[ 9.129133] bus_for_each_dev+0x5c/0x90 +[ 9.132953] driver_attach+0x20/0x2c +[ 9.136513] bus_add_driver+0x104/0x1fc +[ 9.140333] driver_register+0x74/0x120 +[ 9.144153] __pci_register_driver+0x40/0x50 +[ 9.148407] mt7915_init+0x5c/0x1000 [mt7915e] +[ 9.152848] do_one_initcall+0x40/0x25c +[ 9.156669] do_init_module+0x44/0x230 +[ 9.160403] load_module+0x1f30/0x2750 +[ 9.164135] __do_sys_init_module+0x150/0x200 +[ 9.168475] __arm64_sys_init_module+0x18/0x20 +[ 9.172901] invoke_syscall.constprop.0+0x4c/0xe0 +[ 9.177589] do_el0_svc+0x48/0xe0 +[ 9.180889] el0_svc+0x14/0x50 +[ 9.183929] el0t_64_sync_handler+0x9c/0x120 +[ 9.188183] el0t_64_sync+0x158/0x15c + +Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Pavan Chebbi +Link: https://lore.kernel.org/r/67ca94bdd3d9eaeb86e52b3050fbca0bcf7bb02f.1669908312.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c +@@ -133,17 +133,18 @@ mtk_wed_wo_dequeue(struct mtk_wed_wo *wo + + static int + mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, +- gfp_t gfp, bool rx) ++ bool rx) + { + enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + int n_buf = 0; + + spin_lock_bh(&q->lock); + while (q->queued < q->n_desc) { +- void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); + struct mtk_wed_wo_queue_entry *entry; + dma_addr_t addr; ++ void *buf; + ++ buf = page_frag_alloc(&q->cache, q->buf_size, GFP_ATOMIC); + if (!buf) + break; + +@@ -215,7 +216,7 @@ mtk_wed_wo_rx_run_queue(struct mtk_wed_w + mtk_wed_mcu_rx_unsolicited_event(wo, skb); + } + +- if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { ++ if (mtk_wed_wo_queue_refill(wo, q, true)) { + u32 index = (q->head - 1) % q->n_desc; + + mtk_wed_wo_queue_kick(wo, q, index); +@@ -432,7 +433,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ + if (ret) + goto error; + +- mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); ++ mtk_wed_wo_queue_refill(wo, &wo->q_tx, false); + mtk_wed_wo_queue_reset(wo, &wo->q_tx); + + regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; +@@ -446,7 +447,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ + if (ret) + goto error; + +- mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); ++ mtk_wed_wo_queue_refill(wo, &wo->q_rx, true); + mtk_wed_wo_queue_reset(wo, &wo->q_rx); + + /* rx queue irqmask */ diff --git a/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch b/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch new file mode 100644 index 0000000000..fa6f56dbe7 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch @@ -0,0 +1,52 @@ +From: Lorenzo Bianconi +Date: Tue, 10 Jan 2023 10:31:26 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for rx queue + +Queue spinlock is currently held in mtk_wed_wo_queue_rx_clean and +mtk_wed_wo_queue_refill routines for MTK Wireless Ethernet Dispatcher +MCU rx queue. mtk_wed_wo_queue_refill() is running during initialization +and in rx tasklet while mtk_wed_wo_queue_rx_clean() is running in +mtk_wed_wo_hw_deinit() during hw de-init phase after rx tasklet has been +disabled. Since mtk_wed_wo_queue_rx_clean and mtk_wed_wo_queue_refill +routines can't run concurrently get rid of spinlock for mcu rx queue. + +Reviewed-by: Alexander Duyck +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/36ec3b729542ea60898471d890796f745479ba32.1673342990.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c +@@ -138,7 +138,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w + enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + int n_buf = 0; + +- spin_lock_bh(&q->lock); + while (q->queued < q->n_desc) { + struct mtk_wed_wo_queue_entry *entry; + dma_addr_t addr; +@@ -172,7 +171,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w + q->queued++; + n_buf++; + } +- spin_unlock_bh(&q->lock); + + return n_buf; + } +@@ -316,7 +314,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed + { + struct page *page; + +- spin_lock_bh(&q->lock); + for (;;) { + void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); + +@@ -325,7 +322,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed + + skb_free_frag(buf); + } +- spin_unlock_bh(&q->lock); + + if (!q->cache.va) + return; diff --git a/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch b/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch new file mode 100644 index 0000000000..9b1e4c3250 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch @@ -0,0 +1,75 @@ +From: Lorenzo Bianconi +Date: Thu, 12 Jan 2023 10:21:29 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for tx queue + +Similar to MTK Wireless Ethernet Dispatcher (WED) MCU rx queue, +we do not need to protect WED MCU tx queue with a spin lock since +the tx queue is accessed in the two following routines: +- mtk_wed_wo_queue_tx_skb(): + it is run at initialization and during mt7915 normal operation. + Moreover MCU messages are serialized through MCU mutex. +- mtk_wed_wo_queue_tx_clean(): + it runs just at mt7915 driver module unload when no more messages + are sent to the MCU. + +Remove tx queue spinlock. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/7bd0337b2a13ab1a63673b7c03fd35206b3b284e.1673515140.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c +@@ -258,7 +258,6 @@ mtk_wed_wo_queue_alloc(struct mtk_wed_wo + int n_desc, int buf_size, int index, + struct mtk_wed_wo_queue_regs *regs) + { +- spin_lock_init(&q->lock); + q->regs = *regs; + q->n_desc = n_desc; + q->buf_size = buf_size; +@@ -290,7 +289,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed + struct page *page; + int i; + +- spin_lock_bh(&q->lock); + for (i = 0; i < q->n_desc; i++) { + struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; + +@@ -299,7 +297,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed + skb_free_frag(entry->buf); + entry->buf = NULL; + } +- spin_unlock_bh(&q->lock); + + if (!q->cache.va) + return; +@@ -347,8 +344,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w + int ret = 0, index; + u32 ctrl; + +- spin_lock_bh(&q->lock); +- + q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); + index = (q->head + 1) % q->n_desc; + if (q->tail == index) { +@@ -379,8 +374,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w + mtk_wed_wo_queue_kick(wo, q, q->head); + mtk_wed_wo_kickout(wo); + out: +- spin_unlock_bh(&q->lock); +- + dev_kfree_skb(skb); + + return ret; +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -211,7 +211,6 @@ struct mtk_wed_wo_queue { + struct mtk_wed_wo_queue_regs regs; + + struct page_frag_cache cache; +- spinlock_t lock; + + struct mtk_wed_wo_queue_desc *desc; + dma_addr_t desc_dma; diff --git a/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch b/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch new file mode 100644 index 0000000000..c91861a8f1 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch @@ -0,0 +1,70 @@ +From: Lorenzo Bianconi +Date: Sat, 14 Jan 2023 18:01:28 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_reset utility + routine + +This is a preliminary patch to add Wireless Ethernet Dispatcher reset +support. + +Reviewed-by: Leon Romanovsky +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3256,6 +3256,27 @@ static void mtk_set_mcr_max_rx(struct mt + mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); + } + ++static void mtk_hw_reset(struct mtk_eth *eth) ++{ ++ u32 val; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); ++ val = RSTCTRL_PPE0_V2; ++ } else { ++ val = RSTCTRL_PPE0; ++ } ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= RSTCTRL_PPE1; ++ ++ ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, ++ 0x3ffffff); ++} ++ + static int mtk_hw_init(struct mtk_eth *eth) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | +@@ -3295,22 +3316,9 @@ static int mtk_hw_init(struct mtk_eth *e + return 0; + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); +- val = RSTCTRL_PPE0_V2; +- } else { +- val = RSTCTRL_PPE0; +- } +- +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- val |= RSTCTRL_PPE1; +- +- ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); ++ mtk_hw_reset(eth); + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, +- 0x3ffffff); +- + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); diff --git a/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch b/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch new file mode 100644 index 0000000000..6597eb5b74 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch @@ -0,0 +1,107 @@ +From: Lorenzo Bianconi +Date: Sat, 14 Jan 2023 18:01:29 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_warm_reset + support + +Introduce mtk_hw_warm_reset utility routine. This is a preliminary patch +to align reset procedure to vendor sdk and avoid to power down the chip +during hw reset. + +Reviewed-by: Leon Romanovsky +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3277,7 +3277,54 @@ static void mtk_hw_reset(struct mtk_eth + 0x3ffffff); + } + +-static int mtk_hw_init(struct mtk_eth *eth) ++static u32 mtk_hw_reset_read(struct mtk_eth *eth) ++{ ++ u32 val; ++ ++ regmap_read(eth->ethsys, ETHSYS_RSTCTRL, &val); ++ return val; ++} ++ ++static void mtk_hw_warm_reset(struct mtk_eth *eth) ++{ ++ u32 rst_mask, val; ++ ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, RSTCTRL_FE, ++ RSTCTRL_FE); ++ if (readx_poll_timeout_atomic(mtk_hw_reset_read, eth, val, ++ val & RSTCTRL_FE, 1, 1000)) { ++ dev_err(eth->dev, "warm reset failed\n"); ++ mtk_hw_reset(eth); ++ return; ++ } ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; ++ else ++ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ rst_mask |= RSTCTRL_PPE1; ++ ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); ++ ++ udelay(1); ++ val = mtk_hw_reset_read(eth); ++ if (!(val & rst_mask)) ++ dev_err(eth->dev, "warm reset stage0 failed %08x (%08x)\n", ++ val, rst_mask); ++ ++ rst_mask |= RSTCTRL_FE; ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, ~rst_mask); ++ ++ udelay(1); ++ val = mtk_hw_reset_read(eth); ++ if (val & rst_mask) ++ dev_err(eth->dev, "warm reset stage1 failed %08x (%08x)\n", ++ val, rst_mask); ++} ++ ++static int mtk_hw_init(struct mtk_eth *eth, bool reset) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | + ETHSYS_DMA_AG_MAP_PPE; +@@ -3316,7 +3363,12 @@ static int mtk_hw_init(struct mtk_eth *e + return 0; + } + +- mtk_hw_reset(eth); ++ msleep(100); ++ ++ if (reset) ++ mtk_hw_warm_reset(eth); ++ else ++ mtk_hw_reset(eth); + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + /* Set FE to PDMAv2 if necessary */ +@@ -3507,7 +3559,7 @@ static void mtk_pending_work(struct work + if (eth->dev->pins) + pinctrl_select_state(eth->dev->pins->p, + eth->dev->pins->default_state); +- mtk_hw_init(eth); ++ mtk_hw_init(eth, true); + + /* restart DMA and enable IRQs */ + for (i = 0; i < MTK_MAC_COUNT; i++) { +@@ -4109,7 +4161,7 @@ static int mtk_probe(struct platform_dev + eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); + INIT_WORK(ð->pending_work, mtk_pending_work); + +- err = mtk_hw_init(eth); ++ err = mtk_hw_init(eth, false); + if (err) + goto err_wed_exit; + diff --git a/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch b/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch new file mode 100644 index 0000000000..55ab19f4c8 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch @@ -0,0 +1,262 @@ +From: Lorenzo Bianconi +Date: Sat, 14 Jan 2023 18:01:30 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: align reset procedure to vendor + sdk + +Avoid to power-down the ethernet chip during hw reset and align reset +procedure to vendor sdk. + +Reviewed-by: Leon Romanovsky +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2844,14 +2844,29 @@ static void mtk_dma_free(struct mtk_eth + kfree(eth->scratch_head); + } + ++static bool mtk_hw_reset_check(struct mtk_eth *eth) ++{ ++ u32 val = mtk_r32(eth, MTK_INT_STATUS2); ++ ++ return (val & MTK_FE_INT_FQ_EMPTY) || (val & MTK_FE_INT_RFIFO_UF) || ++ (val & MTK_FE_INT_RFIFO_OV) || (val & MTK_FE_INT_TSO_FAIL) || ++ (val & MTK_FE_INT_TSO_ALIGN) || (val & MTK_FE_INT_TSO_ILLEGAL); ++} ++ + static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + ++ if (test_bit(MTK_RESETTING, ð->state)) ++ return; ++ ++ if (!mtk_hw_reset_check(eth)) ++ return; ++ + eth->netdev[mac->id]->stats.tx_errors++; +- netif_err(eth, tx_err, dev, +- "transmit timed out\n"); ++ netif_err(eth, tx_err, dev, "transmit timed out\n"); ++ + schedule_work(ð->pending_work); + } + +@@ -3331,15 +3346,17 @@ static int mtk_hw_init(struct mtk_eth *e + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + int i, val, ret; + +- if (test_and_set_bit(MTK_HW_INIT, ð->state)) ++ if (!reset && test_and_set_bit(MTK_HW_INIT, ð->state)) + return 0; + +- pm_runtime_enable(eth->dev); +- pm_runtime_get_sync(eth->dev); ++ if (!reset) { ++ pm_runtime_enable(eth->dev); ++ pm_runtime_get_sync(eth->dev); + +- ret = mtk_clk_enable(eth); +- if (ret) +- goto err_disable_pm; ++ ret = mtk_clk_enable(eth); ++ if (ret) ++ goto err_disable_pm; ++ } + + if (eth->ethsys) + regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, +@@ -3468,8 +3485,10 @@ static int mtk_hw_init(struct mtk_eth *e + return 0; + + err_disable_pm: +- pm_runtime_put_sync(eth->dev); +- pm_runtime_disable(eth->dev); ++ if (!reset) { ++ pm_runtime_put_sync(eth->dev); ++ pm_runtime_disable(eth->dev); ++ } + + return ret; + } +@@ -3531,30 +3550,53 @@ static int mtk_do_ioctl(struct net_devic + return -EOPNOTSUPP; + } + ++static void mtk_prepare_for_reset(struct mtk_eth *eth) ++{ ++ u32 val; ++ int i; ++ ++ /* disabe FE P3 and P4 */ ++ val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= MTK_FE_LINK_DOWN_P4; ++ mtk_w32(eth, val, MTK_FE_GLO_CFG); ++ ++ /* adjust PPE configurations to prepare for reset */ ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_prepare_reset(eth->ppe[i]); ++ ++ /* disable NETSYS interrupts */ ++ mtk_w32(eth, 0, MTK_FE_INT_ENABLE); ++ ++ /* force link down GMAC */ ++ for (i = 0; i < 2; i++) { ++ val = mtk_r32(eth, MTK_MAC_MCR(i)) & ~MAC_MCR_FORCE_LINK; ++ mtk_w32(eth, val, MTK_MAC_MCR(i)); ++ } ++} ++ + static void mtk_pending_work(struct work_struct *work) + { + struct mtk_eth *eth = container_of(work, struct mtk_eth, pending_work); +- int err, i; + unsigned long restart = 0; ++ u32 val; ++ int i; + + rtnl_lock(); +- +- dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); + set_bit(MTK_RESETTING, ð->state); + ++ 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++) { +- if (!eth->netdev[i]) ++ if (!eth->netdev[i] || !netif_running(eth->netdev[i])) + continue; ++ + mtk_stop(eth->netdev[i]); + __set_bit(i, &restart); + } +- dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__); + +- /* restart underlying hardware such as power, clock, pin mux +- * and the connected phy +- */ +- mtk_hw_deinit(eth); ++ usleep_range(15000, 16000); + + if (eth->dev->pins) + pinctrl_select_state(eth->dev->pins->p, +@@ -3565,15 +3607,19 @@ static void mtk_pending_work(struct work + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!test_bit(i, &restart)) + continue; +- err = mtk_open(eth->netdev[i]); +- if (err) { ++ ++ if (mtk_open(eth->netdev[i])) { + netif_alert(eth, ifup, eth->netdev[i], +- "Driver up/down cycle failed, closing device.\n"); ++ "Driver up/down cycle failed\n"); + dev_close(eth->netdev[i]); + } + } + +- dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); ++ /* enabe FE P3 and P4 */ ++ val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val &= ~MTK_FE_LINK_DOWN_P4; ++ mtk_w32(eth, val, MTK_FE_GLO_CFG); + + clear_bit(MTK_RESETTING, ð->state); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -72,12 +72,24 @@ + #define MTK_HW_LRO_REPLACE_DELTA 1000 + #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 + ++/* Frame Engine Global Configuration */ ++#define MTK_FE_GLO_CFG 0x00 ++#define MTK_FE_LINK_DOWN_P3 BIT(11) ++#define MTK_FE_LINK_DOWN_P4 BIT(12) ++ + /* Frame Engine Global Reset Register */ + #define MTK_RST_GL 0x04 + #define RST_GL_PSE BIT(0) + + /* Frame Engine Interrupt Status Register */ + #define MTK_INT_STATUS2 0x08 ++#define MTK_FE_INT_ENABLE 0x0c ++#define MTK_FE_INT_FQ_EMPTY BIT(8) ++#define MTK_FE_INT_TSO_FAIL BIT(12) ++#define MTK_FE_INT_TSO_ILLEGAL BIT(13) ++#define MTK_FE_INT_TSO_ALIGN BIT(14) ++#define MTK_FE_INT_RFIFO_OV BIT(18) ++#define MTK_FE_INT_RFIFO_UF BIT(19) + #define MTK_GDM1_AF BIT(28) + #define MTK_GDM2_AF BIT(29) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -710,6 +710,33 @@ int mtk_foe_entry_idle_time(struct mtk_p + return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); + } + ++int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) ++{ ++ if (!ppe) ++ return -EINVAL; ++ ++ /* disable KA */ ++ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); ++ ppe_clear(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); ++ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0); ++ usleep_range(10000, 11000); ++ ++ /* set KA timer to maximum */ ++ ppe_set(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); ++ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0xffffffff); ++ ++ /* set KA tick select */ ++ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_TICK_SEL); ++ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); ++ usleep_range(10000, 11000); ++ ++ /* disable scan mode */ ++ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_SCAN_MODE); ++ usleep_range(10000, 11000); ++ ++ return mtk_ppe_wait_busy(ppe); ++} ++ + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, + int version, int index) + { +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -306,6 +306,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + void mtk_ppe_deinit(struct mtk_eth *eth); + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); ++int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); + + void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +@@ -58,6 +58,12 @@ + #define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16) + #define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18) + #define MTK_PPE_TB_CFG_INFO_SEL BIT(20) ++#define MTK_PPE_TB_TICK_SEL BIT(24) ++ ++#define MTK_PPE_BIND_LMT1 0x230 ++#define MTK_PPE_NTU_KEEPALIVE GENMASK(23, 16) ++ ++#define MTK_PPE_KEEPALIVE 0x234 + + enum { + MTK_PPE_SCAN_MODE_DISABLED, diff --git a/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch b/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch new file mode 100644 index 0000000000..d5a7c0eba2 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch @@ -0,0 +1,249 @@ +From: Lorenzo Bianconi +Date: Sat, 14 Jan 2023 18:01:31 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add dma checks to + mtk_hw_reset_check + +Introduce mtk_hw_check_dma_hang routine to monitor possible dma hangs. + +Reviewed-by: Leon Romanovsky +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -50,6 +50,7 @@ static const struct mtk_reg_map mtk_reg_ + .delay_irq = 0x0a0c, + .irq_status = 0x0a20, + .irq_mask = 0x0a28, ++ .adma_rx_dbg0 = 0x0a38, + .int_grp = 0x0a50, + }, + .qdma = { +@@ -79,6 +80,8 @@ static const struct mtk_reg_map mtk_reg_ + [0] = 0x2800, + [1] = 0x2c00, + }, ++ .pse_iq_sta = 0x0110, ++ .pse_oq_sta = 0x0118, + }; + + static const struct mtk_reg_map mt7628_reg_map = { +@@ -109,6 +112,7 @@ static const struct mtk_reg_map mt7986_r + .delay_irq = 0x620c, + .irq_status = 0x6220, + .irq_mask = 0x6228, ++ .adma_rx_dbg0 = 0x6238, + .int_grp = 0x6250, + }, + .qdma = { +@@ -138,6 +142,8 @@ static const struct mtk_reg_map mt7986_r + [0] = 0x4800, + [1] = 0x4c00, + }, ++ .pse_iq_sta = 0x0180, ++ .pse_oq_sta = 0x01a0, + }; + + /* strings used by ethtool */ +@@ -3339,6 +3345,102 @@ static void mtk_hw_warm_reset(struct mtk + val, rst_mask); + } + ++static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) ++{ ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ bool gmac1_tx, gmac2_tx, gdm1_tx, gdm2_tx; ++ bool oq_hang, cdm1_busy, adma_busy; ++ bool wtx_busy, cdm_full, oq_free; ++ u32 wdidx, val, gdm1_fc, gdm2_fc; ++ bool qfsm_hang, qfwd_hang; ++ bool ret = false; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) ++ return false; ++ ++ /* WDMA sanity checks */ ++ wdidx = mtk_r32(eth, reg_map->wdma_base[0] + 0xc); ++ ++ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x204); ++ wtx_busy = FIELD_GET(MTK_TX_DMA_BUSY, val); ++ ++ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x230); ++ cdm_full = !FIELD_GET(MTK_CDM_TXFIFO_RDY, val); ++ ++ oq_free = (!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(24, 16)) && ++ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x4) & GENMASK(8, 0)) && ++ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x10) & GENMASK(24, 16))); ++ ++ if (wdidx == eth->reset.wdidx && wtx_busy && cdm_full && oq_free) { ++ if (++eth->reset.wdma_hang_count > 2) { ++ eth->reset.wdma_hang_count = 0; ++ ret = true; ++ } ++ goto out; ++ } ++ ++ /* QDMA sanity checks */ ++ qfsm_hang = !!mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x234); ++ qfwd_hang = !mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x308); ++ ++ gdm1_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM1_FSM)) > 0; ++ gdm2_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM2_FSM)) > 0; ++ gmac1_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(0))) != 1; ++ gmac2_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(1))) != 1; ++ gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x24); ++ gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x64); ++ ++ if (qfsm_hang && qfwd_hang && ++ ((gdm1_tx && gmac1_tx && gdm1_fc < 1) || ++ (gdm2_tx && gmac2_tx && gdm2_fc < 1))) { ++ if (++eth->reset.qdma_hang_count > 2) { ++ eth->reset.qdma_hang_count = 0; ++ ret = true; ++ } ++ goto out; ++ } ++ ++ /* ADMA sanity checks */ ++ oq_hang = !!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(8, 0)); ++ cdm1_busy = !!(mtk_r32(eth, MTK_FE_CDM1_FSM) & GENMASK(31, 16)); ++ adma_busy = !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & GENMASK(4, 0)) && ++ !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & BIT(6)); ++ ++ if (oq_hang && cdm1_busy && adma_busy) { ++ if (++eth->reset.adma_hang_count > 2) { ++ eth->reset.adma_hang_count = 0; ++ ret = true; ++ } ++ goto out; ++ } ++ ++ eth->reset.wdma_hang_count = 0; ++ eth->reset.qdma_hang_count = 0; ++ eth->reset.adma_hang_count = 0; ++out: ++ eth->reset.wdidx = wdidx; ++ ++ return ret; ++} ++ ++static void mtk_hw_reset_monitor_work(struct work_struct *work) ++{ ++ struct delayed_work *del_work = to_delayed_work(work); ++ struct mtk_eth *eth = container_of(del_work, struct mtk_eth, ++ reset.monitor_work); ++ ++ if (test_bit(MTK_RESETTING, ð->state)) ++ goto out; ++ ++ /* DMA stuck checks */ ++ if (mtk_hw_check_dma_hang(eth)) ++ schedule_work(ð->pending_work); ++ ++out: ++ schedule_delayed_work(ð->reset.monitor_work, ++ MTK_DMA_MONITOR_TIMEOUT); ++} ++ + static int mtk_hw_init(struct mtk_eth *eth, bool reset) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | +@@ -3657,6 +3759,7 @@ static int mtk_cleanup(struct mtk_eth *e + mtk_unreg_dev(eth); + mtk_free_dev(eth); + cancel_work_sync(ð->pending_work); ++ cancel_delayed_work_sync(ð->reset.monitor_work); + + return 0; + } +@@ -4094,6 +4197,7 @@ static int mtk_probe(struct platform_dev + + eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; + INIT_WORK(ð->rx_dim.work, mtk_dim_rx); ++ INIT_DELAYED_WORK(ð->reset.monitor_work, mtk_hw_reset_monitor_work); + + eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; + INIT_WORK(ð->tx_dim.work, mtk_dim_tx); +@@ -4296,6 +4400,8 @@ static int mtk_probe(struct platform_dev + netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx); + + platform_set_drvdata(pdev, eth); ++ schedule_delayed_work(ð->reset.monitor_work, ++ MTK_DMA_MONITOR_TIMEOUT); + + return 0; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -257,6 +257,8 @@ + + #define MTK_RX_DONE_INT_V2 BIT(14) + ++#define MTK_CDM_TXFIFO_RDY BIT(7) ++ + /* QDMA Interrupt grouping registers */ + #define MTK_RLS_DONE_INT BIT(0) + +@@ -542,6 +544,17 @@ + #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) + #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) + ++#define MTK_FE_CDM1_FSM 0x220 ++#define MTK_FE_CDM2_FSM 0x224 ++#define MTK_FE_CDM3_FSM 0x238 ++#define MTK_FE_CDM4_FSM 0x298 ++#define MTK_FE_CDM5_FSM 0x318 ++#define MTK_FE_CDM6_FSM 0x328 ++#define MTK_FE_GDM1_FSM 0x228 ++#define MTK_FE_GDM2_FSM 0x22C ++ ++#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) ++ + struct mtk_rx_dma { + unsigned int rxd1; + unsigned int rxd2; +@@ -938,6 +951,7 @@ struct mtk_reg_map { + u32 delay_irq; /* delay interrupt */ + u32 irq_status; /* interrupt status */ + u32 irq_mask; /* interrupt mask */ ++ u32 adma_rx_dbg0; + u32 int_grp; + } pdma; + struct { +@@ -964,6 +978,8 @@ struct mtk_reg_map { + u32 gdma_to_ppe; + u32 ppe_base; + u32 wdma_base[2]; ++ u32 pse_iq_sta; ++ u32 pse_oq_sta; + }; + + /* struct mtk_eth_data - This is the structure holding all differences +@@ -1006,6 +1022,8 @@ struct mtk_soc_data { + } txrx; + }; + ++#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) ++ + /* currently no SoC has more than 2 macs */ + #define MTK_MAX_DEVS 2 + +@@ -1128,6 +1146,14 @@ struct mtk_eth { + struct rhashtable flow_table; + + struct bpf_prog __rcu *prog; ++ ++ struct { ++ struct delayed_work monitor_work; ++ u32 wdidx; ++ u8 wdma_hang_count; ++ u8 qdma_hang_count; ++ u8 adma_hang_count; ++ } reset; + }; + + /* struct mtk_mac - the structure that holds the info about the MACs of the diff --git a/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch b/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch new file mode 100644 index 0000000000..c21d094ae8 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch @@ -0,0 +1,124 @@ +From: Lorenzo Bianconi +Date: Sat, 14 Jan 2023 18:01:32 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add reset/reset_complete callbacks + +Introduce reset and reset_complete wlan callback to schedule WLAN driver +reset when ethernet/wed driver is resetting. + +Tested-by: Daniel Golle +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3688,6 +3688,11 @@ static void mtk_pending_work(struct work + set_bit(MTK_RESETTING, ð->state); + + mtk_prepare_for_reset(eth); ++ mtk_wed_fe_reset(); ++ /* Run again reset preliminary configuration in order to avoid any ++ * possible race during FE reset since it can run releasing RTNL lock. ++ */ ++ 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++) { +@@ -3725,6 +3730,8 @@ static void mtk_pending_work(struct work + + clear_bit(MTK_RESETTING, ð->state); + ++ mtk_wed_fe_reset_complete(); ++ + rtnl_unlock(); + } + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -205,6 +205,48 @@ mtk_wed_wo_reset(struct mtk_wed_device * + iounmap(reg); + } + ++void mtk_wed_fe_reset(void) ++{ ++ int i; ++ ++ mutex_lock(&hw_lock); ++ ++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { ++ struct mtk_wed_hw *hw = hw_list[i]; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ int err; ++ ++ if (!dev || !dev->wlan.reset) ++ continue; ++ ++ /* reset callback blocks until WLAN reset is completed */ ++ err = dev->wlan.reset(dev); ++ if (err) ++ dev_err(dev->dev, "wlan reset failed: %d\n", err); ++ } ++ ++ mutex_unlock(&hw_lock); ++} ++ ++void mtk_wed_fe_reset_complete(void) ++{ ++ int i; ++ ++ mutex_lock(&hw_lock); ++ ++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { ++ struct mtk_wed_hw *hw = hw_list[i]; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (!dev || !dev->wlan.reset_complete) ++ continue; ++ ++ dev->wlan.reset_complete(dev); ++ } ++ ++ mutex_unlock(&hw_lock); ++} ++ + static struct mtk_wed_hw * + mtk_wed_assign(struct mtk_wed_device *dev) + { +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -128,6 +128,8 @@ void mtk_wed_add_hw(struct device_node * + void mtk_wed_exit(void); + int mtk_wed_flow_add(int index); + void mtk_wed_flow_remove(int index); ++void mtk_wed_fe_reset(void); ++void mtk_wed_fe_reset_complete(void); + #else + static inline void + mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, +@@ -147,6 +149,13 @@ static inline void mtk_wed_flow_remove(i + { + } + ++static inline void mtk_wed_fe_reset(void) ++{ ++} ++ ++static inline void mtk_wed_fe_reset_complete(void) ++{ ++} + #endif + + #ifdef CONFIG_DEBUG_FS +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -151,6 +151,8 @@ struct mtk_wed_device { + void (*release_rx_buf)(struct mtk_wed_device *wed); + void (*update_wo_rx_stats)(struct mtk_wed_device *wed, + struct mtk_wed_wo_rx_stats *stats); ++ int (*reset)(struct mtk_wed_device *wed); ++ void (*reset_complete)(struct mtk_wed_device *wed); + } wlan; + #endif + }; diff --git a/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch new file mode 100644 index 0000000000..c63628da99 --- /dev/null +++ b/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch @@ -0,0 +1,106 @@ +From: Lorenzo Bianconi +Date: Mon, 5 Dec 2022 12:34:42 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: add reset to rx_ring_setup callback + +This patch adds reset parameter to mtk_wed_rx_ring_setup signature +in order to align rx_ring_setup callback to tx_ring_setup one introduced +in 'commit 23dca7a90017 ("net: ethernet: mtk_wed: add reset to +tx_ring_setup callback")' + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Leon Romanovsky +Link: https://lore.kernel.org/r/29c6e7a5469e784406cf3e2920351d1207713d05.1670239984.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1252,7 +1252,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we + } + + static int +-mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, ++ bool reset) + { + u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; +@@ -1261,8 +1262,8 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + return -EINVAL; + + wdma = &dev->tx_wdma[idx]; +- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, +- true)) ++ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, ++ desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1272,6 +1273,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); + ++ if (reset) ++ mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true); ++ + if (!idx) { + wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, + wdma->desc_phys); +@@ -1611,18 +1615,20 @@ mtk_wed_txfree_ring_setup(struct mtk_wed + } + + static int +-mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, ++ bool reset) + { + struct mtk_wed_ring *ring = &dev->rx_ring[idx]; + + if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) + return -EINVAL; + +- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, +- sizeof(*ring->desc), false)) ++ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, ++ sizeof(*ring->desc), false)) + return -ENOMEM; + +- if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, ++ reset)) + return -ENOMEM; + + ring->reg_base = MTK_WED_RING_RX_DATA(idx); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -162,7 +162,7 @@ struct mtk_wed_ops { + int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, + void __iomem *regs, bool reset); + int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, +- void __iomem *regs); ++ void __iomem *regs, bool reset); + int (*txfree_ring_setup)(struct mtk_wed_device *dev, + void __iomem *regs); + int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, +@@ -230,8 +230,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic + (_dev)->ops->irq_get(_dev, _mask) + #define mtk_wed_device_irq_set_mask(_dev, _mask) \ + (_dev)->ops->irq_set_mask(_dev, _mask) +-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ +- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \ ++ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset) + #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ + (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) + #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ +@@ -251,7 +251,7 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) + #define mtk_wed_device_irq_get(_dev, _mask) 0 + #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) +-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV + #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) + #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV + #define mtk_wed_device_stop(_dev) do {} while (0) diff --git a/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch b/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch new file mode 100644 index 0000000000..45af898cf0 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Date: Thu, 27 Oct 2022 19:50:31 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: account for vlan in rx + header length + +The network stack assumes that devices can handle an extra VLAN tag without +increasing the MTU + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -29,7 +29,7 @@ + #define MTK_TX_DMA_BUF_LEN_V2 0xffff + #define MTK_DMA_SIZE 512 + #define MTK_MAC_COUNT 2 +-#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) ++#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 + #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ diff --git a/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch b/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch new file mode 100644 index 0000000000..046a581224 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch @@ -0,0 +1,143 @@ +From: Felix Fietkau +Date: Thu, 27 Oct 2022 19:53:57 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: increase tx ring side for + QDMA devices + +In order to use the hardware traffic shaper feature, a larger tx ring is +needed, especially for the scratch ring, which the hardware shaper uses to +reorder packets. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -944,7 +944,7 @@ static int mtk_init_fq_dma(struct mtk_et + { + const struct mtk_soc_data *soc = eth->soc; + dma_addr_t phy_ring_tail; +- int cnt = MTK_DMA_SIZE; ++ int cnt = MTK_QDMA_RING_SIZE; + dma_addr_t dma_addr; + int i; + +@@ -2208,19 +2208,25 @@ static int mtk_tx_alloc(struct mtk_eth * + struct mtk_tx_ring *ring = ð->tx_ring; + int i, sz = soc->txrx.txd_size; + struct mtk_tx_dma_v2 *txd; ++ int ring_size; + +- ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf), ++ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) ++ ring_size = MTK_QDMA_RING_SIZE; ++ else ++ ring_size = MTK_DMA_SIZE; ++ ++ ring->buf = kcalloc(ring_size, sizeof(*ring->buf), + GFP_KERNEL); + if (!ring->buf) + goto no_tx_mem; + +- ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, ++ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, + &ring->phys, GFP_KERNEL); + if (!ring->dma) + goto no_tx_mem; + +- for (i = 0; i < MTK_DMA_SIZE; i++) { +- int next = (i + 1) % MTK_DMA_SIZE; ++ for (i = 0; i < ring_size; i++) { ++ int next = (i + 1) % ring_size; + u32 next_ptr = ring->phys + next * sz; + + txd = ring->dma + i * sz; +@@ -2240,22 +2246,22 @@ static int mtk_tx_alloc(struct mtk_eth * + * descriptors in ring->dma_pdma. + */ + if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { +- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, ++ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, + &ring->phys_pdma, GFP_KERNEL); + if (!ring->dma_pdma) + goto no_tx_mem; + +- for (i = 0; i < MTK_DMA_SIZE; i++) { ++ for (i = 0; i < ring_size; i++) { + ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF; + ring->dma_pdma[i].txd4 = 0; + } + } + +- ring->dma_size = MTK_DMA_SIZE; +- atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); ++ ring->dma_size = ring_size; ++ atomic_set(&ring->free_count, ring_size - 2); + ring->next_free = ring->dma; + ring->last_free = (void *)txd; +- ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); ++ ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz)); + ring->thresh = MAX_SKB_FRAGS; + + /* make sure that all changes to the dma ring are flushed before we +@@ -2267,14 +2273,14 @@ static int mtk_tx_alloc(struct mtk_eth * + mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); + mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); + mtk_w32(eth, +- ring->phys + ((MTK_DMA_SIZE - 1) * sz), ++ ring->phys + ((ring_size - 1) * sz), + soc->reg_map->qdma.crx_ptr); + mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); + mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, + soc->reg_map->qdma.qtx_cfg); + } else { + mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); +- mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0); ++ mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); + mtk_w32(eth, 0, MT7628_TX_CTX_IDX0); + mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx); + } +@@ -2292,7 +2298,7 @@ static void mtk_tx_clean(struct mtk_eth + int i; + + if (ring->buf) { +- for (i = 0; i < MTK_DMA_SIZE; i++) ++ for (i = 0; i < ring->dma_size; i++) + mtk_tx_unmap(eth, &ring->buf[i], NULL, false); + kfree(ring->buf); + ring->buf = NULL; +@@ -2300,14 +2306,14 @@ static void mtk_tx_clean(struct mtk_eth + + if (ring->dma) { + dma_free_coherent(eth->dma_dev, +- MTK_DMA_SIZE * soc->txrx.txd_size, ++ ring->dma_size * soc->txrx.txd_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- MTK_DMA_SIZE * soc->txrx.txd_size, ++ ring->dma_size * soc->txrx.txd_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2832,7 +2838,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_DMA_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->txrx.txd_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -27,6 +27,7 @@ + #define MTK_MAX_RX_LENGTH_2K 2048 + #define MTK_TX_DMA_BUF_LEN 0x3fff + #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) diff --git a/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch b/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch new file mode 100644 index 0000000000..7e879ca1d5 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch @@ -0,0 +1,52 @@ +From: Felix Fietkau +Date: Fri, 4 Nov 2022 19:49:08 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: avoid port_mg assignment on + MT7622 and newer + +On newer chips, this field is unused and contains some bits related to queue +assignment. Initialize it to 0 in those cases. +Fix offload_version on MT7621 and MT7623, which still need the previous value. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4479,7 +4479,7 @@ static const struct mtk_soc_data mt7621_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7621_CLKS_BITMAP, + .required_pctl = false, +- .offload_version = 2, ++ .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { +@@ -4518,7 +4518,7 @@ static const struct mtk_soc_data mt7623_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, +- .offload_version = 2, ++ .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -175,6 +175,8 @@ int mtk_foe_entry_prepare(struct mtk_eth + val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, pse_port) | + FIELD_PREP(MTK_FOE_IB2_PORT_AG_V2, 0xf); + } else { ++ int port_mg = eth->soc->offload_version > 1 ? 0 : 0x3f; ++ + val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | + FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | + FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | +@@ -182,7 +184,7 @@ int mtk_foe_entry_prepare(struct mtk_eth + entry->ib1 = val; + + val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port) | +- FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | ++ FIELD_PREP(MTK_FOE_IB2_PORT_MG, port_mg) | + FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f); + } + diff --git a/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch b/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch new file mode 100644 index 0000000000..8ceba7831e --- /dev/null +++ b/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch @@ -0,0 +1,654 @@ +From: Felix Fietkau +Date: Thu, 27 Oct 2022 20:17:27 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: implement multi-queue + support for per-port queues + +When sending traffic to multiple ports with different link speeds, queued +packets to one port can drown out tx to other ports. +In order to better handle transmission to multiple ports, use the hardware +shaper feature to implement weighted fair queueing between ports. +Weight and maximum rate are automatically adjusted based on the link speed +of the port. +The first 3 queues are unrestricted and reserved for non-DSA direct tx on +GMAC ports. The following queues are automatically assigned by the MTK DSA +tag driver based on the target port number. +The PPE offload code configures the queues for offloaded traffic in the same +way. +This feature is only supported on devices supporting QDMA. All queues still +share the same DMA ring and descriptor pool. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -55,6 +55,7 @@ static const struct mtk_reg_map mtk_reg_ + }, + .qdma = { + .qtx_cfg = 0x1800, ++ .qtx_sch = 0x1804, + .rx_ptr = 0x1900, + .rx_cnt_cfg = 0x1904, + .qcrx_ptr = 0x1908, +@@ -62,6 +63,7 @@ static const struct mtk_reg_map mtk_reg_ + .rst_idx = 0x1a08, + .delay_irq = 0x1a0c, + .fc_th = 0x1a10, ++ .tx_sch_rate = 0x1a14, + .int_grp = 0x1a20, + .hred = 0x1a44, + .ctx_ptr = 0x1b00, +@@ -117,6 +119,7 @@ static const struct mtk_reg_map mt7986_r + }, + .qdma = { + .qtx_cfg = 0x4400, ++ .qtx_sch = 0x4404, + .rx_ptr = 0x4500, + .rx_cnt_cfg = 0x4504, + .qcrx_ptr = 0x4508, +@@ -134,6 +137,7 @@ static const struct mtk_reg_map mt7986_r + .fq_tail = 0x4724, + .fq_count = 0x4728, + .fq_blen = 0x472c, ++ .tx_sch_rate = 0x4798, + }, + .gdm1_cnt = 0x1c00, + .gdma_to_ppe = 0x3333, +@@ -620,6 +624,75 @@ static void mtk_mac_link_down(struct phy + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + ++static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, ++ int speed) ++{ ++ const struct mtk_soc_data *soc = eth->soc; ++ u32 ofs, val; ++ ++ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) ++ return; ++ ++ val = MTK_QTX_SCH_MIN_RATE_EN | ++ /* minimum: 10 Mbps */ ++ 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)) ++ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; ++ ++ if (IS_ENABLED(CONFIG_SOC_MT7621)) { ++ switch (speed) { ++ case SPEED_10: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); ++ break; ++ case SPEED_100: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3); ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); ++ break; ++ case SPEED_1000: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); ++ break; ++ default: ++ break; ++ } ++ } else { ++ switch (speed) { ++ case SPEED_10: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); ++ break; ++ case SPEED_100: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5); ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); ++ break; ++ case SPEED_1000: ++ val |= MTK_QTX_SCH_MAX_RATE_EN | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ ofs = MTK_QTX_OFFSET * idx; ++ 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, +@@ -645,6 +718,8 @@ static void mtk_mac_link_up(struct phyli + break; + } + ++ mtk_set_queue_speed(mac->hw, mac->id, speed); ++ + /* Configure duplex */ + if (duplex == DUPLEX_FULL) + mcr |= MAC_MCR_FORCE_DPX; +@@ -1105,7 +1180,8 @@ static void mtk_tx_set_dma_desc_v1(struc + + WRITE_ONCE(desc->txd1, info->addr); + +- data = TX_DMA_SWC | TX_DMA_PLEN0(info->size); ++ data = TX_DMA_SWC | TX_DMA_PLEN0(info->size) | ++ FIELD_PREP(TX_DMA_PQID, info->qid); + if (info->last) + data |= TX_DMA_LS0; + WRITE_ONCE(desc->txd3, data); +@@ -1139,9 +1215,6 @@ static void mtk_tx_set_dma_desc_v2(struc + data |= TX_DMA_LS0; + WRITE_ONCE(desc->txd3, data); + +- if (!info->qid && mac->id) +- info->qid = MTK_QDMA_GMAC2_QID; +- + 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); +@@ -1185,11 +1258,12 @@ static int mtk_tx_map(struct sk_buff *sk + .gso = gso, + .csum = skb->ip_summed == CHECKSUM_PARTIAL, + .vlan = skb_vlan_tag_present(skb), +- .qid = skb->mark & MTK_QDMA_TX_MASK, ++ .qid = skb_get_queue_mapping(skb), + .vlan_tci = skb_vlan_tag_get(skb), + .first = true, + .last = !skb_is_nonlinear(skb), + }; ++ struct netdev_queue *txq; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + const struct mtk_soc_data *soc = eth->soc; +@@ -1197,8 +1271,10 @@ static int mtk_tx_map(struct sk_buff *sk + struct mtk_tx_dma *itxd_pdma, *txd_pdma; + struct mtk_tx_buf *itx_buf, *tx_buf; + int i, n_desc = 1; ++ int queue = skb_get_queue_mapping(skb); + int k = 0; + ++ txq = netdev_get_tx_queue(dev, queue); + itxd = ring->next_free; + itxd_pdma = qdma_to_pdma(ring, itxd); + if (itxd == ring->last_free) +@@ -1247,7 +1323,7 @@ static int mtk_tx_map(struct sk_buff *sk + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, + soc->txrx.dma_max_len); +- txd_info.qid = skb->mark & MTK_QDMA_TX_MASK; ++ txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); + txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, +@@ -1286,7 +1362,7 @@ static int mtk_tx_map(struct sk_buff *sk + txd_pdma->txd2 |= TX_DMA_LS1; + } + +- netdev_sent_queue(dev, skb->len); ++ netdev_tx_sent_queue(txq, skb->len); + skb_tx_timestamp(skb); + + ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); +@@ -1298,8 +1374,7 @@ static int mtk_tx_map(struct sk_buff *sk + wmb(); + + if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { +- if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || +- !netdev_xmit_more()) ++ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) + mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); + } else { + int next_idx; +@@ -1368,7 +1443,7 @@ static void mtk_wake_queue(struct mtk_et + for (i = 0; i < MTK_MAC_COUNT; i++) { + if (!eth->netdev[i]) + continue; +- netif_wake_queue(eth->netdev[i]); ++ netif_tx_wake_all_queues(eth->netdev[i]); + } + } + +@@ -1392,7 +1467,7 @@ static netdev_tx_t mtk_start_xmit(struct + + tx_num = mtk_cal_txd_req(eth, skb); + if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { +- netif_stop_queue(dev); ++ netif_tx_stop_all_queues(dev); + netif_err(eth, tx_queued, dev, + "Tx Ring full when queue awake!\n"); + spin_unlock(ð->page_lock); +@@ -1418,7 +1493,7 @@ static netdev_tx_t mtk_start_xmit(struct + goto drop; + + if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) +- netif_stop_queue(dev); ++ netif_tx_stop_all_queues(dev); + + spin_unlock(ð->page_lock); + +@@ -1585,10 +1660,12 @@ static int mtk_xdp_submit_frame(struct m + struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; ++ struct mtk_mac *mac = netdev_priv(dev); + struct mtk_tx_dma_desc_info txd_info = { + .size = xdpf->len, + .first = true, + .last = !xdp_frame_has_frags(xdpf), ++ .qid = mac->id, + }; + int err, index = 0, n_desc = 1, nr_frags; + struct mtk_tx_buf *htx_buf, *tx_buf; +@@ -1638,6 +1715,7 @@ static int mtk_xdp_submit_frame(struct m + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = skb_frag_size(&sinfo->frags[index]); + txd_info.last = index + 1 == nr_frags; ++ txd_info.qid = mac->id; + data = skb_frag_address(&sinfo->frags[index]); + + index++; +@@ -1992,8 +2070,46 @@ rx_done: + return done; + } + ++struct mtk_poll_state { ++ struct netdev_queue *txq; ++ unsigned int total; ++ unsigned int done; ++ unsigned int bytes; ++}; ++ ++static void ++mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac, ++ struct sk_buff *skb) ++{ ++ struct netdev_queue *txq; ++ struct net_device *dev; ++ unsigned int bytes = skb->len; ++ ++ state->total++; ++ eth->tx_packets++; ++ eth->tx_bytes += bytes; ++ ++ dev = eth->netdev[mac]; ++ if (!dev) ++ return; ++ ++ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); ++ if (state->txq == txq) { ++ state->done++; ++ state->bytes += bytes; ++ return; ++ } ++ ++ if (state->txq) ++ netdev_tx_completed_queue(state->txq, state->done, state->bytes); ++ ++ state->txq = txq; ++ state->done = 1; ++ state->bytes = bytes; ++} ++ + static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, +- unsigned int *done, unsigned int *bytes) ++ struct mtk_poll_state *state) + { + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + struct mtk_tx_ring *ring = ð->tx_ring; +@@ -2025,12 +2141,9 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { +- if (tx_buf->type == MTK_TYPE_SKB) { +- struct sk_buff *skb = tx_buf->data; ++ if (tx_buf->type == MTK_TYPE_SKB) ++ mtk_poll_tx_done(eth, state, mac, tx_buf->data); + +- bytes[mac] += skb->len; +- done[mac]++; +- } + budget--; + } + mtk_tx_unmap(eth, tx_buf, &bq, true); +@@ -2049,7 +2162,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + } + + static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, +- unsigned int *done, unsigned int *bytes) ++ struct mtk_poll_state *state) + { + struct mtk_tx_ring *ring = ð->tx_ring; + struct mtk_tx_buf *tx_buf; +@@ -2067,12 +2180,8 @@ static int mtk_poll_tx_pdma(struct mtk_e + break; + + if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { +- if (tx_buf->type == MTK_TYPE_SKB) { +- struct sk_buff *skb = tx_buf->data; +- +- bytes[0] += skb->len; +- done[0]++; +- } ++ if (tx_buf->type == MTK_TYPE_SKB) ++ mtk_poll_tx_done(eth, state, 0, tx_buf->data); + budget--; + } + mtk_tx_unmap(eth, tx_buf, &bq, true); +@@ -2094,26 +2203,15 @@ static int mtk_poll_tx(struct mtk_eth *e + { + struct mtk_tx_ring *ring = ð->tx_ring; + struct dim_sample dim_sample = {}; +- unsigned int done[MTK_MAX_DEVS]; +- unsigned int bytes[MTK_MAX_DEVS]; +- int total = 0, i; +- +- memset(done, 0, sizeof(done)); +- memset(bytes, 0, sizeof(bytes)); ++ struct mtk_poll_state state = {}; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +- budget = mtk_poll_tx_qdma(eth, budget, done, bytes); ++ budget = mtk_poll_tx_qdma(eth, budget, &state); + else +- budget = mtk_poll_tx_pdma(eth, budget, done, bytes); ++ budget = mtk_poll_tx_pdma(eth, budget, &state); + +- for (i = 0; i < MTK_MAC_COUNT; i++) { +- if (!eth->netdev[i] || !done[i]) +- continue; +- netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); +- total += done[i]; +- eth->tx_packets += done[i]; +- eth->tx_bytes += bytes[i]; +- } ++ if (state.txq) ++ netdev_tx_completed_queue(state.txq, state.done, state.bytes); + + dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, + &dim_sample); +@@ -2123,7 +2221,7 @@ static int mtk_poll_tx(struct mtk_eth *e + (atomic_read(&ring->free_count) > ring->thresh)) + mtk_wake_queue(eth); + +- return total; ++ return state.total; + } + + static void mtk_handle_status_irq(struct mtk_eth *eth) +@@ -2209,6 +2307,7 @@ static int mtk_tx_alloc(struct mtk_eth * + int i, sz = soc->txrx.txd_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; ++ u32 ofs, val; + + if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) + ring_size = MTK_QDMA_RING_SIZE; +@@ -2276,8 +2375,25 @@ static int mtk_tx_alloc(struct mtk_eth * + ring->phys + ((ring_size - 1) * sz), + soc->reg_map->qdma.crx_ptr); + mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); +- mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, +- soc->reg_map->qdma.qtx_cfg); ++ ++ for (i = 0, ofs = 0; i < MTK_QDMA_NUM_QUEUES; i++) { ++ val = (QDMA_RES_THRES << 8) | QDMA_RES_THRES; ++ mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs); ++ ++ val = MTK_QTX_SCH_MIN_RATE_EN | ++ /* minimum: 10 Mbps */ ++ 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)) ++ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; ++ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); ++ ofs += MTK_QTX_OFFSET; ++ } ++ val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); ++ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); + } else { + mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); + mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); +@@ -2962,7 +3078,7 @@ static int mtk_start_dma(struct mtk_eth + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) + val |= MTK_MUTLI_CNT | MTK_RESV_BUF | + MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | +- MTK_CHK_DDONE_EN; ++ MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; + else + val |= MTK_RX_BT_32DWORDS; + mtk_w32(eth, val, reg_map->qdma.glo_cfg); +@@ -3008,6 +3124,45 @@ static void mtk_gdm_config(struct mtk_et + mtk_w32(eth, 0, MTK_RST_GL); + } + ++static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr) ++{ ++ struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier); ++ struct mtk_eth *eth = mac->hw; ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ struct ethtool_link_ksettings s; ++ struct net_device *ldev; ++ struct list_head *iter; ++ struct dsa_port *dp; ++ ++ if (event != NETDEV_CHANGE) ++ return NOTIFY_DONE; ++ ++ netdev_for_each_lower_dev(dev, ldev, iter) { ++ if (netdev_priv(ldev) == mac) ++ goto found; ++ } ++ ++ return NOTIFY_DONE; ++ ++found: ++ if (!dsa_slave_dev_check(dev)) ++ return NOTIFY_DONE; ++ ++ if (__ethtool_get_link_ksettings(dev, &s)) ++ return NOTIFY_DONE; ++ ++ if (s.base.speed == 0 || s.base.speed == ((__u32)-1)) ++ return NOTIFY_DONE; ++ ++ dp = dsa_port_from_netdev(dev); ++ if (dp->index >= MTK_QDMA_NUM_QUEUES) ++ return NOTIFY_DONE; ++ ++ mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); ++ ++ return NOTIFY_DONE; ++} ++ + static int mtk_open(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); +@@ -3050,7 +3205,8 @@ static int mtk_open(struct net_device *d + refcount_inc(ð->dma_refcnt); + + phylink_start(mac->phylink); +- netif_start_queue(dev); ++ netif_tx_start_all_queues(dev); ++ + return 0; + } + +@@ -3759,8 +3915,12 @@ static int mtk_unreg_dev(struct mtk_eth + int i; + + for (i = 0; i < MTK_MAC_COUNT; i++) { ++ struct mtk_mac *mac; + if (!eth->netdev[i]) + continue; ++ mac = netdev_priv(eth->netdev[i]); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) ++ unregister_netdevice_notifier(&mac->device_notifier); + unregister_netdev(eth->netdev[i]); + } + +@@ -3977,6 +4137,23 @@ static int mtk_set_rxnfc(struct net_devi + return ret; + } + ++static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ unsigned int queue = 0; ++ ++ if (netdev_uses_dsa(dev)) ++ queue = skb_get_queue_mapping(skb) + 3; ++ else ++ queue = mac->id; ++ ++ if (queue >= dev->num_tx_queues) ++ queue = 0; ++ ++ return queue; ++} ++ + static const struct ethtool_ops mtk_ethtool_ops = { + .get_link_ksettings = mtk_get_link_ksettings, + .set_link_ksettings = mtk_set_link_ksettings, +@@ -4011,6 +4188,7 @@ static const struct net_device_ops mtk_n + .ndo_setup_tc = mtk_eth_setup_tc, + .ndo_bpf = mtk_xdp, + .ndo_xdp_xmit = mtk_xdp_xmit, ++ .ndo_select_queue = mtk_select_queue, + }; + + static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) +@@ -4020,6 +4198,7 @@ static int mtk_add_mac(struct mtk_eth *e + struct phylink *phylink; + struct mtk_mac *mac; + int id, err; ++ int txqs = 1; + + if (!_id) { + dev_err(eth->dev, "missing mac id\n"); +@@ -4037,7 +4216,10 @@ static int mtk_add_mac(struct mtk_eth *e + return -EINVAL; + } + +- eth->netdev[id] = alloc_etherdev(sizeof(*mac)); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) ++ txqs = MTK_QDMA_NUM_QUEUES; ++ ++ eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1); + if (!eth->netdev[id]) { + dev_err(eth->dev, "alloc_etherdev failed\n"); + return -ENOMEM; +@@ -4145,6 +4327,11 @@ static int mtk_add_mac(struct mtk_eth *e + else + eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { ++ mac->device_notifier.notifier_call = mtk_device_event; ++ register_netdevice_notifier(&mac->device_notifier); ++ } ++ + return 0; + + free_netdev: +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -22,6 +22,7 @@ + #include + #include "mtk_ppe.h" + ++#define MTK_QDMA_NUM_QUEUES 16 + #define MTK_QDMA_PAGE_SIZE 2048 + #define MTK_MAX_RX_LENGTH 1536 + #define MTK_MAX_RX_LENGTH_2K 2048 +@@ -216,8 +217,26 @@ + #define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3) + + /* QDMA TX Queue Configuration Registers */ ++#define MTK_QTX_OFFSET 0x10 + #define QDMA_RES_THRES 4 + ++/* QDMA Tx Queue Scheduler Configuration Registers */ ++#define MTK_QTX_SCH_TX_SEL BIT(31) ++#define MTK_QTX_SCH_TX_SEL_V2 GENMASK(31, 30) ++ ++#define MTK_QTX_SCH_LEAKY_BUCKET_EN BIT(30) ++#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE GENMASK(29, 28) ++#define MTK_QTX_SCH_MIN_RATE_EN BIT(27) ++#define MTK_QTX_SCH_MIN_RATE_MAN GENMASK(26, 20) ++#define MTK_QTX_SCH_MIN_RATE_EXP GENMASK(19, 16) ++#define MTK_QTX_SCH_MAX_RATE_WEIGHT GENMASK(15, 12) ++#define MTK_QTX_SCH_MAX_RATE_EN BIT(11) ++#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4) ++#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0) ++ ++/* QDMA TX Scheduler Rate Control Register */ ++#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15) ++ + /* QDMA Global Configuration Register */ + #define MTK_RX_2B_OFFSET BIT(31) + #define MTK_RX_BT_32DWORDS (3 << 11) +@@ -236,6 +255,7 @@ + #define MTK_WCOMP_EN BIT(24) + #define MTK_RESV_BUF (0x40 << 16) + #define MTK_MUTLI_CNT (0x4 << 12) ++#define MTK_LEAKY_BUCKET_EN BIT(11) + + /* QDMA Flow Control Register */ + #define FC_THRES_DROP_MODE BIT(20) +@@ -266,8 +286,6 @@ + #define MTK_STAT_OFFSET 0x40 + + /* QDMA TX NUM */ +-#define MTK_QDMA_TX_NUM 16 +-#define MTK_QDMA_TX_MASK (MTK_QDMA_TX_NUM - 1) + #define QID_BITS_V2(x) (((x) & 0x3f) << 16) + #define MTK_QDMA_GMAC2_QID 8 + +@@ -297,6 +315,7 @@ + #define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) + #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) + #define TX_DMA_SWC BIT(14) ++#define TX_DMA_PQID GENMASK(3, 0) + + /* PDMA on MT7628 */ + #define TX_DMA_DONE BIT(31) +@@ -957,6 +976,7 @@ struct mtk_reg_map { + } pdma; + struct { + u32 qtx_cfg; /* tx queue configuration */ ++ u32 qtx_sch; /* tx queue scheduler configuration */ + u32 rx_ptr; /* rx base pointer */ + u32 rx_cnt_cfg; /* rx max count configuration */ + u32 qcrx_ptr; /* rx cpu pointer */ +@@ -974,6 +994,7 @@ struct mtk_reg_map { + u32 fq_tail; /* fq tail pointer */ + u32 fq_count; /* fq free page count */ + u32 fq_blen; /* fq free page buffer length */ ++ u32 tx_sch_rate; /* tx scheduler rate control registers */ + } qdma; + u32 gdm1_cnt; + u32 gdma_to_ppe; +@@ -1177,6 +1198,7 @@ struct mtk_mac { + __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; + int hwlro_ip_cnt; + unsigned int syscfg0; ++ struct notifier_block device_notifier; + }; + + /* the struct describing the SoC. these are declared in the soc_xyz.c files */ diff --git a/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch b/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch new file mode 100644 index 0000000000..186df4bdc9 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Date: Fri, 28 Oct 2022 18:16:03 +0200 +Subject: [PATCH] net: dsa: tag_mtk: assign per-port queues + +Keeps traffic sent to the switch within link speed limits + +Signed-off-by: Felix Fietkau +--- + +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -25,6 +25,8 @@ static struct sk_buff *mtk_tag_xmit(stru + u8 xmit_tpid; + u8 *mtk_tag; + ++ skb_set_queue_mapping(skb, dp->index); ++ + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is + * being combined. Only in this way we can allow the switch can parse diff --git a/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch b/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch new file mode 100644 index 0000000000..d29177eee7 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch @@ -0,0 +1,93 @@ +From: Felix Fietkau +Date: Thu, 3 Nov 2022 17:49:44 +0100 +Subject: [PATCH] net: ethernet: mediatek: ppe: assign per-port queues + for offloaded traffic + +Keeps traffic sent to the switch within link speed limits + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -399,6 +399,24 @@ int mtk_foe_entry_set_wdma(struct mtk_et + return 0; + } + ++int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, ++ unsigned int queue) ++{ ++ u32 *ib2 = mtk_foe_entry_ib2(eth, entry); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ *ib2 &= ~MTK_FOE_IB2_QID_V2; ++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); ++ *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; ++ } else { ++ *ib2 &= ~MTK_FOE_IB2_QID; ++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, queue); ++ *ib2 |= MTK_FOE_IB2_PSE_QOS; ++ } ++ ++ return 0; ++} ++ + static bool + mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry, + struct mtk_foe_entry *data) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -68,7 +68,9 @@ enum { + #define MTK_FOE_IB2_DSCP GENMASK(31, 24) + + /* CONFIG_MEDIATEK_NETSYS_V2 */ ++#define MTK_FOE_IB2_QID_V2 GENMASK(6, 0) + #define MTK_FOE_IB2_PORT_MG_V2 BIT(7) ++#define MTK_FOE_IB2_PSE_QOS_V2 BIT(8) + #define MTK_FOE_IB2_DEST_PORT_V2 GENMASK(12, 9) + #define MTK_FOE_IB2_MULTICAST_V2 BIT(13) + #define MTK_FOE_IB2_WDMA_WINFO_V2 BIT(19) +@@ -351,6 +353,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e + int sid); + int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, + int wdma_idx, int txq, int bss, int wcid); ++int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, ++ unsigned int queue); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -188,7 +188,7 @@ mtk_flow_set_output_device(struct mtk_et + int *wed_index) + { + struct mtk_wdma_info info = {}; +- int pse_port, dsa_port; ++ int pse_port, dsa_port, queue; + + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { + mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, +@@ -212,8 +212,6 @@ mtk_flow_set_output_device(struct mtk_et + } + + dsa_port = mtk_flow_get_dsa_port(&dev); +- if (dsa_port >= 0) +- mtk_foe_entry_set_dsa(eth, foe, dsa_port); + + if (dev == eth->netdev[0]) + pse_port = 1; +@@ -222,6 +220,14 @@ mtk_flow_set_output_device(struct mtk_et + else + return -EOPNOTSUPP; + ++ if (dsa_port >= 0) { ++ mtk_foe_entry_set_dsa(eth, foe, dsa_port); ++ queue = 3 + dsa_port; ++ } else { ++ queue = pse_port - 1; ++ } ++ mtk_foe_entry_set_queue(eth, foe, queue); ++ + out: + mtk_foe_entry_set_pse_port(eth, foe, pse_port); + diff --git a/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch b/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch new file mode 100644 index 0000000000..6b7f3d6018 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch @@ -0,0 +1,72 @@ +From: Felix Fietkau +Date: Tue, 8 Nov 2022 15:03:15 +0100 +Subject: [PATCH] net: dsa: add support for DSA rx offloading via + metadata dst + +If a metadata dst is present with the type METADATA_HW_PORT_MUX on a dsa cpu +port netdev, assume that it carries the port number and that there is no DSA +tag present in the skb data. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -971,12 +971,14 @@ bool __skb_flow_dissect(const struct net + #if IS_ENABLED(CONFIG_NET_DSA) + if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) && + proto == htons(ETH_P_XDSA))) { ++ struct metadata_dst *md_dst = skb_metadata_dst(skb); + const struct dsa_device_ops *ops; + int offset = 0; + + ops = skb->dev->dsa_ptr->tag_ops; + /* Only DSA header taggers break flow dissection */ +- if (ops->needed_headroom) { ++ if (ops->needed_headroom && ++ (!md_dst || md_dst->type != METADATA_HW_PORT_MUX)) { + if (ops->flow_dissect) + ops->flow_dissect(skb, &proto, &offset); + else +--- a/net/dsa/dsa.c ++++ b/net/dsa/dsa.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "dsa_priv.h" + +@@ -216,6 +217,7 @@ static bool dsa_skb_defer_rx_timestamp(s + static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *unused) + { ++ struct metadata_dst *md_dst = skb_metadata_dst(skb); + struct dsa_port *cpu_dp = dev->dsa_ptr; + struct sk_buff *nskb = NULL; + struct dsa_slave_priv *p; +@@ -229,7 +231,22 @@ static int dsa_switch_rcv(struct sk_buff + if (!skb) + return 0; + +- nskb = cpu_dp->rcv(skb, dev); ++ if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) { ++ unsigned int port = md_dst->u.port_info.port_id; ++ ++ skb_dst_drop(skb); ++ if (!skb_has_extensions(skb)) ++ skb->slow_gro = 0; ++ ++ skb->dev = dsa_master_find_slave(dev, 0, port); ++ if (likely(skb->dev)) { ++ dsa_default_offload_fwd_mark(skb); ++ nskb = skb; ++ } ++ } else { ++ nskb = cpu_dp->rcv(skb, dev); ++ } ++ + if (!nskb) { + kfree_skb(skb); + return 0; diff --git a/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch b/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch new file mode 100644 index 0000000000..b8e3452f30 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch @@ -0,0 +1,192 @@ +From: Felix Fietkau +Date: Fri, 28 Oct 2022 11:01:12 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix VLAN rx hardware + acceleration + +- enable VLAN untagging for PDMA rx +- make it possible to disable the feature via ethtool +- pass VLAN tag to the DSA driver +- untag special tag on PDMA only if no non-DSA devices are in use +- disable special tag untagging on 7986 for now, since it's not working yet + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include "mtk_eth_soc.h" + #include "mtk_wed.h" +@@ -2021,16 +2022,22 @@ static int mtk_poll_rx(struct napi_struc + htons(RX_DMA_VPID(trxd.rxd4)), + RX_DMA_VID(trxd.rxd4)); + } else if (trxd.rxd2 & RX_DMA_VTAG) { +- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ++ __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), + RX_DMA_VID(trxd.rxd3)); + } ++ } ++ ++ /* When using VLAN untagging in combination with DSA, the ++ * hardware treats the MTK special tag as a VLAN and untags it. ++ */ ++ if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { ++ unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); + +- /* If the device is attached to a dsa switch, the special +- * tag inserted in VLAN field by hw switch can * be offloaded +- * by RX HW VLAN offload. Clear vlan info. +- */ +- if (netdev_uses_dsa(netdev)) +- __vlan_hwaccel_clear_tag(skb); ++ if (port < ARRAY_SIZE(eth->dsa_meta) && ++ eth->dsa_meta[port]) ++ skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); ++ ++ __vlan_hwaccel_clear_tag(skb); + } + + skb_record_rx_queue(skb, 0); +@@ -2858,15 +2865,30 @@ static netdev_features_t mtk_fix_feature + + static int mtk_set_features(struct net_device *dev, netdev_features_t features) + { +- int err = 0; ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ netdev_features_t diff = dev->features ^ features; ++ int i; ++ ++ if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) ++ mtk_hwlro_netdev_disable(dev); + +- if (!((dev->features ^ features) & NETIF_F_LRO)) ++ /* Set RX VLAN offloading */ ++ if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) + return 0; + +- if (!(features & NETIF_F_LRO)) +- mtk_hwlro_netdev_disable(dev); ++ mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), ++ MTK_CDMP_EG_CTRL); + +- return err; ++ /* sync features with other MAC */ ++ for (i = 0; i < MTK_MAC_COUNT; i++) { ++ if (!eth->netdev[i] || eth->netdev[i] == dev) ++ continue; ++ eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; ++ eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; ++ } ++ ++ return 0; + } + + /* wait for DMA to finish whatever it is doing before we start using it again */ +@@ -3163,11 +3185,45 @@ found: + return NOTIFY_DONE; + } + ++static bool mtk_uses_dsa(struct net_device *dev) ++{ ++#if IS_ENABLED(CONFIG_NET_DSA) ++ return netdev_uses_dsa(dev) && ++ dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_MTK; ++#else ++ return false; ++#endif ++} ++ + static int mtk_open(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; +- int err; ++ int i, err; ++ ++ if (mtk_uses_dsa(dev) && !eth->prog) { ++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { ++ struct metadata_dst *md_dst = eth->dsa_meta[i]; ++ ++ if (md_dst) ++ continue; ++ ++ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, ++ GFP_KERNEL); ++ if (!md_dst) ++ return -ENOMEM; ++ ++ md_dst->u.port_info.port_id = i; ++ eth->dsa_meta[i] = md_dst; ++ } ++ } else { ++ /* Hardware special tag parsing needs to be disabled if at least ++ * one MAC does not use DSA. ++ */ ++ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ val &= ~MTK_CDMP_STAG_EN; ++ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); ++ } + + err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); + if (err) { +@@ -3688,6 +3744,10 @@ 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)) { ++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); ++ } + + /* Enable RX VLan Offloading */ + mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); +@@ -3907,6 +3967,12 @@ static int mtk_free_dev(struct mtk_eth * + free_netdev(eth->netdev[i]); + } + ++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { ++ if (!eth->dsa_meta[i]) ++ break; ++ metadata_dst_free(eth->dsa_meta[i]); ++ } ++ + return 0; + } + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -22,6 +22,9 @@ + #include + #include "mtk_ppe.h" + ++#define MTK_MAX_DSA_PORTS 7 ++#define MTK_DSA_PORT_MASK GENMASK(2, 0) ++ + #define MTK_QDMA_NUM_QUEUES 16 + #define MTK_QDMA_PAGE_SIZE 2048 + #define MTK_MAX_RX_LENGTH 1536 +@@ -105,6 +108,9 @@ + #define MTK_CDMQ_IG_CTRL 0x1400 + #define MTK_CDMQ_STAG_EN BIT(0) + ++/* CDMQ Exgress Control Register */ ++#define MTK_CDMQ_EG_CTRL 0x1404 ++ + /* CDMP Ingress Control Register */ + #define MTK_CDMP_IG_CTRL 0x400 + #define MTK_CDMP_STAG_EN BIT(0) +@@ -1164,6 +1170,8 @@ struct mtk_eth { + + int ip_align; + ++ struct metadata_dst *dsa_meta[MTK_MAX_DSA_PORTS]; ++ + struct mtk_ppe *ppe[2]; + struct rhashtable flow_table; + diff --git a/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch b/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch new file mode 100644 index 0000000000..a88df2b8e3 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch @@ -0,0 +1,42 @@ +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 28 Jan 2023 12:42:32 +0300 +Subject: [PATCH] net: ethernet: mtk_eth_soc: disable hardware DSA untagging + for second MAC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to my tests on MT7621AT and MT7623NI SoCs, hardware DSA untagging +won't work on the second MAC. Therefore, disable this feature when the +second MAC of the MT7621 and MT7623 SoCs is being used. + +Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") +Link: https://lore.kernel.org/netdev/6249fc14-b38a-c770-36b4-5af6d41c21d3@arinc9.com/ +Tested-by: Arınç ÜNAL +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20230128094232.2451947-1-arinc.unal@arinc9.com +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3201,7 +3201,8 @@ static int mtk_open(struct net_device *d + struct mtk_eth *eth = mac->hw; + int i, err; + +- if (mtk_uses_dsa(dev) && !eth->prog) { ++ if ((mtk_uses_dsa(dev) && !eth->prog) && ++ !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { + for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { + struct metadata_dst *md_dst = eth->dsa_meta[i]; + +@@ -3218,7 +3219,8 @@ static int mtk_open(struct net_device *d + } + } else { + /* Hardware special tag parsing needs to be disabled if at least +- * one MAC does not use DSA. ++ * one MAC does not use DSA, or the second MAC of the MT7621 and ++ * MT7623 SoCs is being used. + */ + u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); + val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch b/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch new file mode 100644 index 0000000000..8da728b9e9 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch @@ -0,0 +1,54 @@ +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sun, 5 Feb 2023 20:53:31 +0300 +Subject: [PATCH] net: ethernet: mtk_eth_soc: enable special tag when any MAC + uses DSA +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The special tag is only enabled when the first MAC uses DSA. However, it +must be enabled when any MAC uses DSA. Change the check accordingly. + +This fixes hardware DSA untagging not working on the second MAC of the +MT7621 and MT7623 SoCs, and likely other SoCs too. Therefore, remove the +check that disables hardware DSA untagging for the second MAC of the MT7621 +and MT7623 SoCs. + +Fixes: a1f47752fd62 ("net: ethernet: mtk_eth_soc: disable hardware DSA untagging for second MAC") +Co-developed-by: Richard van Schagen +Signed-off-by: Richard van Schagen +Signed-off-by: Arınç ÜNAL +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3136,7 +3136,7 @@ static void mtk_gdm_config(struct mtk_et + + val |= config; + +- if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) ++ if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) + val |= MTK_GDMA_SPECIAL_TAG; + + mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); +@@ -3201,8 +3201,7 @@ static int mtk_open(struct net_device *d + struct mtk_eth *eth = mac->hw; + int i, err; + +- if ((mtk_uses_dsa(dev) && !eth->prog) && +- !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { ++ if (mtk_uses_dsa(dev) && !eth->prog) { + for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { + struct metadata_dst *md_dst = eth->dsa_meta[i]; + +@@ -3219,8 +3218,7 @@ static int mtk_open(struct net_device *d + } + } else { + /* Hardware special tag parsing needs to be disabled if at least +- * one MAC does not use DSA, or the second MAC of the MT7621 and +- * MT7623 SoCs is being used. ++ * one MAC does not use DSA. + */ + u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); + val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch b/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch new file mode 100644 index 0000000000..51cd572ab2 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch @@ -0,0 +1,129 @@ +From: Vladimir Oltean +Date: Tue, 7 Feb 2023 12:30:27 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix DSA TX tag hwaccel for switch + port 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Arınç reports that on his MT7621AT Unielec U7621-06 board and MT7623NI +Bananapi BPI-R2, packets received by the CPU over mt7530 switch port 0 +(of which this driver acts as the DSA master) are not processed +correctly by software. More precisely, they arrive without a DSA tag +(in packet or in the hwaccel area - skb_metadata_dst()), so DSA cannot +demux them towards the switch's interface for port 0. Traffic from other +ports receives a skb_metadata_dst() with the correct port and is demuxed +properly. + +Looking at mtk_poll_rx(), it becomes apparent that this driver uses the +skb vlan hwaccel area: + + union { + u32 vlan_all; + struct { + __be16 vlan_proto; + __u16 vlan_tci; + }; + }; + +as a temporary storage for the VLAN hwaccel tag, or the DSA hwaccel tag. +If this is a DSA master it's a DSA hwaccel tag, and finally clears up +the skb VLAN hwaccel header. + +I'm guessing that the problem is the (mis)use of API. +skb_vlan_tag_present() looks like this: + + #define skb_vlan_tag_present(__skb) (!!(__skb)->vlan_all) + +So if both vlan_proto and vlan_tci are zeroes, skb_vlan_tag_present() +returns precisely false. I don't know for sure what is the format of the +DSA hwaccel tag, but I surely know that lowermost 3 bits of vlan_proto +are 0 when receiving from port 0: + + unsigned int port = vlan_proto & GENMASK(2, 0); + +If the RX descriptor has no other bits set to non-zero values in +RX_DMA_VTAG, then the call to __vlan_hwaccel_put_tag() will not, in +fact, make the subsequent skb_vlan_tag_present() return true, because +it's implemented like this: + +static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb, + __be16 vlan_proto, u16 vlan_tci) +{ + skb->vlan_proto = vlan_proto; + skb->vlan_tci = vlan_tci; +} + +What we need to do to fix this problem (assuming this is the problem) is +to stop using skb->vlan_all as temporary storage for driver affairs, and +just create some local variables that serve the same purpose, but +hopefully better. Instead of calling skb_vlan_tag_present(), let's look +at a boolean has_hwaccel_tag which we set to true when the RX DMA +descriptors have something. Disambiguate based on netdev_uses_dsa() +whether this is a VLAN or DSA hwaccel tag, and only call +__vlan_hwaccel_put_tag() if we're certain it's a VLAN tag. + +Arınç confirms that the treatment works, so this validates the +assumption. + +Link: https://lore.kernel.org/netdev/704f3a72-fc9e-714a-db54-272e17612637@arinc9.com/ +Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") +Reported-by: Arınç ÜNAL +Tested-by: Arınç ÜNAL +Signed-off-by: Vladimir Oltean +Reviewed-by: Felix Fietkau +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1877,7 +1877,9 @@ static int mtk_poll_rx(struct napi_struc + + while (done < budget) { + unsigned int pktlen, *rxdcsum; ++ bool has_hwaccel_tag = false; + struct net_device *netdev; ++ u16 vlan_proto, vlan_tci; + dma_addr_t dma_addr; + u32 hash, reason; + int mac = 0; +@@ -2017,27 +2019,29 @@ static int mtk_poll_rx(struct napi_struc + + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +- if (trxd.rxd3 & RX_DMA_VTAG_V2) +- __vlan_hwaccel_put_tag(skb, +- htons(RX_DMA_VPID(trxd.rxd4)), +- RX_DMA_VID(trxd.rxd4)); ++ if (trxd.rxd3 & RX_DMA_VTAG_V2) { ++ vlan_proto = RX_DMA_VPID(trxd.rxd4); ++ vlan_tci = RX_DMA_VID(trxd.rxd4); ++ has_hwaccel_tag = true; ++ } + } else if (trxd.rxd2 & RX_DMA_VTAG) { +- __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), +- RX_DMA_VID(trxd.rxd3)); ++ vlan_proto = RX_DMA_VPID(trxd.rxd3); ++ vlan_tci = RX_DMA_VID(trxd.rxd3); ++ has_hwaccel_tag = true; + } + } + + /* When using VLAN untagging in combination with DSA, the + * hardware treats the MTK special tag as a VLAN and untags it. + */ +- if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { +- unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); ++ if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { ++ unsigned int port = vlan_proto & GENMASK(2, 0); + + if (port < ARRAY_SIZE(eth->dsa_meta) && + eth->dsa_meta[port]) + skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); +- +- __vlan_hwaccel_clear_tag(skb); ++ } else if (has_hwaccel_tag) { ++ __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); + } + + skb_record_rx_queue(skb, 0); diff --git a/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch b/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch new file mode 100644 index 0000000000..a3bb1c5db7 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch @@ -0,0 +1,26 @@ +From: Christophe JAILLET +Date: Sun, 12 Feb 2023 07:51:51 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: No need to clear memory after a + dma_alloc_coherent() call + +dma_alloc_coherent() already clears the allocated memory, there is no need +to explicitly call memset(). + +Moreover, it is likely that the size in the memset() is incorrect and +should be "size * sizeof(*ring->desc)". + +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/d5acce7dd108887832c9719f62c7201b4c83b3fb.1676184599.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -779,7 +779,6 @@ mtk_wed_rro_ring_alloc(struct mtk_wed_de + + ring->desc_size = sizeof(*ring->desc); + ring->size = size; +- memset(ring->desc, 0, size); + + return 0; + } diff --git a/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch b/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch new file mode 100644 index 0000000000..e043a681da --- /dev/null +++ b/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch @@ -0,0 +1,61 @@ +From: Lorenzo Bianconi +Date: Wed, 7 Dec 2022 15:04:54 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: fix some possible NULL pointer + dereferences + +Fix possible NULL pointer dereference in mtk_wed_detach routine checking +wo pointer is properly allocated before running mtk_wed_wo_reset() and +mtk_wed_wo_deinit(). +Even if it is just a theoretical issue at the moment check wo pointer is +not NULL in mtk_wed_mcu_msg_update. +Moreover, honor mtk_wed_mcu_send_msg return value in mtk_wed_wo_reset() + +Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") +Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Leon Romanovsky +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -174,9 +174,10 @@ mtk_wed_wo_reset(struct mtk_wed_device * + mtk_wdma_tx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); + +- mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, +- MTK_WED_WO_CMD_CHANGE_STATE, &state, +- sizeof(state), false); ++ if (mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, ++ MTK_WED_WO_CMD_CHANGE_STATE, &state, ++ sizeof(state), false)) ++ return; + + if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, + val == MTK_WED_WOIF_DISABLE_DONE, +@@ -632,9 +633,11 @@ mtk_wed_detach(struct mtk_wed_device *de + mtk_wed_free_tx_rings(dev); + + if (mtk_wed_get_rx_capa(dev)) { +- mtk_wed_wo_reset(dev); ++ if (hw->wed_wo) ++ mtk_wed_wo_reset(dev); + mtk_wed_free_rx_rings(dev); +- mtk_wed_wo_deinit(hw); ++ if (hw->wed_wo) ++ mtk_wed_wo_deinit(hw); + } + + if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -207,6 +207,9 @@ int mtk_wed_mcu_msg_update(struct mtk_we + if (dev->hw->version == 1) + return 0; + ++ if (WARN_ON(!wo)) ++ return -ENODEV; ++ + return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, + true); + } diff --git a/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch b/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch new file mode 100644 index 0000000000..0afe7106e5 --- /dev/null +++ b/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch @@ -0,0 +1,58 @@ +From: Lorenzo Bianconi +Date: Wed, 7 Dec 2022 15:04:55 +0100 +Subject: [PATCH] net: ethernet: mtk_wed: fix possible deadlock if + mtk_wed_wo_init fails + +Introduce __mtk_wed_detach() in order to avoid a deadlock in +mtk_wed_attach routine if mtk_wed_wo_init fails since both +mtk_wed_attach and mtk_wed_detach run holding hw_lock mutex. + +Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Leon Romanovsky +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -619,12 +619,10 @@ mtk_wed_deinit(struct mtk_wed_device *de + } + + static void +-mtk_wed_detach(struct mtk_wed_device *dev) ++__mtk_wed_detach(struct mtk_wed_device *dev) + { + struct mtk_wed_hw *hw = dev->hw; + +- mutex_lock(&hw_lock); +- + mtk_wed_deinit(dev); + + mtk_wdma_rx_reset(dev); +@@ -657,6 +655,13 @@ mtk_wed_detach(struct mtk_wed_device *de + module_put(THIS_MODULE); + + hw->wed_dev = NULL; ++} ++ ++static void ++mtk_wed_detach(struct mtk_wed_device *dev) ++{ ++ mutex_lock(&hw_lock); ++ __mtk_wed_detach(dev); + mutex_unlock(&hw_lock); + } + +@@ -1538,8 +1543,10 @@ mtk_wed_attach(struct mtk_wed_device *de + ret = mtk_wed_wo_init(hw); + } + out: +- if (ret) +- mtk_wed_detach(dev); ++ if (ret) { ++ dev_err(dev->hw->dev, "failed to attach wed device\n"); ++ __mtk_wed_detach(dev); ++ } + unlock: + mutex_unlock(&hw_lock); + diff --git a/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch b/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch new file mode 100644 index 0000000000..ca5b6b3a3e --- /dev/null +++ b/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Date: Fri, 24 Mar 2023 14:56:58 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix tx throughput regression with + direct 1G links + +Using the QDMA tx scheduler to throttle tx to line speed works fine for +switch ports, but apparently caused a regression on non-switch ports. + +Based on a number of tests, it seems that this throttling can be safely +dropped without re-introducing the issues on switch ports that the +tx scheduling changes resolved. + +Link: https://lore.kernel.org/netdev/trinity-92c3826f-c2c8-40af-8339-bc6d0d3ffea4-1678213958520@3c-app-gmx-bs16/ +Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") +Reported-by: Frank Wunderlich +Reported-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -719,8 +719,6 @@ static void mtk_mac_link_up(struct phyli + break; + } + +- mtk_set_queue_speed(mac->hw, mac->id, speed); +- + /* Configure duplex */ + if (duplex == DUPLEX_FULL) + mcr |= MAC_MCR_FORCE_DPX; diff --git a/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch b/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch new file mode 100644 index 0000000000..850b806410 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch @@ -0,0 +1,55 @@ +From b6a709cb51f7bdc55c01cec886098a9753ce8c28 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:10:42 +0100 +Subject: [PATCH 01/10] net: mtk_eth_soc: add definitions for PCS + +As a result of help from Frank Wunderlich to investigate and test, we +know a bit more about the PCS on the Mediatek platforms. Update the +definitions from this investigation. + +This PCS appears similar, but not identical to the Lynx PCS. + +Although not included in this patch, but for future reference, the PHY +ID registers at offset 4 read as 0x4d544950 'MTIP'. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -504,8 +504,10 @@ + #define ETHSYS_DMA_AG_MAP_PPE BIT(2) + + /* SGMII subsystem config registers */ +-/* Register to auto-negotiation restart */ ++/* BMCR (low 16) BMSR (high 16) */ + #define SGMSYS_PCS_CONTROL_1 0x0 ++#define SGMII_BMCR GENMASK(15, 0) ++#define SGMII_BMSR GENMASK(31, 16) + #define SGMII_AN_RESTART BIT(9) + #define SGMII_ISOLATE BIT(10) + #define SGMII_AN_ENABLE BIT(12) +@@ -515,13 +517,18 @@ + #define SGMII_PCS_FAULT BIT(23) + #define SGMII_AN_EXPANSION_CLR BIT(30) + ++#define SGMSYS_PCS_ADVERTISE 0x8 ++#define SGMII_ADVERTISE GENMASK(15, 0) ++#define SGMII_LPA GENMASK(31, 16) ++ + /* Register to programmable link timer, the unit in 2 * 8ns */ + #define SGMSYS_PCS_LINK_TIMER 0x18 +-#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0)) ++#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) ++#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) + + /* Register to control remote fault */ + #define SGMSYS_SGMII_MODE 0x20 +-#define SGMII_IF_MODE_BIT0 BIT(0) ++#define SGMII_IF_MODE_SGMII BIT(0) + #define SGMII_SPEED_DUPLEX_AN BIT(1) + #define SGMII_SPEED_MASK GENMASK(3, 2) + #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) diff --git a/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch b/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch new file mode 100644 index 0000000000..4ea428c9d6 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch @@ -0,0 +1,74 @@ +From 5cf7797526ee81bea0f627bccaa3d887f48f53e0 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:10:47 +0100 +Subject: [PATCH 02/10] net: mtk_eth_soc: eliminate unnecessary error handling + +The functions called by the pcs_config() method always return zero, so +there is no point trying to handle an error from these functions. Make +these functions void, eliminate the "err" variable and simply return +zero from the pcs_config() function itself. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -20,7 +20,7 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st + } + + /* For SGMII interface mode */ +-static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) ++static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { + unsigned int val; + +@@ -39,16 +39,13 @@ static int mtk_pcs_setup_mode_an(struct + regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); + val &= ~SGMII_PHYA_PWD; + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); +- +- return 0; +- + } + + /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a + * fixed speed. + */ +-static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, +- phy_interface_t interface) ++static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, ++ phy_interface_t interface) + { + unsigned int val; + +@@ -73,8 +70,6 @@ static int mtk_pcs_setup_mode_force(stru + regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); + val &= ~SGMII_PHYA_PWD; + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); +- +- return 0; + } + + static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +@@ -83,15 +78,14 @@ static int mtk_pcs_config(struct phylink + bool permit_pause_to_mac) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- int err = 0; + + /* Setup SGMIISYS with the determined property */ + if (interface != PHY_INTERFACE_MODE_SGMII) +- err = mtk_pcs_setup_mode_force(mpcs, interface); ++ mtk_pcs_setup_mode_force(mpcs, interface); + else if (phylink_autoneg_inband(mode)) +- err = mtk_pcs_setup_mode_an(mpcs); ++ mtk_pcs_setup_mode_an(mpcs); + +- return err; ++ return 0; + } + + static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch b/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch new file mode 100644 index 0000000000..64a4a72fa6 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch @@ -0,0 +1,46 @@ +From c000dca098002da193b98099df051c9ead0cacb4 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:10:52 +0100 +Subject: [PATCH 03/10] net: mtk_eth_soc: add pcs_get_state() implementation + +Add a pcs_get_state() implementation which uses the advertisements +to compute the resulting link modes, and BMSR contents to determine +negotiation and link status. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -19,6 +19,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st + return container_of(pcs, struct mtk_pcs, pcs); + } + ++static void mtk_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); ++ unsigned int bm, adv; ++ ++ /* Read the BMSR and LPA */ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); ++ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); ++ ++ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), ++ FIELD_GET(SGMII_LPA, adv)); ++} ++ + /* For SGMII interface mode */ + static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { +@@ -117,6 +131,7 @@ static void mtk_pcs_link_up(struct phyli + } + + static const struct phylink_pcs_ops mtk_pcs_ops = { ++ .pcs_get_state = mtk_pcs_get_state, + .pcs_config = mtk_pcs_config, + .pcs_an_restart = mtk_pcs_restart_an, + .pcs_link_up = mtk_pcs_link_up, diff --git a/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch b/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch new file mode 100644 index 0000000000..24610fe11e --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch @@ -0,0 +1,130 @@ +From 0d2351dc2768061689abd4de1529fa206bbd574e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:10:58 +0100 +Subject: [PATCH 04/10] net: mtk_eth_soc: convert mtk_sgmii to use + regmap_update_bits() + +mtk_sgmii does a lot of read-modify-write operations, for which there +is a specific regmap function. Use this function instead of open-coding +the operations. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 61 ++++++++++------------- + 1 file changed, 26 insertions(+), 35 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -36,23 +36,18 @@ static void mtk_pcs_get_state(struct phy + /* For SGMII interface mode */ + static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { +- unsigned int val; +- + /* Setup the link timer and QPHY power up inside SGMIISYS */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); + +- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); +- val |= SGMII_REMOTE_FAULT_DIS; +- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); +- +- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); +- val |= SGMII_AN_RESTART; +- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); +- +- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); +- val &= ~SGMII_PHYA_PWD; +- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); ++ ++ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, ++ SGMII_AN_RESTART, SGMII_AN_RESTART); ++ ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, ++ SGMII_PHYA_PWD, 0); + } + + /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a +@@ -61,29 +56,26 @@ static void mtk_pcs_setup_mode_an(struct + static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, + phy_interface_t interface) + { +- unsigned int val; ++ unsigned int rgc3; + +- regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); +- val &= ~RG_PHY_SPEED_MASK; + if (interface == PHY_INTERFACE_MODE_2500BASEX) +- val |= RG_PHY_SPEED_3_125G; +- regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); ++ rgc3 = RG_PHY_SPEED_3_125G; ++ ++ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, ++ RG_PHY_SPEED_3_125G, rgc3); + + /* Disable SGMII AN */ +- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); +- val &= ~SGMII_AN_ENABLE; +- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, ++ SGMII_AN_ENABLE, 0); + + /* Set the speed etc but leave the duplex unchanged */ +- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); +- val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; +- val |= SGMII_SPEED_1000; +- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, ++ SGMII_SPEED_1000); + + /* Release PHYA power down state */ +- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); +- val &= ~SGMII_PHYA_PWD; +- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, ++ SGMII_PHYA_PWD, 0); + } + + static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +@@ -105,29 +97,28 @@ static int mtk_pcs_config(struct phylink + static void mtk_pcs_restart_an(struct phylink_pcs *pcs) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- unsigned int val; + +- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); +- val |= SGMII_AN_RESTART; +- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, ++ SGMII_AN_RESTART, SGMII_AN_RESTART); + } + + static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, int speed, int duplex) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- unsigned int val; ++ unsigned int sgm_mode; + + if (!phy_interface_mode_is_8023z(interface)) + return; + + /* SGMII force duplex setting */ +- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); +- val &= ~SGMII_DUPLEX_FULL; + if (duplex == DUPLEX_FULL) +- val |= SGMII_DUPLEX_FULL; ++ sgm_mode = SGMII_DUPLEX_FULL; ++ else ++ sgm_mode = 0; + +- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_DUPLEX_FULL, sgm_mode); + } + + static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch b/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch new file mode 100644 index 0000000000..ba76ca40ff --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch @@ -0,0 +1,52 @@ +From 12198c3a410fe69843e335c1bbf6d4c2a4d48e4e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:03 +0100 +Subject: [PATCH 05/10] net: mtk_eth_soc: add out of band forcing of speed and + duplex in pcs_link_up + +Add support for forcing the link speed and duplex setting in the +pcs_link_up() method for out of band modes, which will be useful when +we finish converting the pcs_config() method. Until then, we still have +to force duplex for 802.3z modes to work correctly. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 28 ++++++++++++++--------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -108,17 +108,23 @@ static void mtk_pcs_link_up(struct phyli + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int sgm_mode; + +- if (!phy_interface_mode_is_8023z(interface)) +- return; ++ if (!phylink_autoneg_inband(mode) || ++ phy_interface_mode_is_8023z(interface)) { ++ /* Force the speed and duplex setting */ ++ if (speed == SPEED_10) ++ sgm_mode = SGMII_SPEED_10; ++ else if (speed == SPEED_100) ++ sgm_mode = SGMII_SPEED_100; ++ else ++ sgm_mode = SGMII_SPEED_1000; + +- /* SGMII force duplex setting */ +- if (duplex == DUPLEX_FULL) +- sgm_mode = SGMII_DUPLEX_FULL; +- else +- sgm_mode = 0; ++ if (duplex == DUPLEX_FULL) ++ sgm_mode |= SGMII_DUPLEX_FULL; + +- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_DUPLEX_FULL, sgm_mode); ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, ++ sgm_mode); ++ } + } + + static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch b/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch new file mode 100644 index 0000000000..b76e159275 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch @@ -0,0 +1,48 @@ +From 6f38fffe2179dd29612aea2c67c46ed6682b4e46 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:08 +0100 +Subject: [PATCH 06/10] net: mtk_eth_soc: move PHY power up + +The PHY power up is common to both configuration paths, so move it into +the parent function. We need to do this for all serdes modes. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -45,9 +45,6 @@ static void mtk_pcs_setup_mode_an(struct + + regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, + SGMII_AN_RESTART, SGMII_AN_RESTART); +- +- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, +- SGMII_PHYA_PWD, 0); + } + + /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a +@@ -72,10 +69,6 @@ static void mtk_pcs_setup_mode_force(str + regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, + SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, + SGMII_SPEED_1000); +- +- /* Release PHYA power down state */ +- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, +- SGMII_PHYA_PWD, 0); + } + + static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +@@ -91,6 +84,10 @@ static int mtk_pcs_config(struct phylink + else if (phylink_autoneg_inband(mode)) + mtk_pcs_setup_mode_an(mpcs); + ++ /* Release PHYA power down state */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, ++ SGMII_PHYA_PWD, 0); ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch b/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch new file mode 100644 index 0000000000..cd9f0699b3 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch @@ -0,0 +1,48 @@ +From f752c0df13dfeb721c11d3debb79f08cf437344f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:13 +0100 +Subject: [PATCH 07/10] net: mtk_eth_soc: move interface speed selection + +Move the selection of the underlying interface speed to the pcs_config +function, so we always program the interface speed. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -53,14 +53,6 @@ static void mtk_pcs_setup_mode_an(struct + static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, + phy_interface_t interface) + { +- unsigned int rgc3; +- +- if (interface == PHY_INTERFACE_MODE_2500BASEX) +- rgc3 = RG_PHY_SPEED_3_125G; +- +- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, +- RG_PHY_SPEED_3_125G, rgc3); +- + /* Disable SGMII AN */ + regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, + SGMII_AN_ENABLE, 0); +@@ -77,6 +69,16 @@ static int mtk_pcs_config(struct phylink + bool permit_pause_to_mac) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); ++ unsigned int rgc3; ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ rgc3 = RG_PHY_SPEED_3_125G; ++ else ++ rgc3 = 0; ++ ++ /* Configure the underlying interface speed */ ++ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, ++ RG_PHY_SPEED_3_125G, rgc3); + + /* Setup SGMIISYS with the determined property */ + if (interface != PHY_INTERFACE_MODE_SGMII) diff --git a/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch b/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch new file mode 100644 index 0000000000..f08358e963 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch @@ -0,0 +1,52 @@ +From c125c66ea71b9377ae2478c4f1b87b180cc5c6ef Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:18 +0100 +Subject: [PATCH 08/10] net: mtk_eth_soc: add advertisement programming + +Program the advertisement into the mtk PCS block. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -70,16 +70,27 @@ static int mtk_pcs_config(struct phylink + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int rgc3; ++ int advertise; ++ bool changed; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + rgc3 = RG_PHY_SPEED_3_125G; + else + rgc3 = 0; + ++ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, ++ advertising); ++ if (advertise < 0) ++ return advertise; ++ + /* Configure the underlying interface speed */ + regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, + RG_PHY_SPEED_3_125G, rgc3); + ++ /* Update the advertisement, noting whether it has changed */ ++ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, ++ SGMII_ADVERTISE, advertise, &changed); ++ + /* Setup SGMIISYS with the determined property */ + if (interface != PHY_INTERFACE_MODE_SGMII) + mtk_pcs_setup_mode_force(mpcs, interface); +@@ -90,7 +101,7 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, + SGMII_PHYA_PWD, 0); + +- return 0; ++ return changed; + } + + static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch b/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch new file mode 100644 index 0000000000..602d52c6f4 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch @@ -0,0 +1,63 @@ +From 3027d89f87707e7f3e5b683e0d37a32afb5bde96 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:23 +0100 +Subject: [PATCH 09/10] net: mtk_eth_soc: move and correct link timer + programming + +Program the link timer appropriately for the interface mode being +used, using the newly introduced phylink helper that provides the +nanosecond link timer interval. + +The intervals are 1.6ms for SGMII based protocols and 10ms for +802.3z based protocols. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -36,10 +36,6 @@ static void mtk_pcs_get_state(struct phy + /* For SGMII interface mode */ + static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { +- /* Setup the link timer and QPHY power up inside SGMIISYS */ +- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, +- SGMII_LINK_TIMER_DEFAULT); +- + regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, + SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); + +@@ -69,8 +65,8 @@ static int mtk_pcs_config(struct phylink + bool permit_pause_to_mac) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); ++ int advertise, link_timer; + unsigned int rgc3; +- int advertise; + bool changed; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) +@@ -83,6 +79,10 @@ static int mtk_pcs_config(struct phylink + if (advertise < 0) + return advertise; + ++ link_timer = phylink_get_link_timer_ns(interface); ++ if (link_timer < 0) ++ return link_timer; ++ + /* Configure the underlying interface speed */ + regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, + RG_PHY_SPEED_3_125G, rgc3); +@@ -91,6 +91,9 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, + SGMII_ADVERTISE, advertise, &changed); + ++ /* Setup the link timer and QPHY power up inside SGMIISYS */ ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); ++ + /* Setup SGMIISYS with the determined property */ + if (interface != PHY_INTERFACE_MODE_SGMII) + mtk_pcs_setup_mode_force(mpcs, interface); diff --git a/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch b/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch new file mode 100644 index 0000000000..0e9a0535a7 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch @@ -0,0 +1,132 @@ +From 81b0f12a2a8a1699a7d49c3995e5f71e4ec018e6 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 27 Oct 2022 14:11:28 +0100 +Subject: [PATCH 10/10] net: mtk_eth_soc: add support for in-band 802.3z + negotiation + +As a result of help from Frank Wunderlich to investigate and test, we +now know how to program this PCS for in-band 802.3z negotiation. Add +support for this by moving the contents of the two functions into the +common mtk_pcs_config() function and adding the register settings for +802.3z negotiation. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 77 ++++++++++++----------- + 1 file changed, 42 insertions(+), 35 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -33,41 +33,15 @@ static void mtk_pcs_get_state(struct phy + FIELD_GET(SGMII_LPA, adv)); + } + +-/* For SGMII interface mode */ +-static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) +-{ +- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); +- +- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, +- SGMII_AN_RESTART, SGMII_AN_RESTART); +-} +- +-/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a +- * fixed speed. +- */ +-static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, +- phy_interface_t interface) +-{ +- /* Disable SGMII AN */ +- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, +- SGMII_AN_ENABLE, 0); +- +- /* Set the speed etc but leave the duplex unchanged */ +- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, +- SGMII_SPEED_1000); +-} +- + static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) + { + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); ++ unsigned int rgc3, sgm_mode, bmcr; + int advertise, link_timer; +- unsigned int rgc3; +- bool changed; ++ bool changed, use_an; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + rgc3 = RG_PHY_SPEED_3_125G; +@@ -83,6 +57,37 @@ static int mtk_pcs_config(struct phylink + if (link_timer < 0) + return link_timer; + ++ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and ++ * we assume that fixes it's speed at bitrate = line rate (in ++ * other words, 1000Mbps or 2500Mbps). ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ sgm_mode = SGMII_IF_MODE_SGMII; ++ if (phylink_autoneg_inband(mode)) { ++ sgm_mode |= SGMII_REMOTE_FAULT_DIS | ++ SGMII_SPEED_DUPLEX_AN; ++ use_an = true; ++ } else { ++ use_an = false; ++ } ++ } else if (phylink_autoneg_inband(mode)) { ++ /* 1000base-X or 2500base-X autoneg */ ++ sgm_mode = SGMII_REMOTE_FAULT_DIS; ++ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ advertising); ++ } else { ++ /* 1000base-X or 2500base-X without autoneg */ ++ sgm_mode = 0; ++ use_an = false; ++ } ++ ++ if (use_an) { ++ /* FIXME: Do we need to set AN_RESTART here? */ ++ bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; ++ } else { ++ bmcr = 0; ++ } ++ + /* Configure the underlying interface speed */ + regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, + RG_PHY_SPEED_3_125G, rgc3); +@@ -94,11 +99,14 @@ static int mtk_pcs_config(struct phylink + /* Setup the link timer and QPHY power up inside SGMIISYS */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); + +- /* Setup SGMIISYS with the determined property */ +- if (interface != PHY_INTERFACE_MODE_SGMII) +- mtk_pcs_setup_mode_force(mpcs, interface); +- else if (phylink_autoneg_inband(mode)) +- mtk_pcs_setup_mode_an(mpcs); ++ /* Update the sgmsys mode register */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, ++ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | ++ SGMII_IF_MODE_SGMII, sgm_mode); ++ ++ /* Update the BMCR */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, ++ SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); + + /* Release PHYA power down state */ + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, +@@ -121,8 +129,7 @@ static void mtk_pcs_link_up(struct phyli + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int sgm_mode; + +- if (!phylink_autoneg_inband(mode) || +- phy_interface_mode_is_8023z(interface)) { ++ if (!phylink_autoneg_inband(mode)) { + /* Force the speed and duplex setting */ + if (speed == SPEED_10) + sgm_mode = SGMII_SPEED_10; diff --git a/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch b/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch new file mode 100644 index 0000000000..a02c583deb --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch @@ -0,0 +1,119 @@ +From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Wed, 1 Feb 2023 19:23:29 +0100 +Subject: [PATCH 11/13] net: mediatek: sgmii: ensure the SGMII PHY is powered + down on configuration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The code expect the PHY to be in power down which is only true after reset. +Allow changes of the SGMII parameters more than once. + +Only power down when reconfiguring to avoid bouncing the link when there's +no reason to - based on code from Russell King. + +There are cases when the SGMII_PHYA_PWD register contains 0x9 which +prevents SGMII from working. The SGMII still shows link but no traffic +can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was +taken from a good working state of the SGMII interface. + +Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC") +Suggested-by: Russell King (Oracle) +Signed-off-by: Alexander Couzens +[ bmork: rebased and squashed into one patch ] +Reviewed-by: Russell King (Oracle) +Signed-off-by: Bjørn Mork +Acked-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++ + drivers/net/ethernet/mediatek/mtk_sgmii.c | 39 +++++++++++++++------ + 2 files changed, 30 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1067,11 +1067,13 @@ struct mtk_soc_data { + * @regmap: The register map pointing at the range used to setup + * SGMII modes + * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap ++ * @interface: Currently configured interface mode + * @pcs: Phylink PCS structure + */ + struct mtk_pcs { + struct regmap *regmap; + u32 ana_rgc3; ++ phy_interface_t interface; + struct phylink_pcs pcs; + }; + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink + int advertise, link_timer; + bool changed, use_an; + +- if (interface == PHY_INTERFACE_MODE_2500BASEX) +- rgc3 = RG_PHY_SPEED_3_125G; +- else +- rgc3 = 0; +- + advertise = phylink_mii_c22_pcs_encode_advertisement(interface, + advertising); + if (advertise < 0) +@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink + bmcr = 0; + } + +- /* Configure the underlying interface speed */ +- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, +- RG_PHY_SPEED_3_125G, rgc3); ++ if (mpcs->interface != interface) { ++ /* PHYA power down */ ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, ++ SGMII_PHYA_PWD, SGMII_PHYA_PWD); ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ rgc3 = RG_PHY_SPEED_3_125G; ++ else ++ rgc3 = 0; ++ ++ /* Configure the underlying interface speed */ ++ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, ++ RG_PHY_SPEED_3_125G, rgc3); ++ ++ mpcs->interface = interface; ++ } + + /* Update the advertisement, noting whether it has changed */ + regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, +@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, + SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); + +- /* Release PHYA power down state */ +- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, +- SGMII_PHYA_PWD, 0); ++ /* Release PHYA power down state ++ * Only removing bit SGMII_PHYA_PWD isn't enough. ++ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which ++ * prevents SGMII from working. The SGMII still shows link but no traffic ++ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was ++ * taken from a good working state of the SGMII interface. ++ * Unknown how much the QPHY needs but it is racy without a sleep. ++ * Tested on mt7622 & mt7986. ++ */ ++ usleep_range(50, 100); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + + return changed; + } +@@ -171,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + return PTR_ERR(ss->pcs[i].regmap); + + ss->pcs[i].pcs.ops = &mtk_pcs_ops; ++ ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; + } + + return 0; diff --git a/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch b/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch new file mode 100644 index 0000000000..a06298c0a9 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch @@ -0,0 +1,52 @@ +From 9d32637122de88f1ef614c29703f0e050cad342e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Wed, 1 Feb 2023 19:23:30 +0100 +Subject: [PATCH 12/13] net: mediatek: sgmii: fix duplex configuration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The logic of the duplex bit is inverted. Setting it means half +duplex, not full duplex. + +Fix and rename macro to avoid confusion. + +Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") +Reviewed-by: Russell King (Oracle) +Signed-off-by: Bjørn Mork +Acked-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -534,7 +534,7 @@ + #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) + #define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) + #define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) +-#define SGMII_DUPLEX_FULL BIT(4) ++#define SGMII_DUPLEX_HALF BIT(4) + #define SGMII_IF_MODE_BIT5 BIT(5) + #define SGMII_REMOTE_FAULT_DIS BIT(8) + #define SGMII_CODE_SYNC_SET_VAL BIT(9) +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -154,11 +154,11 @@ static void mtk_pcs_link_up(struct phyli + else + sgm_mode = SGMII_SPEED_1000; + +- if (duplex == DUPLEX_FULL) +- sgm_mode |= SGMII_DUPLEX_FULL; ++ if (duplex != DUPLEX_FULL) ++ sgm_mode |= SGMII_DUPLEX_HALF; + + regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, ++ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, + sgm_mode); + } + } diff --git a/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch b/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch new file mode 100644 index 0000000000..56d7a1348f --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch @@ -0,0 +1,33 @@ +From 3337a6e04ddf2923a1bdcf3d31b3b52412bf82dd Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Wed, 1 Feb 2023 19:23:31 +0100 +Subject: [PATCH 13/13] mtk_sgmii: enable PCS polling to allow SFP work +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently there is no IRQ handling (even the SGMII supports it). +Enable polling to support SFP ports. + +Fixes: 14a44ab0330d ("net: mtk_eth_soc: partially convert to phylink_pcs") +Reviewed-by: Russell King (Oracle) +Signed-off-by: Alexander Couzens +[ bmork: changed "1" => "true" ] +Signed-off-by: Bjørn Mork +Acked-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -187,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + return PTR_ERR(ss->pcs[i].regmap); + + ss->pcs[i].pcs.ops = &mtk_pcs_ops; ++ ss->pcs[i].pcs.poll = true; + ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; + } + diff --git a/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch b/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch new file mode 100644 index 0000000000..6acc62d4ab --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch @@ -0,0 +1,48 @@ +From 611e2dabb4b3243d176739fd6a5a34d007fa3f86 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 14 Mar 2023 00:34:26 +0000 +Subject: [PATCH 1/2] net: ethernet: mtk_eth_soc: reset PCS state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reset the internal PCS state machine when changing interface mode. +This prevents confusing the state machine when changing interface +modes, e.g. from SGMII to 2500Base-X or vice-versa. + +Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") +Reviewed-by: Russell King (Oracle) +Tested-by: Bjørn Mork +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ + drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -542,6 +542,10 @@ + #define SGMII_SEND_AN_ERROR_EN BIT(11) + #define SGMII_IF_MODE_MASK GENMASK(5, 1) + ++/* Register to reset SGMII design */ ++#define SGMII_RESERVED_0 0x34 ++#define SGMII_SW_RESET BIT(0) ++ + /* Register to set SGMII speed, ANA RG_ Control Signals III*/ + #define SGMSYS_ANA_RG_CS3 0x2028 + #define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -88,6 +88,10 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, + SGMII_PHYA_PWD, SGMII_PHYA_PWD); + ++ /* Reset SGMII PCS state */ ++ regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, ++ SGMII_SW_RESET, SGMII_SW_RESET); ++ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + rgc3 = RG_PHY_SPEED_3_125G; + else diff --git a/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch b/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch new file mode 100644 index 0000000000..0fabeea20c --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch @@ -0,0 +1,103 @@ +From 6e933a804c7db8be64f367f33e63cd7dcc302ebb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 14 Mar 2023 00:34:45 +0000 +Subject: [PATCH 2/2] net: ethernet: mtk_eth_soc: only write values if needed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Only restart auto-negotiation and write link timer if actually +necessary. This prevents losing the link in case of minor +changes. + +Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") +Reviewed-by: Russell King (Oracle) +Tested-by: Bjørn Mork +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 24 +++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink + const unsigned long *advertising, + bool permit_pause_to_mac) + { ++ bool mode_changed = false, changed, use_an; + struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int rgc3, sgm_mode, bmcr; + int advertise, link_timer; +- bool changed, use_an; + + advertise = phylink_mii_c22_pcs_encode_advertisement(interface, + advertising); + if (advertise < 0) + return advertise; + +- link_timer = phylink_get_link_timer_ns(interface); +- if (link_timer < 0) +- return link_timer; +- + /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and + * we assume that fixes it's speed at bitrate = line rate (in + * other words, 1000Mbps or 2500Mbps). +@@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink + } + + if (use_an) { +- /* FIXME: Do we need to set AN_RESTART here? */ +- bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; ++ bmcr = SGMII_AN_ENABLE; + } else { + bmcr = 0; + } + + if (mpcs->interface != interface) { ++ link_timer = phylink_get_link_timer_ns(interface); ++ if (link_timer < 0) ++ return link_timer; ++ + /* PHYA power down */ + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, + SGMII_PHYA_PWD, SGMII_PHYA_PWD); +@@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, + RG_PHY_SPEED_3_125G, rgc3); + ++ /* Setup the link timer */ ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); ++ + mpcs->interface = interface; ++ mode_changed = true; + } + + /* Update the advertisement, noting whether it has changed */ + regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, + SGMII_ADVERTISE, advertise, &changed); + +- /* Setup the link timer and QPHY power up inside SGMIISYS */ +- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); +- + /* Update the sgmsys mode register */ + regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, + SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | +@@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink + + /* Update the BMCR */ + regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, +- SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); ++ SGMII_AN_ENABLE, bmcr); + + /* Release PHYA power down state + * Only removing bit SGMII_PHYA_PWD isn't enough. +@@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink + usleep_range(50, 100); + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + +- return changed; ++ return changed || mode_changed; + } + + static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch new file mode 100644 index 0000000000..a1247218b0 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch @@ -0,0 +1,206 @@ +From f5d43ddd334b7c32fcaed9ba46afbd85cb467f1f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:56:28 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for MT7981 SoC + +The MediaTek MT7981 SoC comes with two 1G/2.5G SGMII ports, just like +MT7986. + +In addition MT7981 is equipped with a built-in 1000Base-T PHY which can +be used with GMAC1. + +As many MT7981 boards make use of inverting SGMII signal polarity, add +new device-tree attribute 'mediatek,pn_swap' to support them. + +Signed-off-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 31 ++++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_sgmii.c | 10 +++++++ + 4 files changed, 73 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c +@@ -96,12 +96,20 @@ static int set_mux_gmac2_gmac0_to_gephy( + + static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) + { +- unsigned int val = 0; ++ unsigned int val = 0, mask = 0, reg = 0; + bool updated = true; + + switch (path) { + case MTK_ETH_PATH_GMAC2_SGMII: +- val = CO_QPHY_SEL; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) { ++ reg = USB_PHY_SWITCH_REG; ++ val = SGMII_QPHY_SEL; ++ mask = QPHY_SEL_MASK; ++ } else { ++ reg = INFRA_MISC2; ++ val = CO_QPHY_SEL; ++ mask = val; ++ } + break; + default: + updated = false; +@@ -109,7 +117,7 @@ static int set_mux_u3_gmac2_to_qphy(stru + } + + if (updated) +- regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val); ++ regmap_update_bits(eth->infra, reg, mask, val); + + dev_dbg(eth->dev, "path %s in %s updated = %d\n", + mtk_eth_path_name(path), __func__, updated); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4803,6 +4803,26 @@ static const struct mtk_soc_data mt7629_ + }, + }; + ++static const struct mtk_soc_data mt7981_data = { ++ .reg_map = &mt7986_reg_map, ++ .ana_rgc3 = 0x128, ++ .caps = MT7981_CAPS, ++ .hw_features = MTK_HW_FEATURES, ++ .required_clks = MT7981_CLKS_BITMAP, ++ .required_pctl = false, ++ .offload_version = 2, ++ .hash_offset = 4, ++ .foe_entry_size = sizeof(struct mtk_foe_entry), ++ .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 mt7986_data = { + .reg_map = &mt7986_reg_map, + .ana_rgc3 = 0x128, +@@ -4845,6 +4865,7 @@ const struct of_device_id of_mtk_match[] + { .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}, + {}, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -556,11 +556,22 @@ + #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 + #define SGMII_PHYA_PWD BIT(4) + ++/* Register to QPHY wrapper control */ ++#define SGMSYS_QPHY_WRAP_CTRL 0xec ++#define SGMII_PN_SWAP_MASK GENMASK(1, 0) ++#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) ++#define MTK_SGMII_FLAG_PN_SWAP BIT(0) ++ + /* Infrasys subsystem config registers */ + #define INFRA_MISC2 0x70c + #define CO_QPHY_SEL BIT(0) + #define GEPHY_MAC_SEL BIT(1) + ++/* Top misc registers */ ++#define USB_PHY_SWITCH_REG 0x218 ++#define QPHY_SEL_MASK GENMASK(1, 0) ++#define SGMII_QPHY_SEL 0x2 ++ + /* MT7628/88 specific stuff */ + #define MT7628_PDMA_OFFSET 0x0800 + #define MT7628_SDM_OFFSET 0x0c00 +@@ -741,6 +752,17 @@ enum mtk_clks_map { + 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) | \ +@@ -854,6 +876,7 @@ enum mkt_eth_capabilities { + MTK_NETSYS_V2_BIT, + MTK_SOC_MT7628_BIT, + MTK_RSTCTRL_PPE1_BIT, ++ MTK_U3_COPHY_V2_BIT, + + /* MUX BITS*/ + MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, +@@ -888,6 +911,7 @@ enum mkt_eth_capabilities { + #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) ++#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) + + #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ + BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) +@@ -960,6 +984,11 @@ enum mkt_eth_capabilities { + MTK_MUX_U3_GMAC2_TO_QPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA) + ++#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ ++ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ ++ 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) +@@ -1073,12 +1102,14 @@ struct mtk_soc_data { + * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap + * @interface: Currently configured interface mode + * @pcs: Phylink PCS structure ++ * @flags: Flags indicating hardware properties + */ + struct mtk_pcs { + struct regmap *regmap; + u32 ana_rgc3; + phy_interface_t interface; + struct phylink_pcs pcs; ++ u32 flags; + }; + + /* struct mtk_sgmii - This is the structure holding sgmii regmap and its +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -87,6 +87,11 @@ static int mtk_pcs_config(struct phylink + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, + SGMII_PHYA_PWD, SGMII_PHYA_PWD); + ++ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) ++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, ++ SGMII_PN_SWAP_MASK, ++ SGMII_PN_SWAP_TX_RX); ++ + /* Reset SGMII PCS state */ + regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, + SGMII_SW_RESET, SGMII_SW_RESET); +@@ -186,6 +191,11 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + + ss->pcs[i].ana_rgc3 = ana_rgc3; + ss->pcs[i].regmap = syscon_node_to_regmap(np); ++ ++ ss->pcs[i].flags = 0; ++ if (of_property_read_bool(np, "mediatek,pnswap")) ++ ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; ++ + of_node_put(np); + if (IS_ERR(ss->pcs[i].regmap)) + return PTR_ERR(ss->pcs[i].regmap); diff --git a/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch b/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch new file mode 100644 index 0000000000..1cb1f40538 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch @@ -0,0 +1,76 @@ +From c0a440031d4314d1023c1b87f43a4233634eebdb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:57:15 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: set MDIO bus clock frequency +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Set MDIO bus clock frequency and allow setting a custom maximum +frequency from device tree. + +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Tested-by: Bjørn Mork +Signed-off-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 +++++++ + 2 files changed, 28 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -744,8 +744,10 @@ static const struct phylink_mac_ops mtk_ + + static int mtk_mdio_init(struct mtk_eth *eth) + { ++ unsigned int max_clk = 2500000, divider; + struct device_node *mii_np; + int ret; ++ u32 val; + + mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus"); + if (!mii_np) { +@@ -772,6 +774,25 @@ static int mtk_mdio_init(struct mtk_eth + eth->mii_bus->parent = eth->dev; + + snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); ++ ++ if (!of_property_read_u32(mii_np, "clock-frequency", &val)) { ++ if (val > MDC_MAX_FREQ || val < MDC_MAX_FREQ / MDC_MAX_DIVIDER) { ++ dev_err(eth->dev, "MDIO clock frequency out of range"); ++ ret = -EINVAL; ++ goto err_put_node; ++ } ++ max_clk = val; ++ } ++ divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); ++ ++ /* Configure MDC Divider */ ++ val = mtk_r32(eth, MTK_PPSC); ++ val &= ~PPSC_MDC_CFG; ++ val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; ++ mtk_w32(eth, val, MTK_PPSC); ++ ++ dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); ++ + ret = of_mdiobus_register(eth->mii_bus, mii_np); + + err_put_node: +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -363,6 +363,13 @@ + #define RX_DMA_VTAG_V2 BIT(0) + #define RX_DMA_L4_VALID_V2 BIT(2) + ++/* PHY Polling and SMI Master Control registers */ ++#define MTK_PPSC 0x10000 ++#define PPSC_MDC_CFG GENMASK(29, 24) ++#define PPSC_MDC_TURBO BIT(20) ++#define MDC_MAX_FREQ 25000000 ++#define MDC_MAX_DIVIDER 63 ++ + /* PHY Indirect Access Control registers */ + #define MTK_PHY_IAC 0x10004 + #define PHY_IAC_ACCESS BIT(31) diff --git a/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch b/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch new file mode 100644 index 0000000000..110944658d --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch @@ -0,0 +1,512 @@ +From 2a3ec7ae313310c1092e4256208cc04d1958e469 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:58:02 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: switch to external PCS driver + +Now that we got a PCS driver, use it and remove the now redundant +PCS code and it's header macros from the Ethernet driver. + +Signed-off-by: Daniel Golle +Tested-by: Frank Wunderlich +Reviewed-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/Kconfig | 2 + + drivers/net/ethernet/mediatek/Makefile | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 61 +++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 93 +-------- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 217 -------------------- + 5 files changed, 56 insertions(+), 319 deletions(-) + delete mode 100644 drivers/net/ethernet/mediatek/mtk_sgmii.c + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -19,6 +19,8 @@ config NET_MEDIATEK_SOC + select DIMLIB + select PAGE_POOL + select PAGE_POOL_STATS ++ select PCS_MTK_LYNXI ++ select REGMAP_MMIO + help + This driver supports the gigabit ethernet MACs in the + MediaTek SoC family. +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -4,7 +4,7 @@ + # + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o +-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.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_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_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -400,7 +401,7 @@ static struct phylink_pcs *mtk_mac_selec + sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? + 0 : mac->id; + +- return mtk_sgmii_select_pcs(eth->sgmii, sid); ++ return eth->sgmii_pcs[sid]; + } + + return NULL; +@@ -4016,8 +4017,17 @@ static int mtk_unreg_dev(struct mtk_eth + return 0; + } + ++static void mtk_sgmii_destroy(struct mtk_eth *eth) ++{ ++ int i; ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) ++ mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]); ++} ++ + static int mtk_cleanup(struct mtk_eth *eth) + { ++ mtk_sgmii_destroy(eth); + mtk_unreg_dev(eth); + mtk_free_dev(eth); + cancel_work_sync(ð->pending_work); +@@ -4457,6 +4467,36 @@ void mtk_eth_set_dma_device(struct mtk_e + rtnl_unlock(); + } + ++static int mtk_sgmii_init(struct mtk_eth *eth) ++{ ++ struct device_node *np; ++ struct regmap *regmap; ++ u32 flags; ++ int i; ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i); ++ if (!np) ++ break; ++ ++ regmap = syscon_node_to_regmap(np); ++ flags = 0; ++ if (of_property_read_bool(np, "mediatek,pnswap")) ++ flags |= MTK_SGMII_FLAG_PN_SWAP; ++ ++ of_node_put(np); ++ ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, regmap, ++ eth->soc->ana_rgc3, ++ flags); ++ } ++ ++ return 0; ++} ++ + static int mtk_probe(struct platform_device *pdev) + { + struct resource *res = NULL; +@@ -4520,13 +4560,7 @@ static int mtk_probe(struct platform_dev + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { +- eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), +- GFP_KERNEL); +- if (!eth->sgmii) +- return -ENOMEM; +- +- err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node, +- eth->soc->ana_rgc3); ++ err = mtk_sgmii_init(eth); + + if (err) + return err; +@@ -4537,14 +4571,17 @@ static int mtk_probe(struct platform_dev + "mediatek,pctl"); + if (IS_ERR(eth->pctl)) { + dev_err(&pdev->dev, "no pctl regmap found\n"); +- return PTR_ERR(eth->pctl); ++ err = PTR_ERR(eth->pctl); ++ goto err_destroy_sgmii; + } + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) +- return -EINVAL; ++ if (!res) { ++ err = -EINVAL; ++ goto err_destroy_sgmii; ++ } + } + + if (eth->soc->offload_version) { +@@ -4703,6 +4740,8 @@ err_deinit_hw: + mtk_hw_deinit(eth); + err_wed_exit: + mtk_wed_exit(); ++err_destroy_sgmii: ++ mtk_sgmii_destroy(eth); + + return err; + } +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -510,65 +510,6 @@ + #define ETHSYS_DMA_AG_MAP_QDMA BIT(1) + #define ETHSYS_DMA_AG_MAP_PPE BIT(2) + +-/* SGMII subsystem config registers */ +-/* BMCR (low 16) BMSR (high 16) */ +-#define SGMSYS_PCS_CONTROL_1 0x0 +-#define SGMII_BMCR GENMASK(15, 0) +-#define SGMII_BMSR GENMASK(31, 16) +-#define SGMII_AN_RESTART BIT(9) +-#define SGMII_ISOLATE BIT(10) +-#define SGMII_AN_ENABLE BIT(12) +-#define SGMII_LINK_STATYS BIT(18) +-#define SGMII_AN_ABILITY BIT(19) +-#define SGMII_AN_COMPLETE BIT(21) +-#define SGMII_PCS_FAULT BIT(23) +-#define SGMII_AN_EXPANSION_CLR BIT(30) +- +-#define SGMSYS_PCS_ADVERTISE 0x8 +-#define SGMII_ADVERTISE GENMASK(15, 0) +-#define SGMII_LPA GENMASK(31, 16) +- +-/* Register to programmable link timer, the unit in 2 * 8ns */ +-#define SGMSYS_PCS_LINK_TIMER 0x18 +-#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) +-#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) +- +-/* Register to control remote fault */ +-#define SGMSYS_SGMII_MODE 0x20 +-#define SGMII_IF_MODE_SGMII BIT(0) +-#define SGMII_SPEED_DUPLEX_AN BIT(1) +-#define SGMII_SPEED_MASK GENMASK(3, 2) +-#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) +-#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) +-#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) +-#define SGMII_DUPLEX_HALF BIT(4) +-#define SGMII_IF_MODE_BIT5 BIT(5) +-#define SGMII_REMOTE_FAULT_DIS BIT(8) +-#define SGMII_CODE_SYNC_SET_VAL BIT(9) +-#define SGMII_CODE_SYNC_SET_EN BIT(10) +-#define SGMII_SEND_AN_ERROR_EN BIT(11) +-#define SGMII_IF_MODE_MASK GENMASK(5, 1) +- +-/* Register to reset SGMII design */ +-#define SGMII_RESERVED_0 0x34 +-#define SGMII_SW_RESET BIT(0) +- +-/* Register to set SGMII speed, ANA RG_ Control Signals III*/ +-#define SGMSYS_ANA_RG_CS3 0x2028 +-#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) +-#define RG_PHY_SPEED_1_25G 0x0 +-#define RG_PHY_SPEED_3_125G BIT(2) +- +-/* Register to power up QPHY */ +-#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 +-#define SGMII_PHYA_PWD BIT(4) +- +-/* Register to QPHY wrapper control */ +-#define SGMSYS_QPHY_WRAP_CTRL 0xec +-#define SGMII_PN_SWAP_MASK GENMASK(1, 0) +-#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) +-#define MTK_SGMII_FLAG_PN_SWAP BIT(0) +- + /* Infrasys subsystem config registers */ + #define INFRA_MISC2 0x70c + #define CO_QPHY_SEL BIT(0) +@@ -1102,31 +1043,6 @@ struct mtk_soc_data { + /* currently no SoC has more than 2 macs */ + #define MTK_MAX_DEVS 2 + +-/* struct mtk_pcs - This structure holds each sgmii regmap and associated +- * data +- * @regmap: The register map pointing at the range used to setup +- * SGMII modes +- * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap +- * @interface: Currently configured interface mode +- * @pcs: Phylink PCS structure +- * @flags: Flags indicating hardware properties +- */ +-struct mtk_pcs { +- struct regmap *regmap; +- u32 ana_rgc3; +- phy_interface_t interface; +- struct phylink_pcs pcs; +- u32 flags; +-}; +- +-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its +- * characteristics +- * @pcs Array of individual PCS structures +- */ +-struct mtk_sgmii { +- struct mtk_pcs pcs[MTK_MAX_DEVS]; +-}; +- + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer +@@ -1146,6 +1062,7 @@ struct mtk_sgmii { + * MII modes + * @infra: The register map pointing at the range used to setup + * SGMII and GePHY path ++ * @sgmii_pcs: Pointers to mtk-pcs-lynxi phylink_pcs instances + * @pctl: The register map pointing at the range used to setup + * GMAC port drive/slew values + * @dma_refcnt: track how many netdevs are using the DMA engine +@@ -1186,8 +1103,8 @@ struct mtk_eth { + u32 msg_enable; + unsigned long sysclk; + struct regmap *ethsys; +- struct regmap *infra; +- struct mtk_sgmii *sgmii; ++ struct regmap *infra; ++ struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS]; + struct regmap *pctl; + bool hwlro; + refcount_t dma_refcnt; +@@ -1349,10 +1266,6 @@ void mtk_stats_update_mac(struct mtk_mac + void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); + +-struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id); +-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, +- u32 ana_rgc3); +- + int mtk_gmac_sgmii_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); +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ /dev/null +@@ -1,217 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2018-2019 MediaTek Inc. +- +-/* A library for MediaTek SGMII circuit +- * +- * Author: Sean Wang +- * +- */ +- +-#include +-#include +-#include +-#include +- +-#include "mtk_eth_soc.h" +- +-static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs) +-{ +- return container_of(pcs, struct mtk_pcs, pcs); +-} +- +-static void mtk_pcs_get_state(struct phylink_pcs *pcs, +- struct phylink_link_state *state) +-{ +- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- unsigned int bm, adv; +- +- /* Read the BMSR and LPA */ +- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); +- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); +- +- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), +- FIELD_GET(SGMII_LPA, adv)); +-} +- +-static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +- phy_interface_t interface, +- const unsigned long *advertising, +- bool permit_pause_to_mac) +-{ +- bool mode_changed = false, changed, use_an; +- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- unsigned int rgc3, sgm_mode, bmcr; +- int advertise, link_timer; +- +- advertise = phylink_mii_c22_pcs_encode_advertisement(interface, +- advertising); +- if (advertise < 0) +- return advertise; +- +- /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and +- * we assume that fixes it's speed at bitrate = line rate (in +- * other words, 1000Mbps or 2500Mbps). +- */ +- if (interface == PHY_INTERFACE_MODE_SGMII) { +- sgm_mode = SGMII_IF_MODE_SGMII; +- if (phylink_autoneg_inband(mode)) { +- sgm_mode |= SGMII_REMOTE_FAULT_DIS | +- SGMII_SPEED_DUPLEX_AN; +- use_an = true; +- } else { +- use_an = false; +- } +- } else if (phylink_autoneg_inband(mode)) { +- /* 1000base-X or 2500base-X autoneg */ +- sgm_mode = SGMII_REMOTE_FAULT_DIS; +- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, +- advertising); +- } else { +- /* 1000base-X or 2500base-X without autoneg */ +- sgm_mode = 0; +- use_an = false; +- } +- +- if (use_an) { +- bmcr = SGMII_AN_ENABLE; +- } else { +- bmcr = 0; +- } +- +- if (mpcs->interface != interface) { +- link_timer = phylink_get_link_timer_ns(interface); +- if (link_timer < 0) +- return link_timer; +- +- /* PHYA power down */ +- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, +- SGMII_PHYA_PWD, SGMII_PHYA_PWD); +- +- if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) +- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, +- SGMII_PN_SWAP_MASK, +- SGMII_PN_SWAP_TX_RX); +- +- /* Reset SGMII PCS state */ +- regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, +- SGMII_SW_RESET, SGMII_SW_RESET); +- +- if (interface == PHY_INTERFACE_MODE_2500BASEX) +- rgc3 = RG_PHY_SPEED_3_125G; +- else +- rgc3 = 0; +- +- /* Configure the underlying interface speed */ +- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, +- RG_PHY_SPEED_3_125G, rgc3); +- +- /* Setup the link timer */ +- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); +- +- mpcs->interface = interface; +- mode_changed = true; +- } +- +- /* Update the advertisement, noting whether it has changed */ +- regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, +- SGMII_ADVERTISE, advertise, &changed); +- +- /* Update the sgmsys mode register */ +- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | +- SGMII_IF_MODE_SGMII, sgm_mode); +- +- /* Update the BMCR */ +- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, +- SGMII_AN_ENABLE, bmcr); +- +- /* Release PHYA power down state +- * Only removing bit SGMII_PHYA_PWD isn't enough. +- * There are cases when the SGMII_PHYA_PWD register contains 0x9 which +- * prevents SGMII from working. The SGMII still shows link but no traffic +- * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was +- * taken from a good working state of the SGMII interface. +- * Unknown how much the QPHY needs but it is racy without a sleep. +- * Tested on mt7622 & mt7986. +- */ +- usleep_range(50, 100); +- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); +- +- return changed || mode_changed; +-} +- +-static void mtk_pcs_restart_an(struct phylink_pcs *pcs) +-{ +- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- +- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, +- SGMII_AN_RESTART, SGMII_AN_RESTART); +-} +- +-static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, +- phy_interface_t interface, int speed, int duplex) +-{ +- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); +- unsigned int sgm_mode; +- +- if (!phylink_autoneg_inband(mode)) { +- /* Force the speed and duplex setting */ +- if (speed == SPEED_10) +- sgm_mode = SGMII_SPEED_10; +- else if (speed == SPEED_100) +- sgm_mode = SGMII_SPEED_100; +- else +- sgm_mode = SGMII_SPEED_1000; +- +- if (duplex != DUPLEX_FULL) +- sgm_mode |= SGMII_DUPLEX_HALF; +- +- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +- SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, +- sgm_mode); +- } +-} +- +-static const struct phylink_pcs_ops mtk_pcs_ops = { +- .pcs_get_state = mtk_pcs_get_state, +- .pcs_config = mtk_pcs_config, +- .pcs_an_restart = mtk_pcs_restart_an, +- .pcs_link_up = mtk_pcs_link_up, +-}; +- +-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) +-{ +- struct device_node *np; +- int i; +- +- for (i = 0; i < MTK_MAX_DEVS; i++) { +- np = of_parse_phandle(r, "mediatek,sgmiisys", i); +- if (!np) +- break; +- +- ss->pcs[i].ana_rgc3 = ana_rgc3; +- ss->pcs[i].regmap = syscon_node_to_regmap(np); +- +- ss->pcs[i].flags = 0; +- if (of_property_read_bool(np, "mediatek,pnswap")) +- ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; +- +- of_node_put(np); +- if (IS_ERR(ss->pcs[i].regmap)) +- return PTR_ERR(ss->pcs[i].regmap); +- +- ss->pcs[i].pcs.ops = &mtk_pcs_ops; +- ss->pcs[i].pcs.poll = true; +- ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; +- } +- +- return 0; +-} +- +-struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id) +-{ +- if (!ss->pcs[id].regmap) +- return NULL; +- +- return &ss->pcs[id].pcs; +-} diff --git a/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch new file mode 100644 index 0000000000..9ce2735951 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch @@ -0,0 +1,46 @@ +From f5af7931d2a2cae66d0f9dad4ba517b1b00620b3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 19 Apr 2023 19:07:23 +0100 +Subject: [PATCH] net: mtk_eth_soc: use WO firmware for MT7981 + +In order to support wireless offloading on MT7981 we need to load the +appropriate firmware. Recognize MT7981 and load mt7981_wo.bin. + +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 7 ++++++- + drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -326,7 +326,11 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + wo->hw->index + 1); + + /* load firmware */ +- fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; ++ if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed")) ++ fw_name = MT7981_FIRMWARE_WO; ++ else ++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; ++ + ret = request_firmware(&fw, fw_name, wo->hw->dev); + if (ret) + return ret; +@@ -386,5 +390,6 @@ int mtk_wed_mcu_init(struct mtk_wed_wo * + 100, MTK_FW_DL_TIMEOUT); + } + ++MODULE_FIRMWARE(MT7981_FIRMWARE_WO); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -88,6 +88,7 @@ enum mtk_wed_dummy_cr_idx { + MTK_WED_DUMMY_CR_WO_STATUS, + }; + ++#define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" + #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" + #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" + diff --git a/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch b/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch new file mode 100644 index 0000000000..d715c4aa68 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch @@ -0,0 +1,28 @@ +From 7c83e28f10830aa5105c25eaabe890e3adac36aa Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 9 May 2023 03:20:06 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix NULL pointer dereference + +Check for NULL pointer to avoid kernel crashing in case of missing WO +firmware in case only a single WEDv2 device has been initialized, e.g. on +MT7981 which can connect just one wireless frontend. + +Fixes: 86ce0d09e424 ("net: ethernet: mtk_eth_soc: use WO firmware for MT7981") +Signed-off-by: Daniel Golle +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_wed.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -647,7 +647,7 @@ __mtk_wed_detach(struct mtk_wed_device * + BIT(hw->index), BIT(hw->index)); + } + +- if (!hw_list[!hw->index]->wed_dev && ++ if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) && + hw->eth->dma_dev != hw->eth->dev) + mtk_eth_set_dma_device(hw->eth, hw->eth->dev); + diff --git a/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch b/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch new file mode 100644 index 0000000000..93eaffa19e --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch @@ -0,0 +1,403 @@ +From f601293f37c4be618c5efaef85d2ee21f97e82e0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:57:35 +0000 +Subject: [PATCH 092/250] net: ethernet: mtk_eth_soc: ppe: add support for flow + accounting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The PPE units found in MT7622 and newer support packet and byte +accounting of hw-offloaded flows. Add support for reading those counters +as found in MediaTek's SDK[1]. + +[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92 +Tested-by: Bjørn Mork +Signed-off-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + + drivers/net/ethernet/mediatek/mtk_ppe.c | 114 +++++++++++++++++- + drivers/net/ethernet/mediatek/mtk_ppe.h | 25 +++- + .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +- + .../net/ethernet/mediatek/mtk_ppe_offload.c | 8 ++ + drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++ + 7 files changed, 172 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4691,8 +4691,8 @@ static int mtk_probe(struct platform_dev + for (i = 0; i < num_ppe; i++) { + u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; + +- eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, +- eth->soc->offload_version, i); ++ eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, i); ++ + if (!eth->ppe[i]) { + err = -ENOMEM; + goto err_deinit_ppe; +@@ -4816,6 +4816,7 @@ static const struct mtk_soc_data mt7622_ + .required_pctl = false, + .offload_version = 2, + .hash_offset = 2, ++ .has_accounting = true, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), +@@ -4853,6 +4854,7 @@ static const struct mtk_soc_data mt7629_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7629_CLKS_BITMAP, + .required_pctl = false, ++ .has_accounting = true, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4873,6 +4875,7 @@ static const struct mtk_soc_data mt7981_ + .offload_version = 2, + .hash_offset = 4, + .foe_entry_size = sizeof(struct mtk_foe_entry), ++ .has_accounting = true, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +@@ -4893,6 +4896,7 @@ static const struct mtk_soc_data mt7986_ + .offload_version = 2, + .hash_offset = 4, + .foe_entry_size = sizeof(struct mtk_foe_entry), ++ .has_accounting = true, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1011,6 +1011,8 @@ struct mtk_reg_map { + * the extra setup for those pins used by GMAC. + * @hash_offset Flow table hash offset. + * @foe_entry_size Foe table entry size. ++ * @has_accounting Bool indicating support for accounting of ++ * offloaded flows. + * @txd_size Tx DMA descriptor size. + * @rxd_size Rx DMA descriptor size. + * @rx_irq_done_mask Rx irq done register mask. +@@ -1028,6 +1030,7 @@ struct mtk_soc_data { + u8 hash_offset; + u16 foe_entry_size; + netdev_features_t hw_features; ++ bool has_accounting; + struct { + u32 txd_size; + u32 rxd_size; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -74,6 +74,48 @@ static int mtk_ppe_wait_busy(struct mtk_ + return ret; + } + ++static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) ++{ ++ int ret; ++ u32 val; ++ ++ ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, ++ !(val & MTK_PPE_MIB_SER_CR_ST), ++ 20, MTK_PPE_WAIT_TIMEOUT_US); ++ ++ if (ret) ++ dev_err(ppe->dev, "MIB table busy"); ++ ++ return ret; ++} ++ ++static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) ++{ ++ u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; ++ u32 val, cnt_r0, cnt_r1, cnt_r2; ++ int ret; ++ ++ val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; ++ ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); ++ ++ ret = mtk_ppe_mib_wait_busy(ppe); ++ if (ret) ++ return ret; ++ ++ cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); ++ cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); ++ cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); ++ ++ byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); ++ byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); ++ pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); ++ pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); ++ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; ++ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; ++ ++ return 0; ++} ++ + static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) + { + ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); +@@ -459,6 +501,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp + hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); + dma_wmb(); + mtk_ppe_cache_clear(ppe); ++ if (ppe->accounting) { ++ struct mtk_foe_accounting *acct; ++ ++ acct = ppe->acct_table + entry->hash * sizeof(*acct); ++ acct->packets = 0; ++ acct->bytes = 0; ++ } + } + entry->hash = 0xffff; + +@@ -566,6 +615,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + wmb(); + hwe->ib1 = entry->ib1; + ++ if (ppe->accounting) ++ *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; ++ + dma_wmb(); + + mtk_ppe_cache_clear(ppe); +@@ -757,11 +809,39 @@ int mtk_ppe_prepare_reset(struct mtk_ppe + return mtk_ppe_wait_busy(ppe); + } + +-struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, +- int version, int index) ++struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, ++ struct mtk_foe_accounting *diff) ++{ ++ struct mtk_foe_accounting *acct; ++ int size = sizeof(struct mtk_foe_accounting); ++ u64 bytes, packets; ++ ++ if (!ppe->accounting) ++ return NULL; ++ ++ if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) ++ return NULL; ++ ++ acct = ppe->acct_table + index * size; ++ ++ acct->bytes += bytes; ++ acct->packets += packets; ++ ++ if (diff) { ++ diff->bytes = bytes; ++ diff->packets = packets; ++ } ++ ++ return acct; ++} ++ ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) + { ++ bool accounting = eth->soc->has_accounting; + const struct mtk_soc_data *soc = eth->soc; ++ struct mtk_foe_accounting *acct; + struct device *dev = eth->dev; ++ struct mtk_mib_entry *mib; + struct mtk_ppe *ppe; + u32 foe_flow_size; + void *foe; +@@ -778,7 +858,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + ppe->base = base; + ppe->eth = eth; + ppe->dev = dev; +- ppe->version = version; ++ ppe->version = eth->soc->offload_version; ++ ppe->accounting = accounting; + + foe = dmam_alloc_coherent(ppe->dev, + MTK_PPE_ENTRIES * soc->foe_entry_size, +@@ -794,6 +875,23 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + if (!ppe->foe_flow) + goto err_free_l2_flows; + ++ if (accounting) { ++ mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), ++ &ppe->mib_phys, GFP_KERNEL); ++ if (!mib) ++ return NULL; ++ ++ ppe->mib_table = mib; ++ ++ acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), ++ GFP_KERNEL); ++ ++ if (!acct) ++ return NULL; ++ ++ ppe->acct_table = acct; ++ } ++ + mtk_ppe_debugfs_init(ppe, index); + + return ppe; +@@ -923,6 +1021,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); + ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); + } ++ ++ if (ppe->accounting && ppe->mib_phys) { ++ ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys); ++ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, ++ MTK_PPE_MIB_CFG_EN); ++ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, ++ MTK_PPE_MIB_CFG_RD_CLR); ++ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, ++ MTK_PPE_MIB_CFG_RD_CLR); ++ } + } + + int mtk_ppe_stop(struct mtk_ppe *ppe) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -57,6 +57,7 @@ enum { + #define MTK_FOE_IB2_MULTICAST BIT(8) + + #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) ++#define MTK_FOE_IB2_MIB_CNT BIT(15) + #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) + #define MTK_FOE_IB2_WDMA_WINFO BIT(17) + +@@ -285,16 +286,34 @@ struct mtk_flow_entry { + unsigned long cookie; + }; + ++struct mtk_mib_entry { ++ u32 byt_cnt_l; ++ u16 byt_cnt_h; ++ u32 pkt_cnt_l; ++ u8 pkt_cnt_h; ++ u8 _rsv0; ++ u32 _rsv1; ++} __packed; ++ ++struct mtk_foe_accounting { ++ u64 bytes; ++ u64 packets; ++}; ++ + struct mtk_ppe { + struct mtk_eth *eth; + struct device *dev; + void __iomem *base; + int version; + char dirname[5]; ++ bool accounting; + + void *foe_table; + dma_addr_t foe_phys; + ++ struct mtk_mib_entry *mib_table; ++ dma_addr_t mib_phys; ++ + u16 foe_check_time[MTK_PPE_ENTRIES]; + struct hlist_head *foe_flow; + +@@ -303,8 +322,8 @@ struct mtk_ppe { + void *acct_table; + }; + +-struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, +- int version, int index); ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); ++ + void mtk_ppe_deinit(struct mtk_eth *eth); + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); +@@ -359,5 +378,7 @@ int mtk_foe_entry_commit(struct mtk_ppe + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); ++struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, ++ struct mtk_foe_accounting *diff); + + #endif +--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file + struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i); + struct mtk_foe_mac_info *l2; + struct mtk_flow_addr_info ai = {}; ++ struct mtk_foe_accounting *acct; + unsigned char h_source[ETH_ALEN]; + unsigned char h_dest[ETH_ALEN]; + int type, state; +@@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file + if (bind && state != MTK_FOE_STATE_BIND) + continue; + ++ acct = mtk_foe_entry_get_mib(ppe, i, NULL); ++ + type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); + seq_printf(m, "%05x %s %7s", i, + mtk_foe_entry_state_str(state), +@@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file + *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); + + seq_printf(m, " eth=%pM->%pM etype=%04x" +- " vlan=%d,%d ib1=%08x ib2=%08x\n", ++ " vlan=%d,%d ib1=%08x ib2=%08x" ++ " packets=%llu bytes=%llu\n", + h_source, h_dest, ntohs(l2->etype), +- l2->vlan1, l2->vlan2, entry->ib1, ib2); ++ l2->vlan1, l2->vlan2, entry->ib1, ib2, ++ acct ? acct->packets : 0, acct ? acct->bytes : 0); + } + + return 0; +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -497,6 +497,7 @@ static int + mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) + { + struct mtk_flow_entry *entry; ++ struct mtk_foe_accounting diff; + u32 idle; + + entry = rhashtable_lookup(ð->flow_table, &f->cookie, +@@ -507,6 +508,13 @@ mtk_flow_offload_stats(struct mtk_eth *e + idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); + f->stats.lastused = jiffies - idle * HZ; + ++ if (entry->hash != 0xFFFF && ++ mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, ++ &diff)) { ++ f->stats.pkts += diff.packets; ++ f->stats.bytes += diff.bytes; ++ } ++ + return 0; + } + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +@@ -149,6 +149,20 @@ enum { + + #define MTK_PPE_MIB_TB_BASE 0x338 + ++#define MTK_PPE_MIB_SER_CR 0x33C ++#define MTK_PPE_MIB_SER_CR_ST BIT(16) ++#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0) ++ ++#define MTK_PPE_MIB_SER_R0 0x340 ++#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0) ++ ++#define MTK_PPE_MIB_SER_R1 0x344 ++#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16) ++#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0) ++ ++#define MTK_PPE_MIB_SER_R2 0x348 ++#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) ++ + #define MTK_PPE_MIB_CACHE_CTL 0x350 + #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) + #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch b/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch new file mode 100644 index 0000000000..64352426ae --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch @@ -0,0 +1,58 @@ +From 88a0fd5927b7c2c7aecd6dc747d898eb38043d2b Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 20 Apr 2023 22:06:42 +0100 +Subject: [PATCH 093/250] net: mtk_eth_soc: mediatek: fix ppe flow accounting + for v1 hardware + +Older chips (like MT7622) use a different bit in ib2 to enable hardware +counter support. Add macros for both and select the appropriate bit. + +Fixes: 3fbe4d8c0e53 ("net: ethernet: mtk_eth_soc: ppe: add support for flow accounting") +Signed-off-by: Felix Fietkau +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 10 ++++++++-- + drivers/net/ethernet/mediatek/mtk_ppe.h | 3 ++- + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -599,6 +599,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + struct mtk_eth *eth = ppe->eth; + u16 timestamp = mtk_eth_timestamp(eth); + struct mtk_foe_entry *hwe; ++ u32 val; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; +@@ -615,8 +616,13 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + wmb(); + hwe->ib1 = entry->ib1; + +- if (ppe->accounting) +- *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; ++ if (ppe->accounting) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ val = MTK_FOE_IB2_MIB_CNT_V2; ++ else ++ val = MTK_FOE_IB2_MIB_CNT; ++ *mtk_foe_entry_ib2(eth, hwe) |= val; ++ } + + dma_wmb(); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -55,9 +55,10 @@ enum { + #define MTK_FOE_IB2_PSE_QOS BIT(4) + #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) + #define MTK_FOE_IB2_MULTICAST BIT(8) ++#define MTK_FOE_IB2_MIB_CNT BIT(10) + + #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) +-#define MTK_FOE_IB2_MIB_CNT BIT(15) ++#define MTK_FOE_IB2_MIB_CNT_V2 BIT(15) + #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) + #define MTK_FOE_IB2_WDMA_WINFO BIT(17) + diff --git a/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch b/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch new file mode 100644 index 0000000000..217e517c3a --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch @@ -0,0 +1,201 @@ +From: Felix Fietkau +Date: Sun, 20 Nov 2022 23:01:00 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: drop generic vlan rx offload, + only use DSA untagging + +Through testing I found out that hardware vlan rx offload support seems to +have some hardware issues. At least when using multiple MACs and when receiving +tagged packets on the secondary MAC, the hardware can sometimes start to emit +wrong tags on the first MAC as well. + +In order to avoid such issues, drop the feature configuration and use the +offload feature only for DSA hardware untagging on MT7621/MT7622 devices which +only use one MAC. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1897,9 +1897,7 @@ static int mtk_poll_rx(struct napi_struc + + while (done < budget) { + unsigned int pktlen, *rxdcsum; +- bool has_hwaccel_tag = false; + struct net_device *netdev; +- u16 vlan_proto, vlan_tci; + dma_addr_t dma_addr; + u32 hash, reason; + int mac = 0; +@@ -2034,36 +2032,21 @@ static int mtk_poll_rx(struct napi_struc + skb_checksum_none_assert(skb); + skb->protocol = eth_type_trans(skb, netdev); + +- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- mtk_ppe_check_skb(eth->ppe[0], skb, hash); +- +- if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { +- if (trxd.rxd3 & RX_DMA_VTAG_V2) { +- vlan_proto = RX_DMA_VPID(trxd.rxd4); +- vlan_tci = RX_DMA_VID(trxd.rxd4); +- has_hwaccel_tag = true; +- } +- } else if (trxd.rxd2 & RX_DMA_VTAG) { +- vlan_proto = RX_DMA_VPID(trxd.rxd3); +- vlan_tci = RX_DMA_VID(trxd.rxd3); +- has_hwaccel_tag = true; +- } +- } +- + /* When using VLAN untagging in combination with DSA, the + * hardware treats the MTK special tag as a VLAN and untags it. + */ +- if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { +- unsigned int port = vlan_proto & GENMASK(2, 0); ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && ++ (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { ++ unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); + + if (port < ARRAY_SIZE(eth->dsa_meta) && + eth->dsa_meta[port]) + skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); +- } else if (has_hwaccel_tag) { +- __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); + } + ++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ mtk_ppe_check_skb(eth->ppe[0], skb, hash); ++ + skb_record_rx_queue(skb, 0); + napi_gro_receive(napi, skb); + +@@ -2889,29 +2872,11 @@ static netdev_features_t mtk_fix_feature + + static int mtk_set_features(struct net_device *dev, netdev_features_t features) + { +- struct mtk_mac *mac = netdev_priv(dev); +- struct mtk_eth *eth = mac->hw; + netdev_features_t diff = dev->features ^ features; +- int i; + + if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) + mtk_hwlro_netdev_disable(dev); + +- /* Set RX VLAN offloading */ +- if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) +- return 0; +- +- mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), +- MTK_CDMP_EG_CTRL); +- +- /* sync features with other MAC */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { +- if (!eth->netdev[i] || eth->netdev[i] == dev) +- continue; +- eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; +- eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; +- } +- + return 0; + } + +@@ -3225,30 +3190,6 @@ static int mtk_open(struct net_device *d + struct mtk_eth *eth = mac->hw; + int i, err; + +- if (mtk_uses_dsa(dev) && !eth->prog) { +- for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { +- struct metadata_dst *md_dst = eth->dsa_meta[i]; +- +- if (md_dst) +- continue; +- +- md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, +- GFP_KERNEL); +- if (!md_dst) +- return -ENOMEM; +- +- md_dst->u.port_info.port_id = i; +- eth->dsa_meta[i] = md_dst; +- } +- } else { +- /* Hardware special tag parsing needs to be disabled if at least +- * one MAC does not use DSA. +- */ +- u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +- val &= ~MTK_CDMP_STAG_EN; +- mtk_w32(eth, val, MTK_CDMP_IG_CTRL); +- } +- + err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); + if (err) { + netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, +@@ -3287,6 +3228,35 @@ static int mtk_open(struct net_device *d + phylink_start(mac->phylink); + netif_tx_start_all_queues(dev); + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ return 0; ++ ++ if (mtk_uses_dsa(dev) && !eth->prog) { ++ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { ++ struct metadata_dst *md_dst = eth->dsa_meta[i]; ++ ++ if (md_dst) ++ continue; ++ ++ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, ++ GFP_KERNEL); ++ if (!md_dst) ++ return -ENOMEM; ++ ++ md_dst->u.port_info.port_id = i; ++ eth->dsa_meta[i] = md_dst; ++ } ++ } else { ++ /* Hardware special tag parsing needs to be disabled if at least ++ * one MAC does not use DSA. ++ */ ++ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ val &= ~MTK_CDMP_STAG_EN; ++ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); ++ ++ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); ++ } ++ + return 0; + } + +@@ -3771,10 +3741,9 @@ static int mtk_hw_init(struct mtk_eth *e + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + val = mtk_r32(eth, MTK_CDMP_IG_CTRL); + mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); +- } + +- /* Enable RX VLan Offloading */ +- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++ } + + /* set interrupt delays based on current Net DIM sample */ + mtk_dim_rx(ð->rx_dim.work); +@@ -4414,7 +4383,7 @@ static int mtk_add_mac(struct mtk_eth *e + eth->netdev[id]->hw_features |= NETIF_F_LRO; + + eth->netdev[id]->vlan_features = eth->soc->hw_features & +- ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); ++ ~NETIF_F_HW_VLAN_CTAG_TX; + eth->netdev[id]->features |= eth->soc->hw_features; + eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -48,7 +48,6 @@ + #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ + NETIF_F_RXCSUM | \ + NETIF_F_HW_VLAN_CTAG_TX | \ +- NETIF_F_HW_VLAN_CTAG_RX | \ + NETIF_F_SG | NETIF_F_TSO | \ + NETIF_F_TSO6 | \ + NETIF_F_IPV6_CSUM |\ diff --git a/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch b/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch new file mode 100644 index 0000000000..2704faec12 --- /dev/null +++ b/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch @@ -0,0 +1,31 @@ +From b804f765485109f9644cc05d1e8fc79ca6c6e4aa Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 19 Jul 2023 01:39:36 +0100 +Subject: [PATCH 094/250] net: ethernet: mtk_eth_soc: always + mtk_get_ib1_pkt_type + +entries and bind debugfs files would display wrong data on NETSYS_V2 and +later because instead of using mtk_get_ib1_pkt_type the driver would use +MTK_FOE_IB1_PACKET_TYPE which corresponds to NETSYS_V1(.x) SoCs. +Use mtk_get_ib1_pkt_type so entries and bind records display correctly. + +Fixes: 03a3180e5c09e ("net: ethernet: mtk_eth_soc: introduce flow offloading support for mt7986") +Signed-off-by: Daniel Golle +Acked-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/c0ae03d0182f4d27b874cbdf0059bc972c317f3c.1689727134.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file + + acct = mtk_foe_entry_get_mib(ppe, i, NULL); + +- type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1); + seq_printf(m, "%05x %s %7s", i, + mtk_foe_entry_state_str(state), + mtk_foe_pkt_type_str(type)); diff --git a/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch b/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch new file mode 100644 index 0000000000..d7d1c08fce --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch @@ -0,0 +1,78 @@ +From 5ea0e1312bcfebc06b5f91d1bb82b823d6395125 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 19 Jul 2023 12:29:49 +0200 +Subject: [PATCH 095/250] net: ethernet: mtk_ppe: add MTK_FOE_ENTRY_V{1,2}_SIZE + macros + +Introduce MTK_FOE_ENTRY_V{1,2}_SIZE macros in order to make more +explicit foe_entry size for different chipset revisions. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +++++----- + drivers/net/ethernet/mediatek/mtk_ppe.h | 3 +++ + 2 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4765,7 +4765,7 @@ static const struct mtk_soc_data mt7621_ + .required_pctl = false, + .offload_version = 1, + .hash_offset = 2, +- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4786,7 +4786,7 @@ static const struct mtk_soc_data mt7622_ + .offload_version = 2, + .hash_offset = 2, + .has_accounting = true, +- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4805,7 +4805,7 @@ static const struct mtk_soc_data mt7623_ + .required_pctl = true, + .offload_version = 1, + .hash_offset = 2, +- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, ++ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4843,8 +4843,8 @@ static const struct mtk_soc_data mt7981_ + .required_pctl = false, + .offload_version = 2, + .hash_offset = 4, +- .foe_entry_size = sizeof(struct mtk_foe_entry), + .has_accounting = true, ++ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +@@ -4864,8 +4864,8 @@ static const struct mtk_soc_data mt7986_ + .required_pctl = false, + .offload_version = 2, + .hash_offset = 4, +- .foe_entry_size = sizeof(struct mtk_foe_entry), + .has_accounting = true, ++ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -216,6 +216,9 @@ struct mtk_foe_ipv6_6rd { + struct mtk_foe_mac_info l2; + }; + ++#define MTK_FOE_ENTRY_V1_SIZE 80 ++#define MTK_FOE_ENTRY_V2_SIZE 96 ++ + struct mtk_foe_entry { + u32 ib1; + diff --git a/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch b/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch new file mode 100644 index 0000000000..fb54f404b2 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch @@ -0,0 +1,141 @@ +From 8cfa2576d79f9379d167a8994f0fca935c07a8bc Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 22 Jul 2023 21:32:49 +0100 +Subject: [PATCH 096/250] net: ethernet: mtk_eth_soc: remove incorrect PLL + configuration + +MT7623 GMAC0 attempts to configure the system clocking according to the +required speed in the .mac_config callback for non-SGMII, non-baseX and +non-TRGMII modes. + +state->speed setting has never been reliable in the .mac_config +callback - there are cases where this is not the link speed, +particularly via ethtool paths, so this has always been unreliable (as +detailed in phylink's documentation.) + +There is the additional issue that mtk_gmac0_rgmii_adjust() will only +be called if state->interface changes, which means it only configures +the system clocking on the very first .mac_config call, which will be +made when the network device is first brought up before any link is +established. + +Essentially, this code is incredibly buggy, and probably never worked. + +Moreover, checking the in-kernel DT files, it seems no platform makes +use of this code path. + +Therefore, let's remove it, and disable interface modes for port 0 that +are not SGMII, 1000base-X, 2500base-X or TRGMII on the MT7623. + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Tested-by: Frank Wunderlich +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 54 ++++++--------------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + 2 files changed, 17 insertions(+), 38 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -352,7 +352,7 @@ static int mt7621_gmac0_rgmii_adjust(str + } + + static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, +- phy_interface_t interface, int speed) ++ phy_interface_t interface) + { + u32 val; + int ret; +@@ -366,26 +366,7 @@ static void mtk_gmac0_rgmii_adjust(struc + return; + } + +- val = (speed == SPEED_1000) ? +- INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100; +- mtk_w32(eth, val, INTF_MODE); +- +- regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0, +- ETHSYS_TRGMII_CLK_SEL362_5, +- ETHSYS_TRGMII_CLK_SEL362_5); +- +- val = (speed == SPEED_1000) ? 250000000 : 500000000; +- ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val); +- if (ret) +- dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret); +- +- val = (speed == SPEED_1000) ? +- RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100; +- mtk_w32(eth, val, TRGMII_RCK_CTRL); +- +- val = (speed == SPEED_1000) ? +- TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100; +- mtk_w32(eth, val, TRGMII_TCK_CTRL); ++ dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); + } + + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, +@@ -471,17 +452,8 @@ static void mtk_mac_config(struct phylin + state->interface)) + goto err_phy; + } else { +- /* FIXME: this is incorrect. Not only does it +- * use state->speed (which is not guaranteed +- * to be correct) but it also makes use of it +- * in a code path that will only be reachable +- * when the PHY interface mode changes, not +- * when the speed changes. Consequently, RGMII +- * is probably broken. +- */ + mtk_gmac0_rgmii_adjust(mac->hw, +- state->interface, +- state->speed); ++ state->interface); + + /* mt7623_pad_clk_setup */ + for (i = 0 ; i < NUM_TRGMII_CTRL; i++) +@@ -4342,13 +4314,19 @@ static int mtk_add_mac(struct mtk_eth *e + mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; + +- __set_bit(PHY_INTERFACE_MODE_MII, +- mac->phylink_config.supported_interfaces); +- __set_bit(PHY_INTERFACE_MODE_GMII, +- mac->phylink_config.supported_interfaces); ++ /* MT7623 gmac0 is now missing its speed-specific PLL configuration ++ * in its .mac_config method (since state->speed is not valid there. ++ * Disable support for MII, GMII and RGMII. ++ */ ++ if (!mac->hw->soc->disable_pll_modes || mac->id != 0) { ++ __set_bit(PHY_INTERFACE_MODE_MII, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_GMII, ++ mac->phylink_config.supported_interfaces); + +- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) +- phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) ++ phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); ++ } + + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) + __set_bit(PHY_INTERFACE_MODE_TRGMII, +@@ -4806,6 +4784,7 @@ static const struct mtk_soc_data mt7623_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, ++ .disable_pll_modes = true, + .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 +@@ -1030,6 +1030,7 @@ struct mtk_soc_data { + u16 foe_entry_size; + netdev_features_t hw_features; + bool has_accounting; ++ bool disable_pll_modes; + struct { + u32 txd_size; + u32 rxd_size; diff --git a/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch b/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch new file mode 100644 index 0000000000..293066fa9a --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch @@ -0,0 +1,81 @@ +From a4c2233b1e4359b6c64b6f9ba98c8718a11fffee Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 22 Jul 2023 21:32:54 +0100 +Subject: [PATCH 097/250] net: ethernet: mtk_eth_soc: remove mac_pcs_get_state + and modernise + +Remove the .mac_pcs_get_state function, since as far as I can tell is +never called - no DT appears to specify an in-band-status management +nor SFP support for this driver. + +Removal of this, along with the previous patch to remove the incorrect +clocking configuration, means that the driver becomes non-legacy, so +we can remove the "legacy_pre_march2020" status from this driver. + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Tested-by: Frank Wunderlich +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 --------------------- + 1 file changed, 35 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -555,38 +555,6 @@ static int mtk_mac_finish(struct phylink + return 0; + } + +-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); +- u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id)); +- +- state->link = (pmsr & MAC_MSR_LINK); +- state->duplex = (pmsr & MAC_MSR_DPX) >> 1; +- +- switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) { +- case 0: +- state->speed = SPEED_10; +- break; +- case MAC_MSR_SPEED_100: +- state->speed = SPEED_100; +- break; +- case MAC_MSR_SPEED_1000: +- state->speed = SPEED_1000; +- break; +- default: +- state->speed = SPEED_UNKNOWN; +- break; +- } +- +- state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); +- if (pmsr & MAC_MSR_RX_FC) +- state->pause |= MLO_PAUSE_RX; +- if (pmsr & MAC_MSR_TX_FC) +- state->pause |= MLO_PAUSE_TX; +-} +- + static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) + { +@@ -708,7 +676,6 @@ static void mtk_mac_link_up(struct phyli + + static const struct phylink_mac_ops mtk_phylink_ops = { + .mac_select_pcs = mtk_mac_select_pcs, +- .mac_pcs_get_state = mtk_mac_pcs_get_state, + .mac_config = mtk_mac_config, + .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, +@@ -4309,8 +4276,6 @@ static int mtk_add_mac(struct mtk_eth *e + + mac->phylink_config.dev = ð->netdev[id]->dev; + mac->phylink_config.type = PHYLINK_NETDEV; +- /* This driver makes use of state->speed in mac_config */ +- mac->phylink_config.legacy_pre_march2020 = true; + mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; + diff --git a/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch b/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch new file mode 100644 index 0000000000..25c87b0415 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch @@ -0,0 +1,550 @@ +From 5d8d05fbf804b4485646d39551ac27452e45afd3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:52:02 +0100 +Subject: [PATCH 099/250] net: ethernet: mtk_eth_soc: add version in + mtk_soc_data + +Introduce version field in mtk_soc_data data structure in order to +make mtk_eth driver easier to maintain for chipset configuration +codebase. Get rid of MTK_NETSYS_V2 bit in chip capabilities. +This is a preliminary patch to introduce support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/e52fae302ca135436e5cdd26d38d87be2da63055.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 55 +++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 36 +++++++----- + drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++--- + .../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- + drivers/net/ethernet/mediatek/mtk_wed.c | 4 +- + 5 files changed, 66 insertions(+), 49 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -580,7 +580,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_is_netsys_v1(eth)) + val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; + + if (IS_ENABLED(CONFIG_SOC_MT7621)) { +@@ -955,7 +955,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_is_netsys_v2_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -1013,7 +1013,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_is_netsys_v2_or_greater(eth)) { + txd->txd5 = 0; + txd->txd6 = 0; + txd->txd7 = 0; +@@ -1204,7 +1204,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_is_netsys_v2_or_greater(eth)) + mtk_tx_set_dma_desc_v2(dev, txd, info); + else + mtk_tx_set_dma_desc_v1(dev, txd, info); +@@ -1511,7 +1511,7 @@ static void mtk_update_rx_cpu_idx(struct + + static bool mtk_page_pool_enabled(struct mtk_eth *eth) + { +- return MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2); ++ return eth->soc->version == 2; + } + + static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, +@@ -1853,7 +1853,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_is_netsys_v2_or_greater(eth)) + 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)) +@@ -1949,7 +1949,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_is_netsys_v2_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -1974,8 +1974,8 @@ 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) && +- (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { ++ if (mtk_is_netsys_v1(eth) && (trxd.rxd2 & RX_DMA_VTAG) && ++ netdev_uses_dsa(netdev)) { + unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); + + if (port < ARRAY_SIZE(eth->dsa_meta) && +@@ -2285,7 +2285,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_is_netsys_v2_or_greater(eth)) { + txd->txd5 = 0; + txd->txd6 = 0; + txd->txd7 = 0; +@@ -2338,14 +2338,14 @@ 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_is_netsys_v1(eth)) + val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; + mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); + ofs += MTK_QTX_OFFSET; + } + val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); + mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); + } else { + mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); +@@ -2474,7 +2474,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_is_netsys_v2_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -3025,7 +3025,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_is_netsys_v2_or_greater(eth)) + val |= MTK_MUTLI_CNT | MTK_RESV_BUF | + MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | + MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; +@@ -3167,7 +3167,7 @@ static int mtk_open(struct net_device *d + phylink_start(mac->phylink); + netif_tx_start_all_queues(dev); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return 0; + + if (mtk_uses_dsa(dev) && !eth->prog) { +@@ -3432,7 +3432,7 @@ static void mtk_hw_reset(struct mtk_eth + { + u32 val; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); + val = RSTCTRL_PPE0_V2; + } else { +@@ -3444,7 +3444,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_is_netsys_v2_or_greater(eth)) + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, + 0x3ffffff); + } +@@ -3470,7 +3470,7 @@ static void mtk_hw_warm_reset(struct mtk + return; + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; + else + rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; +@@ -3640,7 +3640,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_is_netsys_v2_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -3677,7 +3677,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_is_netsys_v1(eth)) { + val = mtk_r32(eth, MTK_CDMP_IG_CTRL); + mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); + +@@ -3699,7 +3699,7 @@ 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_is_netsys_v2_or_greater(eth)) { + /* PSE should not drop port8 and port9 packets from WDMA Tx */ + mtk_w32(eth, 0x00000300, PSE_DROP_CFG); + +@@ -4488,7 +4488,7 @@ static int mtk_probe(struct platform_dev + } + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; +@@ -4596,9 +4596,8 @@ static int mtk_probe(struct platform_dev + } + + if (eth->soc->offload_version) { +- u32 num_ppe; ++ u32 num_ppe = mtk_is_netsys_v2_or_greater(eth) ? 2 : 1; + +- num_ppe = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; + num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); + for (i = 0; i < num_ppe; i++) { + u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; +@@ -4690,6 +4689,7 @@ static const struct mtk_soc_data mt2701_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, ++ .version = 1, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4706,6 +4706,7 @@ static const struct mtk_soc_data mt7621_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7621_CLKS_BITMAP, + .required_pctl = false, ++ .version = 1, + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +@@ -4726,6 +4727,7 @@ static const struct mtk_soc_data mt7622_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7622_CLKS_BITMAP, + .required_pctl = false, ++ .version = 1, + .offload_version = 2, + .hash_offset = 2, + .has_accounting = true, +@@ -4746,6 +4748,7 @@ static const struct mtk_soc_data mt7623_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, ++ .version = 1, + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +@@ -4768,6 +4771,7 @@ static const struct mtk_soc_data mt7629_ + .required_clks = MT7629_CLKS_BITMAP, + .required_pctl = false, + .has_accounting = true, ++ .version = 1, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4785,6 +4789,7 @@ static const struct mtk_soc_data mt7981_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7981_CLKS_BITMAP, + .required_pctl = false, ++ .version = 2, + .offload_version = 2, + .hash_offset = 4, + .has_accounting = true, +@@ -4806,6 +4811,7 @@ static const struct mtk_soc_data mt7986_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7986_CLKS_BITMAP, + .required_pctl = false, ++ .version = 2, + .offload_version = 2, + .hash_offset = 4, + .has_accounting = true, +@@ -4826,6 +4832,7 @@ static const struct mtk_soc_data rt5350_ + .hw_features = MTK_HW_FEATURES_MT7628, + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, ++ .version = 1, + .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 +@@ -820,7 +820,6 @@ enum mkt_eth_capabilities { + MTK_SHARED_INT_BIT, + MTK_TRGMII_MT7621_CLK_BIT, + MTK_QDMA_BIT, +- MTK_NETSYS_V2_BIT, + MTK_SOC_MT7628_BIT, + MTK_RSTCTRL_PPE1_BIT, + MTK_U3_COPHY_V2_BIT, +@@ -855,7 +854,6 @@ 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_V2 BIT(MTK_NETSYS_V2_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) +@@ -934,11 +932,11 @@ enum mkt_eth_capabilities { + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ +- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) ++ 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) ++ MTK_RSTCTRL_PPE1) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1009,6 +1007,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. ++ * @version SoC version. + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +@@ -1027,6 +1026,7 @@ struct mtk_soc_data { + bool required_pctl; + u8 offload_version; + u8 hash_offset; ++ u8 version; + u16 foe_entry_size; + netdev_features_t hw_features; + bool has_accounting; +@@ -1183,6 +1183,16 @@ struct mtk_mac { + /* the struct describing the SoC. these are declared in the soc_xyz.c files */ + extern const struct of_device_id of_mtk_match[]; + ++static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) ++{ ++ return eth->soc->version == 1; ++} ++ ++static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) ++{ ++ return eth->soc->version > 1; ++} ++ + static inline struct mtk_foe_entry * + mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) + { +@@ -1193,7 +1203,7 @@ mtk_foe_get_entry(struct mtk_ppe *ppe, u + + static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB1_BIND_TIMESTAMP_V2; + + return MTK_FOE_IB1_BIND_TIMESTAMP; +@@ -1201,7 +1211,7 @@ static inline u32 mtk_get_ib1_ts_mask(st + + static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB1_BIND_PPPOE_V2; + + return MTK_FOE_IB1_BIND_PPPOE; +@@ -1209,7 +1219,7 @@ static inline u32 mtk_get_ib1_ppoe_mask( + + static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB1_BIND_VLAN_TAG_V2; + + return MTK_FOE_IB1_BIND_VLAN_TAG; +@@ -1217,7 +1227,7 @@ static inline u32 mtk_get_ib1_vlan_tag_m + + static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB1_BIND_VLAN_LAYER_V2; + + return MTK_FOE_IB1_BIND_VLAN_LAYER; +@@ -1225,7 +1235,7 @@ static inline u32 mtk_get_ib1_vlan_layer + + static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); + + return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, val); +@@ -1233,7 +1243,7 @@ static inline u32 mtk_prep_ib1_vlan_laye + + static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); + + return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, val); +@@ -1241,7 +1251,7 @@ static inline u32 mtk_get_ib1_vlan_layer + + static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB1_PACKET_TYPE_V2; + + return MTK_FOE_IB1_PACKET_TYPE; +@@ -1249,7 +1259,7 @@ static inline u32 mtk_get_ib1_pkt_type_m + + static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE_V2, val); + + return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, val); +@@ -1257,7 +1267,7 @@ static inline u32 mtk_get_ib1_pkt_type(s + + static inline u32 mtk_get_ib2_multicast_mask(struct mtk_eth *eth) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + return MTK_FOE_IB2_MULTICAST_V2; + + return MTK_FOE_IB2_MULTICAST; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -207,7 +207,7 @@ int mtk_foe_entry_prepare(struct mtk_eth + + memset(entry, 0, sizeof(*entry)); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | + FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE_V2, type) | + FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | +@@ -271,7 +271,7 @@ int mtk_foe_entry_set_pse_port(struct mt + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); + u32 val = *ib2; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + val &= ~MTK_FOE_IB2_DEST_PORT_V2; + val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, port); + } else { +@@ -422,7 +422,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; + *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | + MTK_FOE_IB2_WDMA_WINFO_V2; +@@ -446,7 +446,7 @@ int mtk_foe_entry_set_queue(struct mtk_e + { + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + *ib2 &= ~MTK_FOE_IB2_QID_V2; + *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); + *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; +@@ -601,7 +601,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + struct mtk_foe_entry *hwe; + u32 val; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; + entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP_V2, + timestamp); +@@ -617,7 +617,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + hwe->ib1 = entry->ib1; + + if (ppe->accounting) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + val = MTK_FOE_IB2_MIB_CNT_V2; + else + val = MTK_FOE_IB2_MIB_CNT; +@@ -965,7 +965,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | + FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, + MTK_PPE_ENTRIES_SHIFT); +- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(ppe->eth)) + val |= MTK_PPE_TB_CFG_INFO_SEL; + ppe_w32(ppe, MTK_PPE_TB_CFG, val); + +@@ -981,7 +981,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_FLOW_CFG_IP4_NAPT | + MTK_PPE_FLOW_CFG_IP4_DSLITE | + MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; +- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(ppe->eth)) + val |= MTK_PPE_MD_TOAP_BYP_CRSN0 | + MTK_PPE_MD_TOAP_BYP_CRSN1 | + MTK_PPE_MD_TOAP_BYP_CRSN2 | +@@ -1023,7 +1023,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + + ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); + +- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(ppe->eth)) { + ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); + ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); + } +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -193,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_et + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { + mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, + info.bss, info.wcid); +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) { + switch (info.wdma_idx) { + case 0: + pse_port = 8; +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1084,7 +1084,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * + } else { + struct mtk_eth *eth = dev->hw->eth; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (mtk_is_netsys_v2_or_greater(eth)) + wed_set(dev, MTK_WED_RESET_IDX, + MTK_WED_RESET_IDX_RX_V2); + else +@@ -1806,7 +1806,7 @@ void mtk_wed_add_hw(struct device_node * + hw->wdma = wdma; + hw->index = index; + hw->irq = irq; +- hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; ++ hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; + + if (hw->version == 1) { + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, diff --git a/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch b/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch new file mode 100644 index 0000000000..7b945bb869 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch @@ -0,0 +1,29 @@ +From f8fb8dbd158c585be7574faf92db7d614b6722ff Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:52:27 +0100 +Subject: [PATCH 100/250] net: ethernet: mtk_eth_soc: increase MAX_DEVS to 3 + +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 +Link: https://lore.kernel.org/r/3563e5fab367e7d79a7f1296fabaa5c20f202d7a.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1043,8 +1043,8 @@ 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 ++/* currently no SoC has more than 3 macs */ ++#define MTK_MAX_DEVS 3 + + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver diff --git a/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch b/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch new file mode 100644 index 0000000000..8071658313 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch @@ -0,0 +1,186 @@ +From 856be974290f28d7943be2ac5a382c4139486196 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:52:44 +0100 +Subject: [PATCH 101/250] net: ethernet: mtk_eth_soc: rely on MTK_MAX_DEVS and + remove MTK_MAC_COUNT + +Get rid of MTK_MAC_COUNT since it is a duplicated of MTK_MAX_DEVS. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/1856f4266f2fc80677807b1bad867659e7b00c65.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++++++--------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - + 2 files changed, 27 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -881,7 +881,7 @@ static void mtk_stats_update(struct mtk_ + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->mac[i] || !eth->mac[i]->hw_stats) + continue; + if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { +@@ -1386,7 +1386,7 @@ static int mtk_queue_stopped(struct mtk_ + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; + if (netif_queue_stopped(eth->netdev[i])) +@@ -1400,7 +1400,7 @@ static void mtk_wake_queue(struct mtk_et + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; + netif_tx_wake_all_queues(eth->netdev[i]); +@@ -1859,7 +1859,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 >= MTK_MAX_DEVS || + !eth->netdev[mac])) + goto release_desc; + +@@ -2899,7 +2899,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 < MTK_MAX_DEVS; i++) + if (eth->netdev[i]) + netdev_reset_queue(eth->netdev[i]); + if (eth->scratch_ring) { +@@ -3053,8 +3053,13 @@ 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++) { +- u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ u32 val; ++ ++ if (!eth->netdev[i]) ++ continue; ++ ++ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); + + /* default setup the forward port to send frame to PDMA */ + val &= ~0xffff; +@@ -3064,7 +3069,7 @@ static void mtk_gdm_config(struct mtk_et + + val |= config; + +- if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) ++ if (netdev_uses_dsa(eth->netdev[i])) + val |= MTK_GDMA_SPECIAL_TAG; + + mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); +@@ -3661,15 +3666,15 @@ 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 < MTK_MAX_DEVS; i++) { + struct net_device *dev = eth->netdev[i]; + +- mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); +- if (dev) { +- struct mtk_mac *mac = netdev_priv(dev); ++ if (!dev) ++ continue; + +- mtk_set_mcr_max_rx(mac, dev->mtu + MTK_RX_ETH_HLEN); +- } ++ mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); ++ mtk_set_mcr_max_rx(netdev_priv(dev), ++ dev->mtu + MTK_RX_ETH_HLEN); + } + + /* Indicates CDM to parse the MTK special tag from CPU +@@ -3849,7 +3854,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 < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i] || !netif_running(eth->netdev[i])) + continue; + +@@ -3865,8 +3870,8 @@ 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++) { +- if (!test_bit(i, &restart)) ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->netdev[i] || !test_bit(i, &restart)) + continue; + + if (mtk_open(eth->netdev[i])) { +@@ -3893,7 +3898,7 @@ static int mtk_free_dev(struct mtk_eth * + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; + free_netdev(eth->netdev[i]); +@@ -3912,7 +3917,7 @@ static int mtk_unreg_dev(struct mtk_eth + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + struct mtk_mac *mac; + if (!eth->netdev[i]) + continue; +@@ -4213,7 +4218,7 @@ static int mtk_add_mac(struct mtk_eth *e + } + + id = be32_to_cpup(_id); +- if (id >= MTK_MAC_COUNT) { ++ if (id >= MTK_MAX_DEVS) { + dev_err(eth->dev, "%d is not a valid mac id\n", id); + return -EINVAL; + } +@@ -4358,7 +4363,7 @@ void mtk_eth_set_dma_device(struct mtk_e + + rtnl_lock(); + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < MTK_MAX_DEVS; i++) { + dev = eth->netdev[i]; + + if (!dev || !(dev->flags & IFF_UP)) +@@ -4664,7 +4669,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 < MTK_MAX_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/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch b/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch new file mode 100644 index 0000000000..1a9b31f526 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch @@ -0,0 +1,307 @@ +From a41d535855976838d246c079143c948dcf0f7931 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:52:59 +0100 +Subject: [PATCH 102/250] net: ethernet: mtk_eth_soc: add NETSYS_V3 version + support + +Introduce NETSYS_V3 chipset version support. +This is a preliminary patch to introduce support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/0db2260910755d76fa48e303b9f9bdf4e5a82340.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 105 ++++++++++++++------ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 +++++++-- + 2 files changed, 116 insertions(+), 37 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -861,17 +861,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_is_netsys_v3_or_greater(eth)) { ++ 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); +@@ -1175,7 +1190,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); + +@@ -1186,6 +1204,8 @@ static void mtk_tx_set_dma_desc_v2(struc + /* tx checksum offload */ + if (info->csum) + data |= TX_DMA_CHKSUM_V2; ++ if (mtk_is_netsys_v3_or_greater(eth) && netdev_uses_dsa(dev)) ++ data |= TX_DMA_SPTAG_V3; + } + WRITE_ONCE(desc->txd5, data); + +@@ -1251,8 +1271,7 @@ 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; ++ itx_buf->mac_id = mac->id; + setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, + k++); + +@@ -1300,8 +1319,7 @@ 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; ++ tx_buf->mac_id = mac->id; + + setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, + txd_info.size, k++); +@@ -1603,7 +1621,7 @@ static int mtk_xdp_frame_map(struct mtk_ + } + mtk_tx_set_dma_desc(dev, txd, txd_info); + +- tx_buf->flags |= !mac->id ? MTK_TX_FLAGS_FPORT0 : MTK_TX_FLAGS_FPORT1; ++ tx_buf->mac_id = mac->id; + tx_buf->type = dma_map ? MTK_TYPE_XDP_NDO : MTK_TYPE_XDP_TX; + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; + +@@ -1853,11 +1871,24 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) +- 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_is_netsys_v2_or_greater(eth)) { ++ 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 >= MTK_MAX_DEVS || + !eth->netdev[mac])) +@@ -2079,7 +2110,6 @@ static int mtk_poll_tx_qdma(struct mtk_e + + while ((cpu != dma) && budget) { + u32 next_cpu = desc->txd2; +- int mac = 0; + + desc = mtk_qdma_phys_to_virt(ring, desc->txd2); + if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) +@@ -2087,15 +2117,13 @@ 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; +- + if (!tx_buf->data) + break; + + if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { + if (tx_buf->type == MTK_TYPE_SKB) +- mtk_poll_tx_done(eth, state, mac, tx_buf->data); ++ mtk_poll_tx_done(eth, state, tx_buf->mac_id, ++ tx_buf->data); + + budget--; + } +@@ -3704,7 +3732,24 @@ 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_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ /* 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 */ ++ mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, 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_is_netsys_v1(eth)) { + /* PSE should not drop port8 and port9 packets from WDMA Tx */ + mtk_w32(eth, 0x00000300, PSE_DROP_CFG); + +@@ -4266,7 +4311,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_is_netsys_v3_or_greater(eth)) ++ 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 +@@ -122,6 +122,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 + +@@ -287,8 +288,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 +@@ -301,6 +300,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 +@@ -634,12 +635,6 @@ enum mtk_tx_flags { + */ + MTK_TX_FLAGS_SINGLE0 = 0x01, + MTK_TX_FLAGS_PAGE0 = 0x02, +- +- /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted +- * SKB out instead of looking up through hardware TX descriptor. +- */ +- MTK_TX_FLAGS_FPORT0 = 0x04, +- MTK_TX_FLAGS_FPORT1 = 0x08, + }; + + /* This enum allows us to identify how the clock is defined on the array of the +@@ -725,6 +720,35 @@ 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 ++}; ++ + enum mtk_tx_buf_type { + MTK_TYPE_SKB, + MTK_TYPE_XDP_TX, +@@ -743,7 +767,8 @@ struct mtk_tx_buf { + enum mtk_tx_buf_type type; + void *data; + +- u32 flags; ++ u16 mac_id; ++ u16 flags; + DEFINE_DMA_UNMAP_ADDR(dma_addr0); + DEFINE_DMA_UNMAP_LEN(dma_len0); + DEFINE_DMA_UNMAP_ADDR(dma_addr1); +@@ -1192,6 +1217,11 @@ static inline bool mtk_is_netsys_v2_or_g + return eth->soc->version > 1; + } + ++static inline bool mtk_is_netsys_v3_or_greater(struct mtk_eth *eth) ++{ ++ return eth->soc->version > 2; ++} ++ + static inline struct mtk_foe_entry * + mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) + { diff --git a/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch b/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch new file mode 100644 index 0000000000..7a0b285f2c --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch @@ -0,0 +1,193 @@ +From db797ae0542220a98658229397da464c383c991c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:53:13 +0100 +Subject: [PATCH 103/250] 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 +Link: https://lore.kernel.org/r/9499ac3670b2fc5b444404b84e8a4a169beabbf2.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 ++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 56 ++++++++++---------- + 2 files changed, 39 insertions(+), 39 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 +@@ -866,41 +866,41 @@ 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_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_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) +@@ -1045,7 +1045,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/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch b/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch new file mode 100644 index 0000000000..5947d385f2 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch @@ -0,0 +1,132 @@ +From a1c9f7d1d24e90294f6a6755b137fcf306851e93 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 25 Jul 2023 01:53:28 +0100 +Subject: [PATCH 104/250] net: ethernet: mtk_eth_soc: convert clock bitmap to + u64 + +The to-be-added MT7988 SoC adds many new clocks which need to be +controlled by the Ethernet driver, which will result in their total +number exceeding 32. +Prepare by converting clock bitmaps into 64-bit types. + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/6960a39bb0078cf84d7642a9558e6a91c6cc9df3.1690246066.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 96 +++++++++++---------- + 1 file changed, 49 insertions(+), 47 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -666,54 +666,56 @@ enum mtk_clks_map { + 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)) + + enum mtk_dev_state { + MTK_HW_INIT, +@@ -1046,7 +1048,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/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch b/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch new file mode 100644 index 0000000000..8c24321dd4 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch @@ -0,0 +1,477 @@ +From 94f825a7eadfc8b4c8828efdb7705d9703f9c73e Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Jul 2023 01:57:42 +0100 +Subject: [PATCH 105/250] net: ethernet: mtk_eth_soc: add basic support for + MT7988 SoC + +Introduce support for ethernet chip available in MT7988 SoC to +mtk_eth_soc driver. As a first step support only the first GMAC which +is hard-wired to the internal DSA switch having 4 built-in gigabit +Ethernet PHYs. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/25c8377095b95d186872eeda7aa055da83e8f0ca.1690246605.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 201 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 86 +++++++- + 3 files changed, 273 insertions(+), 28 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c +@@ -43,7 +43,7 @@ static const char *mtk_eth_path_name(u64 + static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) + { + bool updated = true; +- u32 val, mask, set; ++ u32 mask, set, reg; + + switch (path) { + case MTK_ETH_PATH_GMAC1_SGMII: +@@ -59,11 +59,13 @@ static int set_mux_gdm1_to_gmac1_esw(str + break; + } + +- if (updated) { +- val = mtk_r32(eth, MTK_MAC_MISC); +- val = (val & mask) | set; +- mtk_w32(eth, val, MTK_MAC_MISC); +- } ++ if (mtk_is_netsys_v3_or_greater(eth)) ++ reg = MTK_MAC_MISC_V3; ++ else ++ reg = MTK_MAC_MISC; ++ ++ if (updated) ++ mtk_m32(eth, mask, set, reg); + + dev_dbg(eth->dev, "path %s in %s updated = %d\n", + mtk_eth_path_name(path), __func__, updated); +--- 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_ppe = 0x3333, ++ .ppe_base = 0x2000, ++ .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) +@@ -195,7 +287,7 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne + return __raw_readl(eth->base + reg); + } + +-static u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg) ++u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg) + { + u32 val; + +@@ -369,6 +461,19 @@ static void mtk_gmac0_rgmii_adjust(struc + dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); + } + ++static void mtk_setup_bridge_switch(struct mtk_eth *eth) ++{ ++ /* Force Port1 XGMAC Link Up */ ++ mtk_m32(eth, 0, MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID), ++ MTK_XGMAC_STS(MTK_GMAC1_ID)); ++ ++ /* Adjust GSW bridge IPG to 11 */ ++ mtk_m32(eth, GSWTX_IPG_MASK | GSWRX_IPG_MASK, ++ (GSW_IPG_11 << GSWTX_IPG_SHIFT) | ++ (GSW_IPG_11 << GSWRX_IPG_SHIFT), ++ MTK_GSW_CFG); ++} ++ + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +@@ -438,6 +543,8 @@ static void mtk_mac_config(struct phylin + goto init_err; + } + break; ++ case PHY_INTERFACE_MODE_INTERNAL: ++ break; + default: + goto err_phy; + } +@@ -515,6 +622,15 @@ static void mtk_mac_config(struct phylin + return; + } + ++ /* Setup gmac */ ++ if (mtk_is_netsys_v3_or_greater(eth) && ++ 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)); ++ ++ mtk_setup_bridge_switch(eth); ++ } ++ + return; + + err_phy: +@@ -725,11 +841,15 @@ 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_is_netsys_v3_or_greater(eth)) ++ mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3); ++ + /* Configure MDC Divider */ +- val = mtk_r32(eth, MTK_PPSC); +- val &= ~PPSC_MDC_CFG; +- val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; +- mtk_w32(eth, val, MTK_PPSC); ++ val = FIELD_PREP(PPSC_MDC_CFG, divider); ++ if (!mtk_is_netsys_v3_or_greater(eth)) ++ val |= PPSC_MDC_TURBO; ++ mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC); + + dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); + +@@ -1190,10 +1310,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); + +@@ -4360,6 +4489,17 @@ static int mtk_add_mac(struct mtk_eth *e + mac->phylink_config.supported_interfaces); + } + ++ if (mtk_is_netsys_v3_or_greater(mac->hw) && ++ MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW_BIT) && ++ 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); ++ } ++ + phylink = phylink_create(&mac->phylink_config, + of_fwnode_handle(mac->of_node), + phy_mode, &mtk_phylink_ops); +@@ -4880,6 +5020,24 @@ 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, ++ .version = 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, +@@ -4898,14 +5056,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 +@@ -117,7 +117,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) ({ typeof(x) _x = (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) +@@ -126,6 +127,11 @@ + #define MTK_GDMA_TO_PDMA 0x0 + #define MTK_GDMA_DROP_ALL 0x7777 + ++/* GDM Egress Control Register */ ++#define MTK_GDMA_EG_CTRL(x) ({ typeof(x) _x = (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)) + +@@ -389,7 +395,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)) +@@ -647,6 +672,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, +@@ -663,6 +693,27 @@ 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 + }; + +@@ -716,6 +767,36 @@ enum mtk_clks_map { + 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, +@@ -964,6 +1045,8 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_RSTCTRL_PPE1) + ++#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) ++ + struct mtk_tx_dma_desc_info { + dma_addr_t addr; + u32 size; +@@ -1309,6 +1392,7 @@ void mtk_stats_update_mac(struct mtk_mac + + void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); ++u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); + + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); diff --git a/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch new file mode 100644 index 0000000000..3dc4662d1a --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch @@ -0,0 +1,27 @@ +From 38a7eb76220731eff40602cf433f24880be0a6c2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 27 Jul 2023 09:02:26 +0200 +Subject: [PATCH 106/250] net: ethernet: mtk_eth_soc: enable page_pool support + for MT7988 SoC + +In order to recycle pages, enable page_pool allocator for MT7988 SoC. + +Tested-by: Daniel Golle +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/fd4e8693980e47385a543e7b002eec0b88bd09df.1690440675.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1658,7 +1658,7 @@ static void mtk_update_rx_cpu_idx(struct + + static bool mtk_page_pool_enabled(struct mtk_eth *eth) + { +- return eth->soc->version == 2; ++ return mtk_is_netsys_v2_or_greater(eth); + } + + static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, diff --git a/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch b/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch new file mode 100644 index 0000000000..32f26d7d27 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch @@ -0,0 +1,135 @@ +From 199e7d5a7f03dd377f3a7a458360dbedd71d50ba Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 27 Jul 2023 09:07:28 +0200 +Subject: [PATCH 107/250] net: ethernet: mtk_eth_soc: enable nft hw + flowtable_offload for MT7988 SoC + +Enable hw Packet Process Engine (PPE) for MT7988 SoC. + +Tested-by: Daniel Golle +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/5e86341b0220a49620dadc02d77970de5ded9efc.1690441576.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ + drivers/net/ethernet/mediatek/mtk_ppe.c | 19 +++++++++++++++---- + drivers/net/ethernet/mediatek/mtk_ppe.h | 19 ++++++++++++++++++- + 3 files changed, 36 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -5028,6 +5028,9 @@ static const struct mtk_soc_data mt7988_ + .required_clks = MT7988_CLKS_BITMAP, + .required_pctl = false, + .version = 3, ++ .offload_version = 2, ++ .hash_offset = 4, ++ .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -422,13 +422,22 @@ int mtk_foe_entry_set_wdma(struct mtk_et + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ switch (eth->soc->version) { ++ case 3: ++ *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; ++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | ++ MTK_FOE_IB2_WDMA_WINFO_V2; ++ l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | ++ FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); ++ break; ++ case 2: + *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; + *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | + MTK_FOE_IB2_WDMA_WINFO_V2; + l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) | + FIELD_PREP(MTK_FOE_WINFO_BSS, bss); +- } else { ++ break; ++ default: + *ib2 &= ~MTK_FOE_IB2_PORT_MG; + *ib2 |= MTK_FOE_IB2_WDMA_WINFO; + if (wdma_idx) +@@ -436,6 +445,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et + l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | + FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | + FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); ++ break; + } + + return 0; +@@ -950,8 +960,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + mtk_ppe_init_foe_table(ppe); + ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); + +- val = MTK_PPE_TB_CFG_ENTRY_80B | +- MTK_PPE_TB_CFG_AGE_NON_L4 | ++ val = MTK_PPE_TB_CFG_AGE_NON_L4 | + MTK_PPE_TB_CFG_AGE_UNBIND | + MTK_PPE_TB_CFG_AGE_TCP | + MTK_PPE_TB_CFG_AGE_UDP | +@@ -967,6 +976,8 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_ENTRIES_SHIFT); + if (mtk_is_netsys_v2_or_greater(ppe->eth)) + val |= MTK_PPE_TB_CFG_INFO_SEL; ++ if (!mtk_is_netsys_v3_or_greater(ppe->eth)) ++ val |= MTK_PPE_TB_CFG_ENTRY_80B; + ppe_w32(ppe, MTK_PPE_TB_CFG, val); + + ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -85,6 +85,17 @@ enum { + #define MTK_FOE_WINFO_BSS GENMASK(5, 0) + #define MTK_FOE_WINFO_WCID GENMASK(15, 6) + ++#define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) ++#define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) ++ ++#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) ++#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) ++#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) ++#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) ++#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) ++#define MTK_FOE_WINFO_PAO_HF BIT(23) ++#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) ++ + enum { + MTK_FOE_STATE_INVALID, + MTK_FOE_STATE_UNBIND, +@@ -106,8 +117,13 @@ struct mtk_foe_mac_info { + u16 pppoe_id; + u16 src_mac_lo; + ++ /* netsys_v2 */ + u16 minfo; + u16 winfo; ++ ++ /* netsys_v3 */ ++ u32 w3info; ++ u32 wpao; + }; + + /* software-only entry type */ +@@ -218,6 +234,7 @@ struct mtk_foe_ipv6_6rd { + + #define MTK_FOE_ENTRY_V1_SIZE 80 + #define MTK_FOE_ENTRY_V2_SIZE 96 ++#define MTK_FOE_ENTRY_V3_SIZE 128 + + struct mtk_foe_entry { + u32 ib1; +@@ -228,7 +245,7 @@ struct mtk_foe_entry { + struct mtk_foe_ipv4_dslite dslite; + struct mtk_foe_ipv6 ipv6; + struct mtk_foe_ipv6_6rd ipv6_6rd; +- u32 data[23]; ++ u32 data[31]; + }; + }; + diff --git a/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch b/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch new file mode 100644 index 0000000000..876bdd5dd3 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch @@ -0,0 +1,78 @@ +From 0c024632c1e7ff69914329bfd87bec749b9c0aed Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 2 Aug 2023 04:31:09 +0100 +Subject: [PATCH 108/250] net: ethernet: mtk_eth_soc: support per-flow + accounting on MT7988 + +NETSYS_V3 uses 64 bits for each counters while older SoCs are using +48/40 bits for each counter. +Support reading per-flow byte and package counters on NETSYS_V3. + +Signed-off-by: Daniel Golle +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/37a0928fa8c1253b197884c68ce1f54239421ac5.1690946442.git.daniel@makrotopia.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + + drivers/net/ethernet/mediatek/mtk_ppe.c | 21 +++++++++++++------- + drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 2 ++ + 3 files changed, 17 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -5030,6 +5030,7 @@ static const struct mtk_soc_data mt7988_ + .version = 3, + .offload_version = 2, + .hash_offset = 4, ++ .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -91,7 +91,6 @@ static int mtk_ppe_mib_wait_busy(struct + + static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) + { +- u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; + u32 val, cnt_r0, cnt_r1, cnt_r2; + int ret; + +@@ -106,12 +105,20 @@ static int mtk_mib_entry_read(struct mtk + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); + cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); + +- byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); +- byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); +- pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); +- pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); +- *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; +- *packets = (pkt_cnt_high << 16) | pkt_cnt_low; ++ if (mtk_is_netsys_v3_or_greater(ppe->eth)) { ++ /* 64 bit for each counter */ ++ u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); ++ *bytes = ((u64)cnt_r1 << 32) | cnt_r0; ++ *packets = ((u64)cnt_r3 << 32) | cnt_r2; ++ } else { ++ /* 48 bit byte counter, 40 bit packet counter */ ++ u32 byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); ++ u32 byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); ++ u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); ++ u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); ++ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; ++ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; ++ } + + return 0; + } +--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +@@ -163,6 +163,8 @@ enum { + #define MTK_PPE_MIB_SER_R2 0x348 + #define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) + ++#define MTK_PPE_MIB_SER_R3 0x34c ++ + #define MTK_PPE_MIB_CACHE_CTL 0x350 + #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) + #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch b/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch new file mode 100644 index 0000000000..6f1639a572 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch @@ -0,0 +1,52 @@ +From 3b12f42772c26869d60398c1710aa27b27cd945c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 21 Aug 2023 17:12:44 +0100 +Subject: [PATCH 109/250] net: ethernet: mtk_eth_soc: fix NULL pointer on hw + reset + +When a hardware reset is triggered on devices not initializing WED the +calls to mtk_wed_fe_reset and mtk_wed_fe_reset_complete dereference a +pointer on uninitialized stack memory. +Break out of both functions in case a hw_list entry is 0. + +Fixes: 08a764a7c51b ("net: ethernet: mtk_wed: add reset/reset_complete callbacks") +Signed-off-by: Daniel Golle +Reviewed-by: Simon Horman +Acked-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/5465c1609b464cc7407ae1530c40821dcdf9d3e6.1692634266.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_wed.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -214,9 +214,13 @@ void mtk_wed_fe_reset(void) + + for (i = 0; i < ARRAY_SIZE(hw_list); i++) { + struct mtk_wed_hw *hw = hw_list[i]; +- struct mtk_wed_device *dev = hw->wed_dev; ++ struct mtk_wed_device *dev; + int err; + ++ if (!hw) ++ break; ++ ++ dev = hw->wed_dev; + if (!dev || !dev->wlan.reset) + continue; + +@@ -237,8 +241,12 @@ void mtk_wed_fe_reset_complete(void) + + for (i = 0; i < ARRAY_SIZE(hw_list); i++) { + struct mtk_wed_hw *hw = hw_list[i]; +- struct mtk_wed_device *dev = hw->wed_dev; ++ struct mtk_wed_device *dev; ++ ++ if (!hw) ++ break; + ++ dev = hw->wed_dev; + if (!dev || !dev->wlan.reset_complete) + continue; + diff --git a/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch new file mode 100644 index 0000000000..2190761fdd --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch @@ -0,0 +1,44 @@ +From 489aea123d74a846ce746bfdb3efe1e7ad512e0d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 22 Aug 2023 17:31:24 +0100 +Subject: [PATCH 110/250] net: ethernet: mtk_eth_soc: fix register definitions + for MT7988 + +More register macros need to be adjusted for the 3rd GMAC on MT7988. +Account for added bit in SYSCFG0_SGMII_MASK. + +Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") +Signed-off-by: Daniel Golle +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/1c8da012e2ca80939906d85f314138c552139f0f.1692721443.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -133,10 +133,12 @@ + #define MTK_GDMA_XGDM_SEL BIT(31) + + /* Unicast Filter MAC Address Register - Low */ +-#define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) ++#define MTK_GDMA_MAC_ADRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ ++ 0x548 : 0x508 + (_x * 0x1000); }) + + /* Unicast Filter MAC Address Register - High */ +-#define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000)) ++#define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ ++ 0x54C : 0x50C + (_x * 0x1000); }) + + /* FE global misc reg*/ + #define MTK_FE_GLO_MISC 0x124 +@@ -503,7 +505,7 @@ + #define ETHSYS_SYSCFG0 0x14 + #define SYSCFG0_GE_MASK 0x3 + #define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2))) +-#define SYSCFG0_SGMII_MASK GENMASK(9, 8) ++#define SYSCFG0_SGMII_MASK GENMASK(9, 7) + #define SYSCFG0_SGMII_GMAC1 ((2 << 8) & SYSCFG0_SGMII_MASK) + #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) + #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) diff --git a/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch b/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch new file mode 100644 index 0000000000..05a18364d6 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch @@ -0,0 +1,188 @@ +From 15a84d1c44ae8c1451c265ee60500588a24e8cd6 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 22 Aug 2023 17:32:03 +0100 +Subject: [PATCH 111/250] net: ethernet: mtk_eth_soc: add reset bits for MT7988 + +Add bits needed to reset the frame engine on MT7988. + +Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/89b6c38380e7a3800c1362aa7575600717bc7543.1692721443.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 76 +++++++++++++++------ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 +++-- + 2 files changed, 68 insertions(+), 24 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3594,19 +3594,34 @@ static void mtk_hw_reset(struct mtk_eth + { + u32 val; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v2_or_greater(eth)) + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ val = RSTCTRL_PPE0_V3; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= RSTCTRL_PPE1_V3; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) ++ val |= RSTCTRL_PPE2; ++ ++ val |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; ++ } else if (mtk_is_netsys_v2_or_greater(eth)) { + val = RSTCTRL_PPE0_V2; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= RSTCTRL_PPE1; + } else { + val = RSTCTRL_PPE0; + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- val |= RSTCTRL_PPE1; +- + ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); + +- if (mtk_is_netsys_v2_or_greater(eth)) ++ if (mtk_is_netsys_v3_or_greater(eth)) ++ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, ++ 0x6f8ff); ++ else if (mtk_is_netsys_v2_or_greater(eth)) + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, + 0x3ffffff); + } +@@ -3632,13 +3647,21 @@ static void mtk_hw_warm_reset(struct mtk + return; + } + +- if (mtk_is_netsys_v2_or_greater(eth)) ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V3; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ rst_mask |= RSTCTRL_PPE1_V3; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) ++ rst_mask |= RSTCTRL_PPE2; ++ ++ rst_mask |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; ++ } else if (mtk_is_netsys_v2_or_greater(eth)) { + rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; +- else ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ rst_mask |= RSTCTRL_PPE1; ++ } else { + rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; +- +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- rst_mask |= RSTCTRL_PPE1; ++ } + + regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); + +@@ -3990,11 +4013,17 @@ static void mtk_prepare_for_reset(struct + u32 val; + int i; + +- /* disabe FE P3 and P4 */ +- val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- val |= MTK_FE_LINK_DOWN_P4; +- mtk_w32(eth, val, MTK_FE_GLO_CFG); ++ /* set FE PPE ports link down */ ++ for (i = MTK_GMAC1_ID; ++ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); ++ i += 2) { ++ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) | MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val |= MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) ++ val |= MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); ++ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); ++ } + + /* adjust PPE configurations to prepare for reset */ + for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) +@@ -4055,11 +4084,18 @@ static void mtk_pending_work(struct work + } + } + +- /* enabe FE P3 and P4 */ +- val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) +- val &= ~MTK_FE_LINK_DOWN_P4; +- mtk_w32(eth, val, MTK_FE_GLO_CFG); ++ /* set FE PPE ports link up */ ++ for (i = MTK_GMAC1_ID; ++ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); ++ i += 2) { ++ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) & ~MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) ++ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); ++ ++ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); ++ } + + clear_bit(MTK_RESETTING, ð->state); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -76,9 +76,8 @@ + #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 + + /* Frame Engine Global Configuration */ +-#define MTK_FE_GLO_CFG 0x00 +-#define MTK_FE_LINK_DOWN_P3 BIT(11) +-#define MTK_FE_LINK_DOWN_P4 BIT(12) ++#define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00) ++#define MTK_FE_LINK_DOWN_P(x) BIT(((x) + 8) % 16) + + /* Frame Engine Global Reset Register */ + #define MTK_RST_GL 0x04 +@@ -522,9 +521,15 @@ + /* ethernet reset control register */ + #define ETHSYS_RSTCTRL 0x34 + #define RSTCTRL_FE BIT(6) ++#define RSTCTRL_WDMA0 BIT(24) ++#define RSTCTRL_WDMA1 BIT(25) ++#define RSTCTRL_WDMA2 BIT(26) + #define RSTCTRL_PPE0 BIT(31) + #define RSTCTRL_PPE0_V2 BIT(30) + #define RSTCTRL_PPE1 BIT(31) ++#define RSTCTRL_PPE0_V3 BIT(29) ++#define RSTCTRL_PPE1_V3 BIT(30) ++#define RSTCTRL_PPE2 BIT(31) + #define RSTCTRL_ETH BIT(23) + + /* ethernet reset check idle register */ +@@ -931,6 +936,7 @@ enum mkt_eth_capabilities { + MTK_QDMA_BIT, + MTK_SOC_MT7628_BIT, + MTK_RSTCTRL_PPE1_BIT, ++ MTK_RSTCTRL_PPE2_BIT, + MTK_U3_COPHY_V2_BIT, + + /* MUX BITS*/ +@@ -965,6 +971,7 @@ enum mkt_eth_capabilities { + #define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) + #define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) + #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) ++#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) + #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) + + #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ +@@ -1047,7 +1054,8 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_RSTCTRL_PPE1) + +-#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) ++#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ ++ MTK_RSTCTRL_PPE2) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch b/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch new file mode 100644 index 0000000000..74ac8dc898 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch @@ -0,0 +1,254 @@ +From 25ce45fe40b574e5d7ffa407f7f2db03e7d5a910 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 22 Aug 2023 17:32:54 +0100 +Subject: [PATCH 112/250] net: ethernet: mtk_eth_soc: add support for in-SoC + SRAM + +MT7981, MT7986 and MT7988 come with in-SoC SRAM dedicated for Ethernet +DMA rings. Support using the SRAM without breaking existing device tree +bindings, ie. only new SoC starting from MT7988 will have the SRAM +declared as additional resource in device tree. For MT7981 and MT7986 +an offset on top of the main I/O base is used. + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/e45e0f230c63ad58869e8fe35b95a2fb8925b625.1692721443.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 88 ++++++++++++++++----- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++- + 2 files changed, 78 insertions(+), 22 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1118,10 +1118,13 @@ static int mtk_init_fq_dma(struct mtk_et + dma_addr_t dma_addr; + int i; + +- eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, +- ð->phy_scratch_ring, +- GFP_KERNEL); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) ++ eth->scratch_ring = eth->sram_base; ++ else ++ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, ++ cnt * soc->txrx.txd_size, ++ ð->phy_scratch_ring, ++ GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) + return -ENOMEM; + +@@ -2429,8 +2432,14 @@ static int mtk_tx_alloc(struct mtk_eth * + if (!ring->buf) + goto no_tx_mem; + +- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, +- &ring->phys, GFP_KERNEL); ++ if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) { ++ ring->dma = eth->sram_base + ring_size * sz; ++ ring->phys = eth->phy_scratch_ring + ring_size * (dma_addr_t)sz; ++ } else { ++ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, ++ &ring->phys, GFP_KERNEL); ++ } ++ + if (!ring->dma) + goto no_tx_mem; + +@@ -2529,8 +2538,7 @@ static void mtk_tx_clean(struct mtk_eth + kfree(ring->buf); + ring->buf = NULL; + } +- +- if (ring->dma) { ++ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, + ring->dma_size * soc->txrx.txd_size, + ring->dma, ring->phys); +@@ -2549,9 +2557,14 @@ static int mtk_rx_alloc(struct mtk_eth * + { + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + struct mtk_rx_ring *ring; +- int rx_data_len, rx_dma_size; ++ int rx_data_len, rx_dma_size, tx_ring_size; + int i; + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) ++ tx_ring_size = MTK_QDMA_RING_SIZE; ++ else ++ tx_ring_size = MTK_DMA_SIZE; ++ + if (rx_flag == MTK_RX_FLAGS_QDMA) { + if (ring_no) + return -EINVAL; +@@ -2586,9 +2599,20 @@ static int mtk_rx_alloc(struct mtk_eth * + ring->page_pool = pp; + } + +- ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || ++ rx_flag != MTK_RX_FLAGS_NORMAL) { ++ ring->dma = dma_alloc_coherent(eth->dma_dev, ++ rx_dma_size * eth->soc->txrx.rxd_size, ++ &ring->phys, GFP_KERNEL); ++ } else { ++ struct mtk_tx_ring *tx_ring = ð->tx_ring; ++ ++ ring->dma = tx_ring->dma + tx_ring_size * ++ eth->soc->txrx.txd_size * (ring_no + 1); ++ ring->phys = tx_ring->phys + tx_ring_size * ++ eth->soc->txrx.txd_size * (ring_no + 1); ++ } ++ + if (!ring->dma) + return -ENOMEM; + +@@ -2673,7 +2697,7 @@ static int mtk_rx_alloc(struct mtk_eth * + return 0; + } + +-static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) ++static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) + { + int i; + +@@ -2696,7 +2720,7 @@ static void mtk_rx_clean(struct mtk_eth + ring->data = NULL; + } + +- if (ring->dma) { ++ if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, + ring->dma_size * eth->soc->txrx.rxd_size, + ring->dma, ring->phys); +@@ -3059,7 +3083,7 @@ static void mtk_dma_free(struct mtk_eth + for (i = 0; i < MTK_MAX_DEVS; i++) + if (eth->netdev[i]) + netdev_reset_queue(eth->netdev[i]); +- if (eth->scratch_ring) { ++ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, + MTK_QDMA_RING_SIZE * soc->txrx.txd_size, + eth->scratch_ring, eth->phy_scratch_ring); +@@ -3067,13 +3091,13 @@ static void mtk_dma_free(struct mtk_eth + eth->phy_scratch_ring = 0; + } + mtk_tx_clean(eth); +- mtk_rx_clean(eth, ð->rx_ring[0]); +- mtk_rx_clean(eth, ð->rx_ring_qdma); ++ mtk_rx_clean(eth, ð->rx_ring[0], MTK_HAS_CAPS(soc->caps, MTK_SRAM)); ++ mtk_rx_clean(eth, ð->rx_ring_qdma, false); + + if (eth->hwlro) { + mtk_hwlro_rx_uninit(eth); + for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) +- mtk_rx_clean(eth, ð->rx_ring[i]); ++ mtk_rx_clean(eth, ð->rx_ring[i], false); + } + + kfree(eth->scratch_head); +@@ -4641,7 +4665,7 @@ static int mtk_sgmii_init(struct mtk_eth + + static int mtk_probe(struct platform_device *pdev) + { +- struct resource *res = NULL; ++ struct resource *res = NULL, *res_sram; + struct device_node *mac_np; + struct mtk_eth *eth; + int err, i; +@@ -4661,6 +4685,20 @@ static int mtk_probe(struct platform_dev + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + eth->ip_align = NET_IP_ALIGN; + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { ++ /* SRAM is actual memory and supports transparent access just like DRAM. ++ * Hence we don't require __iomem being set and don't need to use accessor ++ * functions to read from or write to SRAM. ++ */ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(eth->sram_base)) ++ return PTR_ERR(eth->sram_base); ++ } else { ++ eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET; ++ } ++ } ++ + spin_lock_init(ð->page_lock); + spin_lock_init(ð->tx_irq_lock); + spin_lock_init(ð->rx_irq_lock); +@@ -4724,6 +4762,18 @@ static int mtk_probe(struct platform_dev + err = -EINVAL; + goto err_destroy_sgmii; + } ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ res_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res_sram) { ++ err = -EINVAL; ++ goto err_destroy_sgmii; ++ } ++ eth->phy_scratch_ring = res_sram->start; ++ } else { ++ eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET; ++ } ++ } + } + + if (eth->soc->offload_version) { +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -139,6 +139,9 @@ + #define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x54C : 0x50C + (_x * 0x1000); }) + ++/* Internal SRAM offset */ ++#define MTK_ETH_SRAM_OFFSET 0x40000 ++ + /* FE global misc reg*/ + #define MTK_FE_GLO_MISC 0x124 + +@@ -938,6 +941,7 @@ enum mkt_eth_capabilities { + MTK_RSTCTRL_PPE1_BIT, + MTK_RSTCTRL_PPE2_BIT, + MTK_U3_COPHY_V2_BIT, ++ MTK_SRAM_BIT, + + /* MUX BITS*/ + MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, +@@ -973,6 +977,7 @@ enum mkt_eth_capabilities { + #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) + #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) + #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) ++#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) + + #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ + BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) +@@ -1048,14 +1053,14 @@ enum mkt_eth_capabilities { + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ +- MTK_RSTCTRL_PPE1) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM) + + #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM) + + #define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ +- MTK_RSTCTRL_PPE2) ++ MTK_RSTCTRL_PPE2 | MTK_SRAM) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1215,6 +1220,7 @@ struct mtk_eth { + struct device *dev; + struct device *dma_dev; + void __iomem *base; ++ void *sram_base; + spinlock_t page_lock; + spinlock_t tx_irq_lock; + spinlock_t rx_irq_lock; diff --git a/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch b/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch new file mode 100644 index 0000000000..1584dfd07c --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch @@ -0,0 +1,166 @@ +From 0b0d606eb9650fa01dd5621e072aa29a10544399 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 22 Aug 2023 17:33:12 +0100 +Subject: [PATCH 113/250] net: ethernet: mtk_eth_soc: support 36-bit DMA + addressing on MT7988 + +Systems having 4 GiB of RAM and more require DMA addressing beyond the +current 32-bit limit. Starting from MT7988 the hardware now supports +36-bit DMA addressing, let's use that new capability in the driver to +avoid running into swiotlb on systems with 4 GiB of RAM or more. + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/95b919c98876c9e49761e44662e7c937479eecb8.1692721443.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 22 +++++++++++++-- + 2 files changed, 48 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1311,6 +1311,10 @@ static void mtk_tx_set_dma_desc_v2(struc + data = TX_DMA_PLEN0(info->size); + if (info->last) + data |= TX_DMA_LS0; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ data |= TX_DMA_PREP_ADDR64(info->addr); ++ + WRITE_ONCE(desc->txd3, data); + + /* set forward port */ +@@ -1980,6 +1984,7 @@ static int mtk_poll_rx(struct napi_struc + bool xdp_flush = false; + int idx; + struct sk_buff *skb; ++ u64 addr64 = 0; + u8 *data, *new_data; + struct mtk_rx_dma_v2 *rxd, trxd; + int done = 0, bytes = 0; +@@ -2095,7 +2100,10 @@ static int mtk_poll_rx(struct napi_struc + goto release_desc; + } + +- dma_unmap_single(eth->dma_dev, trxd.rxd1, ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ addr64 = RX_DMA_GET_ADDR64(trxd.rxd2); ++ ++ dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64), + ring->buf_size, DMA_FROM_DEVICE); + + skb = build_skb(data, ring->frag_size); +@@ -2161,6 +2169,9 @@ release_desc: + else + rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); ++ + ring->calc_idx = idx; + done++; + } +@@ -2653,6 +2664,9 @@ static int mtk_rx_alloc(struct mtk_eth * + else + rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); ++ + rxd->rxd3 = 0; + rxd->rxd4 = 0; + if (mtk_is_netsys_v2_or_greater(eth)) { +@@ -2699,6 +2713,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) + { ++ u64 addr64 = 0; + int i; + + if (ring->data && ring->dma) { +@@ -2712,7 +2727,10 @@ static void mtk_rx_clean(struct mtk_eth + if (!rxd->rxd1) + continue; + +- dma_unmap_single(eth->dma_dev, rxd->rxd1, ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ addr64 = RX_DMA_GET_ADDR64(rxd->rxd2); ++ ++ dma_unmap_single(eth->dma_dev, ((u64)rxd->rxd1 | addr64), + ring->buf_size, DMA_FROM_DEVICE); + mtk_rx_put_buff(ring, ring->data[i], false); + } +@@ -4699,6 +4717,14 @@ static int mtk_probe(struct platform_dev + } + } + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); ++ if (err) { ++ dev_err(&pdev->dev, "Wrong DMA config\n"); ++ return -EINVAL; ++ } ++ } ++ + spin_lock_init(ð->page_lock); + spin_lock_init(ð->tx_irq_lock); + spin_lock_init(ð->rx_irq_lock); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -331,6 +331,14 @@ + #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) ++#define TX_DMA_ADDR64_MASK GENMASK(3, 0) ++#if IS_ENABLED(CONFIG_64BIT) ++# define TX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(TX_DMA_ADDR64_MASK, (x))) << 32) ++# define TX_DMA_PREP_ADDR64(x) FIELD_PREP(TX_DMA_ADDR64_MASK, ((x) >> 32)) ++#else ++# define TX_DMA_GET_ADDR64(x) (0) ++# define TX_DMA_PREP_ADDR64(x) (0) ++#endif + + /* PDMA on MT7628 */ + #define TX_DMA_DONE BIT(31) +@@ -343,6 +351,14 @@ + #define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) + #define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) + #define RX_DMA_VTAG BIT(15) ++#define RX_DMA_ADDR64_MASK GENMASK(3, 0) ++#if IS_ENABLED(CONFIG_64BIT) ++# define RX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(RX_DMA_ADDR64_MASK, (x))) << 32) ++# define RX_DMA_PREP_ADDR64(x) FIELD_PREP(RX_DMA_ADDR64_MASK, ((x) >> 32)) ++#else ++# define RX_DMA_GET_ADDR64(x) (0) ++# define RX_DMA_PREP_ADDR64(x) (0) ++#endif + + /* QDMA descriptor rxd3 */ + #define RX_DMA_VID(x) ((x) & VLAN_VID_MASK) +@@ -942,6 +958,7 @@ enum mkt_eth_capabilities { + MTK_RSTCTRL_PPE2_BIT, + MTK_U3_COPHY_V2_BIT, + MTK_SRAM_BIT, ++ MTK_36BIT_DMA_BIT, + + /* MUX BITS*/ + MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, +@@ -978,6 +995,7 @@ enum mkt_eth_capabilities { + #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) + #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) + #define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) ++#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT) + + #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ + BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) +@@ -1059,8 +1077,8 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_RSTCTRL_PPE1 | MTK_SRAM) + +-#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ +- MTK_RSTCTRL_PPE2 | MTK_SRAM) ++#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ ++ MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch b/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch new file mode 100644 index 0000000000..5b27458eb8 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch @@ -0,0 +1,44 @@ +From e10a35abb3da12b812cfb6fc6137926a0c81e39a Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 10 Sep 2023 22:40:30 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix uninitialized variable + +Variable dma_addr in function mtk_poll_rx can be uninitialized on +some of the error paths. In practise this doesn't matter, even random +data present in uninitialized stack memory can safely be used in the +way it happens in the error path. + +However, in order to make Smatch happy make sure the variable is +always initialized. + +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1988,11 +1988,11 @@ static int mtk_poll_rx(struct napi_struc + u8 *data, *new_data; + struct mtk_rx_dma_v2 *rxd, trxd; + int done = 0, bytes = 0; ++ dma_addr_t dma_addr = DMA_MAPPING_ERROR; + + while (done < budget) { + unsigned int pktlen, *rxdcsum; + struct net_device *netdev; +- dma_addr_t dma_addr; + u32 hash, reason; + int mac = 0; + +@@ -2169,7 +2169,8 @@ release_desc: + else + rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) && ++ likely(dma_addr != DMA_MAPPING_ERROR)) + rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); + + ring->calc_idx = idx; diff --git a/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch b/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch new file mode 100644 index 0000000000..ac3e3a3e67 --- /dev/null +++ b/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch @@ -0,0 +1,33 @@ +From 5a124b1fd3e6cb15a943f0cdfe96aa8f6d3d2f39 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 9 Sep 2023 20:41:56 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix pse_port configuration for + MT7988 + +MT7988 SoC support 3 NICs. Fix pse_port configuration in +mtk_flow_set_output_device routine if the traffic is offloaded to eth2. +Rely on mtk_pse_port definitions. + +Fixes: 88efedf517e6 ("net: ethernet: mtk_eth_soc: enable nft hw flowtable_offload for MT7988 SoC") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -214,9 +214,11 @@ mtk_flow_set_output_device(struct mtk_et + dsa_port = mtk_flow_get_dsa_port(&dev); + + if (dev == eth->netdev[0]) +- pse_port = 1; ++ pse_port = PSE_GDM1_PORT; + else if (dev == eth->netdev[1]) +- pse_port = 2; ++ pse_port = PSE_GDM2_PORT; ++ else if (dev == eth->netdev[2]) ++ pse_port = PSE_GDM3_PORT; + else + return -EOPNOTSUPP; + diff --git a/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch b/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch new file mode 100644 index 0000000000..46da5b283f --- /dev/null +++ b/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch @@ -0,0 +1,271 @@ +From: Felix Fietkau +Date: Mon, 20 Mar 2023 11:44:30 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows + from wlan devices + +WED version 2 (on MT7986 and later) can offload flows originating from wireless +devices. In order to make that work, ndo_setup_tc needs to be implemented on +the netdevs. This adds the required code to offload flows coming in from WED, +while keeping track of the incoming wed index used for selecting the correct +PPE device. + +Signed-off-by: Felix Fietkau +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + + .../net/ethernet/mediatek/mtk_ppe_offload.c | 37 ++++--- + drivers/net/ethernet/mediatek/mtk_wed.c | 101 ++++++++++++++++++ + include/linux/soc/mediatek/mtk_wed.h | 6 ++ + 4 files changed, 133 insertions(+), 14 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1435,6 +1435,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk + int mtk_eth_offload_init(struct mtk_eth *eth); + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data); ++int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, ++ int ppe_index); ++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); + + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -237,7 +237,8 @@ out: + } + + static int +-mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) ++mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, ++ int ppe_index) + { + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_action_entry *act; +@@ -454,6 +455,7 @@ mtk_flow_offload_replace(struct mtk_eth + entry->cookie = f->cookie; + memcpy(&entry->data, &foe, sizeof(entry->data)); + entry->wed_index = wed_index; ++ entry->ppe_index = ppe_index; + + err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry); + if (err < 0) +@@ -522,25 +524,15 @@ mtk_flow_offload_stats(struct mtk_eth *e + + static DEFINE_MUTEX(mtk_flow_offload_mutex); + +-static int +-mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) ++int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, ++ int ppe_index) + { +- struct flow_cls_offload *cls = type_data; +- struct net_device *dev = cb_priv; +- struct mtk_mac *mac = netdev_priv(dev); +- struct mtk_eth *eth = mac->hw; + int err; + +- if (!tc_can_offload(dev)) +- return -EOPNOTSUPP; +- +- if (type != TC_SETUP_CLSFLOWER) +- return -EOPNOTSUPP; +- + mutex_lock(&mtk_flow_offload_mutex); + switch (cls->command) { + case FLOW_CLS_REPLACE: +- err = mtk_flow_offload_replace(eth, cls); ++ err = mtk_flow_offload_replace(eth, cls, ppe_index); + break; + case FLOW_CLS_DESTROY: + err = mtk_flow_offload_destroy(eth, cls); +@@ -558,6 +550,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ + } + + static int ++mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) ++{ ++ struct flow_cls_offload *cls = type_data; ++ struct net_device *dev = cb_priv; ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ ++ if (!tc_can_offload(dev)) ++ return -EOPNOTSUPP; ++ ++ if (type != TC_SETUP_CLSFLOWER) ++ return -EOPNOTSUPP; ++ ++ return mtk_flow_offload_cmd(eth, cls, 0); ++} ++ ++static int + mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f) + { + struct mtk_mac *mac = netdev_priv(dev); +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -13,6 +13,8 @@ + #include + #include + #include ++#include ++#include + #include "mtk_eth_soc.h" + #include "mtk_wed_regs.h" + #include "mtk_wed.h" +@@ -41,6 +43,11 @@ + static struct mtk_wed_hw *hw_list[2]; + static DEFINE_MUTEX(hw_lock); + ++struct mtk_wed_flow_block_priv { ++ struct mtk_wed_hw *hw; ++ struct net_device *dev; ++}; ++ + static void + wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) + { +@@ -1753,6 +1760,99 @@ out: + mutex_unlock(&hw_lock); + } + ++static int ++mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) ++{ ++ struct mtk_wed_flow_block_priv *priv = cb_priv; ++ struct flow_cls_offload *cls = type_data; ++ struct mtk_wed_hw *hw = priv->hw; ++ ++ if (!tc_can_offload(priv->dev)) ++ return -EOPNOTSUPP; ++ ++ if (type != TC_SETUP_CLSFLOWER) ++ return -EOPNOTSUPP; ++ ++ return mtk_flow_offload_cmd(hw->eth, cls, hw->index); ++} ++ ++static int ++mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev, ++ struct flow_block_offload *f) ++{ ++ struct mtk_wed_flow_block_priv *priv; ++ static LIST_HEAD(block_cb_list); ++ struct flow_block_cb *block_cb; ++ struct mtk_eth *eth = hw->eth; ++ flow_setup_cb_t *cb; ++ ++ if (!eth->soc->offload_version) ++ return -EOPNOTSUPP; ++ ++ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) ++ return -EOPNOTSUPP; ++ ++ cb = mtk_wed_setup_tc_block_cb; ++ f->driver_block_list = &block_cb_list; ++ ++ switch (f->command) { ++ case FLOW_BLOCK_BIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); ++ if (block_cb) { ++ flow_block_cb_incref(block_cb); ++ return 0; ++ } ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->hw = hw; ++ priv->dev = dev; ++ block_cb = flow_block_cb_alloc(cb, dev, priv, NULL); ++ if (IS_ERR(block_cb)) { ++ kfree(priv); ++ return PTR_ERR(block_cb); ++ } ++ ++ flow_block_cb_incref(block_cb); ++ flow_block_cb_add(block_cb, f); ++ list_add_tail(&block_cb->driver_list, &block_cb_list); ++ return 0; ++ case FLOW_BLOCK_UNBIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); ++ if (!block_cb) ++ return -ENOENT; ++ ++ if (!flow_block_cb_decref(block_cb)) { ++ flow_block_cb_remove(block_cb, f); ++ list_del(&block_cb->driver_list); ++ kfree(block_cb->cb_priv); ++ } ++ return 0; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int ++mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev, ++ enum tc_setup_type type, void *type_data) ++{ ++ struct mtk_wed_hw *hw = wed->hw; ++ ++ if (hw->version < 2) ++ return -EOPNOTSUPP; ++ ++ switch (type) { ++ case TC_SETUP_BLOCK: ++ case TC_SETUP_FT: ++ return mtk_wed_setup_tc_block(hw, dev, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, + void __iomem *wdma, phys_addr_t wdma_phy, + int index) +@@ -1772,6 +1872,7 @@ void mtk_wed_add_hw(struct device_node * + .irq_set_mask = mtk_wed_irq_set_mask, + .detach = mtk_wed_detach, + .ppe_check = mtk_wed_ppe_check, ++ .setup_tc = mtk_wed_setup_tc, + }; + struct device_node *eth_np = eth->dev->of_node; + struct platform_device *pdev; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + #define MTK_WED_TX_QUEUES 2 + #define MTK_WED_RX_QUEUES 2 +@@ -180,6 +181,8 @@ struct mtk_wed_ops { + + u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask); + void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); ++ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, ++ enum tc_setup_type type, void *type_data); + }; + + extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; +@@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic + (_dev)->ops->msg_update(_dev, _id, _msg, _len) + #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) + #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) ++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ ++ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) + #else + static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) + { +@@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV + #define mtk_wed_device_stop(_dev) do {} while (0) + #define mtk_wed_device_dma_reset(_dev) do {} while (0) ++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP + #endif + + #endif diff --git a/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch b/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch new file mode 100644 index 0000000000..b1796641a3 --- /dev/null +++ b/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Mon, 20 Mar 2023 15:37:55 +0100 +Subject: [PATCH] net: ethernet: mediatek: mtk_ppe: prefer newly added l2 + flows over existing ones + +When a device is roaming between interfaces and a new flow entry is created, +we should assume that its output device is more up to date than whatever +entry existed already. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -656,10 +656,20 @@ void mtk_foe_entry_clear(struct mtk_ppe + static int + mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { ++ struct mtk_flow_entry *prev; ++ + entry->type = MTK_FLOW_TYPE_L2; + +- return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node, +- mtk_flow_l2_ht_params); ++ prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &entry->l2_node, ++ mtk_flow_l2_ht_params); ++ if (likely(!prev)) ++ return 0; ++ ++ if (IS_ERR(prev)) ++ return PTR_ERR(prev); ++ ++ return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node, ++ &entry->l2_node, mtk_flow_l2_ht_params); + } + + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) diff --git a/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch b/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch new file mode 100644 index 0000000000..8b8a8e11c7 --- /dev/null +++ b/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch @@ -0,0 +1,334 @@ +From: Felix Fietkau +Date: Thu, 23 Mar 2023 10:24:11 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: improve keeping track of + offloaded flows + +Unify tracking of L2 and L3 flows. Use the generic list field in struct +mtk_foe_entry for tracking L2 subflows. Preparation for improving +flow accounting support. + +Signed-off-by: Felix Fietkau +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 162 ++++++++++++------------ + drivers/net/ethernet/mediatek/mtk_ppe.h | 15 +-- + 2 files changed, 86 insertions(+), 91 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -476,42 +476,43 @@ int mtk_foe_entry_set_queue(struct mtk_e + return 0; + } + ++static int ++mtk_flow_entry_match_len(struct mtk_eth *eth, struct mtk_foe_entry *entry) ++{ ++ int type = mtk_get_ib1_pkt_type(eth, entry->ib1); ++ ++ if (type > MTK_PPE_PKT_TYPE_IPV4_DSLITE) ++ return offsetof(struct mtk_foe_entry, ipv6._rsv); ++ else ++ return offsetof(struct mtk_foe_entry, ipv4.ib2); ++} ++ + static bool + mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry, +- struct mtk_foe_entry *data) ++ struct mtk_foe_entry *data, int len) + { +- int type, len; +- + if ((data->ib1 ^ entry->data.ib1) & MTK_FOE_IB1_UDP) + return false; + +- type = mtk_get_ib1_pkt_type(eth, entry->data.ib1); +- if (type > MTK_PPE_PKT_TYPE_IPV4_DSLITE) +- len = offsetof(struct mtk_foe_entry, ipv6._rsv); +- else +- len = offsetof(struct mtk_foe_entry, ipv4.ib2); +- + return !memcmp(&entry->data.data, &data->data, len - 4); + } + + static void +-__mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++__mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ bool set_state) + { +- struct hlist_head *head; + struct hlist_node *tmp; + + if (entry->type == MTK_FLOW_TYPE_L2) { + rhashtable_remove_fast(&ppe->l2_flows, &entry->l2_node, + mtk_flow_l2_ht_params); + +- head = &entry->l2_flows; +- hlist_for_each_entry_safe(entry, tmp, head, l2_data.list) +- __mtk_foe_entry_clear(ppe, entry); ++ hlist_for_each_entry_safe(entry, tmp, &entry->l2_flows, l2_list) ++ __mtk_foe_entry_clear(ppe, entry, set_state); + return; + } + +- hlist_del_init(&entry->list); +- if (entry->hash != 0xffff) { ++ if (entry->hash != 0xffff && set_state) { + struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, entry->hash); + + hwe->ib1 &= ~MTK_FOE_IB1_STATE; +@@ -531,7 +532,8 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp + if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW) + return; + +- hlist_del_init(&entry->l2_data.list); ++ hlist_del_init(&entry->l2_list); ++ hlist_del_init(&entry->list); + kfree(entry); + } + +@@ -547,66 +549,55 @@ static int __mtk_foe_entry_idle_time(str + return now - timestamp; + } + ++static bool ++mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ struct mtk_foe_entry foe = {}; ++ struct mtk_foe_entry *hwe; ++ u16 hash = entry->hash; ++ int len; ++ ++ if (hash == 0xffff) ++ return false; ++ ++ hwe = mtk_foe_get_entry(ppe, hash); ++ len = mtk_flow_entry_match_len(ppe->eth, &entry->data); ++ memcpy(&foe, hwe, len); ++ ++ if (!mtk_flow_entry_match(ppe->eth, entry, &foe, len) || ++ FIELD_GET(MTK_FOE_IB1_STATE, foe.ib1) != MTK_FOE_STATE_BIND) ++ return false; ++ ++ entry->data.ib1 = foe.ib1; ++ ++ return true; ++} ++ + static void + mtk_flow_entry_update_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + u32 ib1_ts_mask = mtk_get_ib1_ts_mask(ppe->eth); + struct mtk_flow_entry *cur; +- struct mtk_foe_entry *hwe; + struct hlist_node *tmp; + int idle; + + idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); +- hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_data.list) { ++ hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_list) { + int cur_idle; +- u32 ib1; +- +- hwe = mtk_foe_get_entry(ppe, cur->hash); +- ib1 = READ_ONCE(hwe->ib1); + +- if (FIELD_GET(MTK_FOE_IB1_STATE, ib1) != MTK_FOE_STATE_BIND) { +- cur->hash = 0xffff; +- __mtk_foe_entry_clear(ppe, cur); ++ if (!mtk_flow_entry_update(ppe, cur)) { ++ __mtk_foe_entry_clear(ppe, entry, false); + continue; + } + +- cur_idle = __mtk_foe_entry_idle_time(ppe, ib1); ++ cur_idle = __mtk_foe_entry_idle_time(ppe, cur->data.ib1); + if (cur_idle >= idle) + continue; + + idle = cur_idle; + entry->data.ib1 &= ~ib1_ts_mask; +- entry->data.ib1 |= hwe->ib1 & ib1_ts_mask; +- } +-} +- +-static void +-mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) +-{ +- struct mtk_foe_entry foe = {}; +- struct mtk_foe_entry *hwe; +- +- spin_lock_bh(&ppe_lock); +- +- if (entry->type == MTK_FLOW_TYPE_L2) { +- mtk_flow_entry_update_l2(ppe, entry); +- goto out; ++ entry->data.ib1 |= cur->data.ib1 & ib1_ts_mask; + } +- +- if (entry->hash == 0xffff) +- goto out; +- +- hwe = mtk_foe_get_entry(ppe, entry->hash); +- memcpy(&foe, hwe, ppe->eth->soc->foe_entry_size); +- if (!mtk_flow_entry_match(ppe->eth, entry, &foe)) { +- entry->hash = 0xffff; +- goto out; +- } +- +- entry->data.ib1 = foe.ib1; +- +-out: +- spin_unlock_bh(&ppe_lock); + } + + static void +@@ -649,7 +640,8 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + spin_lock_bh(&ppe_lock); +- __mtk_foe_entry_clear(ppe, entry); ++ __mtk_foe_entry_clear(ppe, entry, true); ++ hlist_del_init(&entry->list); + spin_unlock_bh(&ppe_lock); + } + +@@ -696,8 +688,8 @@ mtk_foe_entry_commit_subflow(struct mtk_ + { + const struct mtk_soc_data *soc = ppe->eth->soc; + struct mtk_flow_entry *flow_info; +- struct mtk_foe_entry foe = {}, *hwe; + struct mtk_foe_mac_info *l2; ++ struct mtk_foe_entry *hwe; + u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP; + int type; + +@@ -705,30 +697,30 @@ mtk_foe_entry_commit_subflow(struct mtk_ + if (!flow_info) + return; + +- flow_info->l2_data.base_flow = entry; + flow_info->type = MTK_FLOW_TYPE_L2_SUBFLOW; + flow_info->hash = hash; + hlist_add_head(&flow_info->list, + &ppe->foe_flow[hash / soc->hash_offset]); +- hlist_add_head(&flow_info->l2_data.list, &entry->l2_flows); ++ hlist_add_head(&flow_info->l2_list, &entry->l2_flows); + + hwe = mtk_foe_get_entry(ppe, hash); +- memcpy(&foe, hwe, soc->foe_entry_size); +- foe.ib1 &= ib1_mask; +- foe.ib1 |= entry->data.ib1 & ~ib1_mask; ++ memcpy(&flow_info->data, hwe, soc->foe_entry_size); ++ flow_info->data.ib1 &= ib1_mask; ++ flow_info->data.ib1 |= entry->data.ib1 & ~ib1_mask; + +- l2 = mtk_foe_entry_l2(ppe->eth, &foe); ++ l2 = mtk_foe_entry_l2(ppe->eth, &flow_info->data); + memcpy(l2, &entry->data.bridge.l2, sizeof(*l2)); + +- type = mtk_get_ib1_pkt_type(ppe->eth, foe.ib1); ++ type = mtk_get_ib1_pkt_type(ppe->eth, flow_info->data.ib1); + if (type == MTK_PPE_PKT_TYPE_IPV4_HNAPT) +- memcpy(&foe.ipv4.new, &foe.ipv4.orig, sizeof(foe.ipv4.new)); ++ memcpy(&flow_info->data.ipv4.new, &flow_info->data.ipv4.orig, ++ sizeof(flow_info->data.ipv4.new)); + else if (type >= MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T && l2->etype == ETH_P_IP) + l2->etype = ETH_P_IPV6; + +- *mtk_foe_entry_ib2(ppe->eth, &foe) = entry->data.bridge.ib2; ++ *mtk_foe_entry_ib2(ppe->eth, &flow_info->data) = entry->data.bridge.ib2; + +- __mtk_foe_entry_commit(ppe, &foe, hash); ++ __mtk_foe_entry_commit(ppe, &flow_info->data, hash); + } + + void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) +@@ -738,9 +730,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe + struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, hash); + struct mtk_flow_entry *entry; + struct mtk_foe_bridge key = {}; ++ struct mtk_foe_entry foe = {}; + struct hlist_node *n; + struct ethhdr *eh; + bool found = false; ++ int entry_len; + u8 *tag; + + spin_lock_bh(&ppe_lock); +@@ -748,20 +742,14 @@ void __mtk_ppe_check_skb(struct mtk_ppe + if (FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == MTK_FOE_STATE_BIND) + goto out; + +- hlist_for_each_entry_safe(entry, n, head, list) { +- if (entry->type == MTK_FLOW_TYPE_L2_SUBFLOW) { +- if (unlikely(FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == +- MTK_FOE_STATE_BIND)) +- continue; +- +- entry->hash = 0xffff; +- __mtk_foe_entry_clear(ppe, entry); +- continue; +- } ++ entry_len = mtk_flow_entry_match_len(ppe->eth, hwe); ++ memcpy(&foe, hwe, entry_len); + +- if (found || !mtk_flow_entry_match(ppe->eth, entry, hwe)) { ++ hlist_for_each_entry_safe(entry, n, head, list) { ++ if (found || ++ !mtk_flow_entry_match(ppe->eth, entry, &foe, entry_len)) { + if (entry->hash != 0xffff) +- entry->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, entry, false); + continue; + } + +@@ -810,9 +798,17 @@ out: + + int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { +- mtk_flow_entry_update(ppe, entry); ++ int idle; ++ ++ spin_lock_bh(&ppe_lock); ++ if (entry->type == MTK_FLOW_TYPE_L2) ++ mtk_flow_entry_update_l2(ppe, entry); ++ else ++ mtk_flow_entry_update(ppe, entry); ++ idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ spin_unlock_bh(&ppe_lock); + +- return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ return idle; + } + + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -286,7 +286,12 @@ enum { + + struct mtk_flow_entry { + union { +- struct hlist_node list; ++ /* regular flows + L2 subflows */ ++ struct { ++ struct hlist_node list; ++ struct hlist_node l2_list; ++ }; ++ /* L2 flows */ + struct { + struct rhash_head l2_node; + struct hlist_head l2_flows; +@@ -296,13 +301,7 @@ struct mtk_flow_entry { + s8 wed_index; + u8 ppe_index; + u16 hash; +- union { +- struct mtk_foe_entry data; +- struct { +- struct mtk_flow_entry *base_flow; +- struct hlist_node list; +- } l2_data; +- }; ++ struct mtk_foe_entry data; + struct rhash_head node; + unsigned long cookie; + }; diff --git a/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch new file mode 100644 index 0000000000..e20f94f1d4 --- /dev/null +++ b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch @@ -0,0 +1,342 @@ +From: Felix Fietkau +Date: Thu, 23 Mar 2023 11:05:22 +0100 +Subject: [PATCH] net: ethernet: mediatek: fix ppe flow accounting for L2 + flows + +For L2 flows, the packet/byte counters should report the sum of the +counters of their subflows, both current and expired. +In order to make this work, change the way that accounting data is tracked. +Reset counters when a flow enters bind. Once it expires (or enters unbind), +store the last counter value in struct mtk_flow_entry. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -79,9 +79,9 @@ static int mtk_ppe_mib_wait_busy(struct + int ret; + u32 val; + +- ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, +- !(val & MTK_PPE_MIB_SER_CR_ST), +- 20, MTK_PPE_WAIT_TIMEOUT_US); ++ ret = readl_poll_timeout_atomic(ppe->base + MTK_PPE_MIB_SER_CR, val, ++ !(val & MTK_PPE_MIB_SER_CR_ST), ++ 20, MTK_PPE_WAIT_TIMEOUT_US); + + if (ret) + dev_err(ppe->dev, "MIB table busy"); +@@ -89,17 +89,31 @@ static int mtk_ppe_mib_wait_busy(struct + return ret; + } + +-static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) ++static inline struct mtk_foe_accounting * ++mtk_ppe_acct_data(struct mtk_ppe *ppe, u16 index) ++{ ++ if (!ppe->acct_table) ++ return NULL; ++ ++ return ppe->acct_table + index * sizeof(struct mtk_foe_accounting); ++} ++ ++struct mtk_foe_accounting *mtk_ppe_mib_entry_read(struct mtk_ppe *ppe, u16 index) + { + u32 val, cnt_r0, cnt_r1, cnt_r2; ++ struct mtk_foe_accounting *acct; + int ret; + + val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; + ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); + ++ acct = mtk_ppe_acct_data(ppe, index); ++ if (!acct) ++ return NULL; ++ + ret = mtk_ppe_mib_wait_busy(ppe); + if (ret) +- return ret; ++ return acct; + + cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); +@@ -108,19 +122,19 @@ static int mtk_mib_entry_read(struct mtk + if (mtk_is_netsys_v3_or_greater(ppe->eth)) { + /* 64 bit for each counter */ + u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); +- *bytes = ((u64)cnt_r1 << 32) | cnt_r0; +- *packets = ((u64)cnt_r3 << 32) | cnt_r2; ++ acct->bytes += ((u64)cnt_r1 << 32) | cnt_r0; ++ acct->packets += ((u64)cnt_r3 << 32) | cnt_r2; + } else { + /* 48 bit byte counter, 40 bit packet counter */ + u32 byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); + u32 byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); + u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); + u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); +- *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; +- *packets = (pkt_cnt_high << 16) | pkt_cnt_low; ++ acct->bytes += ((u64)byte_cnt_high << 32) | byte_cnt_low; ++ acct->packets += (pkt_cnt_high << 16) | pkt_cnt_low; + } + +- return 0; ++ return acct; + } + + static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) +@@ -519,13 +533,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp + hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); + dma_wmb(); + mtk_ppe_cache_clear(ppe); +- if (ppe->accounting) { +- struct mtk_foe_accounting *acct; +- +- acct = ppe->acct_table + entry->hash * sizeof(*acct); +- acct->packets = 0; +- acct->bytes = 0; +- } + } + entry->hash = 0xffff; + +@@ -550,11 +557,14 @@ static int __mtk_foe_entry_idle_time(str + } + + static bool +-mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ u64 *packets, u64 *bytes) + { ++ struct mtk_foe_accounting *acct; + struct mtk_foe_entry foe = {}; + struct mtk_foe_entry *hwe; + u16 hash = entry->hash; ++ bool ret = false; + int len; + + if (hash == 0xffff) +@@ -565,18 +575,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp + memcpy(&foe, hwe, len); + + if (!mtk_flow_entry_match(ppe->eth, entry, &foe, len) || +- FIELD_GET(MTK_FOE_IB1_STATE, foe.ib1) != MTK_FOE_STATE_BIND) +- return false; ++ FIELD_GET(MTK_FOE_IB1_STATE, foe.ib1) != MTK_FOE_STATE_BIND) { ++ acct = mtk_ppe_acct_data(ppe, hash); ++ if (acct) { ++ entry->prev_packets += acct->packets; ++ entry->prev_bytes += acct->bytes; ++ } ++ ++ goto out; ++ } + + entry->data.ib1 = foe.ib1; ++ acct = mtk_ppe_mib_entry_read(ppe, hash); ++ ret = true; ++ ++out: ++ if (acct) { ++ *packets += acct->packets; ++ *bytes += acct->bytes; ++ } + +- return true; ++ return ret; + } + + static void + mtk_flow_entry_update_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + u32 ib1_ts_mask = mtk_get_ib1_ts_mask(ppe->eth); ++ u64 *packets = &entry->packets; ++ u64 *bytes = &entry->bytes; + struct mtk_flow_entry *cur; + struct hlist_node *tmp; + int idle; +@@ -585,7 +612,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe + hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_list) { + int cur_idle; + +- if (!mtk_flow_entry_update(ppe, cur)) { ++ if (!mtk_flow_entry_update(ppe, cur, packets, bytes)) { ++ entry->prev_packets += cur->prev_packets; ++ entry->prev_bytes += cur->prev_bytes; + __mtk_foe_entry_clear(ppe, entry, false); + continue; + } +@@ -600,10 +629,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe + } + } + ++void mtk_foe_entry_get_stats(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ int *idle) ++{ ++ entry->packets = entry->prev_packets; ++ entry->bytes = entry->prev_bytes; ++ ++ spin_lock_bh(&ppe_lock); ++ ++ if (entry->type == MTK_FLOW_TYPE_L2) ++ mtk_flow_entry_update_l2(ppe, entry); ++ else ++ mtk_flow_entry_update(ppe, entry, &entry->packets, &entry->bytes); ++ ++ *idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ ++ spin_unlock_bh(&ppe_lock); ++} ++ + static void + __mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, + u16 hash) + { ++ struct mtk_foe_accounting *acct; + struct mtk_eth *eth = ppe->eth; + u16 timestamp = mtk_eth_timestamp(eth); + struct mtk_foe_entry *hwe; +@@ -634,6 +682,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + + dma_wmb(); + ++ acct = mtk_ppe_mib_entry_read(ppe, hash); ++ if (acct) { ++ acct->packets = 0; ++ acct->bytes = 0; ++ } ++ + mtk_ppe_cache_clear(ppe); + } + +@@ -796,21 +850,6 @@ out: + spin_unlock_bh(&ppe_lock); + } + +-int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) +-{ +- int idle; +- +- spin_lock_bh(&ppe_lock); +- if (entry->type == MTK_FLOW_TYPE_L2) +- mtk_flow_entry_update_l2(ppe, entry); +- else +- mtk_flow_entry_update(ppe, entry); +- idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); +- spin_unlock_bh(&ppe_lock); +- +- return idle; +-} +- + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) + { + if (!ppe) +@@ -838,32 +877,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe + return mtk_ppe_wait_busy(ppe); + } + +-struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, +- struct mtk_foe_accounting *diff) +-{ +- struct mtk_foe_accounting *acct; +- int size = sizeof(struct mtk_foe_accounting); +- u64 bytes, packets; +- +- if (!ppe->accounting) +- return NULL; +- +- if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) +- return NULL; +- +- acct = ppe->acct_table + index * size; +- +- acct->bytes += bytes; +- acct->packets += packets; +- +- if (diff) { +- diff->bytes = bytes; +- diff->packets = packets; +- } +- +- return acct; +-} +- + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) + { + bool accounting = eth->soc->has_accounting; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -304,6 +304,8 @@ struct mtk_flow_entry { + struct mtk_foe_entry data; + struct rhash_head node; + unsigned long cookie; ++ u64 prev_packets, prev_bytes; ++ u64 packets, bytes; + }; + + struct mtk_mib_entry { +@@ -348,6 +350,7 @@ void mtk_ppe_deinit(struct mtk_eth *eth) + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); ++struct mtk_foe_accounting *mtk_ppe_mib_entry_read(struct mtk_ppe *ppe, u16 index); + + void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); + +@@ -396,9 +399,8 @@ int mtk_foe_entry_set_queue(struct mtk_e + unsigned int queue); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); +-int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); +-struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, +- struct mtk_foe_accounting *diff); ++void mtk_foe_entry_get_stats(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ int *idle); + + #endif +--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -96,7 +96,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file + if (bind && state != MTK_FOE_STATE_BIND) + continue; + +- acct = mtk_foe_entry_get_mib(ppe, i, NULL); ++ acct = mtk_ppe_mib_entry_read(ppe, i); + + type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1); + seq_printf(m, "%05x %s %7s", i, +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -501,24 +501,21 @@ static int + mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) + { + struct mtk_flow_entry *entry; +- struct mtk_foe_accounting diff; +- u32 idle; ++ u64 packets, bytes; ++ int idle; + + entry = rhashtable_lookup(ð->flow_table, &f->cookie, + mtk_flow_ht_params); + if (!entry) + return -ENOENT; + +- idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); ++ packets = entry->packets; ++ bytes = entry->bytes; ++ mtk_foe_entry_get_stats(eth->ppe[entry->ppe_index], entry, &idle); ++ f->stats.pkts += entry->packets - packets; ++ f->stats.bytes += entry->bytes - bytes; + f->stats.lastused = jiffies - idle * HZ; + +- if (entry->hash != 0xFFFF && +- mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, +- &diff)) { +- f->stats.pkts += diff.packets; +- f->stats.bytes += diff.bytes; +- } +- + return 0; + } + diff --git a/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch b/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch new file mode 100644 index 0000000000..a224b62624 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch @@ -0,0 +1,45 @@ +From: Lorenzo Bianconi +Date: Sun, 27 Aug 2023 19:31:41 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add some more info in wed_txinfo_show + handler + +Add some new info in Wireless Ethernet Dispatcher wed_txinfo_show +debugfs handler useful during debugging. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/3390292655d568180b73d2a25576f61aa63310e5.1693157377.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -127,8 +127,17 @@ wed_txinfo_show(struct seq_file *s, void + DUMP_WDMA_RING(WDMA_RING_RX(0)), + DUMP_WDMA_RING(WDMA_RING_RX(1)), + +- DUMP_STR("TX FREE"), ++ DUMP_STR("WED TX FREE"), + DUMP_WED(WED_RX_MIB(0)), ++ DUMP_WED_RING(WED_RING_RX(0)), ++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), ++ DUMP_WED(WED_RX_MIB(1)), ++ DUMP_WED_RING(WED_RING_RX(1)), ++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), ++ ++ DUMP_STR("WED WPDMA TX FREE"), ++ DUMP_WED_RING(WED_WPDMA_RING_RX(0)), ++ DUMP_WED_RING(WED_WPDMA_RING_RX(1)), + }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -266,6 +266,8 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) + #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) + + #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) + #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) diff --git a/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch b/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch new file mode 100644 index 0000000000..df6edfdf94 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch @@ -0,0 +1,47 @@ +From: Lorenzo Bianconi +Date: Sun, 27 Aug 2023 19:33:47 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: minor change in wed_{tx,rx}info_show + +No functional changes, just cosmetic ones. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/71e046c72a978745f0435af265dda610aa9bfbcf.1693157578.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct + } + } + +- + static int + wed_txinfo_show(struct seq_file *s, void *data) + { +@@ -142,10 +141,8 @@ wed_txinfo_show(struct seq_file *s, void + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (!dev) +- return 0; +- +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + + return 0; + } +@@ -217,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (!dev) +- return 0; +- +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + + return 0; + } diff --git a/target/linux/generic/backport-6.6/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch b/target/linux/generic/backport-6.6/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch new file mode 100644 index 0000000000..0bf9dea24f --- /dev/null +++ b/target/linux/generic/backport-6.6/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch @@ -0,0 +1,29 @@ +From: Lorenzo Bianconi +Date: Tue, 12 Sep 2023 10:22:56 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: rely on mtk_pse_port definitions + in mtk_flow_set_output_device + +Similar to ethernet ports, rely on mtk_pse_port definitions for +pse wdma ports as well. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/b86bdb717e963e3246c1dec5f736c810703cf056.1694506814.git.lorenzo@kernel.org +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -196,10 +196,10 @@ mtk_flow_set_output_device(struct mtk_et + if (mtk_is_netsys_v2_or_greater(eth)) { + switch (info.wdma_idx) { + case 0: +- pse_port = 8; ++ pse_port = PSE_WDMA0_PORT; + break; + case 1: +- pse_port = 9; ++ pse_port = PSE_WDMA1_PORT; + break; + default: + return -EINVAL; diff --git a/target/linux/generic/backport-6.6/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch b/target/linux/generic/backport-6.6/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch new file mode 100644 index 0000000000..c99e1334d4 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch @@ -0,0 +1,26 @@ +From: Lorenzo Bianconi +Date: Tue, 12 Sep 2023 10:28:00 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: check update_wo_rx_stats in + mtk_wed_update_rx_stats() + +Check if update_wo_rx_stats function pointer is properly set in +mtk_wed_update_rx_stats routine before accessing it. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/b0d233386e059bccb59f18f69afb79a7806e5ded.1694507226.git.lorenzo@kernel.org +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -68,6 +68,9 @@ mtk_wed_update_rx_stats(struct mtk_wed_d + struct mtk_wed_wo_rx_stats *stats; + int i; + ++ if (!wed->wlan.update_wo_rx_stats) ++ return; ++ + if (count * sizeof(*stats) > skb->len - sizeof(u32)) + return; + diff --git a/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch b/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch new file mode 100644 index 0000000000..cd7fb92e20 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch @@ -0,0 +1,68 @@ +From: Lorenzo Bianconi +Date: Wed, 13 Sep 2023 20:42:47 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: do not assume offload callbacks are + always set + +Check if wlan.offload_enable and wlan.offload_disable callbacks are set +in mtk_wed_flow_add/mtk_wed_flow_remove since mt7996 will not rely +on them. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1712,19 +1712,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_devi + int mtk_wed_flow_add(int index) + { + struct mtk_wed_hw *hw = hw_list[index]; +- int ret; ++ int ret = 0; + +- if (!hw || !hw->wed_dev) +- return -ENODEV; ++ mutex_lock(&hw_lock); + +- if (hw->num_flows) { +- hw->num_flows++; +- return 0; ++ if (!hw || !hw->wed_dev) { ++ ret = -ENODEV; ++ goto out; + } + +- mutex_lock(&hw_lock); +- if (!hw->wed_dev) { +- ret = -ENODEV; ++ if (!hw->wed_dev->wlan.offload_enable) ++ goto out; ++ ++ if (hw->num_flows) { ++ hw->num_flows++; + goto out; + } + +@@ -1743,14 +1744,15 @@ void mtk_wed_flow_remove(int index) + { + struct mtk_wed_hw *hw = hw_list[index]; + +- if (!hw) +- return; ++ mutex_lock(&hw_lock); + +- if (--hw->num_flows) +- return; ++ if (!hw || !hw->wed_dev) ++ goto out; + +- mutex_lock(&hw_lock); +- if (!hw->wed_dev) ++ if (!hw->wed_dev->wlan.offload_disable) ++ goto out; ++ ++ if (--hw->num_flows) + goto out; + + hw->wed_dev->wlan.offload_disable(hw->wed_dev); diff --git a/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch b/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch new file mode 100644 index 0000000000..2948188650 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch @@ -0,0 +1,232 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:05 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce versioning utility routines + +Similar to mtk_eth_soc, introduce the following wed versioning +utility routines: +- mtk_wed_is_v1 +- mtk_wed_is_v2 + +This is a preliminary patch to introduce WED support for MT7988 SoC + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -277,7 +277,7 @@ mtk_wed_assign(struct mtk_wed_device *de + if (!hw->wed_dev) + goto out; + +- if (hw->version == 1) ++ if (mtk_wed_is_v1(hw)) + return NULL; + + /* MT7986 WED devices do not have any pcie slot restrictions */ +@@ -358,7 +358,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + desc->buf0 = cpu_to_le32(buf_phys); + desc->buf1 = cpu_to_le32(buf_phys + txd_size); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | + FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, + MTK_WED_BUF_SIZE - txd_size) | +@@ -497,7 +497,7 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + { + u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; + else + mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +@@ -576,7 +576,7 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | + MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); + wdma_clr(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); +@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); + wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); +@@ -624,7 +624,7 @@ mtk_wed_deinit(struct mtk_wed_device *de + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + wed_clr(dev, MTK_WED_CTRL, +@@ -730,7 +730,7 @@ mtk_wed_bus_init(struct mtk_wed_device * + static void + mtk_wed_set_wpdma(struct mtk_wed_device *dev) + { +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); + } else { + mtk_wed_bus_init(dev); +@@ -761,7 +761,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev + MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; + wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + u32 offset = dev->hw->index ? 0x04000400 : 0; + + wdma_set(dev, MTK_WDMA_GLO_CFG, +@@ -934,7 +934,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_TX_BM_TKID, + FIELD_PREP(MTK_WED_TX_BM_TKID_START, + dev->wlan.token_start) | +@@ -967,7 +967,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_set(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); +@@ -1217,7 +1217,7 @@ mtk_wed_reset_dma(struct mtk_wed_device + } + + dev->init_done = false; +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + if (!busy) { +@@ -1343,7 +1343,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, + MTK_WED_PCIE_INT_TRIGGER_STATUS); + +@@ -1416,7 +1416,7 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | + MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + } else { +@@ -1465,7 +1465,7 @@ mtk_wed_start(struct mtk_wed_device *dev + + mtk_wed_set_ext_int(dev, true); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN | + FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, + dev->hw->index); +@@ -1550,7 +1550,7 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (hw->version == 1) { ++ if (mtk_wed_is_v1(hw)) { + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); + } else { +@@ -1618,7 +1618,7 @@ static int + mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) + { + struct mtk_wed_ring *ring = &dev->txfree_ring; +- int i, index = dev->hw->version == 1; ++ int i, index = mtk_wed_is_v1(dev->hw); + + /* + * For txfree event handling, the same DMA ring is shared between WED +@@ -1676,7 +1676,7 @@ mtk_wed_irq_get(struct mtk_wed_device *d + { + u32 val, ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + ext_mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; + else + ext_mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +@@ -1843,7 +1843,7 @@ mtk_wed_setup_tc(struct mtk_wed_device * + { + struct mtk_wed_hw *hw = wed->hw; + +- if (hw->version < 2) ++ if (mtk_wed_is_v1(hw)) + return -EOPNOTSUPP; + + switch (type) { +@@ -1917,9 +1917,9 @@ void mtk_wed_add_hw(struct device_node * + hw->wdma = wdma; + hw->index = index; + hw->irq = irq; +- hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; ++ hw->version = eth->soc->version; + +- if (hw->version == 1) { ++ if (mtk_wed_is_v1(hw)) { + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, + "mediatek,pcie-mirror"); + hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -40,6 +40,16 @@ struct mtk_wdma_info { + }; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++static inline bool mtk_wed_is_v1(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 1; ++} ++ ++static inline bool mtk_wed_is_v2(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 2; ++} ++ + static inline void + wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) + { +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -263,7 +263,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w + debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); + debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); +- if (hw->version != 1) ++ if (!mtk_wed_is_v1(hw)) + debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, + &wed_rxinfo_fops); + } +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -207,7 +207,7 @@ int mtk_wed_mcu_msg_update(struct mtk_we + { + struct mtk_wed_wo *wo = dev->hw->wed_wo; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return 0; + + if (WARN_ON(!wo)) diff --git a/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch b/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch new file mode 100644 index 0000000000..bc34aa33a9 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch @@ -0,0 +1,234 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:06 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: do not configure rx offload if not + supported + +Check if rx offload is supported running mtk_wed_get_rx_capa routine +before configuring it. This is a preliminary patch to introduce Wireless +Ethernet Dispatcher (WED) support for MT7988 SoC. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); + wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + +- if (mtk_wed_is_v1(dev->hw)) ++ if (!mtk_wed_get_rx_capa(dev)) + return; + + wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); +@@ -732,16 +732,21 @@ mtk_wed_set_wpdma(struct mtk_wed_device + { + if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); +- } else { +- mtk_wed_bus_init(dev); +- +- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); +- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); +- wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); +- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); ++ return; + } ++ ++ mtk_wed_bus_init(dev); ++ ++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); ++ ++ if (!mtk_wed_get_rx_capa(dev)) ++ return; ++ ++ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); ++ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); + } + + static void +@@ -973,15 +978,17 @@ mtk_wed_hw_init(struct mtk_wed_device *d + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + } else { + wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); +- /* rx hw init */ +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, +- MTK_WED_WPDMA_RX_D_RST_CRX_IDX | +- MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); +- +- mtk_wed_rx_buffer_hw_init(dev); +- mtk_wed_rro_hw_init(dev); +- mtk_wed_route_qm_hw_init(dev); ++ if (mtk_wed_get_rx_capa(dev)) { ++ /* rx hw init */ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ ++ mtk_wed_rx_buffer_hw_init(dev); ++ mtk_wed_rro_hw_init(dev); ++ mtk_wed_route_qm_hw_init(dev); ++ } + } + + wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); +@@ -1353,8 +1360,6 @@ mtk_wed_configure_irq(struct mtk_wed_dev + + wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); + } else { +- wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, +- GENMASK(1, 0)); + /* initail tx interrupt trigger */ + wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, + MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | +@@ -1373,15 +1378,20 @@ mtk_wed_configure_irq(struct mtk_wed_dev + FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, + dev->wlan.txfree_tbit)); + +- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, +- MTK_WED_WPDMA_INT_CTRL_RX0_EN | +- MTK_WED_WPDMA_INT_CTRL_RX0_CLR | +- MTK_WED_WPDMA_INT_CTRL_RX1_EN | +- MTK_WED_WPDMA_INT_CTRL_RX1_CLR | +- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, +- dev->wlan.rx_tbit[0]) | +- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, +- dev->wlan.rx_tbit[1])); ++ if (mtk_wed_get_rx_capa(dev)) { ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, ++ MTK_WED_WPDMA_INT_CTRL_RX0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RX1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, ++ dev->wlan.rx_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, ++ dev->wlan.rx_tbit[1])); ++ ++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, ++ GENMASK(1, 0)); ++ } + + wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); + wed_set(dev, MTK_WED_WDMA_INT_CTRL, +@@ -1400,6 +1410,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev + static void + mtk_wed_dma_enable(struct mtk_wed_device *dev) + { ++ int i; ++ + wed_set(dev, MTK_WED_WPDMA_INT_CTRL, MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); + + wed_set(dev, MTK_WED_GLO_CFG, +@@ -1419,33 +1431,33 @@ mtk_wed_dma_enable(struct mtk_wed_device + if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); +- } else { +- int i; ++ return; ++ } + +- wed_set(dev, MTK_WED_WPDMA_CTRL, +- MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ wed_set(dev, MTK_WED_WPDMA_CTRL, ++ MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | ++ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); + +- wed_set(dev, MTK_WED_WDMA_GLO_CFG, +- MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | +- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ if (!mtk_wed_get_rx_capa(dev)) ++ return; + +- wed_set(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); +- +- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | +- MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); + +- wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, +- MTK_WED_WPDMA_RX_D_RX_DRV_EN | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, +- 0x2)); ++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RX_DRV_EN | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, ++ 0x2)); + +- for (i = 0; i < MTK_WED_RX_QUEUES; i++) +- mtk_wed_check_wfdma_rx_fill(dev, i); +- } ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) ++ mtk_wed_check_wfdma_rx_fill(dev, i); + } + + static void +@@ -1472,7 +1484,7 @@ mtk_wed_start(struct mtk_wed_device *dev + + val |= BIT(0) | (BIT(1) * !!dev->hw->index); + regmap_write(dev->hw->mirror, dev->hw->index * 4, val); +- } else { ++ } else if (mtk_wed_get_rx_capa(dev)) { + /* driver set mid ready and only once */ + wed_w32(dev, MTK_WED_EXT_INT_MASK1, + MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); +@@ -1484,7 +1496,6 @@ mtk_wed_start(struct mtk_wed_device *dev + + if (mtk_wed_rro_cfg(dev)) + return; +- + } + + mtk_wed_set_512_support(dev, dev->wlan.wcid_512); +@@ -1550,13 +1561,14 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (mtk_wed_is_v1(hw)) { ++ if (mtk_wed_is_v1(hw)) + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); +- } else { ++ else + dev->rev_id = wed_r32(dev, MTK_WED_REV_ID); ++ ++ if (mtk_wed_get_rx_capa(dev)) + ret = mtk_wed_wo_init(hw); +- } + out: + if (ret) { + dev_err(dev->hw->dev, "failed to attach wed device\n"); +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -207,7 +207,7 @@ int mtk_wed_mcu_msg_update(struct mtk_we + { + struct mtk_wed_wo *wo = dev->hw->wed_wo; + +- if (mtk_wed_is_v1(dev->hw)) ++ if (!mtk_wed_get_rx_capa(dev)) + return 0; + + if (WARN_ON(!wo)) diff --git a/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch new file mode 100644 index 0000000000..d83434fb2c --- /dev/null +++ b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch @@ -0,0 +1,52 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:07 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: rename mtk_rxbm_desc in + mtk_wed_bm_desc + +Rename mtk_rxbm_desc structure in mtk_wed_bm_desc since it will be used +even on tx side by MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -421,7 +421,7 @@ free_pagelist: + static int + mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) + { +- struct mtk_rxbm_desc *desc; ++ struct mtk_wed_bm_desc *desc; + dma_addr_t desc_phys; + + dev->rx_buf_ring.size = dev->wlan.rx_nbuf; +@@ -441,7 +441,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d + static void + mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) + { +- struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; ++ struct mtk_wed_bm_desc *desc = dev->rx_buf_ring.desc; + + if (!desc) + return; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -45,7 +45,7 @@ enum mtk_wed_wo_cmd { + MTK_WED_WO_CMD_WED_END + }; + +-struct mtk_rxbm_desc { ++struct mtk_wed_bm_desc { + __le32 buf0; + __le32 token; + } __packed __aligned(4); +@@ -105,7 +105,7 @@ struct mtk_wed_device { + struct { + int size; + struct page_frag_cache rx_page; +- struct mtk_rxbm_desc *desc; ++ struct mtk_wed_bm_desc *desc; + dma_addr_t desc_phys; + } rx_buf_ring; + diff --git a/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch b/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch new file mode 100644 index 0000000000..8000a8759e --- /dev/null +++ b/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch @@ -0,0 +1,87 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:08 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce mtk_wed_buf structure + +Introduce mtk_wed_buf structure to store both virtual and physical +addresses allocated in mtk_wed_tx_buffer_alloc() routine. This is a +preliminary patch to add WED support for MT7988 SoC since it relies on a +different dma descriptor layout not storing page dma addresses. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -299,9 +299,9 @@ out: + static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { ++ struct mtk_wed_buf *page_list; + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +- void **page_list; + int token = dev->wlan.token_start; + int ring_size; + int n_pages; +@@ -342,7 +342,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + return -ENOMEM; + } + +- page_list[page_idx++] = page; ++ page_list[page_idx].p = page; ++ page_list[page_idx++].phy_addr = page_phys; + dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, + DMA_BIDIRECTIONAL); + +@@ -386,8 +387,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + static void + mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) + { ++ struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages; + struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; +- void **page_list = dev->tx_buf_ring.pages; + int page_idx; + int i; + +@@ -399,13 +400,12 @@ mtk_wed_free_tx_buffer(struct mtk_wed_de + + for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; + i += MTK_WED_BUF_PER_PAGE) { +- void *page = page_list[page_idx++]; +- dma_addr_t buf_addr; ++ dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ void *page = page_list[page_idx++].p; + + if (!page) + break; + +- buf_addr = le32_to_cpu(desc[i].buf0); + dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, + DMA_BIDIRECTIONAL); + __free_page(page); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -76,6 +76,11 @@ struct mtk_wed_wo_rx_stats { + __le32 rx_drop_cnt; + }; + ++struct mtk_wed_buf { ++ void *p; ++ dma_addr_t phy_addr; ++}; ++ + struct mtk_wed_device { + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + const struct mtk_wed_ops *ops; +@@ -97,7 +102,7 @@ struct mtk_wed_device { + + struct { + int size; +- void **pages; ++ struct mtk_wed_buf *pages; + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; + } tx_buf_ring; diff --git a/target/linux/generic/backport-6.6/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch b/target/linux/generic/backport-6.6/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch new file mode 100644 index 0000000000..98d782b1d0 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch @@ -0,0 +1,88 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:09 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: move mem_region array out of + mtk_wed_mcu_load_firmware + +Remove mtk_wed_wo_memory_region boot structure in mtk_wed_wo. +This is a preliminary patch to introduce WED support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -16,14 +16,30 @@ + #include "mtk_wed_wo.h" + #include "mtk_wed.h" + ++static struct mtk_wed_wo_memory_region mem_region[] = { ++ [MTK_WED_WO_REGION_EMI] = { ++ .name = "wo-emi", ++ }, ++ [MTK_WED_WO_REGION_ILM] = { ++ .name = "wo-ilm", ++ }, ++ [MTK_WED_WO_REGION_DATA] = { ++ .name = "wo-data", ++ .shared = true, ++ }, ++ [MTK_WED_WO_REGION_BOOT] = { ++ .name = "wo-boot", ++ }, ++}; ++ + static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) + { +- return readl(wo->boot.addr + reg); ++ return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + } + + static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) + { +- writel(val, wo->boot.addr + reg); ++ writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + } + + static struct sk_buff * +@@ -294,18 +310,6 @@ next: + static int + mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) + { +- static struct mtk_wed_wo_memory_region mem_region[] = { +- [MTK_WED_WO_REGION_EMI] = { +- .name = "wo-emi", +- }, +- [MTK_WED_WO_REGION_ILM] = { +- .name = "wo-ilm", +- }, +- [MTK_WED_WO_REGION_DATA] = { +- .name = "wo-data", +- .shared = true, +- }, +- }; + const struct mtk_wed_fw_trailer *trailer; + const struct firmware *fw; + const char *fw_name; +@@ -319,11 +323,6 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + return ret; + } + +- wo->boot.name = "wo-boot"; +- ret = mtk_wed_get_memory_region(wo, &wo->boot); +- if (ret) +- return ret; +- + /* set dummy cr */ + wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, + wo->hw->index + 1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -228,7 +228,6 @@ struct mtk_wed_wo_queue { + + struct mtk_wed_wo { + struct mtk_wed_hw *hw; +- struct mtk_wed_wo_memory_region boot; + + struct mtk_wed_wo_queue q_tx; + struct mtk_wed_wo_queue q_rx; diff --git a/target/linux/generic/backport-6.6/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch b/target/linux/generic/backport-6.6/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch new file mode 100644 index 0000000000..48b0d02049 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch @@ -0,0 +1,71 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:10 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: make memory region optional + +Make mtk_wed_wo_memory_region optionals. +This is a preliminary patch to introduce Wireless Ethernet Dispatcher +support for MT7988 SoC since MT7988 WED fw image will have a different +layout. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -234,19 +234,13 @@ int mtk_wed_mcu_msg_update(struct mtk_we + } + + static int +-mtk_wed_get_memory_region(struct mtk_wed_wo *wo, ++mtk_wed_get_memory_region(struct mtk_wed_hw *hw, int index, + struct mtk_wed_wo_memory_region *region) + { + struct reserved_mem *rmem; + struct device_node *np; +- int index; + +- index = of_property_match_string(wo->hw->node, "memory-region-names", +- region->name); +- if (index < 0) +- return index; +- +- np = of_parse_phandle(wo->hw->node, "memory-region", index); ++ np = of_parse_phandle(hw->node, "memory-region", index); + if (!np) + return -ENODEV; + +@@ -258,7 +252,7 @@ mtk_wed_get_memory_region(struct mtk_wed + + region->phy_addr = rmem->base; + region->size = rmem->size; +- region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); ++ region->addr = devm_ioremap(hw->dev, region->phy_addr, region->size); + + return !region->addr ? -EINVAL : 0; + } +@@ -271,6 +265,9 @@ mtk_wed_mcu_run_firmware(struct mtk_wed_ + const struct mtk_wed_fw_trailer *trailer; + const struct mtk_wed_fw_region *fw_region; + ++ if (!region->phy_addr || !region->size) ++ return 0; ++ + trailer_ptr = fw->data + fw->size - sizeof(*trailer); + trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; + region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); +@@ -318,7 +315,13 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +- ret = mtk_wed_get_memory_region(wo, &mem_region[i]); ++ int index = of_property_match_string(wo->hw->node, ++ "memory-region-names", ++ mem_region[i].name); ++ if (index < 0) ++ continue; ++ ++ ret = mtk_wed_get_memory_region(wo->hw, index, &mem_region[i]); + if (ret) + return ret; + } diff --git a/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch b/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch new file mode 100644 index 0000000000..c43114fb5b --- /dev/null +++ b/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch @@ -0,0 +1,217 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:12 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add mtk_wed_soc_data structure + +Introduce mtk_wed_soc_data utility structure to contain per-SoC +definitions. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -48,6 +48,26 @@ struct mtk_wed_flow_block_priv { + struct net_device *dev; + }; + ++static const struct mtk_wed_soc_data mt7622_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x088, ++ .wpdma_rx_ring0 = 0x770, ++ .reset_idx_tx_mask = GENMASK(3, 0), ++ .reset_idx_rx_mask = GENMASK(17, 16), ++ }, ++ .wdma_desc_size = sizeof(struct mtk_wdma_desc), ++}; ++ ++static const struct mtk_wed_soc_data mt7986_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x0c8, ++ .wpdma_rx_ring0 = 0x770, ++ .reset_idx_tx_mask = GENMASK(1, 0), ++ .reset_idx_rx_mask = GENMASK(7, 6), ++ }, ++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), ++}; ++ + static void + wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) + { +@@ -746,7 +766,7 @@ mtk_wed_set_wpdma(struct mtk_wed_device + return; + + wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); +- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); ++ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); + } + + static void +@@ -940,22 +960,10 @@ mtk_wed_hw_init(struct mtk_wed_device *d + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + + if (mtk_wed_is_v1(dev->hw)) { +- wed_w32(dev, MTK_WED_TX_BM_TKID, +- FIELD_PREP(MTK_WED_TX_BM_TKID_START, +- dev->wlan.token_start) | +- FIELD_PREP(MTK_WED_TX_BM_TKID_END, +- dev->wlan.token_start + +- dev->wlan.nbuf - 1)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | + MTK_WED_TX_BM_DYN_THR_HI); + } else { +- wed_w32(dev, MTK_WED_TX_BM_TKID_V2, +- FIELD_PREP(MTK_WED_TX_BM_TKID_START, +- dev->wlan.token_start) | +- FIELD_PREP(MTK_WED_TX_BM_TKID_END, +- dev->wlan.token_start + +- dev->wlan.nbuf - 1)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | + MTK_WED_TX_BM_DYN_THR_HI_V2); +@@ -970,6 +978,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d + MTK_WED_TX_TKID_DYN_THR_HI); + } + ++ wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid, ++ FIELD_PREP(MTK_WED_TX_BM_TKID_START, dev->wlan.token_start) | ++ FIELD_PREP(MTK_WED_TX_BM_TKID_END, ++ dev->wlan.token_start + dev->wlan.nbuf - 1)); ++ + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + + if (mtk_wed_is_v1(dev->hw)) { +@@ -1104,13 +1117,8 @@ mtk_wed_rx_reset(struct mtk_wed_device * + if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); + } else { +- struct mtk_eth *eth = dev->hw->eth; +- +- if (mtk_is_netsys_v2_or_greater(eth)) +- wed_set(dev, MTK_WED_RESET_IDX, +- MTK_WED_RESET_IDX_RX_V2); +- else +- wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX); ++ wed_set(dev, MTK_WED_RESET_IDX, ++ dev->hw->soc->regmap.reset_idx_rx_mask); + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +@@ -1163,7 +1171,8 @@ mtk_wed_reset_dma(struct mtk_wed_device + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); + } else { +- wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX); ++ wed_w32(dev, MTK_WED_RESET_IDX, ++ dev->hw->soc->regmap.reset_idx_tx_mask); + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +@@ -1255,7 +1264,6 @@ static int + mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, + bool reset) + { +- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; + + if (idx >= ARRAY_SIZE(dev->rx_wdma)) +@@ -1263,7 +1271,7 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we + + wdma = &dev->rx_wdma[idx]; + if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, +- desc_size, true)) ++ dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1284,7 +1292,6 @@ static int + mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, + bool reset) + { +- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; + + if (idx >= ARRAY_SIZE(dev->tx_wdma)) +@@ -1292,7 +1299,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + + wdma = &dev->tx_wdma[idx]; + if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, +- desc_size, true)) ++ dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1931,7 +1938,12 @@ void mtk_wed_add_hw(struct device_node * + hw->irq = irq; + hw->version = eth->soc->version; + +- if (mtk_wed_is_v1(hw)) { ++ switch (hw->version) { ++ case 2: ++ hw->soc = &mt7986_data; ++ break; ++ default: ++ case 1: + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, + "mediatek,pcie-mirror"); + hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, +@@ -1945,6 +1957,8 @@ void mtk_wed_add_hw(struct device_node * + regmap_write(hw->mirror, 0, 0); + regmap_write(hw->mirror, 4, 0); + } ++ hw->soc = &mt7622_data; ++ break; + } + + mtk_wed_hw_add_debugfs(hw); +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -12,7 +12,18 @@ + struct mtk_eth; + struct mtk_wed_wo; + ++struct mtk_wed_soc_data { ++ struct { ++ u32 tx_bm_tkid; ++ u32 wpdma_rx_ring0; ++ u32 reset_idx_tx_mask; ++ u32 reset_idx_rx_mask; ++ } regmap; ++ u32 wdma_desc_size; ++}; ++ + struct mtk_wed_hw { ++ const struct mtk_wed_soc_data *soc; + struct device_node *node; + struct mtk_eth *eth; + struct regmap *regs; +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -100,8 +100,6 @@ struct mtk_wdma_desc { + + #define MTK_WED_TX_BM_BASE 0x084 + +-#define MTK_WED_TX_BM_TKID 0x088 +-#define MTK_WED_TX_BM_TKID_V2 0x0c8 + #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) + #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) + +@@ -160,9 +158,6 @@ struct mtk_wdma_desc { + #define MTK_WED_GLO_CFG_RX_2B_OFFSET BIT(31) + + #define MTK_WED_RESET_IDX 0x20c +-#define MTK_WED_RESET_IDX_TX GENMASK(3, 0) +-#define MTK_WED_RESET_IDX_RX GENMASK(17, 16) +-#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6) + #define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30) + + #define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) +@@ -286,7 +281,6 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) + + #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c +-#define MTK_WED_WPDMA_RX_RING 0x770 + + #define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) + #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) diff --git a/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch b/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch new file mode 100644 index 0000000000..f874899c5b --- /dev/null +++ b/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch @@ -0,0 +1,1280 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:13 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce WED support for MT7988 + +Similar to MT7986 and MT7622, enable Wireless Ethernet Ditpatcher for +MT7988 in order to offload traffic forwarded from LAN/WLAN to WLAN/LAN + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -195,6 +195,7 @@ static const struct mtk_reg_map mt7988_r + .wdma_base = { + [0] = 0x4800, + [1] = 0x4c00, ++ [2] = 0x5000, + }, + .pse_iq_sta = 0x0180, + .pse_oq_sta = 0x01a0, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1132,7 +1132,7 @@ struct mtk_reg_map { + u32 gdm1_cnt; + u32 gdma_to_ppe; + u32 ppe_base; +- u32 wdma_base[2]; ++ u32 wdma_base[3]; + u32 pse_iq_sta; + u32 pse_oq_sta; + }; +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -201,6 +201,9 @@ mtk_flow_set_output_device(struct mtk_et + case 1: + pse_port = PSE_WDMA1_PORT; + break; ++ case 2: ++ pse_port = PSE_WDMA2_PORT; ++ break; + default: + return -EINVAL; + } +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -16,17 +16,19 @@ + #include + #include + #include "mtk_eth_soc.h" +-#include "mtk_wed_regs.h" + #include "mtk_wed.h" + #include "mtk_ppe.h" + #include "mtk_wed_wo.h" + + #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) + +-#define MTK_WED_PKT_SIZE 1900 ++#define MTK_WED_PKT_SIZE 1920 + #define MTK_WED_BUF_SIZE 2048 ++#define MTK_WED_PAGE_BUF_SIZE 128 + #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) ++#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) + #define MTK_WED_RX_RING_SIZE 1536 ++#define MTK_WED_RX_PG_BM_CNT 8192 + + #define MTK_WED_TX_RING_SIZE 2048 + #define MTK_WED_WDMA_RING_SIZE 1024 +@@ -40,7 +42,10 @@ + #define MTK_WED_RRO_QUE_CNT 8192 + #define MTK_WED_MIOD_ENTRY_CNT 128 + +-static struct mtk_wed_hw *hw_list[2]; ++#define MTK_WED_TX_BM_DMA_SIZE 65536 ++#define MTK_WED_TX_BM_PKT_CNT 32768 ++ ++static struct mtk_wed_hw *hw_list[3]; + static DEFINE_MUTEX(hw_lock); + + struct mtk_wed_flow_block_priv { +@@ -55,6 +60,7 @@ static const struct mtk_wed_soc_data mt7 + .reset_idx_tx_mask = GENMASK(3, 0), + .reset_idx_rx_mask = GENMASK(17, 16), + }, ++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc), + .wdma_desc_size = sizeof(struct mtk_wdma_desc), + }; + +@@ -65,6 +71,18 @@ static const struct mtk_wed_soc_data mt7 + .reset_idx_tx_mask = GENMASK(1, 0), + .reset_idx_rx_mask = GENMASK(7, 6), + }, ++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc), ++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), ++}; ++ ++static const struct mtk_wed_soc_data mt7988_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x0c8, ++ .wpdma_rx_ring0 = 0x7d0, ++ .reset_idx_tx_mask = GENMASK(1, 0), ++ .reset_idx_rx_mask = GENMASK(7, 6), ++ }, ++ .tx_ring_desc_size = sizeof(struct mtk_wed_bm_desc), + .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), + }; + +@@ -319,33 +337,38 @@ out: + static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { ++ u32 desc_size = dev->hw->soc->tx_ring_desc_size; ++ int i, page_idx = 0, n_pages, ring_size; ++ int token = dev->wlan.token_start; + struct mtk_wed_buf *page_list; +- struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +- int token = dev->wlan.token_start; +- int ring_size; +- int n_pages; +- int i, page_idx; ++ void *desc_ptr; + +- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); +- n_pages = ring_size / MTK_WED_BUF_PER_PAGE; ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ dev->tx_buf_ring.size = ring_size; ++ } else { ++ dev->tx_buf_ring.size = MTK_WED_TX_BM_DMA_SIZE; ++ ring_size = MTK_WED_TX_BM_PKT_CNT; ++ } ++ n_pages = dev->tx_buf_ring.size / MTK_WED_BUF_PER_PAGE; + + page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); + if (!page_list) + return -ENOMEM; + +- dev->tx_buf_ring.size = ring_size; + dev->tx_buf_ring.pages = page_list; + +- desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), +- &desc_phys, GFP_KERNEL); +- if (!desc) ++ desc_ptr = dma_alloc_coherent(dev->hw->dev, ++ dev->tx_buf_ring.size * desc_size, ++ &desc_phys, GFP_KERNEL); ++ if (!desc_ptr) + return -ENOMEM; + +- dev->tx_buf_ring.desc = desc; ++ dev->tx_buf_ring.desc = desc_ptr; + dev->tx_buf_ring.desc_phys = desc_phys; + +- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { ++ for (i = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { + dma_addr_t page_phys, buf_phys; + struct page *page; + void *buf; +@@ -371,28 +394,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + buf_phys = page_phys; + + for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { +- u32 txd_size; +- u32 ctrl; +- +- txd_size = dev->wlan.init_buf(buf, buf_phys, token++); ++ struct mtk_wdma_desc *desc = desc_ptr; + + desc->buf0 = cpu_to_le32(buf_phys); +- desc->buf1 = cpu_to_le32(buf_phys + txd_size); ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ u32 txd_size, ctrl; + +- if (mtk_wed_is_v1(dev->hw)) +- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | +- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, +- MTK_WED_BUF_SIZE - txd_size) | +- MTK_WDMA_DESC_CTRL_LAST_SEG1; +- else +- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | +- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2, +- MTK_WED_BUF_SIZE - txd_size) | +- MTK_WDMA_DESC_CTRL_LAST_SEG0; +- desc->ctrl = cpu_to_le32(ctrl); +- desc->info = 0; +- desc++; ++ txd_size = dev->wlan.init_buf(buf, buf_phys, ++ token++); ++ desc->buf1 = cpu_to_le32(buf_phys + txd_size); ++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size); ++ if (mtk_wed_is_v1(dev->hw)) ++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG1 | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, ++ MTK_WED_BUF_SIZE - txd_size); ++ else ++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2, ++ MTK_WED_BUF_SIZE - txd_size); ++ desc->ctrl = cpu_to_le32(ctrl); ++ desc->info = 0; ++ } else { ++ desc->ctrl = cpu_to_le32(token << 16); ++ } + ++ desc_ptr += desc_size; + buf += MTK_WED_BUF_SIZE; + buf_phys += MTK_WED_BUF_SIZE; + } +@@ -408,31 +434,31 @@ static void + mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) + { + struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages; +- struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; +- int page_idx; +- int i; ++ struct mtk_wed_hw *hw = dev->hw; ++ int i, page_idx = 0; + + if (!page_list) + return; + +- if (!desc) ++ if (!dev->tx_buf_ring.desc) + goto free_pagelist; + +- for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; +- i += MTK_WED_BUF_PER_PAGE) { +- dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ for (i = 0; i < dev->tx_buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { ++ dma_addr_t page_phy = page_list[page_idx].phy_addr; + void *page = page_list[page_idx++].p; + + if (!page) + break; + +- dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, ++ dma_unmap_page(dev->hw->dev, page_phy, PAGE_SIZE, + DMA_BIDIRECTIONAL); + __free_page(page); + } + +- dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), +- desc, dev->tx_buf_ring.desc_phys); ++ dma_free_coherent(dev->hw->dev, ++ dev->tx_buf_ring.size * hw->soc->tx_ring_desc_size, ++ dev->tx_buf_ring.desc, ++ dev->tx_buf_ring.desc_phys); + + free_pagelist: + kfree(page_list); +@@ -517,13 +543,23 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + { + u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (mtk_wed_is_v1(dev->hw)) ++ switch (dev->hw->version) { ++ case 1: + mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; +- else ++ break; ++ case 2: + mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | + MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH | + MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | + MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR; ++ break; ++ case 3: ++ mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ break; ++ default: ++ break; ++ } + + if (!dev->hw->num_flows) + mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; +@@ -535,6 +571,9 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + static void + mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable) + { ++ if (!mtk_wed_is_v2(dev->hw)) ++ return; ++ + if (enable) { + wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR); + wed_w32(dev, MTK_WED_TXP_DW1, +@@ -609,6 +648,14 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WED_WPDMA_RX_D_RX_DRV_EN); + wed_clr(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw) && ++ mtk_wed_get_rx_capa(dev)) { ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, ++ MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, ++ MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ } + } + + mtk_wed_set_512_support(dev, false); +@@ -651,6 +698,14 @@ mtk_wed_deinit(struct mtk_wed_device *de + MTK_WED_CTRL_RX_ROUTE_QM_EN | + MTK_WED_CTRL_WED_RX_BM_EN | + MTK_WED_CTRL_RX_RRO_QM_EN); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_AMSDU); ++ wed_clr(dev, MTK_WED_PCIE_INT_CTRL, ++ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA | ++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER); ++ } + } + + static void +@@ -700,21 +755,37 @@ mtk_wed_detach(struct mtk_wed_device *de + mutex_unlock(&hw_lock); + } + +-#define PCIE_BASE_ADDR0 0x11280000 + static void + mtk_wed_bus_init(struct mtk_wed_device *dev) + { + switch (dev->wlan.bus_type) { + case MTK_WED_BUS_PCIE: { + struct device_node *np = dev->hw->eth->dev->of_node; +- struct regmap *regs; + +- regs = syscon_regmap_lookup_by_phandle(np, +- "mediatek,wed-pcie"); +- if (IS_ERR(regs)) +- break; ++ if (mtk_wed_is_v2(dev->hw)) { ++ struct regmap *regs; ++ ++ regs = syscon_regmap_lookup_by_phandle(np, ++ "mediatek,wed-pcie"); ++ if (IS_ERR(regs)) ++ break; + +- regmap_update_bits(regs, 0, BIT(0), BIT(0)); ++ regmap_update_bits(regs, 0, BIT(0), BIT(0)); ++ } ++ ++ if (dev->wlan.msi) { ++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, ++ dev->hw->pcie_base | 0xc08); ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, ++ dev->hw->pcie_base | 0xc04); ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8)); ++ } else { ++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, ++ dev->hw->pcie_base | 0x180); ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, ++ dev->hw->pcie_base | 0x184); ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24)); ++ } + + wed_w32(dev, MTK_WED_PCIE_INT_CTRL, + FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2)); +@@ -722,19 +793,9 @@ mtk_wed_bus_init(struct mtk_wed_device * + /* pcie interrupt control: pola/source selection */ + wed_set(dev, MTK_WED_PCIE_INT_CTRL, + MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA | +- FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1)); +- wed_r32(dev, MTK_WED_PCIE_INT_CTRL); +- +- wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180); +- wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184); +- +- /* pcie interrupt status trigger register */ +- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24)); +- wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER); +- +- /* pola setting */ +- wed_set(dev, MTK_WED_PCIE_INT_CTRL, +- MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA); ++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER | ++ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, ++ dev->hw->index)); + break; + } + case MTK_WED_BUS_AXI: +@@ -772,18 +833,19 @@ mtk_wed_set_wpdma(struct mtk_wed_device + static void + mtk_wed_hw_init_early(struct mtk_wed_device *dev) + { +- u32 mask, set; ++ u32 set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2); ++ u32 mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE; + + mtk_wed_deinit(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); + mtk_wed_set_wpdma(dev); + +- mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE | +- MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | +- MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; +- set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) | +- MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | +- MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ mask |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | ++ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; ++ set |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | ++ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ } + wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); + + if (mtk_wed_is_v1(dev->hw)) { +@@ -931,11 +993,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_ + } + + /* configure RX_ROUTE_QM */ +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); +- wed_set(dev, MTK_WED_RTQM_GLO_CFG, +- FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ if (mtk_wed_is_v2(dev->hw)) { ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, ++ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, ++ 0x3 + dev->hw->index)); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ } else { ++ wed_set(dev, MTK_WED_RTQM_ENQ_CFG0, ++ FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT, ++ 0x3 + dev->hw->index)); ++ } + /* enable RX_ROUTE_QM */ + wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); + } +@@ -948,22 +1017,30 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + dev->init_done = true; + mtk_wed_set_ext_int(dev, false); +- wed_w32(dev, MTK_WED_TX_BM_CTRL, +- MTK_WED_TX_BM_CTRL_PAUSE | +- FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, +- dev->tx_buf_ring.size / 128) | +- FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, +- MTK_WED_TX_RING_SIZE / 256)); + + wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); +- + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + + if (mtk_wed_is_v1(dev->hw)) { ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | + MTK_WED_TX_BM_DYN_THR_HI); +- } else { ++ } else if (mtk_wed_is_v2(dev->hw)) { ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); ++ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, ++ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | ++ MTK_WED_TX_TKID_DYN_THR_HI); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | + MTK_WED_TX_BM_DYN_THR_HI_V2); +@@ -973,9 +1050,6 @@ mtk_wed_hw_init(struct mtk_wed_device *d + dev->tx_buf_ring.size / 128) | + FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, + dev->tx_buf_ring.size / 128)); +- wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, +- FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | +- MTK_WED_TX_TKID_DYN_THR_HI); + } + + wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid, +@@ -985,26 +1059,62 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* switch to new bm architecture */ ++ wed_clr(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_LEGACY_EN); ++ ++ wed_w32(dev, MTK_WED_TX_TKID_CTRL, ++ MTK_WED_TX_TKID_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3, ++ dev->wlan.nbuf / 128) | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3, ++ dev->wlan.nbuf / 128)); ++ /* return SKBID + SDP back to bm */ ++ wed_set(dev, MTK_WED_TX_TKID_CTRL, ++ MTK_WED_TX_TKID_CTRL_FREE_FORMAT); ++ ++ wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, ++ MTK_WED_TX_BM_PKT_CNT | ++ MTK_WED_TX_BM_INIT_SW_TAIL_IDX); ++ } ++ + if (mtk_wed_is_v1(dev->hw)) { + wed_set(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); +- } else { +- wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); +- if (mtk_wed_get_rx_capa(dev)) { +- /* rx hw init */ +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, +- MTK_WED_WPDMA_RX_D_RST_CRX_IDX | +- MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); +- +- mtk_wed_rx_buffer_hw_init(dev); +- mtk_wed_rro_hw_init(dev); +- mtk_wed_route_qm_hw_init(dev); +- } ++ } else if (mtk_wed_get_rx_capa(dev)) { ++ /* rx hw init */ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ ++ /* reset prefetch index of ring */ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ ++ /* reset prefetch FIFO of ring */ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR | ++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0); ++ ++ mtk_wed_rx_buffer_hw_init(dev); ++ mtk_wed_rro_hw_init(dev); ++ mtk_wed_route_qm_hw_init(dev); + } + + wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); ++ if (!mtk_wed_is_v1(dev->hw)) ++ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); + } + + static void +@@ -1302,6 +1412,24 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ struct mtk_wdma_desc *desc = wdma->desc; ++ int i; ++ ++ for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) { ++ desc->buf0 = 0; ++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc->buf1 = 0; ++ desc->info = cpu_to_le32(MTK_WDMA_TXD0_DESC_INFO_DMA_DONE); ++ desc++; ++ desc->buf0 = 0; ++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc->buf1 = 0; ++ desc->info = cpu_to_le32(MTK_WDMA_TXD1_DESC_INFO_DMA_DONE); ++ desc++; ++ } ++ } ++ + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, + wdma->desc_phys); + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, +@@ -1367,6 +1495,9 @@ mtk_wed_configure_irq(struct mtk_wed_dev + + wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN); ++ + /* initail tx interrupt trigger */ + wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, + MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | +@@ -1419,33 +1550,60 @@ mtk_wed_dma_enable(struct mtk_wed_device + { + int i; + +- wed_set(dev, MTK_WED_WPDMA_INT_CTRL, MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL, ++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wdma_set(dev, MTK_WDMA_GLO_CFG, ++ MTK_WDMA_GLO_CFG_TX_DMA_EN | ++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | ++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); ++ wed_set(dev, MTK_WED_WPDMA_CTRL, MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ } else { ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR); ++ wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); ++ } + + wed_set(dev, MTK_WED_GLO_CFG, + MTK_WED_GLO_CFG_TX_DMA_EN | + MTK_WED_GLO_CFG_RX_DMA_EN); +- wed_set(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ + wed_set(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); + +- wdma_set(dev, MTK_WDMA_GLO_CFG, +- MTK_WDMA_GLO_CFG_TX_DMA_EN | +- MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | +- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); +- + if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + return; + } + +- wed_set(dev, MTK_WED_WPDMA_CTRL, +- MTK_WED_WPDMA_CTRL_SDL1_FIXED); + wed_set(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) | ++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8)); ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_DDONE2_EN); ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN); ++ ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); ++ ++ wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ } ++ + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | + MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); +@@ -1457,11 +1615,22 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | + MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); + ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN); + wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, + MTK_WED_WPDMA_RX_D_RX_DRV_EN | + FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, +- 0x2)); ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, 0x2)); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_EN | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8)); ++ ++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN); ++ wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ } + + for (i = 0; i < MTK_WED_RX_QUEUES; i++) + mtk_wed_check_wfdma_rx_fill(dev, i); +@@ -1501,6 +1670,12 @@ mtk_wed_start(struct mtk_wed_device *dev + wed_r32(dev, MTK_WED_EXT_INT_MASK1); + wed_r32(dev, MTK_WED_EXT_INT_MASK2); + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_w32(dev, MTK_WED_EXT_INT_MASK3, ++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); ++ wed_r32(dev, MTK_WED_EXT_INT_MASK3); ++ } ++ + if (mtk_wed_rro_cfg(dev)) + return; + } +@@ -1552,6 +1727,7 @@ mtk_wed_attach(struct mtk_wed_device *de + dev->irq = hw->irq; + dev->wdma_idx = hw->index; + dev->version = hw->version; ++ dev->hw->pcie_base = mtk_wed_get_pcie_base(dev); + + if (hw->eth->dma_dev == hw->eth->dev && + of_dma_is_coherent(hw->eth->dev->of_node)) +@@ -1619,6 +1795,23 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev + ring->reg_base = MTK_WED_RING_TX(idx); + ring->wpdma = regs; + ++ if (mtk_wed_is_v3_or_greater(dev->hw) && idx == 1) { ++ /* reset prefetch index */ ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR | ++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR); ++ ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR | ++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR); ++ ++ /* reset prefetch FIFO */ ++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, ++ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR | ++ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR); ++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0); ++ } ++ + /* WED -> WPDMA */ + wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); + wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_TX_RING_SIZE); +@@ -1693,15 +1886,13 @@ mtk_wed_rx_ring_setup(struct mtk_wed_dev + static u32 + mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) + { +- u32 val, ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ u32 val, ext_mask; + +- if (mtk_wed_is_v1(dev->hw)) +- ext_mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ ext_mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; + else +- ext_mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +- MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH | +- MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | +- MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR; ++ ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + + val = wed_r32(dev, MTK_WED_EXT_INT_STATUS); + wed_w32(dev, MTK_WED_EXT_INT_STATUS, val); +@@ -1942,6 +2133,9 @@ void mtk_wed_add_hw(struct device_node * + case 2: + hw->soc = &mt7986_data; + break; ++ case 3: ++ hw->soc = &mt7988_data; ++ break; + default: + case 1: + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -9,6 +9,8 @@ + #include + #include + ++#include "mtk_wed_regs.h" ++ + struct mtk_eth; + struct mtk_wed_wo; + +@@ -19,6 +21,7 @@ struct mtk_wed_soc_data { + u32 reset_idx_tx_mask; + u32 reset_idx_rx_mask; + } regmap; ++ u32 tx_ring_desc_size; + u32 wdma_desc_size; + }; + +@@ -35,6 +38,7 @@ struct mtk_wed_hw { + struct dentry *debugfs_dir; + struct mtk_wed_device *wed_dev; + struct mtk_wed_wo *wed_wo; ++ u32 pcie_base; + u32 debugfs_reg; + u32 num_flows; + u8 version; +@@ -61,6 +65,16 @@ static inline bool mtk_wed_is_v2(struct + return hw->version == 2; + } + ++static inline bool mtk_wed_is_v3(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 3; ++} ++ ++static inline bool mtk_wed_is_v3_or_greater(struct mtk_wed_hw *hw) ++{ ++ return hw->version > 2; ++} ++ + static inline void + wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) + { +@@ -143,6 +157,21 @@ wpdma_txfree_w32(struct mtk_wed_device * + writel(val, dev->txfree_ring.wpdma + reg); + } + ++static inline u32 mtk_wed_get_pcie_base(struct mtk_wed_device *dev) ++{ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return MTK_WED_PCIE_BASE; ++ ++ switch (dev->hw->index) { ++ case 1: ++ return MTK_WED_PCIE_BASE1; ++ case 2: ++ return MTK_WED_PCIE_BASE2; ++ default: ++ return MTK_WED_PCIE_BASE0; ++ } ++} ++ + void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, + void __iomem *wdma, phys_addr_t wdma_phy, + int index); +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -331,10 +331,22 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + wo->hw->index + 1); + + /* load firmware */ +- if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed")) +- fw_name = MT7981_FIRMWARE_WO; +- else +- fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; ++ switch (wo->hw->version) { ++ case 2: ++ if (of_device_is_compatible(wo->hw->node, ++ "mediatek,mt7981-wed")) ++ fw_name = MT7981_FIRMWARE_WO; ++ else ++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 ++ : MT7986_FIRMWARE_WO0; ++ break; ++ case 3: ++ fw_name = wo->hw->index ? MT7988_FIRMWARE_WO1 ++ : MT7988_FIRMWARE_WO0; ++ break; ++ default: ++ return -EINVAL; ++ } + + ret = request_firmware(&fw, fw_name, wo->hw->dev); + if (ret) +@@ -355,15 +367,16 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + } + + /* set the start address */ +- boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR +- : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; ++ if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index) ++ boot_cr = MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR; ++ else ++ boot_cr = MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; + wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); + /* wo firmware reset */ + wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); + +- val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); +- val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK +- : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; ++ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR) | ++ MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; + wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); + out: + release_firmware(fw); +@@ -398,3 +411,5 @@ int mtk_wed_mcu_init(struct mtk_wed_wo * + MODULE_FIRMWARE(MT7981_FIRMWARE_WO); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ++MODULE_FIRMWARE(MT7988_FIRMWARE_WO0); ++MODULE_FIRMWARE(MT7988_FIRMWARE_WO1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -13,6 +13,9 @@ + #define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30) + #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31) + ++#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE BIT(29) ++#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE BIT(31) ++ + struct mtk_wdma_desc { + __le32 buf0; + __le32 ctrl; +@@ -37,6 +40,7 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) + #define MTK_WED_RESET_RX_RRO_QM BIT(20) + #define MTK_WED_RESET_RX_ROUTE_QM BIT(21) ++#define MTK_WED_RESET_TX_AMSDU BIT(22) + #define MTK_WED_RESET_WED BIT(31) + + #define MTK_WED_CTRL 0x00c +@@ -44,6 +48,9 @@ struct mtk_wdma_desc { + #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1) + #define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2) + #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3) ++#define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5) ++#define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6) ++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY BIT(7) + #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8) + #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) + #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) +@@ -54,9 +61,14 @@ struct mtk_wdma_desc { + #define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) + #define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) + #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) ++#define MTK_WED_CTRL_TX_TKID_ALI_EN BIT(20) ++#define MTK_WED_CTRL_TX_TKID_ALI_BUSY BIT(21) ++#define MTK_WED_CTRL_TX_AMSDU_EN BIT(22) ++#define MTK_WED_CTRL_TX_AMSDU_BUSY BIT(23) + #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) + #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) + #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) ++#define MTK_WED_CTRL_FLD_MIB_RD_CLR BIT(28) + + #define MTK_WED_EXT_INT_STATUS 0x020 + #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0) +@@ -89,6 +101,7 @@ struct mtk_wdma_desc { + #define MTK_WED_EXT_INT_MASK 0x028 + #define MTK_WED_EXT_INT_MASK1 0x02c + #define MTK_WED_EXT_INT_MASK2 0x030 ++#define MTK_WED_EXT_INT_MASK3 0x034 + + #define MTK_WED_STATUS 0x060 + #define MTK_WED_STATUS_TX GENMASK(15, 8) +@@ -96,9 +109,14 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_BM_CTRL 0x080 + #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) + #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) ++#define MTK_WED_TX_BM_CTRL_LEGACY_EN BIT(26) ++#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT BIT(27) + #define MTK_WED_TX_BM_CTRL_PAUSE BIT(28) + + #define MTK_WED_TX_BM_BASE 0x084 ++#define MTK_WED_TX_BM_INIT_PTR 0x088 ++#define MTK_WED_TX_BM_SW_TAIL_IDX GENMASK(16, 0) ++#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX BIT(16) + + #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) + #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) +@@ -122,6 +140,9 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16) + #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28) + ++#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0) ++#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16) ++ + #define MTK_WED_TX_TKID_DYN_THR 0x0e0 + #define MTK_WED_TX_TKID_DYN_THR_LO GENMASK(6, 0) + #define MTK_WED_TX_TKID_DYN_THR_HI GENMASK(22, 16) +@@ -199,12 +220,15 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC BIT(5) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC BIT(6) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC BIT(7) +-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(18, 16) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(15, 12) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4 BIT(18) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT BIT(19) +-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK BIT(20) + #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR BIT(21) + #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP BIT(24) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST BIT(25) + #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV BIT(28) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK BIT(30) + + #define MTK_WED_WPDMA_RESET_IDX 0x50c + #define MTK_WED_WPDMA_RESET_IDX_TX GENMASK(3, 0) +@@ -250,9 +274,10 @@ struct mtk_wdma_desc { + #define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16) + + #define MTK_WED_PCIE_INT_CTRL 0x57c +-#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20) +-#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16) + #define MTK_WED_PCIE_INT_CTRL_POLL_EN GENMASK(13, 12) ++#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16) ++#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20) ++#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER BIT(21) + + #define MTK_WED_WPDMA_CFG_BASE 0x580 + #define MTK_WED_WPDMA_CFG_INT_MASK 0x584 +@@ -286,6 +311,20 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) + #define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c + ++#define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4 ++#define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8) ++#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16) ++ ++#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX 0x7b8 ++#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR BIT(15) ++ ++#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX 0x7bc ++ ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG 0x7c0 ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR BIT(16) ++ + #define MTK_WED_WDMA_RING_TX 0x800 + + #define MTK_WED_WDMA_TX_MIB 0x810 +@@ -293,6 +332,18 @@ struct mtk_wdma_desc { + #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) + #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) + ++#define MTK_WED_WDMA_RX_PREF_CFG 0x950 ++#define MTK_WED_WDMA_RX_PREF_EN BIT(0) ++#define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8) ++#define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16) ++#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24) ++#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25) ++#define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26) ++ ++#define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C ++#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0) ++#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR BIT(16) ++ + #define MTK_WED_WDMA_GLO_CFG 0xa04 + #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) + #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) +@@ -325,6 +376,7 @@ struct mtk_wdma_desc { + #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16) + + #define MTK_WED_WDMA_INT_CTRL 0xa2c ++#define MTK_WED_WDMA_INT_POLL_PRD GENMASK(7, 0) + #define MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL GENMASK(17, 16) + + #define MTK_WED_WDMA_CFG_BASE 0xaa0 +@@ -388,6 +440,18 @@ struct mtk_wdma_desc { + #define MTK_WDMA_INT_GRP1 0x250 + #define MTK_WDMA_INT_GRP2 0x254 + ++#define MTK_WDMA_PREF_TX_CFG 0x2d0 ++#define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0) ++ ++#define MTK_WDMA_PREF_RX_CFG 0x2dc ++#define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0) ++ ++#define MTK_WDMA_WRBK_TX_CFG 0x300 ++#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30) ++ ++#define MTK_WDMA_WRBK_RX_CFG 0x344 ++#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30) ++ + #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) + #define MTK_PCIE_MIRROR_MAP_EN BIT(0) + #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) +@@ -401,6 +465,30 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) + #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) + ++#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c ++#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28 ++#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n) (0xb2c + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS0_FDROP_CNT 0xb34 ++ ++#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT 0xb44 ++#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n) (0xb48 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT 0xb50 ++#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n) (0xb54 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS1_FDROP_CNT 0xb5c ++ ++#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT 0xb6c ++#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n) (0xb70 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT 0xb78 ++#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n) (0xb7c + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS2_FDROP_CNT 0xb84 ++ ++#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT 0xb94 ++#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n) (0xb98 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT 0xba0 ++#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n) (0xba4 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS3_FDROP_CNT 0xbac ++ + #define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) + #define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) + #define MTK_WED_RTQM_Q2N_MIB 0xb80 +@@ -409,6 +497,24 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q2B_MIB 0xb8c + #define MTK_WED_RTQM_PFDBK_MIB 0xb90 + ++#define MTK_WED_RTQM_ENQ_CFG0 0xbb8 ++#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT GENMASK(15, 12) ++ ++#define MTK_WED_RTQM_FDROP_MIB 0xb84 ++#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT 0xbbc ++#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT 0xbc0 ++#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT 0xbc4 ++#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT 0xbc8 ++#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT 0xbcc ++#define MTK_WED_RTQM_ENQ_ERR_CNT 0xbd0 ++ ++#define MTK_WED_RTQM_DEQ_DMAD_CNT 0xbd8 ++#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT 0xbdc ++#define MTK_WED_RTQM_DEQ_PKT_CNT 0xbe0 ++#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT 0xbe4 ++#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT 0xbe8 ++#define MTK_WED_RTQM_DEQ_ERR_CNT 0xbec ++ + #define MTK_WED_RROQM_GLO_CFG 0xc04 + #define MTK_WED_RROQM_RST_IDX 0xc08 + #define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) +@@ -458,7 +564,116 @@ struct mtk_wdma_desc { + #define MTK_WED_RX_BM_INTF 0xd9c + #define MTK_WED_RX_BM_ERR_STS 0xda8 + ++#define MTK_RRO_IND_CMD_SIGNATURE 0xe00 ++#define MTK_RRO_IND_CMD_DMA_IDX GENMASK(11, 0) ++#define MTK_RRO_IND_CMD_MAGIC_CNT GENMASK(30, 28) ++ ++#define MTK_WED_IND_CMD_RX_CTRL0 0xe04 ++#define MTK_WED_IND_CMD_PROC_IDX GENMASK(11, 0) ++#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT GENMASK(19, 16) ++#define MTK_WED_IND_CMD_MAGIC_CNT GENMASK(30, 28) ++ ++#define MTK_WED_IND_CMD_RX_CTRL1 0xe08 ++#define MTK_WED_IND_CMD_RX_CTRL2 0xe0c ++#define MTK_WED_IND_CMD_MAX_CNT GENMASK(11, 0) ++#define MTK_WED_IND_CMD_BASE_M GENMASK(19, 16) ++ ++#define MTK_WED_RRO_CFG0 0xe10 ++#define MTK_WED_RRO_CFG1 0xe14 ++#define MTK_WED_RRO_CFG1_MAX_WIN_SZ GENMASK(31, 29) ++#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M GENMASK(19, 16) ++#define MTK_WED_RRO_CFG1_PARTICL_SE_ID GENMASK(11, 0) ++ ++#define MTK_WED_ADDR_ELEM_CFG0 0xe18 ++#define MTK_WED_ADDR_ELEM_CFG1 0xe1c ++#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT GENMASK(19, 16) ++ ++#define MTK_WED_ADDR_ELEM_TBL_CFG 0xe20 ++#define MTK_WED_ADDR_ELEM_TBL_OFFSET GENMASK(6, 0) ++#define MTK_WED_ADDR_ELEM_TBL_RD_RDY BIT(28) ++#define MTK_WED_ADDR_ELEM_TBL_WR_RDY BIT(29) ++#define MTK_WED_ADDR_ELEM_TBL_RD BIT(30) ++#define MTK_WED_ADDR_ELEM_TBL_WR BIT(31) ++ ++#define MTK_WED_RADDR_ELEM_TBL_WDATA 0xe24 ++#define MTK_WED_RADDR_ELEM_TBL_RDATA 0xe28 ++ ++#define MTK_WED_PN_CHECK_CFG 0xe30 ++#define MTK_WED_PN_CHECK_SE_ID GENMASK(11, 0) ++#define MTK_WED_PN_CHECK_RD_RDY BIT(28) ++#define MTK_WED_PN_CHECK_WR_RDY BIT(29) ++#define MTK_WED_PN_CHECK_RD BIT(30) ++#define MTK_WED_PN_CHECK_WR BIT(31) ++ ++#define MTK_WED_PN_CHECK_WDATA_M 0xe38 ++#define MTK_WED_PN_CHECK_IS_FIRST BIT(17) ++ ++#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n) (0xe44 + (_n) * 0x8) ++ ++#define MTK_WED_RRO_MSDU_PG_RING2_CFG 0xe58 ++#define MTK_WED_RRO_MSDU_PG_DRV_CLR BIT(26) ++#define MTK_WED_RRO_MSDU_PG_DRV_EN BIT(31) ++ ++#define MTK_WED_RRO_MSDU_PG_CTRL0(_n) (0xe5c + (_n) * 0xc) ++#define MTK_WED_RRO_MSDU_PG_CTRL1(_n) (0xe60 + (_n) * 0xc) ++#define MTK_WED_RRO_MSDU_PG_CTRL2(_n) (0xe64 + (_n) * 0xc) ++ ++#define MTK_WED_RRO_RX_D_RX(_n) (0xe80 + (_n) * 0x10) ++ ++#define MTK_WED_RRO_RX_MAGIC_CNT BIT(13) ++ ++#define MTK_WED_RRO_RX_D_CFG(_n) (0xea0 + (_n) * 0x4) ++#define MTK_WED_RRO_RX_D_DRV_CLR BIT(26) ++#define MTK_WED_RRO_RX_D_DRV_EN BIT(31) ++ ++#define MTK_WED_RRO_PG_BM_RX_DMAM 0xeb0 ++#define MTK_WED_RRO_PG_BM_RX_SDL0 GENMASK(13, 0) ++ ++#define MTK_WED_RRO_PG_BM_BASE 0xeb4 ++#define MTK_WED_RRO_PG_BM_INIT_PTR 0xeb8 ++#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX GENMASK(15, 0) ++#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX BIT(16) ++ ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX 0xeec ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN BIT(0) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR BIT(1) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG GENMASK(6, 2) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN BIT(8) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR BIT(9) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG GENMASK(14, 10) ++ ++#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG 0xef4 ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN BIT(0) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR BIT(1) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG GENMASK(6, 2) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN BIT(8) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR BIT(9) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG GENMASK(14, 10) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN BIT(16) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18) ++ ++#define MTK_WED_RX_IND_CMD_CNT0 0xf20 ++#define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31) ++ ++#define MTK_WED_RX_IND_CMD_CNT(_n) (0xf20 + (_n) * 0x4) ++#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT GENMASK(15, 0) ++ ++#define MTK_WED_RX_ADDR_ELEM_CNT(_n) (0xf48 + (_n) * 0x4) ++#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT GENMASK(15, 0) ++#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT GENMASK(31, 16) ++#define MTK_WED_ADDR_ELEM_ACKSN_CNT GENMASK(27, 0) ++ ++#define MTK_WED_RX_MSDU_PG_CNT(_n) (0xf5c + (_n) * 0x4) ++ ++#define MTK_WED_RX_PN_CHK_CNT 0xf70 ++#define MTK_WED_PN_CHK_FAIL_CNT GENMASK(15, 0) ++ + #define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 + #define MTK_WED_PCIE_INT_MASK 0x0 + ++#define MTK_WED_PCIE_BASE 0x11280000 ++#define MTK_WED_PCIE_BASE0 0x11300000 ++#define MTK_WED_PCIE_BASE1 0x11310000 ++#define MTK_WED_PCIE_BASE2 0x11290000 + #endif +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -91,6 +91,8 @@ enum mtk_wed_dummy_cr_idx { + #define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" + #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" + #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" ++#define MT7988_FIRMWARE_WO0 "mediatek/mt7988_wo_0.bin" ++#define MT7988_FIRMWARE_WO1 "mediatek/mt7988_wo_1.bin" + + #define MTK_WO_MCU_CFG_LS_BASE 0 + #define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -139,6 +139,8 @@ struct mtk_wed_device { + u32 wpdma_rx; + + bool wcid_512; ++ bool hw_rro; ++ bool msi; + + u16 token_start; + unsigned int nbuf; +@@ -212,10 +214,12 @@ mtk_wed_device_attach(struct mtk_wed_dev + return ret; + } + +-static inline bool +-mtk_wed_get_rx_capa(struct mtk_wed_device *dev) ++static inline bool mtk_wed_get_rx_capa(struct mtk_wed_device *dev) + { + #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ if (dev->version == 3) ++ return dev->wlan.hw_rro; ++ + return dev->version != 1; + #else + return false; diff --git a/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch b/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch new file mode 100644 index 0000000000..e91ae69d08 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch @@ -0,0 +1,95 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:14 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: refactor mtk_wed_check_wfdma_rx_fill + routine + +Refactor mtk_wed_check_wfdma_rx_fill() in order to be reused adding HW +receive offload support for MT7988 SoC. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -585,22 +585,15 @@ mtk_wed_set_512_support(struct mtk_wed_d + } + } + +-#define MTK_WFMDA_RX_DMA_EN BIT(2) +-static void +-mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) ++static int ++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, ++ struct mtk_wed_ring *ring) + { +- u32 val; + int i; + +- if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) +- return; /* queue is not configured by mt76 */ +- + for (i = 0; i < 3; i++) { +- u32 cur_idx; ++ u32 cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX); + +- cur_idx = wed_r32(dev, +- MTK_WED_WPDMA_RING_RX_DATA(idx) + +- MTK_WED_RING_OFS_CPU_IDX); + if (cur_idx == MTK_WED_RX_RING_SIZE - 1) + break; + +@@ -609,12 +602,10 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_w + + if (i == 3) { + dev_err(dev->hw->dev, "rx dma enable failed\n"); +- return; ++ return -ETIMEDOUT; + } + +- val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | +- MTK_WFMDA_RX_DMA_EN; +- wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); ++ return 0; + } + + static void +@@ -1545,6 +1536,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev + wed_w32(dev, MTK_WED_INT_MASK, irq_mask); + } + ++#define MTK_WFMDA_RX_DMA_EN BIT(2) + static void + mtk_wed_dma_enable(struct mtk_wed_device *dev) + { +@@ -1632,8 +1624,26 @@ mtk_wed_dma_enable(struct mtk_wed_device + wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); + } + +- for (i = 0; i < MTK_WED_RX_QUEUES; i++) +- mtk_wed_check_wfdma_rx_fill(dev, i); ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_ring[i]; ++ u32 val; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; /* queue is not configured by mt76 */ ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) { ++ dev_err(dev->hw->dev, ++ "rx_ring(%d) dma enable failed\n", i); ++ continue; ++ } ++ ++ val = wifi_r32(dev, ++ dev->wlan.wpdma_rx_glo - ++ dev->wlan.phy_base) | MTK_WFMDA_RX_DMA_EN; ++ wifi_w32(dev, ++ dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, ++ val); ++ } + } + + static void diff --git a/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch b/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch new file mode 100644 index 0000000000..6534d73d8e --- /dev/null +++ b/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch @@ -0,0 +1,465 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:15 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce partial AMSDU offload + support for MT7988 + +Introduce partial AMSDU offload support for MT7988 SoC in order to merge +in hw packets belonging to the same AMSDU before passing them to the +WLAN nic. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -438,7 +438,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e + } + + int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, +- int wdma_idx, int txq, int bss, int wcid) ++ int wdma_idx, int txq, int bss, int wcid, ++ bool amsdu_en) + { + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); +@@ -450,6 +451,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et + MTK_FOE_IB2_WDMA_WINFO_V2; + l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | + FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); ++ l2->amsdu = FIELD_PREP(MTK_FOE_WINFO_AMSDU_EN, amsdu_en); + break; + case 2: + *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -88,13 +88,13 @@ enum { + #define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) + #define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) + +-#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) +-#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) +-#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) +-#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) +-#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) +-#define MTK_FOE_WINFO_PAO_HF BIT(23) +-#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) ++#define MTK_FOE_WINFO_AMSDU_USR_INFO GENMASK(15, 0) ++#define MTK_FOE_WINFO_AMSDU_TID GENMASK(19, 16) ++#define MTK_FOE_WINFO_AMSDU_IS_FIXEDRATE BIT(20) ++#define MTK_FOE_WINFO_AMSDU_IS_PRIOR BIT(21) ++#define MTK_FOE_WINFO_AMSDU_IS_SP BIT(22) ++#define MTK_FOE_WINFO_AMSDU_HF BIT(23) ++#define MTK_FOE_WINFO_AMSDU_EN BIT(24) + + enum { + MTK_FOE_STATE_INVALID, +@@ -123,7 +123,7 @@ struct mtk_foe_mac_info { + + /* netsys_v3 */ + u32 w3info; +- u32 wpao; ++ u32 amsdu; + }; + + /* software-only entry type */ +@@ -394,7 +394,8 @@ int mtk_foe_entry_set_vlan(struct mtk_et + int mtk_foe_entry_set_pppoe(struct mtk_eth *eth, struct mtk_foe_entry *entry, + int sid); + int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, +- int wdma_idx, int txq, int bss, int wcid); ++ int wdma_idx, int txq, int bss, int wcid, ++ bool amsdu_en); + int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, + unsigned int queue); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -111,6 +111,7 @@ mtk_flow_get_wdma_info(struct net_device + info->queue = path->mtk_wdma.queue; + info->bss = path->mtk_wdma.bss; + info->wcid = path->mtk_wdma.wcid; ++ info->amsdu = path->mtk_wdma.amsdu; + + return 0; + } +@@ -192,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_et + + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { + mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, +- info.bss, info.wcid); ++ info.bss, info.wcid, info.amsdu); + if (mtk_is_netsys_v2_or_greater(eth)) { + switch (info.wdma_idx) { + case 0: +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -29,6 +29,8 @@ + #define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) + #define MTK_WED_RX_RING_SIZE 1536 + #define MTK_WED_RX_PG_BM_CNT 8192 ++#define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4) ++#define MTK_WED_AMSDU_NPAGES 32 + + #define MTK_WED_TX_RING_SIZE 2048 + #define MTK_WED_WDMA_RING_SIZE 1024 +@@ -172,6 +174,23 @@ mtk_wdma_rx_reset(struct mtk_wed_device + return ret; + } + ++static u32 ++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return !!(wed_r32(dev, reg) & mask); ++} ++ ++static int ++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ int sleep = 15000; ++ int timeout = 100 * sleep; ++ u32 val; ++ ++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, ++ timeout, false, dev, reg, mask); ++} ++ + static void + mtk_wdma_tx_reset(struct mtk_wed_device *dev) + { +@@ -335,6 +354,118 @@ out: + } + + static int ++mtk_wed_amsdu_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_hw *hw = dev->hw; ++ struct mtk_wed_amsdu *wed_amsdu; ++ int i; ++ ++ if (!mtk_wed_is_v3_or_greater(hw)) ++ return 0; ++ ++ wed_amsdu = devm_kcalloc(hw->dev, MTK_WED_AMSDU_NPAGES, ++ sizeof(*wed_amsdu), GFP_KERNEL); ++ if (!wed_amsdu) ++ return -ENOMEM; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) { ++ void *ptr; ++ ++ /* each segment is 64K */ ++ ptr = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | ++ __GFP_ZERO | __GFP_COMP | ++ GFP_DMA32, ++ get_order(MTK_WED_AMSDU_BUF_SIZE)); ++ if (!ptr) ++ goto error; ++ ++ wed_amsdu[i].txd = ptr; ++ wed_amsdu[i].txd_phy = dma_map_single(hw->dev, ptr, ++ MTK_WED_AMSDU_BUF_SIZE, ++ DMA_TO_DEVICE); ++ if (dma_mapping_error(hw->dev, wed_amsdu[i].txd_phy)) ++ goto error; ++ } ++ dev->hw->wed_amsdu = wed_amsdu; ++ ++ return 0; ++ ++error: ++ for (i--; i >= 0; i--) ++ dma_unmap_single(hw->dev, wed_amsdu[i].txd_phy, ++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE); ++ return -ENOMEM; ++} ++ ++static void ++mtk_wed_amsdu_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu; ++ int i; ++ ++ if (!wed_amsdu) ++ return; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) { ++ dma_unmap_single(dev->hw->dev, wed_amsdu[i].txd_phy, ++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE); ++ free_pages((unsigned long)wed_amsdu[i].txd, ++ get_order(MTK_WED_AMSDU_BUF_SIZE)); ++ } ++} ++ ++static int ++mtk_wed_amsdu_init(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu; ++ int i, ret; ++ ++ if (!wed_amsdu) ++ return 0; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) ++ wed_w32(dev, MTK_WED_AMSDU_HIFTXD_BASE_L(i), ++ wed_amsdu[i].txd_phy); ++ ++ /* init all sta parameter */ ++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO_INIT, MTK_WED_AMSDU_STA_RMVL | ++ MTK_WED_AMSDU_STA_WTBL_HDRT_MODE | ++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_LEN, ++ dev->wlan.amsdu_max_len >> 8) | ++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_NUM, ++ dev->wlan.amsdu_max_subframes)); ++ ++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO, MTK_WED_AMSDU_STA_INFO_DO_INIT); ++ ++ ret = mtk_wed_poll_busy(dev, MTK_WED_AMSDU_STA_INFO, ++ MTK_WED_AMSDU_STA_INFO_DO_INIT); ++ if (ret) { ++ dev_err(dev->hw->dev, "amsdu initialization failed\n"); ++ return ret; ++ } ++ ++ /* init partial amsdu offload txd src */ ++ wed_set(dev, MTK_WED_AMSDU_HIFTXD_CFG, ++ FIELD_PREP(MTK_WED_AMSDU_HIFTXD_SRC, dev->hw->index)); ++ ++ /* init qmem */ ++ wed_set(dev, MTK_WED_AMSDU_PSE, MTK_WED_AMSDU_PSE_RESET); ++ ret = mtk_wed_poll_busy(dev, MTK_WED_MON_AMSDU_QMEM_STS1, BIT(29)); ++ if (ret) { ++ pr_info("%s: amsdu qmem initialization failed\n", __func__); ++ return ret; ++ } ++ ++ /* eagle E1 PCIE1 tx ring 22 flow control issue */ ++ if (dev->wlan.id == 0x7991) ++ wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING); ++ ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ ++ return 0; ++} ++ ++static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { + u32 desc_size = dev->hw->soc->tx_ring_desc_size; +@@ -708,6 +839,7 @@ __mtk_wed_detach(struct mtk_wed_device * + + mtk_wdma_rx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ mtk_wed_amsdu_free_buffer(dev); + mtk_wed_free_tx_buffer(dev); + mtk_wed_free_tx_rings(dev); + +@@ -1128,23 +1260,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring * + } + } + +-static u32 +-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) +-{ +- return !!(wed_r32(dev, reg) & mask); +-} +- +-static int +-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) +-{ +- int sleep = 15000; +- int timeout = 100 * sleep; +- u32 val; +- +- return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, +- timeout, false, dev, reg, mask); +-} +- + static int + mtk_wed_rx_reset(struct mtk_wed_device *dev) + { +@@ -1691,6 +1806,7 @@ mtk_wed_start(struct mtk_wed_device *dev + } + + mtk_wed_set_512_support(dev, dev->wlan.wcid_512); ++ mtk_wed_amsdu_init(dev); + + mtk_wed_dma_enable(dev); + dev->running = true; +@@ -1747,6 +1863,10 @@ mtk_wed_attach(struct mtk_wed_device *de + if (ret) + goto out; + ++ ret = mtk_wed_amsdu_buffer_alloc(dev); ++ if (ret) ++ goto out; ++ + if (mtk_wed_get_rx_capa(dev)) { + ret = mtk_wed_rro_alloc(dev); + if (ret) +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -25,6 +25,11 @@ struct mtk_wed_soc_data { + u32 wdma_desc_size; + }; + ++struct mtk_wed_amsdu { ++ void *txd; ++ dma_addr_t txd_phy; ++}; ++ + struct mtk_wed_hw { + const struct mtk_wed_soc_data *soc; + struct device_node *node; +@@ -38,6 +43,7 @@ struct mtk_wed_hw { + struct dentry *debugfs_dir; + struct mtk_wed_device *wed_dev; + struct mtk_wed_wo *wed_wo; ++ struct mtk_wed_amsdu *wed_amsdu; + u32 pcie_base; + u32 debugfs_reg; + u32 num_flows; +@@ -52,6 +58,7 @@ struct mtk_wdma_info { + u8 queue; + u16 wcid; + u8 bss; ++ u8 amsdu; + }; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -672,6 +672,82 @@ struct mtk_wdma_desc { + #define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 + #define MTK_WED_PCIE_INT_MASK 0x0 + ++#define MTK_WED_AMSDU_FIFO 0x1800 ++#define MTK_WED_AMSDU_IS_PRIOR0_RING BIT(10) ++ ++#define MTK_WED_AMSDU_STA_INFO 0x01810 ++#define MTK_WED_AMSDU_STA_INFO_DO_INIT BIT(0) ++#define MTK_WED_AMSDU_STA_INFO_SET_INIT BIT(1) ++ ++#define MTK_WED_AMSDU_STA_INFO_INIT 0x01814 ++#define MTK_WED_AMSDU_STA_WTBL_HDRT_MODE BIT(0) ++#define MTK_WED_AMSDU_STA_RMVL BIT(1) ++#define MTK_WED_AMSDU_STA_MAX_AMSDU_LEN GENMASK(7, 2) ++#define MTK_WED_AMSDU_STA_MAX_AMSDU_NUM GENMASK(11, 8) ++ ++#define MTK_WED_AMSDU_HIFTXD_BASE_L(_n) (0x1980 + (_n) * 0x4) ++ ++#define MTK_WED_AMSDU_PSE 0x1910 ++#define MTK_WED_AMSDU_PSE_RESET BIT(16) ++ ++#define MTK_WED_AMSDU_HIFTXD_CFG 0x1968 ++#define MTK_WED_AMSDU_HIFTXD_SRC GENMASK(16, 15) ++ ++#define MTK_WED_MON_AMSDU_FIFO_DMAD 0x1a34 ++ ++#define MTK_WED_MON_AMSDU_ENG_DMAD(_n) (0x1a80 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QFPL(_n) (0x1a84 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QENI(_n) (0x1a88 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QENO(_n) (0x1a8c + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_MERG(_n) (0x1a90 + (_n) * 0x50) ++ ++#define MTK_WED_MON_AMSDU_ENG_CNT8(_n) (0x1a94 + (_n) * 0x50) ++#define MTK_WED_AMSDU_ENG_MAX_QGPP_CNT GENMASK(10, 0) ++#define MTK_WED_AMSDU_ENG_MAX_PL_CNT GENMASK(27, 16) ++ ++#define MTK_WED_MON_AMSDU_ENG_CNT9(_n) (0x1a98 + (_n) * 0x50) ++#define MTK_WED_AMSDU_ENG_CUR_ENTRY GENMASK(10, 0) ++#define MTK_WED_AMSDU_ENG_MAX_BUF_MERGED GENMASK(20, 16) ++#define MTK_WED_AMSDU_ENG_MAX_MSDU_MERGED GENMASK(28, 24) ++ ++#define MTK_WED_MON_AMSDU_QMEM_STS1 0x1e04 ++ ++#define MTK_WED_MON_AMSDU_QMEM_CNT(_n) (0x1e0c + (_n) * 0x4) ++#define MTK_WED_AMSDU_QMEM_FQ_CNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QCNT GENMASK(11, 0) ++ ++#define MTK_WED_MON_AMSDU_QMEM_PTR(_n) (0x1e20 + (_n) * 0x4) ++#define MTK_WED_AMSDU_QMEM_FQ_HEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_FQ_TAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QTAIL GENMASK(11, 0) ++ ++#define MTK_WED_MON_AMSDU_HIFTXD_FETCH_MSDU(_n) (0x1ec4 + (_n) * 0x4) ++ + #define MTK_WED_PCIE_BASE 0x11280000 + #define MTK_WED_PCIE_BASE0 0x11300000 + #define MTK_WED_PCIE_BASE1 0x11310000 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -928,6 +928,7 @@ struct net_device_path { + u8 queue; + u16 wcid; + u8 bss; ++ u8 amsdu; + } mtk_wdma; + }; + }; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -129,6 +129,7 @@ struct mtk_wed_device { + enum mtk_wed_bus_tye bus_type; + void __iomem *base; + u32 phy_base; ++ u32 id; + + u32 wpdma_phys; + u32 wpdma_int; +@@ -147,10 +148,12 @@ struct mtk_wed_device { + unsigned int rx_nbuf; + unsigned int rx_npkt; + unsigned int rx_size; ++ unsigned int amsdu_max_len; + + u8 tx_tbit[MTK_WED_TX_QUEUES]; + u8 rx_tbit[MTK_WED_RX_QUEUES]; + u8 txfree_tbit; ++ u8 amsdu_max_subframes; + + u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); + int (*offload_enable)(struct mtk_wed_device *wed); +@@ -224,6 +227,15 @@ static inline bool mtk_wed_get_rx_capa(s + #else + return false; + #endif ++} ++ ++static inline bool mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev) ++{ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ return dev->version == 3; ++#else ++ return false; ++#endif + } + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED diff --git a/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch b/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch new file mode 100644 index 0000000000..0cf4c18875 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch @@ -0,0 +1,483 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:16 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce hw_rro support for MT7988 + +MT7988 SoC support 802.11 receive reordering offload in hw while +MT7986 SoC implements it through the firmware running on the mcu. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -26,7 +26,7 @@ + #define MTK_WED_BUF_SIZE 2048 + #define MTK_WED_PAGE_BUF_SIZE 128 + #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) +-#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) ++#define MTK_WED_RX_BUF_PER_PAGE (PAGE_SIZE / MTK_WED_PAGE_BUF_SIZE) + #define MTK_WED_RX_RING_SIZE 1536 + #define MTK_WED_RX_PG_BM_CNT 8192 + #define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4) +@@ -596,6 +596,68 @@ free_pagelist: + } + + static int ++mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ int n_pages = MTK_WED_RX_PG_BM_CNT / MTK_WED_RX_BUF_PER_PAGE; ++ struct mtk_wed_buf *page_list; ++ struct mtk_wed_bm_desc *desc; ++ dma_addr_t desc_phys; ++ int i, page_idx = 0; ++ ++ if (!dev->wlan.hw_rro) ++ return 0; ++ ++ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); ++ if (!page_list) ++ return -ENOMEM; ++ ++ dev->hw_rro.size = dev->wlan.rx_nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ dev->hw_rro.pages = page_list; ++ desc = dma_alloc_coherent(dev->hw->dev, ++ dev->wlan.rx_nbuf * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ dev->hw_rro.desc = desc; ++ dev->hw_rro.desc_phys = desc_phys; ++ ++ for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_BUF_PER_PAGE) { ++ dma_addr_t page_phys, buf_phys; ++ struct page *page; ++ int s; ++ ++ page = __dev_alloc_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; ++ ++ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(dev->hw->dev, page_phys)) { ++ __free_page(page); ++ return -ENOMEM; ++ } ++ ++ page_list[page_idx].p = page; ++ page_list[page_idx++].phy_addr = page_phys; ++ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ ++ buf_phys = page_phys; ++ for (s = 0; s < MTK_WED_RX_BUF_PER_PAGE; s++) { ++ desc->buf0 = cpu_to_le32(buf_phys); ++ buf_phys += MTK_WED_PAGE_BUF_SIZE; ++ desc++; ++ } ++ ++ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ } ++ ++ return 0; ++} ++ ++static int + mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) + { + struct mtk_wed_bm_desc *desc; +@@ -612,7 +674,42 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d + dev->rx_buf_ring.desc_phys = desc_phys; + dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); + +- return 0; ++ return mtk_wed_hwrro_buffer_alloc(dev); ++} ++ ++static void ++mtk_wed_hwrro_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_buf *page_list = dev->hw_rro.pages; ++ struct mtk_wed_bm_desc *desc = dev->hw_rro.desc; ++ int i, page_idx = 0; ++ ++ if (!dev->wlan.hw_rro) ++ return; ++ ++ if (!page_list) ++ return; ++ ++ if (!desc) ++ goto free_pagelist; ++ ++ for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_BUF_PER_PAGE) { ++ dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ void *page = page_list[page_idx++].p; ++ ++ if (!page) ++ break; ++ ++ dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ __free_page(page); ++ } ++ ++ dma_free_coherent(dev->hw->dev, dev->hw_rro.size * sizeof(*desc), ++ desc, dev->hw_rro.desc_phys); ++ ++free_pagelist: ++ kfree(page_list); + } + + static void +@@ -626,6 +723,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_de + dev->wlan.release_rx_buf(dev); + dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), + desc, dev->rx_buf_ring.desc_phys); ++ ++ mtk_wed_hwrro_free_buffer(dev); ++} ++ ++static void ++mtk_wed_hwrro_init(struct mtk_wed_device *dev) ++{ ++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) ++ return; ++ ++ wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM, ++ FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128)); ++ ++ wed_w32(dev, MTK_WED_RRO_PG_BM_BASE, dev->hw_rro.desc_phys); ++ ++ wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR, ++ MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX | ++ FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX, ++ MTK_WED_RX_PG_BM_CNT)); ++ ++ /* enable rx_page_bm to fetch dmad */ ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN); + } + + static void +@@ -639,6 +758,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed + wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, + FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); + wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++ ++ mtk_wed_hwrro_init(dev); + } + + static void +@@ -934,6 +1055,8 @@ mtk_wed_bus_init(struct mtk_wed_device * + static void + mtk_wed_set_wpdma(struct mtk_wed_device *dev) + { ++ int i; ++ + if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); + return; +@@ -951,6 +1074,15 @@ mtk_wed_set_wpdma(struct mtk_wed_device + + wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); + wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); ++ ++ if (!dev->wlan.hw_rro) ++ return; ++ ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]); ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]); ++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i), ++ dev->wlan.wpdma_rx_pg + i * 0x10); + } + + static void +@@ -1762,6 +1894,165 @@ mtk_wed_dma_enable(struct mtk_wed_device + } + + static void ++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask, bool reset) ++{ ++ int i; ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask); ++ wed_w32(dev, MTK_WED_INT_MASK, irq_mask); ++ ++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) ++ return; ++ ++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX, ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG, ++ dev->wlan.rro_rx_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG, ++ dev->wlan.rro_rx_tbit[1])); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG, ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[1]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[2])); ++ ++ /* RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after ++ * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken ++ */ ++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[i]; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) ++ dev_err(dev->hw->dev, ++ "rx_rro_ring(%d) initialization failed\n", i); ++ } ++ ++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_page_ring[i]; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) ++ dev_err(dev->hw->dev, ++ "rx_page_ring(%d) initialization failed\n", i); ++ } ++} ++ ++static void ++mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, ++ void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx]; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE, ++ readl(regs)); ++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ring->flags |= MTK_WED_RING_CONFIGURED; ++} ++ ++static void ++mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->rx_page_ring[idx]; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE, ++ readl(regs)); ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ring->flags |= MTK_WED_RING_CONFIGURED; ++} ++ ++static int ++mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->ind_cmd_ring; ++ u32 val = readl(regs + MTK_WED_RING_OFS_COUNT); ++ int i, count = 0; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE, ++ readl(regs) & 0xfffffff0); ++ ++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ++ /* ack sn cr */ ++ wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base + ++ dev->wlan.ind_cmd.ack_sn_addr); ++ wed_w32(dev, MTK_WED_RRO_CFG1, ++ FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ, ++ dev->wlan.ind_cmd.win_size) | ++ FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID, ++ dev->wlan.ind_cmd.particular_sid)); ++ ++ /* particular session addr element */ ++ wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0, ++ dev->wlan.ind_cmd.particular_se_phys); ++ ++ for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) { ++ wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA, ++ dev->wlan.ind_cmd.addr_elem_phys[i] >> 4); ++ wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG, ++ MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f)); ++ ++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG); ++ while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) && count++ < 100) ++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG); ++ if (count >= 100) ++ dev_err(dev->hw->dev, ++ "write ba session base failed\n"); ++ } ++ ++ /* pn check init */ ++ for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) { ++ wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M, ++ MTK_WED_PN_CHECK_IS_FIRST); ++ ++ wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR | ++ FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i)); ++ ++ count = 0; ++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG); ++ while (!(val & MTK_WED_PN_CHECK_WR_RDY) && count++ < 100) ++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG); ++ if (count >= 100) ++ dev_err(dev->hw->dev, ++ "session(%d) initialization failed\n", i); ++ } ++ ++ wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN); ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN); ++ ++ return 0; ++} ++ ++static void + mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask) + { + int i; +@@ -2215,6 +2506,10 @@ void mtk_wed_add_hw(struct device_node * + .detach = mtk_wed_detach, + .ppe_check = mtk_wed_ppe_check, + .setup_tc = mtk_wed_setup_tc, ++ .start_hw_rro = mtk_wed_start_hw_rro, ++ .rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup, ++ .msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup, ++ .ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup, + }; + struct device_node *eth_np = eth->dev->of_node; + struct platform_device *pdev; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -10,6 +10,7 @@ + + #define MTK_WED_TX_QUEUES 2 + #define MTK_WED_RX_QUEUES 2 ++#define MTK_WED_RX_PAGE_QUEUES 3 + + #define WED_WO_STA_REC 0x6 + +@@ -99,6 +100,9 @@ struct mtk_wed_device { + struct mtk_wed_ring txfree_ring; + struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; + struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; ++ struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES]; ++ struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES]; ++ struct mtk_wed_ring ind_cmd_ring; + + struct { + int size; +@@ -120,6 +124,13 @@ struct mtk_wed_device { + dma_addr_t fdbk_phys; + } rro; + ++ struct { ++ int size; ++ struct mtk_wed_buf *pages; ++ struct mtk_wed_bm_desc *desc; ++ dma_addr_t desc_phys; ++ } hw_rro; ++ + /* filled by driver: */ + struct { + union { +@@ -138,6 +149,8 @@ struct mtk_wed_device { + u32 wpdma_txfree; + u32 wpdma_rx_glo; + u32 wpdma_rx; ++ u32 wpdma_rx_rro[MTK_WED_RX_QUEUES]; ++ u32 wpdma_rx_pg; + + bool wcid_512; + bool hw_rro; +@@ -152,9 +165,20 @@ struct mtk_wed_device { + + u8 tx_tbit[MTK_WED_TX_QUEUES]; + u8 rx_tbit[MTK_WED_RX_QUEUES]; ++ u8 rro_rx_tbit[MTK_WED_RX_QUEUES]; ++ u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES]; + u8 txfree_tbit; + u8 amsdu_max_subframes; + ++ struct { ++ u8 se_group_nums; ++ u16 win_size; ++ u16 particular_sid; ++ u32 ack_sn_addr; ++ dma_addr_t particular_se_phys; ++ dma_addr_t addr_elem_phys[1024]; ++ } ind_cmd; ++ + u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); + int (*offload_enable)(struct mtk_wed_device *wed); + void (*offload_disable)(struct mtk_wed_device *wed); +@@ -193,6 +217,14 @@ struct mtk_wed_ops { + void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); + int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, + enum tc_setup_type type, void *type_data); ++ void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask, ++ bool reset); ++ void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ int (*ind_rx_ring_setup)(struct mtk_wed_device *dev, ++ void __iomem *regs); + }; + + extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; +@@ -264,6 +296,15 @@ static inline bool mtk_wed_is_amsdu_supp + #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) + #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ + (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) ++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) \ ++ (_dev)->ops->start_hw_rro(_dev, _mask, _reset) ++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \ ++ (_dev)->ops->ind_rx_ring_setup(_dev, _regs) ++ + #else + static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) + { +@@ -283,6 +324,10 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_stop(_dev) do {} while (0) + #define mtk_wed_device_dma_reset(_dev) do {} while (0) + #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP ++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) do {} while (0) ++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) -ENODEV + #endif + + #endif diff --git a/target/linux/generic/backport-6.6/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch b/target/linux/generic/backport-6.6/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch new file mode 100644 index 0000000000..5ea43a4445 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch @@ -0,0 +1,78 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:17 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: debugfs: move wed_v2 specific regs + out of regs array + +Move specific WED2.0 debugfs entries out of regs array. This is a +preliminary patch to introduce WED 3.0 debugfs info. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -151,7 +151,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo); + static int + wed_rxinfo_show(struct seq_file *s, void *data) + { +- static const struct reg_dump regs[] = { ++ static const struct reg_dump regs_common[] = { + DUMP_STR("WPDMA RX"), + DUMP_WPDMA_RX_RING(0), + DUMP_WPDMA_RX_RING(1), +@@ -169,7 +169,7 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED_RING(WED_RING_RX_DATA(0)), + DUMP_WED_RING(WED_RING_RX_DATA(1)), + +- DUMP_STR("WED RRO"), ++ DUMP_STR("WED WO RRO"), + DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), + DUMP_WED(WED_RROQM_MID_MIB), + DUMP_WED(WED_RROQM_MOD_MIB), +@@ -180,17 +180,6 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RROQM_FDBK_ANC_MIB), + DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), + +- DUMP_STR("WED Route QM"), +- DUMP_WED(WED_RTQM_R2H_MIB(0)), +- DUMP_WED(WED_RTQM_R2Q_MIB(0)), +- DUMP_WED(WED_RTQM_Q2H_MIB(0)), +- DUMP_WED(WED_RTQM_R2H_MIB(1)), +- DUMP_WED(WED_RTQM_R2Q_MIB(1)), +- DUMP_WED(WED_RTQM_Q2H_MIB(1)), +- DUMP_WED(WED_RTQM_Q2N_MIB), +- DUMP_WED(WED_RTQM_Q2B_MIB), +- DUMP_WED(WED_RTQM_PFDBK_MIB), +- + DUMP_STR("WED WDMA TX"), + DUMP_WED(WED_WDMA_TX_MIB), + DUMP_WED_RING(WED_WDMA_RING_TX), +@@ -211,11 +200,25 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RX_BM_INTF), + DUMP_WED(WED_RX_BM_ERR_STS), + }; ++ static const struct reg_dump regs_wed_v2[] = { ++ DUMP_STR("WED Route QM"), ++ DUMP_WED(WED_RTQM_R2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(0)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2H_MIB(1)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2N_MIB), ++ DUMP_WED(WED_RTQM_Q2B_MIB), ++ DUMP_WED(WED_RTQM_PFDBK_MIB), ++ }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (dev) +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) { ++ dump_wed_regs(s, dev, regs_common, ARRAY_SIZE(regs_common)); ++ dump_wed_regs(s, dev, regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ } + + return 0; + } diff --git a/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch b/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch new file mode 100644 index 0000000000..f491d2fd80 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch @@ -0,0 +1,432 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:18 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: debugfs: add WED 3.0 debugfs entries + +Introduce WED3.0 debugfs entries useful for debugging. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -11,6 +11,7 @@ struct reg_dump { + u16 offset; + u8 type; + u8 base; ++ u32 mask; + }; + + enum { +@@ -25,6 +26,8 @@ enum { + + #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } + #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ } ++#define DUMP_REG_MASK(_reg, _mask) \ ++ { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask } + #define DUMP_RING(_prefix, _base, ...) \ + { _prefix " BASE", _base, __VA_ARGS__ }, \ + { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \ +@@ -32,6 +35,7 @@ enum { + { _prefix " DIDX", _base + 0xc, __VA_ARGS__ } + + #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED) ++#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask) + #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED) + + #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA) +@@ -212,12 +216,58 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RTQM_Q2B_MIB), + DUMP_WED(WED_RTQM_PFDBK_MIB), + }; ++ static const struct reg_dump regs_wed_v3[] = { ++ DUMP_STR("WED RX RRO DATA"), ++ DUMP_WED_RING(WED_RRO_RX_D_RX(0)), ++ DUMP_WED_RING(WED_RRO_RX_D_RX(1)), ++ ++ DUMP_STR("WED RX MSDU PAGE"), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)), ++ ++ DUMP_STR("WED RX IND CMD"), ++ DUMP_WED(WED_IND_CMD_RX_CTRL1), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX), ++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT), ++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, ++ WED_IND_CMD_PREFETCH_FREE_CNT), ++ DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID), ++ ++ DUMP_STR("WED ADDR ELEM"), ++ DUMP_WED(WED_ADDR_ELEM_CFG0), ++ DUMP_WED_MASK(WED_ADDR_ELEM_CFG1, ++ WED_ADDR_ELEM_PREFETCH_FREE_CNT), ++ ++ DUMP_STR("WED Route QM"), ++ DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT), ++ DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT), ++ DUMP_WED(WED_RTQM_ENQ_ERR_CNT), ++ ++ DUMP_WED(WED_RTQM_DEQ_DMAD_CNT), ++ DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT), ++ DUMP_WED(WED_RTQM_DEQ_PKT_CNT), ++ DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT), ++ DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT), ++ DUMP_WED(WED_RTQM_DEQ_ERR_CNT), ++ }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + + if (dev) { + dump_wed_regs(s, dev, regs_common, ARRAY_SIZE(regs_common)); +- dump_wed_regs(s, dev, regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ if (mtk_wed_is_v2(hw)) ++ dump_wed_regs(s, dev, ++ regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ else ++ dump_wed_regs(s, dev, ++ regs_wed_v3, ARRAY_SIZE(regs_wed_v3)); + } + + return 0; +@@ -225,6 +275,314 @@ wed_rxinfo_show(struct seq_file *s, void + DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); + + static int ++wed_amsdu_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED AMDSU INFO"), ++ DUMP_WED(WED_MON_AMSDU_FIFO_DMAD), ++ ++ DUMP_STR("WED AMDSU ENG0 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(0)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG1 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(1)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG2 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(2)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG3 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(3)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG4 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(4)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG5 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(5)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG6 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(6)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG7 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(7)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG8 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(8)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED QMEM INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_FQ_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_SP_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID0_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID1_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID2_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID3_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID4_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID5_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID6_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID7_QCNT), ++ ++ DUMP_STR("WED QMEM HEAD INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_FQ_HEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_SP_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID0_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID1_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID2_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID3_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID4_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID5_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID6_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID7_QHEAD), ++ ++ DUMP_STR("WED QMEM TAIL INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_FQ_TAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_SP_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID0_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID1_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID2_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID3_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID4_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID5_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID6_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID7_QTAIL), ++ ++ DUMP_STR("WED HIFTXD MSDU INFO"), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(1)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(2)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(3)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(4)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(5)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(6)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(7)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(8)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(9)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(10)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(11)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(12)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(13)), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_amsdu); ++ ++static int ++wed_rtqm_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"), ++ DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS1(Legacy)"), ++ DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS2(RRO3.0)"), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS3(DEBUG)"), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_rtqm); ++ ++static int ++wed_rro_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("RRO/IND CMD CNT"), ++ DUMP_WED(WED_RX_IND_CMD_CNT(1)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(2)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(3)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(4)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(5)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(6)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(7)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(8)), ++ DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9), ++ WED_IND_CMD_MAGIC_CNT_FAIL_CNT), ++ ++ DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)), ++ DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1), ++ WED_ADDR_ELEM_SIG_FAIL_CNT), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(1)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(2)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(3)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(4)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(5)), ++ DUMP_WED_MASK(WED_RX_PN_CHK_CNT, ++ WED_PN_CHK_FAIL_CNT), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_rro); ++ ++static int + mtk_wed_reg_set(void *data, u64 val) + { + struct mtk_wed_hw *hw = data; +@@ -266,7 +624,16 @@ void mtk_wed_hw_add_debugfs(struct mtk_w + debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); + debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); +- if (!mtk_wed_is_v1(hw)) ++ if (!mtk_wed_is_v1(hw)) { + debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, + &wed_rxinfo_fops); ++ if (mtk_wed_is_v3_or_greater(hw)) { ++ debugfs_create_file_unsafe("amsdu", 0400, dir, hw, ++ &wed_amsdu_fops); ++ debugfs_create_file_unsafe("rtqm", 0400, dir, hw, ++ &wed_rtqm_fops); ++ debugfs_create_file_unsafe("rro", 0400, dir, hw, ++ &wed_rro_fops); ++ } ++ } + } diff --git a/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch b/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch new file mode 100644 index 0000000000..aaaabf05e8 --- /dev/null +++ b/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch @@ -0,0 +1,587 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:19 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add wed 3.0 reset support + +Introduce support for resetting Wireless Ethernet Dispatcher 3.0 +available on MT988 SoC. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -148,6 +148,90 @@ mtk_wdma_read_reset(struct mtk_wed_devic + return wdma_r32(dev, MTK_WDMA_GLO_CFG); + } + ++static void ++mtk_wdma_v3_rx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status; ++ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return; ++ ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ /* prefetch FIFO */ ++ wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG, ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG, ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR); ++ ++ /* core FIFO */ ++ wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR); ++ wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR); ++ ++ /* writeback FIFO */ ++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ ++ /* prefetch ring status */ ++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR); ++ ++ /* writeback ring status */ ++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR); ++} ++ + static int + mtk_wdma_rx_reset(struct mtk_wed_device *dev) + { +@@ -160,6 +244,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device + if (ret) + dev_err(dev->hw->dev, "rx reset failed\n"); + ++ mtk_wdma_v3_rx_reset(dev); + wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + +@@ -192,6 +277,84 @@ mtk_wed_poll_busy(struct mtk_wed_device + } + + static void ++mtk_wdma_v3_tx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status; ++ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return; ++ ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ /* prefetch FIFO */ ++ wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG, ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG, ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR); ++ ++ /* core FIFO */ ++ wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR); ++ wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR); ++ ++ /* writeback FIFO */ ++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ ++ /* prefetch ring status */ ++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR); ++ ++ /* writeback ring status */ ++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR); ++} ++ ++static void + mtk_wdma_tx_reset(struct mtk_wed_device *dev) + { + u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; +@@ -202,6 +365,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device + !(status & mask), 0, 10000)) + dev_err(dev->hw->dev, "tx reset failed\n"); + ++ mtk_wdma_v3_tx_reset(dev); + wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + +@@ -1405,13 +1569,33 @@ mtk_wed_rx_reset(struct mtk_wed_device * + if (ret) + return ret; + ++ if (dev->wlan.hw_rro) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS, ++ MTK_WED_RX_IND_CMD_BUSY); ++ mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG); ++ } ++ + wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN); + ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, + MTK_WED_WPDMA_RX_D_RX_DRV_BUSY); ++ if (!ret && mtk_wed_is_v3_or_greater(dev->hw)) ++ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_BUSY); + if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* 1.a. disable prefetch HW */ ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_BUSY); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL); ++ } ++ + wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, + MTK_WED_WPDMA_RX_D_RST_CRX_IDX | + MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +@@ -1439,23 +1623,52 @@ mtk_wed_rx_reset(struct mtk_wed_device * + wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); + } + ++ if (dev->wlan.hw_rro) { ++ /* disable rro msdu page drv */ ++ wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ ++ /* disable rro data drv */ ++ wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN); ++ ++ /* rro msdu page drv reset */ ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ ++ /* rro data drv reset */ ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), ++ MTK_WED_RRO_RX_D_DRV_CLR); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2), ++ MTK_WED_RRO_RX_D_DRV_CLR); ++ } ++ + /* reset route qm */ + wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); + ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, + MTK_WED_CTRL_RX_ROUTE_QM_BUSY); +- if (ret) ++ if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); +- else +- wed_set(dev, MTK_WED_RTQM_GLO_CFG, +- MTK_WED_RTQM_Q_RST); ++ } else if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_RTQM_RST, BIT(0)); ++ wed_clr(dev, MTK_WED_RTQM_RST, BIT(0)); ++ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); ++ } else { ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ } + + /* reset tx wdma */ + mtk_wdma_tx_reset(dev); + + /* reset tx wdma drv */ + wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN); +- mtk_wed_poll_busy(dev, MTK_WED_CTRL, +- MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS, ++ MTK_WED_WPDMA_STATUS_TX_DRV); ++ else ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); + + /* reset wed rx dma */ +@@ -1476,6 +1689,14 @@ mtk_wed_rx_reset(struct mtk_wed_device * + MTK_WED_CTRL_WED_RX_BM_BUSY); + mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); + ++ if (dev->wlan.hw_rro) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_RX_PG_BM_BUSY); ++ wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM); ++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM); ++ } ++ + /* wo change to enable state */ + val = MTK_WED_WO_STATE_ENABLE; + ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, +@@ -1493,6 +1714,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * + false); + } + mtk_wed_free_rx_buffer(dev); ++ mtk_wed_hwrro_free_buffer(dev); + + return 0; + } +@@ -1526,15 +1748,41 @@ mtk_wed_reset_dma(struct mtk_wed_device + + /* 2. reset WDMA rx DMA */ + busy = !!mtk_wdma_rx_reset(dev); +- wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ val = MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE | ++ wed_r32(dev, MTK_WED_WDMA_GLO_CFG); ++ val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN; ++ wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val); ++ } else { ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ } ++ + if (!busy) + busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY); ++ if (!busy && mtk_wed_is_v3_or_greater(dev->hw)) ++ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_BUSY); + + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* 1.a. disable prefetch HW */ ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_BUSY); ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_DDONE2_EN); ++ ++ /* 2. Reset dma index */ ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, ++ MTK_WED_WDMA_RESET_IDX_RX_ALL); ++ } ++ + wed_w32(dev, MTK_WED_WDMA_RESET_IDX, + MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV); + wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0); +@@ -1550,8 +1798,13 @@ mtk_wed_reset_dma(struct mtk_wed_device + wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + + for (i = 0; i < 100; i++) { +- val = wed_r32(dev, MTK_WED_TX_BM_INTF); +- if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) ++ if (mtk_wed_is_v1(dev->hw)) ++ val = FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, ++ wed_r32(dev, MTK_WED_TX_BM_INTF)); ++ else ++ val = FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP, ++ wed_r32(dev, MTK_WED_TX_TKID_INTF)); ++ if (val == 0x40) + break; + } + +@@ -1573,6 +1826,8 @@ mtk_wed_reset_dma(struct mtk_wed_device + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ wed_w32(dev, MTK_WED_RX1_CTRL2, 0); + } else { + wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, + MTK_WED_WPDMA_RESET_IDX_TX | +@@ -1589,7 +1844,14 @@ mtk_wed_reset_dma(struct mtk_wed_device + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +- mtk_wed_rx_reset(dev); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* reset amsdu engine */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_AMSDU); ++ } ++ ++ if (mtk_wed_get_rx_capa(dev)) ++ mtk_wed_rx_reset(dev); + } + + static int +@@ -1841,6 +2103,7 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); + + wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); + } + + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, +@@ -1904,6 +2167,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_devi + if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) + return; + ++ if (reset) { ++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ return; ++ } ++ + wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR); + wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, + MTK_WED_RRO_MSDU_PG_DRV_CLR); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -28,6 +28,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET 0x008 + #define MTK_WED_RESET_TX_BM BIT(0) + #define MTK_WED_RESET_RX_BM BIT(1) ++#define MTK_WED_RESET_RX_PG_BM BIT(2) ++#define MTK_WED_RESET_RRO_RX_TO_PG BIT(3) + #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) + #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) + #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) +@@ -106,6 +108,9 @@ struct mtk_wdma_desc { + #define MTK_WED_STATUS 0x060 + #define MTK_WED_STATUS_TX GENMASK(15, 8) + ++#define MTK_WED_WPDMA_STATUS 0x068 ++#define MTK_WED_WPDMA_STATUS_TX_DRV GENMASK(15, 8) ++ + #define MTK_WED_TX_BM_CTRL 0x080 + #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) + #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) +@@ -140,6 +145,9 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16) + #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28) + ++#define MTK_WED_TX_TKID_INTF 0x0dc ++#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP GENMASK(25, 16) ++ + #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0) + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16) + +@@ -190,6 +198,7 @@ struct mtk_wdma_desc { + #define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) + + #define MTK_WED_SCR0 0x3c0 ++#define MTK_WED_RX1_CTRL2 0x418 + #define MTK_WED_WPDMA_INT_TRIGGER 0x504 + #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) + #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) +@@ -303,6 +312,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 + #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) ++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL BIT(20) + #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) + + #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c +@@ -313,6 +323,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4 + #define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_BUSY BIT(1) + #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8) + #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16) + +@@ -334,11 +345,13 @@ struct mtk_wdma_desc { + + #define MTK_WED_WDMA_RX_PREF_CFG 0x950 + #define MTK_WED_WDMA_RX_PREF_EN BIT(0) ++#define MTK_WED_WDMA_RX_PREF_BUSY BIT(1) + #define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8) + #define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16) + #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24) + #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25) + #define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26) ++#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY BIT(27) + + #define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C + #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0) +@@ -367,6 +380,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WDMA_RESET_IDX 0xa08 + #define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16) ++#define MTK_WED_WDMA_RESET_IDX_RX_ALL BIT(20) + #define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24) + + #define MTK_WED_WDMA_INT_CLR 0xa24 +@@ -437,21 +451,62 @@ struct mtk_wdma_desc { + #define MTK_WDMA_INT_MASK_RX_DELAY BIT(30) + #define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31) + ++#define MTK_WDMA_XDMA_TX_FIFO_CFG 0x238 ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR BIT(0) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR BIT(4) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR BIT(8) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR BIT(12) ++ ++#define MTK_WDMA_XDMA_RX_FIFO_CFG 0x23c ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR BIT(0) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR BIT(4) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR BIT(8) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR BIT(12) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR BIT(15) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR BIT(18) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR BIT(21) ++ + #define MTK_WDMA_INT_GRP1 0x250 + #define MTK_WDMA_INT_GRP2 0x254 + + #define MTK_WDMA_PREF_TX_CFG 0x2d0 + #define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0) ++#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY BIT(1) + + #define MTK_WDMA_PREF_RX_CFG 0x2dc + #define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0) ++#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY BIT(1) ++ ++#define MTK_WDMA_PREF_RX_FIFO_CFG 0x2e0 ++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR BIT(0) ++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR BIT(16) ++ ++#define MTK_WDMA_PREF_TX_FIFO_CFG 0x2d4 ++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR BIT(0) ++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR BIT(16) ++ ++#define MTK_WDMA_PREF_SIDX_CFG 0x2e4 ++#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0) ++#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4) + + #define MTK_WDMA_WRBK_TX_CFG 0x300 ++#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY BIT(0) + #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30) + ++#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n) (0x304 + (_n) * 0x4) ++#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR BIT(0) ++ + #define MTK_WDMA_WRBK_RX_CFG 0x344 ++#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY BIT(0) + #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30) + ++#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n) (0x348 + (_n) * 0x4) ++#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR BIT(0) ++ ++#define MTK_WDMA_WRBK_SIDX_CFG 0x388 ++#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0) ++#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4) ++ + #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) + #define MTK_PCIE_MIRROR_MAP_EN BIT(0) + #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) +@@ -465,6 +520,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) + #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) + ++#define MTK_WED_RTQM_RST 0xb04 ++ + #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c + #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4) + #define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28 +@@ -653,6 +710,9 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17) + #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18) + ++#define MTK_WED_RRO_RX_HW_STS 0xf00 ++#define MTK_WED_RX_IND_CMD_BUSY GENMASK(31, 0) ++ + #define MTK_WED_RX_IND_CMD_CNT0 0xf20 + #define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31) + diff --git a/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch new file mode 100644 index 0000000000..32ac37e8d0 --- /dev/null +++ b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch @@ -0,0 +1,102 @@ +From 038ba1dc4e54d51d953f5618d8eb5dd39bd9de25 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 13 Feb 2024 14:35:51 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR111 and AQR111B0 PHY ID + +Add Aquantia AQR111 and AQR111B0 PHY ID. These PHY advertise 10G speed +but actually supports up to 5G speed, hence some manual fixup is needed. + +The Aquantia AQR111B0 PHY is just a variant of the AQR111 with smaller +chip size. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240213133558.1836-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/aquantia/aquantia_main.c | 52 ++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -22,6 +22,8 @@ + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR111 0x03a1b610 ++#define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +@@ -670,6 +672,16 @@ static int aqr107_probe(struct phy_devic + return aqr_hwmon_probe(phydev); + } + ++static int aqr111_config_init(struct phy_device *phydev) ++{ ++ /* AQR111 reports supporting speed up to 10G, ++ * however only speeds up to 5G are supported. ++ */ ++ phy_set_max_speed(phydev, SPEED_5000); ++ ++ return aqr107_config_init(phydev); ++} ++ + static struct phy_driver aqr_driver[] = { + { + PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +@@ -744,6 +756,44 @@ static struct phy_driver aqr_driver[] = + .link_change_notify = aqr107_link_change_notify, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR111), ++ .name = "Aquantia AQR111", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr111_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0), ++ .name = "Aquantia AQR111B0", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr111_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR405), + .name = "Aquantia AQR405", + .config_aneg = aqr_config_aneg, +@@ -782,6 +832,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; diff --git a/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch new file mode 100644 index 0000000000..073bbbd49d --- /dev/null +++ b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch @@ -0,0 +1,60 @@ +From 71b605d32017e5b8d257db7344bc2f8e8fcc973e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 15 Feb 2024 16:30:05 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR113 PHY ID + +Add Aquantia AQR113 PHY ID. Aquantia AQR113 is just a chip size variant of +the already supported AQR133C where the only difference is the PHY ID +and the hw chip size. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia_main.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -24,6 +24,7 @@ + #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR111 0x03a1b610 + #define PHY_ID_AQR111B0 0x03a1b612 ++#define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +@@ -802,6 +803,25 @@ static struct phy_driver aqr_driver[] = + .read_status = aqr_read_status, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113), ++ .name = "Aquantia AQR113", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), + .name = "Aquantia AQR113C", + .probe = aqr107_probe, +@@ -834,6 +854,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; diff --git a/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch new file mode 100644 index 0000000000..965b8c91b2 --- /dev/null +++ b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch @@ -0,0 +1,59 @@ +From 6d47302a3f0ba31445478d518d98bd55918bc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 15 Feb 2024 22:43:30 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR813 PHY ID + +Aquantia AQR813 is the Octal Port variant of the AQR113. Add PHY ID for +it to provide support for it. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia_main.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -26,6 +26,7 @@ + #define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 ++#define PHY_ID_AQR813 0x31c31cb2 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -840,6 +841,25 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR813), ++ .name = "Aquantia AQR813", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -856,6 +876,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { } + }; + diff --git a/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch b/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch new file mode 100644 index 0000000000..789b93e9f9 --- /dev/null +++ b/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch @@ -0,0 +1,96 @@ +From 7f3eb2174512fe6c9c0f062e96eccb0d3cc6d5cd Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:47 +0200 +Subject: [PATCH] net: introduce napi_is_scheduled helper + +We currently have napi_if_scheduled_mark_missed that can be used to +check if napi is scheduled but that does more thing than simply checking +it and return a bool. Some driver already implement custom function to +check if napi is scheduled. + +Drop these custom function and introduce napi_is_scheduled that simply +check if napi is scheduled atomically. + +Update any driver and code that implement a similar check and instead +use this new helper. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- + drivers/net/wireless/realtek/rtw89/core.c | 2 +- + include/linux/netdevice.h | 23 +++++++++++++++++++++++ + net/core/dev.c | 2 +- + 4 files changed, 25 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c +@@ -2507,14 +2507,6 @@ static int napi_rx_handler(struct napi_s + return work_done; + } + +-/* +- * Returns true if the device is already scheduled for polling. +- */ +-static inline int napi_is_scheduled(struct napi_struct *napi) +-{ +- return test_bit(NAPI_STATE_SCHED, &napi->state); +-} +- + /** + * process_pure_responses - process pure responses from a response queue + * @adap: the adapter +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -1479,7 +1479,7 @@ static void rtw89_core_rx_to_mac80211(st + struct napi_struct *napi = &rtwdev->napi; + + /* In low power mode, napi isn't scheduled. Receive it to netif. */ +- if (unlikely(!test_bit(NAPI_STATE_SCHED, &napi->state))) ++ if (unlikely(!napi_is_scheduled(napi))) + napi = NULL; + + rtw89_core_hw_to_sband_rate(rx_status); +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -468,6 +468,29 @@ static inline bool napi_prefer_busy_poll + return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state); + } + ++/** ++ * napi_is_scheduled - test if NAPI is scheduled ++ * @n: NAPI context ++ * ++ * This check is "best-effort". With no locking implemented, ++ * a NAPI can be scheduled or terminate right after this check ++ * and produce not precise results. ++ * ++ * NAPI_STATE_SCHED is an internal state, napi_is_scheduled ++ * should not be used normally and napi_schedule should be ++ * used instead. ++ * ++ * Use only if the driver really needs to check if a NAPI ++ * is scheduled for example in the context of delayed timer ++ * that can be skipped if a NAPI is already scheduled. ++ * ++ * Return True if NAPI is scheduled, False otherwise. ++ */ ++static inline bool napi_is_scheduled(struct napi_struct *n) ++{ ++ return test_bit(NAPI_STATE_SCHED, &n->state); ++} ++ + bool napi_schedule_prep(struct napi_struct *n); + + /** +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6533,7 +6533,7 @@ static int __napi_poll(struct napi_struc + * accidentally calling ->poll() when NAPI is not scheduled. + */ + work = 0; +- if (test_bit(NAPI_STATE_SCHED, &n->state)) { ++ if (napi_is_scheduled(n)) { + work = n->poll(n, weight); + trace_napi_poll(n, work, weight); + } diff --git a/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch b/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch new file mode 100644 index 0000000000..aa0d730bc8 --- /dev/null +++ b/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch @@ -0,0 +1,77 @@ +From 2d1a42cf7f77cda54dbbee18d00b1200e7bc22aa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:48 +0200 +Subject: [PATCH 1/3] net: stmmac: improve TX timer arm logic + +There is currently a problem with the TX timer getting armed multiple +unnecessary times causing big performance regression on some device that +suffer from heavy handling of hrtimer rearm. + +The use of the TX timer is an old implementation that predates the napi +implementation and the interrupt enable/disable handling. + +Due to stmmac being a very old code, the TX timer was never evaluated +again with this new implementation and was kept there causing +performance regression. The performance regression started to appear +with kernel version 4.19 with 8fce33317023 ("net: stmmac: Rework coalesce +timer and fix multi-queue races") where the timer was reduced to 1ms +causing it to be armed 40 times more than before. + +Decreasing the timer made the problem more present and caused the +regression in the other of 600-700mbps on some device (regression where +this was notice is ipq806x). + +The problem is in the fact that handling the hrtimer on some target is +expensive and recent kernel made the timer armed much more times. +A solution that was proposed was reverting the hrtimer change and use +mod_timer but such solution would still hide the real problem in the +current implementation. + +To fix the regression, apply some additional logic and skip arming the +timer when not needed. + +Arm the timer ONLY if a napi is not already scheduled. Running the timer +is redundant since the same function (stmmac_tx_clean) will run in the +napi TX poll. Also try to cancel any timer if a napi is scheduled to +prevent redundant run of TX call. + +With the following new logic the original performance are restored while +keeping using the hrtimer. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2974,13 +2974,25 @@ static void stmmac_tx_timer_arm(struct s + { + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + u32 tx_coal_timer = priv->tx_coal_timer[queue]; ++ struct stmmac_channel *ch; ++ struct napi_struct *napi; + + if (!tx_coal_timer) + return; + +- hrtimer_start(&tx_q->txtimer, +- STMMAC_COAL_TIMER(tx_coal_timer), +- HRTIMER_MODE_REL); ++ ch = &priv->channel[tx_q->queue_index]; ++ napi = tx_q->xsk_pool ? &ch->rxtx_napi : &ch->tx_napi; ++ ++ /* Arm timer only if napi is not already scheduled. ++ * Try to cancel any timer if napi is scheduled, timer will be armed ++ * again in the next scheduled napi. ++ */ ++ if (unlikely(!napi_is_scheduled(napi))) ++ hrtimer_start(&tx_q->txtimer, ++ STMMAC_COAL_TIMER(tx_coal_timer), ++ HRTIMER_MODE_REL); ++ else ++ hrtimer_try_to_cancel(&tx_q->txtimer); + } + + /** diff --git a/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch new file mode 100644 index 0000000000..95dd24881b --- /dev/null +++ b/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -0,0 +1,96 @@ +From a594166387fe08e6f5a32130c400249a35b298f9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:49 +0200 +Subject: [PATCH 2/3] net: stmmac: move TX timer arm after DMA enable + +Move TX timer arm call after DMA interrupt is enabled again. + +The TX timer arm function changed logic and now is skipped if a napi is +already scheduled. By moving the TX timer arm call after DMA is enabled, +we permit to correctly skip if a DMA interrupt has been fired and a napi +has been scheduled again. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2527,9 +2527,13 @@ static void stmmac_bump_dma_threshold(st + * @priv: driver private structure + * @budget: napi budget limiting this functions packet handling + * @queue: TX queue index ++ * @pending_packets: signal to arm the TX coal timer + * Description: it reclaims the transmit resources after transmission completes. ++ * If some packets still needs to be handled, due to TX coalesce, set ++ * pending_packets to true to make NAPI arm the TX coal timer. + */ +-static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) ++static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, ++ bool *pending_packets) + { + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + unsigned int bytes_compl = 0, pkts_compl = 0; +@@ -2692,7 +2696,7 @@ static int stmmac_tx_clean(struct stmmac + + /* We still have pending packets, let's call for a new scheduling */ + if (tx_q->dirty_tx != tx_q->cur_tx) +- stmmac_tx_timer_arm(priv, queue); ++ *pending_packets = true; + + __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); + +@@ -5488,12 +5492,13 @@ static int stmmac_napi_poll_tx(struct na + struct stmmac_channel *ch = + container_of(napi, struct stmmac_channel, tx_napi); + struct stmmac_priv *priv = ch->priv_data; ++ bool pending_packets = false; + u32 chan = ch->index; + int work_done; + + priv->xstats.napi_poll++; + +- work_done = stmmac_tx_clean(priv, budget, chan); ++ work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets); + work_done = min(work_done, budget); + + if (work_done < budget && napi_complete_done(napi, work_done)) { +@@ -5504,6 +5509,10 @@ static int stmmac_napi_poll_tx(struct na + spin_unlock_irqrestore(&ch->lock, flags); + } + ++ /* TX still have packet to handle, check if we need to arm tx timer */ ++ if (pending_packets) ++ stmmac_tx_timer_arm(priv, chan); ++ + return work_done; + } + +@@ -5512,12 +5521,13 @@ static int stmmac_napi_poll_rxtx(struct + struct stmmac_channel *ch = + container_of(napi, struct stmmac_channel, rxtx_napi); + struct stmmac_priv *priv = ch->priv_data; ++ bool tx_pending_packets = false; + int rx_done, tx_done, rxtx_done; + u32 chan = ch->index; + + priv->xstats.napi_poll++; + +- tx_done = stmmac_tx_clean(priv, budget, chan); ++ tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets); + tx_done = min(tx_done, budget); + + rx_done = stmmac_rx_zc(priv, budget, chan); +@@ -5542,6 +5552,10 @@ static int stmmac_napi_poll_rxtx(struct + spin_unlock_irqrestore(&ch->lock, flags); + } + ++ /* TX still have packet to handle, check if we need to arm tx timer */ ++ if (tx_pending_packets) ++ stmmac_tx_timer_arm(priv, chan); ++ + return min(rxtx_done, budget - 1); + } + diff --git a/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch b/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch new file mode 100644 index 0000000000..bce54eba4f --- /dev/null +++ b/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch @@ -0,0 +1,38 @@ +From 039550960a2235cfe2dfaa773df9f98f8da31a0c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:50 +0200 +Subject: [PATCH 3/3] net: stmmac: increase TX coalesce timer to 5ms + +Commit 8fce33317023 ("net: stmmac: Rework coalesce timer and fix +multi-queue races") decreased the TX coalesce timer from 40ms to 1ms. + +This caused some performance regression on some target (regression was +reported at least on ipq806x) in the order of 600mbps dropping from +gigabit handling to only 200mbps. + +The problem was identified in the TX timer getting armed too much time. +While this was fixed and improved in another commit, performance can be +improved even further by increasing the timer delay a bit moving from +1ms to 5ms. + +The value is a good balance between battery saving by prevending too +much interrupt to be generated and permitting good performance for +internet oriented devices. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/common.h ++++ b/drivers/net/ethernet/stmicro/stmmac/common.h +@@ -287,7 +287,7 @@ struct stmmac_safety_stats { + #define MIN_DMA_RIWT 0x10 + #define DEF_DMA_RIWT 0xa0 + /* Tx coalesce parameters */ +-#define STMMAC_COAL_TX_TIMER 1000 ++#define STMMAC_COAL_TX_TIMER 5000 + #define STMMAC_MAX_COAL_TX_TICK 100000 + #define STMMAC_TX_MAX_FRAMES 256 + #define STMMAC_TX_FRAMES 25 diff --git a/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch b/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch new file mode 100644 index 0000000000..c0320ad6f9 --- /dev/null +++ b/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch @@ -0,0 +1,150 @@ +From cfbd6de588ef659c198083205dc954a6d3ed2aec Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 29 Dec 2022 17:33:35 +0100 +Subject: [PATCH 4/5] net: dsa: qca8k: introduce single mii read/write lo/hi + +It may be useful to read/write just the lo or hi half of a reg. + +This is especially useful for phy poll with the use of mdio master. +The mdio master reg is composed by the first 16 bit related to setup and +the other half with the returned data or data to write. + +Refactor the mii function to permit single mii read/write of lo or hi +half of the reg. + +Tested-by: Ronald Wahl +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 106 ++++++++++++++++++++++++------- + 1 file changed, 84 insertions(+), 22 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -37,42 +37,104 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u + } + + static int +-qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) ++qca8k_mii_write_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) + { + int ret; ++ u16 lo; + +- ret = bus->read(bus, phy_id, regnum); +- if (ret >= 0) { +- *val = ret; +- ret = bus->read(bus, phy_id, regnum + 1); +- *val |= ret << 16; +- } ++ lo = val & 0xffff; ++ ret = bus->write(bus, phy_id, regnum, lo); ++ if (ret < 0) ++ dev_err_ratelimited(&bus->dev, ++ "failed to write qca8k 32bit lo register\n"); ++ ++ return ret; ++} + +- if (ret < 0) { ++static int ++qca8k_mii_write_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) ++{ ++ int ret; ++ u16 hi; ++ ++ hi = (u16)(val >> 16); ++ ret = bus->write(bus, phy_id, regnum, hi); ++ if (ret < 0) + dev_err_ratelimited(&bus->dev, +- "failed to read qca8k 32bit register\n"); +- *val = 0; +- return ret; +- } ++ "failed to write qca8k 32bit hi register\n"); + ++ return ret; ++} ++ ++static int ++qca8k_mii_read_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) ++{ ++ int ret; ++ ++ ret = bus->read(bus, phy_id, regnum); ++ if (ret < 0) ++ goto err; ++ ++ *val = ret & 0xffff; + return 0; ++ ++err: ++ dev_err_ratelimited(&bus->dev, ++ "failed to read qca8k 32bit lo register\n"); ++ *val = 0; ++ ++ return ret; + } + +-static void +-qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) ++static int ++qca8k_mii_read_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + { +- u16 lo, hi; + int ret; + +- lo = val & 0xffff; +- hi = (u16)(val >> 16); ++ ret = bus->read(bus, phy_id, regnum); ++ if (ret < 0) ++ goto err; + +- ret = bus->write(bus, phy_id, regnum, lo); +- if (ret >= 0) +- ret = bus->write(bus, phy_id, regnum + 1, hi); ++ *val = ret << 16; ++ return 0; ++ ++err: ++ dev_err_ratelimited(&bus->dev, ++ "failed to read qca8k 32bit hi register\n"); ++ *val = 0; ++ ++ return ret; ++} ++ ++static int ++qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) ++{ ++ u32 hi, lo; ++ int ret; ++ ++ *val = 0; ++ ++ ret = qca8k_mii_read_lo(bus, phy_id, regnum, &lo); + if (ret < 0) +- dev_err_ratelimited(&bus->dev, +- "failed to write qca8k 32bit register\n"); ++ goto err; ++ ++ ret = qca8k_mii_read_hi(bus, phy_id, regnum + 1, &hi); ++ if (ret < 0) ++ goto err; ++ ++ *val = lo | hi; ++ ++err: ++ return ret; ++} ++ ++static void ++qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) ++{ ++ if (qca8k_mii_write_lo(bus, phy_id, regnum, val) < 0) ++ return; ++ ++ qca8k_mii_write_hi(bus, phy_id, regnum + 1, val); + } + + static int diff --git a/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch b/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch new file mode 100644 index 0000000000..dcafad0fd5 --- /dev/null +++ b/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch @@ -0,0 +1,73 @@ +From a4165830ca237f2b3318faf62562bce8ce12a389 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 29 Dec 2022 17:33:36 +0100 +Subject: [PATCH 5/5] net: dsa: qca8k: improve mdio master read/write by using + single lo/hi + +Improve mdio master read/write by using singe mii read/write lo/hi. + +In a read and write we need to poll the mdio master regs in a busy loop +to check for a specific bit present in the upper half of the reg. We can +ignore the other half since it won't contain useful data. This will save +an additional useless read for each read and write operation. + +In a read operation the returned data is present in the mdio master reg +lower half. We can ignore the other half since it won't contain useful +data. This will save an additional useless read for each read operation. + +In a read operation it's needed to just set the hi half of the mdio +master reg as the lo half will be replaced by the result. This will save +an additional useless write for each read operation. + +Tested-by: Ronald Wahl +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -754,9 +754,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus + + qca8k_split_addr(reg, &r1, &r2, &page); + +- ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, ++ ret = read_poll_timeout(qca8k_mii_read_hi, ret1, !(val & mask), 0, + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- bus, 0x10 | r2, r1, &val); ++ bus, 0x10 | r2, r1 + 1, &val); + + /* Check if qca8k_read has failed for a different reason + * before returnting -ETIMEDOUT +@@ -798,7 +798,7 @@ qca8k_mdio_write(struct qca8k_priv *priv + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); + + mutex_unlock(&bus->mdio_lock); + +@@ -828,18 +828,18 @@ qca8k_mdio_read(struct qca8k_priv *priv, + if (ret) + goto exit; + +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, val); + + ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + if (ret) + goto exit; + +- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); ++ ret = qca8k_mii_read_lo(bus, 0x10 | r2, r1, &val); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); + + mutex_unlock(&bus->mdio_lock); + diff --git a/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch b/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch new file mode 100644 index 0000000000..9331fd536d --- /dev/null +++ b/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch @@ -0,0 +1,63 @@ +From e03cea60c3db8c6b011cc36ecef9281dff8377f3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jan 2023 21:35:16 +0100 +Subject: [PATCH] net: dsa: qca8k: add QCA8K_ATU_TABLE_SIZE define for fdb + access + +Add and use QCA8K_ATU_TABLE_SIZE instead of hardcoding the ATU size with +a pure number and using sizeof on the array. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-common.c | 10 ++++++---- + drivers/net/dsa/qca/qca8k.h | 2 ++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -150,11 +150,12 @@ static int qca8k_busy_wait(struct qca8k_ + + static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) + { +- u32 reg[3]; ++ u32 reg[QCA8K_ATU_TABLE_SIZE]; + int ret; + + /* load the ARL table into an array */ +- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); ++ ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); + if (ret) + return ret; + +@@ -178,7 +179,7 @@ static int qca8k_fdb_read(struct qca8k_p + static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, + const u8 *mac, u8 aging) + { +- u32 reg[3] = { 0 }; ++ u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 }; + + /* vid - 83:72 */ + reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); +@@ -195,7 +196,8 @@ static void qca8k_fdb_write(struct qca8k + reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ +- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); ++ qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); + } + + static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -148,6 +148,8 @@ + #define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 + + /* Lookup registers */ ++#define QCA8K_ATU_TABLE_SIZE 3 /* 12 bytes wide table / sizeof(u32) */ ++ + #define QCA8K_REG_ATU_DATA0 0x600 + #define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24) + #define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16) diff --git a/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch b/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch new file mode 100644 index 0000000000..b8f8071b0a --- /dev/null +++ b/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch @@ -0,0 +1,261 @@ +From c766e077d927e1775902c18827205ea2ade3a35d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jan 2023 21:35:17 +0100 +Subject: [PATCH] net: dsa: qca8k: convert to regmap read/write API + +Convert qca8k to regmap read/write bulk API. The mgmt eth can write up +to 32 bytes of data at times. Currently we use a custom function to do +it but regmap now supports declaration of read/write bulk even without a +bus. + +Drop the custom function and rework the regmap function to this new +implementation. + +Rework the qca8k_fdb_read/write function to use the new +regmap_bulk_read/write as the old qca8k_bulk_read/write are now dropped. + +Cc: Mark Brown +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 92 ++++++++++++++++++++++++------ + drivers/net/dsa/qca/qca8k-common.c | 47 ++------------- + drivers/net/dsa/qca/qca8k.h | 3 - + 3 files changed, 77 insertions(+), 65 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8 + } + + static int +-qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ++qca8k_read_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t *val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; + +- if (!qca8k_read_eth(priv, reg, val, sizeof(*val))) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -451,16 +447,12 @@ exit: + } + + static int +-qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) ++qca8k_write_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; + +- if (!qca8k_write_eth(priv, reg, &val, sizeof(val))) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -477,17 +469,14 @@ exit: + } + + static int +-qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) ++qca8k_regmap_update_bits_mii(struct qca8k_priv *priv, uint32_t reg, ++ uint32_t mask, uint32_t write_val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; + +- if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -510,17 +499,84 @@ exit: + return ret; + } + ++static int ++qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len, ++ void *val_buf, size_t val_len) ++{ ++ int i, count = val_len / sizeof(u32), ret; ++ u32 reg = *(u32 *)reg_buf & U16_MAX; ++ struct qca8k_priv *priv = ctx; ++ ++ if (priv->mgmt_master && ++ !qca8k_read_eth(priv, reg, val_buf, val_len)) ++ return 0; ++ ++ /* loop count times and increment reg of 4 */ ++ for (i = 0; i < count; i++, reg += sizeof(u32)) { ++ ret = qca8k_read_mii(priv, reg, val_buf + i); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len, ++ const void *val_buf, size_t val_len) ++{ ++ int i, count = val_len / sizeof(u32), ret; ++ u32 reg = *(u32 *)reg_buf & U16_MAX; ++ struct qca8k_priv *priv = ctx; ++ u32 *val = (u32 *)val_buf; ++ ++ if (priv->mgmt_master && ++ !qca8k_write_eth(priv, reg, val, val_len)) ++ return 0; ++ ++ /* loop count times, increment reg of 4 and increment val ptr to ++ * the next value ++ */ ++ for (i = 0; i < count; i++, reg += sizeof(u32), val++) { ++ ret = qca8k_write_mii(priv, reg, *val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_bulk_write(void *ctx, const void *data, size_t bytes) ++{ ++ return qca8k_bulk_gather_write(ctx, data, sizeof(u16), data + sizeof(u16), ++ bytes - sizeof(u16)); ++} ++ ++static int ++qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) ++{ ++ struct qca8k_priv *priv = ctx; ++ ++ if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) ++ return 0; ++ ++ return qca8k_regmap_update_bits_mii(priv, reg, mask, write_val); ++} ++ + static struct regmap_config qca8k_regmap_config = { + .reg_bits = 16, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x16ac, /* end MIB - Port6 range */ +- .reg_read = qca8k_regmap_read, +- .reg_write = qca8k_regmap_write, ++ .read = qca8k_bulk_read, ++ .write = qca8k_bulk_write, + .reg_update_bits = qca8k_regmap_update_bits, + .rd_table = &qca8k_readable_table, + .disable_locking = true, /* Locking is handled by qca8k read/write */ + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ ++ .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ ++ .max_raw_write = 32, + }; + + static int +@@ -2112,8 +2168,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, + + static const struct qca8k_info_ops qca8xxx_ops = { + .autocast_mib = qca8k_get_ethtool_stats_eth, +- .read_eth = qca8k_read_eth, +- .write_eth = qca8k_write_eth, + }; + + static const struct qca8k_match_data qca8327 = { +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_r + .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), + }; + +-/* TODO: remove these extra ops when we can support regmap bulk read/write */ +-static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) +-{ +- int i, count = len / sizeof(u32), ret; +- +- if (priv->mgmt_master && priv->info->ops->read_eth && +- !priv->info->ops->read_eth(priv, reg, val, len)) +- return 0; +- +- for (i = 0; i < count; i++) { +- ret = regmap_read(priv->regmap, reg + (i * 4), val + i); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- +-/* TODO: remove these extra ops when we can support regmap bulk read/write */ +-static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len) +-{ +- int i, count = len / sizeof(u32), ret; +- u32 tmp; +- +- if (priv->mgmt_master && priv->info->ops->write_eth && +- !priv->info->ops->write_eth(priv, reg, val, len)) +- return 0; +- +- for (i = 0; i < count; i++) { +- tmp = val[i]; +- +- ret = regmap_write(priv->regmap, reg + (i * 4), tmp); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- + static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { + u32 val; +@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_p + int ret; + + /* load the ARL table into an array */ +- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, +- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); ++ ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE); + if (ret) + return ret; + +@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k + reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ +- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, +- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); ++ regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE); + } + + static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -330,9 +330,6 @@ struct qca8k_priv; + + struct qca8k_info_ops { + int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data); +- /* TODO: remove these extra ops when we can support regmap bulk read/write */ +- int (*read_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); +- int (*write_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); + }; + + struct qca8k_match_data { diff --git a/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch b/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch new file mode 100644 index 0000000000..3619440f07 --- /dev/null +++ b/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch @@ -0,0 +1,78 @@ +From 2c39dd025da489cf87d26469d9f5ff19715324a0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 24 Jul 2023 05:25:28 +0200 +Subject: [PATCH 1/4] net: dsa: qca8k: enable use_single_write for qca8xxx + +The qca8xxx switch supports 2 way to write reg values, a slow way using +mdio and a fast way by sending specially crafted mgmt packet to +read/write reg. + +The fast way can support up to 32 bytes of data as eth packet are used +to send/receive. + +This correctly works for almost the entire regmap of the switch but with +the use of some kernel selftests for dsa drivers it was found a funny +and interesting hw defect/limitation. + +For some specific reg, bulk write won't work and will result in writing +only part of the requested regs resulting in half data written. This was +especially hard to track and discover due to the total strangeness of +the problem and also by the specific regs where this occurs. + +This occurs in the specific regs of the ATU table, where multiple entry +needs to be written to compose the entire entry. +It was discovered that with a bulk write of 12 bytes on +QCA8K_REG_ATU_DATA0 only QCA8K_REG_ATU_DATA0 and QCA8K_REG_ATU_DATA2 +were written, but QCA8K_REG_ATU_DATA1 was always zero. +Tcpdump was used to make sure the specially crafted packet was correct +and this was confirmed. + +The problem was hard to track as the lack of QCA8K_REG_ATU_DATA1 +resulted in an entry somehow possible as the first bytes of the mac +address are set in QCA8K_REG_ATU_DATA0 and the entry type is set in +QCA8K_REG_ATU_DATA2. + +Funlly enough writing QCA8K_REG_ATU_DATA1 results in the same problem +with QCA8K_REG_ATU_DATA2 empty and QCA8K_REG_ATU_DATA1 and +QCA8K_REG_ATU_FUNC correctly written. +A speculation on the problem might be that there are some kind of +indirection internally when accessing these regs and they can't be +accessed all together, due to the fact that it's really a table mapped +somewhere in the switch SRAM. + +Even more funny is the fact that every other reg was tested with all +kind of combination and they are not affected by this problem. Read +operation was also tested and always worked so it's not affected by this +problem. + +The problem is not present if we limit writing a single reg at times. + +To handle this hardware defect, enable use_single_write so that bulk +api can correctly split the write in multiple different operation +effectively reverting to a non-bulk write. + +Cc: Mark Brown +Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") +Signed-off-by: Christian Marangi +Cc: stable@vger.kernel.org +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -575,8 +575,11 @@ static struct regmap_config qca8k_regmap + .rd_table = &qca8k_readable_table, + .disable_locking = true, /* Locking is handled by qca8k read/write */ + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ +- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ +- .max_raw_write = 32, ++ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */ ++ /* ATU regs suffer from a bug where some data are not correctly ++ * written. Disable bulk write to correctly write ATU entry. ++ */ ++ .use_single_write = true, + }; + + static int diff --git a/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch b/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch new file mode 100644 index 0000000000..d31789370e --- /dev/null +++ b/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch @@ -0,0 +1,146 @@ +From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:10 +0200 +Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off + if standalone + +Address learning should initially be turned off by the driver for port +operation in standalone mode, then the DSA core handles changes to it +via ds->ops->port_bridge_flags(). + +Currently this is not the case for qca8k where learning is enabled +unconditionally in qca8k_setup for every user port. + +Handle ports configured in standalone mode by making the learning +configurable and not enabling it by default. + +Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to +enable learning for bridge that request it and tweak +.port_stp_state_set to correctly disable learning when port is +configured in standalone mode. + +Signed-off-by: Christian Marangi +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++-- + drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 6 ++++ + 3 files changed, 58 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1905,9 +1905,8 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- /* Enable ARP Auto-learning by default */ +- ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_LEARN); + if (ret) + return ret; + +@@ -2013,6 +2012,8 @@ static const struct dsa_switch_ops qca8k + .port_change_mtu = qca8k_port_change_mtu, + .port_max_mtu = qca8k_port_max_mtu, + .port_stp_state_set = qca8k_port_stp_state_set, ++ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, ++ .port_bridge_flags = qca8k_port_bridge_flags, + .port_bridge_join = qca8k_port_bridge_join, + .port_bridge_leave = qca8k_port_bridge_leave, + .port_fast_age = qca8k_port_fast_age, +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch + return 0; + } + ++static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, ++ bool learning) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ if (learning) ++ return regmap_set_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ else ++ return regmap_clear_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++} ++ + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); + struct qca8k_priv *priv = ds->priv; ++ bool learning = false; + u32 stp_state; + + switch (state) { +@@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa + break; + case BR_STATE_LEARNING: + stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; ++ learning = dp->learning; + break; + case BR_STATE_FORWARDING: ++ learning = dp->learning; ++ fallthrough; + default: + stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; + break; +@@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa + + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); ++ ++ qca8k_port_configure_learning(ds, port, learning); ++} ++ ++int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ if (flags.mask & ~BR_LEARNING) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ if (flags.mask & BR_LEARNING) { ++ ret = qca8k_port_configure_learning(ds, port, ++ flags.val & BR_LEARNING); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + int qca8k_port_bridge_join(struct dsa_switch *ds, int port, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch + + /* Common bridge function */ + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); ++int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack); ++int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack); + int qca8k_port_bridge_join(struct dsa_switch *ds, int port, + struct dsa_bridge bridge, + bool *tx_fwd_offload, diff --git a/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch b/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch new file mode 100644 index 0000000000..4b457f67de --- /dev/null +++ b/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch @@ -0,0 +1,53 @@ +From 18e8feae4a807994e4906d659116d249bfecd4c5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:11 +0200 +Subject: [PATCH 2/4] net: dsa: qca8k: limit user ports access to the first CPU + port on setup + +In preparation for multi-CPU support, set CPU port LOOKUP MEMBER outside +the port loop and setup the LOOKUP MEMBER mask for user ports only to +the first CPU port. + +This is to handle flooding condition where every CPU port is set as +target and prevent packet duplication for unknown frames from user ports. + +Secondary CPU port LOOKUP MEMBER mask will be setup later when +port_change_master will be implemented. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Reviewed-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20230730074113.21889-3-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1885,18 +1885,16 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ /* CPU port gets connected to all user ports of the switch */ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ if (ret) ++ return ret; ++ + /* Setup connection between CPU port & user ports + * Configure specific switch configuration for ports + */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* CPU port gets connected to all user ports of the switch */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); +- if (ret) +- return ret; +- } +- + /* Individual user ports get connected to CPU port only */ + if (dsa_is_user_port(ds, i)) { + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), diff --git a/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch b/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch new file mode 100644 index 0000000000..f556628b5b --- /dev/null +++ b/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch @@ -0,0 +1,111 @@ +From a9108b0712bf018dc69020864b21485b71b17dfc Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:12 +0200 +Subject: [PATCH 3/4] net: dsa: qca8k: move qca8xxx hol fixup to separate + function + +Move qca8xxx hol fixup to separate function to tidy things up and to +permit using a more efficent loop in future patch. + +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-4-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 78 +++++++++++++++++--------------- + 1 file changed, 42 insertions(+), 36 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1795,6 +1795,46 @@ static int qca8k_connect_tag_protocol(st + return 0; + } + ++static void qca8k_setup_hol_fixup(struct qca8k_priv *priv, int port) ++{ ++ u32 mask; ++ ++ switch (port) { ++ /* The 2 CPU port and port 5 requires some different ++ * priority than any other ports. ++ */ ++ case 0: ++ case 5: ++ case 6: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); ++ break; ++ default: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); ++ } ++ regmap_write(priv->regmap, QCA8K_REG_PORT_HOL_CTRL0(port), mask); ++ ++ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN; ++ regmap_update_bits(priv->regmap, QCA8K_REG_PORT_HOL_CTRL1(port), ++ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN, ++ mask); ++} ++ + static int + qca8k_setup(struct dsa_switch *ds) + { +@@ -1930,42 +1970,8 @@ qca8k_setup(struct dsa_switch *ds) + * missing settings to improve switch stability under load condition. + * This problem is limited to qca8337 and other qca8k switch are not affected. + */ +- if (priv->switch_id == QCA8K_ID_QCA8337) { +- switch (i) { +- /* The 2 CPU port and port 5 requires some different +- * priority than any other ports. +- */ +- case 0: +- case 5: +- case 6: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); +- break; +- default: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); +- } +- qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); +- +- mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN; +- qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), +- QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN, +- mask); +- } ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ qca8k_setup_hol_fixup(priv, i); + } + + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ diff --git a/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch b/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch new file mode 100644 index 0000000000..faa0142ca9 --- /dev/null +++ b/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch @@ -0,0 +1,158 @@ +From 01e6f8ad8d26ced14b0cf288c42e55d03a7c5070 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:13 +0200 +Subject: [PATCH 4/4] net: dsa: qca8k: use dsa_for_each macro instead of for + loop + +Convert for loop to dsa_for_each macro to save some redundant write on +unconnected/unused port and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-5-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 107 ++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 53 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1839,7 +1839,8 @@ static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int cpu_port, ret, i; ++ struct dsa_port *dp; ++ int cpu_port, ret; + u32 mask; + + cpu_port = qca8k_find_cpu_port(ds); +@@ -1890,27 +1891,27 @@ qca8k_setup(struct dsa_switch *ds) + dev_warn(priv->dev, "mib init failed"); + + /* Initial setup of all ports */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ dsa_switch_for_each_port(dp, ds) { + /* Disable forwarding by default on all ports */ +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(dp->index), + QCA8K_PORT_LOOKUP_MEMBER, 0); + if (ret) + return ret; ++ } + +- /* Enable QCA header mode on all cpu ports */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), +- FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | +- FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); +- if (ret) { +- dev_err(priv->dev, "failed enabling QCA header mode"); +- return ret; +- } ++ /* Disable MAC by default on all user ports */ ++ dsa_switch_for_each_user_port(dp, ds) ++ qca8k_port_set_status(priv, dp->index, 0); ++ ++ /* Enable QCA header mode on all cpu ports */ ++ dsa_switch_for_each_cpu_port(dp, ds) { ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(dp->index), ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); ++ return ret; + } +- +- /* Disable MAC by default on all user ports */ +- if (dsa_is_user_port(ds, i)) +- qca8k_port_set_status(priv, i, 0); + } + + /* Forward all unknown frames to CPU port for Linux processing +@@ -1932,48 +1933,48 @@ qca8k_setup(struct dsa_switch *ds) + return ret; + + /* Setup connection between CPU port & user ports +- * Configure specific switch configuration for ports ++ * Individual user ports get connected to CPU port only + */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* Individual user ports get connected to CPU port only */ +- if (dsa_is_user_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, +- BIT(cpu_port)); +- if (ret) +- return ret; +- +- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); +- if (ret) +- return ret; +- +- /* For port based vlans to work we need to set the +- * default egress vid +- */ +- ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), +- QCA8K_EGREES_VLAN_PORT_MASK(i), +- QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); +- if (ret) +- return ret; +- +- ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), +- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | +- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); +- if (ret) +- return ret; +- } ++ dsa_switch_for_each_user_port(dp, ds) { ++ u8 port = dp->index; + +- /* The port 5 of the qca8337 have some problem in flood condition. The +- * original legacy driver had some specific buffer and priority settings +- * for the different port suggested by the QCA switch team. Add this +- * missing settings to improve switch stability under load condition. +- * This problem is limited to qca8337 and other qca8k switch are not affected. ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(cpu_port)); ++ if (ret) ++ return ret; ++ ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; ++ ++ /* For port based vlans to work we need to set the ++ * default egress vid + */ +- if (priv->switch_id == QCA8K_ID_QCA8337) +- qca8k_setup_hol_fixup(priv, i); ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++ QCA8K_EGREES_VLAN_PORT_MASK(port), ++ QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; + } + ++ /* The port 5 of the qca8337 have some problem in flood condition. The ++ * original legacy driver had some specific buffer and priority settings ++ * for the different port suggested by the QCA switch team. Add this ++ * missing settings to improve switch stability under load condition. ++ * This problem is limited to qca8337 and other qca8k switch are not affected. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ dsa_switch_for_each_available_port(dp, ds) ++ qca8k_setup_hol_fixup(priv, dp->index); ++ + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ + if (priv->switch_id == QCA8K_ID_QCA8327) { + mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | diff --git a/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch b/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch new file mode 100644 index 0000000000..632f422d1f --- /dev/null +++ b/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch @@ -0,0 +1,61 @@ +From 5652d1741574eb89cc02576e50ee3e348bd6dd77 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Wed, 4 Oct 2023 11:19:03 +0200 +Subject: [PATCH 1/2] net: dsa: qca8k: fix regmap bulk read/write methods on + big endian systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit c766e077d927 ("net: dsa: qca8k: convert to regmap read/write +API") introduced bulk read/write methods to qca8k's regmap. + +The regmap bulk read/write methods get the register address in a buffer +passed as a void pointer parameter (the same buffer contains also the +read/written values). The register address occupies only as many bytes +as it requires at the beginning of this buffer. For example if the +.reg_bits member in regmap_config is 16 (as is the case for this +driver), the register address occupies only the first 2 bytes in this +buffer, so it can be cast to u16. + +But the original commit implementing these bulk read/write methods cast +the buffer to u32: + u32 reg = *(u32 *)reg_buf & U16_MAX; +taking the first 4 bytes. This works on little endian systems where the +first 2 bytes of the buffer correspond to the low 16-bits, but it +obviously cannot work on big endian systems. + +Fix this by casting the beginning of the buffer to u16 as + u32 reg = *(u16 *)reg_buf; + +Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") +Signed-off-by: Marek Behún +Tested-by: Christian Marangi +Reviewed-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -504,8 +504,8 @@ qca8k_bulk_read(void *ctx, const void *r + void *val_buf, size_t val_len) + { + int i, count = val_len / sizeof(u32), ret; +- u32 reg = *(u32 *)reg_buf & U16_MAX; + struct qca8k_priv *priv = ctx; ++ u32 reg = *(u16 *)reg_buf; + + if (priv->mgmt_master && + !qca8k_read_eth(priv, reg, val_buf, val_len)) +@@ -526,8 +526,8 @@ qca8k_bulk_gather_write(void *ctx, const + const void *val_buf, size_t val_len) + { + int i, count = val_len / sizeof(u32), ret; +- u32 reg = *(u32 *)reg_buf & U16_MAX; + struct qca8k_priv *priv = ctx; ++ u32 reg = *(u16 *)reg_buf; + u32 *val = (u32 *)val_buf; + + if (priv->mgmt_master && diff --git a/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch b/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch new file mode 100644 index 0000000000..8010076fc0 --- /dev/null +++ b/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch @@ -0,0 +1,514 @@ +From patchwork Thu Mar 9 10:57:44 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13167235 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +Date: Thu, 9 Mar 2023 10:57:44 +0000 +From: Daniel Golle +To: netdev@vger.kernel.org, linux-mediatek@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, + Russell King , + Heiner Kallweit , + Lorenzo Bianconi , + Mark Lee , + John Crispin , Felix Fietkau , + AngeloGioacchino Del Regno + , + Matthias Brugger , + DENG Qingfang , + Landen Chao , + Sean Wang , + Paolo Abeni , + Jakub Kicinski , + Eric Dumazet , + "David S. Miller" , + Vladimir Oltean , + Florian Fainelli , + Andrew Lunn , + Vladimir Oltean +Cc: =?iso-8859-1?q?Bj=F8rn?= Mork , + Frank Wunderlich , + Alexander Couzens +Subject: [PATCH net-next v13 11/16] net: dsa: mt7530: use external PCS driver +Message-ID: + <2ac2ee40d3b0e705461b50613fda6a7edfdbc4b3.1678357225.git.daniel@makrotopia.org> +References: +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +Implement regmap access wrappers, for now only to be used by the +pcs-mtk driver. +Make use of external PCS driver and drop the reduntant implementation +in mt7530.c. +As a nice side effect the SGMII registers can now also more easily be +inspected for debugging via /sys/kernel/debug/regmap. + +Reviewed-by: Russell King (Oracle) +Tested-by: Bjørn Mork +Signed-off-by: Daniel Golle +Tested-by: Frank Wunderlich +--- + drivers/net/dsa/Kconfig | 1 + + drivers/net/dsa/mt7530.c | 277 ++++++++++----------------------------- + drivers/net/dsa/mt7530.h | 47 +------ + 3 files changed, 71 insertions(+), 254 deletions(-) + +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -37,6 +37,7 @@ config NET_DSA_MT7530 + tristate "MediaTek MT753x and MT7621 Ethernet switch support" + select NET_DSA_TAG_MTK + select MEDIATEK_GE_PHY ++ select PCS_MTK_LYNXI + help + This enables support for the MediaTek MT7530, MT7531, and MT7621 + Ethernet switch chips. +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2615,128 +2616,11 @@ static int mt7531_rgmii_setup(struct mt7 + return 0; + } + +-static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, +- phy_interface_t interface, int speed, int duplex) +-{ +- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; +- int port = pcs_to_mt753x_pcs(pcs)->port; +- unsigned int val; +- +- /* For adjusting speed and duplex of SGMII force mode. */ +- if (interface != PHY_INTERFACE_MODE_SGMII || +- phylink_autoneg_inband(mode)) +- return; +- +- /* SGMII force mode setting */ +- val = mt7530_read(priv, MT7531_SGMII_MODE(port)); +- val &= ~MT7531_SGMII_IF_MODE_MASK; +- +- switch (speed) { +- case SPEED_10: +- val |= MT7531_SGMII_FORCE_SPEED_10; +- break; +- case SPEED_100: +- val |= MT7531_SGMII_FORCE_SPEED_100; +- break; +- case SPEED_1000: +- val |= MT7531_SGMII_FORCE_SPEED_1000; +- break; +- } +- +- /* MT7531 SGMII 1G force mode can only work in full duplex mode, +- * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. +- * +- * The speed check is unnecessary as the MAC capabilities apply +- * this restriction. --rmk +- */ +- if ((speed == SPEED_10 || speed == SPEED_100) && +- duplex != DUPLEX_FULL) +- val |= MT7531_SGMII_FORCE_HALF_DUPLEX; +- +- mt7530_write(priv, MT7531_SGMII_MODE(port), val); +-} +- + static bool mt753x_is_mac_port(u32 port) + { + return (port == 5 || port == 6); + } + +-static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, +- phy_interface_t interface) +-{ +- u32 val; +- +- if (!mt753x_is_mac_port(port)) +- return -EINVAL; +- +- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), +- MT7531_SGMII_PHYA_PWD); +- +- val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); +- val &= ~MT7531_RG_TPHY_SPEED_MASK; +- /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B +- * encoding. +- */ +- val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ? +- MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G; +- mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); +- +- mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); +- +- /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex +- * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. +- */ +- mt7530_rmw(priv, MT7531_SGMII_MODE(port), +- MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS, +- MT7531_SGMII_FORCE_SPEED_1000); +- +- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); +- +- return 0; +-} +- +-static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, +- phy_interface_t interface) +-{ +- if (!mt753x_is_mac_port(port)) +- return -EINVAL; +- +- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), +- MT7531_SGMII_PHYA_PWD); +- +- mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), +- MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G); +- +- mt7530_set(priv, MT7531_SGMII_MODE(port), +- MT7531_SGMII_REMOTE_FAULT_DIS | +- MT7531_SGMII_SPEED_DUPLEX_AN); +- +- mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port), +- MT7531_SGMII_TX_CONFIG_MASK, 1); +- +- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); +- +- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART); +- +- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); +- +- return 0; +-} +- +-static void mt7531_pcs_an_restart(struct phylink_pcs *pcs) +-{ +- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; +- int port = pcs_to_mt753x_pcs(pcs)->port; +- u32 val; +- +- /* Only restart AN when AN is enabled */ +- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); +- if (val & MT7531_SGMII_AN_ENABLE) { +- val |= MT7531_SGMII_AN_RESTART; +- mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); +- } +-} +- + static int + mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) +@@ -2759,11 +2643,11 @@ mt7531_mac_config(struct dsa_switch *ds, + phydev = dp->slave->phydev; + return mt7531_rgmii_setup(priv, port, interface, phydev); + case PHY_INTERFACE_MODE_SGMII: +- return mt7531_sgmii_setup_mode_an(priv, port, interface); + case PHY_INTERFACE_MODE_NA: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- return mt7531_sgmii_setup_mode_force(priv, port, interface); ++ /* handled in SGMII PCS driver */ ++ return 0; + default: + return -EINVAL; + } +@@ -2788,11 +2672,11 @@ mt753x_phylink_mac_select_pcs(struct dsa + + switch (interface) { + case PHY_INTERFACE_MODE_TRGMII: ++ return &priv->pcs[port].pcs; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- return &priv->pcs[port].pcs; +- ++ return priv->ports[port].sgmii_pcs; + default: + return NULL; + } +@@ -3033,86 +2917,6 @@ static void mt7530_pcs_get_state(struct + state->pause |= MLO_PAUSE_TX; + } + +-static int +-mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, +- struct phylink_link_state *state) +-{ +- u32 status, val; +- u16 config_reg; +- +- status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); +- state->link = !!(status & MT7531_SGMII_LINK_STATUS); +- state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE); +- if (state->interface == PHY_INTERFACE_MODE_SGMII && +- (status & MT7531_SGMII_AN_ENABLE)) { +- val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port)); +- config_reg = val >> 16; +- +- switch (config_reg & LPA_SGMII_SPD_MASK) { +- case LPA_SGMII_1000: +- state->speed = SPEED_1000; +- break; +- case LPA_SGMII_100: +- state->speed = SPEED_100; +- break; +- case LPA_SGMII_10: +- state->speed = SPEED_10; +- break; +- default: +- dev_err(priv->dev, "invalid sgmii PHY speed\n"); +- state->link = false; +- return -EINVAL; +- } +- +- if (config_reg & LPA_SGMII_FULL_DUPLEX) +- state->duplex = DUPLEX_FULL; +- else +- state->duplex = DUPLEX_HALF; +- } +- +- return 0; +-} +- +-static void +-mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port, +- struct phylink_link_state *state) +-{ +- unsigned int val; +- +- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); +- state->link = !!(val & MT7531_SGMII_LINK_STATUS); +- if (!state->link) +- return; +- +- state->an_complete = state->link; +- +- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) +- state->speed = SPEED_2500; +- else +- state->speed = SPEED_1000; +- +- state->duplex = DUPLEX_FULL; +- state->pause = MLO_PAUSE_NONE; +-} +- +-static void mt7531_pcs_get_state(struct phylink_pcs *pcs, +- struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; +- int port = pcs_to_mt753x_pcs(pcs)->port; +- +- if (state->interface == PHY_INTERFACE_MODE_SGMII) { +- mt7531_sgmii_pcs_get_state_an(priv, port, state); +- return; +- } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) || +- (state->interface == PHY_INTERFACE_MODE_2500BASEX)) { +- mt7531_sgmii_pcs_get_state_inband(priv, port, state); +- return; +- } +- +- state->link = false; +-} +- + static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, + const unsigned long *advertising, +@@ -3132,18 +2936,57 @@ static const struct phylink_pcs_ops mt75 + .pcs_an_restart = mt7530_pcs_an_restart, + }; + +-static const struct phylink_pcs_ops mt7531_pcs_ops = { +- .pcs_validate = mt753x_pcs_validate, +- .pcs_get_state = mt7531_pcs_get_state, +- .pcs_config = mt753x_pcs_config, +- .pcs_an_restart = mt7531_pcs_an_restart, +- .pcs_link_up = mt7531_pcs_link_up, ++static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ struct mt7530_priv *priv = context; ++ ++ *val = mt7530_read(priv, reg); ++ return 0; ++}; ++ ++static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) ++{ ++ struct mt7530_priv *priv = context; ++ ++ mt7530_write(priv, reg, val); ++ return 0; ++}; ++ ++static int mt7530_regmap_update_bits(void *context, unsigned int reg, ++ unsigned int mask, unsigned int val) ++{ ++ struct mt7530_priv *priv = context; ++ ++ mt7530_rmw(priv, reg, mask, val); ++ return 0; ++}; ++ ++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, ++}; ++ ++#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 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)), + }; + + static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; ++ struct regmap *regmap; + int i, ret; + + /* Initialise the PCS devices */ +@@ -3151,8 +2994,6 @@ mt753x_setup(struct dsa_switch *ds) + priv->pcs[i].pcs.ops = priv->info->pcs_ops; + priv->pcs[i].priv = priv; + priv->pcs[i].port = i; +- if (mt753x_is_mac_port(i)) +- priv->pcs[i].pcs.poll = 1; + } + + ret = priv->info->sw_setup(ds); +@@ -3167,6 +3008,16 @@ 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); ++ } ++ + return ret; + } + +@@ -3258,7 +3109,7 @@ static const struct mt753x_info mt753x_t + }, + [ID_MT7531] = { + .id = ID_MT7531, +- .pcs_ops = &mt7531_pcs_ops, ++ .pcs_ops = &mt7530_pcs_ops, + .sw_setup = mt7531_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, +@@ -3366,7 +3217,7 @@ static void + mt7530_remove(struct mdio_device *mdiodev) + { + struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); +- int ret = 0; ++ int ret = 0, i; + + if (!priv) + return; +@@ -3385,6 +3236,10 @@ mt7530_remove(struct mdio_device *mdiode + mt7530_free_irq(priv); + + dsa_unregister_switch(priv->ds); ++ ++ for (i = 0; i < 2; ++i) ++ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); ++ + mutex_destroy(&priv->reg_mutex); + } + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -371,47 +371,8 @@ enum mt7530_vlan_port_acc_frm { + CCR_TX_OCT_CNT_BAD) + + /* MT7531 SGMII register group */ +-#define MT7531_SGMII_REG_BASE 0x5000 +-#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ +- ((p) - 5) * 0x1000 + (r)) +- +-/* Register forSGMII PCS_CONTROL_1 */ +-#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) +-#define MT7531_SGMII_LINK_STATUS BIT(18) +-#define MT7531_SGMII_AN_ENABLE BIT(12) +-#define MT7531_SGMII_AN_RESTART BIT(9) +-#define MT7531_SGMII_AN_COMPLETE BIT(21) +- +-/* Register for SGMII PCS_SPPED_ABILITY */ +-#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08) +-#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0) +-#define MT7531_SGMII_TX_CONFIG BIT(0) +- +-/* Register for SGMII_MODE */ +-#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) +-#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) +-#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) +-#define MT7531_SGMII_FORCE_DUPLEX BIT(4) +-#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2) +-#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) +-#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) +-#define MT7531_SGMII_FORCE_SPEED_10 0 +-#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1) +- +-enum mt7531_sgmii_force_duplex { +- MT7531_SGMII_FORCE_FULL_DUPLEX = 0, +- MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10, +-}; +- +-/* Fields of QPHY_PWR_STATE_CTRL */ +-#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) +-#define MT7531_SGMII_PHYA_PWD BIT(4) +- +-/* Values of SGMII SPEED */ +-#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) +-#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) +-#define MT7531_RG_TPHY_SPEED_1_25G 0x0 +-#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) ++#define MT7531_SGMII_REG_BASE(p) (0x5000 + ((p) - 5) * 0x1000) ++#define MT7531_PHYA_CTRL_SIGNAL3 0x128 + + /* Register for system reset */ + #define MT7530_SYS_CTRL 0x7000 +@@ -710,13 +671,13 @@ struct mt7530_fdb { + * @pm: The matrix used to show all connections with the port. + * @pvid: The VLAN specified is to be considered a PVID at ingress. Any + * untagged frames will be assigned to the related VLAN. +- * @vlan_filtering: The flags indicating whether the port that can recognize +- * VLAN-tagged frames. ++ * @sgmii_pcs: Pointer to PCS instance for SerDes ports + */ + struct mt7530_port { + bool enable; + u32 pm; + u16 pvid; ++ struct phylink_pcs *sgmii_pcs; + }; + + /* Port 5 interface select definitions */ diff --git a/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch b/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch new file mode 100644 index 0000000000..4d024b063a --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch @@ -0,0 +1,32 @@ +From c3552d3f85f06cf4b4818bd84c4fcc09d8d45165 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:19 +0100 +Subject: [PATCH 01/13] 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-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch b/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch new file mode 100644 index 0000000000..5667449296 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch @@ -0,0 +1,111 @@ +From b896355fc4988216d4f38582d07add9252a795ae Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:30 +0100 +Subject: [PATCH 02/13] 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 +@@ -2968,26 +2968,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 */ +@@ -3009,15 +3039,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-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch b/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch new file mode 100644 index 0000000000..3b4689fb19 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch @@ -0,0 +1,74 @@ +From 33396408776385f3d2f6069646169a6b5b28e3b3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:40 +0100 +Subject: [PATCH 03/13] 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 +@@ -2941,7 +2941,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; + }; + +@@ -2949,23 +2949,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 +@@ -2991,6 +2993,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-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch b/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch new file mode 100644 index 0000000000..04033f14f4 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch @@ -0,0 +1,224 @@ +From 743cba4345cb366248f9d375c6a9e50243dc0677 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:52 +0100 +Subject: [PATCH 04/13] 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 +@@ -2937,22 +2958,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) + { +@@ -2965,7 +2970,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, + }; +@@ -2998,7 +3003,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); +@@ -3163,6 +3168,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; + +@@ -3242,6 +3248,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 +@@ -754,6 +754,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 +@@ -774,6 +775,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-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch b/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch new file mode 100644 index 0000000000..6c5bebdd80 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch @@ -0,0 +1,54 @@ +From f3cf1d06e2aef644b426c23b4bb570780b1f8d47 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:04 +0100 +Subject: [PATCH 05/13] 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 +@@ -3049,12 +3049,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; + } + +@@ -3171,6 +3165,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; + +@@ -3263,6 +3258,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-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch b/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch new file mode 100644 index 0000000000..a8933d2cf4 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch @@ -0,0 +1,273 @@ +From e4729ae7c095c0c87794bff47ea43e35d69de986 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:16 +0100 +Subject: [PATCH 06/13] 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; + } +@@ -1125,7 +1125,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; + +@@ -1136,7 +1135,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; +@@ -1157,7 +1156,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; + } +@@ -1958,10 +1957,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) { +@@ -1997,7 +1996,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 +@@ -2006,7 +2005,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-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch b/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch new file mode 100644 index 0000000000..6c68dc0c4f --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch @@ -0,0 +1,75 @@ +From 0d7ae94a0c581f86939bebec0b6ccd66e640d1d8 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:28 +0100 +Subject: [PATCH 07/13] 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 +@@ -689,24 +689,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-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch b/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch new file mode 100644 index 0000000000..dc4fcb6aa1 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch @@ -0,0 +1,155 @@ +From 4d632005c90e253c000d0db73b7cdb9d8dc2e2dd Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:39 +0100 +Subject: [PATCH 08/13] 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 +@@ -3177,44 +3177,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; + +@@ -3228,23 +3205,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)) { +@@ -3253,12 +3260,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-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch b/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch new file mode 100644 index 0000000000..5df859d2df --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch @@ -0,0 +1,54 @@ +From 69b838d2629e6b82bcd9e0ab3c1c03f46e5e01d3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:50 +0100 +Subject: [PATCH 09/13] 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 +@@ -3295,6 +3295,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); +@@ -3313,15 +3324,10 @@ 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); + } + + static void mt7530_shutdown(struct mdio_device *mdiodev) diff --git a/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch new file mode 100644 index 0000000000..d203711884 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -0,0 +1,691 @@ +From 8eceed6dbd74067dbf4d8e39f14734f4d2f35176 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:13 +0100 +Subject: [PATCH 10/13] 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 | 16 +- + 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, 301 insertions(+), 258 deletions(-) + create mode 100644 drivers/net/dsa/mt7530-mdio.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -13062,6 +13062,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_RZN1_A5PSW) += rzn1_a5psw.o + obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.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) + { +@@ -2975,72 +2926,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) + { +@@ -3099,7 +2984,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, +@@ -3133,8 +3018,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, +@@ -3167,16 +3053,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; +@@ -3213,88 +3092,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) +@@ -3304,55 +3104,7 @@ 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); +-} +- +-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); ++EXPORT_SYMBOL_GPL(mt7530_remove_common); + + MODULE_AUTHOR("Sean Wang "); + MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -814,4 +814,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-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch b/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch new file mode 100644 index 0000000000..01011ed1a0 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch @@ -0,0 +1,47 @@ +From a52cadbf76593f8fcb2f4f62cb006e3f2a22ad06 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:28 +0100 +Subject: [PATCH 11/13] 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-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch new file mode 100644 index 0000000000..63bf0e77fa --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -0,0 +1,421 @@ +From b361015763fedea439f13b336b15ef7bdf1f7d4f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:40 +0100 +Subject: [PATCH 12/13] 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 | 135 +++++++++++++++++++++++++++++++++- + drivers/net/dsa/mt7530.h | 12 +-- + 6 files changed, 253 insertions(+), 10 deletions(-) + create mode 100644 drivers/net/dsa/mt7530-mmio.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -13060,9 +13060,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_RZN1_A5PSW) += rzn1_a5psw.o + obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.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 +@@ -2005,6 +2005,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; +@@ -2038,8 +2079,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; +@@ -2538,6 +2586,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) + { +@@ -2614,6 +2681,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) + { +@@ -2683,7 +2761,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 */ +@@ -2761,7 +2840,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; +@@ -2841,6 +2921,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) + { +@@ -2986,6 +3081,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, +@@ -3054,6 +3170,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*/ +@@ -302,9 +303,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-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch b/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch new file mode 100644 index 0000000000..5b5f25e7af --- /dev/null +++ b/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch @@ -0,0 +1,118 @@ +From eb1dd407b4be7ca38166a38c56c8edf52c6a399f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 16 Apr 2023 13:08:14 +0100 +Subject: [PATCH 13/13] 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 +@@ -3048,6 +3048,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 +@@ -748,10 +748,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; +@@ -770,7 +770,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*/ +@@ -778,6 +777,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-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch new file mode 100644 index 0000000000..4cdd67cdcc --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -0,0 +1,1724 @@ +From 70479a40954cf353e87a486997a3477108c75aa9 Mon Sep 17 00:00:00 2001 +From: Frank +Date: Fri, 28 Oct 2022 17:26:21 +0800 +Subject: [PATCH] net: phy: Add driver for Motorcomm yt8521 gigabit ethernet + phy + +Add a driver for the motorcomm yt8521 gigabit ethernet phy. We have verified + the driver on StarFive VisionFive development board, which is developed by + Shanghai StarFive Technology Co., Ltd.. On the board, yt8521 gigabit ethernet + phy works in utp mode, RGMII interface, supports 1000M/100M/10M speeds, and + wol(magic package). + +Signed-off-by: Frank +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + MAINTAINERS | 1 + + drivers/net/phy/Kconfig | 2 +- + drivers/net/phy/motorcomm.c | 1635 ++++++++++++++++++++++++++++++++++- + 3 files changed, 1635 insertions(+), 3 deletions(-) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h + + MOTORCOMM PHY DRIVER + M: Peter Geis ++M: Frank + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/phy/motorcomm.c +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY + tristate "Motorcomm PHYs" + help + Enables support for Motorcomm network PHYs. +- Currently supports the YT8511 gigabit PHY. ++ Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. + + config NATIONAL_PHY + tristate "National Semiconductor PHYs" +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1,15 +1,106 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Driver for Motorcomm PHYs ++ * Motorcomm 8511/8521 PHY driver. + * + * Author: Peter Geis ++ * Author: Frank + */ + ++#include + #include + #include + #include + + #define PHY_ID_YT8511 0x0000010a ++#define PHY_ID_YT8521 0x0000011A ++ ++/* YT8521 Register Overview ++ * UTP Register space | FIBER Register space ++ * ------------------------------------------------------------ ++ * | UTP MII | FIBER MII | ++ * | UTP MMD | | ++ * | UTP Extended | FIBER Extended | ++ * ------------------------------------------------------------ ++ * | Common Extended | ++ * ------------------------------------------------------------ ++ */ ++ ++/* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */ ++ ++/* Specific Function Control Register */ ++#define YTPHY_SPECIFIC_FUNCTION_CONTROL_REG 0x10 ++ ++/* 2b00 Manual MDI configuration ++ * 2b01 Manual MDIX configuration ++ * 2b10 Reserved ++ * 2b11 Enable automatic crossover for all modes *default* ++ */ ++#define YTPHY_SFCR_MDI_CROSSOVER_MODE_MASK (BIT(6) | BIT(5)) ++#define YTPHY_SFCR_CROSSOVER_EN BIT(3) ++#define YTPHY_SFCR_SQE_TEST_EN BIT(2) ++#define YTPHY_SFCR_POLARITY_REVERSAL_EN BIT(1) ++#define YTPHY_SFCR_JABBER_DIS BIT(0) ++ ++/* Specific Status Register */ ++#define YTPHY_SPECIFIC_STATUS_REG 0x11 ++#define YTPHY_SSR_SPEED_MODE_OFFSET 14 ++ ++#define YTPHY_SSR_SPEED_MODE_MASK (BIT(15) | BIT(14)) ++#define YTPHY_SSR_SPEED_10M 0x0 ++#define YTPHY_SSR_SPEED_100M 0x1 ++#define YTPHY_SSR_SPEED_1000M 0x2 ++#define YTPHY_SSR_DUPLEX_OFFSET 13 ++#define YTPHY_SSR_DUPLEX BIT(13) ++#define YTPHY_SSR_PAGE_RECEIVED BIT(12) ++#define YTPHY_SSR_SPEED_DUPLEX_RESOLVED BIT(11) ++#define YTPHY_SSR_LINK BIT(10) ++#define YTPHY_SSR_MDIX_CROSSOVER BIT(6) ++#define YTPHY_SSR_DOWNGRADE BIT(5) ++#define YTPHY_SSR_TRANSMIT_PAUSE BIT(3) ++#define YTPHY_SSR_RECEIVE_PAUSE BIT(2) ++#define YTPHY_SSR_POLARITY BIT(1) ++#define YTPHY_SSR_JABBER BIT(0) ++ ++/* Interrupt enable Register */ ++#define YTPHY_INTERRUPT_ENABLE_REG 0x12 ++#define YTPHY_IER_WOL BIT(6) ++ ++/* Interrupt Status Register */ ++#define YTPHY_INTERRUPT_STATUS_REG 0x13 ++#define YTPHY_ISR_AUTONEG_ERR BIT(15) ++#define YTPHY_ISR_SPEED_CHANGED BIT(14) ++#define YTPHY_ISR_DUPLEX_CHANGED BIT(13) ++#define YTPHY_ISR_PAGE_RECEIVED BIT(12) ++#define YTPHY_ISR_LINK_FAILED BIT(11) ++#define YTPHY_ISR_LINK_SUCCESSED BIT(10) ++#define YTPHY_ISR_WOL BIT(6) ++#define YTPHY_ISR_WIRESPEED_DOWNGRADE BIT(5) ++#define YTPHY_ISR_SERDES_LINK_FAILED BIT(3) ++#define YTPHY_ISR_SERDES_LINK_SUCCESSED BIT(2) ++#define YTPHY_ISR_POLARITY_CHANGED BIT(1) ++#define YTPHY_ISR_JABBER_HAPPENED BIT(0) ++ ++/* Speed Auto Downgrade Control Register */ ++#define YTPHY_SPEED_AUTO_DOWNGRADE_CONTROL_REG 0x14 ++#define YTPHY_SADCR_SPEED_DOWNGRADE_EN BIT(5) ++ ++/* If these bits are set to 3, the PHY attempts five times ( 3(set value) + ++ * additional 2) before downgrading, default 0x3 ++ */ ++#define YTPHY_SADCR_SPEED_RETRY_LIMIT (0x3 << 2) ++ ++/* Rx Error Counter Register */ ++#define YTPHY_RX_ERROR_COUNTER_REG 0x15 ++ ++/* Extended Register's Address Offset Register */ ++#define YTPHY_PAGE_SELECT 0x1E ++ ++/* Extended Register's Data Register */ ++#define YTPHY_PAGE_DATA 0x1F ++ ++/* FIBER Auto-Negotiation link partner ability */ ++#define YTPHY_FLPA_PAUSE (0x3 << 7) ++#define YTPHY_FLPA_ASYM_PAUSE (0x2 << 7) + + #define YT8511_PAGE_SELECT 0x1e + #define YT8511_PAGE 0x1f +@@ -38,6 +129,352 @@ + #define YT8511_DELAY_FE_TX_EN (0xf << 12) + #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) + ++/* Extended register is different from MMD Register and MII Register. ++ * We can use ytphy_read_ext/ytphy_write_ext/ytphy_modify_ext function to ++ * operate extended register. ++ * Extended Register start ++ */ ++ ++/* Phy gmii clock gating Register */ ++#define YT8521_CLOCK_GATING_REG 0xC ++#define YT8521_CGR_RX_CLK_EN BIT(12) ++ ++#define YT8521_EXTREG_SLEEP_CONTROL1_REG 0x27 ++#define YT8521_ESC1R_SLEEP_SW BIT(15) ++#define YT8521_ESC1R_PLLON_SLP BIT(14) ++ ++/* Phy fiber Link timer cfg2 Register */ ++#define YT8521_LINK_TIMER_CFG2_REG 0xA5 ++#define YT8521_LTCR_EN_AUTOSEN BIT(15) ++ ++/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers ++ * of yt8521 phy. There is no need to switch reg space when operating these ++ * registers. ++ */ ++ ++#define YT8521_REG_SPACE_SELECT_REG 0xA000 ++#define YT8521_RSSR_SPACE_MASK BIT(1) ++#define YT8521_RSSR_FIBER_SPACE (0x1 << 1) ++#define YT8521_RSSR_UTP_SPACE (0x0 << 1) ++#define YT8521_RSSR_TO_BE_ARBITRATED (0xFF) ++ ++#define YT8521_CHIP_CONFIG_REG 0xA001 ++#define YT8521_CCR_SW_RST BIT(15) ++ ++#define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) ++#define YT8521_CCR_MODE_UTP_TO_RGMII 0 ++#define YT8521_CCR_MODE_FIBER_TO_RGMII 1 ++#define YT8521_CCR_MODE_UTP_FIBER_TO_RGMII 2 ++#define YT8521_CCR_MODE_UTP_TO_SGMII 3 ++#define YT8521_CCR_MODE_SGPHY_TO_RGMAC 4 ++#define YT8521_CCR_MODE_SGMAC_TO_RGPHY 5 ++#define YT8521_CCR_MODE_UTP_TO_FIBER_AUTO 6 ++#define YT8521_CCR_MODE_UTP_TO_FIBER_FORCE 7 ++ ++/* 3 phy polling modes,poll mode combines utp and fiber mode*/ ++#define YT8521_MODE_FIBER 0x1 ++#define YT8521_MODE_UTP 0x2 ++#define YT8521_MODE_POLL 0x3 ++ ++#define YT8521_RGMII_CONFIG1_REG 0xA003 ++ ++/* TX Gig-E Delay is bits 3:0, default 0x1 ++ * TX Fast-E Delay is bits 7:4, default 0xf ++ * RX Delay is bits 13:10, default 0x0 ++ * Delay = 150ps * N ++ * On = 2250ps, off = 0ps ++ */ ++#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) ++#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) ++#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) ++#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) ++#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) ++#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) ++#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) ++#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) ++#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) ++ ++#define YTPHY_MISC_CONFIG_REG 0xA006 ++#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) ++#define YTPHY_MCR_FIBER_1000BX (0x1 << 0) ++#define YTPHY_MCR_FIBER_100FX (0x0 << 0) ++ ++/* WOL MAC ADDR: MACADDR2(highest), MACADDR1(middle), MACADDR0(lowest) */ ++#define YTPHY_WOL_MACADDR2_REG 0xA007 ++#define YTPHY_WOL_MACADDR1_REG 0xA008 ++#define YTPHY_WOL_MACADDR0_REG 0xA009 ++ ++#define YTPHY_WOL_CONFIG_REG 0xA00A ++#define YTPHY_WCR_INTR_SEL BIT(6) ++#define YTPHY_WCR_ENABLE BIT(3) ++ ++/* 2b00 84ms ++ * 2b01 168ms *default* ++ * 2b10 336ms ++ * 2b11 672ms ++ */ ++#define YTPHY_WCR_PULSE_WIDTH_MASK (BIT(2) | BIT(1)) ++#define YTPHY_WCR_PULSE_WIDTH_672MS (BIT(2) | BIT(1)) ++ ++/* 1b0 Interrupt and WOL events is level triggered and active LOW *default* ++ * 1b1 Interrupt and WOL events is pulse triggered and active LOW ++ */ ++#define YTPHY_WCR_TYPE_PULSE BIT(0) ++ ++/* Extended Register end */ ++ ++struct yt8521_priv { ++ /* combo_advertising is used for case of YT8521 in combo mode, ++ * this means that yt8521 may work in utp or fiber mode which depends ++ * on which media is connected (YT8521_RSSR_TO_BE_ARBITRATED). ++ */ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(combo_advertising); ++ ++ /* YT8521_MODE_FIBER / YT8521_MODE_UTP / YT8521_MODE_POLL*/ ++ u8 polling_mode; ++ u8 strap_mode; /* 8 working modes */ ++ /* current reg page of yt8521 phy: ++ * YT8521_RSSR_UTP_SPACE ++ * YT8521_RSSR_FIBER_SPACE ++ * YT8521_RSSR_TO_BE_ARBITRATED ++ */ ++ u8 reg_page; ++}; ++ ++/** ++ * ytphy_read_ext() - read a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to read ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns the value of regnum reg or negative error code ++ */ ++static int ytphy_read_ext(struct phy_device *phydev, u16 regnum) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); ++ if (ret < 0) ++ return ret; ++ ++ return __phy_read(phydev, YTPHY_PAGE_DATA); ++} ++ ++/** ++ * ytphy_read_ext_with_lock() - read a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to read ++ * ++ * returns the value of regnum reg or negative error code ++ */ ++static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = ytphy_read_ext(phydev, regnum); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++/** ++ * ytphy_write_ext() - write a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative error code ++ */ ++static int ytphy_write_ext(struct phy_device *phydev, u16 regnum, u16 val) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); ++ if (ret < 0) ++ return ret; ++ ++ return __phy_write(phydev, YTPHY_PAGE_DATA, val); ++} ++ ++/** ++ * ytphy_write_ext_with_lock() - write a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * returns 0 or negative error code ++ */ ++static int ytphy_write_ext_with_lock(struct phy_device *phydev, u16 regnum, ++ u16 val) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = ytphy_write_ext(phydev, regnum, val); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++/** ++ * ytphy_modify_ext() - bits modify a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * NOTE: Convenience function which allows a PHY's extended register to be ++ * modified as new register value = (old register value & ~mask) | set. ++ * The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative error code ++ */ ++static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, ++ u16 set) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); ++ if (ret < 0) ++ return ret; ++ ++ return __phy_modify(phydev, YTPHY_PAGE_DATA, mask, set); ++} ++ ++/** ++ * ytphy_modify_ext_with_lock() - bits modify a PHY's extended register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * NOTE: Convenience function which allows a PHY's extended register to be ++ * modified as new register value = (old register value & ~mask) | set. ++ * ++ * returns 0 or negative error code ++ */ ++static int ytphy_modify_ext_with_lock(struct phy_device *phydev, u16 regnum, ++ u16 mask, u16 set) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = ytphy_modify_ext(phydev, regnum, mask, set); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++/** ++ * ytphy_get_wol() - report whether wake-on-lan is enabled ++ * @phydev: a pointer to a &struct phy_device ++ * @wol: a pointer to a &struct ethtool_wolinfo ++ * ++ * NOTE: YTPHY_WOL_CONFIG_REG is common ext reg. ++ */ ++static void ytphy_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int wol_config; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); ++ if (wol_config < 0) ++ return; ++ ++ if (wol_config & YTPHY_WCR_ENABLE) ++ wol->wolopts |= WAKE_MAGIC; ++} ++ ++/** ++ * ytphy_set_wol() - turn wake-on-lan on or off ++ * @phydev: a pointer to a &struct phy_device ++ * @wol: a pointer to a &struct ethtool_wolinfo ++ * ++ * NOTE: YTPHY_WOL_CONFIG_REG, YTPHY_WOL_MACADDR2_REG, YTPHY_WOL_MACADDR1_REG ++ * and YTPHY_WOL_MACADDR0_REG are common ext reg. The ++ * YTPHY_INTERRUPT_ENABLE_REG of UTP is special, fiber also use this register. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) ++{ ++ struct net_device *p_attached_dev; ++ const u16 mac_addr_reg[] = { ++ YTPHY_WOL_MACADDR2_REG, ++ YTPHY_WOL_MACADDR1_REG, ++ YTPHY_WOL_MACADDR0_REG, ++ }; ++ const u8 *mac_addr; ++ int old_page; ++ int ret = 0; ++ u16 mask; ++ u16 val; ++ u8 i; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ p_attached_dev = phydev->attached_dev; ++ if (!p_attached_dev) ++ return -ENODEV; ++ ++ mac_addr = (const u8 *)p_attached_dev->dev_addr; ++ if (!is_valid_ether_addr(mac_addr)) ++ return -EINVAL; ++ ++ /* lock mdio bus then switch to utp reg space */ ++ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ /* Store the device address for the magic packet */ ++ for (i = 0; i < 3; i++) { ++ ret = ytphy_write_ext(phydev, mac_addr_reg[i], ++ ((mac_addr[i * 2] << 8)) | ++ (mac_addr[i * 2 + 1])); ++ if (ret < 0) ++ goto err_restore_page; ++ } ++ ++ /* Enable WOL feature */ ++ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; ++ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; ++ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; ++ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, val); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ /* Enable WOL interrupt */ ++ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, ++ YTPHY_IER_WOL); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ } else { ++ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ /* Disable WOL feature */ ++ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; ++ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0); ++ ++ /* Disable WOL interrupt */ ++ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, ++ YTPHY_IER_WOL, 0); ++ if (ret < 0) ++ goto err_restore_page; ++ } ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ + static int yt8511_read_page(struct phy_device *phydev) + { + return __phy_read(phydev, YT8511_PAGE_SELECT); +@@ -111,6 +548,1181 @@ err_restore_page: + return phy_restore_page(phydev, oldpage, ret); + } + ++/** ++ * yt8521_read_page() - read reg page ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns current reg space of yt8521 (YT8521_RSSR_FIBER_SPACE/ ++ * YT8521_RSSR_UTP_SPACE) or negative errno code ++ */ ++static int yt8521_read_page(struct phy_device *phydev) ++{ ++ int old_page; ++ ++ old_page = ytphy_read_ext(phydev, YT8521_REG_SPACE_SELECT_REG); ++ if (old_page < 0) ++ return old_page; ++ ++ if ((old_page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) ++ return YT8521_RSSR_FIBER_SPACE; ++ ++ return YT8521_RSSR_UTP_SPACE; ++}; ++ ++/** ++ * yt8521_write_page() - write reg page ++ * @phydev: a pointer to a &struct phy_device ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to write. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_write_page(struct phy_device *phydev, int page) ++{ ++ int mask = YT8521_RSSR_SPACE_MASK; ++ int set; ++ ++ if ((page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) ++ set = YT8521_RSSR_FIBER_SPACE; ++ else ++ set = YT8521_RSSR_UTP_SPACE; ++ ++ return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set); ++}; ++ ++/** ++ * yt8521_probe() - read chip config then set suitable polling_mode ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct yt8521_priv *priv; ++ int chip_config; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ chip_config = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ if (chip_config < 0) ++ return chip_config; ++ ++ priv->strap_mode = chip_config & YT8521_CCR_MODE_SEL_MASK; ++ switch (priv->strap_mode) { ++ case YT8521_CCR_MODE_FIBER_TO_RGMII: ++ case YT8521_CCR_MODE_SGPHY_TO_RGMAC: ++ case YT8521_CCR_MODE_SGMAC_TO_RGPHY: ++ priv->polling_mode = YT8521_MODE_FIBER; ++ priv->reg_page = YT8521_RSSR_FIBER_SPACE; ++ phydev->port = PORT_FIBRE; ++ break; ++ case YT8521_CCR_MODE_UTP_FIBER_TO_RGMII: ++ case YT8521_CCR_MODE_UTP_TO_FIBER_AUTO: ++ case YT8521_CCR_MODE_UTP_TO_FIBER_FORCE: ++ priv->polling_mode = YT8521_MODE_POLL; ++ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; ++ phydev->port = PORT_NONE; ++ break; ++ case YT8521_CCR_MODE_UTP_TO_SGMII: ++ case YT8521_CCR_MODE_UTP_TO_RGMII: ++ priv->polling_mode = YT8521_MODE_UTP; ++ priv->reg_page = YT8521_RSSR_UTP_SPACE; ++ phydev->port = PORT_TP; ++ break; ++ } ++ /* set default reg space */ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ ret = ytphy_write_ext_with_lock(phydev, ++ YT8521_REG_SPACE_SELECT_REG, ++ priv->reg_page); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_utp_read_lpa(struct phy_device *phydev) ++{ ++ int lpa, lpagb; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ if (!phydev->autoneg_complete) { ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ++ 0); ++ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ return 0; ++ } ++ ++ if (phydev->is_gigabit_capable) { ++ lpagb = __phy_read(phydev, MII_STAT1000); ++ if (lpagb < 0) ++ return lpagb; ++ ++ if (lpagb & LPA_1000MSFAIL) { ++ int adv = __phy_read(phydev, MII_CTRL1000); ++ ++ if (adv < 0) ++ return adv; ++ ++ if (adv & CTL1000_ENABLE_MASTER) ++ phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n"); ++ else ++ phydev_err(phydev, "Master/Slave resolution failed\n"); ++ return -ENOLINK; ++ } ++ ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ++ lpagb); ++ } ++ ++ lpa = __phy_read(phydev, MII_LPA); ++ if (lpa < 0) ++ return lpa; ++ ++ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); ++ } else { ++ linkmode_zero(phydev->lp_advertising); ++ } ++ ++ return 0; ++} ++ ++/** ++ * yt8521_adjust_status() - update speed and duplex to phydev. when in fiber ++ * mode, adjust speed and duplex. ++ * @phydev: a pointer to a &struct phy_device ++ * @status: yt8521 status read from YTPHY_SPECIFIC_STATUS_REG ++ * @is_utp: false(yt8521 work in fiber mode) or true(yt8521 work in utp mode) ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 ++ */ ++static int yt8521_adjust_status(struct phy_device *phydev, int status, ++ bool is_utp) ++{ ++ int speed_mode, duplex; ++ int speed; ++ int err; ++ int lpa; ++ ++ if (is_utp) ++ duplex = (status & YTPHY_SSR_DUPLEX) >> YTPHY_SSR_DUPLEX_OFFSET; ++ else ++ duplex = DUPLEX_FULL; /* for fiber, it always DUPLEX_FULL */ ++ ++ speed_mode = (status & YTPHY_SSR_SPEED_MODE_MASK) >> ++ YTPHY_SSR_SPEED_MODE_OFFSET; ++ ++ switch (speed_mode) { ++ case YTPHY_SSR_SPEED_10M: ++ if (is_utp) ++ speed = SPEED_10; ++ else ++ /* for fiber, it will never run here, default to ++ * SPEED_UNKNOWN ++ */ ++ speed = SPEED_UNKNOWN; ++ break; ++ case YTPHY_SSR_SPEED_100M: ++ speed = SPEED_100; ++ break; ++ case YTPHY_SSR_SPEED_1000M: ++ speed = SPEED_1000; ++ break; ++ default: ++ speed = SPEED_UNKNOWN; ++ break; ++ } ++ ++ phydev->speed = speed; ++ phydev->duplex = duplex; ++ ++ if (is_utp) { ++ err = ytphy_utp_read_lpa(phydev); ++ if (err < 0) ++ return err; ++ ++ phy_resolve_aneg_pause(phydev); ++ } else { ++ lpa = __phy_read(phydev, MII_LPA); ++ if (lpa < 0) ++ return lpa; ++ ++ /* only support 1000baseX Full */ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->lp_advertising, lpa & LPA_1000XFULL); ++ ++ if (!(lpa & YTPHY_FLPA_PAUSE)) { ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ } else if ((lpa & YTPHY_FLPA_ASYM_PAUSE)) { ++ phydev->pause = 1; ++ phydev->asym_pause = 1; ++ } else { ++ phydev->pause = 1; ++ phydev->asym_pause = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * yt8521_read_status_paged() - determines the speed and duplex of one page ++ * @phydev: a pointer to a &struct phy_device ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to ++ * operate. ++ * ++ * returns 1 (utp or fiber link),0 (no link) or negative errno code ++ */ ++static int yt8521_read_status_paged(struct phy_device *phydev, int page) ++{ ++ int fiber_latch_val; ++ int fiber_curr_val; ++ int old_page; ++ int ret = 0; ++ int status; ++ int link; ++ ++ linkmode_zero(phydev->lp_advertising); ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->asym_pause = 0; ++ phydev->pause = 0; ++ ++ /* YT8521 has two reg space (utp/fiber) for linkup with utp/fiber ++ * respectively. but for utp/fiber combo mode, reg space should be ++ * arbitrated based on media priority. by default, utp takes ++ * priority. reg space should be properly set before read ++ * YTPHY_SPECIFIC_STATUS_REG. ++ */ ++ ++ page &= YT8521_RSSR_SPACE_MASK; ++ old_page = phy_select_page(phydev, page); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ /* Read YTPHY_SPECIFIC_STATUS_REG, which indicates the speed and duplex ++ * of the PHY is actually using. ++ */ ++ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ status = ret; ++ link = !!(status & YTPHY_SSR_LINK); ++ ++ /* When PHY is in fiber mode, speed transferred from 1000Mbps to ++ * 100Mbps,there is not link down from YTPHY_SPECIFIC_STATUS_REG, so ++ * we need check MII_BMSR to identify such case. ++ */ ++ if (page == YT8521_RSSR_FIBER_SPACE) { ++ ret = __phy_read(phydev, MII_BMSR); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ fiber_latch_val = ret; ++ ret = __phy_read(phydev, MII_BMSR); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ fiber_curr_val = ret; ++ if (link && fiber_latch_val != fiber_curr_val) { ++ link = 0; ++ phydev_info(phydev, ++ "%s, fiber link down detect, latch = %04x, curr = %04x\n", ++ __func__, fiber_latch_val, fiber_curr_val); ++ } ++ } else { ++ /* Read autonegotiation status */ ++ ret = __phy_read(phydev, MII_BMSR); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ phydev->autoneg_complete = ret & BMSR_ANEGCOMPLETE ? 1 : 0; ++ } ++ ++ if (link) { ++ if (page == YT8521_RSSR_UTP_SPACE) ++ yt8521_adjust_status(phydev, status, true); ++ else ++ yt8521_adjust_status(phydev, status, false); ++ } ++ return phy_restore_page(phydev, old_page, link); ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_read_status() - determines the negotiated speed and duplex ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_read_status(struct phy_device *phydev) ++{ ++ struct yt8521_priv *priv = phydev->priv; ++ int link_fiber = 0; ++ int link_utp; ++ int link; ++ int ret; ++ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ link = yt8521_read_status_paged(phydev, priv->reg_page); ++ if (link < 0) ++ return link; ++ } else { ++ /* when page is YT8521_RSSR_TO_BE_ARBITRATED, arbitration is ++ * needed. by default, utp is higher priority. ++ */ ++ ++ link_utp = yt8521_read_status_paged(phydev, ++ YT8521_RSSR_UTP_SPACE); ++ if (link_utp < 0) ++ return link_utp; ++ ++ if (!link_utp) { ++ link_fiber = yt8521_read_status_paged(phydev, ++ YT8521_RSSR_FIBER_SPACE); ++ if (link_fiber < 0) ++ return link_fiber; ++ } ++ ++ link = link_utp || link_fiber; ++ } ++ ++ if (link) { ++ if (phydev->link == 0) { ++ /* arbitrate reg space based on linkup media type. */ ++ if (priv->polling_mode == YT8521_MODE_POLL && ++ priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { ++ if (link_fiber) ++ priv->reg_page = ++ YT8521_RSSR_FIBER_SPACE; ++ else ++ priv->reg_page = YT8521_RSSR_UTP_SPACE; ++ ++ ret = ytphy_write_ext_with_lock(phydev, ++ YT8521_REG_SPACE_SELECT_REG, ++ priv->reg_page); ++ if (ret < 0) ++ return ret; ++ ++ phydev->port = link_fiber ? PORT_FIBRE : PORT_TP; ++ ++ phydev_info(phydev, "%s, link up, media: %s\n", ++ __func__, ++ (phydev->port == PORT_TP) ? ++ "UTP" : "Fiber"); ++ } ++ } ++ phydev->link = 1; ++ } else { ++ if (phydev->link == 1) { ++ phydev_info(phydev, "%s, link down, media: %s\n", ++ __func__, (phydev->port == PORT_TP) ? ++ "UTP" : "Fiber"); ++ ++ /* When in YT8521_MODE_POLL mode, need prepare for next ++ * arbitration. ++ */ ++ if (priv->polling_mode == YT8521_MODE_POLL) { ++ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; ++ phydev->port = PORT_NONE; ++ } ++ } ++ ++ phydev->link = 0; ++ } ++ ++ return 0; ++} ++ ++/** ++ * yt8521_modify_bmcr_paged - bits modify a PHY's BMCR register of one page ++ * @phydev: the phy_device struct ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to operate ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * NOTE: Convenience function which allows a PHY's BMCR register to be ++ * modified as new register value = (old register value & ~mask) | set. ++ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space ++ * has MII_BMCR. poll mode combines utp and faber,so need do both. ++ * If it is reset, it will wait for completion. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_modify_bmcr_paged(struct phy_device *phydev, int page, ++ u16 mask, u16 set) ++{ ++ int max_cnt = 500; /* the max wait time of reset ~ 500 ms */ ++ int old_page; ++ int ret = 0; ++ ++ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ ret = __phy_modify(phydev, MII_BMCR, mask, set); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ /* If it is reset, need to wait for the reset to complete */ ++ if (set == BMCR_RESET) { ++ while (max_cnt--) { ++ usleep_range(1000, 1100); ++ ret = __phy_read(phydev, MII_BMCR); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ if (!(ret & BMCR_RESET)) ++ return phy_restore_page(phydev, old_page, 0); ++ } ++ } ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_modify_utp_fiber_bmcr - bits modify a PHY's BMCR register ++ * @phydev: the phy_device struct ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * NOTE: Convenience function which allows a PHY's BMCR register to be ++ * modified as new register value = (old register value & ~mask) | set. ++ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space ++ * has MII_BMCR. poll mode combines utp and faber,so need do both. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_modify_utp_fiber_bmcr(struct phy_device *phydev, u16 mask, ++ u16 set) ++{ ++ struct yt8521_priv *priv = phydev->priv; ++ int ret; ++ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ ret = yt8521_modify_bmcr_paged(phydev, priv->reg_page, mask, ++ set); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_UTP_SPACE, ++ mask, set); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_FIBER_SPACE, ++ mask, set); ++ if (ret < 0) ++ return ret; ++ } ++ return 0; ++} ++ ++/** ++ * yt8521_soft_reset() - called to issue a PHY software reset ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_soft_reset(struct phy_device *phydev) ++{ ++ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_RESET); ++} ++ ++/** ++ * yt8521_suspend() - suspend the hardware ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_suspend(struct phy_device *phydev) ++{ ++ int wol_config; ++ ++ /* YTPHY_WOL_CONFIG_REG is common ext reg */ ++ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); ++ if (wol_config < 0) ++ return wol_config; ++ ++ /* if wol enable, do nothing */ ++ if (wol_config & YTPHY_WCR_ENABLE) ++ return 0; ++ ++ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN); ++} ++ ++/** ++ * yt8521_resume() - resume the hardware ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_resume(struct phy_device *phydev) ++{ ++ int ret; ++ int wol_config; ++ ++ /* disable auto sleep */ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YT8521_EXTREG_SLEEP_CONTROL1_REG, ++ YT8521_ESC1R_SLEEP_SW, 0); ++ if (ret < 0) ++ return ret; ++ ++ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); ++ if (wol_config < 0) ++ return wol_config; ++ ++ /* if wol enable, do nothing */ ++ if (wol_config & YTPHY_WCR_ENABLE) ++ return 0; ++ ++ return yt8521_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0); ++} ++ ++/** ++ * yt8521_config_init() - called to initialize the PHY ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_config_init(struct phy_device *phydev) ++{ ++ int old_page; ++ int ret = 0; ++ u16 val; ++ ++ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; ++ val |= YT8521_RC1R_RX_DELAY_DIS; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; ++ val |= YT8521_RC1R_RX_DELAY_EN; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; ++ val |= YT8521_RC1R_RX_DELAY_DIS; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; ++ val |= YT8521_RC1R_RX_DELAY_EN; ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ break; ++ default: /* do not support other modes */ ++ ret = -EOPNOTSUPP; ++ goto err_restore_page; ++ } ++ ++ /* set rgmii delay mode */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { ++ ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, ++ (YT8521_RC1R_RX_DELAY_MASK | ++ YT8521_RC1R_FE_TX_DELAY_MASK | ++ YT8521_RC1R_GE_TX_DELAY_MASK), ++ val); ++ if (ret < 0) ++ goto err_restore_page; ++ } ++ ++ /* disable auto sleep */ ++ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, ++ YT8521_ESC1R_SLEEP_SW, 0); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ /* enable RXC clock when no wire plug */ ++ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, ++ YT8521_CGR_RX_CLK_EN, 0); ++ if (ret < 0) ++ goto err_restore_page; ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_prepare_fiber_features() - A small helper function that setup ++ * fiber's features. ++ * @phydev: a pointer to a &struct phy_device ++ * @dst: a pointer to store fiber's features ++ */ ++static void yt8521_prepare_fiber_features(struct phy_device *phydev, ++ unsigned long *dst) ++{ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, dst); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, dst); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, dst); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, dst); ++} ++ ++/** ++ * yt8521_fiber_setup_forced - configures/forces speed from @phydev ++ * @phydev: target phy_device struct ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_fiber_setup_forced(struct phy_device *phydev) ++{ ++ u16 val; ++ int ret; ++ ++ if (phydev->speed == SPEED_1000) ++ val = YTPHY_MCR_FIBER_1000BX; ++ else if (phydev->speed == SPEED_100) ++ val = YTPHY_MCR_FIBER_100FX; ++ else ++ return -EINVAL; ++ ++ ret = __phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* disable Fiber auto sensing */ ++ ret = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, ++ YT8521_LTCR_EN_AUTOSEN, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = ytphy_modify_ext(phydev, YTPHY_MISC_CONFIG_REG, ++ YTPHY_MCR_FIBER_SPEED_MASK, val); ++ if (ret < 0) ++ return ret; ++ ++ return ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, ++ YT8521_CCR_SW_RST, 0); ++} ++ ++/** ++ * ytphy_check_and_restart_aneg - Enable and restart auto-negotiation ++ * @phydev: target phy_device struct ++ * @restart: whether aneg restart is requested ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) ++{ ++ int ret; ++ ++ if (!restart) { ++ /* Advertisement hasn't changed, but maybe aneg was never on to ++ * begin with? Or maybe phy was isolated? ++ */ ++ ret = __phy_read(phydev, MII_BMCR); ++ if (ret < 0) ++ return ret; ++ ++ if (!(ret & BMCR_ANENABLE) || (ret & BMCR_ISOLATE)) ++ restart = true; ++ } ++ /* Enable and Restart Autonegotiation ++ * Don't isolate the PHY if we're negotiating ++ */ ++ if (restart) ++ return __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, ++ BMCR_ANENABLE | BMCR_ANRESTART); ++ ++ return 0; ++} ++ ++/** ++ * yt8521_fiber_config_aneg - restart auto-negotiation or write ++ * YTPHY_MISC_CONFIG_REG. ++ * @phydev: target phy_device struct ++ * ++ * NOTE:The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_fiber_config_aneg(struct phy_device *phydev) ++{ ++ int err, changed = 0; ++ int bmcr; ++ u16 adv; ++ ++ if (phydev->autoneg != AUTONEG_ENABLE) ++ return yt8521_fiber_setup_forced(phydev); ++ ++ /* enable Fiber auto sensing */ ++ err = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, ++ 0, YT8521_LTCR_EN_AUTOSEN); ++ if (err < 0) ++ return err; ++ ++ err = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, ++ YT8521_CCR_SW_RST, 0); ++ if (err < 0) ++ return err; ++ ++ bmcr = __phy_read(phydev, MII_BMCR); ++ if (bmcr < 0) ++ return bmcr; ++ ++ /* When it is coming from fiber forced mode, add bmcr power down ++ * and power up to let aneg work fine. ++ */ ++ if (!(bmcr & BMCR_ANENABLE)) { ++ __phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN); ++ usleep_range(1000, 1100); ++ __phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0); ++ } ++ ++ adv = linkmode_adv_to_mii_adv_x(phydev->advertising, ++ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); ++ ++ /* Setup fiber advertisement */ ++ err = __phy_modify_changed(phydev, MII_ADVERTISE, ++ ADVERTISE_1000XHALF | ADVERTISE_1000XFULL | ++ ADVERTISE_1000XPAUSE | ++ ADVERTISE_1000XPSE_ASYM, ++ adv); ++ if (err < 0) ++ return err; ++ ++ if (err > 0) ++ changed = 1; ++ ++ return ytphy_check_and_restart_aneg(phydev, changed); ++} ++ ++/** ++ * ytphy_setup_master_slave ++ * @phydev: target phy_device struct ++ * ++ * NOTE: The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_setup_master_slave(struct phy_device *phydev) ++{ ++ u16 ctl = 0; ++ ++ if (!phydev->is_gigabit_capable) ++ return 0; ++ ++ switch (phydev->master_slave_set) { ++ case MASTER_SLAVE_CFG_MASTER_PREFERRED: ++ ctl |= CTL1000_PREFER_MASTER; ++ break; ++ case MASTER_SLAVE_CFG_SLAVE_PREFERRED: ++ break; ++ case MASTER_SLAVE_CFG_MASTER_FORCE: ++ ctl |= CTL1000_AS_MASTER; ++ fallthrough; ++ case MASTER_SLAVE_CFG_SLAVE_FORCE: ++ ctl |= CTL1000_ENABLE_MASTER; ++ break; ++ case MASTER_SLAVE_CFG_UNKNOWN: ++ case MASTER_SLAVE_CFG_UNSUPPORTED: ++ return 0; ++ default: ++ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ return __phy_modify_changed(phydev, MII_CTRL1000, ++ (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER | ++ CTL1000_PREFER_MASTER), ctl); ++} ++ ++/** ++ * ytphy_utp_config_advert - sanitize and advertise auto-negotiation parameters ++ * @phydev: target phy_device struct ++ * ++ * NOTE: Writes MII_ADVERTISE with the appropriate values, ++ * after sanitizing the values to make sure we only advertise ++ * what is supported. Returns < 0 on error, 0 if the PHY's advertisement ++ * hasn't changed, and > 0 if it has changed. ++ * The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_utp_config_advert(struct phy_device *phydev) ++{ ++ int err, bmsr, changed = 0; ++ u32 adv; ++ ++ /* Only allow advertising what this PHY supports */ ++ linkmode_and(phydev->advertising, phydev->advertising, ++ phydev->supported); ++ ++ adv = linkmode_adv_to_mii_adv_t(phydev->advertising); ++ ++ /* Setup standard advertisement */ ++ err = __phy_modify_changed(phydev, MII_ADVERTISE, ++ ADVERTISE_ALL | ADVERTISE_100BASE4 | ++ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, ++ adv); ++ if (err < 0) ++ return err; ++ if (err > 0) ++ changed = 1; ++ ++ bmsr = __phy_read(phydev, MII_BMSR); ++ if (bmsr < 0) ++ return bmsr; ++ ++ /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all ++ * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a ++ * logical 1. ++ */ ++ if (!(bmsr & BMSR_ESTATEN)) ++ return changed; ++ ++ adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); ++ ++ err = __phy_modify_changed(phydev, MII_CTRL1000, ++ ADVERTISE_1000FULL | ADVERTISE_1000HALF, ++ adv); ++ if (err < 0) ++ return err; ++ if (err > 0) ++ changed = 1; ++ ++ return changed; ++} ++ ++/** ++ * ytphy_utp_config_aneg - restart auto-negotiation or write BMCR ++ * @phydev: target phy_device struct ++ * @changed: whether autoneg is requested ++ * ++ * NOTE: If auto-negotiation is enabled, we configure the ++ * advertising, and then restart auto-negotiation. If it is not ++ * enabled, then we write the BMCR. ++ * The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_utp_config_aneg(struct phy_device *phydev, bool changed) ++{ ++ int err; ++ u16 ctl; ++ ++ err = ytphy_setup_master_slave(phydev); ++ if (err < 0) ++ return err; ++ else if (err) ++ changed = true; ++ ++ if (phydev->autoneg != AUTONEG_ENABLE) { ++ /* configures/forces speed/duplex from @phydev */ ++ ++ ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex); ++ ++ return __phy_modify(phydev, MII_BMCR, ~(BMCR_LOOPBACK | ++ BMCR_ISOLATE | BMCR_PDOWN), ctl); ++ } ++ ++ err = ytphy_utp_config_advert(phydev); ++ if (err < 0) /* error */ ++ return err; ++ else if (err) ++ changed = true; ++ ++ return ytphy_check_and_restart_aneg(phydev, changed); ++} ++ ++/** ++ * yt8521_config_aneg_paged() - switch reg space then call genphy_config_aneg ++ * of one page ++ * @phydev: a pointer to a &struct phy_device ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to ++ * operate. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_config_aneg_paged(struct phy_device *phydev, int page) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(fiber_supported); ++ struct yt8521_priv *priv = phydev->priv; ++ int old_page; ++ int ret = 0; ++ ++ page &= YT8521_RSSR_SPACE_MASK; ++ ++ old_page = phy_select_page(phydev, page); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, ++ * phydev->advertising should be updated. ++ */ ++ if (priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { ++ linkmode_zero(fiber_supported); ++ yt8521_prepare_fiber_features(phydev, fiber_supported); ++ ++ /* prepare fiber_supported, then setup advertising. */ ++ if (page == YT8521_RSSR_FIBER_SPACE) { ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, ++ fiber_supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, ++ fiber_supported); ++ linkmode_and(phydev->advertising, ++ priv->combo_advertising, fiber_supported); ++ } else { ++ /* ETHTOOL_LINK_MODE_Autoneg_BIT is also used in utp */ ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ fiber_supported); ++ linkmode_andnot(phydev->advertising, ++ priv->combo_advertising, ++ fiber_supported); ++ } ++ } ++ ++ if (page == YT8521_RSSR_FIBER_SPACE) ++ ret = yt8521_fiber_config_aneg(phydev); ++ else ++ ret = ytphy_utp_config_aneg(phydev, false); ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_config_aneg() - change reg space then call yt8521_config_aneg_paged ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_config_aneg(struct phy_device *phydev) ++{ ++ struct yt8521_priv *priv = phydev->priv; ++ int ret; ++ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ ret = yt8521_config_aneg_paged(phydev, priv->reg_page); ++ if (ret < 0) ++ return ret; ++ } else { ++ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, ++ * phydev->advertising need to be saved at first run. ++ * Because it contains the advertising which supported by both ++ * mac and yt8521(utp and fiber). ++ */ ++ if (linkmode_empty(priv->combo_advertising)) { ++ linkmode_copy(priv->combo_advertising, ++ phydev->advertising); ++ } ++ ++ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_UTP_SPACE); ++ if (ret < 0) ++ return ret; ++ ++ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_FIBER_SPACE); ++ if (ret < 0) ++ return ret; ++ ++ /* we don't known which will be link, so restore ++ * phydev->advertising as default value. ++ */ ++ linkmode_copy(phydev->advertising, priv->combo_advertising); ++ } ++ return 0; ++} ++ ++/** ++ * yt8521_aneg_done_paged() - determines the auto negotiation result of one ++ * page. ++ * @phydev: a pointer to a &struct phy_device ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to ++ * operate. ++ * ++ * returns 0(no link)or 1(fiber or utp link) or negative errno code ++ */ ++static int yt8521_aneg_done_paged(struct phy_device *phydev, int page) ++{ ++ int old_page; ++ int ret = 0; ++ int link; ++ ++ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); ++ if (ret < 0) ++ goto err_restore_page; ++ ++ link = !!(ret & YTPHY_SSR_LINK); ++ ret = link; ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_aneg_done() - determines the auto negotiation result ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0(no link)or 1(fiber or utp link) or negative errno code ++ */ ++static int yt8521_aneg_done(struct phy_device *phydev) ++{ ++ struct yt8521_priv *priv = phydev->priv; ++ int link_fiber = 0; ++ int link_utp; ++ int link; ++ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ link = yt8521_aneg_done_paged(phydev, priv->reg_page); ++ } else { ++ link_utp = yt8521_aneg_done_paged(phydev, ++ YT8521_RSSR_UTP_SPACE); ++ if (link_utp < 0) ++ return link_utp; ++ ++ if (!link_utp) { ++ link_fiber = yt8521_aneg_done_paged(phydev, ++ YT8521_RSSR_FIBER_SPACE); ++ if (link_fiber < 0) ++ return link_fiber; ++ } ++ link = link_fiber || link_utp; ++ phydev_info(phydev, "%s, link_fiber: %d, link_utp: %d\n", ++ __func__, link_fiber, link_utp); ++ } ++ ++ return link; ++} ++ ++/** ++ * ytphy_utp_read_abilities - read PHY abilities from Clause 22 registers ++ * @phydev: target phy_device struct ++ * ++ * NOTE: Reads the PHY's abilities and populates ++ * phydev->supported accordingly. ++ * The caller must have taken the MDIO bus lock. ++ * ++ * returns 0 or negative errno code ++ */ ++static int ytphy_utp_read_abilities(struct phy_device *phydev) ++{ ++ int val; ++ ++ linkmode_set_bit_array(phy_basic_ports_array, ++ ARRAY_SIZE(phy_basic_ports_array), ++ phydev->supported); ++ ++ val = __phy_read(phydev, MII_BMSR); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported, ++ val & BMSR_ANEGCAPABLE); ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported, ++ val & BMSR_100FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported, ++ val & BMSR_100HALF); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported, ++ val & BMSR_10FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported, ++ val & BMSR_10HALF); ++ ++ if (val & BMSR_ESTATEN) { ++ val = __phy_read(phydev, MII_ESTATUS); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->supported, val & ESTATUS_1000_TFULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->supported, val & ESTATUS_1000_THALF); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->supported, val & ESTATUS_1000_XFULL); ++ } ++ ++ return 0; ++} ++ ++/** ++ * yt8521_get_features_paged() - read supported link modes for one page ++ * @phydev: a pointer to a &struct phy_device ++ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to ++ * operate. ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_get_features_paged(struct phy_device *phydev, int page) ++{ ++ int old_page; ++ int ret = 0; ++ ++ page &= YT8521_RSSR_SPACE_MASK; ++ old_page = phy_select_page(phydev, page); ++ if (old_page < 0) ++ goto err_restore_page; ++ ++ if (page == YT8521_RSSR_FIBER_SPACE) { ++ linkmode_zero(phydev->supported); ++ yt8521_prepare_fiber_features(phydev, phydev->supported); ++ } else { ++ ret = ytphy_utp_read_abilities(phydev); ++ if (ret < 0) ++ goto err_restore_page; ++ } ++ ++err_restore_page: ++ return phy_restore_page(phydev, old_page, ret); ++} ++ ++/** ++ * yt8521_get_features - switch reg space then call yt8521_get_features_paged ++ * @phydev: target phy_device struct ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8521_get_features(struct phy_device *phydev) ++{ ++ struct yt8521_priv *priv = phydev->priv; ++ int ret; ++ ++ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { ++ ret = yt8521_get_features_paged(phydev, priv->reg_page); ++ } else { ++ ret = yt8521_get_features_paged(phydev, ++ YT8521_RSSR_UTP_SPACE); ++ if (ret < 0) ++ return ret; ++ ++ /* add fiber's features to phydev->supported */ ++ yt8521_prepare_fiber_features(phydev, phydev->supported); ++ } ++ return ret; ++} ++ + static struct phy_driver motorcomm_phy_drvs[] = { + { + PHY_ID_MATCH_EXACT(PHY_ID_YT8511), +@@ -121,16 +1733,35 @@ static struct phy_driver motorcomm_phy_d + .read_page = yt8511_read_page, + .write_page = yt8511_write_page, + }, ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_YT8521), ++ .name = "YT8521 Gigabit Ethernet", ++ .get_features = yt8521_get_features, ++ .probe = yt8521_probe, ++ .read_page = yt8521_read_page, ++ .write_page = yt8521_write_page, ++ .get_wol = ytphy_get_wol, ++ .set_wol = ytphy_set_wol, ++ .config_aneg = yt8521_config_aneg, ++ .aneg_done = yt8521_aneg_done, ++ .config_init = yt8521_config_init, ++ .read_status = yt8521_read_status, ++ .soft_reset = yt8521_soft_reset, ++ .suspend = yt8521_suspend, ++ .resume = yt8521_resume, ++ }, + }; + + module_phy_driver(motorcomm_phy_drvs); + +-MODULE_DESCRIPTION("Motorcomm PHY driver"); ++MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); + MODULE_AUTHOR("Peter Geis"); ++MODULE_AUTHOR("Frank"); + MODULE_LICENSE("GPL"); + + static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, + { /* sentinal */ } + }; + diff --git a/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch b/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch new file mode 100644 index 0000000000..cce71c8d84 --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch @@ -0,0 +1,49 @@ +From 4e0243e7128c9b25ea2739136076a95d6adaba5e Mon Sep 17 00:00:00 2001 +From: Frank +Date: Fri, 4 Nov 2022 16:44:41 +0800 +Subject: [PATCH] net: phy: fix yt8521 duplicated argument to & or | + +cocci warnings: (new ones prefixed by >>) +>> drivers/net/phy/motorcomm.c:1122:8-35: duplicated argument to & or | + drivers/net/phy/motorcomm.c:1126:8-35: duplicated argument to & or | + drivers/net/phy/motorcomm.c:1130:8-34: duplicated argument to & or | + drivers/net/phy/motorcomm.c:1134:8-34: duplicated argument to & or | + + The second YT8521_RC1R_GE_TX_DELAY_xx should be YT8521_RC1R_FE_TX_DELAY_xx. + +Fixes: 70479a40954c ("net: phy: Add driver for Motorcomm yt8521 gigabit ethernet phy") +Reported-by: kernel test robot +Reported-by: Julia Lawall +Signed-off-by: Frank +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1119,19 +1119,19 @@ static int yt8521_config_init(struct phy + + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: +- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; ++ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; + val |= YT8521_RC1R_RX_DELAY_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: +- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; ++ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; + val |= YT8521_RC1R_RX_DELAY_EN; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: +- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; ++ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; + val |= YT8521_RC1R_RX_DELAY_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_ID: +- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; ++ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; + val |= YT8521_RC1R_RX_DELAY_EN; + break; + case PHY_INTERFACE_MODE_SGMII: diff --git a/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch new file mode 100644 index 0000000000..d22cc69425 --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch @@ -0,0 +1,140 @@ +From 813abcd98fb1b2cccf850cdfa092a4bfc50b2363 Mon Sep 17 00:00:00 2001 +From: Frank +Date: Tue, 22 Nov 2022 16:42:32 +0800 +Subject: [PATCH] net: phy: add Motorcomm YT8531S phy id. + +We added patch for motorcomm.c to support YT8531S. This patch has +been tested on AM335x platform which has one YT8531S interface +card and passed all test cases. +The tested cases indluding: YT8531S UTP function with support of +10M/100M/1000M; YT8531S Fiber function with support of 100M/1000M; +and YT8531S Combo function that supports auto detection of media type. + +Since most functions of YT8531S are similar to YT8521 and we reuse some +codes for YT8521 in the patch file. + +Signed-off-by: Frank +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 2 +- + drivers/net/phy/motorcomm.c | 52 +++++++++++++++++++++++++++++++++---- + 2 files changed, 48 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY + tristate "Motorcomm PHYs" + help + Enables support for Motorcomm network PHYs. +- Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. ++ Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. + + config NATIONAL_PHY + tristate "National Semiconductor PHYs" +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Motorcomm 8511/8521 PHY driver. ++ * Motorcomm 8511/8521/8531S PHY driver. + * + * Author: Peter Geis + * Author: Frank +@@ -12,9 +12,10 @@ + #include + + #define PHY_ID_YT8511 0x0000010a +-#define PHY_ID_YT8521 0x0000011A ++#define PHY_ID_YT8521 0x0000011A ++#define PHY_ID_YT8531S 0x4F51E91A + +-/* YT8521 Register Overview ++/* YT8521/YT8531S Register Overview + * UTP Register space | FIBER Register space + * ------------------------------------------------------------ + * | UTP MII | FIBER MII | +@@ -147,7 +148,7 @@ + #define YT8521_LINK_TIMER_CFG2_REG 0xA5 + #define YT8521_LTCR_EN_AUTOSEN BIT(15) + +-/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers ++/* 0xA000, 0xA001, 0xA003, 0xA006 ~ 0xA00A and 0xA012 are common ext registers + * of yt8521 phy. There is no need to switch reg space when operating these + * registers. + */ +@@ -221,6 +222,9 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YT8531S_SYNCE_CFG_REG 0xA012 ++#define YT8531S_SCR_SYNCE_ENABLE BIT(6) ++ + /* Extended Register end */ + + struct yt8521_priv { +@@ -648,6 +652,26 @@ static int yt8521_probe(struct phy_devic + } + + /** ++ * yt8531s_probe() - read chip config then set suitable polling_mode ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * returns 0 or negative errno code ++ */ ++static int yt8531s_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Disable SyncE clock output by default */ ++ ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, ++ YT8531S_SCR_SYNCE_ENABLE, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* same as yt8521_probe */ ++ return yt8521_probe(phydev); ++} ++ ++/** + * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp + * @phydev: a pointer to a &struct phy_device + * +@@ -1750,11 +1774,28 @@ static struct phy_driver motorcomm_phy_d + .suspend = yt8521_suspend, + .resume = yt8521_resume, + }, ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), ++ .name = "YT8531S Gigabit Ethernet", ++ .get_features = yt8521_get_features, ++ .probe = yt8531s_probe, ++ .read_page = yt8521_read_page, ++ .write_page = yt8521_write_page, ++ .get_wol = ytphy_get_wol, ++ .set_wol = ytphy_set_wol, ++ .config_aneg = yt8521_config_aneg, ++ .aneg_done = yt8521_aneg_done, ++ .config_init = yt8521_config_init, ++ .read_status = yt8521_read_status, ++ .soft_reset = yt8521_soft_reset, ++ .suspend = yt8521_suspend, ++ .resume = yt8521_resume, ++ }, + }; + + module_phy_driver(motorcomm_phy_drvs); + +-MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); ++MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); + MODULE_AUTHOR("Peter Geis"); + MODULE_AUTHOR("Frank"); + MODULE_LICENSE("GPL"); +@@ -1762,6 +1803,7 @@ MODULE_LICENSE("GPL"); + static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, + { /* sentinal */ } + }; + diff --git a/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch b/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch new file mode 100644 index 0000000000..94fc32aadb --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch @@ -0,0 +1,26 @@ +From 4104a713204d62aca482eebb0c6226d82a0721eb Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Sat, 28 Jan 2023 14:35:57 +0800 +Subject: [PATCH] net: phy: fix the spelling problem of Sentinel + +CHECK: 'sentinal' may be misspelled - perhaps 'sentinel'? + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20230128063558.5850-1-Frank.Sae@motor-comm.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/motorcomm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1804,7 +1804,7 @@ static const struct mdio_device_id __may + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, +- { /* sentinal */ } ++ { /* sentinel */ } + }; + + MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); diff --git a/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch b/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch new file mode 100644 index 0000000000..076fa82d26 --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch @@ -0,0 +1,29 @@ +From 3c1dc22162d673d595855d24f95200ed2643f88f Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Sat, 28 Jan 2023 14:35:58 +0800 +Subject: [PATCH] net: phy: motorcomm: change the phy id of yt8521 and yt8531s + to lowercase + +The phy id is usually defined in lower case. + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20230128063558.5850-2-Frank.Sae@motor-comm.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/motorcomm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -12,8 +12,8 @@ + #include + + #define PHY_ID_YT8511 0x0000010a +-#define PHY_ID_YT8521 0x0000011A +-#define PHY_ID_YT8531S 0x4F51E91A ++#define PHY_ID_YT8521 0x0000011a ++#define PHY_ID_YT8531S 0x4f51e91a + + /* YT8521/YT8531S Register Overview + * UTP Register space | FIBER Register space diff --git a/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch new file mode 100644 index 0000000000..ba9a6ab4cc --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch @@ -0,0 +1,107 @@ +From 4869a146cd60fc8115230f0a45e15e534c531922 Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Thu, 2 Feb 2023 11:00:34 +0800 +Subject: [PATCH] net: phy: Add BIT macro for Motorcomm yt8521/yt8531 gigabit + ethernet phy + +Add BIT macro for Motorcomm yt8521/yt8531 gigabit ethernet phy. + This is a preparatory patch. Add BIT macro for 0xA012 reg, and + supplement for 0xA001 and 0xA003 reg. These will be used to support dts. + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 55 ++++++++++++++++++++++++++++++++++--- + 1 file changed, 51 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -161,6 +161,11 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++/* 1b0 disable 1.9ns rxc clock delay *default* ++ * 1b1 enable 1.9ns rxc clock delay ++ */ ++#define YT8521_CCR_RXC_DLY_EN BIT(8) ++#define YT8521_CCR_RXC_DLY_1_900_NS 1900 + + #define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) + #define YT8521_CCR_MODE_UTP_TO_RGMII 0 +@@ -178,22 +183,41 @@ + #define YT8521_MODE_POLL 0x3 + + #define YT8521_RGMII_CONFIG1_REG 0xA003 +- ++/* 1b0 use original tx_clk_rgmii *default* ++ * 1b1 use inverted tx_clk_rgmii. ++ */ ++#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) + /* TX Gig-E Delay is bits 3:0, default 0x1 + * TX Fast-E Delay is bits 7:4, default 0xf + * RX Delay is bits 13:10, default 0x0 + * Delay = 150ps * N + * On = 2250ps, off = 0ps + */ +-#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) ++#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) + #define YT8521_RC1R_RX_DELAY_EN (0xF << 10) + #define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) +-#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) ++#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) + #define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) + #define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) +-#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) ++#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) + #define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) + #define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) ++#define YT8521_RC1R_RGMII_0_000_NS 0 ++#define YT8521_RC1R_RGMII_0_150_NS 1 ++#define YT8521_RC1R_RGMII_0_300_NS 2 ++#define YT8521_RC1R_RGMII_0_450_NS 3 ++#define YT8521_RC1R_RGMII_0_600_NS 4 ++#define YT8521_RC1R_RGMII_0_750_NS 5 ++#define YT8521_RC1R_RGMII_0_900_NS 6 ++#define YT8521_RC1R_RGMII_1_050_NS 7 ++#define YT8521_RC1R_RGMII_1_200_NS 8 ++#define YT8521_RC1R_RGMII_1_350_NS 9 ++#define YT8521_RC1R_RGMII_1_500_NS 10 ++#define YT8521_RC1R_RGMII_1_650_NS 11 ++#define YT8521_RC1R_RGMII_1_800_NS 12 ++#define YT8521_RC1R_RGMII_1_950_NS 13 ++#define YT8521_RC1R_RGMII_2_100_NS 14 ++#define YT8521_RC1R_RGMII_2_250_NS 15 + + #define YTPHY_MISC_CONFIG_REG 0xA006 + #define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) +@@ -222,6 +246,29 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_SYNCE_CFG_REG 0xA012 ++#define YT8521_SCR_SYNCE_ENABLE BIT(5) ++/* 1b0 output 25m clock ++ * 1b1 output 125m clock *default* ++ */ ++#define YT8521_SCR_CLK_FRE_SEL_125M BIT(3) ++#define YT8521_SCR_CLK_SRC_MASK GENMASK(2, 1) ++#define YT8521_SCR_CLK_SRC_PLL_125M 0 ++#define YT8521_SCR_CLK_SRC_UTP_RX 1 ++#define YT8521_SCR_CLK_SRC_SDS_RX 2 ++#define YT8521_SCR_CLK_SRC_REF_25M 3 ++#define YT8531_SCR_SYNCE_ENABLE BIT(6) ++/* 1b0 output 25m clock *default* ++ * 1b1 output 125m clock ++ */ ++#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4) ++#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1) ++#define YT8531_SCR_CLK_SRC_PLL_125M 0 ++#define YT8531_SCR_CLK_SRC_UTP_RX 1 ++#define YT8531_SCR_CLK_SRC_SDS_RX 2 ++#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 ++#define YT8531_SCR_CLK_SRC_REF_25M 4 ++#define YT8531_SCR_CLK_SRC_SSC_25M 5 + #define YT8531S_SYNCE_CFG_REG 0xA012 + #define YT8531S_SCR_SYNCE_ENABLE BIT(6) + diff --git a/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch new file mode 100644 index 0000000000..6d89fae84c --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch @@ -0,0 +1,343 @@ +From a6e68f0f8769f79c67cdcfb6302feecd36197dec Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Thu, 2 Feb 2023 11:00:35 +0800 +Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8521 gigabit + ethernet phy + +Add dts support for Motorcomm yt8521 gigabit ethernet phy. + Add ytphy_rgmii_clk_delay_config function to support dst config for + the delay of rgmii clk. This funciont is common for yt8521, yt8531s + and yt8531. + This patch has been verified on AM335x platform. + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 253 ++++++++++++++++++++++++++++-------- + 1 file changed, 199 insertions(+), 54 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #define PHY_ID_YT8511 0x0000010a + #define PHY_ID_YT8521 0x0000011a +@@ -187,21 +188,9 @@ + * 1b1 use inverted tx_clk_rgmii. + */ + #define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) +-/* TX Gig-E Delay is bits 3:0, default 0x1 +- * TX Fast-E Delay is bits 7:4, default 0xf +- * RX Delay is bits 13:10, default 0x0 +- * Delay = 150ps * N +- * On = 2250ps, off = 0ps +- */ + #define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) +-#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) +-#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) + #define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) +-#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) +-#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) + #define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) +-#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) +-#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) + #define YT8521_RC1R_RGMII_0_000_NS 0 + #define YT8521_RC1R_RGMII_0_150_NS 1 + #define YT8521_RC1R_RGMII_0_300_NS 2 +@@ -274,6 +263,10 @@ + + /* Extended Register end */ + ++#define YTPHY_DTS_OUTPUT_CLK_DIS 0 ++#define YTPHY_DTS_OUTPUT_CLK_25M 25000000 ++#define YTPHY_DTS_OUTPUT_CLK_125M 125000000 ++ + struct yt8521_priv { + /* combo_advertising is used for case of YT8521 in combo mode, + * this means that yt8521 may work in utp or fiber mode which depends +@@ -641,6 +634,142 @@ static int yt8521_write_page(struct phy_ + }; + + /** ++ * struct ytphy_cfg_reg_map - map a config value to a register value ++ * @cfg: value in device configuration ++ * @reg: value in the register ++ */ ++struct ytphy_cfg_reg_map { ++ u32 cfg; ++ u32 reg; ++}; ++ ++static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = { ++ /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */ ++ { 0, YT8521_RC1R_RGMII_0_000_NS }, ++ { 150, YT8521_RC1R_RGMII_0_150_NS }, ++ { 300, YT8521_RC1R_RGMII_0_300_NS }, ++ { 450, YT8521_RC1R_RGMII_0_450_NS }, ++ { 600, YT8521_RC1R_RGMII_0_600_NS }, ++ { 750, YT8521_RC1R_RGMII_0_750_NS }, ++ { 900, YT8521_RC1R_RGMII_0_900_NS }, ++ { 1050, YT8521_RC1R_RGMII_1_050_NS }, ++ { 1200, YT8521_RC1R_RGMII_1_200_NS }, ++ { 1350, YT8521_RC1R_RGMII_1_350_NS }, ++ { 1500, YT8521_RC1R_RGMII_1_500_NS }, ++ { 1650, YT8521_RC1R_RGMII_1_650_NS }, ++ { 1800, YT8521_RC1R_RGMII_1_800_NS }, ++ { 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */ ++ { 2100, YT8521_RC1R_RGMII_2_100_NS }, ++ { 2250, YT8521_RC1R_RGMII_2_250_NS }, ++ ++ /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */ ++ { 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS }, ++ { 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS }, ++ { 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS }, ++ { 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS }, ++ { 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS }, ++ { 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS }, ++ { 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS }, ++ { 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS }, ++ { 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS }, ++ { 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS }, ++ { 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS }, ++ { 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS }, ++ { 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS }, ++ { 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS }, ++ { 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS }, ++ { 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS } ++}; ++ ++static u32 ytphy_get_delay_reg_value(struct phy_device *phydev, ++ const char *prop_name, ++ const struct ytphy_cfg_reg_map *tbl, ++ int tb_size, ++ u16 *rxc_dly_en, ++ u32 dflt) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ int tb_size_half = tb_size / 2; ++ u32 val; ++ int i; ++ ++ if (of_property_read_u32(node, prop_name, &val)) ++ goto err_dts_val; ++ ++ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of ++ * tb_size is valid. ++ */ ++ if (!rxc_dly_en) ++ tb_size = tb_size_half; ++ ++ for (i = 0; i < tb_size; i++) { ++ if (tbl[i].cfg == val) { ++ if (rxc_dly_en && i < tb_size_half) ++ *rxc_dly_en = 0; ++ return tbl[i].reg; ++ } ++ } ++ ++ phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n", ++ val, prop_name, dflt); ++ ++err_dts_val: ++ /* when rxc_dly_en is not NULL, it is get the delay for rx. ++ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps, ++ * so YT8521_CCR_RXC_DLY_EN should not be set. ++ */ ++ if (rxc_dly_en) ++ *rxc_dly_en = 0; ++ ++ return dflt; ++} ++ ++static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) ++{ ++ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays); ++ u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN; ++ u32 rx_reg, tx_reg; ++ u16 mask, val = 0; ++ int ret; ++ ++ rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps", ++ ytphy_rgmii_delays, tb_size, ++ &rxc_dly_en, ++ YT8521_RC1R_RGMII_1_950_NS); ++ tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps", ++ ytphy_rgmii_delays, tb_size, NULL, ++ YT8521_RC1R_RGMII_1_950_NS); ++ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ rxc_dly_en = 0; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg); ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ rxc_dly_en = 0; ++ val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) | ++ FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); ++ break; ++ default: /* do not support other modes */ ++ return -EOPNOTSUPP; ++ } ++ ++ ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, ++ YT8521_CCR_RXC_DLY_EN, rxc_dly_en); ++ if (ret < 0) ++ return ret; ++ ++ /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */ ++ mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK; ++ return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_ + */ + static int yt8521_probe(struct phy_device *phydev) + { ++ struct device_node *node = phydev->mdio.dev.of_node; + struct device *dev = &phydev->mdio.dev; + struct yt8521_priv *priv; + int chip_config; ++ u16 mask, val; ++ u32 freq; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_devic + return ret; + } + +- return 0; ++ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) ++ freq = YTPHY_DTS_OUTPUT_CLK_DIS; ++ ++ if (phydev->drv->phy_id == PHY_ID_YT8521) { ++ switch (freq) { ++ case YTPHY_DTS_OUTPUT_CLK_DIS: ++ mask = YT8521_SCR_SYNCE_ENABLE; ++ val = 0; ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_25M: ++ mask = YT8521_SCR_SYNCE_ENABLE | ++ YT8521_SCR_CLK_SRC_MASK | ++ YT8521_SCR_CLK_FRE_SEL_125M; ++ val = YT8521_SCR_SYNCE_ENABLE | ++ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, ++ YT8521_SCR_CLK_SRC_REF_25M); ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_125M: ++ mask = YT8521_SCR_SYNCE_ENABLE | ++ YT8521_SCR_CLK_SRC_MASK | ++ YT8521_SCR_CLK_FRE_SEL_125M; ++ val = YT8521_SCR_SYNCE_ENABLE | ++ YT8521_SCR_CLK_FRE_SEL_125M | ++ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, ++ YT8521_SCR_CLK_SRC_PLL_125M); ++ break; ++ default: ++ phydev_warn(phydev, "Freq err:%u\n", freq); ++ return -EINVAL; ++ } ++ } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { ++ return 0; ++ } else { ++ phydev_warn(phydev, "PHY id err\n"); ++ return -EINVAL; ++ } ++ ++ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, ++ val); + } + + /** +@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_devi + */ + static int yt8521_config_init(struct phy_device *phydev) + { ++ struct device_node *node = phydev->mdio.dev.of_node; + int old_page; + int ret = 0; +- u16 val; + + old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); + if (old_page < 0) + goto err_restore_page; + +- switch (phydev->interface) { +- case PHY_INTERFACE_MODE_RGMII: +- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; +- val |= YT8521_RC1R_RX_DELAY_DIS; +- break; +- case PHY_INTERFACE_MODE_RGMII_RXID: +- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; +- val |= YT8521_RC1R_RX_DELAY_EN; +- break; +- case PHY_INTERFACE_MODE_RGMII_TXID: +- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; +- val |= YT8521_RC1R_RX_DELAY_DIS; +- break; +- case PHY_INTERFACE_MODE_RGMII_ID: +- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; +- val |= YT8521_RC1R_RX_DELAY_EN; +- break; +- case PHY_INTERFACE_MODE_SGMII: +- break; +- default: /* do not support other modes */ +- ret = -EOPNOTSUPP; +- goto err_restore_page; +- } +- + /* set rgmii delay mode */ + if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { +- ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, +- (YT8521_RC1R_RX_DELAY_MASK | +- YT8521_RC1R_FE_TX_DELAY_MASK | +- YT8521_RC1R_GE_TX_DELAY_MASK), +- val); ++ ret = ytphy_rgmii_clk_delay_config(phydev); + if (ret < 0) + goto err_restore_page; + } + +- /* disable auto sleep */ +- ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, +- YT8521_ESC1R_SLEEP_SW, 0); +- if (ret < 0) +- goto err_restore_page; +- +- /* enable RXC clock when no wire plug */ +- ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, +- YT8521_CGR_RX_CLK_EN, 0); +- if (ret < 0) +- goto err_restore_page; ++ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { ++ /* disable auto sleep */ ++ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, ++ YT8521_ESC1R_SLEEP_SW, 0); ++ if (ret < 0) ++ goto err_restore_page; ++ } + ++ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { ++ /* enable RXC clock when no wire plug */ ++ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, ++ YT8521_CGR_RX_CLK_EN, 0); ++ if (ret < 0) ++ goto err_restore_page; ++ } + err_restore_page: + return phy_restore_page(phydev, old_page, ret); + } diff --git a/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch new file mode 100644 index 0000000000..86fc04695c --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch @@ -0,0 +1,100 @@ +From 36152f87dda4af221b16258751451d9cd3d0fb0b Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Thu, 2 Feb 2023 11:00:36 +0800 +Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8531s gigabit + ethernet phy + +Add dts support for Motorcomm yt8531s gigabit ethernet phy. + Change yt8521_probe to support clk config of yt8531s. Becase + yt8521_probe does the things which yt8531s is needed, so + removed yt8531s function. + This patch has been verified on AM335x platform with yt8531s board. + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 51 ++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 24 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -258,8 +258,6 @@ + #define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 + #define YT8531_SCR_CLK_SRC_REF_25M 4 + #define YT8531_SCR_CLK_SRC_SSC_25M 5 +-#define YT8531S_SYNCE_CFG_REG 0xA012 +-#define YT8531S_SCR_SYNCE_ENABLE BIT(6) + + /* Extended Register end */ + +@@ -858,7 +856,32 @@ static int yt8521_probe(struct phy_devic + return -EINVAL; + } + } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { +- return 0; ++ switch (freq) { ++ case YTPHY_DTS_OUTPUT_CLK_DIS: ++ mask = YT8531_SCR_SYNCE_ENABLE; ++ val = 0; ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_25M: ++ mask = YT8531_SCR_SYNCE_ENABLE | ++ YT8531_SCR_CLK_SRC_MASK | ++ YT8531_SCR_CLK_FRE_SEL_125M; ++ val = YT8531_SCR_SYNCE_ENABLE | ++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, ++ YT8531_SCR_CLK_SRC_REF_25M); ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_125M: ++ mask = YT8531_SCR_SYNCE_ENABLE | ++ YT8531_SCR_CLK_SRC_MASK | ++ YT8531_SCR_CLK_FRE_SEL_125M; ++ val = YT8531_SCR_SYNCE_ENABLE | ++ YT8531_SCR_CLK_FRE_SEL_125M | ++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, ++ YT8531_SCR_CLK_SRC_PLL_125M); ++ break; ++ default: ++ phydev_warn(phydev, "Freq err:%u\n", freq); ++ return -EINVAL; ++ } + } else { + phydev_warn(phydev, "PHY id err\n"); + return -EINVAL; +@@ -869,26 +892,6 @@ static int yt8521_probe(struct phy_devic + } + + /** +- * yt8531s_probe() - read chip config then set suitable polling_mode +- * @phydev: a pointer to a &struct phy_device +- * +- * returns 0 or negative errno code +- */ +-static int yt8531s_probe(struct phy_device *phydev) +-{ +- int ret; +- +- /* Disable SyncE clock output by default */ +- ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, +- YT8531S_SCR_SYNCE_ENABLE, 0); +- if (ret < 0) +- return ret; +- +- /* same as yt8521_probe */ +- return yt8521_probe(phydev); +-} +- +-/** + * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp + * @phydev: a pointer to a &struct phy_device + * +@@ -1970,7 +1973,7 @@ static struct phy_driver motorcomm_phy_d + PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), + .name = "YT8531S Gigabit Ethernet", + .get_features = yt8521_get_features, +- .probe = yt8531s_probe, ++ .probe = yt8521_probe, + .read_page = yt8521_read_page, + .write_page = yt8521_write_page, + .get_wol = ytphy_get_wol, diff --git a/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch new file mode 100644 index 0000000000..60eea4fa47 --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch @@ -0,0 +1,302 @@ +From 4ac94f728a588e7096dd5010cd7141a309ea7805 Mon Sep 17 00:00:00 2001 +From: Frank Sae +Date: Thu, 2 Feb 2023 11:00:37 +0800 +Subject: [PATCH] net: phy: Add driver for Motorcomm yt8531 gigabit ethernet + phy + +Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have + verified the driver on AM335x platform with yt8531 board. On the + board, yt8531 gigabit ethernet phy works in utp mode, RGMII + interface, supports 1000M/100M/10M speeds, and wol(magic package). + +Signed-off-by: Frank Sae +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 2 +- + drivers/net/phy/motorcomm.c | 208 +++++++++++++++++++++++++++++++++++- + 2 files changed, 207 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY + tristate "Motorcomm PHYs" + help + Enables support for Motorcomm network PHYs. +- Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. ++ Currently supports YT85xx Gigabit Ethernet PHYs. + + config NATIONAL_PHY + tristate "National Semiconductor PHYs" +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Motorcomm 8511/8521/8531S PHY driver. ++ * Motorcomm 8511/8521/8531/8531S PHY driver. + * + * Author: Peter Geis + * Author: Frank +@@ -14,6 +14,7 @@ + + #define PHY_ID_YT8511 0x0000010a + #define PHY_ID_YT8521 0x0000011a ++#define PHY_ID_YT8531 0x4f51e91b + #define PHY_ID_YT8531S 0x4f51e91a + + /* YT8521/YT8531S Register Overview +@@ -517,6 +518,61 @@ err_restore_page: + return phy_restore_page(phydev, old_page, ret); + } + ++static int yt8531_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ const u16 mac_addr_reg[] = { ++ YTPHY_WOL_MACADDR2_REG, ++ YTPHY_WOL_MACADDR1_REG, ++ YTPHY_WOL_MACADDR0_REG, ++ }; ++ const u8 *mac_addr; ++ u16 mask, val; ++ int ret; ++ u8 i; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ mac_addr = phydev->attached_dev->dev_addr; ++ ++ /* Store the device address for the magic packet */ ++ for (i = 0; i < 3; i++) { ++ ret = ytphy_write_ext_with_lock(phydev, mac_addr_reg[i], ++ ((mac_addr[i * 2] << 8)) | ++ (mac_addr[i * 2 + 1])); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* Enable WOL feature */ ++ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; ++ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; ++ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; ++ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, ++ mask, val); ++ if (ret < 0) ++ return ret; ++ ++ /* Enable WOL interrupt */ ++ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, ++ YTPHY_IER_WOL); ++ if (ret < 0) ++ return ret; ++ } else { ++ /* Disable WOL feature */ ++ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; ++ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, ++ mask, 0); ++ ++ /* Disable WOL interrupt */ ++ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, ++ YTPHY_IER_WOL, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int yt8511_read_page(struct phy_device *phydev) + { + return __phy_read(phydev, YT8511_PAGE_SELECT); +@@ -767,6 +823,17 @@ static int ytphy_rgmii_clk_delay_config( + return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); + } + ++static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = ytphy_rgmii_clk_delay_config(phydev); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ + /** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device +@@ -891,6 +958,43 @@ static int yt8521_probe(struct phy_devic + val); + } + ++static int yt8531_probe(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u16 mask, val; ++ u32 freq; ++ ++ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) ++ freq = YTPHY_DTS_OUTPUT_CLK_DIS; ++ ++ switch (freq) { ++ case YTPHY_DTS_OUTPUT_CLK_DIS: ++ mask = YT8531_SCR_SYNCE_ENABLE; ++ val = 0; ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_25M: ++ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | ++ YT8531_SCR_CLK_FRE_SEL_125M; ++ val = YT8531_SCR_SYNCE_ENABLE | ++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, ++ YT8531_SCR_CLK_SRC_REF_25M); ++ break; ++ case YTPHY_DTS_OUTPUT_CLK_125M: ++ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | ++ YT8531_SCR_CLK_FRE_SEL_125M; ++ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M | ++ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, ++ YT8531_SCR_CLK_SRC_PLL_125M); ++ break; ++ default: ++ phydev_warn(phydev, "Freq err:%u\n", freq); ++ return -EINVAL; ++ } ++ ++ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, ++ val); ++} ++ + /** + * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp + * @phydev: a pointer to a &struct phy_device +@@ -1387,6 +1491,94 @@ err_restore_page: + return phy_restore_page(phydev, old_page, ret); + } + ++static int yt8531_config_init(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ int ret; ++ ++ ret = ytphy_rgmii_clk_delay_config_with_lock(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { ++ /* disable auto sleep */ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YT8521_EXTREG_SLEEP_CONTROL1_REG, ++ YT8521_ESC1R_SLEEP_SW, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { ++ /* enable RXC clock when no wire plug */ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YT8521_CLOCK_GATING_REG, ++ YT8521_CGR_RX_CLK_EN, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * yt8531_link_change_notify() - Adjust the tx clock direction according to ++ * the current speed and dts config. ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * NOTE: This function is only used to adapt to VF2 with JH7110 SoC. Please ++ * keep "motorcomm,tx-clk-adj-enabled" not exist in dts when the soc is not ++ * JH7110. ++ */ ++static void yt8531_link_change_notify(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ bool tx_clk_adj_enabled = false; ++ bool tx_clk_1000_inverted; ++ bool tx_clk_100_inverted; ++ bool tx_clk_10_inverted; ++ u16 val = 0; ++ int ret; ++ ++ if (of_property_read_bool(node, "motorcomm,tx-clk-adj-enabled")) ++ tx_clk_adj_enabled = true; ++ ++ if (!tx_clk_adj_enabled) ++ return; ++ ++ if (of_property_read_bool(node, "motorcomm,tx-clk-10-inverted")) ++ tx_clk_10_inverted = true; ++ if (of_property_read_bool(node, "motorcomm,tx-clk-100-inverted")) ++ tx_clk_100_inverted = true; ++ if (of_property_read_bool(node, "motorcomm,tx-clk-1000-inverted")) ++ tx_clk_1000_inverted = true; ++ ++ if (phydev->speed < 0) ++ return; ++ ++ switch (phydev->speed) { ++ case SPEED_1000: ++ if (tx_clk_1000_inverted) ++ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; ++ break; ++ case SPEED_100: ++ if (tx_clk_100_inverted) ++ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; ++ break; ++ case SPEED_10: ++ if (tx_clk_10_inverted) ++ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; ++ break; ++ default: ++ return; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, YT8521_RGMII_CONFIG1_REG, ++ YT8521_RC1R_TX_CLK_SEL_INVERTED, val); ++ if (ret < 0) ++ phydev_warn(phydev, "Modify TX_CLK_SEL err:%d\n", ret); ++} ++ + /** + * yt8521_prepare_fiber_features() - A small helper function that setup + * fiber's features. +@@ -1970,6 +2162,17 @@ static struct phy_driver motorcomm_phy_d + .resume = yt8521_resume, + }, + { ++ PHY_ID_MATCH_EXACT(PHY_ID_YT8531), ++ .name = "YT8531 Gigabit Ethernet", ++ .probe = yt8531_probe, ++ .config_init = yt8531_config_init, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .get_wol = ytphy_get_wol, ++ .set_wol = yt8531_set_wol, ++ .link_change_notify = yt8531_link_change_notify, ++ }, ++ { + PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), + .name = "YT8531S Gigabit Ethernet", + .get_features = yt8521_get_features, +@@ -1990,7 +2193,7 @@ static struct phy_driver motorcomm_phy_d + + module_phy_driver(motorcomm_phy_drvs); + +-MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); ++MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S PHY driver"); + MODULE_AUTHOR("Peter Geis"); + MODULE_AUTHOR("Frank"); + MODULE_LICENSE("GPL"); +@@ -1998,6 +2201,7 @@ MODULE_LICENSE("GPL"); + static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, + { /* sentinel */ } + }; diff --git a/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch b/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch new file mode 100644 index 0000000000..29ae86dbbc --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch @@ -0,0 +1,34 @@ +From 9753613f7399601f9bae6ee81e9d4274246c98ab Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 15 Feb 2023 07:21:47 +0300 +Subject: [PATCH] net: phy: motorcomm: uninitialized variables in + yt8531_link_change_notify() + +These booleans are never set to false, but are just used without being +initialized. + +Fixes: 4ac94f728a58 ("net: phy: Add driver for Motorcomm yt8531 gigabit ethernet phy") +Signed-off-by: Dan Carpenter +Reviewed-by: Frank Sae +Link: https://lore.kernel.org/r/Y+xd2yJet2ImHLoQ@kili +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/motorcomm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -1533,10 +1533,10 @@ static int yt8531_config_init(struct phy + static void yt8531_link_change_notify(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; ++ bool tx_clk_1000_inverted = false; ++ bool tx_clk_100_inverted = false; ++ bool tx_clk_10_inverted = false; + bool tx_clk_adj_enabled = false; +- bool tx_clk_1000_inverted; +- bool tx_clk_100_inverted; +- bool tx_clk_10_inverted; + u16 val = 0; + int ret; + diff --git a/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch new file mode 100644 index 0000000000..010ca9b68a --- /dev/null +++ b/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch @@ -0,0 +1,170 @@ +From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 20 Jul 2023 19:15:09 +0800 +Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, and the default strength may not be +suitable for all boards. So add configurable options to better match +the boards.(e.g. StarFive VisionFive 2) + +When we configure the drive strength, we need to read the current +LDO voltage value to ensure that it is a legal value at that LDO +voltage. + +Reviewed-by: Hal Feng +Signed-off-by: Samin Guo +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 118 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -163,6 +163,10 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) ++#define YT8531_LDO_VOL_3V3 0x0 ++#define YT8531_LDO_VOL_1V8 0x2 ++ + /* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +@@ -236,6 +240,12 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 ++#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) ++#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ ++#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ ++#define YT8531_RGMII_RX_DS_DEFAULT 0x3 ++ + #define YTPHY_SYNCE_CFG_REG 0xA012 + #define YT8521_SCR_SYNCE_ENABLE BIT(5) + /* 1b0 output 25m clock +@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ + } + + /** ++ * struct ytphy_ldo_vol_map - map a current value to a register value ++ * @vol: ldo voltage ++ * @ds: value in the register ++ * @cur: value in device configuration ++ */ ++struct ytphy_ldo_vol_map { ++ u32 vol; ++ u32 ds; ++ u32 cur; ++}; ++ ++static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, ++}; ++ ++static u32 yt8531_get_ldo_vol(struct phy_device *phydev) ++{ ++ u32 val; ++ ++ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); ++ ++ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; ++} ++ ++static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) ++{ ++ u32 vol; ++ int i; ++ ++ vol = yt8531_get_ldo_vol(phydev); ++ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { ++ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) ++ return yt8531_ldo_vol[i].ds; ++ } ++ ++ return -EINVAL; ++} ++ ++static int yt8531_set_ds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 ds_field_low, ds_field_hi, val; ++ int ret, ds; ++ ++ /* set rgmii rx clk driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXC_DS_MASK, ++ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); ++ if (ret < 0) ++ return ret; ++ ++ /* set rgmii rx data driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ds_field_hi = FIELD_GET(BIT(2), ds); ++ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); ++ ++ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); ++ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, ++ ds_field_low | ds_field_hi); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy + return ret; + } + ++ ret = yt8531_set_ds(phydev); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch new file mode 100644 index 0000000000..f82c8fc622 --- /dev/null +++ b/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -0,0 +1,173 @@ +From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 13 Jul 2023 09:42:07 +0100 +Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods + +Add phylink PCS enable/disable callbacks that will allow us to place +IEEE 802.3 register compliant PCS in power-down mode while not being +used. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++-------- + include/linux/phylink.h | 16 +++++++++++++ + 2 files changed, 55 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -34,6 +34,10 @@ enum { + PHYLINK_DISABLE_STOPPED, + PHYLINK_DISABLE_LINK, + PHYLINK_DISABLE_MAC_WOL, ++ ++ PCS_STATE_DOWN = 0, ++ PCS_STATE_STARTING, ++ PCS_STATE_STARTED, + }; + + /** +@@ -72,6 +76,7 @@ struct phylink { + struct phylink_link_state phy_state; + struct work_struct resolve; + unsigned int pcs_neg_mode; ++ unsigned int pcs_state; + + bool mac_link_dropped; + bool using_mac_select_pcs; +@@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str + } + } + ++static void phylink_pcs_disable(struct phylink_pcs *pcs) ++{ ++ if (pcs && pcs->ops->pcs_disable) ++ pcs->ops->pcs_disable(pcs); ++} ++ ++static int phylink_pcs_enable(struct phylink_pcs *pcs) ++{ ++ int err = 0; ++ ++ if (pcs && pcs->ops->pcs_enable) ++ err = pcs->ops->pcs_enable(pcs); ++ ++ return err; ++} ++ + static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) +@@ -1094,11 +1115,17 @@ static void phylink_major_config(struct + /* If we have a new PCS, switch to the new PCS after preparing the MAC + * for the change. + */ +- if (pcs_changed) ++ if (pcs_changed) { ++ phylink_pcs_disable(pl->pcs); ++ + pl->pcs = pcs; ++ } + + phylink_mac_config(pl, state); + ++ if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) ++ phylink_pcs_enable(pl->pcs); ++ + neg_mode = pl->cur_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; +@@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph + pl->link_config.pause = MLO_PAUSE_AN; + pl->link_config.speed = SPEED_UNKNOWN; + pl->link_config.duplex = DUPLEX_UNKNOWN; ++ pl->pcs_state = PCS_STATE_DOWN; + pl->mac_ops = mac_ops; + __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); + timer_setup(&pl->link_poll, phylink_fixed_poll, 0); +@@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl) + if (pl->netdev) + netif_carrier_off(pl->netdev); + ++ pl->pcs_state = PCS_STATE_STARTING; ++ + /* Apply the link configuration to the MAC when starting. This allows + * a fixed-link to start with the correct parameters, and also + * ensures that we set the appropriate advertisement for Serdes links. +@@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl) + */ + phylink_mac_initial_config(pl, true); + ++ pl->pcs_state = PCS_STATE_STARTED; ++ + phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); + + if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { +@@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl) + poll = true; + } + +- switch (pl->cfg_link_an_mode) { +- case MLO_AN_FIXED: ++ if (pl->cfg_link_an_mode == MLO_AN_FIXED) + poll |= pl->config->poll_fixed_state; +- break; +- case MLO_AN_INBAND: +- if (pl->pcs) +- poll |= pl->pcs->poll; +- break; +- } ++ + if (poll) + mod_timer(&pl->link_poll, jiffies + HZ); + if (pl->phydev) +@@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl) + } + + phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); ++ ++ pl->pcs_state = PCS_STATE_DOWN; ++ ++ phylink_pcs_disable(pl->pcs); + } + EXPORT_SYMBOL_GPL(phylink_stop); + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -533,6 +533,8 @@ struct phylink_pcs { + /** + * struct phylink_pcs_ops - MAC PCS operations structure. + * @pcs_validate: validate the link configuration. ++ * @pcs_enable: enable the PCS. ++ * @pcs_disable: disable the PCS. + * @pcs_get_state: read the current MAC PCS link state from the hardware. + * @pcs_config: configure the MAC PCS for the selected mode and state. + * @pcs_an_restart: restart 802.3z BaseX autonegotiation. +@@ -542,6 +544,8 @@ struct phylink_pcs { + struct phylink_pcs_ops { + int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, + const struct phylink_link_state *state); ++ int (*pcs_enable)(struct phylink_pcs *pcs); ++ void (*pcs_disable)(struct phylink_pcs *pcs); + void (*pcs_get_state)(struct phylink_pcs *pcs, + struct phylink_link_state *state); + int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, +@@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs + const struct phylink_link_state *state); + + /** ++ * pcs_enable() - enable the PCS. ++ * @pcs: a pointer to a &struct phylink_pcs. ++ */ ++int pcs_enable(struct phylink_pcs *pcs); ++ ++/** ++ * pcs_disable() - disable the PCS. ++ * @pcs: a pointer to a &struct phylink_pcs. ++ */ ++void pcs_disable(struct phylink_pcs *pcs); ++ ++/** + * pcs_get_state() - Read the current inband link state from the hardware + * @pcs: a pointer to a &struct phylink_pcs. + * @state: a pointer to a &struct phylink_link_state. diff --git a/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch b/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch new file mode 100644 index 0000000000..6b6369761a --- /dev/null +++ b/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch @@ -0,0 +1,44 @@ +From e4ccdfb78a47132f2d215658aab8902fc457c4b4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 18 Aug 2023 04:07:46 +0100 +Subject: [PATCH 082/125] net: pcs: lynxi: implement pcs_disable op + +When switching from 10GBase-R/5GBase-R/USXGMII to one of the interface +modes provided by mtk-pcs-lynxi we need to make sure to always perform +a full configuration of the PHYA. + +Implement pcs_disable op which resets the stored interface mode to +PHY_INTERFACE_MODE_NA to trigger a full reconfiguration once the LynxI +PCS driver had previously been deselected in favor of another PCS +driver such as the to-be-added driver for the USXGMII PCS found in +MT7988. + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/f23d1a60d2c9d2fb72e32dcb0eaa5f7e867a3d68.1692327891.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -234,11 +234,19 @@ static void mtk_pcs_lynxi_link_up(struct + } + } + ++static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++} ++ + static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { + .pcs_get_state = mtk_pcs_lynxi_get_state, + .pcs_config = mtk_pcs_lynxi_config, + .pcs_an_restart = mtk_pcs_lynxi_restart_an, + .pcs_link_up = mtk_pcs_lynxi_link_up, ++ .pcs_disable = mtk_pcs_lynxi_disable, + }; + + struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, diff --git a/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch new file mode 100644 index 0000000000..c4141eee93 --- /dev/null +++ b/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch @@ -0,0 +1,136 @@ +From: Andy Ren +Date: Mon, 7 Nov 2022 09:42:42 -0800 +Subject: [PATCH] net/core: Allow live renaming when an interface is up + +Allow a network interface to be renamed when the interface +is up. + +As described in the netconsole documentation [1], when netconsole is +used as a built-in, it will bring up the specified interface as soon as +possible. As a result, user space will not be able to rename the +interface since the kernel disallows renaming of interfaces that are +administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set +by the kernel. + +The original solution [2] to this problem was to add a new parameter to +the netconsole configuration parameters that allows renaming of +the interface used by netconsole while it is administratively up. +However, during the discussion that followed, it became apparent that we +have no reason to keep the current restriction and instead we should +allow user space to rename interfaces regardless of their administrative +state: + +1. The restriction was put in place over 20 years ago when renaming was +only possible via IOCTL and before rtnetlink started notifying user +space about such changes like it does today. + +2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version +5.2 and no regressions were reported. + +3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about +the administrative state of interface. + +Therefore, allow user space to rename running interfaces by removing the +restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in +possible triage by emitting a message to the kernel log that an +interface was renamed while UP. + +[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst +[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ + +Signed-off-by: Andy Ren +Reviewed-by: Ido Schimmel +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1691,7 +1691,6 @@ struct net_device_ops { + * @IFF_FAILOVER: device is a failover master device + * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device + * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device +- * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running + * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with + * skb_headlen(skb) == 0 (data starts from frag0) + * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN +@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { + IFF_FAILOVER = 1<<27, + IFF_FAILOVER_SLAVE = 1<<28, + IFF_L3MDEV_RX_HANDLER = 1<<29, +- IFF_LIVE_RENAME_OK = 1<<30, ++ /* was IFF_LIVE_RENAME_OK */ + IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), + IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), + }; +@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { + #define IFF_FAILOVER IFF_FAILOVER + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE + #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER +-#define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK + #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR + + /* Specifies the type of the struct net_device::ml_priv pointer */ +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1188,22 +1188,6 @@ int dev_change_name(struct net_device *d + + net = dev_net(dev); + +- /* Some auto-enslaved devices e.g. failover slaves are +- * special, as userspace might rename the device after +- * the interface had been brought up and running since +- * the point kernel initiated auto-enslavement. Allow +- * live name change even when these slave devices are +- * up and running. +- * +- * Typically, users of these auto-enslaving devices +- * don't actually care about slave name change, as +- * they are supposed to operate on master interface +- * directly. +- */ +- if (dev->flags & IFF_UP && +- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) +- return -EBUSY; +- + down_write(&devnet_rename_sem); + + if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { +@@ -1220,7 +1204,8 @@ int dev_change_name(struct net_device *d + } + + if (oldname[0] && !strchr(oldname, '%')) +- netdev_info(dev, "renamed from %s\n", oldname); ++ netdev_info(dev, "renamed from %s%s\n", oldname, ++ dev->flags & IFF_UP ? " (while UP)" : ""); + + old_assign_type = dev->name_assign_type; + dev->name_assign_type = NET_NAME_RENAMED; +--- a/net/core/failover.c ++++ b/net/core/failover.c +@@ -80,14 +80,14 @@ static int failover_slave_register(struc + goto err_upper_link; + } + +- slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_register && + !fops->slave_register(slave_dev, failover_dev)) + return NOTIFY_OK; + + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + err_upper_link: + netdev_rx_handler_unregister(slave_dev); + done: +@@ -121,7 +121,7 @@ int failover_slave_unregister(struct net + + netdev_rx_handler_unregister(slave_dev); + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_unregister && + !fops->slave_unregister(slave_dev, failover_dev)) diff --git a/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch b/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch new file mode 100644 index 0000000000..17131c16d3 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch @@ -0,0 +1,158 @@ +From 69649ef8405320f81497f4757faac8234f61b167 Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Fri, 6 Jan 2023 17:07:39 +0100 +Subject: [PATCH] cdc_ether: no need to blacklist any r8152 devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The r8152 driver does not need this anymore. + +Dropping blacklist entries adds optional support for these +devices in ECM mode. + +The 8153 devices are handled by the r8153_ecm driver when +in ECM mode, and must still be blacklisted here. + +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/cdc_ether.c | 114 ------------------------------------ + 1 file changed, 114 deletions(-) + +--- a/drivers/net/usb/cdc_ether.c ++++ b/drivers/net/usb/cdc_ether.c +@@ -768,13 +768,6 @@ static const struct usb_device_id produc + .driver_info = 0, + }, + +-/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- + /* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ + { + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, +@@ -782,119 +775,12 @@ static const struct usb_device_id produc + .driver_info = 0, + }, + +-/* Samsung USB Ethernet Adapters */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-#if IS_ENABLED(CONFIG_USB_RTL8152) +-/* Linksys USB3GIGV1 Ethernet Adapter */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +-#endif +- +-/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- + /* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ + { + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, + }, +- +-/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Microsoft Surface 2 dock (based on Realtek RTL8152) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, +- +-/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ +-{ +- USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, +- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +- .driver_info = 0, +-}, + + /* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */ + { diff --git a/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch b/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch new file mode 100644 index 0000000000..565fbb3074 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch @@ -0,0 +1,46 @@ +From 02767440e1dda9861a11ca1dbe0f19a760b1d5c2 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Thu, 19 Jan 2023 15:40:43 +0800 +Subject: [PATCH] r8152: reduce the control transfer of rtl8152_get_version() + +Reduce the control transfer by moving calling rtl8152_get_version() in +rtl8152_probe(). This could prevent from calling rtl8152_get_version() +for unnecessary situations. For example, after setting config #2 for the +device, there are two interfaces and rtl8152_probe() may be called +twice. However, we don't need to call rtl8152_get_version() for this +situation. + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -9638,20 +9638,21 @@ static int rtl8152_probe(struct usb_inte + const struct usb_device_id *id) + { + struct usb_device *udev = interface_to_usbdev(intf); +- u8 version = rtl8152_get_version(intf); + struct r8152 *tp; + struct net_device *netdev; ++ u8 version; + int ret; + +- if (version == RTL_VER_UNKNOWN) +- return -ENODEV; +- + if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) + return -ENODEV; + + if (!rtl_check_vendor_ok(intf)) + return -ENODEV; + ++ version = rtl8152_get_version(intf); ++ if (version == RTL_VER_UNKNOWN) ++ return -ENODEV; ++ + usb_reset_device(udev); + netdev = alloc_etherdev(sizeof(struct r8152)); + if (!netdev) { diff --git a/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch b/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch new file mode 100644 index 0000000000..cdabca36d2 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch @@ -0,0 +1,55 @@ +From 5cc33f139e11b893ff6dc60d8a0ae865a65521ac Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Thu, 6 Apr 2023 17:14:26 -0700 +Subject: [PATCH] r8152: Add __GFP_NOWARN to big allocations + +When memory is a little tight on my system, it's pretty easy to see +warnings that look like this. + + ksoftirqd/0: page allocation failure: order:3, mode:0x40a20(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0 + ... + Call trace: + dump_backtrace+0x0/0x1e8 + show_stack+0x20/0x2c + dump_stack_lvl+0x60/0x78 + dump_stack+0x18/0x38 + warn_alloc+0x104/0x174 + __alloc_pages+0x588/0x67c + alloc_rx_agg+0xa0/0x190 [r8152 ...] + r8152_poll+0x270/0x760 [r8152 ...] + __napi_poll+0x44/0x1ec + net_rx_action+0x100/0x300 + __do_softirq+0xec/0x38c + run_ksoftirqd+0x38/0xec + smpboot_thread_fn+0xb8/0x248 + kthread+0x134/0x154 + ret_from_fork+0x10/0x20 + +On a fragmented system it's normal that order 3 allocations will +sometimes fail, especially atomic ones. The driver handles these +failures fine and the WARN just creates spam in the logs for this +case. The __GFP_NOWARN flag is exactly for this situation, so add it +to the allocation. + +NOTE: my testing is on a 5.15 system, but there should be no reason +that this would be fundamentally different on a mainline kernel. + +Signed-off-by: Douglas Anderson +Acked-by: Hayes Wang +Link: https://lore.kernel.org/r/20230406171411.1.I84dbef45786af440fd269b71e9436a96a8e7a152@changeid +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -1947,7 +1947,7 @@ static struct rx_agg *alloc_rx_agg(struc + if (!rx_agg) + return NULL; + +- rx_agg->page = alloc_pages(mflags | __GFP_COMP, order); ++ rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order); + if (!rx_agg->page) + goto free_rx; + diff --git a/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch b/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch new file mode 100644 index 0000000000..3ba79d6cc6 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch @@ -0,0 +1,70 @@ +From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Wed, 26 Jul 2023 11:08:07 +0800 +Subject: [PATCH] r8152: adjust generic_ocp_write function + +Reduce the control transfer if all bytes of first or the last DWORD are +written. + +The original method is to split the control transfer into three parts +(the first DWORD, middle continuous data, and the last DWORD). However, +they could be combined if whole bytes of the first DWORD or last DWORD +are written. That is, the first DWORD or the last DWORD could be combined +with the middle continuous data, if the byte_en is 0xff. + +Signed-off-by: Hayes Wang +Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 29 ++++++++++++++++++----------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -1313,16 +1313,24 @@ static int generic_ocp_write(struct r815 + byteen_end = byteen & BYTE_EN_END_MASK; + + byen = byteen_start | (byteen_start << 4); +- ret = set_registers(tp, index, type | byen, 4, data); +- if (ret < 0) +- goto error1; +- +- index += 4; +- data += 4; +- size -= 4; + +- if (size) { ++ /* Split the first DWORD if the byte_en is not 0xff */ ++ if (byen != BYTE_EN_DWORD) { ++ ret = set_registers(tp, index, type | byen, 4, data); ++ if (ret < 0) ++ goto error1; ++ ++ index += 4; ++ data += 4; + size -= 4; ++ } ++ ++ if (size) { ++ byen = byteen_end | (byteen_end >> 4); ++ ++ /* Split the last DWORD if the byte_en is not 0xff */ ++ if (byen != BYTE_EN_DWORD) ++ size -= 4; + + while (size) { + if (size > limit) { +@@ -1349,10 +1357,9 @@ static int generic_ocp_write(struct r815 + } + } + +- byen = byteen_end | (byteen_end >> 4); +- ret = set_registers(tp, index, type | byen, 4, data); +- if (ret < 0) +- goto error1; ++ /* Set the last DWORD */ ++ if (byen != BYTE_EN_DWORD) ++ ret = set_registers(tp, index, type | byen, 4, data); + } + + error1: diff --git a/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch b/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch new file mode 100644 index 0000000000..bc70c5af02 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch @@ -0,0 +1,129 @@ +From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Wed, 26 Jul 2023 11:08:08 +0800 +Subject: [PATCH] r8152: set bp in bulk + +PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we +could combine the control transfers into one control transfer. + +Signed-off-by: Hayes Wang +Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 75 ++++++++++++++--------------------------- + 1 file changed, 25 insertions(+), 50 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3990,29 +3990,10 @@ static void rtl_reset_bmu(struct r8152 * + /* Clear the bp to stop the firmware before loading a new one */ + static void rtl_clear_bp(struct r8152 *tp, u16 type) + { +- switch (tp->version) { +- case RTL_VER_01: +- case RTL_VER_02: +- case RTL_VER_07: +- break; +- case RTL_VER_03: +- case RTL_VER_04: +- case RTL_VER_05: +- case RTL_VER_06: +- ocp_write_byte(tp, type, PLA_BP_EN, 0); +- break; +- case RTL_VER_14: +- ocp_write_word(tp, type, USB_BP2_EN, 0); ++ u16 bp[16] = {0}; ++ u16 bp_num; + +- ocp_write_word(tp, type, USB_BP_8, 0); +- ocp_write_word(tp, type, USB_BP_9, 0); +- ocp_write_word(tp, type, USB_BP_10, 0); +- ocp_write_word(tp, type, USB_BP_11, 0); +- ocp_write_word(tp, type, USB_BP_12, 0); +- ocp_write_word(tp, type, USB_BP_13, 0); +- ocp_write_word(tp, type, USB_BP_14, 0); +- ocp_write_word(tp, type, USB_BP_15, 0); +- break; ++ switch (tp->version) { + case RTL_VER_08: + case RTL_VER_09: + case RTL_VER_10: +@@ -4020,32 +4001,31 @@ static void rtl_clear_bp(struct r8152 *t + case RTL_VER_12: + case RTL_VER_13: + case RTL_VER_15: +- default: + if (type == MCU_TYPE_USB) { + ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); +- +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0); +- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0); +- } else { +- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); ++ bp_num = 16; ++ break; + } ++ fallthrough; ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ ocp_write_byte(tp, type, PLA_BP_EN, 0); ++ fallthrough; ++ case RTL_VER_01: ++ case RTL_VER_02: ++ case RTL_VER_07: ++ bp_num = 8; ++ break; ++ case RTL_VER_14: ++ default: ++ ocp_write_word(tp, type, USB_BP2_EN, 0); ++ bp_num = 16; + break; + } + +- ocp_write_word(tp, type, PLA_BP_0, 0); +- ocp_write_word(tp, type, PLA_BP_1, 0); +- ocp_write_word(tp, type, PLA_BP_2, 0); +- ocp_write_word(tp, type, PLA_BP_3, 0); +- ocp_write_word(tp, type, PLA_BP_4, 0); +- ocp_write_word(tp, type, PLA_BP_5, 0); +- ocp_write_word(tp, type, PLA_BP_6, 0); +- ocp_write_word(tp, type, PLA_BP_7, 0); ++ generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type); + + /* wait 3 ms to make sure the firmware is stopped */ + usleep_range(3000, 6000); +@@ -5022,10 +5002,9 @@ static void rtl8152_fw_phy_nc_apply(stru + + static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) + { +- u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg; ++ u16 bp_en_addr, type, fw_ver_reg; + u32 length; + u8 *data; +- int i; + + switch (__le32_to_cpu(mac->blk_hdr.type)) { + case RTL_FW_PLA: +@@ -5067,12 +5046,8 @@ static void rtl8152_fw_mac_apply(struct + ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr), + __le16_to_cpu(mac->bp_ba_value)); + +- bp_index = __le16_to_cpu(mac->bp_start); +- bp_num = __le16_to_cpu(mac->bp_num); +- for (i = 0; i < bp_num; i++) { +- ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i])); +- bp_index += 2; +- } ++ generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD, ++ __le16_to_cpu(mac->bp_num) << 1, mac->bp, type); + + bp_en_addr = __le16_to_cpu(mac->bp_en_addr); + if (bp_en_addr) diff --git a/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch b/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch new file mode 100644 index 0000000000..d7fdcdb2c6 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch @@ -0,0 +1,39 @@ +From cf74eb5a5bc867258e7d0b0d1c3c4a60e1e3de2f Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Mon, 14 Aug 2023 08:35:21 -0700 +Subject: [PATCH] eth: r8152: try to use a normal budget + +Mario reports that loading r8152 on his system leads to a: + + netif_napi_add_weight() called with weight 256 + +warning getting printed. We don't have any solid data +on why such high budget was chosen, and it may cause +stalls in processing other softirqs and rt threads. +So try to switch back to the default (64) weight. + +If this slows down someone's system we should investigate +which part of stopping starting the NAPI poll in this +driver are expensive. + +Reported-by: Mario Limonciello +Link: https://lore.kernel.org/all/0bfd445a-81f7-f702-08b0-bd5a72095e49@amd.com/ +Acked-by: Hayes Wang +Link: https://lore.kernel.org/r/20230814153521.2697982-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -9784,8 +9784,7 @@ static int rtl8152_probe(struct usb_inte + + usb_set_intfdata(intf, tp); + +- netif_napi_add_weight(netdev, &tp->napi, r8152_poll, +- tp->support_2500full ? 256 : 64); ++ netif_napi_add(netdev, &tp->napi, r8152_poll); + + ret = register_netdev(netdev); + if (ret != 0) { diff --git a/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch b/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch new file mode 100644 index 0000000000..8901767be5 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch @@ -0,0 +1,398 @@ +From d9962b0d42029bcb40fe3c38bce06d1870fa4df4 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Fri, 20 Oct 2023 14:06:59 -0700 +Subject: [PATCH] r8152: Block future register access if register access fails + +Even though the functions to read/write registers can fail, most of +the places in the r8152 driver that read/write register values don't +check error codes. The lack of error code checking is problematic in +at least two ways. + +The first problem is that the r8152 driver often uses code patterns +similar to this: + x = read_register() + x = x | SOME_BIT; + write_register(x); + +...with the above pattern, if the read_register() fails and returns +garbage then we'll end up trying to write modified garbage back to the +Realtek adapter. If the write_register() succeeds that's bad. Note +that as of commit f53a7ad18959 ("r8152: Set memory to all 0xFFs on +failed reg reads") the "garbage" returned by read_register() will at +least be consistent garbage, but it is still garbage. + +It turns out that this problem is very serious. Writing garbage to +some of the hardware registers on the Ethernet adapter can put the +adapter in such a bad state that it needs to be power cycled (fully +unplugged and plugged in again) before it can enumerate again. + +The second problem is that the r8152 driver generally has functions +that are long sequences of register writes. Assuming everything will +be OK if a random register write fails in the middle isn't a great +assumption. + +One might wonder if the above two problems are real. You could ask if +we would really have a successful write after a failed read. It turns +out that the answer appears to be "yes, this can happen". In fact, +we've seen at least two distinct failure modes where this happens. + +On a sc7180-trogdor Chromebook if you drop into kdb for a while and +then resume, you can see: +1. We get a "Tx timeout" +2. The "Tx timeout" queues up a USB reset. +3. In rtl8152_pre_reset() we try to reinit the hardware. +4. The first several (2-9) register accesses fail with a timeout, then + things recover. + +The above test case was actually fixed by the patch ("r8152: Increase +USB control msg timeout to 5000ms as per spec") but at least shows +that we really can see successful calls after failed ones. + +On a different (AMD) based Chromebook with a particular adapter, we +found that during reboot tests we'd also sometimes get a transitory +failure. In this case we saw -EPIPE being returned sometimes. Retrying +worked, but retrying is not always safe for all register accesses +since reading/writing some registers might have side effects (like +registers that clear on read). + +Let's fully lock out all register access if a register access fails. +When we do this, we'll try to queue up a USB reset and try to unlock +register access after the reset. This is slightly tricker than it +sounds since the r8152 driver has an optimized reset sequence that +only works reliably after probe happens. In order to handle this, we +avoid the optimized reset if probe didn't finish. Instead, we simply +retry the probe routine in this case. + +When locking out access, we'll use the existing infrastructure that +the driver was using when it detected we were unplugged. This keeps us +from getting stuck in delay loops in some parts of the driver. + +Signed-off-by: Douglas Anderson +Reviewed-by: Grant Grundler +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 207 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 176 insertions(+), 31 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -772,6 +772,9 @@ enum rtl8152_flags { + SCHEDULE_TASKLET, + GREEN_ETHERNET, + RX_EPROTO, ++ IN_PRE_RESET, ++ PROBED_WITH_NO_ERRORS, ++ PROBE_SHOULD_RETRY, + }; + + #define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB 0x721e +@@ -952,6 +955,8 @@ struct r8152 { + u8 version; + u8 duplex; + u8 autoneg; ++ ++ unsigned int reg_access_reset_count; + }; + + /** +@@ -1199,6 +1204,96 @@ static unsigned int agg_buf_sz = 16384; + + #define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) + ++/* If register access fails then we block access and issue a reset. If this ++ * happens too many times in a row without a successful access then we stop ++ * trying to reset and just leave access blocked. ++ */ ++#define REGISTER_ACCESS_MAX_RESETS 3 ++ ++static void rtl_set_inaccessible(struct r8152 *tp) ++{ ++ set_bit(RTL8152_INACCESSIBLE, &tp->flags); ++ smp_mb__after_atomic(); ++} ++ ++static void rtl_set_accessible(struct r8152 *tp) ++{ ++ clear_bit(RTL8152_INACCESSIBLE, &tp->flags); ++ smp_mb__after_atomic(); ++} ++ ++static ++int r8152_control_msg(struct r8152 *tp, unsigned int pipe, __u8 request, ++ __u8 requesttype, __u16 value, __u16 index, void *data, ++ __u16 size, const char *msg_tag) ++{ ++ struct usb_device *udev = tp->udev; ++ int ret; ++ ++ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) ++ return -ENODEV; ++ ++ ret = usb_control_msg(udev, pipe, request, requesttype, ++ value, index, data, size, ++ USB_CTRL_GET_TIMEOUT); ++ ++ /* No need to issue a reset to report an error if the USB device got ++ * unplugged; just return immediately. ++ */ ++ if (ret == -ENODEV) ++ return ret; ++ ++ /* If the write was successful then we're done */ ++ if (ret >= 0) { ++ tp->reg_access_reset_count = 0; ++ return ret; ++ } ++ ++ dev_err(&udev->dev, ++ "Failed to %s %d bytes at %#06x/%#06x (%d)\n", ++ msg_tag, size, value, index, ret); ++ ++ /* Block all future register access until we reset. Much of the code ++ * in the driver doesn't check for errors. Notably, many parts of the ++ * driver do a read/modify/write of a register value without ++ * confirming that the read succeeded. Writing back modified garbage ++ * like this can fully wedge the adapter, requiring a power cycle. ++ */ ++ rtl_set_inaccessible(tp); ++ ++ /* If probe hasn't yet finished, then we'll request a retry of the ++ * whole probe routine if we get any control transfer errors. We ++ * never have to clear this bit since we free/reallocate the whole "tp" ++ * structure if we retry probe. ++ */ ++ if (!test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) { ++ set_bit(PROBE_SHOULD_RETRY, &tp->flags); ++ return ret; ++ } ++ ++ /* Failing to access registers in pre-reset is not surprising since we ++ * wouldn't be resetting if things were behaving normally. The register ++ * access we do in pre-reset isn't truly mandatory--we're just reusing ++ * the disable() function and trying to be nice by powering the ++ * adapter down before resetting it. Thus, if we're in pre-reset, ++ * we'll return right away and not try to queue up yet another reset. ++ * We know the post-reset is already coming. ++ */ ++ if (test_bit(IN_PRE_RESET, &tp->flags)) ++ return ret; ++ ++ if (tp->reg_access_reset_count < REGISTER_ACCESS_MAX_RESETS) { ++ usb_queue_reset_device(tp->intf); ++ tp->reg_access_reset_count++; ++ } else if (tp->reg_access_reset_count == REGISTER_ACCESS_MAX_RESETS) { ++ dev_err(&udev->dev, ++ "Tried to reset %d times; giving up.\n", ++ REGISTER_ACCESS_MAX_RESETS); ++ } ++ ++ return ret; ++} ++ + static + int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) + { +@@ -1209,9 +1304,10 @@ int get_registers(struct r8152 *tp, u16 + if (!tmp) + return -ENOMEM; + +- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_in, +- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, +- value, index, tmp, size, USB_CTRL_GET_TIMEOUT); ++ ret = r8152_control_msg(tp, tp->pipe_ctrl_in, ++ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, ++ value, index, tmp, size, "read"); ++ + if (ret < 0) + memset(data, 0xff, size); + else +@@ -1232,9 +1328,9 @@ int set_registers(struct r8152 *tp, u16 + if (!tmp) + return -ENOMEM; + +- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_out, +- RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, +- value, index, tmp, size, USB_CTRL_SET_TIMEOUT); ++ ret = r8152_control_msg(tp, tp->pipe_ctrl_out, ++ RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, ++ value, index, tmp, size, "write"); + + kfree(tmp); + +@@ -1243,10 +1339,8 @@ int set_registers(struct r8152 *tp, u16 + + static void rtl_set_unplug(struct r8152 *tp) + { +- if (tp->udev->state == USB_STATE_NOTATTACHED) { +- set_bit(RTL8152_INACCESSIBLE, &tp->flags); +- smp_mb__after_atomic(); +- } ++ if (tp->udev->state == USB_STATE_NOTATTACHED) ++ rtl_set_inaccessible(tp); + } + + static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, +@@ -8275,7 +8369,7 @@ static int rtl8152_pre_reset(struct usb_ + struct r8152 *tp = usb_get_intfdata(intf); + struct net_device *netdev; + +- if (!tp) ++ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) + return 0; + + netdev = tp->netdev; +@@ -8290,7 +8384,9 @@ static int rtl8152_pre_reset(struct usb_ + napi_disable(&tp->napi); + if (netif_carrier_ok(netdev)) { + mutex_lock(&tp->control); ++ set_bit(IN_PRE_RESET, &tp->flags); + tp->rtl_ops.disable(tp); ++ clear_bit(IN_PRE_RESET, &tp->flags); + mutex_unlock(&tp->control); + } + +@@ -8303,9 +8399,11 @@ static int rtl8152_post_reset(struct usb + struct net_device *netdev; + struct sockaddr sa; + +- if (!tp) ++ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) + return 0; + ++ rtl_set_accessible(tp); ++ + /* reset the MAC address in case of policy change */ + if (determine_ethernet_addr(tp, &sa) >= 0) { + rtnl_lock(); +@@ -9507,17 +9605,29 @@ static u8 __rtl_get_hw_ver(struct usb_de + __le32 *tmp; + u8 version; + int ret; ++ int i; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return 0; + +- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), +- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, +- PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), +- USB_CTRL_GET_TIMEOUT); +- if (ret > 0) +- ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; ++ /* Retry up to 3 times in case there is a transitory error. We do this ++ * since retrying a read of the version is always safe and this ++ * function doesn't take advantage of r8152_control_msg(). ++ */ ++ for (i = 0; i < 3; i++) { ++ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ++ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, ++ PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), ++ USB_CTRL_GET_TIMEOUT); ++ if (ret > 0) { ++ ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; ++ break; ++ } ++ } ++ ++ if (i != 0 && ret > 0) ++ dev_warn(&udev->dev, "Needed %d retries to read version\n", i); + + kfree(tmp); + +@@ -9616,25 +9726,14 @@ static bool rtl8152_supports_lenovo_macp + return 0; + } + +-static int rtl8152_probe(struct usb_interface *intf, +- const struct usb_device_id *id) ++static int rtl8152_probe_once(struct usb_interface *intf, ++ const struct usb_device_id *id, u8 version) + { + struct usb_device *udev = interface_to_usbdev(intf); + struct r8152 *tp; + struct net_device *netdev; +- u8 version; + int ret; + +- if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) +- return -ENODEV; +- +- if (!rtl_check_vendor_ok(intf)) +- return -ENODEV; +- +- version = rtl8152_get_version(intf); +- if (version == RTL_VER_UNKNOWN) +- return -ENODEV; +- + usb_reset_device(udev); + netdev = alloc_etherdev(sizeof(struct r8152)); + if (!netdev) { +@@ -9797,10 +9896,20 @@ static int rtl8152_probe(struct usb_inte + else + device_set_wakeup_enable(&udev->dev, false); + ++ /* If we saw a control transfer error while probing then we may ++ * want to try probe() again. Consider this an error. ++ */ ++ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) ++ goto out2; ++ ++ set_bit(PROBED_WITH_NO_ERRORS, &tp->flags); + netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); + + return 0; + ++out2: ++ unregister_netdev(netdev); ++ + out1: + tasklet_kill(&tp->tx_tl); + cancel_delayed_work_sync(&tp->hw_phy_work); +@@ -9809,10 +9918,46 @@ out1: + rtl8152_release_firmware(tp); + usb_set_intfdata(intf, NULL); + out: ++ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) ++ ret = -EAGAIN; ++ + free_netdev(netdev); + return ret; + } + ++#define RTL8152_PROBE_TRIES 3 ++ ++static int rtl8152_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ u8 version; ++ int ret; ++ int i; ++ ++ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) ++ return -ENODEV; ++ ++ if (!rtl_check_vendor_ok(intf)) ++ return -ENODEV; ++ ++ version = rtl8152_get_version(intf); ++ if (version == RTL_VER_UNKNOWN) ++ return -ENODEV; ++ ++ for (i = 0; i < RTL8152_PROBE_TRIES; i++) { ++ ret = rtl8152_probe_once(intf, id, version); ++ if (ret != -EAGAIN) ++ break; ++ } ++ if (ret == -EAGAIN) { ++ dev_err(&intf->dev, ++ "r8152 failed probe after %d tries; giving up\n", i); ++ return -ENODEV; ++ } ++ ++ return ret; ++} ++ + static void rtl8152_disconnect(struct usb_interface *intf) + { + struct r8152 *tp = usb_get_intfdata(intf); diff --git a/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch b/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch new file mode 100644 index 0000000000..7bbd1be820 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch @@ -0,0 +1,83 @@ +From 66eee612a1ba39f9a76a9ace4a34d012044767fb Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Tue, 26 Sep 2023 19:17:13 +0800 +Subject: [PATCH] r8152: break the loop when the budget is exhausted + +[ Upstream commit 2cf51f931797d9a47e75d999d0993a68cbd2a560 ] + +A bulk transfer of the USB may contain many packets. And, the total +number of the packets in the bulk transfer may be more than budget. + +Originally, only budget packets would be handled by napi_gro_receive(), +and the other packets would be queued in the driver for next schedule. + +This patch would break the loop about getting next bulk transfer, when +the budget is exhausted. That is, only the current bulk transfer would +be handled, and the other bulk transfers would be queued for next +schedule. Besides, the packets which are more than the budget in the +current bulk trasnfer would be still queued in the driver, as the +original method. + +In addition, a bulk transfer wouldn't contain more than 400 packets, so +the check of queue length is unnecessary. Therefore, I replace it with +WARN_ON_ONCE(). + +Fixes: cf74eb5a5bc8 ("eth: r8152: try to use a normal budget") +Signed-off-by: Hayes Wang +Link: https://lore.kernel.org/r/20230926111714.9448-433-nic_swsd@realtek.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2542,7 +2542,7 @@ static int rx_bottom(struct r8152 *tp, i + } + } + +- if (list_empty(&tp->rx_done)) ++ if (list_empty(&tp->rx_done) || work_done >= budget) + goto out1; + + clear_bit(RX_EPROTO, &tp->flags); +@@ -2558,6 +2558,15 @@ static int rx_bottom(struct r8152 *tp, i + struct urb *urb; + u8 *rx_data; + ++ /* A bulk transfer of USB may contain may packets, so the ++ * total packets may more than the budget. Deal with all ++ * packets in current bulk transfer, and stop to handle the ++ * next bulk transfer until next schedule, if budget is ++ * exhausted. ++ */ ++ if (work_done >= budget) ++ break; ++ + list_del_init(cursor); + + agg = list_entry(cursor, struct rx_agg, list); +@@ -2577,9 +2586,7 @@ static int rx_bottom(struct r8152 *tp, i + unsigned int pkt_len, rx_frag_head_sz; + struct sk_buff *skb; + +- /* limit the skb numbers for rx_queue */ +- if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000)) +- break; ++ WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000); + + pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; + if (pkt_len < ETH_ZLEN) +@@ -2657,9 +2664,10 @@ submit: + } + } + ++ /* Splice the remained list back to rx_done for next schedule */ + if (!list_empty(&rx_queue)) { + spin_lock_irqsave(&tp->rx_lock, flags); +- list_splice_tail(&rx_queue, &tp->rx_done); ++ list_splice(&rx_queue, &tp->rx_done); + spin_unlock_irqrestore(&tp->rx_lock, flags); + } + diff --git a/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch b/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch new file mode 100644 index 0000000000..c858152067 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch @@ -0,0 +1,47 @@ +From 1b0fce8c8e69485e49a7d34aac3d4c2a2aa15d62 Mon Sep 17 00:00:00 2001 +From: Davide Tronchin +Date: Thu, 29 Jun 2023 12:37:36 +0200 +Subject: [PATCH] net: usb: cdc_ether: add u-blox 0x1313 composition. + +Add CDC-ECM support for LARA-R6 01B. + +The new LARA-R6 product variant identified by the "01B" string can be +configured (by AT interface) in three different USB modes: +* Default mode (Vendor ID: 0x1546 Product ID: 0x1311) with 4 serial +interfaces +* RmNet mode (Vendor ID: 0x1546 Product ID: 0x1312) with 4 serial +interfaces and 1 RmNet virtual network interface +* CDC-ECM mode (Vendor ID: 0x1546 Product ID: 0x1313) with 4 serial +interface and 1 CDC-ECM virtual network interface +The first 4 interfaces of all the 3 configurations (default, RmNet, ECM) +are the same. + +In CDC-ECM mode LARA-R6 01B exposes the following interfaces: +If 0: Diagnostic +If 1: AT parser +If 2: AT parser +If 3: AT parset/alternative functions +If 4: CDC-ECM interface + +Signed-off-by: Davide Tronchin +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/usb/cdc_ether.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/usb/cdc_ether.c ++++ b/drivers/net/usb/cdc_ether.c +@@ -879,6 +879,12 @@ static const struct usb_device_id produc + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, + }, { ++ /* U-blox LARA-R6 01B */ ++ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM, ++ USB_CDC_SUBCLASS_ETHERNET, ++ USB_CDC_PROTO_NONE), ++ .driver_info = (unsigned long)&wwan_info, ++}, { + /* ZTE modules */ + USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, diff --git a/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch b/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch new file mode 100644 index 0000000000..3c9680a279 --- /dev/null +++ b/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch @@ -0,0 +1,122 @@ +From 788d30daa8f97f06166b6a63f0e51f2a4c2f036a Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Tue, 26 Sep 2023 19:17:14 +0800 +Subject: [PATCH] r8152: use napi_gro_frags + +Use napi_gro_frags() for the skb of fragments when the work_done is less +than budget. + +Signed-off-by: Hayes Wang +Link: https://lore.kernel.org/r/20230926111714.9448-434-nic_swsd@realtek.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 67 ++++++++++++++++++++++++++++++----------- + 1 file changed, 50 insertions(+), 17 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2583,8 +2583,9 @@ static int rx_bottom(struct r8152 *tp, i + while (urb->actual_length > len_used) { + struct net_device *netdev = tp->netdev; + struct net_device_stats *stats = &netdev->stats; +- unsigned int pkt_len, rx_frag_head_sz; ++ unsigned int pkt_len, rx_frag_head_sz, len; + struct sk_buff *skb; ++ bool use_frags; + + WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000); + +@@ -2597,45 +2598,77 @@ static int rx_bottom(struct r8152 *tp, i + break; + + pkt_len -= ETH_FCS_LEN; ++ len = pkt_len; + rx_data += sizeof(struct rx_desc); + +- if (!agg_free || tp->rx_copybreak > pkt_len) +- rx_frag_head_sz = pkt_len; ++ if (!agg_free || tp->rx_copybreak > len) ++ use_frags = false; + else +- rx_frag_head_sz = tp->rx_copybreak; ++ use_frags = true; ++ ++ if (use_frags) { ++ /* If the budget is exhausted, the packet ++ * would be queued in the driver. That is, ++ * napi_gro_frags() wouldn't be called, so ++ * we couldn't use napi_get_frags(). ++ */ ++ if (work_done >= budget) { ++ rx_frag_head_sz = tp->rx_copybreak; ++ skb = napi_alloc_skb(napi, ++ rx_frag_head_sz); ++ } else { ++ rx_frag_head_sz = 0; ++ skb = napi_get_frags(napi); ++ } ++ } else { ++ rx_frag_head_sz = 0; ++ skb = napi_alloc_skb(napi, len); ++ } + +- skb = napi_alloc_skb(napi, rx_frag_head_sz); + if (!skb) { + stats->rx_dropped++; + goto find_next_rx; + } + + skb->ip_summed = r8152_rx_csum(tp, rx_desc); +- memcpy(skb->data, rx_data, rx_frag_head_sz); +- skb_put(skb, rx_frag_head_sz); +- pkt_len -= rx_frag_head_sz; +- rx_data += rx_frag_head_sz; +- if (pkt_len) { ++ rtl_rx_vlan_tag(rx_desc, skb); ++ ++ if (use_frags) { ++ if (rx_frag_head_sz) { ++ memcpy(skb->data, rx_data, ++ rx_frag_head_sz); ++ skb_put(skb, rx_frag_head_sz); ++ len -= rx_frag_head_sz; ++ rx_data += rx_frag_head_sz; ++ skb->protocol = eth_type_trans(skb, ++ netdev); ++ } ++ + skb_add_rx_frag(skb, 0, agg->page, + agg_offset(agg, rx_data), +- pkt_len, +- SKB_DATA_ALIGN(pkt_len)); ++ len, SKB_DATA_ALIGN(len)); + get_page(agg->page); ++ } else { ++ memcpy(skb->data, rx_data, len); ++ skb_put(skb, len); ++ skb->protocol = eth_type_trans(skb, netdev); + } + +- skb->protocol = eth_type_trans(skb, netdev); +- rtl_rx_vlan_tag(rx_desc, skb); + if (work_done < budget) { ++ if (use_frags) ++ napi_gro_frags(napi); ++ else ++ napi_gro_receive(napi, skb); ++ + work_done++; + stats->rx_packets++; +- stats->rx_bytes += skb->len; +- napi_gro_receive(napi, skb); ++ stats->rx_bytes += pkt_len; + } else { + __skb_queue_tail(&tp->rx_queue, skb); + } + + find_next_rx: +- rx_data = rx_agg_align(rx_data + pkt_len + ETH_FCS_LEN); ++ rx_data = rx_agg_align(rx_data + len + ETH_FCS_LEN); + rx_desc = (struct rx_desc *)rx_data; + len_used = agg_offset(agg, rx_data); + len_used += sizeof(struct rx_desc); diff --git a/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch b/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch new file mode 100644 index 0000000000..592111fb95 --- /dev/null +++ b/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch @@ -0,0 +1,39 @@ +From 156a5bb89ca6f3edd2be0bfd0de15e575442927e Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Tue, 3 Jan 2023 15:12:47 +0200 +Subject: [PATCH] leds: Move led_init_default_state_get() to the global header + +There are users inside and outside LED framework that have implemented +a local copy of led_init_default_state_get(). In order to deduplicate +that, as the first step move the declaration from LED header to the +global one. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230103131256.33894-3-andriy.shevchenko@linux.intel.com +--- + drivers/leds/leds.h | 1 - + include/linux/leds.h | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/leds/leds.h ++++ b/drivers/leds/leds.h +@@ -27,7 +27,6 @@ ssize_t led_trigger_read(struct file *fi + ssize_t led_trigger_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t pos, size_t count); +-enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); + + extern struct rw_semaphore leds_list_lock; + extern struct list_head leds_list; +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -63,6 +63,8 @@ struct led_init_data { + bool devname_mandatory; + }; + ++enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); ++ + struct led_hw_trigger_type { + int dummy; + }; diff --git a/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch b/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch new file mode 100644 index 0000000000..f6a025fa12 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch @@ -0,0 +1,67 @@ +From 3e8b4d6277fd19d98c817576954dd6a4ff3caa2b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 17 Apr 2023 17:17:23 +0200 +Subject: [PATCH 1/9] net: dsa: qca8k: move qca8k_port_to_phy() to header + +Move qca8k_port_to_phy() to qca8k header as it's useful for future +reference in Switch LEDs module since the same logic is applied to get +the right index of the switch port. +Make it inline as it's simple function that just decrease the port. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Michal Kubiak +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 15 --------------- + drivers/net/dsa/qca/qca8k.h | 14 ++++++++++++++ + 2 files changed, 14 insertions(+), 15 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -789,21 +789,6 @@ err_clear_skb: + return ret; + } + +-static u32 +-qca8k_port_to_phy(int port) +-{ +- /* From Andrew Lunn: +- * Port 0 has no internal phy. +- * Port 1 has an internal PHY at MDIO address 0. +- * Port 2 has an internal PHY at MDIO address 1. +- * ... +- * Port 5 has an internal PHY at MDIO address 4. +- * Port 6 has no internal PHY. +- */ +- +- return port - 1; +-} +- + static int + qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) + { +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -421,6 +421,20 @@ struct qca8k_fdb { + u8 mac[6]; + }; + ++static inline u32 qca8k_port_to_phy(int port) ++{ ++ /* From Andrew Lunn: ++ * Port 0 has no internal phy. ++ * Port 1 has an internal PHY at MDIO address 0. ++ * Port 2 has an internal PHY at MDIO address 1. ++ * ... ++ * Port 5 has an internal PHY at MDIO address 4. ++ * Port 6 has no internal PHY. ++ */ ++ ++ return port - 1; ++} ++ + /* Common setup function */ + extern const struct qca8k_mib_desc ar8327_mib[]; + extern const struct regmap_access_table qca8k_readable_table; diff --git a/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch b/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch new file mode 100644 index 0000000000..409fe9c7a1 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch @@ -0,0 +1,435 @@ +From 1e264f9d2918b5737023c44a23ae04def1095210 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 17 Apr 2023 17:17:24 +0200 +Subject: [PATCH 2/9] net: dsa: qca8k: add LEDs basic support + +Add LEDs basic support for qca8k Switch Family by adding basic +brightness_set() support. + +Since these LEDs refelect port status, the default label is set to +":port". DT binding should describe the color and function of the +LEDs using standard LEDs api. +Each LED always have the device name as prefix. The device name is +composed from the mii bus id and the PHY addr resulting in example +names like: +- qca8k-0.0:00:amber:lan +- qca8k-0.0:00:white:lan +- qca8k-0.0:01:amber:lan +- qca8k-0.0:01:white:lan + +These LEDs supports only blocking variant of the brightness_set() +function since they can sleep during access of the switch leds to set +the brightness. + +While at it add to the qca8k header file each mode defined by the Switch +Documentation for future use. + +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/Kconfig | 8 ++ + drivers/net/dsa/qca/Makefile | 3 + + drivers/net/dsa/qca/qca8k-8xxx.c | 5 + + drivers/net/dsa/qca/qca8k-leds.c | 239 +++++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 60 ++++++++ + drivers/net/dsa/qca/qca8k_leds.h | 16 +++ + 6 files changed, 331 insertions(+) + create mode 100644 drivers/net/dsa/qca/qca8k-leds.c + create mode 100644 drivers/net/dsa/qca/qca8k_leds.h + +--- a/drivers/net/dsa/qca/Kconfig ++++ b/drivers/net/dsa/qca/Kconfig +@@ -15,3 +15,11 @@ config NET_DSA_QCA8K + help + This enables support for the Qualcomm Atheros QCA8K Ethernet + switch chips. ++ ++config NET_DSA_QCA8K_LEDS_SUPPORT ++ bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support" ++ depends on NET_DSA_QCA8K ++ depends on LEDS_CLASS ++ help ++ This enabled support for LEDs present on the Qualcomm Atheros ++ QCA8K Ethernet switch chips. +--- a/drivers/net/dsa/qca/Makefile ++++ b/drivers/net/dsa/qca/Makefile +@@ -2,3 +2,6 @@ + obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o + obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o + qca8k-y += qca8k-common.o qca8k-8xxx.o ++ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT ++qca8k-y += qca8k-leds.o ++endif +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -22,6 +22,7 @@ + #include + + #include "qca8k.h" ++#include "qca8k_leds.h" + + static void + qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) +@@ -1851,6 +1852,10 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ ret = qca8k_setup_led_ctrl(priv); ++ if (ret) ++ return ret; ++ + qca8k_setup_pcs(priv, &priv->pcs_port_0, 0); + qca8k_setup_pcs(priv, &priv->pcs_port_6, 6); + +--- /dev/null ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -0,0 +1,239 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++ ++#include "qca8k.h" ++#include "qca8k_leds.h" ++ ++static int ++qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) ++{ ++ switch (port_num) { ++ case 0: ++ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); ++ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; ++ break; ++ case 1: ++ case 2: ++ case 3: ++ /* Port 123 are controlled on a different reg */ ++ reg_info->reg = QCA8K_LED_CTRL3_REG; ++ reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num); ++ break; ++ case 4: ++ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); ++ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_led_brightness_set(struct qca8k_led *led, ++ enum led_brightness brightness) ++{ ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 mask, val; ++ ++ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); ++ ++ val = QCA8K_LED_ALWAYS_OFF; ++ if (brightness) ++ val = QCA8K_LED_ALWAYS_ON; ++ ++ /* HW regs to control brightness is special and port 1-2-3 ++ * are placed in a different reg. ++ * ++ * To control port 0 brightness: ++ * - the 2 bit (15, 14) of: ++ * - QCA8K_LED_CTRL0_REG for led1 ++ * - QCA8K_LED_CTRL1_REG for led2 ++ * - QCA8K_LED_CTRL2_REG for led3 ++ * ++ * To control port 4: ++ * - the 2 bit (31, 30) of: ++ * - QCA8K_LED_CTRL0_REG for led1 ++ * - QCA8K_LED_CTRL1_REG for led2 ++ * - QCA8K_LED_CTRL2_REG for led3 ++ * ++ * To control port 1: ++ * - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1 ++ * - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2 ++ * - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3 ++ * ++ * To control port 2: ++ * - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1 ++ * - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2 ++ * - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3 ++ * ++ * To control port 3: ++ * - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1 ++ * - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2 ++ * - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3 ++ * ++ * To abstract this and have less code, we use the port and led numm ++ * to calculate the shift and the correct reg due to this problem of ++ * not having a 1:1 map of LED with the regs. ++ */ ++ if (led->port_num == 0 || led->port_num == 4) { ++ mask = QCA8K_LED_PATTERN_EN_MASK; ++ val <<= QCA8K_LED_PATTERN_EN_SHIFT; ++ } else { ++ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; ++ } ++ ++ return regmap_update_bits(priv->regmap, reg_info.reg, ++ mask << reg_info.shift, ++ val << reg_info.shift); ++} ++ ++static int ++qca8k_cled_brightness_set_blocking(struct led_classdev *ldev, ++ enum led_brightness brightness) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ ++ return qca8k_led_brightness_set(led, brightness); ++} ++ ++static enum led_brightness ++qca8k_led_brightness_get(struct qca8k_led *led) ++{ ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 val; ++ int ret; ++ ++ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); ++ ++ ret = regmap_read(priv->regmap, reg_info.reg, &val); ++ if (ret) ++ return 0; ++ ++ val >>= reg_info.shift; ++ ++ if (led->port_num == 0 || led->port_num == 4) { ++ val &= QCA8K_LED_PATTERN_EN_MASK; ++ val >>= QCA8K_LED_PATTERN_EN_SHIFT; ++ } else { ++ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; ++ } ++ ++ /* Assume brightness ON only when the LED is set to always ON */ ++ return val == QCA8K_LED_ALWAYS_ON; ++} ++ ++static int ++qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) ++{ ++ struct fwnode_handle *led = NULL, *leds = NULL; ++ struct led_init_data init_data = { }; ++ struct dsa_switch *ds = priv->ds; ++ enum led_default_state state; ++ struct qca8k_led *port_led; ++ int led_num, led_index; ++ int ret; ++ ++ leds = fwnode_get_named_child_node(port, "leds"); ++ if (!leds) { ++ dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n", ++ port_num); ++ return 0; ++ } ++ ++ fwnode_for_each_child_node(leds, led) { ++ /* Reg represent the led number of the port. ++ * Each port can have at most 3 leds attached ++ * Commonly: ++ * 1. is gigabit led ++ * 2. is mbit led ++ * 3. additional status led ++ */ ++ if (fwnode_property_read_u32(led, "reg", &led_num)) ++ continue; ++ ++ if (led_num >= QCA8K_LED_PORT_COUNT) { ++ dev_warn(priv->dev, "Invalid LED reg %d defined for port %d", ++ led_num, port_num); ++ continue; ++ } ++ ++ led_index = QCA8K_LED_PORT_INDEX(port_num, led_num); ++ ++ port_led = &priv->ports_led[led_index]; ++ port_led->port_num = port_num; ++ port_led->led_num = led_num; ++ port_led->priv = priv; ++ ++ state = led_init_default_state_get(led); ++ switch (state) { ++ case LEDS_DEFSTATE_ON: ++ port_led->cdev.brightness = 1; ++ qca8k_led_brightness_set(port_led, 1); ++ break; ++ case LEDS_DEFSTATE_KEEP: ++ port_led->cdev.brightness = ++ qca8k_led_brightness_get(port_led); ++ break; ++ default: ++ port_led->cdev.brightness = 0; ++ qca8k_led_brightness_set(port_led, 0); ++ } ++ ++ port_led->cdev.max_brightness = 1; ++ port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; ++ init_data.default_label = ":port"; ++ init_data.fwnode = led; ++ init_data.devname_mandatory = true; ++ init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->slave_mii_bus->id, ++ port_num); ++ if (!init_data.devicename) ++ return -ENOMEM; ++ ++ ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data); ++ if (ret) ++ dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num); ++ ++ kfree(init_data.devicename); ++ } ++ ++ return 0; ++} ++ ++int ++qca8k_setup_led_ctrl(struct qca8k_priv *priv) ++{ ++ struct fwnode_handle *ports, *port; ++ int port_num; ++ int ret; ++ ++ ports = device_get_named_child_node(priv->dev, "ports"); ++ if (!ports) { ++ dev_info(priv->dev, "No ports node specified in device tree!"); ++ return 0; ++ } ++ ++ fwnode_for_each_child_node(ports, port) { ++ if (fwnode_property_read_u32(port, "reg", &port_num)) ++ continue; ++ ++ /* Skip checking for CPU port 0 and CPU port 6 as not supported */ ++ if (port_num == 0 || port_num == 6) ++ continue; ++ ++ /* Each port can have at most 3 different leds attached. ++ * Switch port starts from 0 to 6, but port 0 and 6 are CPU ++ * port. The port index needs to be decreased by one to identify ++ * the correct port for LED setup. ++ */ ++ ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num)); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + + #define QCA8K_ETHERNET_MDIO_PRIORITY 7 +@@ -85,6 +86,51 @@ + #define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x) + #define QCA8K_MDIO_MASTER_MAX_PORTS 5 + #define QCA8K_MDIO_MASTER_MAX_REG 32 ++ ++/* LED control register */ ++#define QCA8K_LED_PORT_COUNT 3 ++#define QCA8K_LED_COUNT ((QCA8K_NUM_PORTS - QCA8K_NUM_CPU_PORTS) * QCA8K_LED_PORT_COUNT) ++#define QCA8K_LED_RULE_COUNT 6 ++#define QCA8K_LED_RULE_MAX 11 ++#define QCA8K_LED_PORT_INDEX(_phy, _led) (((_phy) * QCA8K_LED_PORT_COUNT) + (_led)) ++ ++#define QCA8K_LED_PHY123_PATTERN_EN_SHIFT(_phy, _led) ((((_phy) - 1) * 6) + 8 + (2 * (_led))) ++#define QCA8K_LED_PHY123_PATTERN_EN_MASK GENMASK(1, 0) ++ ++#define QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT 0 ++#define QCA8K_LED_PHY4_CONTROL_RULE_SHIFT 16 ++ ++#define QCA8K_LED_CTRL_REG(_i) (0x050 + (_i) * 4) ++#define QCA8K_LED_CTRL0_REG 0x50 ++#define QCA8K_LED_CTRL1_REG 0x54 ++#define QCA8K_LED_CTRL2_REG 0x58 ++#define QCA8K_LED_CTRL3_REG 0x5C ++#define QCA8K_LED_CTRL_SHIFT(_i) (((_i) % 2) * 16) ++#define QCA8K_LED_CTRL_MASK GENMASK(15, 0) ++#define QCA8K_LED_RULE_MASK GENMASK(13, 0) ++#define QCA8K_LED_BLINK_FREQ_MASK GENMASK(1, 0) ++#define QCA8K_LED_BLINK_FREQ_SHITF 0 ++#define QCA8K_LED_BLINK_2HZ 0 ++#define QCA8K_LED_BLINK_4HZ 1 ++#define QCA8K_LED_BLINK_8HZ 2 ++#define QCA8K_LED_BLINK_AUTO 3 ++#define QCA8K_LED_LINKUP_OVER_MASK BIT(2) ++#define QCA8K_LED_TX_BLINK_MASK BIT(4) ++#define QCA8K_LED_RX_BLINK_MASK BIT(5) ++#define QCA8K_LED_COL_BLINK_MASK BIT(7) ++#define QCA8K_LED_LINK_10M_EN_MASK BIT(8) ++#define QCA8K_LED_LINK_100M_EN_MASK BIT(9) ++#define QCA8K_LED_LINK_1000M_EN_MASK BIT(10) ++#define QCA8K_LED_POWER_ON_LIGHT_MASK BIT(11) ++#define QCA8K_LED_HALF_DUPLEX_MASK BIT(12) ++#define QCA8K_LED_FULL_DUPLEX_MASK BIT(13) ++#define QCA8K_LED_PATTERN_EN_MASK GENMASK(15, 14) ++#define QCA8K_LED_PATTERN_EN_SHIFT 14 ++#define QCA8K_LED_ALWAYS_OFF 0 ++#define QCA8K_LED_ALWAYS_BLINK_4HZ 1 ++#define QCA8K_LED_ALWAYS_ON 2 ++#define QCA8K_LED_RULE_CONTROLLED 3 ++ + #define QCA8K_GOL_MAC_ADDR0 0x60 + #define QCA8K_GOL_MAC_ADDR1 0x64 + #define QCA8K_MAX_FRAME_SIZE 0x78 +@@ -382,6 +428,19 @@ struct qca8k_pcs { + int port; + }; + ++struct qca8k_led_pattern_en { ++ u32 reg; ++ u8 shift; ++}; ++ ++struct qca8k_led { ++ u8 port_num; ++ u8 led_num; ++ u16 old_rule; ++ struct qca8k_priv *priv; ++ struct led_classdev cdev; ++}; ++ + struct qca8k_priv { + u8 switch_id; + u8 switch_revision; +@@ -406,6 +465,7 @@ struct qca8k_priv { + struct qca8k_pcs pcs_port_0; + struct qca8k_pcs pcs_port_6; + const struct qca8k_match_data *info; ++ struct qca8k_led ports_led[QCA8K_LED_COUNT]; + }; + + struct qca8k_mib_desc { +--- /dev/null ++++ b/drivers/net/dsa/qca/qca8k_leds.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef __QCA8K_LEDS_H ++#define __QCA8K_LEDS_H ++ ++/* Leds Support function */ ++#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT ++int qca8k_setup_led_ctrl(struct qca8k_priv *priv); ++#else ++static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv) ++{ ++ return 0; ++} ++#endif ++ ++#endif /* __QCA8K_LEDS_H */ diff --git a/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch b/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch new file mode 100644 index 0000000000..231c4156df --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch @@ -0,0 +1,74 @@ +From 91acadcc6e599dfc62717abcdad58a459cfb1684 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 17 Apr 2023 17:17:25 +0200 +Subject: [PATCH 3/9] net: dsa: qca8k: add LEDs blink_set() support + +Add LEDs blink_set() support to qca8k Switch Family. +These LEDs support hw accellerated blinking at a fixed rate +of 4Hz. + +Reject any other value since not supported by the LEDs switch. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Acked-by: Pavel Machek +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-leds.c | 38 ++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -128,6 +128,43 @@ qca8k_led_brightness_get(struct qca8k_le + } + + static int ++qca8k_cled_blink_set(struct led_classdev *ldev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ; ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ ++ if (*delay_on == 0 && *delay_off == 0) { ++ *delay_on = 125; ++ *delay_off = 125; ++ } ++ ++ if (*delay_on != 125 || *delay_off != 125) { ++ /* The hardware only supports blinking at 4Hz. Fall back ++ * to software implementation in other cases. ++ */ ++ return -EINVAL; ++ } ++ ++ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); ++ ++ if (led->port_num == 0 || led->port_num == 4) { ++ mask = QCA8K_LED_PATTERN_EN_MASK; ++ val <<= QCA8K_LED_PATTERN_EN_SHIFT; ++ } else { ++ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; ++ } ++ ++ regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, ++ val << reg_info.shift); ++ ++ return 0; ++} ++ ++static int + qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) + { + struct fwnode_handle *led = NULL, *leds = NULL; +@@ -186,6 +223,7 @@ qca8k_parse_port_leds(struct qca8k_priv + + port_led->cdev.max_brightness = 1; + port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; ++ port_led->cdev.blink_set = qca8k_cled_blink_set; + init_data.default_label = ":port"; + init_data.fwnode = led; + init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch b/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch new file mode 100644 index 0000000000..bc905b4468 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch @@ -0,0 +1,59 @@ +From e5029edd53937a29801ef507cee12e657ff31ea9 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:26 +0200 +Subject: [PATCH 4/9] leds: Provide stubs for when CLASS_LED & NEW_LEDS are + disabled + +Provide stubs for devm_led_classdev_register_ext() and +led_init_default_state_get() so that LED drivers embedded within other +drivers such as PHYs and Ethernet switches still build when LEDS_CLASS +or NEW_LEDS are disabled. This also helps with Kconfig dependencies, +which are somewhat hairy for phylib and mdio and only get worse when +adding a dependency on LED_CLASS. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/linux/leds.h | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -63,7 +63,15 @@ struct led_init_data { + bool devname_mandatory; + }; + ++#if IS_ENABLED(CONFIG_NEW_LEDS) + enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); ++#else ++static inline enum led_default_state ++led_init_default_state_get(struct fwnode_handle *fwnode) ++{ ++ return LEDS_DEFSTATE_OFF; ++} ++#endif + + struct led_hw_trigger_type { + int dummy; +@@ -198,9 +206,19 @@ static inline int led_classdev_register( + return led_classdev_register_ext(parent, led_cdev, NULL); + } + ++#if IS_ENABLED(CONFIG_LEDS_CLASS) + int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); ++#else ++static inline int ++devm_led_classdev_register_ext(struct device *parent, ++ struct led_classdev *led_cdev, ++ struct led_init_data *init_data) ++{ ++ return 0; ++} ++#endif + + static inline int devm_led_classdev_register(struct device *parent, + struct led_classdev *led_cdev) diff --git a/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch new file mode 100644 index 0000000000..0d2c0bcd83 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -0,0 +1,191 @@ +From 01e5b728e9e43ae444e0369695a5f72209906464 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:27 +0200 +Subject: [PATCH 5/9] net: phy: Add a binding for PHY LEDs + +Define common binding parsing for all PHY drivers with LEDs using +phylib. Parse the DT as part of the phy_probe and add LEDs to the +linux LED class infrastructure. For the moment, provide a dummy +brightness function, which will later be replaced with a call into the +PHY driver. This allows testing since the LED core might otherwise +reject an LED whose brightness cannot be set. + +Add a dependency on LED_CLASS. It either needs to be built in, or not +enabled, since a modular build can result in linker errors. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 1 + + drivers/net/phy/phy_device.c | 76 ++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 16 ++++++++ + 3 files changed, 93 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -18,6 +18,7 @@ menuconfig PHYLIB + depends on NETDEVICES + select MDIO_DEVICE + select MDIO_DEVRES ++ depends on LEDS_CLASS || LEDS_CLASS=n + help + Ethernet controllers are usually attached to PHY + devices. This option provides infrastructure for +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -19,10 +19,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -642,6 +644,7 @@ struct phy_device *phy_device_create(str + device_initialize(&mdiodev->dev); + + dev->state = PHY_DOWN; ++ INIT_LIST_HEAD(&dev->leds); + + mutex_init(&dev->lock); + INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); +@@ -3035,6 +3038,74 @@ static bool phy_drv_supports_irq(struct + return phydrv->config_intr && phydrv->handle_interrupt; + } + ++/* Dummy implementation until calls into PHY driver are added */ ++static int phy_led_set_brightness(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ return 0; ++} ++ ++static int of_phy_led(struct phy_device *phydev, ++ struct device_node *led) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct led_init_data init_data = {}; ++ struct led_classdev *cdev; ++ struct phy_led *phyled; ++ int err; ++ ++ phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); ++ if (!phyled) ++ return -ENOMEM; ++ ++ cdev = &phyled->led_cdev; ++ ++ err = of_property_read_u8(led, "reg", &phyled->index); ++ if (err) ++ return err; ++ ++ cdev->brightness_set_blocking = phy_led_set_brightness; ++ cdev->max_brightness = 1; ++ init_data.devicename = dev_name(&phydev->mdio.dev); ++ init_data.fwnode = of_fwnode_handle(led); ++ init_data.devname_mandatory = true; ++ ++ err = devm_led_classdev_register_ext(dev, cdev, &init_data); ++ if (err) ++ return err; ++ ++ list_add(&phyled->list, &phydev->leds); ++ ++ return 0; ++} ++ ++static int of_phy_leds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct device_node *leds, *led; ++ int err; ++ ++ if (!IS_ENABLED(CONFIG_OF_MDIO)) ++ return 0; ++ ++ if (!node) ++ return 0; ++ ++ leds = of_get_child_by_name(node, "leds"); ++ if (!leds) ++ return 0; ++ ++ for_each_available_child_of_node(leds, led) { ++ err = of_phy_led(phydev, led); ++ if (err) { ++ of_node_put(led); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ + /** + * fwnode_mdio_find_device - Given a fwnode, find the mdio_device + * @fwnode: pointer to the mdio_device's fwnode +@@ -3213,6 +3284,11 @@ static int phy_probe(struct device *dev) + /* Set the state to READY by default */ + phydev->state = PHY_READY; + ++ /* Get the LEDs from the device tree, and instantiate standard ++ * LEDs for them. ++ */ ++ err = of_phy_leds(phydev); ++ + out: + /* Re-assert the reset signal on error */ + if (err) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -606,6 +607,7 @@ struct macsec_ops; + * @phy_num_led_triggers: Number of triggers in @phy_led_triggers + * @led_link_trigger: LED trigger for link up/down + * @last_triggered: last LED trigger for link speed ++ * @leds: list of PHY LED structures + * @master_slave_set: User requested master/slave configuration + * @master_slave_get: Current master/slave advertisement + * @master_slave_state: Current master/slave configuration +@@ -698,6 +700,7 @@ struct phy_device { + + struct phy_led_trigger *led_link_trigger; + #endif ++ struct list_head leds; + + /* + * Interrupt number for this PHY +@@ -772,6 +775,19 @@ struct phy_tdr_config { + #define PHY_PAIR_ALL -1 + + /** ++ * struct phy_led: An LED driven by the PHY ++ * ++ * @list: List of LEDs ++ * @led_cdev: Standard LED class structure ++ * @index: Number of the LED ++ */ ++struct phy_led { ++ struct list_head list; ++ struct led_classdev led_cdev; ++ u8 index; ++}; ++ ++/** + * struct phy_driver - Driver structure for a particular PHY type + * + * @mdiodrv: Data common to all MDIO devices diff --git a/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch new file mode 100644 index 0000000000..4873c40a77 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -0,0 +1,97 @@ +From 684818189b04b095b34964ed4a3ea5249a840eab Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:28 +0200 +Subject: [PATCH 6/9] net: phy: phy_device: Call into the PHY driver to set LED + brightness + +Linux LEDs can be software controlled via the brightness file in /sys. +LED drivers need to implement a brightness_set function which the core +will call. Implement an intermediary in phy_device, which will call +into the phy driver if it implements the necessary function. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 15 ++++++++++++--- + include/linux/phy.h | 13 +++++++++++++ + 2 files changed, 25 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3038,11 +3038,18 @@ static bool phy_drv_supports_irq(struct + return phydrv->config_intr && phydrv->handle_interrupt; + } + +-/* Dummy implementation until calls into PHY driver are added */ + static int phy_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness value) + { +- return 0; ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ int err; ++ ++ mutex_lock(&phydev->lock); ++ err = phydev->drv->led_brightness_set(phydev, phyled->index, value); ++ mutex_unlock(&phydev->lock); ++ ++ return err; + } + + static int of_phy_led(struct phy_device *phydev, +@@ -3059,12 +3066,14 @@ static int of_phy_led(struct phy_device + return -ENOMEM; + + cdev = &phyled->led_cdev; ++ phyled->phydev = phydev; + + err = of_property_read_u8(led, "reg", &phyled->index); + if (err) + return err; + +- cdev->brightness_set_blocking = phy_led_set_brightness; ++ if (phydev->drv->led_brightness_set) ++ cdev->brightness_set_blocking = phy_led_set_brightness; + cdev->max_brightness = 1; + init_data.devicename = dev_name(&phydev->mdio.dev); + init_data.fwnode = of_fwnode_handle(led); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -778,15 +778,19 @@ struct phy_tdr_config { + * struct phy_led: An LED driven by the PHY + * + * @list: List of LEDs ++ * @phydev: PHY this LED is attached to + * @led_cdev: Standard LED class structure + * @index: Number of the LED + */ + struct phy_led { + struct list_head list; ++ struct phy_device *phydev; + struct led_classdev led_cdev; + u8 index; + }; + ++#define to_phy_led(d) container_of(d, struct phy_led, led_cdev) ++ + /** + * struct phy_driver - Driver structure for a particular PHY type + * +@@ -1001,6 +1005,15 @@ struct phy_driver { + int (*get_sqi)(struct phy_device *dev); + /** @get_sqi_max: Get the maximum signal quality indication */ + int (*get_sqi_max)(struct phy_device *dev); ++ ++ /** ++ * @led_brightness_set: Set a PHY LED brightness. Index ++ * indicates which of the PHYs led should be set. Value ++ * follows the standard LED class meaning, e.g. LED_OFF, ++ * LED_HALF, LED_FULL. ++ */ ++ int (*led_brightness_set)(struct phy_device *dev, ++ u8 index, enum led_brightness value); + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch new file mode 100644 index 0000000000..5114c0e6da --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch @@ -0,0 +1,112 @@ +From 2d3960e58ef7c83fe1dbf952f056b9e906cb6df8 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:29 +0200 +Subject: [PATCH 7/9] net: phy: marvell: Add software control of the LEDs + +Add a brightness function, so the LEDs can be controlled from +software using the standard Linux LED infrastructure. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/marvell.c | 45 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 40 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -144,11 +144,13 @@ + /* WOL Event Interrupt Enable */ + #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7) + +-/* LED Timer Control Register */ +-#define MII_88E1318S_PHY_LED_TCR 0x12 +-#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) +-#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) +-#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) ++#define MII_88E1318S_PHY_LED_FUNC 0x10 ++#define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) ++#define MII_88E1318S_PHY_LED_FUNC_ON (0x9) ++#define MII_88E1318S_PHY_LED_TCR 0x12 ++#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) ++#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) ++#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) + + /* Magic Packet MAC address registers */ + #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17 +@@ -2832,6 +2834,34 @@ static int marvell_hwmon_probe(struct ph + } + #endif + ++static int m88e1318_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ int reg; ++ ++ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC); ++ if (reg < 0) ++ return reg; ++ ++ switch (index) { ++ case 0: ++ case 1: ++ case 2: ++ reg &= ~(0xf << (4 * index)); ++ if (value == LED_OFF) ++ reg |= MII_88E1318S_PHY_LED_FUNC_OFF << (4 * index); ++ else ++ reg |= MII_88E1318S_PHY_LED_FUNC_ON << (4 * index); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC, reg); ++} ++ + static int marvell_probe(struct phy_device *phydev) + { + struct marvell_priv *priv; +@@ -3081,6 +3111,7 @@ static struct phy_driver marvell_drivers + .get_sset_count = marvell_get_sset_count, + .get_strings = marvell_get_strings, + .get_stats = marvell_get_stats, ++ .led_brightness_set = m88e1318_led_brightness_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1145, +@@ -3187,6 +3218,7 @@ static struct phy_driver marvell_drivers + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, ++ .led_brightness_set = m88e1318_led_brightness_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1540, +@@ -3213,6 +3245,7 @@ static struct phy_driver marvell_drivers + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, ++ .led_brightness_set = m88e1318_led_brightness_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1545, +@@ -3239,6 +3272,7 @@ static struct phy_driver marvell_drivers + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, ++ .led_brightness_set = m88e1318_led_brightness_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E3016, +@@ -3380,6 +3414,7 @@ static struct phy_driver marvell_drivers + .get_stats = marvell_get_stats, + .get_tunable = m88e1540_get_tunable, + .set_tunable = m88e1540_set_tunable, ++ .led_brightness_set = m88e1318_led_brightness_set, + }, + }; + diff --git a/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch new file mode 100644 index 0000000000..00bdcc5468 --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -0,0 +1,73 @@ +From 4e901018432e38eab35d2a352661ce4727795be1 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:30 +0200 +Subject: [PATCH 8/9] net: phy: phy_device: Call into the PHY driver to set LED + blinking + +Linux LEDs can be requested to perform hardware accelerated +blinking. Pass this to the PHY driver, if it implements the op. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 18 ++++++++++++++++++ + include/linux/phy.h | 12 ++++++++++++ + 2 files changed, 30 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3052,6 +3052,22 @@ static int phy_led_set_brightness(struct + return err; + } + ++static int phy_led_blink_set(struct led_classdev *led_cdev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ int err; ++ ++ mutex_lock(&phydev->lock); ++ err = phydev->drv->led_blink_set(phydev, phyled->index, ++ delay_on, delay_off); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++ + static int of_phy_led(struct phy_device *phydev, + struct device_node *led) + { +@@ -3074,6 +3090,8 @@ static int of_phy_led(struct phy_device + + if (phydev->drv->led_brightness_set) + cdev->brightness_set_blocking = phy_led_set_brightness; ++ if (phydev->drv->led_blink_set) ++ cdev->blink_set = phy_led_blink_set; + cdev->max_brightness = 1; + init_data.devicename = dev_name(&phydev->mdio.dev); + init_data.fwnode = of_fwnode_handle(led); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1014,6 +1014,18 @@ struct phy_driver { + */ + int (*led_brightness_set)(struct phy_device *dev, + u8 index, enum led_brightness value); ++ ++ /** ++ * @led_blink_set: Set a PHY LED brightness. Index indicates ++ * which of the PHYs led should be configured to blink. Delays ++ * are in milliseconds and if both are zero then a sensible ++ * default should be chosen. The call should adjust the ++ * timings in that case and if it can't match the values ++ * specified exactly. ++ */ ++ int (*led_blink_set)(struct phy_device *dev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off); + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch b/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch new file mode 100644 index 0000000000..8d5081a43c --- /dev/null +++ b/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch @@ -0,0 +1,104 @@ +From ea9e86485decb2ac1750005bd96c166c9b780406 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 17 Apr 2023 17:17:31 +0200 +Subject: [PATCH 9/9] net: phy: marvell: Implement led_blink_set() + +The Marvell PHY can blink the LEDs, simple on/off. All LEDs blink at +the same rate, and the reset default is 84ms per blink, which is +around 12Hz. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/marvell.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -147,6 +147,8 @@ + #define MII_88E1318S_PHY_LED_FUNC 0x10 + #define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) + #define MII_88E1318S_PHY_LED_FUNC_ON (0x9) ++#define MII_88E1318S_PHY_LED_FUNC_HI_Z (0xa) ++#define MII_88E1318S_PHY_LED_FUNC_BLINK (0xb) + #define MII_88E1318S_PHY_LED_TCR 0x12 + #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) + #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) +@@ -2862,6 +2864,35 @@ static int m88e1318_led_brightness_set(s + MII_88E1318S_PHY_LED_FUNC, reg); + } + ++static int m88e1318_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int reg; ++ ++ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC); ++ if (reg < 0) ++ return reg; ++ ++ switch (index) { ++ case 0: ++ case 1: ++ case 2: ++ reg &= ~(0xf << (4 * index)); ++ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); ++ /* Reset default is 84ms */ ++ *delay_on = 84 / 2; ++ *delay_off = 84 / 2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC, reg); ++} ++ + static int marvell_probe(struct phy_device *phydev) + { + struct marvell_priv *priv; +@@ -3112,6 +3143,7 @@ static struct phy_driver marvell_drivers + .get_strings = marvell_get_strings, + .get_stats = marvell_get_stats, + .led_brightness_set = m88e1318_led_brightness_set, ++ .led_blink_set = m88e1318_led_blink_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1145, +@@ -3219,6 +3251,7 @@ static struct phy_driver marvell_drivers + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, ++ .led_blink_set = m88e1318_led_blink_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1540, +@@ -3246,6 +3279,7 @@ static struct phy_driver marvell_drivers + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, ++ .led_blink_set = m88e1318_led_blink_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E1545, +@@ -3273,6 +3307,7 @@ static struct phy_driver marvell_drivers + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, ++ .led_blink_set = m88e1318_led_blink_set, + }, + { + .phy_id = MARVELL_PHY_ID_88E3016, +@@ -3415,6 +3450,7 @@ static struct phy_driver marvell_drivers + .get_tunable = m88e1540_get_tunable, + .set_tunable = m88e1540_set_tunable, + .led_brightness_set = m88e1318_led_brightness_set, ++ .led_blink_set = m88e1318_led_blink_set, + }, + }; + diff --git a/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch b/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch new file mode 100644 index 0000000000..56df3f095e --- /dev/null +++ b/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch @@ -0,0 +1,38 @@ +From 4774ad841bef97cc51df90195338c5b2573dd4cb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 23 Apr 2023 19:28:00 +0200 +Subject: [PATCH] net: phy: marvell: Fix inconsistent indenting in + led_blink_set + +Fix inconsistent indeinting in m88e1318_led_blink_set reported by kernel +test robot, probably done by the presence of an if condition dropped in +later revision of the same code. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/oe-kbuild-all/202304240007.0VEX8QYG-lkp@intel.com/ +Fixes: ea9e86485dec ("net: phy: marvell: Implement led_blink_set()") +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20230423172800.3470-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/marvell.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -2880,10 +2880,10 @@ static int m88e1318_led_blink_set(struct + case 1: + case 2: + reg &= ~(0xf << (4 * index)); +- reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); +- /* Reset default is 84ms */ +- *delay_on = 84 / 2; +- *delay_off = 84 / 2; ++ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); ++ /* Reset default is 84ms */ ++ *delay_on = 84 / 2; ++ *delay_off = 84 / 2; + break; + default: + return -EINVAL; diff --git a/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch b/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch new file mode 100644 index 0000000000..3170c26058 --- /dev/null +++ b/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch @@ -0,0 +1,87 @@ +From e2f24cb1b5daf9a4f6f3ba574c1fa74aab9807a4 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 19 Apr 2023 23:07:40 +0200 +Subject: [PATCH 2/5] leds: trigger: netdev: Drop NETDEV_LED_MODE_LINKUP from + mode + +Putting NETDEV_LED_MODE_LINKUP in the same list of the netdev trigger +modes is wrong as it's used to set the link state of the device and not +to set a blink mode as it's done by NETDEV_LED_LINK, NETDEV_LED_TX and +NETDEV_LED_RX. It's also wrong to put this state in the same bitmap of the +netdev trigger mode and should be external to it. + +Drop NETDEV_LED_MODE_LINKUP from mode list and convert to a simple bool +that will be true or false based on the carrier link. No functional +change intended. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230419210743.3594-3-ansuelsmth@gmail.com +--- + drivers/leds/trigger/ledtrig-netdev.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -50,10 +50,10 @@ struct led_netdev_data { + unsigned int last_activity; + + unsigned long mode; ++ bool carrier_link_up; + #define NETDEV_LED_LINK 0 + #define NETDEV_LED_TX 1 + #define NETDEV_LED_RX 2 +-#define NETDEV_LED_MODE_LINKUP 3 + }; + + enum netdev_led_attr { +@@ -73,9 +73,9 @@ static void set_baseline_state(struct le + if (!led_cdev->blink_brightness) + led_cdev->blink_brightness = led_cdev->max_brightness; + +- if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) ++ if (!trigger_data->carrier_link_up) { + led_set_brightness(led_cdev, LED_OFF); +- else { ++ } else { + if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) + led_set_brightness(led_cdev, + led_cdev->blink_brightness); +@@ -131,10 +131,9 @@ static ssize_t device_name_store(struct + trigger_data->net_dev = + dev_get_by_name(&init_net, trigger_data->device_name); + +- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ trigger_data->carrier_link_up = false; + if (trigger_data->net_dev != NULL) +- if (netif_carrier_ok(trigger_data->net_dev)) +- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); + + trigger_data->last_activity = 0; + +@@ -315,11 +314,10 @@ static int netdev_trig_notify(struct not + + spin_lock_bh(&trigger_data->lock); + +- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ trigger_data->carrier_link_up = false; + switch (evt) { + case NETDEV_CHANGENAME: +- if (netif_carrier_ok(dev)) +- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ trigger_data->carrier_link_up = netif_carrier_ok(dev); + fallthrough; + case NETDEV_REGISTER: + if (trigger_data->net_dev) +@@ -333,8 +331,7 @@ static int netdev_trig_notify(struct not + break; + case NETDEV_UP: + case NETDEV_CHANGE: +- if (netif_carrier_ok(dev)) +- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ trigger_data->carrier_link_up = netif_carrier_ok(dev); + break; + } + diff --git a/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch b/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch new file mode 100644 index 0000000000..19cc1d7c9e --- /dev/null +++ b/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch @@ -0,0 +1,149 @@ +From bdec9cb83936e0ac4cb87fed5b49fad0175f7dec Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 19 Apr 2023 23:07:41 +0200 +Subject: [PATCH 3/5] leds: trigger: netdev: Rename add namespace to netdev + trigger enum modes + +Rename NETDEV trigger enum modes to a more symbolic name and add a +namespace to them. + +Also add __TRIGGER_NETDEV_MAX to identify the max modes of the netdev +trigger. + +This is a cleanup to drop the define and no behaviour change are +intended. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230419210743.3594-4-ansuelsmth@gmail.com +--- + drivers/leds/trigger/ledtrig-netdev.c | 58 ++++++++++++--------------- + 1 file changed, 25 insertions(+), 33 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -51,15 +51,15 @@ struct led_netdev_data { + + unsigned long mode; + bool carrier_link_up; +-#define NETDEV_LED_LINK 0 +-#define NETDEV_LED_TX 1 +-#define NETDEV_LED_RX 2 + }; + +-enum netdev_led_attr { +- NETDEV_ATTR_LINK, +- NETDEV_ATTR_TX, +- NETDEV_ATTR_RX ++enum led_trigger_netdev_modes { ++ TRIGGER_NETDEV_LINK = 0, ++ TRIGGER_NETDEV_TX, ++ TRIGGER_NETDEV_RX, ++ ++ /* Keep last */ ++ __TRIGGER_NETDEV_MAX, + }; + + static void set_baseline_state(struct led_netdev_data *trigger_data) +@@ -76,7 +76,7 @@ static void set_baseline_state(struct le + if (!trigger_data->carrier_link_up) { + led_set_brightness(led_cdev, LED_OFF); + } else { +- if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) + led_set_brightness(led_cdev, + led_cdev->blink_brightness); + else +@@ -85,8 +85,8 @@ static void set_baseline_state(struct le + /* If we are looking for RX/TX start periodically + * checking stats + */ +- if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || +- test_bit(NETDEV_LED_RX, &trigger_data->mode)) ++ if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) + schedule_delayed_work(&trigger_data->work, 0); + } + } +@@ -146,20 +146,16 @@ static ssize_t device_name_store(struct + static DEVICE_ATTR_RW(device_name); + + static ssize_t netdev_led_attr_show(struct device *dev, char *buf, +- enum netdev_led_attr attr) ++ enum led_trigger_netdev_modes attr) + { + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + int bit; + + switch (attr) { +- case NETDEV_ATTR_LINK: +- bit = NETDEV_LED_LINK; +- break; +- case NETDEV_ATTR_TX: +- bit = NETDEV_LED_TX; +- break; +- case NETDEV_ATTR_RX: +- bit = NETDEV_LED_RX; ++ case TRIGGER_NETDEV_LINK: ++ case TRIGGER_NETDEV_TX: ++ case TRIGGER_NETDEV_RX: ++ bit = attr; + break; + default: + return -EINVAL; +@@ -169,7 +165,7 @@ static ssize_t netdev_led_attr_show(stru + } + + static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, +- size_t size, enum netdev_led_attr attr) ++ size_t size, enum led_trigger_netdev_modes attr) + { + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + unsigned long state; +@@ -181,14 +177,10 @@ static ssize_t netdev_led_attr_store(str + return ret; + + switch (attr) { +- case NETDEV_ATTR_LINK: +- bit = NETDEV_LED_LINK; +- break; +- case NETDEV_ATTR_TX: +- bit = NETDEV_LED_TX; +- break; +- case NETDEV_ATTR_RX: +- bit = NETDEV_LED_RX; ++ case TRIGGER_NETDEV_LINK: ++ case TRIGGER_NETDEV_TX: ++ case TRIGGER_NETDEV_RX: ++ bit = attr; + break; + default: + return -EINVAL; +@@ -360,21 +352,21 @@ static void netdev_trig_work(struct work + } + + /* If we are not looking for RX/TX then return */ +- if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && +- !test_bit(NETDEV_LED_RX, &trigger_data->mode)) ++ if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && ++ !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) + return; + + dev_stats = dev_get_stats(trigger_data->net_dev, &temp); + new_activity = +- (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? ++ (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? + dev_stats->tx_packets : 0) + +- (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? ++ (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? + dev_stats->rx_packets : 0); + + if (trigger_data->last_activity != new_activity) { + led_stop_software_blink(trigger_data->led_cdev); + +- invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); ++ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); + interval = jiffies_to_msecs( + atomic_read(&trigger_data->interval)); + /* base state is ON (link present) */ diff --git a/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch b/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch new file mode 100644 index 0000000000..3b45951f57 --- /dev/null +++ b/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch @@ -0,0 +1,82 @@ +From 164b67d53476a9d114be85c885bd31f783835be4 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 19 Apr 2023 23:07:42 +0200 +Subject: [PATCH 4/5] leds: trigger: netdev: Convert device attr to macro + +Convert link tx and rx device attr to a common macro to reduce common +code and in preparation for additional attr. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230419210743.3594-5-ansuelsmth@gmail.com +--- + drivers/leds/trigger/ledtrig-netdev.c | 57 ++++++++------------------- + 1 file changed, 16 insertions(+), 41 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -198,47 +198,22 @@ static ssize_t netdev_led_attr_store(str + return size; + } + +-static ssize_t link_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); +-} +- +-static ssize_t link_store(struct device *dev, +- struct device_attribute *attr, const char *buf, size_t size) +-{ +- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); +-} +- +-static DEVICE_ATTR_RW(link); +- +-static ssize_t tx_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); +-} +- +-static ssize_t tx_store(struct device *dev, +- struct device_attribute *attr, const char *buf, size_t size) +-{ +- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); +-} +- +-static DEVICE_ATTR_RW(tx); +- +-static ssize_t rx_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); +-} +- +-static ssize_t rx_store(struct device *dev, +- struct device_attribute *attr, const char *buf, size_t size) +-{ +- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); +-} +- +-static DEVICE_ATTR_RW(rx); ++#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ ++ static ssize_t trigger_name##_show(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++ { \ ++ return netdev_led_attr_show(dev, buf, trigger); \ ++ } \ ++ static ssize_t trigger_name##_store(struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t size) \ ++ { \ ++ return netdev_led_attr_store(dev, buf, size, trigger); \ ++ } \ ++ static DEVICE_ATTR_RW(trigger_name) ++ ++DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); ++DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); ++DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); + + static ssize_t interval_show(struct device *dev, + struct device_attribute *attr, char *buf) diff --git a/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch b/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch new file mode 100644 index 0000000000..180bee9612 --- /dev/null +++ b/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch @@ -0,0 +1,106 @@ +From d1b9e1391ab2dc80e9db87fe8b2de015c651e4c9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 19 Apr 2023 23:07:43 +0200 +Subject: [PATCH 5/5] leds: trigger: netdev: Use mutex instead of spinlocks + +Some LEDs may require to sleep while doing some operation like setting +brightness and other cleanup. + +For this reason, using a spinlock will cause a sleep under spinlock +warning. + +It should be safe to convert this to a sleepable lock since: +- sysfs read/write can sleep +- netdev_trig_work is a work queue and can sleep +- netdev _trig_notify can sleep + +The spinlock was used when brightness didn't support sleeping, but this +changed and now it supported with brightness_set_blocking(). + +Convert to mutex lock to permit sleeping using brightness_set_blocking(). + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230419210743.3594-6-ansuelsmth@gmail.com +--- + drivers/leds/trigger/ledtrig-netdev.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -20,7 +20,7 @@ + #include + #include + #include +-#include ++#include + #include + #include "../leds.h" + +@@ -37,7 +37,7 @@ + */ + + struct led_netdev_data { +- spinlock_t lock; ++ struct mutex lock; + + struct delayed_work work; + struct notifier_block notifier; +@@ -97,9 +97,9 @@ static ssize_t device_name_show(struct d + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + ssize_t len; + +- spin_lock_bh(&trigger_data->lock); ++ mutex_lock(&trigger_data->lock); + len = sprintf(buf, "%s\n", trigger_data->device_name); +- spin_unlock_bh(&trigger_data->lock); ++ mutex_unlock(&trigger_data->lock); + + return len; + } +@@ -115,7 +115,7 @@ static ssize_t device_name_store(struct + + cancel_delayed_work_sync(&trigger_data->work); + +- spin_lock_bh(&trigger_data->lock); ++ mutex_lock(&trigger_data->lock); + + if (trigger_data->net_dev) { + dev_put(trigger_data->net_dev); +@@ -138,7 +138,7 @@ static ssize_t device_name_store(struct + trigger_data->last_activity = 0; + + set_baseline_state(trigger_data); +- spin_unlock_bh(&trigger_data->lock); ++ mutex_unlock(&trigger_data->lock); + + return size; + } +@@ -279,7 +279,7 @@ static int netdev_trig_notify(struct not + + cancel_delayed_work_sync(&trigger_data->work); + +- spin_lock_bh(&trigger_data->lock); ++ mutex_lock(&trigger_data->lock); + + trigger_data->carrier_link_up = false; + switch (evt) { +@@ -304,7 +304,7 @@ static int netdev_trig_notify(struct not + + set_baseline_state(trigger_data); + +- spin_unlock_bh(&trigger_data->lock); ++ mutex_unlock(&trigger_data->lock); + + return NOTIFY_DONE; + } +@@ -365,7 +365,7 @@ static int netdev_trig_activate(struct l + if (!trigger_data) + return -ENOMEM; + +- spin_lock_init(&trigger_data->lock); ++ mutex_init(&trigger_data->lock); + + trigger_data->notifier.notifier_call = netdev_trig_notify; + trigger_data->notifier.priority = 10; diff --git a/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch new file mode 100644 index 0000000000..ac18611733 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch @@ -0,0 +1,74 @@ +From ed554d3f945179c5b159bddfad7be34b403fe11a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:31 +0200 +Subject: [PATCH 01/13] leds: add APIs for LEDs hw control + +Add an option to permit LED driver to declare support for a specific +trigger to use hw control and setup the LED to blink based on specific +provided modes. + +Add APIs for LEDs hw control. These functions will be used to activate +hardware control where a LED will use the provided flags, from an +unique defined supported trigger, to setup the LED to be driven by +hardware. + +Add hw_control_is_supported() to ask the LED driver if the requested +mode by the trigger are supported and the LED can be setup to follow +the requested modes. + +Deactivate hardware blink control by setting brightness to LED_OFF via +the brightness_set() callback. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + include/linux/leds.h | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -164,6 +164,43 @@ struct led_classdev { + + /* LEDs that have private triggers have this set */ + struct led_hw_trigger_type *trigger_type; ++ ++ /* Unique trigger name supported by LED set in hw control mode */ ++ const char *hw_control_trigger; ++ /* ++ * Check if the LED driver supports the requested mode provided by the ++ * defined supported trigger to setup the LED to hw control mode. ++ * ++ * Return 0 on success. Return -EOPNOTSUPP when the passed flags are not ++ * supported and software fallback needs to be used. ++ * Return a negative error number on any other case for check fail due ++ * to various reason like device not ready or timeouts. ++ */ ++ int (*hw_control_is_supported)(struct led_classdev *led_cdev, ++ unsigned long flags); ++ /* ++ * Activate hardware control, LED driver will use the provided flags ++ * from the supported trigger and setup the LED to be driven by hardware ++ * following the requested mode from the trigger flags. ++ * Deactivate hardware blink control by setting brightness to LED_OFF via ++ * the brightness_set() callback. ++ * ++ * Return 0 on success, a negative error number on flags apply fail. ++ */ ++ int (*hw_control_set)(struct led_classdev *led_cdev, ++ unsigned long flags); ++ /* ++ * Get from the LED driver the current mode that the LED is set in hw ++ * control mode and put them in flags. ++ * Trigger can use this to get the initial state of a LED already set in ++ * hardware blink control. ++ * ++ * Return 0 on success, a negative error number on failing parsing the ++ * initial mode. Error from this function is NOT FATAL as the device ++ * may be in a not supported initial state by the attached LED trigger. ++ */ ++ int (*hw_control_get)(struct led_classdev *led_cdev, ++ unsigned long *flags); + #endif + + #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch b/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch new file mode 100644 index 0000000000..1a221727a0 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch @@ -0,0 +1,37 @@ +From 052c38eb17e866c5b4cd43924e7a5e20167b55c0 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 29 May 2023 18:32:32 +0200 +Subject: [PATCH 02/13] leds: add API to get attached device for LED hw control + +Some specific LED triggers blink the LED based on events from a device +or subsystem. +For example, an LED could be blinked to indicate a network device is +receiving packets, or a disk is reading blocks. To correctly enable and +request the hw control of the LED, the trigger has to check if the +network interface or block device configured via a /sys/class/led file +match the one the LED driver provide for hw control for. + +Provide an API call to get the device which the LED blinks for. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + include/linux/leds.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -201,6 +201,12 @@ struct led_classdev { + */ + int (*hw_control_get)(struct led_classdev *led_cdev, + unsigned long *flags); ++ /* ++ * Get the device this LED blinks in response to. ++ * e.g. for a PHY LED, it is the network device. If the LED is ++ * not yet associated to a device, return NULL. ++ */ ++ struct device *(*hw_control_get_device)(struct led_classdev *led_cdev); + #endif + + #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch b/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch new file mode 100644 index 0000000000..af9fb7fdc3 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch @@ -0,0 +1,113 @@ +From 8aa2fd7b66980ecd2e45e95af61cf7eafede1211 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:33 +0200 +Subject: [PATCH 03/13] Documentation: leds: leds-class: Document new Hardware + driven LEDs APIs + +Document new Hardware driven LEDs APIs. + +Some LEDs can be programmed to be driven by hardware. This is not +limited to blink but also to turn off or on autonomously. +To support this feature, a LED needs to implement various additional +ops and needs to declare specific support for the supported triggers. + +Add documentation for each required value and API to make hw control +possible and implementable by both LEDs and triggers. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + Documentation/leds/leds-class.rst | 81 +++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +--- a/Documentation/leds/leds-class.rst ++++ b/Documentation/leds/leds-class.rst +@@ -169,6 +169,87 @@ Setting the brightness to zero with brig + should completely turn off the LED and cancel the previously programmed + hardware blinking function, if any. + ++Hardware driven LEDs ++==================== ++ ++Some LEDs can be programmed to be driven by hardware. This is not ++limited to blink but also to turn off or on autonomously. ++To support this feature, a LED needs to implement various additional ++ops and needs to declare specific support for the supported triggers. ++ ++With hw control we refer to the LED driven by hardware. ++ ++LED driver must define the following value to support hw control: ++ ++ - hw_control_trigger: ++ unique trigger name supported by the LED in hw control ++ mode. ++ ++LED driver must implement the following API to support hw control: ++ - hw_control_is_supported: ++ check if the flags passed by the supported trigger can ++ be parsed and activate hw control on the LED. ++ ++ Return 0 if the passed flags mask is supported and ++ can be set with hw_control_set(). ++ ++ If the passed flags mask is not supported -EOPNOTSUPP ++ must be returned, the LED trigger will use software ++ fallback in this case. ++ ++ Return a negative error in case of any other error like ++ device not ready or timeouts. ++ ++ - hw_control_set: ++ activate hw control. LED driver will use the provided ++ flags passed from the supported trigger, parse them to ++ a set of mode and setup the LED to be driven by hardware ++ following the requested modes. ++ ++ Set LED_OFF via the brightness_set to deactivate hw control. ++ ++ Return 0 on success, a negative error number on failing to ++ apply flags. ++ ++ - hw_control_get: ++ get active modes from a LED already in hw control, parse ++ them and set in flags the current active flags for the ++ supported trigger. ++ ++ Return 0 on success, a negative error number on failing ++ parsing the initial mode. ++ Error from this function is NOT FATAL as the device may ++ be in a not supported initial state by the attached LED ++ trigger. ++ ++ - hw_control_get_device: ++ return the device associated with the LED driver in ++ hw control. A trigger might use this to match the ++ returned device from this function with a configured ++ device for the trigger as the source for blinking ++ events and correctly enable hw control. ++ (example a netdev trigger configured to blink for a ++ particular dev match the returned dev from get_device ++ to set hw control) ++ ++ Returns a pointer to a struct device or NULL if nothing ++ is currently attached. ++ ++LED driver can activate additional modes by default to workaround the ++impossibility of supporting each different mode on the supported trigger. ++Examples are hardcoding the blink speed to a set interval, enable special ++feature like bypassing blink if some requirements are not met. ++ ++A trigger should first check if the hw control API are supported by the LED ++driver and check if the trigger is supported to verify if hw control is possible, ++use hw_control_is_supported to check if the flags are supported and only at ++the end use hw_control_set to activate hw control. ++ ++A trigger can use hw_control_get to check if a LED is already in hw control ++and init their flags. ++ ++When the LED is in hw control, no software blink is possible and doing so ++will effectively disable hw control. + + Known Issues + ============ diff --git a/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch b/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch new file mode 100644 index 0000000000..3c804c0b41 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch @@ -0,0 +1,69 @@ +From 28a6a2ef18ad840a390d519840c303b03040961c Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 29 May 2023 18:32:34 +0200 +Subject: [PATCH 04/13] leds: trigger: netdev: refactor code setting device + name + +Move the code into a helper, ready for it to be called at +other times. No intended behaviour change. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 29 ++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -104,15 +104,9 @@ static ssize_t device_name_show(struct d + return len; + } + +-static ssize_t device_name_store(struct device *dev, +- struct device_attribute *attr, const char *buf, +- size_t size) ++static int set_device_name(struct led_netdev_data *trigger_data, ++ const char *name, size_t size) + { +- struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); +- +- if (size >= IFNAMSIZ) +- return -EINVAL; +- + cancel_delayed_work_sync(&trigger_data->work); + + mutex_lock(&trigger_data->lock); +@@ -122,7 +116,7 @@ static ssize_t device_name_store(struct + trigger_data->net_dev = NULL; + } + +- memcpy(trigger_data->device_name, buf, size); ++ memcpy(trigger_data->device_name, name, size); + trigger_data->device_name[size] = 0; + if (size > 0 && trigger_data->device_name[size - 1] == '\n') + trigger_data->device_name[size - 1] = 0; +@@ -140,6 +134,23 @@ static ssize_t device_name_store(struct + set_baseline_state(trigger_data); + mutex_unlock(&trigger_data->lock); + ++ return 0; ++} ++ ++static ssize_t device_name_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, ++ size_t size) ++{ ++ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ++ int ret; ++ ++ if (size >= IFNAMSIZ) ++ return -EINVAL; ++ ++ ret = set_device_name(trigger_data, buf, size); ++ ++ if (ret < 0) ++ return ret; + return size; + } + diff --git a/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch b/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch new file mode 100644 index 0000000000..284b519482 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch @@ -0,0 +1,54 @@ +From 4fd1b6d47a7a38e81fdc6f8be2ccd4216b3f93db Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:35 +0200 +Subject: [PATCH 05/13] leds: trigger: netdev: introduce check for possible hw + control + +Introduce function to check if the requested mode can use hw control in +preparation for hw control support. Currently everything is handled in +software so can_hw_control will always return false. + +Add knob with the new value hw_control in trigger_data struct to +set hw control possible. Useful for future implementation to implement +in set_baseline_state() the required function to set the requested mode +using LEDs hw control ops and in other function to reject set if hw +control is currently active. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -51,6 +51,7 @@ struct led_netdev_data { + + unsigned long mode; + bool carrier_link_up; ++ bool hw_control; + }; + + enum led_trigger_netdev_modes { +@@ -91,6 +92,11 @@ static void set_baseline_state(struct le + } + } + ++static bool can_hw_control(struct led_netdev_data *trigger_data) ++{ ++ return false; ++} ++ + static ssize_t device_name_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -204,6 +210,8 @@ static ssize_t netdev_led_attr_store(str + else + clear_bit(bit, &trigger_data->mode); + ++ trigger_data->hw_control = can_hw_control(trigger_data); ++ + set_baseline_state(trigger_data); + + return size; diff --git a/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch b/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch new file mode 100644 index 0000000000..09759bc623 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch @@ -0,0 +1,42 @@ +From 6352f25f9fadba59d5df2ba7139495759ccc81d5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:36 +0200 +Subject: [PATCH 06/13] leds: trigger: netdev: add basic check for hw control + support + +Add basic check for hw control support. Check if the required API are +defined and check if the defined trigger supported in hw control for the +LED driver match netdev. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -92,8 +92,22 @@ static void set_baseline_state(struct le + } + } + ++static bool supports_hw_control(struct led_classdev *led_cdev) ++{ ++ if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || ++ !led_cdev->hw_control_is_supported) ++ return false; ++ ++ return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); ++} ++ + static bool can_hw_control(struct led_netdev_data *trigger_data) + { ++ struct led_classdev *led_cdev = trigger_data->led_cdev; ++ ++ if (!supports_hw_control(led_cdev)) ++ return false; ++ + return false; + } + diff --git a/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch b/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch new file mode 100644 index 0000000000..6634906800 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch @@ -0,0 +1,28 @@ +From c84c80c7388f887b10dafd70fc55bc6c5fe9fa5a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:37 +0200 +Subject: [PATCH 07/13] leds: trigger: netdev: reject interval store for + hw_control + +Reject interval store with hw_control enabled. It's are currently not +supported and MUST be set to the default value with hw control enabled. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -265,6 +265,9 @@ static ssize_t interval_store(struct dev + unsigned long value; + int ret; + ++ if (trigger_data->hw_control) ++ return -EINVAL; ++ + ret = kstrtoul(buf, 0, &value); + if (ret) + return ret; diff --git a/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch new file mode 100644 index 0000000000..52faa4809b --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch @@ -0,0 +1,107 @@ +From 7c145a34ba6e380616af93262fcab9fc7261d851 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:38 +0200 +Subject: [PATCH 08/13] leds: trigger: netdev: add support for LED hw control + +Add support for LED hw control for the netdev trigger. + +The trigger on calling set_baseline_state to configure a new mode, will +do various check to verify if hw control can be used for the requested +mode in can_hw_control() function. + +It will first check if the LED driver supports hw control for the netdev +trigger, then will use hw_control_is_supported() and finally will call +hw_control_set() to apply the requested mode. + +To use such mode, interval MUST be set to the default value and net_dev +MUST be set. If one of these 2 value are not valid, hw control will +never be used and normal software fallback is used. + +The default interval value is moved to a define to make sure they are +always synced. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 43 +++++++++++++++++++++++++-- + 1 file changed, 41 insertions(+), 2 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -24,6 +24,8 @@ + #include + #include "../leds.h" + ++#define NETDEV_LED_DEFAULT_INTERVAL 50 ++ + /* + * Configurable sysfs attributes: + * +@@ -68,6 +70,13 @@ static void set_baseline_state(struct le + int current_brightness; + struct led_classdev *led_cdev = trigger_data->led_cdev; + ++ /* Already validated, hw control is possible with the requested mode */ ++ if (trigger_data->hw_control) { ++ led_cdev->hw_control_set(led_cdev, trigger_data->mode); ++ ++ return; ++ } ++ + current_brightness = led_cdev->brightness; + if (current_brightness) + led_cdev->blink_brightness = current_brightness; +@@ -103,12 +112,42 @@ static bool supports_hw_control(struct l + + static bool can_hw_control(struct led_netdev_data *trigger_data) + { ++ unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); ++ unsigned int interval = atomic_read(&trigger_data->interval); + struct led_classdev *led_cdev = trigger_data->led_cdev; ++ int ret; + + if (!supports_hw_control(led_cdev)) + return false; + +- return false; ++ /* ++ * Interval must be set to the default ++ * value. Any different value is rejected if in hw ++ * control. ++ */ ++ if (interval != default_interval) ++ return false; ++ ++ /* ++ * net_dev must be set with hw control, otherwise no ++ * blinking can be happening and there is nothing to ++ * offloaded. ++ */ ++ if (!trigger_data->net_dev) ++ return false; ++ ++ /* Check if the requested mode is supported */ ++ ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); ++ /* Fall back to software blinking if not supported */ ++ if (ret == -EOPNOTSUPP) ++ return false; ++ if (ret) { ++ dev_warn(led_cdev->dev, ++ "Current mode check failed with error %d\n", ret); ++ return false; ++ } ++ ++ return true; + } + + static ssize_t device_name_show(struct device *dev, +@@ -413,7 +452,7 @@ static int netdev_trig_activate(struct l + trigger_data->device_name[0] = 0; + + trigger_data->mode = 0; +- atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); ++ atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); + trigger_data->last_activity = 0; + + led_set_trigger_data(led_cdev, trigger_data); diff --git a/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch new file mode 100644 index 0000000000..c129ffa4f5 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch @@ -0,0 +1,58 @@ +From 33ec0b53befff2c0a7f3aa19ff08556d60585d6b Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 29 May 2023 18:32:39 +0200 +Subject: [PATCH 09/13] leds: trigger: netdev: validate configured netdev + +The netdev which the LED should blink for is configurable in +/sys/class/led/foo/device_name. Ensure when offloading that the +configured netdev is the same as the netdev the LED is associated +with. If it is not, only perform software blinking. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 24 ++++++++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -110,6 +110,24 @@ static bool supports_hw_control(struct l + return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); + } + ++/* ++ * Validate the configured netdev is the same as the one associated with ++ * the LED driver in hw control. ++ */ ++static bool validate_net_dev(struct led_classdev *led_cdev, ++ struct net_device *net_dev) ++{ ++ struct device *dev = led_cdev->hw_control_get_device(led_cdev); ++ struct net_device *ndev; ++ ++ if (!dev) ++ return false; ++ ++ ndev = to_net_dev(dev); ++ ++ return ndev == net_dev; ++} ++ + static bool can_hw_control(struct led_netdev_data *trigger_data) + { + unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); +@@ -131,9 +149,11 @@ static bool can_hw_control(struct led_ne + /* + * net_dev must be set with hw control, otherwise no + * blinking can be happening and there is nothing to +- * offloaded. ++ * offloaded. Additionally, for hw control to be ++ * valid, the configured netdev must be the same as ++ * netdev associated to the LED. + */ +- if (!trigger_data->net_dev) ++ if (!validate_net_dev(led_cdev, trigger_data->net_dev)) + return false; + + /* Check if the requested mode is supported */ diff --git a/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch b/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch new file mode 100644 index 0000000000..e20594c99a --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch @@ -0,0 +1,53 @@ +From 0316cc5629d15880dd3f097d221c55ca648bcd61 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:40 +0200 +Subject: [PATCH 10/13] leds: trigger: netdev: init mode if hw control already + active + +On netdev trigger activation, hw control may be already active by +default. If this is the case and a device is actually provided by +hw_control_get_device(), init the already active mode and set the +bool to hw_control bool to true to reflect the already set mode in the +trigger_data. + +Co-developed-by: Andrew Lunn +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -454,6 +454,8 @@ static void netdev_trig_work(struct work + static int netdev_trig_activate(struct led_classdev *led_cdev) + { + struct led_netdev_data *trigger_data; ++ unsigned long mode; ++ struct device *dev; + int rc; + + trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); +@@ -475,6 +477,21 @@ static int netdev_trig_activate(struct l + atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); + trigger_data->last_activity = 0; + ++ /* Check if hw control is active by default on the LED. ++ * Init already enabled mode in hw control. ++ */ ++ if (supports_hw_control(led_cdev) && ++ !led_cdev->hw_control_get(led_cdev, &mode)) { ++ dev = led_cdev->hw_control_get_device(led_cdev); ++ if (dev) { ++ const char *name = dev_name(dev); ++ ++ set_device_name(trigger_data, name, strlen(name)); ++ trigger_data->hw_control = true; ++ trigger_data->mode = mode; ++ } ++ } ++ + led_set_trigger_data(led_cdev, trigger_data); + + rc = register_netdevice_notifier(&trigger_data->notifier); diff --git a/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch b/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch new file mode 100644 index 0000000000..70aed850d1 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch @@ -0,0 +1,54 @@ +From 947acacab5ea151291b861cdfbde16ff5cf1b08c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:41 +0200 +Subject: [PATCH 11/13] leds: trigger: netdev: expose netdev trigger modes in + linux include + +Expose netdev trigger modes to make them accessible by LED driver that +will support netdev trigger for hw control. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 9 --------- + include/linux/leds.h | 10 ++++++++++ + 2 files changed, 10 insertions(+), 9 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -56,15 +56,6 @@ struct led_netdev_data { + bool hw_control; + }; + +-enum led_trigger_netdev_modes { +- TRIGGER_NETDEV_LINK = 0, +- TRIGGER_NETDEV_TX, +- TRIGGER_NETDEV_RX, +- +- /* Keep last */ +- __TRIGGER_NETDEV_MAX, +-}; +- + static void set_baseline_state(struct led_netdev_data *trigger_data) + { + int current_brightness; +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -527,6 +527,16 @@ static inline void *led_get_trigger_data + + #endif /* CONFIG_LEDS_TRIGGERS */ + ++/* Trigger specific enum */ ++enum led_trigger_netdev_modes { ++ TRIGGER_NETDEV_LINK = 0, ++ TRIGGER_NETDEV_TX, ++ TRIGGER_NETDEV_RX, ++ ++ /* Keep last */ ++ __TRIGGER_NETDEV_MAX, ++}; ++ + /* Trigger specific functions */ + #ifdef CONFIG_LEDS_TRIGGER_DISK + void ledtrig_disk_activity(bool write); diff --git a/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch b/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch new file mode 100644 index 0000000000..ad76d89b7b --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch @@ -0,0 +1,200 @@ +From e0256648c831af13cbfe4a1787327fcec01c2807 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 May 2023 18:32:42 +0200 +Subject: [PATCH 12/13] net: dsa: qca8k: implement hw_control ops + +Implement hw_control ops to drive Switch LEDs based on hardware events. + +Netdev trigger is the declared supported trigger for hw control +operation and supports the following mode: +- tx +- rx + +When hw_control_set is called, LEDs are set to follow the requested +mode. +Each LEDs will blink at 4Hz by default. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-leds.c | 154 +++++++++++++++++++++++++++++++ + 1 file changed, 154 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -32,6 +32,43 @@ qca8k_get_enable_led_reg(int port_num, i + } + + static int ++qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) ++{ ++ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); ++ ++ /* 6 total control rule: ++ * 3 control rules for phy0-3 that applies to all their leds ++ * 3 control rules for phy4 ++ */ ++ if (port_num == 4) ++ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; ++ else ++ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; ++ ++ return 0; ++} ++ ++static int ++qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable some default rule by default to the requested mode: ++ * - Blink at 4Hz by default ++ */ ++ *offload_trigger |= QCA8K_LED_BLINK_4HZ; ++ ++ return 0; ++} ++ ++static int + qca8k_led_brightness_set(struct qca8k_led *led, + enum led_brightness brightness) + { +@@ -165,6 +202,119 @@ qca8k_cled_blink_set(struct led_classdev + } + + static int ++qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 mask, val = QCA8K_LED_ALWAYS_OFF; ++ ++ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); ++ ++ if (enable) ++ val = QCA8K_LED_RULE_CONTROLLED; ++ ++ if (led->port_num == 0 || led->port_num == 4) { ++ mask = QCA8K_LED_PATTERN_EN_MASK; ++ val <<= QCA8K_LED_PATTERN_EN_SHIFT; ++ } else { ++ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; ++ } ++ ++ return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, ++ val << reg_info.shift); ++} ++ ++static bool ++qca8k_cled_hw_control_status(struct led_classdev *ldev) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 val; ++ ++ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); ++ ++ regmap_read(priv->regmap, reg_info.reg, &val); ++ ++ val >>= reg_info.shift; ++ ++ if (led->port_num == 0 || led->port_num == 4) { ++ val &= QCA8K_LED_PATTERN_EN_MASK; ++ val >>= QCA8K_LED_PATTERN_EN_SHIFT; ++ } else { ++ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; ++ } ++ ++ return val == QCA8K_LED_RULE_CONTROLLED; ++} ++ ++static int ++qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) ++{ ++ u32 offload_trigger = 0; ++ ++ return qca8k_parse_netdev(rules, &offload_trigger); ++} ++ ++static int ++qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 offload_trigger = 0; ++ int ret; ++ ++ ret = qca8k_parse_netdev(rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_cled_trigger_offload(ldev, true); ++ if (ret) ++ return ret; ++ ++ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); ++ ++ return regmap_update_bits(priv->regmap, reg_info.reg, ++ QCA8K_LED_RULE_MASK << reg_info.shift, ++ offload_trigger << reg_info.shift); ++} ++ ++static int ++qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ struct qca8k_led_pattern_en reg_info; ++ struct qca8k_priv *priv = led->priv; ++ u32 val; ++ int ret; ++ ++ /* With hw control not active return err */ ++ if (!qca8k_cled_hw_control_status(ldev)) ++ return -EINVAL; ++ ++ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); ++ ++ ret = regmap_read(priv->regmap, reg_info.reg, &val); ++ if (ret) ++ return ret; ++ ++ val >>= reg_info.shift; ++ val &= QCA8K_LED_RULE_MASK; ++ ++ /* Parsing specific to netdev trigger */ ++ if (val & QCA8K_LED_TX_BLINK_MASK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA8K_LED_RX_BLINK_MASK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ ++ return 0; ++} ++ ++static int + qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) + { + struct fwnode_handle *led = NULL, *leds = NULL; +@@ -224,6 +374,10 @@ qca8k_parse_port_leds(struct qca8k_priv + port_led->cdev.max_brightness = 1; + port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; + port_led->cdev.blink_set = qca8k_cled_blink_set; ++ port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; ++ port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; ++ port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; ++ port_led->cdev.hw_control_trigger = "netdev"; + init_data.default_label = ":port"; + init_data.fwnode = led; + init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch new file mode 100644 index 0000000000..feb6b9e1e4 --- /dev/null +++ b/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch @@ -0,0 +1,70 @@ +From 4f53c27f772e27e4cf4e5507d6f4d5980002cb6a Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 29 May 2023 18:32:43 +0200 +Subject: [PATCH 13/13] net: dsa: qca8k: add op to get ports netdev + +In order that the LED trigger can blink the switch MAC ports LED, it +needs to know the netdev associated to the port. Add the callback to +return the struct device of the netdev. + +Add an helper function qca8k_phy_to_port() to convert the phy back to +dsa_port index, as we reference LED port based on the internal PHY +index and needs to be converted back. + +Signed-off-by: Andrew Lunn +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-leds.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -5,6 +5,18 @@ + #include "qca8k.h" + #include "qca8k_leds.h" + ++static u32 qca8k_phy_to_port(int phy) ++{ ++ /* Internal PHY 0 has port at index 1. ++ * Internal PHY 1 has port at index 2. ++ * Internal PHY 2 has port at index 3. ++ * Internal PHY 3 has port at index 4. ++ * Internal PHY 4 has port at index 5. ++ */ ++ ++ return phy + 1; ++} ++ + static int + qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) + { +@@ -314,6 +326,20 @@ qca8k_cled_hw_control_get(struct led_cla + return 0; + } + ++static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev) ++{ ++ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); ++ struct qca8k_priv *priv = led->priv; ++ struct dsa_port *dp; ++ ++ dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num)); ++ if (!dp) ++ return NULL; ++ if (dp->slave) ++ return &dp->slave->dev; ++ return NULL; ++} ++ + static int + qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) + { +@@ -377,6 +403,7 @@ qca8k_parse_port_leds(struct qca8k_priv + port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; + port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; + port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; ++ port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device; + port_led->cdev.hw_control_trigger = "netdev"; + init_data.default_label = ":port"; + init_data.fwnode = led; diff --git a/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch b/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch new file mode 100644 index 0000000000..1c564b3897 --- /dev/null +++ b/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch @@ -0,0 +1,242 @@ +From d5e01266e7f5fa12400d4c8aa4e86fe89dcc61e9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 19 Jun 2023 22:46:58 +0200 +Subject: [PATCH 1/3] leds: trigger: netdev: add additional specific link speed + mode + +Add additional modes for specific link speed. Use ethtool APIs to get the +current link speed and enable the LED accordingly. Under netdev event +handler the rtnl lock is already held and is not needed to be set to +access ethtool APIs. + +This is especially useful for PHY and Switch that supports LEDs hw +control for specific link speed. (example scenario a PHY that have 2 LED +connected one green and one orange where the green is turned on with +1000mbps speed and orange is turned on with 10mpbs speed) + +On mode set from sysfs we check if we have enabled split link speed mode +and reject enabling generic link mode to prevent wrong and redundant +configuration. + +Rework logic on the set baseline state to support these new modes to +select if we need to turn on or off the LED. + +Add additional modes: +- link_10: Turn on LED when link speed is 10mbps +- link_100: Turn on LED when link speed is 100mbps +- link_1000: Turn on LED when link speed is 1000mbps + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Acked-by: Lee Jones +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 80 +++++++++++++++++++++++---- + include/linux/leds.h | 3 + + 2 files changed, 73 insertions(+), 10 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -21,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include "../leds.h" + +@@ -52,6 +54,8 @@ struct led_netdev_data { + unsigned int last_activity; + + unsigned long mode; ++ int link_speed; ++ + bool carrier_link_up; + bool hw_control; + }; +@@ -77,7 +81,24 @@ static void set_baseline_state(struct le + if (!trigger_data->carrier_link_up) { + led_set_brightness(led_cdev, LED_OFF); + } else { ++ bool blink_on = false; ++ + if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_10) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_100) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_1000) ++ blink_on = true; ++ ++ if (blink_on) + led_set_brightness(led_cdev, + led_cdev->blink_brightness); + else +@@ -161,6 +182,18 @@ static bool can_hw_control(struct led_ne + return true; + } + ++static void get_device_state(struct led_netdev_data *trigger_data) ++{ ++ struct ethtool_link_ksettings cmd; ++ ++ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); ++ if (!trigger_data->carrier_link_up) ++ return; ++ ++ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) ++ trigger_data->link_speed = cmd.base.speed; ++} ++ + static ssize_t device_name_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -196,8 +229,12 @@ static int set_device_name(struct led_ne + dev_get_by_name(&init_net, trigger_data->device_name); + + trigger_data->carrier_link_up = false; +- if (trigger_data->net_dev != NULL) +- trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); ++ trigger_data->link_speed = SPEED_UNKNOWN; ++ if (trigger_data->net_dev != NULL) { ++ rtnl_lock(); ++ get_device_state(trigger_data); ++ rtnl_unlock(); ++ } + + trigger_data->last_activity = 0; + +@@ -234,6 +271,9 @@ static ssize_t netdev_led_attr_show(stru + + switch (attr) { + case TRIGGER_NETDEV_LINK: ++ case TRIGGER_NETDEV_LINK_10: ++ case TRIGGER_NETDEV_LINK_100: ++ case TRIGGER_NETDEV_LINK_1000: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; +@@ -249,7 +289,7 @@ static ssize_t netdev_led_attr_store(str + size_t size, enum led_trigger_netdev_modes attr) + { + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); +- unsigned long state; ++ unsigned long state, mode = trigger_data->mode; + int ret; + int bit; + +@@ -259,6 +299,9 @@ static ssize_t netdev_led_attr_store(str + + switch (attr) { + case TRIGGER_NETDEV_LINK: ++ case TRIGGER_NETDEV_LINK_10: ++ case TRIGGER_NETDEV_LINK_100: ++ case TRIGGER_NETDEV_LINK_1000: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; +@@ -267,13 +310,20 @@ static ssize_t netdev_led_attr_store(str + return -EINVAL; + } + +- cancel_delayed_work_sync(&trigger_data->work); +- + if (state) +- set_bit(bit, &trigger_data->mode); ++ set_bit(bit, &mode); + else +- clear_bit(bit, &trigger_data->mode); ++ clear_bit(bit, &mode); ++ ++ if (test_bit(TRIGGER_NETDEV_LINK, &mode) && ++ (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_100, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) ++ return -EINVAL; ++ ++ cancel_delayed_work_sync(&trigger_data->work); + ++ trigger_data->mode = mode; + trigger_data->hw_control = can_hw_control(trigger_data); + + set_baseline_state(trigger_data); +@@ -295,6 +345,9 @@ static ssize_t netdev_led_attr_store(str + static DEVICE_ATTR_RW(trigger_name) + + DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); ++DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); ++DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); ++DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); + DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); + DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); + +@@ -338,6 +391,9 @@ static DEVICE_ATTR_RW(interval); + static struct attribute *netdev_trig_attrs[] = { + &dev_attr_device_name.attr, + &dev_attr_link.attr, ++ &dev_attr_link_10.attr, ++ &dev_attr_link_100.attr, ++ &dev_attr_link_1000.attr, + &dev_attr_rx.attr, + &dev_attr_tx.attr, + &dev_attr_interval.attr, +@@ -368,9 +424,10 @@ static int netdev_trig_notify(struct not + mutex_lock(&trigger_data->lock); + + trigger_data->carrier_link_up = false; ++ trigger_data->link_speed = SPEED_UNKNOWN; + switch (evt) { + case NETDEV_CHANGENAME: +- trigger_data->carrier_link_up = netif_carrier_ok(dev); ++ get_device_state(trigger_data); + fallthrough; + case NETDEV_REGISTER: + if (trigger_data->net_dev) +@@ -384,7 +441,7 @@ static int netdev_trig_notify(struct not + break; + case NETDEV_UP: + case NETDEV_CHANGE: +- trigger_data->carrier_link_up = netif_carrier_ok(dev); ++ get_device_state(trigger_data); + break; + } + +@@ -427,7 +484,10 @@ static void netdev_trig_work(struct work + if (trigger_data->last_activity != new_activity) { + led_stop_software_blink(trigger_data->led_cdev); + +- invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); ++ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); + interval = jiffies_to_msecs( + atomic_read(&trigger_data->interval)); + /* base state is ON (link present) */ +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -530,6 +530,9 @@ static inline void *led_get_trigger_data + /* Trigger specific enum */ + enum led_trigger_netdev_modes { + TRIGGER_NETDEV_LINK = 0, ++ TRIGGER_NETDEV_LINK_10, ++ TRIGGER_NETDEV_LINK_100, ++ TRIGGER_NETDEV_LINK_1000, + TRIGGER_NETDEV_TX, + TRIGGER_NETDEV_RX, + diff --git a/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch b/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch new file mode 100644 index 0000000000..a5ab461828 --- /dev/null +++ b/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch @@ -0,0 +1,138 @@ +From f22f95b9ff1551c9bab13104131929f33d51f23f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 19 Jun 2023 22:46:59 +0200 +Subject: [PATCH 2/3] leds: trigger: netdev: add additional specific link + duplex mode + +Add additional modes for specific link duplex. Use ethtool APIs to get the +current link duplex and enable the LED accordingly. Under netdev event +handler the rtnl lock is already held and is not needed to be set to +access ethtool APIs. + +This is especially useful for PHY and Switch that supports LEDs hw +control for specific link duplex. + +Add additional modes: +- half_duplex: Turn on LED when link is half duplex +- full_duplex: Turn on LED when link is full duplex + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Acked-by: Lee Jones +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 27 +++++++++++++++++++++++++-- + include/linux/leds.h | 2 ++ + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -55,6 +55,7 @@ struct led_netdev_data { + + unsigned long mode; + int link_speed; ++ u8 duplex; + + bool carrier_link_up; + bool hw_control; +@@ -98,6 +99,14 @@ static void set_baseline_state(struct le + trigger_data->link_speed == SPEED_1000) + blink_on = true; + ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && ++ trigger_data->duplex == DUPLEX_HALF) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && ++ trigger_data->duplex == DUPLEX_FULL) ++ blink_on = true; ++ + if (blink_on) + led_set_brightness(led_cdev, + led_cdev->blink_brightness); +@@ -190,8 +199,10 @@ static void get_device_state(struct led_ + if (!trigger_data->carrier_link_up) + return; + +- if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) ++ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { + trigger_data->link_speed = cmd.base.speed; ++ trigger_data->duplex = cmd.base.duplex; ++ } + } + + static ssize_t device_name_show(struct device *dev, +@@ -230,6 +241,7 @@ static int set_device_name(struct led_ne + + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; ++ trigger_data->duplex = DUPLEX_UNKNOWN; + if (trigger_data->net_dev != NULL) { + rtnl_lock(); + get_device_state(trigger_data); +@@ -274,6 +286,8 @@ static ssize_t netdev_led_attr_show(stru + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_HALF_DUPLEX: ++ case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; +@@ -302,6 +316,8 @@ static ssize_t netdev_led_attr_store(str + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_HALF_DUPLEX: ++ case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; +@@ -348,6 +364,8 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD + DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); + DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); + DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); ++DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); ++DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); + DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); + DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); + +@@ -394,6 +412,8 @@ static struct attribute *netdev_trig_att + &dev_attr_link_10.attr, + &dev_attr_link_100.attr, + &dev_attr_link_1000.attr, ++ &dev_attr_full_duplex.attr, ++ &dev_attr_half_duplex.attr, + &dev_attr_rx.attr, + &dev_attr_tx.attr, + &dev_attr_interval.attr, +@@ -425,6 +445,7 @@ static int netdev_trig_notify(struct not + + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; ++ trigger_data->duplex = DUPLEX_UNKNOWN; + switch (evt) { + case NETDEV_CHANGENAME: + get_device_state(trigger_data); +@@ -487,7 +508,9 @@ static void netdev_trig_work(struct work + invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || +- test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); ++ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); + interval = jiffies_to_msecs( + atomic_read(&trigger_data->interval)); + /* base state is ON (link present) */ +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -533,6 +533,8 @@ enum led_trigger_netdev_modes { + TRIGGER_NETDEV_LINK_10, + TRIGGER_NETDEV_LINK_100, + TRIGGER_NETDEV_LINK_1000, ++ TRIGGER_NETDEV_HALF_DUPLEX, ++ TRIGGER_NETDEV_FULL_DUPLEX, + TRIGGER_NETDEV_TX, + TRIGGER_NETDEV_RX, + diff --git a/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch b/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch new file mode 100644 index 0000000000..67528cafe0 --- /dev/null +++ b/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch @@ -0,0 +1,45 @@ +From b655892ffd6d89b0c7407e099c40dbde82ee3f03 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 19 Jun 2023 22:47:00 +0200 +Subject: [PATCH 3/3] leds: trigger: netdev: expose hw_control status via sysfs + +Expose hw_control status via sysfs for the netdev trigger to give +userspace better understanding of the current state of the trigger and +the LED. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Kalesh AP +Acked-by: Lee Jones +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -406,6 +406,16 @@ static ssize_t interval_store(struct dev + + static DEVICE_ATTR_RW(interval); + ++static ssize_t hw_control_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ++ ++ return sprintf(buf, "%d\n", trigger_data->hw_control); ++} ++ ++static DEVICE_ATTR_RO(hw_control); ++ + static struct attribute *netdev_trig_attrs[] = { + &dev_attr_device_name.attr, + &dev_attr_link.attr, +@@ -417,6 +427,7 @@ static struct attribute *netdev_trig_att + &dev_attr_rx.attr, + &dev_attr_tx.attr, + &dev_attr_interval.attr, ++ &dev_attr_hw_control.attr, + NULL + }; + ATTRIBUTE_GROUPS(netdev_trig); diff --git a/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch b/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch new file mode 100644 index 0000000000..ac322e1939 --- /dev/null +++ b/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch @@ -0,0 +1,64 @@ +From 2555f35a4f428a9bfdf09aa0459dbfdf59a24a9a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 21 Jun 2023 11:54:09 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for additional modes for netdev + trigger + +The QCA8K switch supports additional modes that can be handled in +hardware for the LED netdev trigger. + +Add these additional modes to further support the Switch LEDs and +offload more blink modes. + +Add additional modes: +- link_10 +- link_100 +- link_1000 +- half_duplex +- full_duplex + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230621095409.25859-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/qca/qca8k-leds.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -68,6 +68,16 @@ qca8k_parse_netdev(unsigned long rules, + *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; + if (test_bit(TRIGGER_NETDEV_RX, &rules)) + *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK; + + if (rules && !*offload_trigger) + return -EOPNOTSUPP; +@@ -322,6 +332,16 @@ qca8k_cled_hw_control_get(struct led_cla + set_bit(TRIGGER_NETDEV_TX, rules); + if (val & QCA8K_LED_RX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA8K_LED_LINK_10M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA8K_LED_LINK_100M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA8K_LED_LINK_1000M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA8K_LED_HALF_DUPLEX_MASK) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA8K_LED_FULL_DUPLEX_MASK) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); + + return 0; + } diff --git a/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch b/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch new file mode 100644 index 0000000000..58777cd280 --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch @@ -0,0 +1,64 @@ +From 4f86eb098e18fd0f032877dfa1a7e8c1503ca409 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:41 +0200 +Subject: [PATCH 1/6] net: dsa: mv88e6xxx: pass directly chip structure to + mv88e6xxx_phy_is_internal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since this function is a simple helper, we do not need to pass a full +dsa_switch structure, we can directly pass the mv88e6xxx_chip structure. +Doing so will allow to share this function with any other function +not manipulating dsa_switch structure but needing info about number of +internal phys + +Signed-off-by: Alexis Lothoré +Reviewed-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -470,10 +470,8 @@ restore_link: + return err; + } + +-static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) ++static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) + { +- struct mv88e6xxx_chip *chip = ds->priv; +- + return port < chip->info->num_internal_phys; + } + +@@ -591,7 +589,7 @@ static void mv88e6095_phylink_get_caps(s + + config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; + +- if (mv88e6xxx_phy_is_internal(chip->ds, port)) { ++ if (mv88e6xxx_phy_is_internal(chip, port)) { + __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); + } else { + if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && +@@ -839,7 +837,7 @@ static void mv88e6xxx_get_caps(struct ds + chip->info->ops->phylink_get_caps(chip, port, config); + mv88e6xxx_reg_unlock(chip); + +- if (mv88e6xxx_phy_is_internal(ds, port)) { ++ if (mv88e6xxx_phy_is_internal(chip, port)) { + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + /* Internal ports with no phy-mode need GMII for PHYLIB */ +@@ -860,7 +858,7 @@ static void mv88e6xxx_mac_config(struct + + mv88e6xxx_reg_lock(chip); + +- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { ++ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { + /* In inband mode, the link may come up at any time while the + * link is not forced down. Force the link down while we + * reconfigure the interface mode. diff --git a/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch b/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch new file mode 100644 index 0000000000..75a21a931d --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch @@ -0,0 +1,31 @@ +From 73cbfad9296eed004992806e056db5b48583ca41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:42 +0200 +Subject: [PATCH 2/6] net: dsa: mv88e6xxx: use mv88e6xxx_phy_is_internal in + mv88e6xxx_port_ppu_updates +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make sure to use existing helper to get internal PHYs count instead of +redoing it manually + +Signed-off-by: Alexis Lothoré +Reviewed-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -484,7 +484,7 @@ static int mv88e6xxx_port_ppu_updates(st + * report whether the port is internal. + */ + if (chip->info->family == MV88E6XXX_FAMILY_6250) +- return port < chip->info->num_internal_phys; ++ return mv88e6xxx_phy_is_internal(chip, port); + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) { diff --git a/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch b/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch new file mode 100644 index 0000000000..e24dca819b --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch @@ -0,0 +1,69 @@ +From 1414d30660d201f515a9d877571ceea9ca190b6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:43 +0200 +Subject: [PATCH 3/6] net: dsa: mv88e6xxx: add field to specify internal phys + layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mv88e6xxx currently assumes that switch equipped with internal phys have +those phys mapped contiguously starting from port 0 (see +mv88e6xxx_phy_is_internal). However, some switches have internal PHYs but +NOT starting from port 0. For example 88e6393X, 88E6193X and 88E6191X have +integrated PHYs available on ports 1 to 8 +To properly support this offset, add a new field to allow specifying an +internal PHYs layout. If field is not set, default layout is assumed (start +at port 0) + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- + drivers/net/dsa/mv88e6xxx/chip.h | 5 +++++ + drivers/net/dsa/mv88e6xxx/global2.c | 5 ++++- + 3 files changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -472,7 +472,9 @@ restore_link: + + static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) + { +- return port < chip->info->num_internal_phys; ++ return port >= chip->info->internal_phys_offset && ++ port < chip->info->num_internal_phys + ++ chip->info->internal_phys_offset; + } + + static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -167,6 +167,11 @@ struct mv88e6xxx_info { + + /* Supports PTP */ + bool ptp_support; ++ ++ /* Internal PHY start index. 0 means that internal PHYs range starts at ++ * port 0, 1 means internal PHYs range starts at port 1, etc ++ */ ++ unsigned int internal_phys_offset; + }; + + struct mv88e6xxx_atu_entry { +--- a/drivers/net/dsa/mv88e6xxx/global2.c ++++ b/drivers/net/dsa/mv88e6xxx/global2.c +@@ -1185,8 +1185,11 @@ int mv88e6xxx_g2_irq_mdio_setup(struct m + struct mii_bus *bus) + { + int phy, irq, err, err_phy; ++ int phy_start = chip->info->internal_phys_offset; ++ int phy_end = chip->info->internal_phys_offset + ++ chip->info->num_internal_phys; + +- for (phy = 0; phy < chip->info->num_internal_phys; phy++) { ++ for (phy = phy_start; phy < phy_end; phy++) { + irq = irq_find_mapping(chip->g2_irq.domain, phy); + if (irq < 0) { + err = irq; diff --git a/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch b/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch new file mode 100644 index 0000000000..12ea3ebda0 --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch @@ -0,0 +1,52 @@ +From eb8c75f82a6711387f3b9e03e28923f3e75a761b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:44 +0200 +Subject: [PATCH 4/6] net: dsa: mv88e6xxx: fix 88E6393X family internal phys + layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +88E6393X/88E6193X/88E6191X switches have in fact 8 internal PHYs, but those +are not present starting at port 0: supported ports go from 1 to 8 + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5944,7 +5944,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6191X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, +@@ -5967,7 +5968,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6193X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, +@@ -6286,7 +6288,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6393X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, diff --git a/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch b/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch new file mode 100644 index 0000000000..72dfcee82c --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch @@ -0,0 +1,110 @@ +From cef945452c8468efce75ba0dc8420510a5b84af9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:45 +0200 +Subject: [PATCH 5/6] net: dsa: mv88e6xxx: pass mv88e6xxx_chip structure to + port_max_speed_mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some switches families have minor differences on supported link speed for +ports. Instead of redefining a new port_max_speed_mode for each different +configuration, allow to pass mv88e6xxx_chip structure to allow +differentiating those chips by known chip id + +Signed-off-by: Alexis Lothoré +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- + drivers/net/dsa/mv88e6xxx/port.c | 12 ++++++++---- + drivers/net/dsa/mv88e6xxx/port.h | 12 ++++++++---- + 4 files changed, 19 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3328,7 +3328,7 @@ static int mv88e6xxx_setup_port(struct m + caps = pl_config.mac_capabilities; + + if (chip->info->ops->port_max_speed_mode) +- mode = chip->info->ops->port_max_speed_mode(port); ++ mode = chip->info->ops->port_max_speed_mode(chip, port); + else + mode = PHY_INTERFACE_MODE_NA; + +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -508,7 +508,8 @@ struct mv88e6xxx_ops { + int speed, int duplex); + + /* What interface mode should be used for maximum speed? */ +- phy_interface_t (*port_max_speed_mode)(int port); ++ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, ++ int port); + + int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); + +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(stru + duplex); + } + +-phy_interface_t mv88e6341_port_max_speed_mode(int port) ++phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 5) + return PHY_INTERFACE_MODE_2500BASEX; +@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(stru + duplex); + } + +-phy_interface_t mv88e6390_port_max_speed_mode(int port) ++phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 9 || port == 10) + return PHY_INTERFACE_MODE_2500BASEX; +@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(str + duplex); + } + +-phy_interface_t mv88e6390x_port_max_speed_mode(int port) ++phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 9 || port == 10) + return PHY_INTERFACE_MODE_XAUI; +@@ -500,7 +503,8 @@ int mv88e6393x_port_set_speed_duplex(str + return 0; + } + +-phy_interface_t mv88e6393x_port_max_speed_mode(int port) ++phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 0 || port == 9 || port == 10) + return PHY_INTERFACE_MODE_10GBASER; +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -359,10 +359,14 @@ int mv88e6390x_port_set_speed_duplex(str + int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, + int speed, int duplex); + +-phy_interface_t mv88e6341_port_max_speed_mode(int port); +-phy_interface_t mv88e6390_port_max_speed_mode(int port); +-phy_interface_t mv88e6390x_port_max_speed_mode(int port); +-phy_interface_t mv88e6393x_port_max_speed_mode(int port); ++phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); + + int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); + diff --git a/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch b/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch new file mode 100644 index 0000000000..dc6d5497f2 --- /dev/null +++ b/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch @@ -0,0 +1,153 @@ +From 23680321789863bab2d60af507858ce50ff9f56a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:46 +0200 +Subject: [PATCH 6/6] net: dsa: mv88e6xxx: enable support for 88E6361 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Marvell 88E6361 is an 8-port switch derived from the +88E6393X/88E9193X/88E6191X switches family. It can benefit from the +existing mv88e6xxx driver by simply adding the proper switch description in +the driver. Main differences with other switches from this +family are: +- 8 ports exposed (instead of 11): ports 1, 2 and 8 not available +- No 5GBase-x nor SFI/USXGMII support + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++---- + drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- + drivers/net/dsa/mv88e6xxx/port.c | 14 ++++++++--- + drivers/net/dsa/mv88e6xxx/port.h | 1 + + 4 files changed, 51 insertions(+), 9 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -797,6 +797,8 @@ static void mv88e6393x_phylink_get_caps( + unsigned long *supported = config->supported_interfaces; + bool is_6191x = + chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; ++ bool is_6361 = ++ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; + + mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); + +@@ -811,13 +813,17 @@ static void mv88e6393x_phylink_get_caps( + /* 6191X supports >1G modes only on port 10 */ + if (!is_6191x || port == 10) { + __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); +- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); +- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ config->mac_capabilities |= MAC_2500FD; ++ ++ /* 6361 only supports up to 2500BaseX */ ++ if (!is_6361) { ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ config->mac_capabilities |= MAC_5000FD | ++ MAC_10000FD; ++ } + /* FIXME: USXGMII is not supported yet */ + /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ +- +- config->mac_capabilities |= MAC_2500FD | MAC_5000FD | +- MAC_10000FD; + } + } + +@@ -6231,6 +6237,32 @@ static const struct mv88e6xxx_info mv88e + .ptp_support = true, + .ops = &mv88e6352_ops, + }, ++ [MV88E6361] = { ++ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, ++ .family = MV88E6XXX_FAMILY_6393, ++ .name = "Marvell 88E6361", ++ .num_databases = 4096, ++ .num_macs = 16384, ++ .num_ports = 11, ++ /* Ports 1, 2 and 8 are not routed */ ++ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), ++ .num_internal_phys = 5, ++ .internal_phys_offset = 3, ++ .max_vid = 4095, ++ .max_sid = 63, ++ .port_base_addr = 0x0, ++ .phy_base_addr = 0x0, ++ .global1_addr = 0x1b, ++ .global2_addr = 0x1c, ++ .age_time_coeff = 3750, ++ .g1_irqs = 10, ++ .g2_irqs = 14, ++ .atu_move_port_mask = 0x1f, ++ .pvt = true, ++ .multi_chip = true, ++ .ptp_support = true, ++ .ops = &mv88e6393x_ops, ++ }, + [MV88E6390] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, + .family = MV88E6XXX_FAMILY_6390, +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -82,6 +82,7 @@ enum mv88e6xxx_model { + MV88E6350, + MV88E6351, + MV88E6352, ++ MV88E6361, + MV88E6390, + MV88E6390X, + MV88E6393X, +@@ -100,7 +101,7 @@ enum mv88e6xxx_family { + MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ + MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ + MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ +- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ ++ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ + }; + + /** +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -424,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(str + u16 reg, ctrl; + int err; + ++ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && ++ speed > 2500) ++ return -EOPNOTSUPP; ++ + if (speed == 200 && port != 0) + return -EOPNOTSUPP; + +@@ -506,10 +510,14 @@ int mv88e6393x_port_set_speed_duplex(str + phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) + { +- if (port == 0 || port == 9 || port == 10) +- return PHY_INTERFACE_MODE_10GBASER; + +- return PHY_INTERFACE_MODE_NA; ++ if (port != 0 && port != 9 && port != 10) ++ return PHY_INTERFACE_MODE_NA; ++ ++ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) ++ return PHY_INTERFACE_MODE_2500BASEX; ++ ++ return PHY_INTERFACE_MODE_10GBASER; + } + + static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -133,6 +133,7 @@ + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 ++#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 diff --git a/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch b/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch new file mode 100644 index 0000000000..33759632eb --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch @@ -0,0 +1,82 @@ +From fbfc4ca465a1f8d81bf2d67d95bf7fc67c3cf0c2 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Fri, 18 Nov 2022 06:39:20 +0000 +Subject: [PATCH] nvmem: stm32: move STM32MP15_BSEC_NUM_LOWER in config + +Support STM32MP15_BSEC_NUM_LOWER in stm32 romem config to prepare +the next SoC in STM32MP family. + +Signed-off-by: Patrick Delaunay +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -22,16 +22,15 @@ + /* shadow registers offest */ + #define STM32MP15_BSEC_DATA0 0x200 + +-/* 32 (x 32-bits) lower shadow registers */ +-#define STM32MP15_BSEC_NUM_LOWER 32 +- + struct stm32_romem_cfg { + int size; ++ u8 lower; + }; + + struct stm32_romem_priv { + void __iomem *base; + struct nvmem_config cfg; ++ u8 lower; + }; + + static int stm32_romem_read(void *context, unsigned int offset, void *buf, +@@ -85,7 +84,7 @@ static int stm32_bsec_read(void *context + for (i = roffset; (i < roffset + rbytes); i += 4) { + u32 otp = i >> 2; + +- if (otp < STM32MP15_BSEC_NUM_LOWER) { ++ if (otp < priv->lower) { + /* read lower data from shadow registers */ + val = readl_relaxed( + priv->base + STM32MP15_BSEC_DATA0 + i); +@@ -159,6 +158,8 @@ static int stm32_romem_probe(struct plat + priv->cfg.priv = priv; + priv->cfg.owner = THIS_MODULE; + ++ priv->lower = 0; ++ + cfg = (const struct stm32_romem_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; + if (!cfg) { +@@ -167,6 +168,7 @@ static int stm32_romem_probe(struct plat + priv->cfg.reg_read = stm32_romem_read; + } else { + priv->cfg.size = cfg->size; ++ priv->lower = cfg->lower; + priv->cfg.reg_read = stm32_bsec_read; + priv->cfg.reg_write = stm32_bsec_write; + } +@@ -174,8 +176,17 @@ static int stm32_romem_probe(struct plat + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); + } + ++/* ++ * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) ++ * => 96 x 32-bits data words ++ * - Lower: 1K bits, 2:1 redundancy, incremental bit programming ++ * => 32 (x 32-bits) lower shadow registers = words 0 to 31 ++ * - Upper: 2K bits, ECC protection, word programming only ++ * => 64 (x 32-bits) = words 32 to 95 ++ */ + static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { +- .size = 384, /* 96 x 32-bits data words */ ++ .size = 384, ++ .lower = 32, + }; + + static const struct of_device_id stm32_romem_of_match[] = { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch b/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch new file mode 100644 index 0000000000..5791df2606 --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch @@ -0,0 +1,34 @@ +From d61784e6410f3df2028e6eb91b06ffed37a660e0 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Fri, 18 Nov 2022 06:39:21 +0000 +Subject: [PATCH] nvmem: stm32: add warning when upper OTPs are updated + +As the upper OTPs are ECC protected, they support only one 32 bits word +programming. +For a second modification of this word, these ECC become invalid and +this OTP will be no more accessible, the shadowed value is invalid. + +This patch adds a warning to indicate an upper OTP update, because this +operation is dangerous as OTP is not locked by the driver after the first +update to avoid a second update. + +Signed-off-by: Patrick Delaunay +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -132,6 +132,9 @@ static int stm32_bsec_write(void *contex + } + } + ++ if (offset + bytes >= priv->lower * 4) ++ dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n"); ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch b/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch new file mode 100644 index 0000000000..b83ad69c6b --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch @@ -0,0 +1,26 @@ +From a3816a7d7c097c1da46aad5f5d1e229b607dce04 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Fri, 18 Nov 2022 06:39:22 +0000 +Subject: [PATCH] nvmem: stm32: add nvmem type attribute + +Inform NVMEM framework of type attribute for stm32-romem as NVMEM_TYPE_OTP +so userspace is able to know how the data is stored in BSEC. + +Signed-off-by: Patrick Delaunay +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -160,6 +160,7 @@ static int stm32_romem_probe(struct plat + priv->cfg.dev = dev; + priv->cfg.priv = priv; + priv->cfg.owner = THIS_MODULE; ++ priv->cfg.type = NVMEM_TYPE_OTP; + + priv->lower = 0; + diff --git a/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch b/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch new file mode 100644 index 0000000000..52ba1e65b5 --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch @@ -0,0 +1,27 @@ +From 06aac0e11960a7ddccc1888326b5906d017e0f24 Mon Sep 17 00:00:00 2001 +From: Jiangshan Yi +Date: Fri, 18 Nov 2022 06:39:24 +0000 +Subject: [PATCH] nvmem: stm32: fix spelling typo in comment + +Fix spelling typo in comment. + +Reported-by: k2ci +Signed-off-by: Jiangshan Yi +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -19,7 +19,7 @@ + #define STM32_SMC_WRITE_SHADOW 0x03 + #define STM32_SMC_READ_OTP 0x04 + +-/* shadow registers offest */ ++/* shadow registers offset */ + #define STM32MP15_BSEC_DATA0 0x200 + + struct stm32_romem_cfg { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch b/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch new file mode 100644 index 0000000000..8f024f4c1a --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch @@ -0,0 +1,27 @@ +From fb817c4ef63e8cfb6e77ae4a2875ae854c80708f Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Fri, 18 Nov 2022 06:39:26 +0000 +Subject: [PATCH] nvmem: Kconfig: Fix spelling mistake "controlls" -> + "controls" + +There is a spelling mistake in a Kconfig description. Fix it. + +Signed-off-by: Colin Ian King +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -164,7 +164,7 @@ config NVMEM_MICROCHIP_OTPC + depends on ARCH_AT91 || COMPILE_TEST + help + This driver enable the OTP controller available on Microchip SAMA7G5 +- SoCs. It controlls the access to the OTP memory connected to it. ++ SoCs. It controls the access to the OTP memory connected to it. + + config NVMEM_MTK_EFUSE + tristate "Mediatek SoCs EFUSE support" diff --git a/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch b/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch new file mode 100644 index 0000000000..861386ad31 --- /dev/null +++ b/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch @@ -0,0 +1,67 @@ +From ada84d07af6097b2addd18262668ce6cb9e15206 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 18 Nov 2022 06:39:27 +0000 +Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They +decided to store U-Boot environment data inside U-Boot partition and to +use a custom header (with "uEnv" magic and env data length). + +Add support for Broadcom's specific binding and their custom format. + +Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding") +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20221118063932.6418-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -16,6 +16,7 @@ + enum u_boot_env_format { + U_BOOT_FORMAT_SINGLE, + U_BOOT_FORMAT_REDUNDANT, ++ U_BOOT_FORMAT_BROADCOM, + }; + + struct u_boot_env { +@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant { + uint8_t data[]; + } __packed; + ++struct u_boot_env_image_broadcom { ++ __le32 magic; ++ __le32 len; ++ __le32 crc32; ++ uint8_t data[0]; ++} __packed; ++ + static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) + { +@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo + crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; ++ case U_BOOT_FORMAT_BROADCOM: ++ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); ++ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ data_offset = offsetof(struct u_boot_env_image_broadcom, data); ++ break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); + crc32_data_len = priv->mtd->size - crc32_data_offset; +@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_ + { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, + { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, ++ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, + {}, + }; + diff --git a/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch b/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch new file mode 100644 index 0000000000..01400fd490 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch @@ -0,0 +1,26 @@ +From 2e8dc541ae207349b51c65391be625ffe1f86e0c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 6 Feb 2023 13:43:41 +0000 +Subject: [PATCH] nvmem: core: remove spurious white space + +Remove a spurious white space in for the ida_alloc() call. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -764,7 +764,7 @@ struct nvmem_device *nvmem_register(cons + if (!nvmem) + return ERR_PTR(-ENOMEM); + +- rval = ida_alloc(&nvmem_ida, GFP_KERNEL); ++ rval = ida_alloc(&nvmem_ida, GFP_KERNEL); + if (rval < 0) { + kfree(nvmem); + return ERR_PTR(rval); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch new file mode 100644 index 0000000000..454d3bf0ed --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch @@ -0,0 +1,180 @@ +From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:46 +0000 +Subject: [PATCH] nvmem: core: add an index parameter to the cell + +Sometimes a cell can represend multiple values. For example, a base +ethernet address stored in the NVMEM can be expanded into multiple +discreet ones by adding an offset. + +For this use case, introduce an index parameter which is then used to +distiguish between values. This parameter will then be passed to the +post process hook which can then use it to create different values +during reading. + +At the moment, there is only support for the device tree path. You can +add the index to the phandle, e.g. + + &net { + nvmem-cells = <&base_mac_address 2>; + nvmem-cell-names = "mac-address"; + }; + + &nvmem_provider { + base_mac_address: base-mac-address@0 { + #nvmem-cell-cells = <1>; + reg = <0 6>; + }; + }; + +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 37 ++++++++++++++++++++++++---------- + drivers/nvmem/imx-ocotp.c | 4 ++-- + include/linux/nvmem-provider.h | 4 ++-- + 3 files changed, 30 insertions(+), 15 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -60,6 +60,7 @@ struct nvmem_cell_entry { + struct nvmem_cell { + struct nvmem_cell_entry *entry; + const char *id; ++ int index; + }; + + static DEFINE_MUTEX(nvmem_mutex); +@@ -1122,7 +1123,8 @@ struct nvmem_device *devm_nvmem_device_g + } + EXPORT_SYMBOL_GPL(devm_nvmem_device_get); + +-static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id) ++static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, ++ const char *id, int index) + { + struct nvmem_cell *cell; + const char *name = NULL; +@@ -1141,6 +1143,7 @@ static struct nvmem_cell *nvmem_create_c + + cell->id = name; + cell->entry = entry; ++ cell->index = index; + + return cell; + } +@@ -1179,7 +1182,7 @@ nvmem_cell_get_from_lookup(struct device + __nvmem_device_put(nvmem); + cell = ERR_PTR(-ENOENT); + } else { +- cell = nvmem_create_cell(cell_entry, con_id); ++ cell = nvmem_create_cell(cell_entry, con_id, 0); + if (IS_ERR(cell)) + __nvmem_device_put(nvmem); + } +@@ -1227,15 +1230,27 @@ struct nvmem_cell *of_nvmem_cell_get(str + struct nvmem_device *nvmem; + struct nvmem_cell_entry *cell_entry; + struct nvmem_cell *cell; ++ struct of_phandle_args cell_spec; + int index = 0; ++ int cell_index = 0; ++ int ret; + + /* if cell name exists, find index to the name */ + if (id) + index = of_property_match_string(np, "nvmem-cell-names", id); + +- cell_np = of_parse_phandle(np, "nvmem-cells", index); +- if (!cell_np) +- return ERR_PTR(-ENOENT); ++ ret = of_parse_phandle_with_optional_args(np, "nvmem-cells", ++ "#nvmem-cell-cells", ++ index, &cell_spec); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ if (cell_spec.args_count > 1) ++ return ERR_PTR(-EINVAL); ++ ++ cell_np = cell_spec.np; ++ if (cell_spec.args_count) ++ cell_index = cell_spec.args[0]; + + nvmem_np = of_get_parent(cell_np); + if (!nvmem_np) { +@@ -1257,7 +1272,7 @@ struct nvmem_cell *of_nvmem_cell_get(str + return ERR_PTR(-ENOENT); + } + +- cell = nvmem_create_cell(cell_entry, id); ++ cell = nvmem_create_cell(cell_entry, id, cell_index); + if (IS_ERR(cell)) + __nvmem_device_put(nvmem); + +@@ -1410,8 +1425,8 @@ static void nvmem_shift_read_buffer_in_p + } + + static int __nvmem_cell_read(struct nvmem_device *nvmem, +- struct nvmem_cell_entry *cell, +- void *buf, size_t *len, const char *id) ++ struct nvmem_cell_entry *cell, ++ void *buf, size_t *len, const char *id, int index) + { + int rc; + +@@ -1425,7 +1440,7 @@ static int __nvmem_cell_read(struct nvme + nvmem_shift_read_buffer_in_place(cell, buf); + + if (nvmem->cell_post_process) { +- rc = nvmem->cell_post_process(nvmem->priv, id, ++ rc = nvmem->cell_post_process(nvmem->priv, id, index, + cell->offset, buf, cell->bytes); + if (rc) + return rc; +@@ -1460,7 +1475,7 @@ void *nvmem_cell_read(struct nvmem_cell + if (!buf) + return ERR_PTR(-ENOMEM); + +- rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id); ++ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index); + if (rc) { + kfree(buf); + return ERR_PTR(rc); +@@ -1773,7 +1788,7 @@ ssize_t nvmem_device_cell_read(struct nv + if (rc) + return rc; + +- rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL); ++ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0); + if (rc) + return rc; + +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -222,8 +222,8 @@ read_end: + return ret; + } + +-static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset, +- void *data, size_t bytes) ++static int imx_ocotp_cell_pp(void *context, const char *id, int index, ++ unsigned int offset, void *data, size_t bytes) + { + struct ocotp_priv *priv = context; + +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr + typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, + void *val, size_t bytes); + /* used for vendor specific post processing of cell data */ +-typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset, +- void *buf, size_t bytes); ++typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes); + + enum nvmem_type { + NVMEM_TYPE_UNKNOWN = 0, diff --git a/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch b/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch new file mode 100644 index 0000000000..f3829b3e17 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch @@ -0,0 +1,78 @@ +From fbd03d27776c6121a483921601418e3c8f0ff37e Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:47 +0000 +Subject: [PATCH] nvmem: core: move struct nvmem_cell_info to nvmem-provider.h + +struct nvmem_cell_info is used to describe a cell. Thus this should +really be in the nvmem-provider's header. There are two (unused) nvmem +access methods which use the nvmem_cell_info to describe the cell to be +accesses. One can argue, that they will create a cell before accessing, +thus they are both a provider and a consumer. + +struct nvmem_cell_info will get used more and more by nvmem-providers, +don't force them to also include the consumer header, although they are +not. + +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-14-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/nvmem-consumer.h | 10 +--------- + include/linux/nvmem-provider.h | 19 ++++++++++++++++++- + 2 files changed, 19 insertions(+), 10 deletions(-) + +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -18,15 +18,7 @@ struct device_node; + /* consumer cookie */ + struct nvmem_cell; + struct nvmem_device; +- +-struct nvmem_cell_info { +- const char *name; +- unsigned int offset; +- unsigned int bytes; +- unsigned int bit_offset; +- unsigned int nbits; +- struct device_node *np; +-}; ++struct nvmem_cell_info; + + /** + * struct nvmem_cell_lookup - cell lookup entry +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -14,7 +14,6 @@ + #include + + struct nvmem_device; +-struct nvmem_cell_info; + typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, + void *val, size_t bytes); + typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, +@@ -48,6 +47,24 @@ struct nvmem_keepout { + }; + + /** ++ * struct nvmem_cell_info - NVMEM cell description ++ * @name: Name. ++ * @offset: Offset within the NVMEM device. ++ * @bytes: Length of the cell. ++ * @bit_offset: Bit offset if cell is smaller than a byte. ++ * @nbits: Number of bits. ++ * @np: Optional device_node pointer. ++ */ ++struct nvmem_cell_info { ++ const char *name; ++ unsigned int offset; ++ unsigned int bytes; ++ unsigned int bit_offset; ++ unsigned int nbits; ++ struct device_node *np; ++}; ++ ++/** + * struct nvmem_config - NVMEM device configuration + * + * @dev: Parent device. diff --git a/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch b/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch new file mode 100644 index 0000000000..8f996eab34 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch @@ -0,0 +1,65 @@ +From cc5bdd323dde6494623f3ffe3a5b887fa21cd375 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:48 +0000 +Subject: [PATCH] nvmem: core: drop the removal of the cells in + nvmem_add_cells() + +If nvmem_add_cells() fails, the whole nvmem_register() will fail +and the cells will then be removed anyway. This is a preparation +to introduce a nvmem_add_one_cell() which can then be used by +nvmem_add_cells(). + +This is then the same to what nvmem_add_cells_from_table() and +nvmem_add_cells_from_of() do. + +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-15-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -515,7 +515,7 @@ static int nvmem_add_cells(struct nvmem_ + int ncells) + { + struct nvmem_cell_entry **cells; +- int i, rval; ++ int i, rval = 0; + + cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); + if (!cells) +@@ -525,28 +525,22 @@ static int nvmem_add_cells(struct nvmem_ + cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); + if (!cells[i]) { + rval = -ENOMEM; +- goto err; ++ goto out; + } + + rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); + if (rval) { + kfree(cells[i]); +- goto err; ++ goto out; + } + + nvmem_cell_entry_add(cells[i]); + } + ++out: + /* remove tmp array */ + kfree(cells); + +- return 0; +-err: +- while (i--) +- nvmem_cell_entry_drop(cells[i]); +- +- kfree(cells); +- + return rval; + } + diff --git a/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch new file mode 100644 index 0000000000..711ce229b2 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch @@ -0,0 +1,122 @@ +From 2ded6830d376d5e7bf43d59f7f7fdf1a59abc676 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:49 +0000 +Subject: [PATCH] nvmem: core: add nvmem_add_one_cell() + +Add a new function to add exactly one cell. This will be used by the +nvmem layout drivers to add custom cells. In contrast to the +nvmem_add_cells(), this has the advantage that we don't have to assemble +a list of cells on runtime. + +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-16-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 59 ++++++++++++++++++++-------------- + include/linux/nvmem-provider.h | 8 +++++ + 2 files changed, 43 insertions(+), 24 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -502,6 +502,36 @@ static int nvmem_cell_info_to_nvmem_cell + } + + /** ++ * nvmem_add_one_cell() - Add one cell information to an nvmem device ++ * ++ * @nvmem: nvmem device to add cells to. ++ * @info: nvmem cell info to add to the device ++ * ++ * Return: 0 or negative error code on failure. ++ */ ++int nvmem_add_one_cell(struct nvmem_device *nvmem, ++ const struct nvmem_cell_info *info) ++{ ++ struct nvmem_cell_entry *cell; ++ int rval; ++ ++ cell = kzalloc(sizeof(*cell), GFP_KERNEL); ++ if (!cell) ++ return -ENOMEM; ++ ++ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell); ++ if (rval) { ++ kfree(cell); ++ return rval; ++ } ++ ++ nvmem_cell_entry_add(cell); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nvmem_add_one_cell); ++ ++/** + * nvmem_add_cells() - Add cell information to an nvmem device + * + * @nvmem: nvmem device to add cells to. +@@ -514,34 +544,15 @@ static int nvmem_add_cells(struct nvmem_ + const struct nvmem_cell_info *info, + int ncells) + { +- struct nvmem_cell_entry **cells; +- int i, rval = 0; +- +- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); +- if (!cells) +- return -ENOMEM; ++ int i, rval; + + for (i = 0; i < ncells; i++) { +- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); +- if (!cells[i]) { +- rval = -ENOMEM; +- goto out; +- } +- +- rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); +- if (rval) { +- kfree(cells[i]); +- goto out; +- } +- +- nvmem_cell_entry_add(cells[i]); ++ rval = nvmem_add_one_cell(nvmem, &info[i]); ++ if (rval) ++ return rval; + } + +-out: +- /* remove tmp array */ +- kfree(cells); +- +- return rval; ++ return 0; + } + + /** +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -153,6 +153,9 @@ struct nvmem_device *devm_nvmem_register + void nvmem_add_cell_table(struct nvmem_cell_table *table); + void nvmem_del_cell_table(struct nvmem_cell_table *table); + ++int nvmem_add_one_cell(struct nvmem_device *nvmem, ++ const struct nvmem_cell_info *info); ++ + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -170,6 +173,11 @@ devm_nvmem_register(struct device *dev, + + static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {} + static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {} ++static inline int nvmem_add_one_cell(struct nvmem_device *nvmem, ++ const struct nvmem_cell_info *info) ++{ ++ return -EOPNOTSUPP; ++} + + #endif /* CONFIG_NVMEM */ + #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch b/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch new file mode 100644 index 0000000000..e1791e5c83 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch @@ -0,0 +1,93 @@ +From 50014d659617dc58780a5d31ceb76c82779a9d8b Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:50 +0000 +Subject: [PATCH] nvmem: core: use nvmem_add_one_cell() in + nvmem_add_cells_from_of() + +Convert nvmem_add_cells_from_of() to use the new nvmem_add_one_cell(). +This will remove duplicate code and it will make it possible to add a +hook to a nvmem layout in between, which can change fields before the +cell is finally added. + +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-17-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 45 ++++++++++++++------------------------------ + 1 file changed, 14 insertions(+), 31 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -688,15 +688,14 @@ static int nvmem_validate_keepouts(struc + + static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) + { +- struct device_node *parent, *child; + struct device *dev = &nvmem->dev; +- struct nvmem_cell_entry *cell; ++ struct device_node *child; + const __be32 *addr; +- int len; ++ int len, ret; + +- parent = dev->of_node; ++ for_each_child_of_node(dev->of_node, child) { ++ struct nvmem_cell_info info = {0}; + +- for_each_child_of_node(parent, child) { + addr = of_get_property(child, "reg", &len); + if (!addr) + continue; +@@ -706,40 +705,24 @@ static int nvmem_add_cells_from_of(struc + return -EINVAL; + } + +- cell = kzalloc(sizeof(*cell), GFP_KERNEL); +- if (!cell) { +- of_node_put(child); +- return -ENOMEM; +- } +- +- cell->nvmem = nvmem; +- cell->offset = be32_to_cpup(addr++); +- cell->bytes = be32_to_cpup(addr); +- cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); ++ info.offset = be32_to_cpup(addr++); ++ info.bytes = be32_to_cpup(addr); ++ info.name = kasprintf(GFP_KERNEL, "%pOFn", child); + + addr = of_get_property(child, "bits", &len); + if (addr && len == (2 * sizeof(u32))) { +- cell->bit_offset = be32_to_cpup(addr++); +- cell->nbits = be32_to_cpup(addr); ++ info.bit_offset = be32_to_cpup(addr++); ++ info.nbits = be32_to_cpup(addr); + } + +- if (cell->nbits) +- cell->bytes = DIV_ROUND_UP( +- cell->nbits + cell->bit_offset, +- BITS_PER_BYTE); +- +- if (!IS_ALIGNED(cell->offset, nvmem->stride)) { +- dev_err(dev, "cell %s unaligned to nvmem stride %d\n", +- cell->name, nvmem->stride); +- /* Cells already added will be freed later. */ +- kfree_const(cell->name); +- kfree(cell); ++ info.np = of_node_get(child); ++ ++ ret = nvmem_add_one_cell(nvmem, &info); ++ kfree(info.name); ++ if (ret) { + of_node_put(child); +- return -EINVAL; ++ return ret; + } +- +- cell->np = of_node_get(child); +- nvmem_cell_entry_add(cell); + } + + return 0; diff --git a/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch b/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch new file mode 100644 index 0000000000..172a78b76a --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch @@ -0,0 +1,562 @@ +From 6a0bc3522e746025e2d9a63ab2cb5d7062c2d39c Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Mon, 6 Feb 2023 13:43:51 +0000 +Subject: [PATCH] nvmem: stm32: add OP-TEE support for STM32MP13x + +For boot with OP-TEE on STM32MP13, the communication with the secure +world no more use STMicroelectronics SMC but communication with the +STM32MP BSEC TA, for data access (read/write) or lock operation: +- all the request are sent to OP-TEE trusted application, +- for upper OTP with ECC protection and with word programming only + each OTP are permanently locked when programmed to avoid ECC error + on the second write operation + +Signed-off-by: Patrick Delaunay +Reviewed-by: Etienne Carriere +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-18-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 11 + + drivers/nvmem/Makefile | 1 + + drivers/nvmem/stm32-bsec-optee-ta.c | 298 ++++++++++++++++++++++++++++ + drivers/nvmem/stm32-bsec-optee-ta.h | 80 ++++++++ + drivers/nvmem/stm32-romem.c | 54 ++++- + 5 files changed, 441 insertions(+), 3 deletions(-) + create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.c + create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.h + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -290,9 +290,20 @@ config NVMEM_SPRD_EFUSE + This driver can also be built as a module. If so, the module + will be called nvmem-sprd-efuse. + ++config NVMEM_STM32_BSEC_OPTEE_TA ++ bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" ++ depends on OPTEE ++ help ++ Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE ++ trusted application STM32MP BSEC. ++ ++ This library is a used by stm32-romem driver or included in the module ++ called nvmem-stm32-romem. ++ + config NVMEM_STM32_ROMEM + tristate "STMicroelectronics STM32 factory-programmed memory support" + depends on ARCH_STM32 || COMPILE_TEST ++ imply NVMEM_STM32_BSEC_OPTEE_TA + help + Say y here to enable read-only access for STMicroelectronics STM32 + factory-programmed memory area. +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -61,6 +61,7 @@ obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem + nvmem_sprd_efuse-y := sprd-efuse.o + obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o + nvmem_stm32_romem-y := stm32-romem.o ++nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o + obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o + nvmem_sunplus_ocotp-y := sunplus-ocotp.o + obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o +--- /dev/null ++++ b/drivers/nvmem/stm32-bsec-optee-ta.c +@@ -0,0 +1,298 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver ++ * ++ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++ ++#include "stm32-bsec-optee-ta.h" ++ ++/* ++ * Read OTP memory ++ * ++ * [in] value[0].a OTP start offset in byte ++ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) ++ * [out] memref[1].buffer Output buffer to store read values ++ * [out] memref[1].size Size of OTP to be read ++ * ++ * Return codes: ++ * TEE_SUCCESS - Invoke command success ++ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param ++ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller ++ */ ++#define PTA_BSEC_READ_MEM 0x0 ++ ++/* ++ * Write OTP memory ++ * ++ * [in] value[0].a OTP start offset in byte ++ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) ++ * [in] memref[1].buffer Input buffer to read values ++ * [in] memref[1].size Size of OTP to be written ++ * ++ * Return codes: ++ * TEE_SUCCESS - Invoke command success ++ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param ++ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller ++ */ ++#define PTA_BSEC_WRITE_MEM 0x1 ++ ++/* value of PTA_BSEC access type = value[in] b */ ++#define SHADOW_ACCESS 0 ++#define FUSE_ACCESS 1 ++#define LOCK_ACCESS 2 ++ ++/* Bitfield definition for LOCK status */ ++#define LOCK_PERM BIT(30) ++ ++/* OP-TEE STM32MP BSEC TA UUID */ ++static const uuid_t stm32mp_bsec_ta_uuid = ++ UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5, ++ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03); ++ ++/* ++ * Check whether this driver supports the BSEC TA in the TEE instance ++ * represented by the params (ver/data) to this function. ++ */ ++static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver, ++ const void *data) ++{ ++ /* Currently this driver only supports GP compliant, OP-TEE based TA */ ++ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) && ++ (ver->gen_caps & TEE_GEN_CAP_GP)) ++ return 1; ++ else ++ return 0; ++} ++ ++/* Open a session to OP-TEE for STM32MP BSEC TA */ ++static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id) ++{ ++ struct tee_ioctl_open_session_arg sess_arg; ++ int rc; ++ ++ memset(&sess_arg, 0, sizeof(sess_arg)); ++ export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid); ++ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; ++ sess_arg.num_params = 0; ++ ++ rc = tee_client_open_session(ctx, &sess_arg, NULL); ++ if ((rc < 0) || (sess_arg.ret != 0)) { ++ pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n", ++ __func__, sess_arg.ret, rc); ++ if (!rc) ++ rc = -EINVAL; ++ } else { ++ *id = sess_arg.session; ++ } ++ ++ return rc; ++} ++ ++/* close a session to OP-TEE for STM32MP BSEC TA */ ++static void stm32_bsec_ta_close_session(void *ctx, u32 id) ++{ ++ tee_client_close_session(ctx, id); ++} ++ ++/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */ ++int stm32_bsec_optee_ta_open(struct tee_context **ctx) ++{ ++ struct tee_context *tee_ctx; ++ u32 session_id; ++ int rc; ++ ++ /* Open context with TEE driver */ ++ tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL); ++ if (IS_ERR(tee_ctx)) { ++ rc = PTR_ERR(tee_ctx); ++ if (rc == -ENOENT) ++ return -EPROBE_DEFER; ++ pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc); ++ ++ return rc; ++ } ++ ++ /* Check STM32MP BSEC TA presence */ ++ rc = stm32_bsec_ta_open_session(tee_ctx, &session_id); ++ if (rc) { ++ tee_client_close_context(tee_ctx); ++ return rc; ++ } ++ ++ stm32_bsec_ta_close_session(tee_ctx, session_id); ++ ++ *ctx = tee_ctx; ++ ++ return 0; ++} ++ ++/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */ ++void stm32_bsec_optee_ta_close(void *ctx) ++{ ++ tee_client_close_context(ctx); ++} ++ ++/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */ ++int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ struct tee_shm *shm; ++ struct tee_ioctl_invoke_arg arg; ++ struct tee_param param[2]; ++ u8 *shm_buf; ++ u32 start, num_bytes; ++ int ret; ++ u32 session_id; ++ ++ ret = stm32_bsec_ta_open_session(ctx, &session_id); ++ if (ret) ++ return ret; ++ ++ memset(&arg, 0, sizeof(arg)); ++ memset(¶m, 0, sizeof(param)); ++ ++ arg.func = PTA_BSEC_READ_MEM; ++ arg.session = session_id; ++ arg.num_params = 2; ++ ++ /* align access on 32bits */ ++ start = ALIGN_DOWN(offset, 4); ++ num_bytes = round_up(offset + bytes - start, 4); ++ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; ++ param[0].u.value.a = start; ++ param[0].u.value.b = SHADOW_ACCESS; ++ ++ shm = tee_shm_alloc_kernel_buf(ctx, num_bytes); ++ if (IS_ERR(shm)) { ++ ret = PTR_ERR(shm); ++ goto out_tee_session; ++ } ++ ++ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; ++ param[1].u.memref.shm = shm; ++ param[1].u.memref.size = num_bytes; ++ ++ ret = tee_client_invoke_func(ctx, &arg, param); ++ if (ret < 0 || arg.ret != 0) { ++ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", ++ arg.ret, ret); ++ if (!ret) ++ ret = -EIO; ++ } ++ if (!ret) { ++ shm_buf = tee_shm_get_va(shm, 0); ++ if (IS_ERR(shm_buf)) { ++ ret = PTR_ERR(shm_buf); ++ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); ++ } else { ++ /* read data from 32 bits aligned buffer */ ++ memcpy(buf, &shm_buf[offset % 4], bytes); ++ } ++ } ++ ++ tee_shm_free(shm); ++ ++out_tee_session: ++ stm32_bsec_ta_close_session(ctx, session_id); ++ ++ return ret; ++} ++ ++/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */ ++int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, ++ unsigned int offset, void *buf, size_t bytes) ++{ struct tee_shm *shm; ++ struct tee_ioctl_invoke_arg arg; ++ struct tee_param param[2]; ++ u8 *shm_buf; ++ int ret; ++ u32 session_id; ++ ++ ret = stm32_bsec_ta_open_session(ctx, &session_id); ++ if (ret) ++ return ret; ++ ++ /* Allow only writing complete 32-bits aligned words */ ++ if ((bytes % 4) || (offset % 4)) ++ return -EINVAL; ++ ++ memset(&arg, 0, sizeof(arg)); ++ memset(¶m, 0, sizeof(param)); ++ ++ arg.func = PTA_BSEC_WRITE_MEM; ++ arg.session = session_id; ++ arg.num_params = 2; ++ ++ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; ++ param[0].u.value.a = offset; ++ param[0].u.value.b = FUSE_ACCESS; ++ ++ shm = tee_shm_alloc_kernel_buf(ctx, bytes); ++ if (IS_ERR(shm)) { ++ ret = PTR_ERR(shm); ++ goto out_tee_session; ++ } ++ ++ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; ++ param[1].u.memref.shm = shm; ++ param[1].u.memref.size = bytes; ++ ++ shm_buf = tee_shm_get_va(shm, 0); ++ if (IS_ERR(shm_buf)) { ++ ret = PTR_ERR(shm_buf); ++ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); ++ tee_shm_free(shm); ++ ++ goto out_tee_session; ++ } ++ ++ memcpy(shm_buf, buf, bytes); ++ ++ ret = tee_client_invoke_func(ctx, &arg, param); ++ if (ret < 0 || arg.ret != 0) { ++ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); ++ if (!ret) ++ ret = -EIO; ++ } ++ pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret); ++ ++ /* Lock the upper OTPs with ECC protection, word programming only */ ++ if (!ret && ((offset + bytes) >= (lower * 4))) { ++ u32 start, nb_lock; ++ u32 *lock = (u32 *)shm_buf; ++ int i; ++ ++ /* ++ * don't lock the lower OTPs, no ECC protection and incremental ++ * bit programming, a second write is allowed ++ */ ++ start = max_t(u32, offset, lower * 4); ++ nb_lock = (offset + bytes - start) / 4; ++ ++ param[0].u.value.a = start; ++ param[0].u.value.b = LOCK_ACCESS; ++ param[1].u.memref.size = nb_lock * 4; ++ ++ for (i = 0; i < nb_lock; i++) ++ lock[i] = LOCK_PERM; ++ ++ ret = tee_client_invoke_func(ctx, &arg, param); ++ if (ret < 0 || arg.ret != 0) { ++ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); ++ if (!ret) ++ ret = -EIO; ++ } ++ pr_debug("Lock upper OTPs %d to %d, ret=%d\n", ++ start / 4, start / 4 + nb_lock, ret); ++ } ++ ++ tee_shm_free(shm); ++ ++out_tee_session: ++ stm32_bsec_ta_close_session(ctx, session_id); ++ ++ return ret; ++} +--- /dev/null ++++ b/drivers/nvmem/stm32-bsec-optee-ta.h +@@ -0,0 +1,80 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver ++ * ++ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved ++ */ ++ ++#if IS_ENABLED(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) ++/** ++ * stm32_bsec_optee_ta_open() - initialize the STM32 BSEC TA ++ * @ctx: the OP-TEE context on success ++ * ++ * Return: ++ * On success, 0. On failure, -errno. ++ */ ++int stm32_bsec_optee_ta_open(struct tee_context **ctx); ++ ++/** ++ * stm32_bsec_optee_ta_close() - release the STM32 BSEC TA ++ * @ctx: the OP-TEE context ++ * ++ * This function used to clean the OP-TEE resources initialized in ++ * stm32_bsec_optee_ta_open(); it can be used as callback to ++ * devm_add_action_or_reset() ++ */ ++void stm32_bsec_optee_ta_close(void *ctx); ++ ++/** ++ * stm32_bsec_optee_ta_read() - nvmem read access using TA client driver ++ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open ++ * @offset: nvmem offset ++ * @buf: buffer to fill with nvem values ++ * @bytes: number of bytes to read ++ * ++ * Return: ++ * On success, 0. On failure, -errno. ++ */ ++int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, ++ void *buf, size_t bytes); ++ ++/** ++ * stm32_bsec_optee_ta_write() - nvmem write access using TA client driver ++ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open ++ * @lower: number of lower OTP, not protected by ECC ++ * @offset: nvmem offset ++ * @buf: buffer with nvem values ++ * @bytes: number of bytes to write ++ * ++ * Return: ++ * On success, 0. On failure, -errno. ++ */ ++int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, ++ unsigned int offset, void *buf, size_t bytes); ++ ++#else ++ ++static inline int stm32_bsec_optee_ta_open(struct tee_context **ctx) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void stm32_bsec_optee_ta_close(void *ctx) ++{ ++} ++ ++static inline int stm32_bsec_optee_ta_read(struct tee_context *ctx, ++ unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline int stm32_bsec_optee_ta_write(struct tee_context *ctx, ++ unsigned int lower, ++ unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ return -EOPNOTSUPP; ++} ++#endif /* CONFIG_NVMEM_STM32_BSEC_OPTEE_TA */ +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -11,6 +11,9 @@ + #include + #include + #include ++#include ++ ++#include "stm32-bsec-optee-ta.h" + + /* BSEC secure service access from non-secure */ + #define STM32_SMC_BSEC 0x82001003 +@@ -25,12 +28,14 @@ + struct stm32_romem_cfg { + int size; + u8 lower; ++ bool ta; + }; + + struct stm32_romem_priv { + void __iomem *base; + struct nvmem_config cfg; + u8 lower; ++ struct tee_context *ctx; + }; + + static int stm32_romem_read(void *context, unsigned int offset, void *buf, +@@ -138,12 +143,29 @@ static int stm32_bsec_write(void *contex + return 0; + } + ++static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ struct stm32_romem_priv *priv = context; ++ ++ return stm32_bsec_optee_ta_read(priv->ctx, offset, buf, bytes); ++} ++ ++static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ struct stm32_romem_priv *priv = context; ++ ++ return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); ++} ++ + static int stm32_romem_probe(struct platform_device *pdev) + { + const struct stm32_romem_cfg *cfg; + struct device *dev = &pdev->dev; + struct stm32_romem_priv *priv; + struct resource *res; ++ int rc; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -173,15 +195,31 @@ static int stm32_romem_probe(struct plat + } else { + priv->cfg.size = cfg->size; + priv->lower = cfg->lower; +- priv->cfg.reg_read = stm32_bsec_read; +- priv->cfg.reg_write = stm32_bsec_write; ++ if (cfg->ta) { ++ rc = stm32_bsec_optee_ta_open(&priv->ctx); ++ /* wait for OP-TEE client driver to be up and ready */ ++ if (rc) ++ return rc; ++ } ++ if (priv->ctx) { ++ rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); ++ if (rc) { ++ dev_err(dev, "devm_add_action_or_reset() failed (%d)\n", rc); ++ return rc; ++ } ++ priv->cfg.reg_read = stm32_bsec_pta_read; ++ priv->cfg.reg_write = stm32_bsec_pta_write; ++ } else { ++ priv->cfg.reg_read = stm32_bsec_read; ++ priv->cfg.reg_write = stm32_bsec_write; ++ } + } + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); + } + + /* +- * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) ++ * STM32MP15/13 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) + * => 96 x 32-bits data words + * - Lower: 1K bits, 2:1 redundancy, incremental bit programming + * => 32 (x 32-bits) lower shadow registers = words 0 to 31 +@@ -191,6 +229,13 @@ static int stm32_romem_probe(struct plat + static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { + .size = 384, + .lower = 32, ++ .ta = false, ++}; ++ ++static const struct stm32_romem_cfg stm32mp13_bsec_cfg = { ++ .size = 384, ++ .lower = 32, ++ .ta = true, + }; + + static const struct of_device_id stm32_romem_of_match[] = { +@@ -198,7 +243,10 @@ static const struct of_device_id stm32_r + .compatible = "st,stm32mp15-bsec", + .data = (void *)&stm32mp15_bsec_cfg, + }, { ++ .compatible = "st,stm32mp13-bsec", ++ .data = (void *)&stm32mp13_bsec_cfg, + }, ++ { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, stm32_romem_of_match); + diff --git a/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch b/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch new file mode 100644 index 0000000000..cea8e93858 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch @@ -0,0 +1,85 @@ +From df2f34ef1d924125ffaf29dfdaf7cdbd3183c321 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Mon, 6 Feb 2023 13:43:52 +0000 +Subject: [PATCH] nvmem: stm32: detect bsec pta presence for STM32MP15x + +On STM32MP15x SoC, the SMC backend is optional when OP-TEE is used; +the PTA BSEC should be used as it is done on STM32MP13x platform, +but the BSEC SMC can be also used: it is a legacy mode in OP-TEE, +not recommended but used in previous OP-TEE firmware. + +The presence of OP-TEE is dynamically detected in STM32MP15x device tree +and the supported NVMEM backend is dynamically detected: +- PTA with stm32_bsec_pta_find +- SMC with stm32_bsec_check + +With OP-TEE but without PTA and SMC detection, the probe is deferred for +STM32MP15x devices. + +On STM32MP13x platform, only the PTA is supported with cfg->ta = true +and this detection is skipped. + +Signed-off-by: Patrick Delaunay +Reviewed-by: Etienne Carriere +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-19-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 38 +++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -159,6 +159,31 @@ static int stm32_bsec_pta_write(void *co + return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); + } + ++static bool stm32_bsec_smc_check(void) ++{ ++ u32 val; ++ int ret; ++ ++ /* check that the OP-TEE support the BSEC SMC (legacy mode) */ ++ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, 0, 0, &val); ++ ++ return !ret; ++} ++ ++static bool optee_presence_check(void) ++{ ++ struct device_node *np; ++ bool tee_detected = false; ++ ++ /* check that the OP-TEE node is present and available. */ ++ np = of_find_compatible_node(NULL, NULL, "linaro,optee-tz"); ++ if (np && of_device_is_available(np)) ++ tee_detected = true; ++ of_node_put(np); ++ ++ return tee_detected; ++} ++ + static int stm32_romem_probe(struct platform_device *pdev) + { + const struct stm32_romem_cfg *cfg; +@@ -195,11 +220,16 @@ static int stm32_romem_probe(struct plat + } else { + priv->cfg.size = cfg->size; + priv->lower = cfg->lower; +- if (cfg->ta) { ++ if (cfg->ta || optee_presence_check()) { + rc = stm32_bsec_optee_ta_open(&priv->ctx); +- /* wait for OP-TEE client driver to be up and ready */ +- if (rc) +- return rc; ++ if (rc) { ++ /* wait for OP-TEE client driver to be up and ready */ ++ if (rc == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ /* BSEC PTA is required or SMC not supported */ ++ if (cfg->ta || !stm32_bsec_smc_check()) ++ return rc; ++ } + } + if (priv->ctx) { + rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch b/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch new file mode 100644 index 0000000000..9d6275a737 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch @@ -0,0 +1,32 @@ +From 3e5ac22aa564026e99defc3a8e02082521a5b231 Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Mon, 6 Feb 2023 13:43:53 +0000 +Subject: [PATCH] nvmem: rave-sp-eeprm: fix kernel-doc bad line warning + +Convert an empty line to " *" to avoid a kernel-doc warning: + +drivers/nvmem/rave-sp-eeprom.c:48: warning: bad line: + +Signed-off-by: Randy Dunlap +Cc: Srinivas Kandagatla +Cc: Andrey Vostrikov +Cc: Nikita Yushchenko +Cc: Andrey Smirnov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-20-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rave-sp-eeprom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/rave-sp-eeprom.c ++++ b/drivers/nvmem/rave-sp-eeprom.c +@@ -45,7 +45,7 @@ enum rave_sp_eeprom_header_size { + * @type: Access type (see enum rave_sp_eeprom_access_type) + * @success: Success flag (Success = 1, Failure = 0) + * @data: Read data +- ++ * + * Note this structure corresponds to RSP_*_EEPROM payload from RAVE + * SP ICD + */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch b/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch new file mode 100644 index 0000000000..1ab9e609d3 --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch @@ -0,0 +1,43 @@ +From eb7dda20f42a9137e9ee53d5ed3b743d49338cb5 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 6 Feb 2023 13:43:54 +0000 +Subject: [PATCH] nvmem: qcom-spmi-sdam: register at device init time + +There are currently no in-tree users of the Qualcomm SDAM nvmem driver +and there is generally no point in registering a driver that can be +built as a module at subsys init time. + +Register the driver at the normal device init time instead and let +driver core sort out the probe order. + +Signed-off-by: Johan Hovold +Reviewed-by: Bjorn Andersson +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-21-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qcom-spmi-sdam.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +--- a/drivers/nvmem/qcom-spmi-sdam.c ++++ b/drivers/nvmem/qcom-spmi-sdam.c +@@ -175,18 +175,7 @@ static struct platform_driver sdam_drive + }, + .probe = sdam_probe, + }; +- +-static int __init sdam_init(void) +-{ +- return platform_driver_register(&sdam_driver); +-} +-subsys_initcall(sdam_init); +- +-static void __exit sdam_exit(void) +-{ +- return platform_driver_unregister(&sdam_driver); +-} +-module_exit(sdam_exit); ++module_platform_driver(sdam_driver); + + MODULE_DESCRIPTION("QCOM SPMI SDAM driver"); + MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch b/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch new file mode 100644 index 0000000000..dcf704c6ff --- /dev/null +++ b/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch @@ -0,0 +1,46 @@ +From 1dc7e37bb0ec1c997fac82031332a38c7610352f Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 6 Feb 2023 13:43:56 +0000 +Subject: [PATCH] nvmem: stm32: fix OPTEE dependency + +The stm32 nvmem driver fails to link as built-in when OPTEE +is a loadable module: + +aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: +stm32-bsec-optee-ta.c:(.text+0xc8): undefined reference to `tee_client_open_session' +aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: +stm32-bsec-optee-ta.c:(.text+0x1fc): undefined reference to `tee_client_open_context' + +Change the CONFIG_NVMEM_STM32_ROMEM definition so it can only +be built-in if OPTEE is either built-in or disabled, and +make NVMEM_STM32_BSEC_OPTEE_TA a hidden symbol instead. + +Signed-off-by: Arnd Bergmann +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-23-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -291,8 +291,7 @@ config NVMEM_SPRD_EFUSE + will be called nvmem-sprd-efuse. + + config NVMEM_STM32_BSEC_OPTEE_TA +- bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" +- depends on OPTEE ++ def_bool NVMEM_STM32_ROMEM && OPTEE + help + Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE + trusted application STM32MP BSEC. +@@ -303,7 +302,7 @@ config NVMEM_STM32_BSEC_OPTEE_TA + config NVMEM_STM32_ROMEM + tristate "STMicroelectronics STM32 factory-programmed memory support" + depends on ARCH_STM32 || COMPILE_TEST +- imply NVMEM_STM32_BSEC_OPTEE_TA ++ depends on OPTEE || !OPTEE + help + Say y here to enable read-only access for STMicroelectronics STM32 + factory-programmed memory area. diff --git a/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch b/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch new file mode 100644 index 0000000000..60a90136c9 --- /dev/null +++ b/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch @@ -0,0 +1,75 @@ +From 4d70c74659d9746502b23d055dba03d1d28ec388 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Wed, 30 Nov 2022 15:48:35 +0200 +Subject: [PATCH] i915: Move list_count() to list.h as list_count_nodes() for + broader use + +Some of the existing users, and definitely will be new ones, want to +count existing nodes in the list. Provide a generic API for that by +moving code from i915 to list.h. + +Reviewed-by: Lucas De Marchi +Acked-by: Jani Nikula +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20221130134838.23805-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/gt/intel_engine_cs.c | 15 ++------------- + include/linux/list.h | 15 +++++++++++++++ + 2 files changed, 17 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c ++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +@@ -4154,17 +4154,6 @@ void intel_execlists_show_requests(struc + spin_unlock_irqrestore(&sched_engine->lock, flags); + } + +-static unsigned long list_count(struct list_head *list) +-{ +- struct list_head *pos; +- unsigned long count = 0; +- +- list_for_each(pos, list) +- count++; +- +- return count; +-} +- + void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, + struct i915_request *hung_rq, + struct drm_printer *m) +@@ -4175,8 +4164,8 @@ void intel_execlists_dump_active_request + + intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); + +- drm_printf(m, "\tOn hold?: %lu\n", +- list_count(&engine->sched_engine->hold)); ++ drm_printf(m, "\tOn hold?: %zu\n", ++ list_count_nodes(&engine->sched_engine->hold)); + + spin_unlock_irqrestore(&engine->sched_engine->lock, flags); + } +--- a/include/linux/list.h ++++ b/include/linux/list.h +@@ -656,6 +656,21 @@ static inline void list_splice_tail_init + pos = n, n = pos->prev) + + /** ++ * list_count_nodes - count nodes in the list ++ * @head: the head for your list. ++ */ ++static inline size_t list_count_nodes(struct list_head *head) ++{ ++ struct list_head *pos; ++ size_t count = 0; ++ ++ list_for_each(pos, head) ++ count++; ++ ++ return count; ++} ++ ++/** + * list_entry_is_head - test if the entry points to the head of the list + * @pos: the type * to cursor + * @head: the head for your list. diff --git a/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch b/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch new file mode 100644 index 0000000000..8328e87c0a --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch @@ -0,0 +1,35 @@ +From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001 +From: Nick Alcock +Date: Tue, 4 Apr 2023 18:21:11 +0100 +Subject: [PATCH] nvmem: xilinx: zynqmp: make modular + +This driver has a MODULE_LICENSE but is not tristate so cannot be +built as a module, unlike all its peers: make it modular to match. + +Signed-off-by: Nick Alcock +Suggested-by: Michal Simek +Cc: Luis Chamberlain +Cc: linux-modules@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: Hitomi Hasegawa +Cc: Srinivas Kandagatla +Cc: Michal Simek +Cc: linux-arm-kernel@lists.infradead.org +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP + be called nvmem-vf610-ocotp. + + config NVMEM_ZYNQMP +- bool "Xilinx ZYNQMP SoC nvmem firmware support" ++ tristate "Xilinx ZYNQMP SoC nvmem firmware support" + depends on ARCH_ZYNQMP + help + This is a driver to access hardware related data like diff --git a/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch new file mode 100644 index 0000000000..94cd23c18a --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch @@ -0,0 +1,387 @@ +From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:21 +0100 +Subject: [PATCH] nvmem: core: introduce NVMEM layouts + +NVMEM layouts are used to generate NVMEM cells during runtime. Think of +an EEPROM with a well-defined conent. For now, the content can be +described by a device tree or a board file. But this only works if the +offsets and lengths are static and don't change. One could also argue +that putting the layout of the EEPROM in the device tree is the wrong +place. Instead, the device tree should just have a specific compatible +string. + +Right now there are two use cases: + (1) The NVMEM cell needs special processing. E.g. if it only specifies + a base MAC address offset and you need to add an offset, or it + needs to parse a MAC from ASCII format or some proprietary format. + (Post processing of cells is added in a later commit). + (2) u-boot environment parsing. The cells don't have a particular + offset but it needs parsing the content to determine the offsets + and length. + +Co-developed-by: Miquel Raynal +Signed-off-by: Miquel Raynal +Signed-off-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/driver-api/nvmem.rst | 15 ++++ + drivers/nvmem/Kconfig | 4 + + drivers/nvmem/Makefile | 1 + + drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++ + drivers/nvmem/layouts/Kconfig | 5 ++ + drivers/nvmem/layouts/Makefile | 4 + + include/linux/nvmem-consumer.h | 7 ++ + include/linux/nvmem-provider.h | 51 ++++++++++++ + 8 files changed, 207 insertions(+) + create mode 100644 drivers/nvmem/layouts/Kconfig + create mode 100644 drivers/nvmem/layouts/Makefile + +--- a/Documentation/driver-api/nvmem.rst ++++ b/Documentation/driver-api/nvmem.rst +@@ -185,3 +185,18 @@ ex:: + ===================== + + See Documentation/devicetree/bindings/nvmem/nvmem.txt ++ ++8. NVMEM layouts ++================ ++ ++NVMEM layouts are yet another mechanism to create cells. With the device ++tree binding it is possible to specify simple cells by using an offset ++and a length. Sometimes, the cells doesn't have a static offset, but ++the content is still well defined, e.g. tag-length-values. In this case, ++the NVMEM device content has to be first parsed and the cells need to ++be added accordingly. Layouts let you read the content of the NVMEM device ++and let you add cells dynamically. ++ ++Another use case for layouts is the post processing of cells. With layouts, ++it is possible to associate a custom post processing hook to a cell. It ++even possible to add this hook to cells not created by the layout itself. +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -21,6 +21,10 @@ config NVMEM_SYSFS + This interface is mostly used by userspace applications to + read/write directly into nvmem. + ++# Layouts ++ ++source "drivers/nvmem/layouts/Kconfig" ++ + # Devices + + config NVMEM_APPLE_EFUSES +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -5,6 +5,7 @@ + + obj-$(CONFIG_NVMEM) += nvmem_core.o + nvmem_core-y := core.o ++obj-y += layouts/ + + # Devices + obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -40,6 +40,7 @@ struct nvmem_device { + nvmem_reg_write_t reg_write; + nvmem_cell_post_process_t cell_post_process; + struct gpio_desc *wp_gpio; ++ struct nvmem_layout *layout; + void *priv; + }; + +@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list); + + static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); + ++static DEFINE_SPINLOCK(nvmem_layout_lock); ++static LIST_HEAD(nvmem_layouts); ++ + static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, + void *val, size_t bytes) + { +@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc + return 0; + } + ++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) ++{ ++ layout->owner = owner; ++ ++ spin_lock(&nvmem_layout_lock); ++ list_add(&layout->node, &nvmem_layouts); ++ spin_unlock(&nvmem_layout_lock); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(__nvmem_layout_register); ++ ++void nvmem_layout_unregister(struct nvmem_layout *layout) ++{ ++ spin_lock(&nvmem_layout_lock); ++ list_del(&layout->node); ++ spin_unlock(&nvmem_layout_lock); ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_unregister); ++ ++static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) ++{ ++ struct device_node *layout_np, *np = nvmem->dev.of_node; ++ struct nvmem_layout *l, *layout = NULL; ++ ++ layout_np = of_get_child_by_name(np, "nvmem-layout"); ++ if (!layout_np) ++ return NULL; ++ ++ spin_lock(&nvmem_layout_lock); ++ ++ list_for_each_entry(l, &nvmem_layouts, node) { ++ if (of_match_node(l->of_match_table, layout_np)) { ++ if (try_module_get(l->owner)) ++ layout = l; ++ ++ break; ++ } ++ } ++ ++ spin_unlock(&nvmem_layout_lock); ++ of_node_put(layout_np); ++ ++ return layout; ++} ++ ++static void nvmem_layout_put(struct nvmem_layout *layout) ++{ ++ if (layout) ++ module_put(layout->owner); ++} ++ ++static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem) ++{ ++ struct nvmem_layout *layout = nvmem->layout; ++ int ret; ++ ++ if (layout && layout->add_cells) { ++ ret = layout->add_cells(&nvmem->dev, nvmem, layout); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++#if IS_ENABLED(CONFIG_OF) ++/** ++ * of_nvmem_layout_get_container() - Get OF node to layout container. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: a node pointer with refcount incremented or NULL if no ++ * container exists. Use of_node_put() on it when done. ++ */ ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); ++} ++EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); ++#endif ++ ++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout) ++{ ++ struct device_node __maybe_unused *layout_np; ++ const struct of_device_id *match; ++ ++ layout_np = of_nvmem_layout_get_container(nvmem); ++ match = of_match_node(layout->of_match_table, layout_np); ++ ++ return match ? match->data : NULL; ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); ++ + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons + goto err_put_device; + } + ++ /* ++ * If the driver supplied a layout by config->layout, the module ++ * pointer will be NULL and nvmem_layout_put() will be a noop. ++ */ ++ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); ++ + if (config->cells) { + rval = nvmem_add_cells(nvmem, config->cells, config->ncells); + if (rval) +@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + ++ rval = nvmem_add_cells_from_layout(nvmem); ++ if (rval) ++ goto err_remove_cells; ++ + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + + return nvmem; + + err_remove_cells: + nvmem_device_remove_all_cells(nvmem); ++ nvmem_layout_put(nvmem->layout); + if (config->compat) + nvmem_sysfs_remove_compat(nvmem, config); + err_put_device: +@@ -881,6 +991,7 @@ static void nvmem_device_release(struct + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + + nvmem_device_remove_all_cells(nvmem); ++ nvmem_layout_put(nvmem->layout); + device_unregister(&nvmem->dev); + } + +@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str + return ERR_PTR(-EINVAL); + } + ++ /* nvmem layouts produce cells within the nvmem-layout container */ ++ if (of_node_name_eq(nvmem_np, "nvmem-layout")) { ++ nvmem_np = of_get_next_parent(nvmem_np); ++ if (!nvmem_np) { ++ of_node_put(cell_np); ++ return ERR_PTR(-EINVAL); ++ } ++ } ++ + nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); + of_node_put(nvmem_np); + if (IS_ERR(nvmem)) { +--- /dev/null ++++ b/drivers/nvmem/layouts/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++menu "Layout Types" ++ ++endmenu +--- /dev/null ++++ b/drivers/nvmem/layouts/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for nvmem layouts. ++# +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(str + const char *id); + struct nvmem_device *of_nvmem_device_get(struct device_node *np, + const char *name); ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); + #else + static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, + const char *id) +@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nv + { + return ERR_PTR(-EOPNOTSUPP); + } ++ ++static inline struct device_node * ++of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return ERR_PTR(-EOPNOTSUPP); ++} + #endif /* CONFIG_NVMEM && CONFIG_OF */ + + #endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -88,6 +88,7 @@ struct nvmem_cell_info { + * @stride: Minimum read/write access stride. + * @priv: User context passed to read/write callbacks. + * @ignore_wp: Write Protect pin is managed by the provider. ++ * @layout: Fixed layout associated with this nvmem device. + * + * Note: A default "nvmem" name will be assigned to the device if + * no name is specified in its configuration. In such case "" is +@@ -109,6 +110,7 @@ struct nvmem_config { + bool read_only; + bool root_only; + bool ignore_wp; ++ struct nvmem_layout *layout; + struct device_node *of_node; + bool no_of_node; + nvmem_reg_read_t reg_read; +@@ -142,6 +144,33 @@ struct nvmem_cell_table { + struct list_head node; + }; + ++/** ++ * struct nvmem_layout - NVMEM layout definitions ++ * ++ * @name: Layout name. ++ * @of_match_table: Open firmware match table. ++ * @add_cells: Will be called if a nvmem device is found which ++ * has this layout. The function will add layout ++ * specific cells with nvmem_add_one_cell(). ++ * @owner: Pointer to struct module. ++ * @node: List node. ++ * ++ * A nvmem device can hold a well defined structure which can just be ++ * evaluated during runtime. For example a TLV list, or a list of "name=val" ++ * pairs. A nvmem layout can parse the nvmem device and add appropriate ++ * cells. ++ */ ++struct nvmem_layout { ++ const char *name; ++ const struct of_device_id *of_match_table; ++ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, ++ struct nvmem_layout *layout); ++ ++ /* private */ ++ struct module *owner; ++ struct list_head node; ++}; ++ + #if IS_ENABLED(CONFIG_NVMEM) + + struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); +@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c + int nvmem_add_one_cell(struct nvmem_device *nvmem, + const struct nvmem_cell_info *info); + ++int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner); ++#define nvmem_layout_register(layout) \ ++ __nvmem_layout_register(layout, THIS_MODULE) ++void nvmem_layout_unregister(struct nvmem_layout *layout); ++ ++const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout); ++ + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str + return -EOPNOTSUPP; + } + ++static inline int nvmem_layout_register(struct nvmem_layout *layout) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} ++ ++static inline const void * ++nvmem_layout_get_match_data(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout) ++{ ++ return NULL; ++} ++ + #endif /* CONFIG_NVMEM */ + #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch new file mode 100644 index 0000000000..6fa7b6382d --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch @@ -0,0 +1,61 @@ +From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:22 +0100 +Subject: [PATCH] nvmem: core: handle the absence of expected layouts + +Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout +is not available. This condition cannot be triggered today as nvmem +layout drivers are initialed as part of an early init call, but soon +these drivers will be converted into modules and be initialized with a +standard priority, so the unavailability of the drivers might become a +reality that must be taken care of. + +Let's anticipate this by telling the caller the layout might not yet be +available. A probe deferral is requested in this case. + +Please note this does not affect any nvmem device not using layouts, +because an early check against the "nvmem-layout" container presence +will return NULL in this case. + +Signed-off-by: Miquel Raynal +Tested-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste + static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) + { + struct device_node *layout_np, *np = nvmem->dev.of_node; +- struct nvmem_layout *l, *layout = NULL; ++ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); + + layout_np = of_get_child_by_name(np, "nvmem-layout"); + if (!layout_np) +@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons + * pointer will be NULL and nvmem_layout_put() will be a noop. + */ + nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); ++ if (IS_ERR(nvmem->layout)) { ++ rval = PTR_ERR(nvmem->layout); ++ nvmem->layout = NULL; ++ ++ if (rval == -EPROBE_DEFER) ++ goto err_teardown_compat; ++ } + + if (config->cells) { + rval = nvmem_add_cells(nvmem, config->cells, config->ncells); +@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons + err_remove_cells: + nvmem_device_remove_all_cells(nvmem); + nvmem_layout_put(nvmem->layout); ++err_teardown_compat: + if (config->compat) + nvmem_sysfs_remove_compat(nvmem, config); + err_put_device: diff --git a/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch b/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch new file mode 100644 index 0000000000..b9341666f9 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch @@ -0,0 +1,52 @@ +From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:23 +0100 +Subject: [PATCH] nvmem: core: request layout modules loading + +When a storage device like an eeprom or an mtd device probes, it +registers an nvmem device if the nvmem subsystem has been enabled (bool +symbol). During nvmem registration, if the device is using layouts to +expose dynamic nvmem cells, the core will first try to get a reference +over the layout driver callbacks. In practice there is not relationship +that can be described between the storage driver and the nvmem +layout. So there is no way we can enforce both drivers will be built-in +or both will be modules. If the storage device driver is built-in but +the layout is built as a module, instead of badly failing with an +endless probe deferral loop, lets just make a modprobe call in case the +driver was made available in an initramfs with +of_device_node_request_module(), and offer a fully functional system to +the user. + +Signed-off-by: Miquel Raynal +Tested-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + struct nvmem_device { +@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout + if (!layout_np) + return NULL; + ++ /* ++ * In case the nvmem device was built-in while the layout was built as a ++ * module, we shall manually request the layout driver loading otherwise ++ * we'll never have any match. ++ */ ++ of_request_module(layout_np); ++ + spin_lock(&nvmem_layout_lock); + + list_for_each_entry(l, &nvmem_layouts, node) { diff --git a/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch b/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch new file mode 100644 index 0000000000..53628cd4e4 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch @@ -0,0 +1,86 @@ +From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:24 +0100 +Subject: [PATCH] nvmem: core: add per-cell post processing + +Instead of relying on the name the consumer is using for the cell, like +it is done for the nvmem .cell_post_process configuration parameter, +provide a per-cell post processing hook. This can then be populated by +the NVMEM provider (or the NVMEM layout) when adding the cell. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 17 +++++++++++++++++ + include/linux/nvmem-provider.h | 3 +++ + 2 files changed, 20 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -54,6 +54,7 @@ struct nvmem_cell_entry { + int bytes; + int bit_offset; + int nbits; ++ nvmem_cell_post_process_t read_post_process; + struct device_node *np; + struct nvmem_device *nvmem; + struct list_head node; +@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell + cell->offset = info->offset; + cell->bytes = info->bytes; + cell->name = info->name; ++ cell->read_post_process = info->read_post_process; + + cell->bit_offset = info->bit_offset; + cell->nbits = info->nbits; +@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme + if (cell->bit_offset || cell->nbits) + nvmem_shift_read_buffer_in_place(cell, buf); + ++ if (cell->read_post_process) { ++ rc = cell->read_post_process(nvmem->priv, id, index, ++ cell->offset, buf, cell->bytes); ++ if (rc) ++ return rc; ++ } ++ + if (nvmem->cell_post_process) { + rc = nvmem->cell_post_process(nvmem->priv, id, index, + cell->offset, buf, cell->bytes); +@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru + (cell->bit_offset == 0 && len != cell->bytes)) + return -EINVAL; + ++ /* ++ * Any cells which have a read_post_process hook are read-only because ++ * we cannot reverse the operation and it might affect other cells, ++ * too. ++ */ ++ if (cell->read_post_process) ++ return -EINVAL; ++ + if (cell->bit_offset || cell->nbits) { + buf = nvmem_cell_prepare_write_buffer(cell, buf, len); + if (IS_ERR(buf)) +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -54,6 +54,8 @@ struct nvmem_keepout { + * @bit_offset: Bit offset if cell is smaller than a byte. + * @nbits: Number of bits. + * @np: Optional device_node pointer. ++ * @read_post_process: Callback for optional post processing of cell data ++ * on reads. + */ + struct nvmem_cell_info { + const char *name; +@@ -62,6 +64,7 @@ struct nvmem_cell_info { + unsigned int bit_offset; + unsigned int nbits; + struct device_node *np; ++ nvmem_cell_post_process_t read_post_process; + }; + + /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch b/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch new file mode 100644 index 0000000000..32990148c8 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch @@ -0,0 +1,59 @@ +From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:25 +0100 +Subject: [PATCH] nvmem: core: allow to modify a cell before adding it + +Provide a way to modify a cell before it will get added. This is useful +to attach a custom post processing hook via a layout. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 4 ++++ + include/linux/nvmem-provider.h | 5 +++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc + + static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) + { ++ struct nvmem_layout *layout = nvmem->layout; + struct device *dev = &nvmem->dev; + struct device_node *child; + const __be32 *addr; +@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc + + info.np = of_node_get(child); + ++ if (layout && layout->fixup_cell_info) ++ layout->fixup_cell_info(nvmem, layout, &info); ++ + ret = nvmem_add_one_cell(nvmem, &info); + kfree(info.name); + if (ret) { +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -155,6 +155,8 @@ struct nvmem_cell_table { + * @add_cells: Will be called if a nvmem device is found which + * has this layout. The function will add layout + * specific cells with nvmem_add_one_cell(). ++ * @fixup_cell_info: Will be called before a cell is added. Can be ++ * used to modify the nvmem_cell_info. + * @owner: Pointer to struct module. + * @node: List node. + * +@@ -168,6 +170,9 @@ struct nvmem_layout { + const struct of_device_id *of_match_table; + int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, + struct nvmem_layout *layout); ++ void (*fixup_cell_info)(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout, ++ struct nvmem_cell_info *cell); + + /* private */ + struct module *owner; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch b/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch new file mode 100644 index 0000000000..2a5fa618ea --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch @@ -0,0 +1,81 @@ +From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:26 +0100 +Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts + +In preparation of retiring the global post processing hook change this +driver to use layouts. The layout will be supplied during registration +and will be used to add the post processing hook to all added cells. + +Signed-off-by: Michael Walle +Tested-by: Michael Walle # on kontron-pitx-imx8m +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -225,18 +225,13 @@ read_end: + static int imx_ocotp_cell_pp(void *context, const char *id, int index, + unsigned int offset, void *data, size_t bytes) + { +- struct ocotp_priv *priv = context; ++ u8 *buf = data; ++ int i; + + /* Deal with some post processing of nvmem cell data */ +- if (id && !strcmp(id, "mac-address")) { +- if (priv->params->reverse_mac_address) { +- u8 *buf = data; +- int i; +- +- for (i = 0; i < bytes/2; i++) +- swap(buf[i], buf[bytes - i - 1]); +- } +- } ++ if (id && !strcmp(id, "mac-address")) ++ for (i = 0; i < bytes / 2; i++) ++ swap(buf[i], buf[bytes - i - 1]); + + return 0; + } +@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvm + .stride = 1, + .reg_read = imx_ocotp_read, + .reg_write = imx_ocotp_write, +- .cell_post_process = imx_ocotp_cell_pp, + }; + + static const struct ocotp_params imx6q_params = { +@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco + }; + MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); + ++static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout, ++ struct nvmem_cell_info *cell) ++{ ++ cell->read_post_process = imx_ocotp_cell_pp; ++} ++ ++struct nvmem_layout imx_ocotp_layout = { ++ .fixup_cell_info = imx_ocotp_fixup_cell_info, ++}; ++ + static int imx_ocotp_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; ++ if (priv->params->reverse_mac_address) ++ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; ++ + priv->config = &imx_ocotp_nvmem_config; + + clk_prepare_enable(priv->clk); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch b/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch new file mode 100644 index 0000000000..eac202b882 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch @@ -0,0 +1,68 @@ +From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:27 +0100 +Subject: [PATCH] nvmem: cell: drop global cell_post_process + +There are no users anymore for the global cell_post_process callback +anymore. New users should use proper nvmem layouts. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 9 --------- + include/linux/nvmem-provider.h | 2 -- + 2 files changed, 11 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -39,7 +39,6 @@ struct nvmem_device { + unsigned int nkeepout; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; +- nvmem_cell_post_process_t cell_post_process; + struct gpio_desc *wp_gpio; + struct nvmem_layout *layout; + void *priv; +@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(cons + nvmem->type = config->type; + nvmem->reg_read = config->reg_read; + nvmem->reg_write = config->reg_write; +- nvmem->cell_post_process = config->cell_post_process; + nvmem->keepout = config->keepout; + nvmem->nkeepout = config->nkeepout; + if (config->of_node) +@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme + if (rc) + return rc; + } +- +- if (nvmem->cell_post_process) { +- rc = nvmem->cell_post_process(nvmem->priv, id, index, +- cell->offset, buf, cell->bytes); +- if (rc) +- return rc; +- } + + if (len) + *len = cell->bytes; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -85,7 +85,6 @@ struct nvmem_cell_info { + * @no_of_node: Device should not use the parent's of_node even if it's !NULL. + * @reg_read: Callback to read data. + * @reg_write: Callback to write data. +- * @cell_post_process: Callback for vendor specific post processing of cell data + * @size: Device size. + * @word_size: Minimum read/write access granularity. + * @stride: Minimum read/write access stride. +@@ -118,7 +117,6 @@ struct nvmem_config { + bool no_of_node; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; +- nvmem_cell_post_process_t cell_post_process; + int size; + int word_size; + int stride; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch b/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch new file mode 100644 index 0000000000..46b30a2ed9 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch @@ -0,0 +1,76 @@ +From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:28 +0100 +Subject: [PATCH] nvmem: core: provide own priv pointer in post process + callback + +It doesn't make any more sense to have a opaque pointer set up by the +nvmem device. Usually, the layout isn't associated with a particular +nvmem device. Instead, let the caller who set the post process callback +provide the priv pointer. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 4 +++- + include/linux/nvmem-provider.h | 5 ++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -54,6 +54,7 @@ struct nvmem_cell_entry { + int bit_offset; + int nbits; + nvmem_cell_post_process_t read_post_process; ++ void *priv; + struct device_node *np; + struct nvmem_device *nvmem; + struct list_head node; +@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell + cell->bytes = info->bytes; + cell->name = info->name; + cell->read_post_process = info->read_post_process; ++ cell->priv = info->priv; + + cell->bit_offset = info->bit_offset; + cell->nbits = info->nbits; +@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme + nvmem_shift_read_buffer_in_place(cell, buf); + + if (cell->read_post_process) { +- rc = cell->read_post_process(nvmem->priv, id, index, ++ rc = cell->read_post_process(cell->priv, id, index, + cell->offset, buf, cell->bytes); + if (rc) + return rc; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p + void *val, size_t bytes); + /* used for vendor specific post processing of cell data */ + typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, +- unsigned int offset, void *buf, size_t bytes); ++ unsigned int offset, void *buf, ++ size_t bytes); + + enum nvmem_type { + NVMEM_TYPE_UNKNOWN = 0, +@@ -56,6 +57,7 @@ struct nvmem_keepout { + * @np: Optional device_node pointer. + * @read_post_process: Callback for optional post processing of cell data + * on reads. ++ * @priv: Opaque data passed to the read_post_process hook. + */ + struct nvmem_cell_info { + const char *name; +@@ -65,6 +67,7 @@ struct nvmem_cell_info { + unsigned int nbits; + struct device_node *np; + nvmem_cell_post_process_t read_post_process; ++ void *priv; + }; + + /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch new file mode 100644 index 0000000000..7d97658b60 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch @@ -0,0 +1,215 @@ +From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 4 Apr 2023 18:21:29 +0100 +Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver + +This layout applies to the VPD of the Kontron sl28 boards. The VPD only +contains a base MAC address. Therefore, we have to add an individual +offset to it. This is done by taking the second argument of the nvmem +phandle into account. Also this let us checking the VPD version and the +checksum. + +Signed-off-by: Michael Walle +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/Kconfig | 9 ++ + drivers/nvmem/layouts/Makefile | 2 + + drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++ + 3 files changed, 176 insertions(+) + create mode 100644 drivers/nvmem/layouts/sl28vpd.c + +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -2,4 +2,13 @@ + + menu "Layout Types" + ++config NVMEM_LAYOUT_SL28_VPD ++ tristate "Kontron sl28 VPD layout support" ++ select CRC8 ++ help ++ Say Y here if you want to support the VPD layout of the Kontron ++ SMARC-sAL28 boards. ++ ++ If unsure, say N. ++ + endmenu +--- a/drivers/nvmem/layouts/Makefile ++++ b/drivers/nvmem/layouts/Makefile +@@ -2,3 +2,5 @@ + # + # Makefile for nvmem layouts. + # ++ ++obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o +--- /dev/null ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -0,0 +1,165 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SL28VPD_MAGIC 'V' ++ ++struct sl28vpd_header { ++ u8 magic; ++ u8 version; ++} __packed; ++ ++struct sl28vpd_v1 { ++ struct sl28vpd_header header; ++ char serial_number[15]; ++ u8 base_mac_address[ETH_ALEN]; ++ u8 crc8; ++} __packed; ++ ++static int sl28vpd_mac_address_pp(void *priv, const char *id, int index, ++ unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ if (bytes != ETH_ALEN) ++ return -EINVAL; ++ ++ if (index < 0) ++ return -EINVAL; ++ ++ if (!is_valid_ether_addr(buf)) ++ return -EINVAL; ++ ++ eth_addr_add(buf, index); ++ ++ return 0; ++} ++ ++static const struct nvmem_cell_info sl28vpd_v1_entries[] = { ++ { ++ .name = "serial-number", ++ .offset = offsetof(struct sl28vpd_v1, serial_number), ++ .bytes = sizeof_field(struct sl28vpd_v1, serial_number), ++ }, ++ { ++ .name = "base-mac-address", ++ .offset = offsetof(struct sl28vpd_v1, base_mac_address), ++ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address), ++ .read_post_process = sl28vpd_mac_address_pp, ++ }, ++}; ++ ++static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem) ++{ ++ struct sl28vpd_v1 data_v1; ++ u8 table[CRC8_TABLE_SIZE]; ++ int ret; ++ u8 crc; ++ ++ crc8_populate_msb(table, 0x07); ++ ++ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1); ++ if (ret < 0) ++ return ret; ++ else if (ret != sizeof(data_v1)) ++ return -EIO; ++ ++ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0); ++ ++ if (crc != data_v1.crc8) { ++ dev_err(dev, ++ "Checksum is invalid (got %02x, expected %02x).\n", ++ crc, data_v1.crc8); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem, ++ struct nvmem_layout *layout) ++{ ++ const struct nvmem_cell_info *pinfo; ++ struct nvmem_cell_info info = {0}; ++ struct device_node *layout_np; ++ struct sl28vpd_header hdr; ++ int ret, i; ++ ++ /* check header */ ++ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); ++ if (ret < 0) ++ return ret; ++ else if (ret != sizeof(hdr)) ++ return -EIO; ++ ++ if (hdr.magic != SL28VPD_MAGIC) { ++ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic); ++ return -EINVAL; ++ } ++ ++ if (hdr.version != 1) { ++ dev_err(dev, "Version %d is unsupported.\n", hdr.version); ++ return -EINVAL; ++ } ++ ++ ret = sl28vpd_v1_check_crc(dev, nvmem); ++ if (ret) ++ return ret; ++ ++ layout_np = of_nvmem_layout_get_container(nvmem); ++ if (!layout_np) ++ return -ENOENT; ++ ++ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) { ++ pinfo = &sl28vpd_v1_entries[i]; ++ ++ info.name = pinfo->name; ++ info.offset = pinfo->offset; ++ info.bytes = pinfo->bytes; ++ info.read_post_process = pinfo->read_post_process; ++ info.np = of_get_child_by_name(layout_np, pinfo->name); ++ ++ ret = nvmem_add_one_cell(nvmem, &info); ++ if (ret) { ++ of_node_put(layout_np); ++ return ret; ++ } ++ } ++ ++ of_node_put(layout_np); ++ ++ return 0; ++} ++ ++static const struct of_device_id sl28vpd_of_match_table[] = { ++ { .compatible = "kontron,sl28-vpd" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); ++ ++struct nvmem_layout sl28vpd_layout = { ++ .name = "sl28-vpd", ++ .of_match_table = sl28vpd_of_match_table, ++ .add_cells = sl28vpd_add_cells, ++}; ++ ++static int __init sl28vpd_init(void) ++{ ++ return nvmem_layout_register(&sl28vpd_layout); ++} ++ ++static void __exit sl28vpd_exit(void) ++{ ++ nvmem_layout_unregister(&sl28vpd_layout); ++} ++ ++module_init(sl28vpd_init); ++module_exit(sl28vpd_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Michael Walle "); ++MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch new file mode 100644 index 0000000000..ca8b4bc069 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch @@ -0,0 +1,306 @@ +From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:31 +0100 +Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver + +This layout applies on top of any non volatile storage device containing +an ONIE table factory flashed. This table follows the tlv +(type-length-value) organization described in the link below. We cannot +afford using regular parsers because the content of these tables is +manufacturer specific and must be dynamically discovered. + +Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/Kconfig | 9 ++ + drivers/nvmem/layouts/Makefile | 1 + + drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++ + 3 files changed, 267 insertions(+) + create mode 100644 drivers/nvmem/layouts/onie-tlv.c + +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD + + If unsure, say N. + ++config NVMEM_LAYOUT_ONIE_TLV ++ tristate "ONIE tlv support" ++ select CRC32 ++ help ++ Say Y here if you want to support the Open Compute Project ONIE ++ Type-Length-Value standard table. ++ ++ If unsure, say N. ++ + endmenu +--- a/drivers/nvmem/layouts/Makefile ++++ b/drivers/nvmem/layouts/Makefile +@@ -4,3 +4,4 @@ + # + + obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o ++obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o +--- /dev/null ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -0,0 +1,257 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * ONIE tlv NVMEM cells provider ++ * ++ * Copyright (C) 2022 Open Compute Group ONIE ++ * Author: Miquel Raynal ++ * Based on the nvmem driver written by: Vadym Kochan ++ * Inspired by the first layout written by: Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define ONIE_TLV_MAX_LEN 2048 ++#define ONIE_TLV_CRC_FIELD_SZ 6 ++#define ONIE_TLV_CRC_SZ 4 ++#define ONIE_TLV_HDR_ID "TlvInfo" ++ ++struct onie_tlv_hdr { ++ u8 id[8]; ++ u8 version; ++ __be16 data_len; ++} __packed; ++ ++struct onie_tlv { ++ u8 type; ++ u8 len; ++} __packed; ++ ++static const char *onie_tlv_cell_name(u8 type) ++{ ++ switch (type) { ++ case 0x21: ++ return "product-name"; ++ case 0x22: ++ return "part-number"; ++ case 0x23: ++ return "serial-number"; ++ case 0x24: ++ return "mac-address"; ++ case 0x25: ++ return "manufacture-date"; ++ case 0x26: ++ return "device-version"; ++ case 0x27: ++ return "label-revision"; ++ case 0x28: ++ return "platform-name"; ++ case 0x29: ++ return "onie-version"; ++ case 0x2A: ++ return "num-macs"; ++ case 0x2B: ++ return "manufacturer"; ++ case 0x2C: ++ return "country-code"; ++ case 0x2D: ++ return "vendor"; ++ case 0x2E: ++ return "diag-version"; ++ case 0x2F: ++ return "service-tag"; ++ case 0xFD: ++ return "vendor-extension"; ++ case 0xFE: ++ return "crc32"; ++ default: ++ break; ++ } ++ ++ return NULL; ++} ++ ++static int onie_tlv_mac_read_cb(void *priv, const char *id, int index, ++ unsigned int offset, void *buf, ++ size_t bytes) ++{ ++ eth_addr_add(buf, index); ++ ++ return 0; ++} ++ ++static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf) ++{ ++ switch (type) { ++ case 0x24: ++ return &onie_tlv_mac_read_cb; ++ default: ++ break; ++ } ++ ++ return NULL; ++} ++ ++static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem, ++ size_t data_len, u8 *data) ++{ ++ struct nvmem_cell_info cell = {}; ++ struct device_node *layout; ++ struct onie_tlv tlv; ++ unsigned int hdr_len = sizeof(struct onie_tlv_hdr); ++ unsigned int offset = 0; ++ int ret; ++ ++ layout = of_nvmem_layout_get_container(nvmem); ++ if (!layout) ++ return -ENOENT; ++ ++ while (offset < data_len) { ++ memcpy(&tlv, data + offset, sizeof(tlv)); ++ if (offset + tlv.len >= data_len) { ++ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n", ++ tlv.len, hdr_len + offset); ++ break; ++ } ++ ++ cell.name = onie_tlv_cell_name(tlv.type); ++ if (!cell.name) ++ continue; ++ ++ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len); ++ cell.bytes = tlv.len; ++ cell.np = of_get_child_by_name(layout, cell.name); ++ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv)); ++ ++ ret = nvmem_add_one_cell(nvmem, &cell); ++ if (ret) { ++ of_node_put(layout); ++ return ret; ++ } ++ ++ offset += sizeof(tlv) + tlv.len; ++ } ++ ++ of_node_put(layout); ++ ++ return 0; ++} ++ ++static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr) ++{ ++ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) { ++ dev_err(dev, "Invalid header\n"); ++ return false; ++ } ++ ++ if (hdr->version != 0x1) { ++ dev_err(dev, "Invalid version number\n"); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table) ++{ ++ struct onie_tlv crc_hdr; ++ u32 read_crc, calc_crc; ++ __be32 crc_be; ++ ++ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr)); ++ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) { ++ dev_err(dev, "Invalid CRC field\n"); ++ return false; ++ } ++ ++ /* The table contains a JAMCRC, which is XOR'ed compared to the original ++ * CRC32 implementation as known in the Ethernet world. ++ */ ++ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ); ++ read_crc = be32_to_cpu(crc_be); ++ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF; ++ if (read_crc != calc_crc) { ++ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n", ++ read_crc, calc_crc); ++ return false; ++ } ++ ++ return true; ++} ++ ++static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem, ++ struct nvmem_layout *layout) ++{ ++ struct onie_tlv_hdr hdr; ++ size_t table_len, data_len, hdr_len; ++ u8 *table, *data; ++ int ret; ++ ++ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); ++ if (ret < 0) ++ return ret; ++ ++ if (!onie_tlv_hdr_is_valid(dev, &hdr)) { ++ dev_err(dev, "Invalid ONIE TLV header\n"); ++ return -EINVAL; ++ } ++ ++ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len); ++ data_len = be16_to_cpu(hdr.data_len); ++ table_len = hdr_len + data_len; ++ if (table_len > ONIE_TLV_MAX_LEN) { ++ dev_err(dev, "Invalid ONIE TLV data length\n"); ++ return -EINVAL; ++ } ++ ++ table = devm_kmalloc(dev, table_len, GFP_KERNEL); ++ if (!table) ++ return -ENOMEM; ++ ++ ret = nvmem_device_read(nvmem, 0, table_len, table); ++ if (ret != table_len) ++ return ret; ++ ++ if (!onie_tlv_crc_is_valid(dev, table_len, table)) ++ return -EINVAL; ++ ++ data = table + hdr_len; ++ ret = onie_tlv_add_cells(dev, nvmem, data_len, data); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static const struct of_device_id onie_tlv_of_match_table[] = { ++ { .compatible = "onie,tlv-layout", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table); ++ ++static struct nvmem_layout onie_tlv_layout = { ++ .name = "ONIE tlv layout", ++ .of_match_table = onie_tlv_of_match_table, ++ .add_cells = onie_tlv_parse_table, ++}; ++ ++static int __init onie_tlv_init(void) ++{ ++ return nvmem_layout_register(&onie_tlv_layout); ++} ++ ++static void __exit onie_tlv_exit(void) ++{ ++ nvmem_layout_unregister(&onie_tlv_layout); ++} ++ ++module_init(onie_tlv_init); ++module_exit(onie_tlv_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Miquel Raynal "); ++MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); ++MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch b/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch new file mode 100644 index 0000000000..94a0911d73 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch @@ -0,0 +1,32 @@ +From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Tue, 4 Apr 2023 18:21:34 +0100 +Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The driver can be compile tested with !CONFIG_OF making certain data +unused: + + drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=] + +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-27-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3 + .ta = true, + }; + +-static const struct of_device_id stm32_romem_of_match[] = { ++static const struct of_device_id stm32_romem_of_match[] __maybe_unused = { + { .compatible = "st,stm32f4-otp", }, { + .compatible = "st,stm32mp15-bsec", + .data = (void *)&stm32mp15_bsec_cfg, diff --git a/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch b/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch new file mode 100644 index 0000000000..abda402bdd --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch @@ -0,0 +1,120 @@ +From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Tue, 4 Apr 2023 18:21:35 +0100 +Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed + binning data + +On some MediaTek SoCs GPU speed binning data is available for read +in the SoC's eFuse array but it has a format that is incompatible +with what the OPP API expects, as we read a number from 0 to 7 but +opp-supported-hw is expecting a bitmask to enable an OPP entry: +being what we read limited to 0-7, it's straightforward to simply +convert the value to BIT(value) as a post-processing action. + +So, introduce post-processing support and enable it by evaluating +the newly introduced platform data's `uses_post_processing` member, +currently enabled only for MT8186. + +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-28-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 51 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -10,6 +10,11 @@ + #include + #include + #include ++#include ++ ++struct mtk_efuse_pdata { ++ bool uses_post_processing; ++}; + + struct mtk_efuse_priv { + void __iomem *base; +@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context, + return 0; + } + ++static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index, ++ unsigned int offset, void *data, size_t bytes) ++{ ++ u8 *val = data; ++ ++ if (val[0] < 8) ++ val[0] = BIT(val[0]); ++ ++ return 0; ++} ++ ++static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_layout *layout, ++ struct nvmem_cell_info *cell) ++{ ++ size_t sz = strlen(cell->name); ++ ++ /* ++ * On some SoCs, the GPU speedbin is not read as bitmask but as ++ * a number with range [0-7] (max 3 bits): post process to use ++ * it in OPP tables to describe supported-hw. ++ */ ++ if (cell->nbits <= 3 && ++ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0) ++ cell->read_post_process = mtk_efuse_gpu_speedbin_pp; ++} ++ ++static struct nvmem_layout mtk_efuse_layout = { ++ .fixup_cell_info = mtk_efuse_fixup_cell_info, ++}; ++ + static int mtk_efuse_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo + struct nvmem_device *nvmem; + struct nvmem_config econfig = {}; + struct mtk_efuse_priv *priv; ++ const struct mtk_efuse_pdata *pdata; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + ++ pdata = device_get_match_data(dev); + econfig.stride = 1; + econfig.word_size = 1; + econfig.reg_read = mtk_reg_read; + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ if (pdata->uses_post_processing) ++ econfig.layout = &mtk_efuse_layout; + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); + } + ++static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { ++ .uses_post_processing = true, ++}; ++ ++static const struct mtk_efuse_pdata mtk_efuse_pdata = { ++ .uses_post_processing = false, ++}; ++ + static const struct of_device_id mtk_efuse_of_match[] = { +- { .compatible = "mediatek,mt8173-efuse",}, +- { .compatible = "mediatek,efuse",}, ++ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata }, ++ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata }, ++ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata }, + {/* sentinel */}, + }; + MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch b/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch new file mode 100644 index 0000000000..200eb1928f --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch @@ -0,0 +1,39 @@ +From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001 +From: Yang Li +Date: Tue, 4 Apr 2023 18:21:38 +0100 +Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource() + +According to commit 7945f929f1a7 ("drivers: provide +devm_platform_ioremap_resource()"), convert platform_get_resource(), +devm_ioremap_resource() to a single call to use +devm_platform_ioremap_resource(), as this is exactly what this function +does. + +Signed-off-by: Yang Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/bcm-ocotp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/bcm-ocotp.c ++++ b/drivers/nvmem/bcm-ocotp.c +@@ -244,7 +244,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_ + static int bcm_otpc_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *res; + struct otpc_priv *priv; + struct nvmem_device *nvmem; + int err; +@@ -259,8 +258,7 @@ static int bcm_otpc_probe(struct platfor + return -ENODEV; + + /* Get OTP base address register. */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) { + dev_err(dev, "unable to map I/O memory\n"); + return PTR_ERR(priv->base); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch b/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch new file mode 100644 index 0000000000..890dacd08d --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch @@ -0,0 +1,39 @@ +From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001 +From: Yang Li +Date: Tue, 4 Apr 2023 18:21:39 +0100 +Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource() + +According to commit 7945f929f1a7 ("drivers: provide +devm_platform_ioremap_resource()"), convert platform_get_resource(), +devm_ioremap_resource() to a single call to use +devm_platform_ioremap_resource(), as this is exactly what this function +does. + +Signed-off-by: Yang Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/nintendo-otp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/nintendo-otp.c ++++ b/drivers/nvmem/nintendo-otp.c +@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla + struct device *dev = &pdev->dev; + const struct of_device_id *of_id = + of_match_device(nintendo_otp_of_table, dev); +- struct resource *res; + struct nvmem_device *nvmem; + struct nintendo_otp_priv *priv; + +@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla + if (!priv) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->regs = devm_ioremap_resource(dev, res); ++ priv->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + diff --git a/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch new file mode 100644 index 0000000000..3f5d3c1ad4 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch @@ -0,0 +1,32 @@ +From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001 +From: Yang Li +Date: Tue, 4 Apr 2023 18:21:40 +0100 +Subject: [PATCH] nvmem: vf610-ocotp: Use + devm_platform_get_and_ioremap_resource() + +According to commit 890cc39a8799 ("drivers: provide +devm_platform_get_and_ioremap_resource()"), convert +platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yang Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/vf610-ocotp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/vf610-ocotp.c ++++ b/drivers/nvmem/vf610-ocotp.c +@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat + if (!ocotp_dev) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- ocotp_dev->base = devm_ioremap_resource(dev, res); ++ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(ocotp_dev->base)) + return PTR_ERR(ocotp_dev->base); + diff --git a/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch b/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch new file mode 100644 index 0000000000..eeb407e9bb --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch @@ -0,0 +1,115 @@ +From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 4 Apr 2023 18:21:42 +0100 +Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post + read lengths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Callback .read_post_process() is designed to modify raw cell content +before providing it to the consumer. So far we were dealing with +modifications that didn't affect cell size (length). In some cases +however cell content needs to be reformatted and resized. + +It's required e.g. to provide properly formatted MAC address in case +it's stored in a non-binary format (e.g. using ASCII). + +There were few discussions how to optimally handle that. Following +possible solutions were considered: +1. Allow .read_post_process() to realloc (resize) content buffer +2. Allow .read_post_process() to adjust (decrease) just buffer length +3. Register NVMEM cells using post-read sizes + +The preferred solution was the last one. The problem is that simply +adjusting "bytes" in NVMEM providers would result in core code NOT +passing whole raw data to .read_post_process() callbacks. It means +callback functions couldn't do their job without somehow manually +reading original cell content on their own. + +This patch deals with that by registering NVMEM cells with both lengths: +raw content one and post read one. It allows: +1. Core code to read whole raw cell content +2. Callbacks to return content they want + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 11 +++++++---- + include/linux/nvmem-provider.h | 2 ++ + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -50,6 +50,7 @@ struct nvmem_device { + struct nvmem_cell_entry { + const char *name; + int offset; ++ size_t raw_len; + int bytes; + int bit_offset; + int nbits; +@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell + { + cell->nvmem = nvmem; + cell->offset = info->offset; ++ cell->raw_len = info->raw_len ?: info->bytes; + cell->bytes = info->bytes; + cell->name = info->name; + cell->read_post_process = info->read_post_process; +@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme + { + int rc; + +- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes); ++ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len); + + if (rc) + return rc; +@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme + + if (cell->read_post_process) { + rc = cell->read_post_process(cell->priv, id, index, +- cell->offset, buf, cell->bytes); ++ cell->offset, buf, cell->raw_len); + if (rc) + return rc; + } +@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme + */ + void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) + { +- struct nvmem_device *nvmem = cell->entry->nvmem; ++ struct nvmem_cell_entry *entry = cell->entry; ++ struct nvmem_device *nvmem = entry->nvmem; + u8 *buf; + int rc; + + if (!nvmem) + return ERR_PTR(-EINVAL); + +- buf = kzalloc(cell->entry->bytes, GFP_KERNEL); ++ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -51,6 +51,7 @@ struct nvmem_keepout { + * struct nvmem_cell_info - NVMEM cell description + * @name: Name. + * @offset: Offset within the NVMEM device. ++ * @raw_len: Length of raw data (without post processing). + * @bytes: Length of the cell. + * @bit_offset: Bit offset if cell is smaller than a byte. + * @nbits: Number of bits. +@@ -62,6 +63,7 @@ struct nvmem_keepout { + struct nvmem_cell_info { + const char *name; + unsigned int offset; ++ size_t raw_len; + unsigned int bytes; + unsigned int bit_offset; + unsigned int nbits; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch b/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch new file mode 100644 index 0000000000..adde0ffc4b --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch @@ -0,0 +1,81 @@ +From c49f1a8af6bcf6d18576bca898f8083ca4b129e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 4 Apr 2023 18:21:43 +0100 +Subject: [PATCH] nvmem: u-boot-env: post-process "ethaddr" env variable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +U-Boot environment variables are stored in ASCII format so "ethaddr" +requires parsing into binary to make it work with Ethernet interfaces. + +This includes support for indexes to support #nvmem-cell-cells = <1>. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-36-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV + tristate "U-Boot environment variables support" + depends on OF && MTD + select CRC32 ++ select GENERIC_NET_UTILS + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -4,6 +4,8 @@ + */ + + #include ++#include ++#include + #include + #include + #include +@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context + return 0; + } + ++static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (bytes != 3 * ETH_ALEN - 1) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { +@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u + priv->cells[idx].offset = data_offset + value - data; + priv->cells[idx].bytes = strlen(value); + priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ if (!strcmp(var, "ethaddr")) { ++ priv->cells[idx].raw_len = strlen(value); ++ priv->cells[idx].bytes = ETH_ALEN; ++ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ } + } + + if (WARN_ON(idx != priv->ncells)) diff --git a/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch b/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch new file mode 100644 index 0000000000..7c6fe22b5f --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch @@ -0,0 +1,42 @@ +From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:44 +0100 +Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide a module_nvmem_layout_driver() macro at the end of the +nvmem-provider.h header to reduce the boilerplate when registering nvmem +layout drivers. + +Suggested-by: Srinivas Kandagatla +Signed-off-by: Miquel Raynal +Acked-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/nvmem-provider.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -9,6 +9,7 @@ + #ifndef _LINUX_NVMEM_PROVIDER_H + #define _LINUX_NVMEM_PROVIDER_H + ++#include + #include + #include + #include +@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem + } + + #endif /* CONFIG_NVMEM */ ++ ++#define module_nvmem_layout_driver(__layout_driver) \ ++ module_driver(__layout_driver, nvmem_layout_register, \ ++ nvmem_layout_unregister) ++ + #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch new file mode 100644 index 0000000000..06646dd68b --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch @@ -0,0 +1,39 @@ +From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:45 +0100 +Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver() + +Stop open-coding the module init/exit functions. Use the +module_nvmem_layout_driver() instead. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/sl28vpd.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = { + .of_match_table = sl28vpd_of_match_table, + .add_cells = sl28vpd_add_cells, + }; +- +-static int __init sl28vpd_init(void) +-{ +- return nvmem_layout_register(&sl28vpd_layout); +-} +- +-static void __exit sl28vpd_exit(void) +-{ +- nvmem_layout_unregister(&sl28vpd_layout); +-} +- +-module_init(sl28vpd_init); +-module_exit(sl28vpd_exit); ++module_nvmem_layout_driver(sl28vpd_layout); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Michael Walle "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch b/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch new file mode 100644 index 0000000000..826f4378c2 --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch @@ -0,0 +1,39 @@ +From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:46 +0100 +Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver() + +Stop open-coding the module init/exit functions. Use the +module_nvmem_layout_driver() instead. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/onie-tlv.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo + .of_match_table = onie_tlv_of_match_table, + .add_cells = onie_tlv_parse_table, + }; +- +-static int __init onie_tlv_init(void) +-{ +- return nvmem_layout_register(&onie_tlv_layout); +-} +- +-static void __exit onie_tlv_exit(void) +-{ +- nvmem_layout_unregister(&onie_tlv_layout); +-} +- +-module_init(onie_tlv_init); +-module_exit(onie_tlv_exit); ++module_nvmem_layout_driver(onie_tlv_layout); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Miquel Raynal "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch b/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch new file mode 100644 index 0000000000..f20db85ceb --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch @@ -0,0 +1,24 @@ +From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:47 +0100 +Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias + +The MODULE_ALIAS macro is misused here as it carries the +description. There is currently no relevant alias to provide so let's +just drop it. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/onie-tlv.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Miquel Raynal "); + MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); +-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch b/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch new file mode 100644 index 0000000000..5cf847b57a --- /dev/null +++ b/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch @@ -0,0 +1,31 @@ +From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001 +From: Tom Rix +Date: Tue, 4 Apr 2023 18:21:48 +0100 +Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout + storage-class-specifier to static + +smatch reports +drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol + 'sl28vpd_layout' was not declared. Should it be static? + +This variable is only used in one file so it should be static. + +Signed-off-by: Tom Rix +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts/sl28vpd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd + }; + MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); + +-struct nvmem_layout sl28vpd_layout = { ++static struct nvmem_layout sl28vpd_layout = { + .name = "sl28-vpd", + .of_match_table = sl28vpd_of_match_table, + .add_cells = sl28vpd_add_cells, diff --git a/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch b/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch new file mode 100644 index 0000000000..13ee2d4229 --- /dev/null +++ b/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch @@ -0,0 +1,100 @@ +From a5be5ce0e25439fae3cd42e3d775979547926812 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 3 Nov 2022 09:25:29 +0100 +Subject: [PATCH] firmware/nvram: bcm47xx: support init from IO memory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide NVMEM content to the NVRAM driver from a simple +memory resource. This is necessary to use NVRAM in a memory- +mapped flash device. Patch taken from OpenWrts development +tree. + +This patch makes it possible to use memory-mapped NVRAM +on the D-Link DWL-8610AP and the D-Link DIR-890L. + +Cc: Hauke Mehrtens +Cc: linux-mips@vger.kernel.org +Cc: Florian Fainelli +Cc: bcm-kernel-feedback-list@broadcom.com +Cc: Thomas Bogendoerfer +Signed-off-by: Rafał Miłecki +[Added an export for modules potentially using the init symbol] +Signed-off-by: Linus Walleij +Link: https://lore.kernel.org/r/20221103082529.359084-1-linus.walleij@linaro.org +Signed-off-by: Florian Fainelli +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 18 ++++++++++++++++++ + drivers/nvmem/brcm_nvram.c | 3 +++ + include/linux/bcm47xx_nvram.h | 6 ++++++ + 3 files changed, 27 insertions(+) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -110,6 +110,24 @@ found: + return 0; + } + ++int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size) ++{ ++ if (nvram_len) { ++ pr_warn("nvram already initialized\n"); ++ return -EEXIST; ++ } ++ ++ if (!bcm47xx_nvram_is_valid(nvram_start)) { ++ pr_err("No valid NVRAM found\n"); ++ return -ENOENT; ++ } ++ ++ bcm47xx_nvram_copy(nvram_start, res_size); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(bcm47xx_nvram_init_from_iomem); ++ + /* + * On bcm47xx we need access to the NVRAM very early, so we can't use mtd + * subsystem to access flash. We can't even use platform device / driver to +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -3,6 +3,7 @@ + * Copyright (C) 2021 Rafał Miłecki + */ + ++#include + #include + #include + #include +@@ -139,6 +140,8 @@ static int brcm_nvram_probe(struct platf + if (err) + return err; + ++ bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); ++ + config.dev = dev; + config.cells = priv->cells; + config.ncells = priv->ncells; +--- a/include/linux/bcm47xx_nvram.h ++++ b/include/linux/bcm47xx_nvram.h +@@ -11,6 +11,7 @@ + #include + + #ifdef CONFIG_BCM47XX_NVRAM ++int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size); + int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); + int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); + int bcm47xx_nvram_gpio_pin(const char *name); +@@ -20,6 +21,11 @@ static inline void bcm47xx_nvram_release + vfree(nvram); + }; + #else ++static inline int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, ++ size_t res_size) ++{ ++ return -ENOTSUPP; ++} + static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) + { + return -ENOTSUPP; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch b/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch new file mode 100644 index 0000000000..38cfccd5ef --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch @@ -0,0 +1,31 @@ +From eebc6573ad940b62a87776db3917e912b4f52d78 Mon Sep 17 00:00:00 2001 +From: Tom Rix +Date: Sun, 11 Jun 2023 15:03:05 +0100 +Subject: [PATCH] nvmem: imx-ocotp: set varaiable imx_ocotp_layout + storage-class-specifier to static + +smatch reports +drivers/nvmem/imx-ocotp.c:599:21: warning: symbol + 'imx_ocotp_layout' was not declared. Should it be static? + +This variable is only used in one file so should be static. + +Signed-off-by: Tom Rix +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-2-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/imx-ocotp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -596,7 +596,7 @@ static void imx_ocotp_fixup_cell_info(st + cell->read_post_process = imx_ocotp_cell_pp; + } + +-struct nvmem_layout imx_ocotp_layout = { ++static struct nvmem_layout imx_ocotp_layout = { + .fixup_cell_info = imx_ocotp_fixup_cell_info, + }; + diff --git a/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch b/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch new file mode 100644 index 0000000000..7523e5ebf6 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch @@ -0,0 +1,71 @@ +From 8a00fc606312c68b98add8fe8e6f7a013ce29e78 Mon Sep 17 00:00:00 2001 +From: Alexander Stein +Date: Sun, 11 Jun 2023 15:03:06 +0100 +Subject: [PATCH] nvmem: imx-ocotp: Reverse MAC addresses on all i.MX derivates + +Not just i.MX8M, but all i.MX6/7 (and subtypes) need to reverse the +MAC address read from fuses. Exceptions are i.MX6SLL and i.MX7ULP which +do not support ethernet at all. + +Fixes: d0221a780cbc ("nvmem: imx-ocotp: add support for post processing") +Signed-off-by: Alexander Stein +Tested-by: Richard Leitner # imx6q +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-3-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/imx-ocotp.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -97,7 +97,6 @@ struct ocotp_params { + unsigned int bank_address_words; + void (*set_timing)(struct ocotp_priv *priv); + struct ocotp_ctrl_reg ctrl; +- bool reverse_mac_address; + }; + + static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags) +@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_ + .bank_address_words = 0, + .set_timing = imx_ocotp_set_imx6_timing, + .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, +- .reverse_mac_address = true, + }; + + static const struct ocotp_params imx8mm_params = { +@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_ + .bank_address_words = 0, + .set_timing = imx_ocotp_set_imx6_timing, + .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, +- .reverse_mac_address = true, + }; + + static const struct ocotp_params imx8mn_params = { +@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_ + .bank_address_words = 0, + .set_timing = imx_ocotp_set_imx6_timing, + .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, +- .reverse_mac_address = true, + }; + + static const struct ocotp_params imx8mp_params = { +@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_ + .bank_address_words = 0, + .set_timing = imx_ocotp_set_imx6_timing, + .ctrl = IMX_OCOTP_BM_CTRL_8MP, +- .reverse_mac_address = true, + }; + + static const struct of_device_id imx_ocotp_dt_ids[] = { +@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platfo + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; +- if (priv->params->reverse_mac_address) +- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; ++ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; + + priv->config = &imx_ocotp_nvmem_config; + diff --git a/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch b/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch new file mode 100644 index 0000000000..fb4d346a95 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch @@ -0,0 +1,81 @@ +From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sun, 11 Jun 2023 15:03:08 +0100 +Subject: [PATCH] nvmem: brcm_nvram: add .read_post_process() for MACs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Parse ASCII MAC format into byte based +2. Calculate relative addresses based on index argument + +Signed-off-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-5-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + drivers/nvmem/brcm_nvram.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM + tristate "Broadcom's NVRAM support" + depends on ARCH_BCM_5301X || COMPILE_TEST + depends on HAS_IOMEM ++ select GENERIC_NET_UTILS + help + This driver provides support for Broadcom's NVRAM that can be accessed + using I/O mapping. +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -4,6 +4,8 @@ + */ + + #include ++#include ++#include + #include + #include + #include +@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context + return 0; + } + ++static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index, ++ unsigned int offset, void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (bytes != 3 * ETH_ALEN - 1) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ + static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data, + size_t len) + { +@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct b + priv->cells[idx].offset = value - (char *)data; + priv->cells[idx].bytes = strlen(value); + priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ if (!strcmp(var, "et0macaddr") || ++ !strcmp(var, "et1macaddr") || ++ !strcmp(var, "et2macaddr")) { ++ priv->cells[idx].raw_len = strlen(value); ++ priv->cells[idx].bytes = ETH_ALEN; ++ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; ++ } + } + + return 0; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch b/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch new file mode 100644 index 0000000000..3b6e6e57f5 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch @@ -0,0 +1,166 @@ +From 8dc61364164e79e44c07fa2ac0a7b6939f00d5db Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sun, 11 Jun 2023 15:03:13 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data + +In preparation to support new Rockchip OTP memory devices with different +clock configurations and register layout, extend rockchip_data struct +with the related members: clks, num_clks, reg_read. + +Additionally, to avoid managing redundant driver data, drop num_clks +member from rockchip_otp struct and update all references to point to +the equivalent member in rockchip_data. + +Signed-off-by: Cristian Ciocaltea +Tested-by: Vincent Legoll +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-10-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 79 ++++++++++++++++++++++-------------- + 1 file changed, 49 insertions(+), 30 deletions(-) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -54,21 +54,19 @@ + + #define OTPC_TIMEOUT 10000 + ++struct rockchip_data { ++ int size; ++ const char * const *clks; ++ int num_clks; ++ nvmem_reg_read_t reg_read; ++}; ++ + struct rockchip_otp { + struct device *dev; + void __iomem *base; +- struct clk_bulk_data *clks; +- int num_clks; ++ struct clk_bulk_data *clks; + struct reset_control *rst; +-}; +- +-/* list of required clocks */ +-static const char * const rockchip_otp_clocks[] = { +- "otp", "apb_pclk", "phy", +-}; +- +-struct rockchip_data { +- int size; ++ const struct rockchip_data *data; + }; + + static int rockchip_otp_reset(struct rockchip_otp *otp) +@@ -132,29 +130,23 @@ static int rockchip_otp_ecc_enable(struc + return ret; + } + +-static int rockchip_otp_read(void *context, unsigned int offset, +- void *val, size_t bytes) ++static int px30_otp_read(void *context, unsigned int offset, ++ void *val, size_t bytes) + { + struct rockchip_otp *otp = context; + u8 *buf = val; +- int ret = 0; +- +- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks); +- if (ret < 0) { +- dev_err(otp->dev, "failed to prepare/enable clks\n"); +- return ret; +- } ++ int ret; + + ret = rockchip_otp_reset(otp); + if (ret) { + dev_err(otp->dev, "failed to reset otp phy\n"); +- goto disable_clks; ++ return ret; + } + + ret = rockchip_otp_ecc_enable(otp, false); + if (ret < 0) { + dev_err(otp->dev, "rockchip_otp_ecc_enable err\n"); +- goto disable_clks; ++ return ret; + } + + writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); +@@ -174,8 +166,28 @@ static int rockchip_otp_read(void *conte + + read_end: + writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); +-disable_clks: +- clk_bulk_disable_unprepare(otp->num_clks, otp->clks); ++ ++ return ret; ++} ++ ++static int rockchip_otp_read(void *context, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ struct rockchip_otp *otp = context; ++ int ret; ++ ++ if (!otp->data || !otp->data->reg_read) ++ return -EINVAL; ++ ++ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks); ++ if (ret < 0) { ++ dev_err(otp->dev, "failed to prepare/enable clks\n"); ++ return ret; ++ } ++ ++ ret = otp->data->reg_read(context, offset, val, bytes); ++ ++ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks); + + return ret; + } +@@ -189,8 +201,15 @@ static struct nvmem_config otp_config = + .reg_read = rockchip_otp_read, + }; + ++static const char * const px30_otp_clocks[] = { ++ "otp", "apb_pclk", "phy", ++}; ++ + static const struct rockchip_data px30_data = { + .size = 0x40, ++ .clks = px30_otp_clocks, ++ .num_clks = ARRAY_SIZE(px30_otp_clocks), ++ .reg_read = px30_otp_read, + }; + + static const struct of_device_id rockchip_otp_match[] = { +@@ -225,21 +244,21 @@ static int rockchip_otp_probe(struct pla + if (!otp) + return -ENOMEM; + ++ otp->data = data; + otp->dev = dev; + otp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(otp->base)) + return PTR_ERR(otp->base); + +- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks); +- otp->clks = devm_kcalloc(dev, otp->num_clks, +- sizeof(*otp->clks), GFP_KERNEL); ++ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), ++ GFP_KERNEL); + if (!otp->clks) + return -ENOMEM; + +- for (i = 0; i < otp->num_clks; ++i) +- otp->clks[i].id = rockchip_otp_clocks[i]; ++ for (i = 0; i < data->num_clks; ++i) ++ otp->clks[i].id = data->clks[i]; + +- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks); ++ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); + if (ret) + return ret; + diff --git a/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch b/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch new file mode 100644 index 0000000000..b5b66cfc5a --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch @@ -0,0 +1,62 @@ +From 30fd21cfb1e64ef20035559a8246f5fbf682c40e Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sun, 11 Jun 2023 15:03:14 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Generalize rockchip_otp_wait_status() + +In preparation to support additional Rockchip OTP memory devices with +different register layout, generalize rockchip_otp_wait_status() to +accept a new parameter for specifying the offset of the status register. + +Signed-off-by: Cristian Ciocaltea +Tested-by: Vincent Legoll +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-11-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -90,18 +90,19 @@ static int rockchip_otp_reset(struct roc + return 0; + } + +-static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag) ++static int rockchip_otp_wait_status(struct rockchip_otp *otp, ++ unsigned int reg, u32 flag) + { + u32 status = 0; + int ret; + +- ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status, ++ ret = readl_poll_timeout_atomic(otp->base + reg, status, + (status & flag), 1, OTPC_TIMEOUT); + if (ret) + return ret; + + /* clean int status */ +- writel(flag, otp->base + OTPC_INT_STATUS); ++ writel(flag, otp->base + reg); + + return 0; + } +@@ -123,7 +124,7 @@ static int rockchip_otp_ecc_enable(struc + + writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); + +- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); ++ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE); + if (ret < 0) + dev_err(otp->dev, "timeout during ecc_enable\n"); + +@@ -156,7 +157,7 @@ static int px30_otp_read(void *context, + otp->base + OTPC_USER_ADDR); + writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, + otp->base + OTPC_USER_ENABLE); +- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); ++ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE); + if (ret < 0) { + dev_err(otp->dev, "timeout during read setup\n"); + goto read_end; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch b/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch new file mode 100644 index 0000000000..3a17479d95 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch @@ -0,0 +1,31 @@ +From d325c9dd2b6e94040ca722ddcadcd6af358dd2be Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sun, 11 Jun 2023 15:03:15 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Use + devm_reset_control_array_get_exclusive() + +In preparation to support new Rockchip OTP memory devices having +specific reset configurations, switch devm_reset_control_get() to +devm_reset_control_array_get_exclusive(). + +Signed-off-by: Cristian Ciocaltea +Tested-by: Vincent Legoll +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-12-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -263,7 +263,7 @@ static int rockchip_otp_probe(struct pla + if (ret) + return ret; + +- otp->rst = devm_reset_control_get(dev, "phy"); ++ otp->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(otp->rst)) + return PTR_ERR(otp->rst); + diff --git a/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch b/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch new file mode 100644 index 0000000000..37cb927b10 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch @@ -0,0 +1,71 @@ +From 912517345b867a69542dc9f5c2cc3e9d8beaccf5 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sun, 11 Jun 2023 15:03:16 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Improve probe error handling + +Enhance error handling in the probe function by making use of +dev_err_probe(), which ensures the error code is always printed, in +addition to the specified error message. + +Signed-off-by: Cristian Ciocaltea +Tested-by: Vincent Legoll +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-13-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -235,10 +235,8 @@ static int rockchip_otp_probe(struct pla + int ret, i; + + data = of_device_get_match_data(dev); +- if (!data) { +- dev_err(dev, "failed to get match data\n"); +- return -EINVAL; +- } ++ if (!data) ++ return dev_err_probe(dev, -EINVAL, "failed to get match data\n"); + + otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), + GFP_KERNEL); +@@ -249,7 +247,8 @@ static int rockchip_otp_probe(struct pla + otp->dev = dev; + otp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(otp->base)) +- return PTR_ERR(otp->base); ++ return dev_err_probe(dev, PTR_ERR(otp->base), ++ "failed to ioremap resource\n"); + + otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), + GFP_KERNEL); +@@ -261,18 +260,22 @@ static int rockchip_otp_probe(struct pla + + ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); + if (ret) +- return ret; ++ return dev_err_probe(dev, ret, "failed to get clocks\n"); + + otp->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(otp->rst)) +- return PTR_ERR(otp->rst); ++ return dev_err_probe(dev, PTR_ERR(otp->rst), ++ "failed to get resets\n"); + + otp_config.size = data->size; + otp_config.priv = otp; + otp_config.dev = dev; +- nvmem = devm_nvmem_register(dev, &otp_config); + +- return PTR_ERR_OR_ZERO(nvmem); ++ nvmem = devm_nvmem_register(dev, &otp_config); ++ if (IS_ERR(nvmem)) ++ return dev_err_probe(dev, PTR_ERR(nvmem), ++ "failed to register nvmem device\n"); ++ return 0; + } + + static struct platform_driver rockchip_otp_driver = { diff --git a/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch b/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch new file mode 100644 index 0000000000..c1e2231c9e --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch @@ -0,0 +1,129 @@ +From 8ab099fafbbc8c9607c399d21a774784a6cb8b45 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sun, 11 Jun 2023 15:03:17 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3588 + +Add support for the OTP memory device found on the Rockchip RK3588 SoC. + +While here, remove the unnecessary 'void *' casts in the OF device ID +table. + +Co-developed-by: Finley Xiao +Signed-off-by: Finley Xiao +Signed-off-by: Cristian Ciocaltea +Tested-by: Vincent Legoll +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-14-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 78 +++++++++++++++++++++++++++++++++++- + 1 file changed, 76 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -54,6 +54,19 @@ + + #define OTPC_TIMEOUT 10000 + ++/* RK3588 Register */ ++#define RK3588_OTPC_AUTO_CTRL 0x04 ++#define RK3588_OTPC_AUTO_EN 0x08 ++#define RK3588_OTPC_INT_ST 0x84 ++#define RK3588_OTPC_DOUT0 0x20 ++#define RK3588_NO_SECURE_OFFSET 0x300 ++#define RK3588_NBYTES 4 ++#define RK3588_BURST_NUM 1 ++#define RK3588_BURST_SHIFT 8 ++#define RK3588_ADDR_SHIFT 16 ++#define RK3588_AUTO_EN BIT(0) ++#define RK3588_RD_DONE BIT(1) ++ + struct rockchip_data { + int size; + const char * const *clks; +@@ -171,6 +184,52 @@ read_end: + return ret; + } + ++static int rk3588_otp_read(void *context, unsigned int offset, ++ void *val, size_t bytes) ++{ ++ struct rockchip_otp *otp = context; ++ unsigned int addr_start, addr_end, addr_len; ++ int ret, i = 0; ++ u32 data; ++ u8 *buf; ++ ++ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; ++ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; ++ addr_len = addr_end - addr_start; ++ addr_start += RK3588_NO_SECURE_OFFSET; ++ ++ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ while (addr_len--) { ++ writel((addr_start << RK3588_ADDR_SHIFT) | ++ (RK3588_BURST_NUM << RK3588_BURST_SHIFT), ++ otp->base + RK3588_OTPC_AUTO_CTRL); ++ writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); ++ ++ ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST, ++ RK3588_RD_DONE); ++ if (ret < 0) { ++ dev_err(otp->dev, "timeout during read setup\n"); ++ goto read_end; ++ } ++ ++ data = readl(otp->base + RK3588_OTPC_DOUT0); ++ memcpy(&buf[i], &data, RK3588_NBYTES); ++ ++ i += RK3588_NBYTES; ++ addr_start++; ++ } ++ ++ memcpy(val, buf + offset % RK3588_NBYTES, bytes); ++ ++read_end: ++ kfree(buf); ++ ++ return ret; ++} ++ + static int rockchip_otp_read(void *context, unsigned int offset, + void *val, size_t bytes) + { +@@ -213,14 +272,29 @@ static const struct rockchip_data px30_d + .reg_read = px30_otp_read, + }; + ++static const char * const rk3588_otp_clocks[] = { ++ "otp", "apb_pclk", "phy", "arb", ++}; ++ ++static const struct rockchip_data rk3588_data = { ++ .size = 0x400, ++ .clks = rk3588_otp_clocks, ++ .num_clks = ARRAY_SIZE(rk3588_otp_clocks), ++ .reg_read = rk3588_otp_read, ++}; ++ + static const struct of_device_id rockchip_otp_match[] = { + { + .compatible = "rockchip,px30-otp", +- .data = (void *)&px30_data, ++ .data = &px30_data, + }, + { + .compatible = "rockchip,rk3308-otp", +- .data = (void *)&px30_data, ++ .data = &px30_data, ++ }, ++ { ++ .compatible = "rockchip,rk3588-otp", ++ .data = &rk3588_data, + }, + { /* sentinel */ }, + }; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch b/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch new file mode 100644 index 0000000000..220e3e9a05 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch @@ -0,0 +1,26 @@ +From 9734408969e978a1c0d5d752be63dd638288e374 Mon Sep 17 00:00:00 2001 +From: Michal Simek +Date: Sun, 11 Jun 2023 15:03:23 +0100 +Subject: [PATCH] nvmem: zynqmp: Switch @xilinx.com emails to @amd.com + +@xilinx.com is still working but better to switch to new amd.com after +AMD/Xilinx acquisition. + +Signed-off-by: Michal Simek +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-20-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvm + + module_platform_driver(zynqmp_nvmem_driver); + +-MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); ++MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); + MODULE_DESCRIPTION("ZynqMP NVMEM driver"); + MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch b/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch new file mode 100644 index 0000000000..f8e6be4241 --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch @@ -0,0 +1,230 @@ +From 22e9e6fcfb5042cb6d6c7874c459b034800092f1 Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Sun, 11 Jun 2023 15:03:25 +0100 +Subject: [PATCH] nvmem: imx: support i.MX93 OCOTP + +Add i.MX93 OCOTP support. i.MX93 OCOTP has two parts: Fuse shadow +block(fsb) and fuse managed by ELE. The FSB part could be directly +accessed with MMIO, the ELE could only be accessed with ELE API. + +Currently the ELE API is not ready, so NULL function callback is used, +but it was tested with downstream ELE API. + +Signed-off-by: Peng Fan +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-22-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 9 ++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/imx-ocotp-ele.c | 175 ++++++++++++++++++++++++++++++++++ + 3 files changed, 186 insertions(+) + create mode 100644 drivers/nvmem/imx-ocotp-ele.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -83,6 +83,15 @@ config NVMEM_IMX_OCOTP + This driver can also be built as a module. If so, the module + will be called nvmem-imx-ocotp. + ++config NVMEM_IMX_OCOTP_ELE ++ tristate "i.MX On-Chip OTP Controller support" ++ depends on ARCH_MXC || COMPILE_TEST ++ depends on HAS_IOMEM ++ depends on OF ++ help ++ This is a driver for the On-Chip OTP Controller (OCOTP) ++ available on i.MX SoCs which has ELE. ++ + config NVMEM_IMX_OCOTP_SCU + tristate "i.MX8 SCU On-Chip OTP Controller support" + depends on IMX_SCU +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-im + nvmem-imx-iim-y := imx-iim.o + obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o + nvmem-imx-ocotp-y := imx-ocotp.o ++obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o ++nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o + obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o + nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o + obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o +--- /dev/null ++++ b/drivers/nvmem/imx-ocotp-ele.c +@@ -0,0 +1,175 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * i.MX9 OCOTP fusebox driver ++ * ++ * Copyright 2023 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum fuse_type { ++ FUSE_FSB = 1, ++ FUSE_ELE = 2, ++ FUSE_INVALID = -1 ++}; ++ ++struct ocotp_map_entry { ++ u32 start; /* start word */ ++ u32 num; /* num words */ ++ enum fuse_type type; ++}; ++ ++struct ocotp_devtype_data { ++ u32 reg_off; ++ char *name; ++ u32 size; ++ u32 num_entry; ++ u32 flag; ++ nvmem_reg_read_t reg_read; ++ struct ocotp_map_entry entry[]; ++}; ++ ++struct imx_ocotp_priv { ++ struct device *dev; ++ void __iomem *base; ++ struct nvmem_config config; ++ struct mutex lock; ++ const struct ocotp_devtype_data *data; ++}; ++ ++static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index) ++{ ++ struct imx_ocotp_priv *priv = context; ++ const struct ocotp_devtype_data *data = priv->data; ++ u32 start, end; ++ int i; ++ ++ for (i = 0; i < data->num_entry; i++) { ++ start = data->entry[i].start; ++ end = data->entry[i].start + data->entry[i].num; ++ ++ if (index >= start && index < end) ++ return data->entry[i].type; ++ } ++ ++ return FUSE_INVALID; ++} ++ ++static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes) ++{ ++ struct imx_ocotp_priv *priv = context; ++ void __iomem *reg = priv->base + priv->data->reg_off; ++ u32 count, index, num_bytes; ++ enum fuse_type type; ++ u32 *buf; ++ void *p; ++ int i; ++ ++ index = offset; ++ num_bytes = round_up(bytes, 4); ++ count = num_bytes >> 2; ++ ++ if (count > ((priv->data->size >> 2) - index)) ++ count = (priv->data->size >> 2) - index; ++ ++ p = kzalloc(num_bytes, GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ mutex_lock(&priv->lock); ++ ++ buf = p; ++ ++ for (i = index; i < (index + count); i++) { ++ type = imx_ocotp_fuse_type(context, i); ++ if (type == FUSE_INVALID || type == FUSE_ELE) { ++ *buf++ = 0; ++ continue; ++ } ++ ++ *buf++ = readl_relaxed(reg + (i << 2)); ++ } ++ ++ memcpy(val, (u8 *)p, bytes); ++ ++ mutex_unlock(&priv->lock); ++ ++ kfree(p); ++ ++ return 0; ++}; ++ ++static int imx_ele_ocotp_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct imx_ocotp_priv *priv; ++ struct nvmem_device *nvmem; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->data = of_device_get_match_data(dev); ++ ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ priv->config.dev = dev; ++ priv->config.name = "ELE-OCOTP"; ++ priv->config.id = NVMEM_DEVID_AUTO; ++ priv->config.owner = THIS_MODULE; ++ priv->config.size = priv->data->size; ++ priv->config.reg_read = priv->data->reg_read; ++ priv->config.word_size = 4; ++ priv->config.stride = 1; ++ priv->config.priv = priv; ++ priv->config.read_only = true; ++ mutex_init(&priv->lock); ++ ++ nvmem = devm_nvmem_register(dev, &priv->config); ++ if (IS_ERR(nvmem)) ++ return PTR_ERR(nvmem); ++ ++ return 0; ++} ++ ++static const struct ocotp_devtype_data imx93_ocotp_data = { ++ .reg_off = 0x8000, ++ .reg_read = imx_ocotp_reg_read, ++ .size = 2048, ++ .num_entry = 6, ++ .entry = { ++ { 0, 52, FUSE_FSB }, ++ { 63, 1, FUSE_ELE}, ++ { 128, 16, FUSE_ELE }, ++ { 182, 1, FUSE_ELE }, ++ { 188, 1, FUSE_ELE }, ++ { 312, 200, FUSE_FSB } ++ }, ++}; ++ ++static const struct of_device_id imx_ele_ocotp_dt_ids[] = { ++ { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); ++ ++static struct platform_driver imx_ele_ocotp_driver = { ++ .driver = { ++ .name = "imx_ele_ocotp", ++ .of_match_table = imx_ele_ocotp_dt_ids, ++ }, ++ .probe = imx_ele_ocotp_probe, ++}; ++module_platform_driver(imx_ele_ocotp_driver); ++ ++MODULE_DESCRIPTION("i.MX OCOTP/ELE driver"); ++MODULE_AUTHOR("Peng Fan "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch b/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch new file mode 100644 index 0000000000..59b2f9fa2c --- /dev/null +++ b/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch @@ -0,0 +1,96 @@ +From 27f699e578b1a72df89dfa3bc42e093a01dc8d10 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sun, 11 Jun 2023 15:03:29 +0100 +Subject: [PATCH] nvmem: core: add support for fixed cells *layout* +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds support for the "fixed-layout" NVMEM layout binding. It allows +defining NVMEM cells in a layout DT node named "nvmem-layout". + +While NVMEM subsystem supports layout drivers it has been discussed that +"fixed-layout" may actually be supperted internally. It's because: +1. It's a very basic layout +2. It allows sharing code with legacy syntax parsing +3. It's safer for soc_device_match() due to -EPROBE_DEFER +4. This will make the syntax transition easier + +Signed-off-by: Rafał Miłecki +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +Message-ID: <20230611140330.154222-26-srinivas.kandagatla@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struc + return 0; + } + +-static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) ++static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) + { + struct nvmem_layout *layout = nvmem->layout; + struct device *dev = &nvmem->dev; +@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struc + const __be32 *addr; + int len, ret; + +- for_each_child_of_node(dev->of_node, child) { ++ for_each_child_of_node(np, child) { + struct nvmem_cell_info info = {0}; + + addr = of_get_property(child, "reg", &len); +@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struc + return 0; + } + ++static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem) ++{ ++ return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node); ++} ++ ++static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem) ++{ ++ struct device_node *layout_np; ++ int err = 0; ++ ++ layout_np = of_nvmem_layout_get_container(nvmem); ++ if (!layout_np) ++ return 0; ++ ++ if (of_device_is_compatible(layout_np, "fixed-layout")) ++ err = nvmem_add_cells_from_dt(nvmem, layout_np); ++ ++ of_node_put(layout_np); ++ ++ return err; ++} ++ + int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) + { + layout->owner = owner; +@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_of(nvmem); ++ rval = nvmem_add_cells_from_legacy_of(nvmem); + if (rval) + goto err_remove_cells; + +@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + ++ rval = nvmem_add_cells_from_fixed_layout(nvmem); ++ if (rval) ++ goto err_remove_cells; ++ + rval = nvmem_add_cells_from_layout(nvmem); + if (rval) + goto err_remove_cells; diff --git a/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch new file mode 100644 index 0000000000..bf7a816bb2 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch @@ -0,0 +1,36 @@ +From 9ccfcbeb8f32ff89e99b36cb9cdebaa0d1b44ed1 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:24 +0100 +Subject: [PATCH] nvmem: sunxi_sid: Convert to devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Acked-by: Jernej Skrabec +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/sunxi_sid.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/sunxi_sid.c ++++ b/drivers/nvmem/sunxi_sid.c +@@ -125,7 +125,6 @@ static int sun8i_sid_read_by_reg(void *c + static int sunxi_sid_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *res; + struct nvmem_config *nvmem_cfg; + struct nvmem_device *nvmem; + struct sunxi_sid *sid; +@@ -142,8 +141,7 @@ static int sunxi_sid_probe(struct platfo + return -EINVAL; + sid->value_offset = cfg->value_offset; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- sid->base = devm_ioremap_resource(dev, res); ++ sid->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sid->base)) + return PTR_ERR(sid->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch new file mode 100644 index 0000000000..f142d735de --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch @@ -0,0 +1,30 @@ +From cfadd0e7d9225566f320bc4dc716682be910be6c Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:25 +0100 +Subject: [PATCH] nvmem: brcm_nvram: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/brcm_nvram.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -159,8 +159,7 @@ static int brcm_nvram_probe(struct platf + return -ENOMEM; + priv->dev = dev; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch new file mode 100644 index 0000000000..0395bbf8bc --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch @@ -0,0 +1,34 @@ +From 0b49178e2b6b4aac3c7fa3ce8d8c02208a13b988 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:26 +0100 +Subject: [PATCH] nvmem: lpc18xx_otp: Convert to + devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/lpc18xx_otp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/lpc18xx_otp.c ++++ b/drivers/nvmem/lpc18xx_otp.c +@@ -68,14 +68,12 @@ static int lpc18xx_otp_probe(struct plat + { + struct nvmem_device *nvmem; + struct lpc18xx_otp *otp; +- struct resource *res; + + otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL); + if (!otp) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- otp->base = devm_ioremap_resource(&pdev->dev, res); ++ otp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(otp->base)) + return PTR_ERR(otp->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch b/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch new file mode 100644 index 0000000000..da077eb4b7 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch @@ -0,0 +1,36 @@ +From 0a223a097709b99a0ba738d6be5b4f52c04ffb64 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:27 +0100 +Subject: [PATCH] nvmem: meson-mx-efuse: Convert to + devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/meson-mx-efuse.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/meson-mx-efuse.c ++++ b/drivers/nvmem/meson-mx-efuse.c +@@ -194,7 +194,6 @@ static int meson_mx_efuse_probe(struct p + { + const struct meson_mx_efuse_platform_data *drvdata; + struct meson_mx_efuse *efuse; +- struct resource *res; + + drvdata = of_device_get_match_data(&pdev->dev); + if (!drvdata) +@@ -204,8 +203,7 @@ static int meson_mx_efuse_probe(struct p + if (!efuse) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- efuse->base = devm_ioremap_resource(&pdev->dev, res); ++ efuse->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(efuse->base)) + return PTR_ERR(efuse->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch b/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch new file mode 100644 index 0000000000..dc144ddfbd --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch @@ -0,0 +1,31 @@ +From 94904db28db49ac8fbb2a273d25156db26a3a985 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:28 +0100 +Subject: [PATCH] nvmem: rockchip-efuse: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-efuse.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -267,8 +267,7 @@ static int rockchip_efuse_probe(struct p + if (!efuse) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- efuse->base = devm_ioremap_resource(dev, res); ++ efuse->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(efuse->base)) + return PTR_ERR(efuse->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch new file mode 100644 index 0000000000..99e20939cc --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch @@ -0,0 +1,30 @@ +From 0a4a8c0d238fec1fa4b85591524ef42ad261cb97 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:29 +0100 +Subject: [PATCH] nvmem: stm32-romem: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -196,8 +196,7 @@ static int stm32_romem_probe(struct plat + if (!priv) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch b/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch new file mode 100644 index 0000000000..6d93752e27 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch @@ -0,0 +1,59 @@ +From 0bc0d6dc2a9a05ae6729b4622f09782d9f230815 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:30 +0100 +Subject: [PATCH] nvmem: qfprom: do some cleanup + +Use devm_platform_ioremap_resource() and +devm_platform_get_and_ioremap_resource() to simplify code. +BTW convert to use dev_err_probe() instead of open it. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -374,8 +374,7 @@ static int qfprom_probe(struct platform_ + return -ENOMEM; + + /* The corrected section is always provided */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->qfpcorrected = devm_ioremap_resource(dev, res); ++ priv->qfpcorrected = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->qfpcorrected)) + return PTR_ERR(priv->qfpcorrected); + +@@ -402,12 +401,10 @@ static int qfprom_probe(struct platform_ + priv->qfpraw = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->qfpraw)) + return PTR_ERR(priv->qfpraw); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 2); +- priv->qfpconf = devm_ioremap_resource(dev, res); ++ priv->qfpconf = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(priv->qfpconf)) + return PTR_ERR(priv->qfpconf); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 3); +- priv->qfpsecurity = devm_ioremap_resource(dev, res); ++ priv->qfpsecurity = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(priv->qfpsecurity)) + return PTR_ERR(priv->qfpsecurity); + +@@ -427,12 +424,8 @@ static int qfprom_probe(struct platform_ + return PTR_ERR(priv->vcc); + + priv->secclk = devm_clk_get(dev, "core"); +- if (IS_ERR(priv->secclk)) { +- ret = PTR_ERR(priv->secclk); +- if (ret != -EPROBE_DEFER) +- dev_err(dev, "Error getting clock: %d\n", ret); +- return ret; +- } ++ if (IS_ERR(priv->secclk)) ++ return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); + + /* Only enable writing if we have SoC data. */ + if (priv->soc_data) diff --git a/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch new file mode 100644 index 0000000000..3e328a4c99 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch @@ -0,0 +1,29 @@ +From 6ac41c556e22a0d7d267c9b9d48681d73af4b368 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:31 +0100 +Subject: [PATCH] nvmem: uniphier: Use devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/uniphier-efuse.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/uniphier-efuse.c ++++ b/drivers/nvmem/uniphier-efuse.c +@@ -41,8 +41,7 @@ static int uniphier_efuse_probe(struct p + if (!priv) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch new file mode 100644 index 0000000000..acbe18e270 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch @@ -0,0 +1,133 @@ +From c8efcf7a86ebf2ff48584d270b3070a7075bc345 Mon Sep 17 00:00:00 2001 +From: Richard Alpe +Date: Mon, 10 Apr 2023 10:20:51 +0200 +Subject: [PATCH] nvmem: add new NXP QorIQ eFuse driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add SFP (Security Fuse Processor) read support for NXP (Freescale) +QorIQ series SOC's. + +This patch adds support for the T1023 SOC using the SFP offset from +the existing T1023 device tree. In theory this should also work for +T1024, T1014 and T1013 which uses the same SFP base offset. + +Signed-off-by: Richard Alpe +Reviewed-by: Niklas Söderlund +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 12 ++++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/qoriq-efuse.c | 78 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 92 insertions(+) + create mode 100644 drivers/nvmem/qoriq-efuse.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -392,4 +392,16 @@ config NVMEM_ZYNQMP + + If sure, say yes. If unsure, say no. + ++config NVMEM_QORIQ_EFUSE ++ tristate "NXP QorIQ eFuse support" ++ depends on PPC_85xx || COMPILE_TEST ++ depends on HAS_IOMEM ++ help ++ This driver provides read support for the eFuses (SFP) on NXP QorIQ ++ series SoC's. This includes secure boot settings, the globally unique ++ NXP ID 'FUIDR' and the OEM unique ID 'OUIDR'. ++ ++ This driver can also be built as a module. If so, the module ++ will be called nvmem_qoriq_efuse. ++ + endif +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -77,3 +77,5 @@ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvme + nvmem-vf610-ocotp-y := vf610-ocotp.o + obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o + nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o ++obj-$(CONFIG_NVMEM_QORIQ_EFUSE) += nvmem-qoriq-efuse.o ++nvmem-qoriq-efuse-y := qoriq-efuse.o +--- /dev/null ++++ b/drivers/nvmem/qoriq-efuse.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2023 Westermo Network Technologies AB ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct qoriq_efuse_priv { ++ void __iomem *base; ++}; ++ ++static int qoriq_efuse_read(void *context, unsigned int offset, void *val, ++ size_t bytes) ++{ ++ struct qoriq_efuse_priv *priv = context; ++ ++ /* .stride = 4 so offset is guaranteed to be aligned */ ++ __ioread32_copy(val, priv->base + offset, bytes / 4); ++ ++ /* Ignore trailing bytes (there shouldn't be any) */ ++ ++ return 0; ++} ++ ++static int qoriq_efuse_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config config = { ++ .dev = &pdev->dev, ++ .read_only = true, ++ .reg_read = qoriq_efuse_read, ++ .stride = sizeof(u32), ++ .word_size = sizeof(u32), ++ .name = "qoriq_efuse_read", ++ .id = NVMEM_DEVID_AUTO, ++ .root_only = true, ++ }; ++ struct qoriq_efuse_priv *priv; ++ struct nvmem_device *nvmem; ++ struct resource *res; ++ ++ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ config.size = resource_size(res); ++ config.priv = priv; ++ nvmem = devm_nvmem_register(config.dev, &config); ++ ++ return PTR_ERR_OR_ZERO(nvmem); ++} ++ ++static const struct of_device_id qoriq_efuse_of_match[] = { ++ { .compatible = "fsl,t1023-sfp", }, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, qoriq_efuse_of_match); ++ ++static struct platform_driver qoriq_efuse_driver = { ++ .probe = qoriq_efuse_probe, ++ .driver = { ++ .name = "qoriq-efuse", ++ .of_match_table = qoriq_efuse_of_match, ++ }, ++}; ++module_platform_driver(qoriq_efuse_driver); ++ ++MODULE_AUTHOR("Richard Alpe "); ++MODULE_DESCRIPTION("NXP QorIQ Security Fuse Processor (SFP) Reader"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch new file mode 100644 index 0000000000..67f30e34a2 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch @@ -0,0 +1,37 @@ +From 9d53d595f688c9837e88a919229cc61a165c7b9e Mon Sep 17 00:00:00 2001 +From: Diederik de Haas +Date: Mon, 24 Jul 2023 13:36:22 +0200 +Subject: [PATCH] nvmem: Kconfig: Fix typo "drive" -> "driver" + +Fix typo where "driver" was meant instead of "drive". +While at it, also capitalize "OTP". + +Signed-off-by: Diederik de Haas +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -247,7 +247,7 @@ config NVMEM_ROCKCHIP_EFUSE + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on HAS_IOMEM + help +- This is a simple drive to dump specified values of Rockchip SoC ++ This is a simple driver to dump specified values of Rockchip SoC + from eFuse, such as cpu-leakage. + + This driver can also be built as a module. If so, the module +@@ -258,8 +258,8 @@ config NVMEM_ROCKCHIP_OTP + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on HAS_IOMEM + help +- This is a simple drive to dump specified values of Rockchip SoC +- from otp, such as cpu-leakage. ++ This is a simple driver to dump specified values of Rockchip SoC ++ from OTP, such as cpu-leakage. + + This driver can also be built as a module. If so, the module + will be called nvmem_rockchip_otp. diff --git a/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch b/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch new file mode 100644 index 0000000000..af4a2926dc --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch @@ -0,0 +1,152 @@ +From 0a9ec38c47c1ca4528aa058e2b9ea61901a7e632 Mon Sep 17 00:00:00 2001 +From: Komal Bajaj +Date: Tue, 1 Aug 2023 12:10:25 +0530 +Subject: [PATCH] nvmem: sec-qfprom: Add Qualcomm secure QFPROM support + +For some of the Qualcomm SoC's, it is possible that +some of the fuse regions or entire qfprom region is +protected from non-secure access. In such situations, +the OS will have to use secure calls to read the region. +With that motivation, add secure qfprom driver. + +Signed-off-by: Komal Bajaj +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 13 ++++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/sec-qfprom.c | 96 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 111 insertions(+) + create mode 100644 drivers/nvmem/sec-qfprom.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM + This driver can also be built as a module. If so, the module + will be called nvmem_qfprom. + ++config NVMEM_QCOM_SEC_QFPROM ++ tristate "QCOM SECURE QFPROM Support" ++ depends on ARCH_QCOM || COMPILE_TEST ++ depends on HAS_IOMEM ++ depends on OF ++ select QCOM_SCM ++ help ++ Say y here to enable secure QFPROM support. The secure QFPROM provides access ++ functions for QFPROM data to rest of the drivers via nvmem interface. ++ ++ This driver can also be built as a module. If so, the module will be called ++ nvmem_sec_qfprom. ++ + config NVMEM_RAVE_SP_EEPROM + tristate "Rave SP EEPROM Support" + depends on RAVE_SP_CORE +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvme + nvmem-nintendo-otp-y := nintendo-otp.o + obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o + nvmem_qfprom-y := qfprom.o ++obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o ++nvmem_sec_qfprom-y := sec-qfprom.o + obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o + nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o + obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o +--- /dev/null ++++ b/drivers/nvmem/sec-qfprom.c +@@ -0,0 +1,96 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * struct sec_qfprom - structure holding secure qfprom attributes ++ * ++ * @base: starting physical address for secure qfprom corrected address space. ++ * @dev: qfprom device structure. ++ */ ++struct sec_qfprom { ++ phys_addr_t base; ++ struct device *dev; ++}; ++ ++static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) ++{ ++ struct sec_qfprom *priv = context; ++ unsigned int i; ++ u8 *val = _val; ++ u32 read_val; ++ u8 *tmp; ++ ++ for (i = 0; i < bytes; i++, reg++) { ++ if (i == 0 || reg % 4 == 0) { ++ if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) { ++ dev_err(priv->dev, "Couldn't access fuse register\n"); ++ return -EINVAL; ++ } ++ tmp = (u8 *)&read_val; ++ } ++ ++ val[i] = tmp[reg & 3]; ++ } ++ ++ return 0; ++} ++ ++static int sec_qfprom_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config econfig = { ++ .name = "sec-qfprom", ++ .stride = 1, ++ .word_size = 1, ++ .id = NVMEM_DEVID_AUTO, ++ .reg_read = sec_qfprom_reg_read, ++ }; ++ struct device *dev = &pdev->dev; ++ struct nvmem_device *nvmem; ++ struct sec_qfprom *priv; ++ struct resource *res; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ priv->base = res->start; ++ ++ econfig.size = resource_size(res); ++ econfig.dev = dev; ++ econfig.priv = priv; ++ ++ priv->dev = dev; ++ ++ nvmem = devm_nvmem_register(dev, &econfig); ++ ++ return PTR_ERR_OR_ZERO(nvmem); ++} ++ ++static const struct of_device_id sec_qfprom_of_match[] = { ++ { .compatible = "qcom,sec-qfprom" }, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, sec_qfprom_of_match); ++ ++static struct platform_driver qfprom_driver = { ++ .probe = sec_qfprom_probe, ++ .driver = { ++ .name = "qcom_sec_qfprom", ++ .of_match_table = sec_qfprom_of_match, ++ }, ++}; ++module_platform_driver(qfprom_driver); ++MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch b/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch new file mode 100644 index 0000000000..dab8ec2c24 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch @@ -0,0 +1,30 @@ +From c32f2186acc9abb4d766361255d7ddf07d15eeb2 Mon Sep 17 00:00:00 2001 +From: Atul Raut +Date: Sun, 30 Jul 2023 15:39:15 -0700 +Subject: [PATCH] nvmem: u-boot-env:: Replace zero-length array with + DECLARE_FLEX_ARRAY() helper + +We are moving toward replacing zero-length arrays with C99 flexible-array +members since they are deprecated. Therefore, the new DECLARE_FLEX_ARRAY() +helper macro should be used to replace the zero-length array declaration. + +This fixes warnings such as: +./drivers/nvmem/u-boot-env.c:50:9-13: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays) + +Signed-off-by: Atul Raut +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -47,7 +47,7 @@ struct u_boot_env_image_broadcom { + __le32 magic; + __le32 len; + __le32 crc32; +- uint8_t data[0]; ++ DECLARE_FLEX_ARRAY(uint8_t, data); + } __packed; + + static int u_boot_env_read(void *context, unsigned int offset, void *val, diff --git a/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch b/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch new file mode 100644 index 0000000000..f9532f39c3 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch @@ -0,0 +1,40 @@ +From 104af6a5b199eb4dc7970d1304aef38ac5a6ed54 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:26 +0200 +Subject: [PATCH] nvmem: core: Create all cells before adding the nvmem device + +Let's pack all the cells creation in one place, so they are all created +before we add the nvmem device. + +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -998,17 +998,17 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); +- +- rval = device_add(&nvmem->dev); ++ rval = nvmem_add_cells_from_fixed_layout(nvmem); + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_fixed_layout(nvmem); ++ rval = nvmem_add_cells_from_layout(nvmem); + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_layout(nvmem); ++ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); ++ ++ rval = device_add(&nvmem->dev); + if (rval) + goto err_remove_cells; + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch b/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch new file mode 100644 index 0000000000..8f64d0c28b --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch @@ -0,0 +1,35 @@ +From 6c7f48ea2e663b679aa8e60d8d8e1e6306a644f9 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:27 +0200 +Subject: [PATCH] nvmem: core: Return NULL when no nvmem layout is found + +Currently, of_nvmem_layout_get_container() returns NULL on error, or an +error pointer if either CONFIG_NVMEM or CONFIG_OF is turned off. We +should likely avoid this kind of mix for two reasons: to clarify the +intend and anyway fix the !CONFIG_OF which will likely always if we use +this helper somewhere else. Let's just return NULL when no layout is +found, we don't need an error value here. + +Link: https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/ +Fixes: 266570f496b9 ("nvmem: core: introduce NVMEM layouts") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202308030002.DnSFOrMB-lkp@intel.com/ +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + include/linux/nvmem-consumer.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -256,7 +256,7 @@ static inline struct nvmem_device *of_nv + static inline struct device_node * + of_nvmem_layout_get_container(struct nvmem_device *nvmem) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return NULL; + } + #endif /* CONFIG_NVMEM && CONFIG_OF */ + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch b/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch new file mode 100644 index 0000000000..28d8bba194 --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch @@ -0,0 +1,29 @@ +From b8257f61b4ddac6d7d0e19a5a4e8b07afb3b4ed3 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:28 +0200 +Subject: [PATCH] nvmem: core: Do not open-code existing functions + +Use of_nvmem_layout_get_container() instead of hardcoding it. + +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -786,10 +786,10 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste + + static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) + { +- struct device_node *layout_np, *np = nvmem->dev.of_node; ++ struct device_node *layout_np; + struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); + +- layout_np = of_get_child_by_name(np, "nvmem-layout"); ++ layout_np = of_nvmem_layout_get_container(nvmem); + if (!layout_np) + return NULL; + diff --git a/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch b/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch new file mode 100644 index 0000000000..b62a0e18da --- /dev/null +++ b/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch @@ -0,0 +1,44 @@ +From 0991afbe4b1805e7f0113ef10d7c5f0698a739e4 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:29 +0200 +Subject: [PATCH] nvmem: core: Notify when a new layout is registered + +Tell listeners a new layout was introduced and is now available. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 4 ++++ + include/linux/nvmem-consumer.h | 2 ++ + 2 files changed, 6 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -772,12 +772,16 @@ int __nvmem_layout_register(struct nvmem + list_add(&layout->node, &nvmem_layouts); + spin_unlock(&nvmem_layout_lock); + ++ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); ++ + return 0; + } + EXPORT_SYMBOL_GPL(__nvmem_layout_register); + + void nvmem_layout_unregister(struct nvmem_layout *layout) + { ++ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); ++ + spin_lock(&nvmem_layout_lock); + list_del(&layout->node); + spin_unlock(&nvmem_layout_lock); +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -43,6 +43,8 @@ enum { + NVMEM_REMOVE, + NVMEM_CELL_ADD, + NVMEM_CELL_REMOVE, ++ NVMEM_LAYOUT_ADD, ++ NVMEM_LAYOUT_REMOVE, + }; + + #if IS_ENABLED(CONFIG_NVMEM) diff --git a/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch b/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch new file mode 100644 index 0000000000..e17be439b2 --- /dev/null +++ b/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch @@ -0,0 +1,29 @@ +From a75b58a46423cfd9b1f73581f4bd2ac2ae743996 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Wed, 2 Aug 2023 18:07:45 +0200 +Subject: [PATCH 1/6] leds: turris-omnia: Use sysfs_emit() instead of sprintf() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the dedicated sysfs_emit() function instead of sprintf() in sysfs +attribute accessor brightness_show(). + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230802160748.11208-4-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/leds-turris-omnia.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -194,7 +194,7 @@ static ssize_t brightness_show(struct de + if (ret < 0) + return ret; + +- return sprintf(buf, "%d\n", ret); ++ return sysfs_emit(buf, "%d\n", ret); + } + + static ssize_t brightness_store(struct device *dev, struct device_attribute *a, diff --git a/target/linux/generic/backport-6.6/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch b/target/linux/generic/backport-6.6/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch new file mode 100644 index 0000000000..d84ad67125 --- /dev/null +++ b/target/linux/generic/backport-6.6/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch @@ -0,0 +1,207 @@ +From a64c3c1357275b1fd61bc9734f638cdb5d8a8bbb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:02 +0200 +Subject: [PATCH 4/6] leds: turris-omnia: Make set_brightness() more efficient +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement caching of the LED color and state values that are sent to MCU +in order to make the set_brightness() operation more efficient by +avoiding I2C transactions which are not needed. + +On Turris Omnia's MCU, which acts as the RGB LED controller, each LED +has a RGB color, and a ON/OFF state, which are configurable via I2C +commands CMD_LED_COLOR and CMD_LED_STATE. + +The CMD_LED_COLOR command sends 5 bytes and the CMD_LED_STATE command 2 +bytes over the I2C bus, which operates at 100 kHz. With I2C overhead +this allows ~1670 color changing commands and ~3200 state changing +commands per second (or around 1000 color + state changes per second). +This may seem more than enough, but the issue is that the I2C bus is +shared with another peripheral, the MCU. The MCU exposes an interrupt +interface, and it can trigger hundreds of interrupts per second. Each +time, we need to read the interrupt state register over this I2C bus. +Whenever we are sending a LED color/state changing command, the +interrupt reading is waiting. + +Currently, every time LED brightness or LED multi intensity is changed, +we send a CMD_LED_STATE command, and if the computed color (brightness +adjusted multi_intensity) is non-zero, we also send a CMD_LED_COLOR +command. + +Consider for example the situation when we have a netdev trigger enabled +for a LED. The netdev trigger does not change the LED color, only the +brightness (either to 0 or to currently configured brightness), and so +there is no need to send the CMD_LED_COLOR command. But each change of +brightness to 0 sends one CMD_LED_STATE command, and each change of +brightness to max_brightness sends one CMD_LED_STATE command and one +CMD_LED_COLOR command: + set_brightness(0) -> CMD_LED_STATE + set_brightness(255) -> CMD_LED_STATE + CMD_LED_COLOR + (unnecessary) + +We can avoid the unnecessary I2C transactions if we cache the values of +state and color that are sent to the controller. If the color does not +change from the one previously sent, there is no need to do the +CMD_LED_COLOR I2C transaction, and if the state does not change, there +is no need to do the CMD_LED_STATE transaction. + +Because we need to make sure that our cached values are consistent with +the controller state, add explicit setting of the LED color to white at +probe time (this is the default setting when MCU resets, but does not +necessarily need to be the case, for example if U-Boot played with the +LED colors). + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-3-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/leds-turris-omnia.c | 96 ++++++++++++++++++++++++++------ + 1 file changed, 78 insertions(+), 18 deletions(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -30,6 +30,8 @@ + struct omnia_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS]; ++ u8 cached_channels[OMNIA_LED_NUM_CHANNELS]; ++ bool on; + int reg; + }; + +@@ -72,36 +74,82 @@ static int omnia_cmd_read_u8(const struc + return -EIO; + } + ++static int omnia_led_send_color_cmd(const struct i2c_client *client, ++ struct omnia_led *led) ++{ ++ char cmd[5]; ++ int ret; ++ ++ cmd[0] = CMD_LED_COLOR; ++ cmd[1] = led->reg; ++ cmd[2] = led->subled_info[0].brightness; ++ cmd[3] = led->subled_info[1].brightness; ++ cmd[4] = led->subled_info[2].brightness; ++ ++ /* Send the color change command */ ++ ret = i2c_master_send(client, cmd, 5); ++ if (ret < 0) ++ return ret; ++ ++ /* Cache the RGB channel brightnesses */ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) ++ led->cached_channels[i] = led->subled_info[i].brightness; ++ ++ return 0; ++} ++ ++/* Determine if the computed RGB channels are different from the cached ones */ ++static bool omnia_led_channels_changed(struct omnia_led *led) ++{ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) ++ if (led->subled_info[i].brightness != led->cached_channels[i]) ++ return true; ++ ++ return false; ++} ++ + static int omnia_led_brightness_set_blocking(struct led_classdev *cdev, + enum led_brightness brightness) + { + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); + struct omnia_led *led = to_omnia_led(mc_cdev); +- u8 buf[5], state; +- int ret; ++ int err = 0; + + mutex_lock(&leds->lock); + +- led_mc_calc_color_components(&led->mc_cdev, brightness); ++ /* ++ * Only recalculate RGB brightnesses from intensities if brightness is ++ * non-zero. Otherwise we won't be using them and we can save ourselves ++ * some software divisions (Omnia's CPU does not implement the division ++ * instruction). ++ */ ++ if (brightness) { ++ led_mc_calc_color_components(mc_cdev, brightness); ++ ++ /* ++ * Send color command only if brightness is non-zero and the RGB ++ * channel brightnesses changed. ++ */ ++ if (omnia_led_channels_changed(led)) ++ err = omnia_led_send_color_cmd(leds->client, led); ++ } + +- buf[0] = CMD_LED_COLOR; +- buf[1] = led->reg; +- buf[2] = mc_cdev->subled_info[0].brightness; +- buf[3] = mc_cdev->subled_info[1].brightness; +- buf[4] = mc_cdev->subled_info[2].brightness; +- +- state = CMD_LED_STATE_LED(led->reg); +- if (buf[2] || buf[3] || buf[4]) +- state |= CMD_LED_STATE_ON; +- +- ret = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state); +- if (ret >= 0 && (state & CMD_LED_STATE_ON)) +- ret = i2c_master_send(leds->client, buf, 5); ++ /* Send on/off state change only if (bool)brightness changed */ ++ if (!err && !brightness != !led->on) { ++ u8 state = CMD_LED_STATE_LED(led->reg); ++ ++ if (brightness) ++ state |= CMD_LED_STATE_ON; ++ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state); ++ if (!err) ++ led->on = !!brightness; ++ } + + mutex_unlock(&leds->lock); + +- return ret; ++ return err; + } + + static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, +@@ -129,11 +177,15 @@ static int omnia_led_register(struct i2c + } + + led->subled_info[0].color_index = LED_COLOR_ID_RED; +- led->subled_info[0].channel = 0; + led->subled_info[1].color_index = LED_COLOR_ID_GREEN; +- led->subled_info[1].channel = 1; + led->subled_info[2].color_index = LED_COLOR_ID_BLUE; +- led->subled_info[2].channel = 2; ++ ++ /* Initial color is white */ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) { ++ led->subled_info[i].intensity = 255; ++ led->subled_info[i].brightness = 255; ++ led->subled_info[i].channel = i; ++ } + + led->mc_cdev.subled_info = led->subled_info; + led->mc_cdev.num_colors = OMNIA_LED_NUM_CHANNELS; +@@ -162,6 +214,14 @@ static int omnia_led_register(struct i2c + return ret; + } + ++ /* Set initial color and cache it */ ++ ret = omnia_led_send_color_cmd(client, led); ++ if (ret < 0) { ++ dev_err(dev, "Cannot set LED %pOF initial color: %i\n", np, ++ ret); ++ return ret; ++ } ++ + ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc_cdev, + &init_data); + if (ret < 0) { diff --git a/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch b/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch new file mode 100644 index 0000000000..00773ab0f6 --- /dev/null +++ b/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch @@ -0,0 +1,202 @@ +From e965e0f6de60874fc0a0caed9a9e0122999e0c7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:03 +0200 +Subject: [PATCH 5/6] leds: turris-omnia: Support HW controlled mode via + private trigger +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for enabling MCU controlled mode of the Turris Omnia LEDs +via a LED private trigger called "omnia-mcu". Recall that private LED +triggers will only be listed in the sysfs trigger file for LEDs that +support them (currently there is no user of this mechanism). + +When in MCU controlled mode, the user can still set LED color, but the +blinking is done by MCU, which does different things for different LEDs: +- WAN LED is blinked according to the LED[0] pin of the WAN PHY +- LAN LEDs are blinked according to the LED[0] output of the + corresponding port of the LAN switch +- PCIe LEDs are blinked according to the logical OR of the MiniPCIe port + LED pins + +In the future I want to make the netdev trigger to transparently offload +the blinking to the HW if user sets compatible settings for the netdev +trigger (for LEDs associated with network devices). +There was some work on this already, and hopefully we will be able to +complete it sometime, but for now there are still multiple blockers for +this, and even if there weren't, we still would not be able to configure +HW controlled mode for the LEDs associated with MiniPCIe ports. + +In the meantime let's support HW controlled mode via the private LED +trigger mechanism. If, in the future, we manage to complete the netdev +trigger offloading, we can still keep this private trigger for backwards +compatibility, if needed. + +We also set "omnia-mcu" to cdev->default_trigger, so that the MCU keeps +control until the user first wants to take over it. If a different +default trigger is specified in device-tree via the +'linux,default-trigger' property, LED class will overwrite +cdev->default_trigger, and so the DT property will be respected. + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-4-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/Kconfig | 1 + + drivers/leds/leds-turris-omnia.c | 98 +++++++++++++++++++++++++++++--- + 2 files changed, 91 insertions(+), 8 deletions(-) + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -164,6 +164,7 @@ config LEDS_TURRIS_OMNIA + depends on I2C + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on OF ++ select LEDS_TRIGGERS + help + This option enables basic support for the LEDs found on the front + side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on the +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -31,7 +31,7 @@ struct omnia_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS]; + u8 cached_channels[OMNIA_LED_NUM_CHANNELS]; +- bool on; ++ bool on, hwtrig; + int reg; + }; + +@@ -120,12 +120,14 @@ static int omnia_led_brightness_set_bloc + + /* + * Only recalculate RGB brightnesses from intensities if brightness is +- * non-zero. Otherwise we won't be using them and we can save ourselves +- * some software divisions (Omnia's CPU does not implement the division +- * instruction). ++ * non-zero (if it is zero and the LED is in HW blinking mode, we use ++ * max_brightness as brightness). Otherwise we won't be using them and ++ * we can save ourselves some software divisions (Omnia's CPU does not ++ * implement the division instruction). + */ +- if (brightness) { +- led_mc_calc_color_components(mc_cdev, brightness); ++ if (brightness || led->hwtrig) { ++ led_mc_calc_color_components(mc_cdev, brightness ?: ++ cdev->max_brightness); + + /* + * Send color command only if brightness is non-zero and the RGB +@@ -135,8 +137,11 @@ static int omnia_led_brightness_set_bloc + err = omnia_led_send_color_cmd(leds->client, led); + } + +- /* Send on/off state change only if (bool)brightness changed */ +- if (!err && !brightness != !led->on) { ++ /* ++ * Send on/off state change only if (bool)brightness changed and the LED ++ * is not being blinked by HW. ++ */ ++ if (!err && !led->hwtrig && !brightness != !led->on) { + u8 state = CMD_LED_STATE_LED(led->reg); + + if (brightness) +@@ -152,6 +157,71 @@ static int omnia_led_brightness_set_bloc + return err; + } + ++static struct led_hw_trigger_type omnia_hw_trigger_type; ++ ++static int omnia_hwtrig_activate(struct led_classdev *cdev) ++{ ++ struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(mc_cdev); ++ int err = 0; ++ ++ mutex_lock(&leds->lock); ++ ++ if (!led->on) { ++ /* ++ * If the LED is off (brightness was set to 0), the last ++ * configured color was not necessarily sent to the MCU. ++ * Recompute with max_brightness and send if needed. ++ */ ++ led_mc_calc_color_components(mc_cdev, cdev->max_brightness); ++ ++ if (omnia_led_channels_changed(led)) ++ err = omnia_led_send_color_cmd(leds->client, led); ++ } ++ ++ if (!err) { ++ /* Put the LED into MCU controlled mode */ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg)); ++ if (!err) ++ led->hwtrig = true; ++ } ++ ++ mutex_unlock(&leds->lock); ++ ++ return err; ++} ++ ++static void omnia_hwtrig_deactivate(struct led_classdev *cdev) ++{ ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(lcdev_to_mccdev(cdev)); ++ int err; ++ ++ mutex_lock(&leds->lock); ++ ++ led->hwtrig = false; ++ ++ /* Put the LED into software mode */ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg) | ++ CMD_LED_MODE_USER); ++ ++ mutex_unlock(&leds->lock); ++ ++ if (err < 0) ++ dev_err(cdev->dev, "Cannot put LED to software mode: %i\n", ++ err); ++} ++ ++static struct led_trigger omnia_hw_trigger = { ++ .name = "omnia-mcu", ++ .activate = omnia_hwtrig_activate, ++ .deactivate = omnia_hwtrig_deactivate, ++ .trigger_type = &omnia_hw_trigger_type, ++}; ++ + static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, + struct device_node *np) + { +@@ -195,6 +265,12 @@ static int omnia_led_register(struct i2c + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness = 255; + cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; ++ cdev->trigger_type = &omnia_hw_trigger_type; ++ /* ++ * Use the omnia-mcu trigger as the default trigger. It may be rewritten ++ * by LED class from the linux,default-trigger property. ++ */ ++ cdev->default_trigger = omnia_hw_trigger.name; + + /* put the LED into software mode */ + ret = omnia_cmd_write_u8(client, CMD_LED_MODE, +@@ -309,6 +385,12 @@ static int omnia_leds_probe(struct i2c_c + + mutex_init(&leds->lock); + ++ ret = devm_led_trigger_register(dev, &omnia_hw_trigger); ++ if (ret < 0) { ++ dev_err(dev, "Cannot register private LED trigger: %d\n", ret); ++ return ret; ++ } ++ + led = &leds->leds[0]; + for_each_available_child_of_node(np, child) { + ret = omnia_led_register(client, led, child); diff --git a/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch b/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch new file mode 100644 index 0000000000..e98397922d --- /dev/null +++ b/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch @@ -0,0 +1,244 @@ +From 0efb3f9609d3de5a7d8c31e3835d7eb3e6adce79 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:04 +0200 +Subject: [PATCH 6/6] leds: turris-omnia: Add support for enabling/disabling HW + gamma correction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the MCU on Turris Omnia is running newer firmware versions, the LED +controller supports RGB gamma correction (and enables it by default for +newer boards). + +Determine whether the gamma correction setting feature is supported and +add the ability to set it via sysfs attribute file. + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-5-kabel@kernel.org +Signed-off-by: Lee Jones +--- + .../sysfs-class-led-driver-turris-omnia | 14 ++ + drivers/leds/leds-turris-omnia.c | 137 +++++++++++++++--- + 2 files changed, 134 insertions(+), 17 deletions(-) + +--- a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia ++++ b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia +@@ -12,3 +12,17 @@ Description: (RW) On the front panel of + able to change this setting from software. + + Format: %i ++ ++What: /sys/class/leds//device/gamma_correction ++Date: August 2023 ++KernelVersion: 6.6 ++Contact: Marek Behún ++Description: (RW) Newer versions of the microcontroller firmware of the ++ Turris Omnia router support gamma correction for the RGB LEDs. ++ This feature can be enabled/disabled by writing to this file. ++ ++ If the feature is not supported because the MCU firmware is too ++ old, the file always reads as 0, and writing to the file results ++ in the EOPNOTSUPP error. ++ ++ Format: %i +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -15,17 +15,30 @@ + #define OMNIA_BOARD_LEDS 12 + #define OMNIA_LED_NUM_CHANNELS 3 + +-#define CMD_LED_MODE 3 +-#define CMD_LED_MODE_LED(l) ((l) & 0x0f) +-#define CMD_LED_MODE_USER 0x10 +- +-#define CMD_LED_STATE 4 +-#define CMD_LED_STATE_LED(l) ((l) & 0x0f) +-#define CMD_LED_STATE_ON 0x10 +- +-#define CMD_LED_COLOR 5 +-#define CMD_LED_SET_BRIGHTNESS 7 +-#define CMD_LED_GET_BRIGHTNESS 8 ++/* MCU controller commands at I2C address 0x2a */ ++#define OMNIA_MCU_I2C_ADDR 0x2a ++ ++#define CMD_GET_STATUS_WORD 0x01 ++#define STS_FEATURES_SUPPORTED BIT(2) ++ ++#define CMD_GET_FEATURES 0x10 ++#define FEAT_LED_GAMMA_CORRECTION BIT(5) ++ ++/* LED controller commands at I2C address 0x2b */ ++#define CMD_LED_MODE 0x03 ++#define CMD_LED_MODE_LED(l) ((l) & 0x0f) ++#define CMD_LED_MODE_USER 0x10 ++ ++#define CMD_LED_STATE 0x04 ++#define CMD_LED_STATE_LED(l) ((l) & 0x0f) ++#define CMD_LED_STATE_ON 0x10 ++ ++#define CMD_LED_COLOR 0x05 ++#define CMD_LED_SET_BRIGHTNESS 0x07 ++#define CMD_LED_GET_BRIGHTNESS 0x08 ++ ++#define CMD_SET_GAMMA_CORRECTION 0x30 ++#define CMD_GET_GAMMA_CORRECTION 0x31 + + struct omnia_led { + struct led_classdev_mc mc_cdev; +@@ -40,6 +53,7 @@ struct omnia_led { + struct omnia_leds { + struct i2c_client *client; + struct mutex lock; ++ bool has_gamma_correction; + struct omnia_led leds[]; + }; + +@@ -50,30 +64,42 @@ static int omnia_cmd_write_u8(const stru + return i2c_master_send(client, buf, sizeof(buf)); + } + +-static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) ++static int omnia_cmd_read_raw(struct i2c_adapter *adapter, u8 addr, u8 cmd, ++ void *reply, size_t len) + { + struct i2c_msg msgs[2]; +- u8 reply; + int ret; + +- msgs[0].addr = client->addr; ++ msgs[0].addr = addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &cmd; +- msgs[1].addr = client->addr; ++ msgs[1].addr = addr; + msgs[1].flags = I2C_M_RD; +- msgs[1].len = 1; +- msgs[1].buf = &reply; ++ msgs[1].len = len; ++ msgs[1].buf = reply; + +- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); + if (likely(ret == ARRAY_SIZE(msgs))) +- return reply; ++ return len; + else if (ret < 0) + return ret; + else + return -EIO; + } + ++static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) ++{ ++ u8 reply; ++ int ret; ++ ++ ret = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); ++ if (ret < 0) ++ return ret; ++ ++ return reply; ++} ++ + static int omnia_led_send_color_cmd(const struct i2c_client *client, + struct omnia_led *led) + { +@@ -352,12 +378,74 @@ static ssize_t brightness_store(struct d + } + static DEVICE_ATTR_RW(brightness); + ++static ssize_t gamma_correction_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_leds *leds = i2c_get_clientdata(client); ++ int ret; ++ ++ if (leds->has_gamma_correction) { ++ ret = omnia_cmd_read_u8(client, CMD_GET_GAMMA_CORRECTION); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = 0; ++ } ++ ++ return sysfs_emit(buf, "%d\n", !!ret); ++} ++ ++static ssize_t gamma_correction_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_leds *leds = i2c_get_clientdata(client); ++ bool val; ++ int ret; ++ ++ if (!leds->has_gamma_correction) ++ return -EOPNOTSUPP; ++ ++ if (kstrtobool(buf, &val) < 0) ++ return -EINVAL; ++ ++ ret = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); ++ ++ return ret < 0 ? ret : count; ++} ++static DEVICE_ATTR_RW(gamma_correction); ++ + static struct attribute *omnia_led_controller_attrs[] = { + &dev_attr_brightness.attr, ++ &dev_attr_gamma_correction.attr, + NULL, + }; + ATTRIBUTE_GROUPS(omnia_led_controller); + ++static int omnia_mcu_get_features(const struct i2c_client *client) ++{ ++ u16 reply; ++ int err; ++ ++ err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, ++ CMD_GET_STATUS_WORD, &reply, sizeof(reply)); ++ if (err < 0) ++ return err; ++ ++ /* Check whether MCU firmware supports the CMD_GET_FEAUTRES command */ ++ if (!(le16_to_cpu(reply) & STS_FEATURES_SUPPORTED)) ++ return 0; ++ ++ err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, ++ CMD_GET_FEATURES, &reply, sizeof(reply)); ++ if (err < 0) ++ return err; ++ ++ return le16_to_cpu(reply); ++} ++ + static int omnia_leds_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +@@ -383,6 +471,21 @@ static int omnia_leds_probe(struct i2c_c + leds->client = client; + i2c_set_clientdata(client, leds); + ++ ret = omnia_mcu_get_features(client); ++ if (ret < 0) { ++ dev_err(dev, "Cannot determine MCU supported features: %d\n", ++ ret); ++ return ret; ++ } ++ ++ leds->has_gamma_correction = ret & FEAT_LED_GAMMA_CORRECTION; ++ if (!leds->has_gamma_correction) { ++ dev_info(dev, ++ "Your board's MCU firmware does not support the LED gamma correction feature.\n"); ++ dev_info(dev, ++ "Consider upgrading MCU firmware with the omnia-mcutool utility.\n"); ++ } ++ + mutex_init(&leds->lock); + + ret = devm_led_trigger_register(dev, &omnia_hw_trigger); diff --git a/target/linux/generic/backport-6.6/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch b/target/linux/generic/backport-6.6/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch new file mode 100644 index 0000000000..b0cebdcf14 --- /dev/null +++ b/target/linux/generic/backport-6.6/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch @@ -0,0 +1,167 @@ +From ffec49d391c5f0195360912b216aa24dbc9b53c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 16 Oct 2023 16:15:38 +0200 +Subject: [PATCH] leds: turris-omnia: Fix brightness setting and trigger + activating +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I have improperly refactored commits + 4d5ed2621c24 ("leds: turris-omnia: Make set_brightness() more efficient") +and + aaf38273cf76 ("leds: turris-omnia: Support HW controlled mode via private trigger") +after Lee requested a change in API semantics of the new functions I +introduced in commit + 28350bc0ac77 ("leds: turris-omnia: Do not use SMBUS calls"). + +Before the change, the function omnia_cmd_write_u8() returned 0 on +success, and afterwards it returned a positive value (number of bytes +written). The latter version was applied, but the following commits did +not properly account for this change. + +This results in non-functional LED's .brightness_set_blocking() and +trigger's .activate() methods. + +The main reasoning behind the semantics change was that read/write +methods should return the number of read/written bytes on success. +It was pointed to me [1] that this is not always true (for example the +regmap API does not do so), and since the driver never uses this number +of read/written bytes information, I decided to fix this issue by +changing the functions to the original semantics (return 0 on success). + +[1] https://lore.kernel.org/linux-gpio/ZQnn+Gi0xVlsGCYA@smile.fi.intel.com/ + +Fixes: 28350bc0ac77 ("leds: turris-omnia: Do not use SMBUS calls") +Signed-off-by: Marek Behún +--- + drivers/leds/leds-turris-omnia.c | 37 +++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 17 deletions(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -60,8 +60,11 @@ struct omnia_leds { + static int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, u8 val) + { + u8 buf[2] = { cmd, val }; ++ int ret; ++ ++ ret = i2c_master_send(client, buf, sizeof(buf)); + +- return i2c_master_send(client, buf, sizeof(buf)); ++ return ret < 0 ? ret : 0; + } + + static int omnia_cmd_read_raw(struct i2c_adapter *adapter, u8 addr, u8 cmd, +@@ -81,7 +84,7 @@ static int omnia_cmd_read_raw(struct i2c + + ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); + if (likely(ret == ARRAY_SIZE(msgs))) +- return len; ++ return 0; + else if (ret < 0) + return ret; + else +@@ -91,11 +94,11 @@ static int omnia_cmd_read_raw(struct i2c + static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) + { + u8 reply; +- int ret; ++ int err; + +- ret = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); +- if (ret < 0) +- return ret; ++ err = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); ++ if (err) ++ return err; + + return reply; + } +@@ -236,7 +239,7 @@ static void omnia_hwtrig_deactivate(stru + + mutex_unlock(&leds->lock); + +- if (err < 0) ++ if (err) + dev_err(cdev->dev, "Cannot put LED to software mode: %i\n", + err); + } +@@ -302,7 +305,7 @@ static int omnia_led_register(struct i2c + ret = omnia_cmd_write_u8(client, CMD_LED_MODE, + CMD_LED_MODE_LED(led->reg) | + CMD_LED_MODE_USER); +- if (ret < 0) { ++ if (ret) { + dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np, + ret); + return ret; +@@ -311,7 +314,7 @@ static int omnia_led_register(struct i2c + /* disable the LED */ + ret = omnia_cmd_write_u8(client, CMD_LED_STATE, + CMD_LED_STATE_LED(led->reg)); +- if (ret < 0) { ++ if (ret) { + dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret); + return ret; + } +@@ -364,7 +367,7 @@ static ssize_t brightness_store(struct d + { + struct i2c_client *client = to_i2c_client(dev); + unsigned long brightness; +- int ret; ++ int err; + + if (kstrtoul(buf, 10, &brightness)) + return -EINVAL; +@@ -372,9 +375,9 @@ static ssize_t brightness_store(struct d + if (brightness > 100) + return -EINVAL; + +- ret = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness); ++ err = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness); + +- return ret < 0 ? ret : count; ++ return err ?: count; + } + static DEVICE_ATTR_RW(brightness); + +@@ -403,7 +406,7 @@ static ssize_t gamma_correction_store(st + struct i2c_client *client = to_i2c_client(dev); + struct omnia_leds *leds = i2c_get_clientdata(client); + bool val; +- int ret; ++ int err; + + if (!leds->has_gamma_correction) + return -EOPNOTSUPP; +@@ -411,9 +414,9 @@ static ssize_t gamma_correction_store(st + if (kstrtobool(buf, &val) < 0) + return -EINVAL; + +- ret = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); ++ err = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); + +- return ret < 0 ? ret : count; ++ return err ?: count; + } + static DEVICE_ATTR_RW(gamma_correction); + +@@ -431,7 +434,7 @@ static int omnia_mcu_get_features(const + + err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, + CMD_GET_STATUS_WORD, &reply, sizeof(reply)); +- if (err < 0) ++ if (err) + return err; + + /* Check whether MCU firmware supports the CMD_GET_FEAUTRES command */ +@@ -440,7 +443,7 @@ static int omnia_mcu_get_features(const + + err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, + CMD_GET_FEATURES, &reply, sizeof(reply)); +- if (err < 0) ++ if (err) + return err; + + return le16_to_cpu(reply); diff --git a/target/linux/generic/backport-6.6/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch b/target/linux/generic/backport-6.6/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch new file mode 100644 index 0000000000..66d4028140 --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch @@ -0,0 +1,37 @@ +From 16724d6ea40a2c9315f5a0d81005dfa4d7a6da24 Mon Sep 17 00:00:00 2001 +From: Luca Weiss +Date: Fri, 20 Oct 2023 11:55:40 +0100 +Subject: [PATCH] nvmem: qfprom: Mark core clk as optional + +On some platforms like sc7280 on non-ChromeOS devices the core clock +cannot be touched by Linux so we cannot provide it. Mark it as optional +as accessing qfprom for reading works without it but we still prohibit +writing if we cannot provide the clock. + +Signed-off-by: Luca Weiss +Reviewed-by: Douglas Anderson +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -423,12 +423,12 @@ static int qfprom_probe(struct platform_ + if (IS_ERR(priv->vcc)) + return PTR_ERR(priv->vcc); + +- priv->secclk = devm_clk_get(dev, "core"); ++ priv->secclk = devm_clk_get_optional(dev, "core"); + if (IS_ERR(priv->secclk)) + return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); + +- /* Only enable writing if we have SoC data. */ +- if (priv->soc_data) ++ /* Only enable writing if we have SoC data and a valid clock */ ++ if (priv->soc_data && priv->secclk) + econfig.reg_write = qfprom_reg_write; + } + diff --git a/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch b/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch new file mode 100644 index 0000000000..35b15776fb --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch @@ -0,0 +1,330 @@ +From 2cc3b37f5b6df8189d55d0e812d9658ce256dfec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 20 Oct 2023 11:55:41 +0100 +Subject: [PATCH] nvmem: add explicit config option to read old syntax fixed OF + cells +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Binding for fixed NVMEM cells defined directly as NVMEM device subnodes +has been deprecated. It has been replaced by the "fixed-layout" NVMEM +layout binding. + +New syntax is meant to be clearer and should help avoiding imprecise +bindings. + +NVMEM subsystem already supports the new binding. It should be a good +idea to limit support for old syntax to existing drivers that actually +support & use it (we can't break backward compatibility!). That way we +additionally encourage new bindings & drivers to ignore deprecated +binding. + +It wasn't clear (to me) if rtc and w1 code actually uses old syntax +fixed cells. I enabled them to don't risk any breakage. + +Signed-off-by: Rafał Miłecki +[for meson-{efuse,mx-efuse}.c] +Acked-by: Martin Blumenstingl +[for mtk-efuse.c, nvmem/core.c, nvmem-provider.h] +Reviewed-by: AngeloGioacchino Del Regno +[MT8192, MT8195 Chromebooks] +Tested-by: AngeloGioacchino Del Regno +[for microchip-otpc.c] +Reviewed-by: Claudiu Beznea +[SAMA7G5-EK] +Tested-by: Claudiu Beznea +Acked-by: Jernej Skrabec +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/mtdcore.c | 2 ++ + drivers/nvmem/apple-efuses.c | 1 + + drivers/nvmem/core.c | 8 +++++--- + drivers/nvmem/imx-ocotp-scu.c | 1 + + drivers/nvmem/imx-ocotp.c | 1 + + drivers/nvmem/meson-efuse.c | 1 + + drivers/nvmem/meson-mx-efuse.c | 1 + + drivers/nvmem/microchip-otpc.c | 1 + + drivers/nvmem/mtk-efuse.c | 1 + + drivers/nvmem/qcom-spmi-sdam.c | 1 + + drivers/nvmem/qfprom.c | 1 + + drivers/nvmem/rave-sp-eeprom.c | 1 + + drivers/nvmem/rockchip-efuse.c | 1 + + drivers/nvmem/sc27xx-efuse.c | 1 + + drivers/nvmem/sec-qfprom.c | 1 + + drivers/nvmem/sprd-efuse.c | 1 + + drivers/nvmem/stm32-romem.c | 1 + + drivers/nvmem/sunplus-ocotp.c | 1 + + drivers/nvmem/sunxi_sid.c | 1 + + drivers/nvmem/uniphier-efuse.c | 1 + + drivers/nvmem/zynqmp_nvmem.c | 1 + + drivers/rtc/nvmem.c | 1 + + drivers/w1/slaves/w1_ds250x.c | 1 + + include/linux/nvmem-provider.h | 2 ++ + 24 files changed, 30 insertions(+), 3 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -523,6 +523,7 @@ static int mtd_nvmem_add(struct mtd_info + config.dev = &mtd->dev; + config.name = dev_name(&mtd->dev); + config.owner = THIS_MODULE; ++ config.add_legacy_fixed_of_cells = of_device_is_compatible(node, "nvmem-cells"); + config.reg_read = mtd_nvmem_reg_read; + config.size = mtd->size; + config.word_size = 1; +@@ -891,6 +892,7 @@ static struct nvmem_device *mtd_otp_nvme + config.name = compatible; + config.id = NVMEM_DEVID_AUTO; + config.owner = THIS_MODULE; ++ config.add_legacy_fixed_of_cells = true; + config.type = NVMEM_TYPE_OTP; + config.root_only = true; + config.ignore_wp = true; +--- a/drivers/nvmem/apple-efuses.c ++++ b/drivers/nvmem/apple-efuses.c +@@ -36,6 +36,7 @@ static int apple_efuses_probe(struct pla + struct resource *res; + struct nvmem_config config = { + .dev = &pdev->dev, ++ .add_legacy_fixed_of_cells = true, + .read_only = true, + .reg_read = apple_efuses_read, + .stride = sizeof(u32), +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -998,9 +998,11 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_legacy_of(nvmem); +- if (rval) +- goto err_remove_cells; ++ if (config->add_legacy_fixed_of_cells) { ++ rval = nvmem_add_cells_from_legacy_of(nvmem); ++ if (rval) ++ goto err_remove_cells; ++ } + + rval = nvmem_add_cells_from_fixed_layout(nvmem); + if (rval) +--- a/drivers/nvmem/imx-ocotp-scu.c ++++ b/drivers/nvmem/imx-ocotp-scu.c +@@ -220,6 +220,7 @@ static int imx_scu_ocotp_write(void *con + + static struct nvmem_config imx_scu_ocotp_nvmem_config = { + .name = "imx-scu-ocotp", ++ .add_legacy_fixed_of_cells = true, + .read_only = false, + .word_size = 4, + .stride = 1, +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -616,6 +616,7 @@ static int imx_ocotp_probe(struct platfo + return PTR_ERR(priv->clk); + + priv->params = of_device_get_match_data(&pdev->dev); ++ imx_ocotp_nvmem_config.add_legacy_fixed_of_cells = true; + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; +--- a/drivers/nvmem/meson-efuse.c ++++ b/drivers/nvmem/meson-efuse.c +@@ -93,6 +93,7 @@ static int meson_efuse_probe(struct plat + + econfig->dev = dev; + econfig->name = dev_name(dev); ++ econfig->add_legacy_fixed_of_cells = true; + econfig->stride = 1; + econfig->word_size = 1; + econfig->reg_read = meson_efuse_read; +--- a/drivers/nvmem/meson-mx-efuse.c ++++ b/drivers/nvmem/meson-mx-efuse.c +@@ -211,6 +211,7 @@ static int meson_mx_efuse_probe(struct p + efuse->config.owner = THIS_MODULE; + efuse->config.dev = &pdev->dev; + efuse->config.priv = efuse; ++ efuse->config.add_legacy_fixed_of_cells = true; + efuse->config.stride = drvdata->word_size; + efuse->config.word_size = drvdata->word_size; + efuse->config.size = SZ_512; +--- a/drivers/nvmem/microchip-otpc.c ++++ b/drivers/nvmem/microchip-otpc.c +@@ -261,6 +261,7 @@ static int mchp_otpc_probe(struct platfo + return ret; + + mchp_nvmem_config.dev = otpc->dev; ++ mchp_nvmem_config.add_legacy_fixed_of_cells = true; + mchp_nvmem_config.size = size; + mchp_nvmem_config.priv = otpc; + nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config); +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -83,6 +83,7 @@ static int mtk_efuse_probe(struct platfo + return PTR_ERR(priv->base); + + pdata = device_get_match_data(dev); ++ econfig.add_legacy_fixed_of_cells = true; + econfig.stride = 1; + econfig.word_size = 1; + econfig.reg_read = mtk_reg_read; +--- a/drivers/nvmem/qcom-spmi-sdam.c ++++ b/drivers/nvmem/qcom-spmi-sdam.c +@@ -142,6 +142,7 @@ static int sdam_probe(struct platform_de + sdam->sdam_config.name = "spmi_sdam"; + sdam->sdam_config.id = NVMEM_DEVID_AUTO; + sdam->sdam_config.owner = THIS_MODULE; ++ sdam->sdam_config.add_legacy_fixed_of_cells = true; + sdam->sdam_config.stride = 1; + sdam->sdam_config.word_size = 1; + sdam->sdam_config.reg_read = sdam_read; +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -357,6 +357,7 @@ static int qfprom_probe(struct platform_ + { + struct nvmem_config econfig = { + .name = "qfprom", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .id = NVMEM_DEVID_AUTO, +--- a/drivers/nvmem/rave-sp-eeprom.c ++++ b/drivers/nvmem/rave-sp-eeprom.c +@@ -328,6 +328,7 @@ static int rave_sp_eeprom_probe(struct p + of_property_read_string(np, "zii,eeprom-name", &config.name); + config.priv = eeprom; + config.dev = dev; ++ config.add_legacy_fixed_of_cells = true; + config.size = size; + config.reg_read = rave_sp_eeprom_reg_read; + config.reg_write = rave_sp_eeprom_reg_write; +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -205,6 +205,7 @@ static int rockchip_rk3399_efuse_read(vo + + static struct nvmem_config econfig = { + .name = "rockchip-efuse", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .read_only = true, +--- a/drivers/nvmem/sc27xx-efuse.c ++++ b/drivers/nvmem/sc27xx-efuse.c +@@ -248,6 +248,7 @@ static int sc27xx_efuse_probe(struct pla + econfig.reg_read = sc27xx_efuse_read; + econfig.priv = efuse; + econfig.dev = &pdev->dev; ++ econfig.add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(&pdev->dev, &econfig); + if (IS_ERR(nvmem)) { + dev_err(&pdev->dev, "failed to register nvmem config\n"); +--- a/drivers/nvmem/sec-qfprom.c ++++ b/drivers/nvmem/sec-qfprom.c +@@ -47,6 +47,7 @@ static int sec_qfprom_probe(struct platf + { + struct nvmem_config econfig = { + .name = "sec-qfprom", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .id = NVMEM_DEVID_AUTO, +--- a/drivers/nvmem/sprd-efuse.c ++++ b/drivers/nvmem/sprd-efuse.c +@@ -408,6 +408,7 @@ static int sprd_efuse_probe(struct platf + econfig.read_only = false; + econfig.name = "sprd-efuse"; + econfig.size = efuse->data->blk_nums * SPRD_EFUSE_BLOCK_WIDTH; ++ econfig.add_legacy_fixed_of_cells = true; + econfig.reg_read = sprd_efuse_read; + econfig.reg_write = sprd_efuse_write; + econfig.priv = efuse; +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -207,6 +207,7 @@ static int stm32_romem_probe(struct plat + priv->cfg.priv = priv; + priv->cfg.owner = THIS_MODULE; + priv->cfg.type = NVMEM_TYPE_OTP; ++ priv->cfg.add_legacy_fixed_of_cells = true; + + priv->lower = 0; + +--- a/drivers/nvmem/sunplus-ocotp.c ++++ b/drivers/nvmem/sunplus-ocotp.c +@@ -145,6 +145,7 @@ disable_clk: + + static struct nvmem_config sp_ocotp_nvmem_config = { + .name = "sp-ocotp", ++ .add_legacy_fixed_of_cells = true, + .read_only = true, + .word_size = 1, + .size = QAC628_OTP_SIZE, +--- a/drivers/nvmem/sunxi_sid.c ++++ b/drivers/nvmem/sunxi_sid.c +@@ -154,6 +154,7 @@ static int sunxi_sid_probe(struct platfo + nvmem_cfg->dev = dev; + nvmem_cfg->name = "sunxi-sid"; + nvmem_cfg->type = NVMEM_TYPE_OTP; ++ nvmem_cfg->add_legacy_fixed_of_cells = true; + nvmem_cfg->read_only = true; + nvmem_cfg->size = cfg->size; + nvmem_cfg->word_size = 1; +--- a/drivers/nvmem/uniphier-efuse.c ++++ b/drivers/nvmem/uniphier-efuse.c +@@ -52,6 +52,7 @@ static int uniphier_efuse_probe(struct p + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ econfig.add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -58,6 +58,7 @@ static int zynqmp_nvmem_probe(struct pla + + priv->dev = dev; + econfig.dev = dev; ++ econfig.add_legacy_fixed_of_cells = true; + econfig.reg_read = zynqmp_nvmem_read; + econfig.priv = priv; + +--- a/drivers/rtc/nvmem.c ++++ b/drivers/rtc/nvmem.c +@@ -21,6 +21,7 @@ int devm_rtc_nvmem_register(struct rtc_d + + nvmem_config->dev = dev; + nvmem_config->owner = rtc->owner; ++ nvmem_config->add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(dev, nvmem_config); + if (IS_ERR(nvmem)) + dev_err(dev, "failed to register nvmem device for RTC\n"); +--- a/drivers/w1/slaves/w1_ds250x.c ++++ b/drivers/w1/slaves/w1_ds250x.c +@@ -168,6 +168,7 @@ static int w1_eprom_add_slave(struct w1_ + struct nvmem_device *nvmem; + struct nvmem_config nvmem_cfg = { + .dev = &sl->dev, ++ .add_legacy_fixed_of_cells = true, + .reg_read = w1_nvmem_read, + .type = NVMEM_TYPE_OTP, + .read_only = true, +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -82,6 +82,7 @@ struct nvmem_cell_info { + * @owner: Pointer to exporter module. Used for refcounting. + * @cells: Optional array of pre-defined NVMEM cells. + * @ncells: Number of elements in cells. ++ * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. + * @keepout: Optional array of keepout ranges (sorted ascending by start). + * @nkeepout: Number of elements in the keepout array. + * @type: Type of the nvmem storage +@@ -112,6 +113,7 @@ struct nvmem_config { + struct module *owner; + const struct nvmem_cell_info *cells; + int ncells; ++ bool add_legacy_fixed_of_cells; + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + enum nvmem_type type; diff --git a/target/linux/generic/backport-6.6/816-v6.7-0003-nvmem-Use-device_get_match_data.patch b/target/linux/generic/backport-6.6/816-v6.7-0003-nvmem-Use-device_get_match_data.patch new file mode 100644 index 0000000000..84c0293982 --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0003-nvmem-Use-device_get_match_data.patch @@ -0,0 +1,77 @@ +From 0720219f4d34a88a9badb4de70cfad7585687d48 Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Fri, 20 Oct 2023 11:55:45 +0100 +Subject: [PATCH] nvmem: Use device_get_match_data() + +Use preferred device_get_match_data() instead of of_match_device() to +get the driver match data. With this, adjust the includes to explicitly +include the correct headers. + +Signed-off-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mxs-ocotp.c | 10 ++++------ + drivers/nvmem/stm32-romem.c | 7 ++++--- + 2 files changed, 8 insertions(+), 9 deletions(-) + +--- a/drivers/nvmem/mxs-ocotp.c ++++ b/drivers/nvmem/mxs-ocotp.c +@@ -13,8 +13,9 @@ + #include + #include + #include +-#include ++#include + #include ++#include + #include + #include + +@@ -140,11 +141,10 @@ static int mxs_ocotp_probe(struct platfo + struct device *dev = &pdev->dev; + const struct mxs_data *data; + struct mxs_ocotp *otp; +- const struct of_device_id *match; + int ret; + +- match = of_match_device(dev->driver->of_match_table, dev); +- if (!match || !match->data) ++ data = device_get_match_data(dev); ++ if (!data) + return -EINVAL; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); +@@ -169,8 +169,6 @@ static int mxs_ocotp_probe(struct platfo + if (ret) + return ret; + +- data = match->data; +- + ocotp_config.size = data->size; + ocotp_config.priv = otp; + ocotp_config.dev = dev; +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -10,7 +10,9 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + #include + + #include "stm32-bsec-optee-ta.h" +@@ -211,8 +213,7 @@ static int stm32_romem_probe(struct plat + + priv->lower = 0; + +- cfg = (const struct stm32_romem_cfg *) +- of_match_device(dev->driver->of_match_table, dev)->data; ++ cfg = device_get_match_data(dev); + if (!cfg) { + priv->cfg.read_only = true; + priv->cfg.size = resource_size(res); diff --git a/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch b/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch new file mode 100644 index 0000000000..7d80ad37f1 --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch @@ -0,0 +1,77 @@ +From f4cf4e5db331a5ce69e3f0b21d322cac0f4e4b5d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 23 Oct 2023 12:27:59 +0200 +Subject: [PATCH] Revert "nvmem: add new config option" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 517f14d9cf3533d5ab4fded195ab6f80a92e378f. + +Config option "no_of_node" is no longer needed since adding a more +explicit and targeted option "add_legacy_fixed_of_cells". + +That "no_of_node" config option was needed *earlier* to help mtd's case. + +DT nodes of MTD partitions (that are also NVMEM devices) may contain +subnodes. Those SHOULD NOT be treated as NVMEM fixed cells. + +To prevent NVMEM core code from parsing subnodes a "no_of_node" option +was added (and set to true in mtd) to make for_each_child_of_node() in +NVMEM a no-op. That was a bit hacky because it was messing with +"of_node" pointer to achieve some side-effect. + +With the introduction of "add_legacy_fixed_of_cells" config option +things got more explicit. MTD subsystem simply tells NVMEM when to look +for fixed cells and there is no need to hack "of_node" pointer anymore. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231023102759.31529-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/mtdcore.c | 1 - + drivers/nvmem/core.c | 2 +- + include/linux/nvmem-provider.h | 2 -- + 3 files changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -531,7 +531,6 @@ static int mtd_nvmem_add(struct mtd_info + config.read_only = true; + config.root_only = true; + config.ignore_wp = true; +- config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); + config.priv = mtd; + + mtd->nvmem = nvmem_register(&config); +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -936,7 +936,7 @@ struct nvmem_device *nvmem_register(cons + nvmem->nkeepout = config->nkeepout; + if (config->of_node) + nvmem->dev.of_node = config->of_node; +- else if (!config->no_of_node) ++ else + nvmem->dev.of_node = config->dev->of_node; + + switch (config->id) { +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -89,7 +89,6 @@ struct nvmem_cell_info { + * @read_only: Device is read-only. + * @root_only: Device is accessibly to root only. + * @of_node: If given, this will be used instead of the parent's of_node. +- * @no_of_node: Device should not use the parent's of_node even if it's !NULL. + * @reg_read: Callback to read data. + * @reg_write: Callback to write data. + * @size: Device size. +@@ -122,7 +121,6 @@ struct nvmem_config { + bool ignore_wp; + struct nvmem_layout *layout; + struct device_node *of_node; +- bool no_of_node; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; + int size; diff --git a/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch b/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch new file mode 100644 index 0000000000..bd5ceaabf7 --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch @@ -0,0 +1,45 @@ +From b7c1e53751cb3990153084f31c41f25fde3b629c Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 24 Nov 2023 20:38:14 +0100 +Subject: [PATCH] nvmem: Do not expect fixed layouts to grab a layout driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Two series lived in parallel for some time, which led to this situation: +- The nvmem-layout container is used for dynamic layouts +- We now expect fixed layouts to also use the nvmem-layout container but +this does not require any additional driver, the support is built-in the +nvmem core. + +Ensure we don't refuse to probe for wrong reasons. + +Fixes: 27f699e578b1 ("nvmem: core: add support for fixed cells *layout*") +Cc: stable@vger.kernel.org +Reported-by: Luca Ceresoli +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Tested-by: Luca Ceresoli +Reviewed-by: Luca Ceresoli + +Link: https://lore.kernel.org/r/20231124193814.360552-1-miquel.raynal@bootlin.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -797,6 +797,12 @@ static struct nvmem_layout *nvmem_layout + if (!layout_np) + return NULL; + ++ /* Fixed layouts don't have a matching driver */ ++ if (of_device_is_compatible(layout_np, "fixed-layout")) { ++ of_node_put(layout_np); ++ return NULL; ++ } ++ + /* + * In case the nvmem device was built-in while the layout was built as a + * module, we shall manually request the layout driver loading otherwise diff --git a/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch b/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch new file mode 100644 index 0000000000..d49a20599d --- /dev/null +++ b/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch @@ -0,0 +1,261 @@ +From 1e37bf84afacd5ba17b7a13a18ca2bc78aff05c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 15 Dec 2023 11:13:58 +0000 +Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This driver uses MMIO access for reading NVRAM from a flash device. +Underneath there is a flash controller that reads data and provides +mapping window. + +Using MMIO interface affects controller configuration and may break real +controller driver. It was reported by multiple users of devices with +NVRAM stored on NAND. + +Modify driver to read & cache NVRAM content during init and use that +copy to provide NVMEM data when requested. On NAND flashes due to their +alignment NVRAM partitions can be quite big (1 MiB and more) while +actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid +allocating so much memory check for actual data length. + +Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/ +Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM") +Cc: +Cc: Arınç ÜNAL +Cc: Florian Fainelli +Cc: Scott Branden +Signed-off-by: Rafał Miłecki +Acked-by: Arınç ÜNAL +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111358.316727-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/brcm_nvram.c | 134 ++++++++++++++++++++++++++----------- + 1 file changed, 94 insertions(+), 40 deletions(-) + +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -17,9 +17,23 @@ + + #define NVRAM_MAGIC "FLSH" + ++/** ++ * struct brcm_nvram - driver state internal struct ++ * ++ * @dev: NVMEM device pointer ++ * @nvmem_size: Size of the whole space available for NVRAM ++ * @data: NVRAM data copy stored to avoid poking underlaying flash controller ++ * @data_len: NVRAM data size ++ * @padding_byte: Padding value used to fill remaining space ++ * @cells: Array of discovered NVMEM cells ++ * @ncells: Number of elements in cells ++ */ + struct brcm_nvram { + struct device *dev; +- void __iomem *base; ++ size_t nvmem_size; ++ uint8_t *data; ++ size_t data_len; ++ uint8_t padding_byte; + struct nvmem_cell_info *cells; + int ncells; + }; +@@ -36,10 +50,47 @@ static int brcm_nvram_read(void *context + size_t bytes) + { + struct brcm_nvram *priv = context; +- u8 *dst = val; ++ size_t to_copy; ++ ++ if (offset + bytes > priv->data_len) ++ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0); ++ else ++ to_copy = bytes; ++ ++ memcpy(val, priv->data + offset, to_copy); ++ ++ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy); ++ ++ return 0; ++} ++ ++static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev) ++{ ++ struct resource *res; ++ void __iomem *base; ++ ++ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->nvmem_size = resource_size(res); ++ ++ priv->padding_byte = readb(base + priv->nvmem_size - 1); ++ for (priv->data_len = priv->nvmem_size; ++ priv->data_len; ++ priv->data_len--) { ++ if (readb(base + priv->data_len - 1) != priv->padding_byte) ++ break; ++ } ++ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len); + +- while (bytes--) +- *dst++ = readb(priv->base + offset++); ++ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL); ++ if (!priv->data) ++ return -ENOMEM; ++ ++ memcpy_fromio(priv->data, base, priv->data_len); ++ ++ bcm47xx_nvram_init_from_iomem(base, priv->data_len); + + return 0; + } +@@ -67,8 +118,13 @@ static int brcm_nvram_add_cells(struct b + size_t len) + { + struct device *dev = priv->dev; +- char *var, *value, *eq; ++ char *var, *value; ++ uint8_t tmp; + int idx; ++ int err = 0; ++ ++ tmp = priv->data[len - 1]; ++ priv->data[len - 1] = '\0'; + + priv->ncells = 0; + for (var = data + sizeof(struct brcm_nvram_header); +@@ -78,67 +134,68 @@ static int brcm_nvram_add_cells(struct b + } + + priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; ++ if (!priv->cells) { ++ err = -ENOMEM; ++ goto out; ++ } + + for (var = data + sizeof(struct brcm_nvram_header), idx = 0; + var < (char *)data + len && *var; + var = value + strlen(value) + 1, idx++) { ++ char *eq, *name; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; ++ name = devm_kstrdup(dev, var, GFP_KERNEL); ++ *eq = '='; ++ if (!name) { ++ err = -ENOMEM; ++ goto out; ++ } + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) +- return -ENOMEM; ++ priv->cells[idx].name = name; + priv->cells[idx].offset = value - (char *)data; + priv->cells[idx].bytes = strlen(value); + priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); +- if (!strcmp(var, "et0macaddr") || +- !strcmp(var, "et1macaddr") || +- !strcmp(var, "et2macaddr")) { ++ if (!strcmp(name, "et0macaddr") || ++ !strcmp(name, "et1macaddr") || ++ !strcmp(name, "et2macaddr")) { + priv->cells[idx].raw_len = strlen(value); + priv->cells[idx].bytes = ETH_ALEN; + priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; + } + } + +- return 0; ++out: ++ priv->data[len - 1] = tmp; ++ return err; + } + + static int brcm_nvram_parse(struct brcm_nvram *priv) + { ++ struct brcm_nvram_header *header = (struct brcm_nvram_header *)priv->data; + struct device *dev = priv->dev; +- struct brcm_nvram_header header; +- uint8_t *data; + size_t len; + int err; + +- memcpy_fromio(&header, priv->base, sizeof(header)); +- +- if (memcmp(header.magic, NVRAM_MAGIC, 4)) { ++ if (memcmp(header->magic, NVRAM_MAGIC, 4)) { + dev_err(dev, "Invalid NVRAM magic\n"); + return -EINVAL; + } + +- len = le32_to_cpu(header.len); +- +- data = kzalloc(len, GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- +- memcpy_fromio(data, priv->base, len); +- data[len - 1] = '\0'; +- +- err = brcm_nvram_add_cells(priv, data, len); +- if (err) { +- dev_err(dev, "Failed to add cells: %d\n", err); +- return err; ++ len = le32_to_cpu(header->len); ++ if (len > priv->nvmem_size) { ++ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, ++ priv->nvmem_size); ++ return -EINVAL; + } + +- kfree(data); ++ err = brcm_nvram_add_cells(priv, priv->data, len); ++ if (err) ++ dev_err(dev, "Failed to add cells: %d\n", err); + + return 0; + } +@@ -150,7 +207,6 @@ static int brcm_nvram_probe(struct platf + .reg_read = brcm_nvram_read, + }; + struct device *dev = &pdev->dev; +- struct resource *res; + struct brcm_nvram *priv; + int err; + +@@ -159,21 +215,19 @@ static int brcm_nvram_probe(struct platf + return -ENOMEM; + priv->dev = dev; + +- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); +- if (IS_ERR(priv->base)) +- return PTR_ERR(priv->base); ++ err = brcm_nvram_copy_data(priv, pdev); ++ if (err) ++ return err; + + err = brcm_nvram_parse(priv); + if (err) + return err; + +- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); +- + config.dev = dev; + config.cells = priv->cells; + config.ncells = priv->ncells; + config.priv = priv; +- config.size = resource_size(res); ++ config.size = priv->nvmem_size; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); + } diff --git a/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch b/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch new file mode 100644 index 0000000000..564fe9822d --- /dev/null +++ b/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch @@ -0,0 +1,140 @@ +From 7f38b70042fcaa49219045bd1a9a2836e27a58ac Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:27 +0000 +Subject: [PATCH] of: device: Export of_device_make_bus_id() + +This helper is really handy to create unique device names based on their +device tree path, we may need it outside of the OF core (in the NVMEM +subsystem) so let's export it. As this helper has nothing patform +specific, let's move it to of/device.c instead of of/platform.c so we +can add its prototype to of_device.h. + +Signed-off-by: Miquel Raynal +Acked-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 41 +++++++++++++++++++++++++++++++++++++++ + drivers/of/platform.c | 40 -------------------------------------- + include/linux/of_device.h | 6 ++++++ + 3 files changed, 47 insertions(+), 40 deletions(-) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -395,3 +395,44 @@ int of_device_uevent_modalias(struct dev + return 0; + } + EXPORT_SYMBOL_GPL(of_device_uevent_modalias); ++ ++/** ++ * of_device_make_bus_id - Use the device node data to assign a unique name ++ * @dev: pointer to device structure that is linked to a device tree node ++ * ++ * This routine will first try using the translated bus address to ++ * derive a unique name. If it cannot, then it will prepend names from ++ * parent nodes until a unique name can be derived. ++ */ ++void of_device_make_bus_id(struct device *dev) ++{ ++ struct device_node *node = dev->of_node; ++ const __be32 *reg; ++ u64 addr; ++ u32 mask; ++ ++ /* Construct the name, using parent nodes if necessary to ensure uniqueness */ ++ while (node->parent) { ++ /* ++ * If the address can be translated, then that is as much ++ * uniqueness as we need. Make it the first component and return ++ */ ++ reg = of_get_property(node, "reg", NULL); ++ if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { ++ if (!of_property_read_u32(node, "mask", &mask)) ++ dev_set_name(dev, dev_name(dev) ? "%llx.%x.%pOFn:%s" : "%llx.%x.%pOFn", ++ addr, ffs(mask) - 1, node, dev_name(dev)); ++ ++ else ++ dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn", ++ addr, node, dev_name(dev)); ++ return; ++ } ++ ++ /* format arguments only used if dev_name() resolves to NULL */ ++ dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", ++ kbasename(node->full_name), dev_name(dev)); ++ node = node->parent; ++ } ++} ++EXPORT_SYMBOL_GPL(of_device_make_bus_id); +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -64,46 +64,6 @@ EXPORT_SYMBOL(of_find_device_by_node); + */ + + /** +- * of_device_make_bus_id - Use the device node data to assign a unique name +- * @dev: pointer to device structure that is linked to a device tree node +- * +- * This routine will first try using the translated bus address to +- * derive a unique name. If it cannot, then it will prepend names from +- * parent nodes until a unique name can be derived. +- */ +-static void of_device_make_bus_id(struct device *dev) +-{ +- struct device_node *node = dev->of_node; +- const __be32 *reg; +- u64 addr; +- u32 mask; +- +- /* Construct the name, using parent nodes if necessary to ensure uniqueness */ +- while (node->parent) { +- /* +- * If the address can be translated, then that is as much +- * uniqueness as we need. Make it the first component and return +- */ +- reg = of_get_property(node, "reg", NULL); +- if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { +- if (!of_property_read_u32(node, "mask", &mask)) +- dev_set_name(dev, dev_name(dev) ? "%llx.%x.%pOFn:%s" : "%llx.%x.%pOFn", +- addr, ffs(mask) - 1, node, dev_name(dev)); +- +- else +- dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn", +- addr, node, dev_name(dev)); +- return; +- } +- +- /* format arguments only used if dev_name() resolves to NULL */ +- dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", +- kbasename(node->full_name), dev_name(dev)); +- node = node->parent; +- } +-} +- +-/** + * of_device_alloc - Allocate and initialize an of_device + * @np: device node to assign to device + * @bus_id: Name to assign to the device. May be null to use default name. +--- a/include/linux/of_device.h ++++ b/include/linux/of_device.h +@@ -56,6 +56,9 @@ static inline int of_dma_configure(struc + { + return of_dma_configure_id(dev, np, force_dma, NULL); + } ++ ++void of_device_make_bus_id(struct device *dev); ++ + #else /* CONFIG_OF */ + + static inline int of_driver_match_device(struct device *dev, +@@ -113,6 +116,9 @@ static inline int of_dma_configure(struc + { + return 0; + } ++ ++static inline void of_device_make_bus_id(struct device *dev) {} ++ + #endif /* CONFIG_OF */ + + #endif /* _LINUX_OF_DEVICE_H */ diff --git a/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch b/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch new file mode 100644 index 0000000000..2093fac8a1 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch @@ -0,0 +1,95 @@ +From 4a1a40233b4a9fc159a5c7a27dc34c5c7bc5be55 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:28 +0000 +Subject: [PATCH] nvmem: Move of_nvmem_layout_get_container() in another header + +nvmem-consumer.h is included by consumer devices, extracting data from +NVMEM devices whereas nvmem-provider.h is included by devices providing +NVMEM content. + +The only users of of_nvmem_layout_get_container() outside of the core +are layout drivers, so better move its prototype to nvmem-provider.h. + +While we do so, we also move the kdoc associated with the function to +the header rather than the .c file. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 8 -------- + include/linux/nvmem-consumer.h | 7 ------- + include/linux/nvmem-provider.h | 21 +++++++++++++++++++++ + 3 files changed, 21 insertions(+), 15 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -848,14 +848,6 @@ static int nvmem_add_cells_from_layout(s + } + + #if IS_ENABLED(CONFIG_OF) +-/** +- * of_nvmem_layout_get_container() - Get OF node to layout container. +- * +- * @nvmem: nvmem device. +- * +- * Return: a node pointer with refcount incremented or NULL if no +- * container exists. Use of_node_put() on it when done. +- */ + struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) + { + return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -241,7 +241,6 @@ struct nvmem_cell *of_nvmem_cell_get(str + const char *id); + struct nvmem_device *of_nvmem_device_get(struct device_node *np, + const char *name); +-struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); + #else + static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, + const char *id) +@@ -254,12 +253,6 @@ static inline struct nvmem_device *of_nv + { + return ERR_PTR(-EOPNOTSUPP); + } +- +-static inline struct device_node * +-of_nvmem_layout_get_container(struct nvmem_device *nvmem) +-{ +- return NULL; +-} + #endif /* CONFIG_NVMEM && CONFIG_OF */ + + #endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -244,6 +244,27 @@ nvmem_layout_get_match_data(struct nvmem + + #endif /* CONFIG_NVMEM */ + ++#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) ++ ++/** ++ * of_nvmem_layout_get_container() - Get OF node of layout container ++ * ++ * @nvmem: nvmem device ++ * ++ * Return: a node pointer with refcount incremented or NULL if no ++ * container exists. Use of_node_put() on it when done. ++ */ ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); ++ ++#else /* CONFIG_NVMEM && CONFIG_OF */ ++ ++static inline struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return NULL; ++} ++ ++#endif /* CONFIG_NVMEM && CONFIG_OF */ ++ + #define module_nvmem_layout_driver(__layout_driver) \ + module_driver(__layout_driver, nvmem_layout_register, \ + nvmem_layout_unregister) diff --git a/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch b/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch new file mode 100644 index 0000000000..e722109f91 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch @@ -0,0 +1,91 @@ +From ec9c08a1cb8dc5e8e003f95f5f62de41dde235bb Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:29 +0000 +Subject: [PATCH] nvmem: Create a header for internal sharing + +Before adding all the NVMEM layout bus infrastructure to the core, let's +move the main nvmem_device structure in an internal header, only +available to the core. This way all the additional code can be added in +a dedicated file in order to keep the current core file tidy. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 24 +----------------------- + drivers/nvmem/internals.h | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 23 deletions(-) + create mode 100644 drivers/nvmem/internals.h + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -20,29 +20,7 @@ + #include + #include + +-struct nvmem_device { +- struct module *owner; +- struct device dev; +- int stride; +- int word_size; +- int id; +- struct kref refcnt; +- size_t size; +- bool read_only; +- bool root_only; +- int flags; +- enum nvmem_type type; +- struct bin_attribute eeprom; +- struct device *base_dev; +- struct list_head cells; +- const struct nvmem_keepout *keepout; +- unsigned int nkeepout; +- nvmem_reg_read_t reg_read; +- nvmem_reg_write_t reg_write; +- struct gpio_desc *wp_gpio; +- struct nvmem_layout *layout; +- void *priv; +-}; ++#include "internals.h" + + #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) + +--- /dev/null ++++ b/drivers/nvmem/internals.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _LINUX_NVMEM_INTERNALS_H ++#define _LINUX_NVMEM_INTERNALS_H ++ ++#include ++#include ++#include ++ ++struct nvmem_device { ++ struct module *owner; ++ struct device dev; ++ struct list_head node; ++ int stride; ++ int word_size; ++ int id; ++ struct kref refcnt; ++ size_t size; ++ bool read_only; ++ bool root_only; ++ int flags; ++ enum nvmem_type type; ++ struct bin_attribute eeprom; ++ struct device *base_dev; ++ struct list_head cells; ++ const struct nvmem_keepout *keepout; ++ unsigned int nkeepout; ++ nvmem_reg_read_t reg_read; ++ nvmem_reg_write_t reg_write; ++ struct gpio_desc *wp_gpio; ++ struct nvmem_layout *layout; ++ void *priv; ++}; ++ ++#endif /* ifndef _LINUX_NVMEM_INTERNALS_H */ diff --git a/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch b/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch new file mode 100644 index 0000000000..db2d8c1b46 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch @@ -0,0 +1,79 @@ +From 1b7c298a4ecbc28cc6ee94005734bff55eb83d22 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:30 +0000 +Subject: [PATCH] nvmem: Simplify the ->add_cells() hook + +The layout entry is not used and will anyway be made useless by the new +layout bus infrastructure coming next, so drop it. While at it, clarify +the kdoc entry. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 3 +-- + drivers/nvmem/layouts/sl28vpd.c | 3 +-- + include/linux/nvmem-provider.h | 8 +++----- + 4 files changed, 6 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -817,7 +817,7 @@ static int nvmem_add_cells_from_layout(s + int ret; + + if (layout && layout->add_cells) { +- ret = layout->add_cells(&nvmem->dev, nvmem, layout); ++ ret = layout->add_cells(&nvmem->dev, nvmem); + if (ret) + return ret; + } +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,7 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout) ++static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) + { + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,7 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout) ++static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) + { + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -156,9 +156,8 @@ struct nvmem_cell_table { + * + * @name: Layout name. + * @of_match_table: Open firmware match table. +- * @add_cells: Will be called if a nvmem device is found which +- * has this layout. The function will add layout +- * specific cells with nvmem_add_one_cell(). ++ * @add_cells: Called to populate the layout using ++ * nvmem_add_one_cell(). + * @fixup_cell_info: Will be called before a cell is added. Can be + * used to modify the nvmem_cell_info. + * @owner: Pointer to struct module. +@@ -172,8 +171,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + const char *name; + const struct of_device_id *of_match_table; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout); ++ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); + void (*fixup_cell_info)(struct nvmem_device *nvmem, + struct nvmem_layout *layout, + struct nvmem_cell_info *cell); diff --git a/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch b/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch new file mode 100644 index 0000000000..65aa37f834 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch @@ -0,0 +1,169 @@ +From 1172460e716784ac7e1049a537bdca8edbf97360 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:31 +0000 +Subject: [PATCH] nvmem: Move and rename ->fixup_cell_info() + +This hook is meant to be used by any provider and instantiating a layout +just for this is useless. Let's instead move this hook to the nvmem +device and add it to the config structure to be easily shared by the +providers. + +While at moving this hook, rename it ->fixup_dt_cell_info() to clarify +its main intended purpose. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 6 +++--- + drivers/nvmem/imx-ocotp.c | 11 +++-------- + drivers/nvmem/internals.h | 2 ++ + drivers/nvmem/mtk-efuse.c | 11 +++-------- + include/linux/nvmem-provider.h | 9 ++++----- + 5 files changed, 15 insertions(+), 24 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -676,7 +676,6 @@ static int nvmem_validate_keepouts(struc + + static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) + { +- struct nvmem_layout *layout = nvmem->layout; + struct device *dev = &nvmem->dev; + struct device_node *child; + const __be32 *addr; +@@ -706,8 +705,8 @@ static int nvmem_add_cells_from_dt(struc + + info.np = of_node_get(child); + +- if (layout && layout->fixup_cell_info) +- layout->fixup_cell_info(nvmem, layout, &info); ++ if (nvmem->fixup_dt_cell_info) ++ nvmem->fixup_dt_cell_info(nvmem, &info); + + ret = nvmem_add_one_cell(nvmem, &info); + kfree(info.name); +@@ -896,6 +895,7 @@ struct nvmem_device *nvmem_register(cons + + kref_init(&nvmem->refcnt); + INIT_LIST_HEAD(&nvmem->cells); ++ nvmem->fixup_dt_cell_info = config->fixup_dt_cell_info; + + nvmem->owner = config->owner; + if (!nvmem->owner && config->dev->driver) +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -584,17 +584,12 @@ static const struct of_device_id imx_oco + }; + MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); + +-static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell) ++static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) + { + cell->read_post_process = imx_ocotp_cell_pp; + } + +-static struct nvmem_layout imx_ocotp_layout = { +- .fixup_cell_info = imx_ocotp_fixup_cell_info, +-}; +- + static int imx_ocotp_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -620,7 +615,7 @@ static int imx_ocotp_probe(struct platfo + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; +- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; ++ imx_ocotp_nvmem_config.fixup_dt_cell_info = &imx_ocotp_fixup_dt_cell_info; + + priv->config = &imx_ocotp_nvmem_config; + +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -23,6 +23,8 @@ struct nvmem_device { + struct bin_attribute eeprom; + struct device *base_dev; + struct list_head cells; ++ void (*fixup_dt_cell_info)(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell); + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + nvmem_reg_read_t reg_read; +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -45,9 +45,8 @@ static int mtk_efuse_gpu_speedbin_pp(voi + return 0; + } + +-static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell) ++static void mtk_efuse_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) + { + size_t sz = strlen(cell->name); + +@@ -61,10 +60,6 @@ static void mtk_efuse_fixup_cell_info(st + cell->read_post_process = mtk_efuse_gpu_speedbin_pp; + } + +-static struct nvmem_layout mtk_efuse_layout = { +- .fixup_cell_info = mtk_efuse_fixup_cell_info, +-}; +- + static int mtk_efuse_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -91,7 +86,7 @@ static int mtk_efuse_probe(struct platfo + econfig.priv = priv; + econfig.dev = dev; + if (pdata->uses_post_processing) +- econfig.layout = &mtk_efuse_layout; ++ econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -83,6 +83,8 @@ struct nvmem_cell_info { + * @cells: Optional array of pre-defined NVMEM cells. + * @ncells: Number of elements in cells. + * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. ++ * @fixup_dt_cell_info: Will be called before a cell is added. Can be ++ * used to modify the nvmem_cell_info. + * @keepout: Optional array of keepout ranges (sorted ascending by start). + * @nkeepout: Number of elements in the keepout array. + * @type: Type of the nvmem storage +@@ -113,6 +115,8 @@ struct nvmem_config { + const struct nvmem_cell_info *cells; + int ncells; + bool add_legacy_fixed_of_cells; ++ void (*fixup_dt_cell_info)(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell); + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + enum nvmem_type type; +@@ -158,8 +162,6 @@ struct nvmem_cell_table { + * @of_match_table: Open firmware match table. + * @add_cells: Called to populate the layout using + * nvmem_add_one_cell(). +- * @fixup_cell_info: Will be called before a cell is added. Can be +- * used to modify the nvmem_cell_info. + * @owner: Pointer to struct module. + * @node: List node. + * +@@ -172,9 +174,6 @@ struct nvmem_layout { + const char *name; + const struct of_device_id *of_match_table; + int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); +- void (*fixup_cell_info)(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell); + + /* private */ + struct module *owner; diff --git a/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch b/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch new file mode 100644 index 0000000000..1881332340 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch @@ -0,0 +1,763 @@ +From fc29fd821d9ac2ae3d32a722fac39ce874efb883 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:32 +0000 +Subject: [PATCH] nvmem: core: Rework layouts to become regular devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Current layout support was initially written without modules support in +mind. When the requirement for module support rose, the existing base +was improved to adopt modularization support, but kind of a design flaw +was introduced. With the existing implementation, when a storage device +registers into NVMEM, the core tries to hook a layout (if any) and +populates its cells immediately. This means, if the hardware description +expects a layout to be hooked up, but no driver was provided for that, +the storage medium will fail to probe and try later from +scratch. Even if we consider that the hardware description shall be +correct, we could still probe the storage device (especially if it +contains the rootfs). + +One way to overcome this situation is to consider the layouts as +devices, and leverage the native notifier mechanism. When a new NVMEM +device is registered, we can populate its nvmem-layout child, if any, +and wait for the matching to be done in order to get the cells (the +waiting can be easily done with the NVMEM notifiers). If the layout +driver is compiled as a module, it should automatically be loaded. This +way, there is no strong order to enforce, any NVMEM device creation +or NVMEM layout driver insertion will be observed as a new event which +may lead to the creation of additional cells, without disturbing the +probes with costly (and sometimes endless) deferrals. + +In order to achieve that goal we create a new bus for the nvmem-layouts +with minimal logic to match nvmem-layout devices with nvmem-layout +drivers. All this infrastructure code is created in the layouts.c file. + +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + drivers/nvmem/Makefile | 2 + + drivers/nvmem/core.c | 170 ++++++++++---------------- + drivers/nvmem/internals.h | 21 ++++ + drivers/nvmem/layouts.c | 201 +++++++++++++++++++++++++++++++ + drivers/nvmem/layouts/Kconfig | 8 ++ + drivers/nvmem/layouts/onie-tlv.c | 24 +++- + drivers/nvmem/layouts/sl28vpd.c | 24 +++- + include/linux/nvmem-provider.h | 38 +++--- + 9 files changed, 354 insertions(+), 135 deletions(-) + create mode 100644 drivers/nvmem/layouts.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + menuconfig NVMEM + bool "NVMEM Support" ++ imply NVMEM_LAYOUTS + help + Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... + +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -5,6 +5,8 @@ + + obj-$(CONFIG_NVMEM) += nvmem_core.o + nvmem_core-y := core.o ++obj-$(CONFIG_NVMEM_LAYOUTS) += nvmem_layouts.o ++nvmem_layouts-y := layouts.o + obj-y += layouts/ + + # Devices +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -56,9 +56,6 @@ static LIST_HEAD(nvmem_lookup_list); + + static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); + +-static DEFINE_SPINLOCK(nvmem_layout_lock); +-static LIST_HEAD(nvmem_layouts); +- + static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, + void *val, size_t bytes) + { +@@ -741,97 +738,22 @@ static int nvmem_add_cells_from_fixed_la + return err; + } + +-int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) ++int nvmem_layout_register(struct nvmem_layout *layout) + { +- layout->owner = owner; +- +- spin_lock(&nvmem_layout_lock); +- list_add(&layout->node, &nvmem_layouts); +- spin_unlock(&nvmem_layout_lock); +- +- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); ++ if (!layout->add_cells) ++ return -EINVAL; + +- return 0; ++ /* Populate the cells */ ++ return layout->add_cells(&layout->nvmem->dev, layout->nvmem); + } +-EXPORT_SYMBOL_GPL(__nvmem_layout_register); ++EXPORT_SYMBOL_GPL(nvmem_layout_register); + + void nvmem_layout_unregister(struct nvmem_layout *layout) + { +- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); +- +- spin_lock(&nvmem_layout_lock); +- list_del(&layout->node); +- spin_unlock(&nvmem_layout_lock); ++ /* Keep the API even with an empty stub in case we need it later */ + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) +-{ +- struct device_node *layout_np; +- struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- if (!layout_np) +- return NULL; +- +- /* Fixed layouts don't have a matching driver */ +- if (of_device_is_compatible(layout_np, "fixed-layout")) { +- of_node_put(layout_np); +- return NULL; +- } +- +- /* +- * In case the nvmem device was built-in while the layout was built as a +- * module, we shall manually request the layout driver loading otherwise +- * we'll never have any match. +- */ +- of_request_module(layout_np); +- +- spin_lock(&nvmem_layout_lock); +- +- list_for_each_entry(l, &nvmem_layouts, node) { +- if (of_match_node(l->of_match_table, layout_np)) { +- if (try_module_get(l->owner)) +- layout = l; +- +- break; +- } +- } +- +- spin_unlock(&nvmem_layout_lock); +- of_node_put(layout_np); +- +- return layout; +-} +- +-static void nvmem_layout_put(struct nvmem_layout *layout) +-{ +- if (layout) +- module_put(layout->owner); +-} +- +-static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem) +-{ +- struct nvmem_layout *layout = nvmem->layout; +- int ret; +- +- if (layout && layout->add_cells) { +- ret = layout->add_cells(&nvmem->dev, nvmem); +- if (ret) +- return ret; +- } +- +- return 0; +-} +- +-#if IS_ENABLED(CONFIG_OF) +-struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) +-{ +- return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); +-} +-EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); +-#endif +- + const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, + struct nvmem_layout *layout) + { +@@ -839,7 +761,7 @@ const void *nvmem_layout_get_match_data( + const struct of_device_id *match; + + layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->of_match_table, layout_np); ++ match = of_match_node(layout->dev.driver->of_match_table, layout_np); + + return match ? match->data : NULL; + } +@@ -951,19 +873,6 @@ struct nvmem_device *nvmem_register(cons + goto err_put_device; + } + +- /* +- * If the driver supplied a layout by config->layout, the module +- * pointer will be NULL and nvmem_layout_put() will be a noop. +- */ +- nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); +- if (IS_ERR(nvmem->layout)) { +- rval = PTR_ERR(nvmem->layout); +- nvmem->layout = NULL; +- +- if (rval == -EPROBE_DEFER) +- goto err_teardown_compat; +- } +- + if (config->cells) { + rval = nvmem_add_cells(nvmem, config->cells, config->ncells); + if (rval) +@@ -984,24 +893,24 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_layout(nvmem); +- if (rval) +- goto err_remove_cells; +- + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); + + rval = device_add(&nvmem->dev); + if (rval) + goto err_remove_cells; + ++ rval = nvmem_populate_layout(nvmem); ++ if (rval) ++ goto err_remove_dev; ++ + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + + return nvmem; + ++err_remove_dev: ++ device_del(&nvmem->dev); + err_remove_cells: + nvmem_device_remove_all_cells(nvmem); +- nvmem_layout_put(nvmem->layout); +-err_teardown_compat: + if (config->compat) + nvmem_sysfs_remove_compat(nvmem, config); + err_put_device: +@@ -1023,7 +932,7 @@ static void nvmem_device_release(struct + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + + nvmem_device_remove_all_cells(nvmem); +- nvmem_layout_put(nvmem->layout); ++ nvmem_destroy_layout(nvmem); + device_unregister(&nvmem->dev); + } + +@@ -1325,6 +1234,12 @@ nvmem_cell_get_from_lookup(struct device + return cell; + } + ++static void nvmem_layout_module_put(struct nvmem_device *nvmem) ++{ ++ if (nvmem->layout && nvmem->layout->dev.driver) ++ module_put(nvmem->layout->dev.driver->owner); ++} ++ + #if IS_ENABLED(CONFIG_OF) + static struct nvmem_cell_entry * + nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np) +@@ -1343,6 +1258,18 @@ nvmem_find_cell_entry_by_node(struct nvm + return cell; + } + ++static int nvmem_layout_module_get_optional(struct nvmem_device *nvmem) ++{ ++ if (!nvmem->layout) ++ return 0; ++ ++ if (!nvmem->layout->dev.driver || ++ !try_module_get(nvmem->layout->dev.driver->owner)) ++ return -EPROBE_DEFER; ++ ++ return 0; ++} ++ + /** + * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id + * +@@ -1405,16 +1332,29 @@ struct nvmem_cell *of_nvmem_cell_get(str + return ERR_CAST(nvmem); + } + ++ ret = nvmem_layout_module_get_optional(nvmem); ++ if (ret) { ++ of_node_put(cell_np); ++ __nvmem_device_put(nvmem); ++ return ERR_PTR(ret); ++ } ++ + cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np); + of_node_put(cell_np); + if (!cell_entry) { + __nvmem_device_put(nvmem); +- return ERR_PTR(-ENOENT); ++ nvmem_layout_module_put(nvmem); ++ if (nvmem->layout) ++ return ERR_PTR(-EPROBE_DEFER); ++ else ++ return ERR_PTR(-ENOENT); + } + + cell = nvmem_create_cell(cell_entry, id, cell_index); +- if (IS_ERR(cell)) ++ if (IS_ERR(cell)) { + __nvmem_device_put(nvmem); ++ nvmem_layout_module_put(nvmem); ++ } + + return cell; + } +@@ -1528,6 +1468,7 @@ void nvmem_cell_put(struct nvmem_cell *c + + kfree(cell); + __nvmem_device_put(nvmem); ++ nvmem_layout_module_put(nvmem); + } + EXPORT_SYMBOL_GPL(nvmem_cell_put); + +@@ -2105,11 +2046,22 @@ EXPORT_SYMBOL_GPL(nvmem_dev_name); + + static int __init nvmem_init(void) + { +- return bus_register(&nvmem_bus_type); ++ int ret; ++ ++ ret = bus_register(&nvmem_bus_type); ++ if (ret) ++ return ret; ++ ++ ret = nvmem_layout_bus_register(); ++ if (ret) ++ bus_unregister(&nvmem_bus_type); ++ ++ return ret; + } + + static void __exit nvmem_exit(void) + { ++ nvmem_layout_bus_unregister(); + bus_unregister(&nvmem_bus_type); + } + +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -34,4 +34,25 @@ struct nvmem_device { + void *priv; + }; + ++#if IS_ENABLED(CONFIG_OF) ++int nvmem_layout_bus_register(void); ++void nvmem_layout_bus_unregister(void); ++int nvmem_populate_layout(struct nvmem_device *nvmem); ++void nvmem_destroy_layout(struct nvmem_device *nvmem); ++#else /* CONFIG_OF */ ++static inline int nvmem_layout_bus_register(void) ++{ ++ return 0; ++} ++ ++static inline void nvmem_layout_bus_unregister(void) {} ++ ++static inline int nvmem_populate_layout(struct nvmem_device *nvmem) ++{ ++ return 0; ++} ++ ++static inline void nvmem_destroy_layout(struct nvmem_device *nvmem) { } ++#endif /* CONFIG_OF */ ++ + #endif /* ifndef _LINUX_NVMEM_INTERNALS_H */ +--- /dev/null ++++ b/drivers/nvmem/layouts.c +@@ -0,0 +1,201 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * NVMEM layout bus handling ++ * ++ * Copyright (C) 2023 Bootlin ++ * Author: Miquel Raynal ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "internals.h" ++ ++#define to_nvmem_layout_driver(drv) \ ++ (container_of((drv), struct nvmem_layout_driver, driver)) ++#define to_nvmem_layout_device(_dev) \ ++ container_of((_dev), struct nvmem_layout, dev) ++ ++static int nvmem_layout_bus_match(struct device *dev, struct device_driver *drv) ++{ ++ return of_driver_match_device(dev, drv); ++} ++ ++static int nvmem_layout_bus_probe(struct device *dev) ++{ ++ struct nvmem_layout_driver *drv = to_nvmem_layout_driver(dev->driver); ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ if (!drv->probe || !drv->remove) ++ return -EINVAL; ++ ++ return drv->probe(layout); ++} ++ ++static void nvmem_layout_bus_remove(struct device *dev) ++{ ++ struct nvmem_layout_driver *drv = to_nvmem_layout_driver(dev->driver); ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ return drv->remove(layout); ++} ++ ++static struct bus_type nvmem_layout_bus_type = { ++ .name = "nvmem-layout", ++ .match = nvmem_layout_bus_match, ++ .probe = nvmem_layout_bus_probe, ++ .remove = nvmem_layout_bus_remove, ++}; ++ ++int nvmem_layout_driver_register(struct nvmem_layout_driver *drv) ++{ ++ drv->driver.bus = &nvmem_layout_bus_type; ++ ++ return driver_register(&drv->driver); ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_driver_register); ++ ++void nvmem_layout_driver_unregister(struct nvmem_layout_driver *drv) ++{ ++ driver_unregister(&drv->driver); ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_driver_unregister); ++ ++static void nvmem_layout_release_device(struct device *dev) ++{ ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ of_node_put(layout->dev.of_node); ++ kfree(layout); ++} ++ ++static int nvmem_layout_create_device(struct nvmem_device *nvmem, ++ struct device_node *np) ++{ ++ struct nvmem_layout *layout; ++ struct device *dev; ++ int ret; ++ ++ layout = kzalloc(sizeof(*layout), GFP_KERNEL); ++ if (!layout) ++ return -ENOMEM; ++ ++ /* Create a bidirectional link */ ++ layout->nvmem = nvmem; ++ nvmem->layout = layout; ++ ++ /* Device model registration */ ++ dev = &layout->dev; ++ device_initialize(dev); ++ dev->parent = &nvmem->dev; ++ dev->bus = &nvmem_layout_bus_type; ++ dev->release = nvmem_layout_release_device; ++ dev->coherent_dma_mask = DMA_BIT_MASK(32); ++ dev->dma_mask = &dev->coherent_dma_mask; ++ device_set_node(dev, of_fwnode_handle(of_node_get(np))); ++ of_device_make_bus_id(dev); ++ of_msi_configure(dev, dev->of_node); ++ ++ ret = device_add(dev); ++ if (ret) { ++ put_device(dev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id of_nvmem_layout_skip_table[] = { ++ { .compatible = "fixed-layout", }, ++ {} ++}; ++ ++static int nvmem_layout_bus_populate(struct nvmem_device *nvmem, ++ struct device_node *layout_dn) ++{ ++ int ret; ++ ++ /* Make sure it has a compatible property */ ++ if (!of_get_property(layout_dn, "compatible", NULL)) { ++ pr_debug("%s() - skipping %pOF, no compatible prop\n", ++ __func__, layout_dn); ++ return 0; ++ } ++ ++ /* Fixed layouts are parsed manually somewhere else for now */ ++ if (of_match_node(of_nvmem_layout_skip_table, layout_dn)) { ++ pr_debug("%s() - skipping %pOF node\n", __func__, layout_dn); ++ return 0; ++ } ++ ++ if (of_node_check_flag(layout_dn, OF_POPULATED_BUS)) { ++ pr_debug("%s() - skipping %pOF, already populated\n", ++ __func__, layout_dn); ++ ++ return 0; ++ } ++ ++ /* NVMEM layout buses expect only a single device representing the layout */ ++ ret = nvmem_layout_create_device(nvmem, layout_dn); ++ if (ret) ++ return ret; ++ ++ of_node_set_flag(layout_dn, OF_POPULATED_BUS); ++ ++ return 0; ++} ++ ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); ++} ++EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); ++ ++/* ++ * Returns the number of devices populated, 0 if the operation was not relevant ++ * for this nvmem device, an error code otherwise. ++ */ ++int nvmem_populate_layout(struct nvmem_device *nvmem) ++{ ++ struct device_node *layout_dn; ++ int ret; ++ ++ layout_dn = of_nvmem_layout_get_container(nvmem); ++ if (!layout_dn) ++ return 0; ++ ++ /* Populate the layout device */ ++ device_links_supplier_sync_state_pause(); ++ ret = nvmem_layout_bus_populate(nvmem, layout_dn); ++ device_links_supplier_sync_state_resume(); ++ ++ of_node_put(layout_dn); ++ return ret; ++} ++ ++void nvmem_destroy_layout(struct nvmem_device *nvmem) ++{ ++ struct device *dev; ++ ++ if (!nvmem->layout) ++ return; ++ ++ dev = &nvmem->layout->dev; ++ of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); ++ device_unregister(dev); ++} ++ ++int nvmem_layout_bus_register(void) ++{ ++ return bus_register(&nvmem_layout_bus_type); ++} ++ ++void nvmem_layout_bus_unregister(void) ++{ ++ bus_unregister(&nvmem_layout_bus_type); ++} +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -1,5 +1,11 @@ + # SPDX-License-Identifier: GPL-2.0 + ++config NVMEM_LAYOUTS ++ bool ++ depends on OF ++ ++if NVMEM_LAYOUTS ++ + menu "Layout Types" + + config NVMEM_LAYOUT_SL28_VPD +@@ -21,3 +27,5 @@ config NVMEM_LAYOUT_ONIE_TLV + If unsure, say N. + + endmenu ++ ++endif +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -225,16 +225,32 @@ static int onie_tlv_parse_table(struct d + return 0; + } + ++static int onie_tlv_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = onie_tlv_parse_table; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void onie_tlv_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ + static const struct of_device_id onie_tlv_of_match_table[] = { + { .compatible = "onie,tlv-layout", }, + {}, + }; + MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table); + +-static struct nvmem_layout onie_tlv_layout = { +- .name = "ONIE tlv layout", +- .of_match_table = onie_tlv_of_match_table, +- .add_cells = onie_tlv_parse_table, ++static struct nvmem_layout_driver onie_tlv_layout = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "onie-tlv-layout", ++ .of_match_table = onie_tlv_of_match_table, ++ }, ++ .probe = onie_tlv_probe, ++ .remove = onie_tlv_remove, + }; + module_nvmem_layout_driver(onie_tlv_layout); + +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -134,16 +134,32 @@ static int sl28vpd_add_cells(struct devi + return 0; + } + ++static int sl28vpd_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = sl28vpd_add_cells; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void sl28vpd_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ + static const struct of_device_id sl28vpd_of_match_table[] = { + { .compatible = "kontron,sl28-vpd" }, + {}, + }; + MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); + +-static struct nvmem_layout sl28vpd_layout = { +- .name = "sl28-vpd", +- .of_match_table = sl28vpd_of_match_table, +- .add_cells = sl28vpd_add_cells, ++static struct nvmem_layout_driver sl28vpd_layout = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "kontron-sl28vpd-layout", ++ .of_match_table = sl28vpd_of_match_table, ++ }, ++ .probe = sl28vpd_probe, ++ .remove = sl28vpd_remove, + }; + module_nvmem_layout_driver(sl28vpd_layout); + +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -9,6 +9,7 @@ + #ifndef _LINUX_NVMEM_PROVIDER_H + #define _LINUX_NVMEM_PROVIDER_H + ++#include + #include + #include + #include +@@ -158,12 +159,11 @@ struct nvmem_cell_table { + /** + * struct nvmem_layout - NVMEM layout definitions + * +- * @name: Layout name. +- * @of_match_table: Open firmware match table. +- * @add_cells: Called to populate the layout using +- * nvmem_add_one_cell(). +- * @owner: Pointer to struct module. +- * @node: List node. ++ * @dev: Device-model layout device. ++ * @nvmem: The underlying NVMEM device ++ * @add_cells: Will be called if a nvmem device is found which ++ * has this layout. The function will add layout ++ * specific cells with nvmem_add_one_cell(). + * + * A nvmem device can hold a well defined structure which can just be + * evaluated during runtime. For example a TLV list, or a list of "name=val" +@@ -171,13 +171,15 @@ struct nvmem_cell_table { + * cells. + */ + struct nvmem_layout { +- const char *name; +- const struct of_device_id *of_match_table; ++ struct device dev; ++ struct nvmem_device *nvmem; + int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++}; + +- /* private */ +- struct module *owner; +- struct list_head node; ++struct nvmem_layout_driver { ++ struct device_driver driver; ++ int (*probe)(struct nvmem_layout *layout); ++ void (*remove)(struct nvmem_layout *layout); + }; + + #if IS_ENABLED(CONFIG_NVMEM) +@@ -194,11 +196,15 @@ void nvmem_del_cell_table(struct nvmem_c + int nvmem_add_one_cell(struct nvmem_device *nvmem, + const struct nvmem_cell_info *info); + +-int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner); +-#define nvmem_layout_register(layout) \ +- __nvmem_layout_register(layout, THIS_MODULE) ++int nvmem_layout_register(struct nvmem_layout *layout); + void nvmem_layout_unregister(struct nvmem_layout *layout); + ++int nvmem_layout_driver_register(struct nvmem_layout_driver *drv); ++void nvmem_layout_driver_unregister(struct nvmem_layout_driver *drv); ++#define module_nvmem_layout_driver(__nvmem_layout_driver) \ ++ module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ ++ nvmem_layout_driver_unregister) ++ + const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, + struct nvmem_layout *layout); + +@@ -262,8 +268,4 @@ static inline struct device_node *of_nvm + + #endif /* CONFIG_NVMEM && CONFIG_OF */ + +-#define module_nvmem_layout_driver(__layout_driver) \ +- module_driver(__layout_driver, nvmem_layout_register, \ +- nvmem_layout_unregister) +- + #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch b/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch new file mode 100644 index 0000000000..89872bec2e --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch @@ -0,0 +1,240 @@ +From 0331c611949fffdf486652450901a4dc52bc5cca Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:34 +0000 +Subject: [PATCH] nvmem: core: Expose cells through sysfs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The binary content of nvmem devices is available to the user so in the +easiest cases, finding the content of a cell is rather easy as it is +just a matter of looking at a known and fixed offset. However, nvmem +layouts have been recently introduced to cope with more advanced +situations, where the offset and size of the cells is not known in +advance or is dynamic. When using layouts, more advanced parsers are +used by the kernel in order to give direct access to the content of each +cell, regardless of its position/size in the underlying +device. Unfortunately, these information are not accessible by users, +unless by fully re-implementing the parser logic in userland. + +Let's expose the cells and their content through sysfs to avoid these +situations. Of course the relevant NVMEM sysfs Kconfig option must be +enabled for this support to be available. + +Not all nvmem devices expose cells. Indeed, the .bin_attrs attribute +group member will be filled at runtime only when relevant and will +remain empty otherwise. In this case, as the cells attribute group will +be empty, it will not lead to any additional folder/file creation. + +Exposed cells are read-only. There is, in practice, everything in the +core to support a write path, but as I don't see any need for that, I +prefer to keep the interface simple (and probably safer). The interface +is documented as being in the "testing" state which means we can later +add a write attribute if though relevant. + +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Tested-by: Chen-Yu Tsai +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 135 +++++++++++++++++++++++++++++++++++++- + drivers/nvmem/internals.h | 1 + + 2 files changed, 135 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -300,6 +300,43 @@ static umode_t nvmem_bin_attr_is_visible + return nvmem_bin_attr_get_umode(nvmem); + } + ++static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, ++ const char *id, int index); ++ ++static ssize_t nvmem_cell_attr_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, char *buf, ++ loff_t pos, size_t count) ++{ ++ struct nvmem_cell_entry *entry; ++ struct nvmem_cell *cell = NULL; ++ size_t cell_sz, read_len; ++ void *content; ++ ++ entry = attr->private; ++ cell = nvmem_create_cell(entry, entry->name, 0); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ if (!cell) ++ return -EINVAL; ++ ++ content = nvmem_cell_read(cell, &cell_sz); ++ if (IS_ERR(content)) { ++ read_len = PTR_ERR(content); ++ goto destroy_cell; ++ } ++ ++ read_len = min_t(unsigned int, cell_sz - pos, count); ++ memcpy(buf, content + pos, read_len); ++ kfree(content); ++ ++destroy_cell: ++ kfree_const(cell->id); ++ kfree(cell); ++ ++ return read_len; ++} ++ + /* default read/write permissions */ + static struct bin_attribute bin_attr_rw_nvmem = { + .attr = { +@@ -321,11 +358,21 @@ static const struct attribute_group nvme + .is_bin_visible = nvmem_bin_attr_is_visible, + }; + ++/* Cell attributes will be dynamically allocated */ ++static struct attribute_group nvmem_cells_group = { ++ .name = "cells", ++}; ++ + static const struct attribute_group *nvmem_dev_groups[] = { + &nvmem_bin_group, + NULL, + }; + ++static const struct attribute_group *nvmem_cells_groups[] = { ++ &nvmem_cells_group, ++ NULL, ++}; ++ + static struct bin_attribute bin_attr_nvmem_eeprom_compat = { + .attr = { + .name = "eeprom", +@@ -381,6 +428,68 @@ static void nvmem_sysfs_remove_compat(st + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + } + ++static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem) ++{ ++ struct bin_attribute **cells_attrs, *attrs; ++ struct nvmem_cell_entry *entry; ++ unsigned int ncells = 0, i = 0; ++ int ret = 0; ++ ++ mutex_lock(&nvmem_mutex); ++ ++ if (list_empty(&nvmem->cells) || nvmem->sysfs_cells_populated) { ++ nvmem_cells_group.bin_attrs = NULL; ++ goto unlock_mutex; ++ } ++ ++ /* Allocate an array of attributes with a sentinel */ ++ ncells = list_count_nodes(&nvmem->cells); ++ cells_attrs = devm_kcalloc(&nvmem->dev, ncells + 1, ++ sizeof(struct bin_attribute *), GFP_KERNEL); ++ if (!cells_attrs) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ attrs = devm_kcalloc(&nvmem->dev, ncells, sizeof(struct bin_attribute), GFP_KERNEL); ++ if (!attrs) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ /* Initialize each attribute to take the name and size of the cell */ ++ list_for_each_entry(entry, &nvmem->cells, node) { ++ sysfs_bin_attr_init(&attrs[i]); ++ attrs[i].attr.name = devm_kasprintf(&nvmem->dev, GFP_KERNEL, ++ "%s@%x", entry->name, ++ entry->offset); ++ attrs[i].attr.mode = 0444; ++ attrs[i].size = entry->bytes; ++ attrs[i].read = &nvmem_cell_attr_read; ++ attrs[i].private = entry; ++ if (!attrs[i].attr.name) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ cells_attrs[i] = &attrs[i]; ++ i++; ++ } ++ ++ nvmem_cells_group.bin_attrs = cells_attrs; ++ ++ ret = devm_device_add_groups(&nvmem->dev, nvmem_cells_groups); ++ if (ret) ++ goto unlock_mutex; ++ ++ nvmem->sysfs_cells_populated = true; ++ ++unlock_mutex: ++ mutex_unlock(&nvmem_mutex); ++ ++ return ret; ++} ++ + #else /* CONFIG_NVMEM_SYSFS */ + + static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem, +@@ -740,11 +849,25 @@ static int nvmem_add_cells_from_fixed_la + + int nvmem_layout_register(struct nvmem_layout *layout) + { ++ int ret; ++ + if (!layout->add_cells) + return -EINVAL; + + /* Populate the cells */ +- return layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ if (ret) ++ return ret; ++ ++#ifdef CONFIG_NVMEM_SYSFS ++ ret = nvmem_populate_sysfs_cells(layout->nvmem); ++ if (ret) { ++ nvmem_device_remove_all_cells(layout->nvmem); ++ return ret; ++ } ++#endif ++ ++ return 0; + } + EXPORT_SYMBOL_GPL(nvmem_layout_register); + +@@ -903,10 +1026,20 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_dev; + ++#ifdef CONFIG_NVMEM_SYSFS ++ rval = nvmem_populate_sysfs_cells(nvmem); ++ if (rval) ++ goto err_destroy_layout; ++#endif ++ + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + + return nvmem; + ++#ifdef CONFIG_NVMEM_SYSFS ++err_destroy_layout: ++ nvmem_destroy_layout(nvmem); ++#endif + err_remove_dev: + device_del(&nvmem->dev); + err_remove_cells: +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -32,6 +32,7 @@ struct nvmem_device { + struct gpio_desc *wp_gpio; + struct nvmem_layout *layout; + void *priv; ++ bool sysfs_cells_populated; + }; + + #if IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-6.6/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch b/target/linux/generic/backport-6.6/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch new file mode 100644 index 0000000000..f686222f88 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch @@ -0,0 +1,65 @@ +From f0ac5b23039610619ca4a4805528553ecb6bc815 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Fri, 15 Dec 2023 11:15:36 +0000 +Subject: [PATCH] nvmem: stm32: add support for STM32MP25 BSEC to control OTP + data + +On STM32MP25, OTP area may be read/written by using BSEC (boot, security +and OTP control). The BSEC internal peripheral is only managed by the +secure world. + +The 12 Kbits of OTP (effective) are organized into the following regions: +- lower OTP (OTP0 to OTP127) = 4096 lower OTP bits, + bitwise (1-bit) programmable +- mid OTP (OTP128 to OTP255) = 4096 middle OTP bits, + bulk (32-bit) programmable +- upper OTP (OTP256 to OTP383) = 4096 upper OTP bits, + bulk (32-bit) programmable, + only accessible when BSEC is in closed state. + +As HWKEY and ECIES key are only accessible by ROM code; +only 368 OTP words are managed in this driver (OTP0 to OTP267). + +This patch adds the STM32MP25 configuration for reading and writing +the OTP data using the OP-TEE BSEC TA services. + +Signed-off-by: Patrick Delaunay +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -269,6 +269,19 @@ static const struct stm32_romem_cfg stm3 + .ta = true, + }; + ++/* ++ * STM32MP25 BSEC OTP: 3 regions of 32-bits data words ++ * lower OTP (OTP0 to OTP127), bitwise (1-bit) programmable ++ * mid OTP (OTP128 to OTP255), bulk (32-bit) programmable ++ * upper OTP (OTP256 to OTP383), bulk (32-bit) programmable ++ * but no access to HWKEY and ECIES key: limited at OTP367 ++ */ ++static const struct stm32_romem_cfg stm32mp25_bsec_cfg = { ++ .size = 368 * 4, ++ .lower = 127, ++ .ta = true, ++}; ++ + static const struct of_device_id stm32_romem_of_match[] __maybe_unused = { + { .compatible = "st,stm32f4-otp", }, { + .compatible = "st,stm32mp15-bsec", +@@ -276,6 +289,9 @@ static const struct of_device_id stm32_r + }, { + .compatible = "st,stm32mp13-bsec", + .data = (void *)&stm32mp13_bsec_cfg, ++ }, { ++ .compatible = "st,stm32mp25-bsec", ++ .data = (void *)&stm32mp25_bsec_cfg, + }, + { /* sentinel */ }, + }; diff --git a/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/target/linux/generic/backport-6.6/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/target/linux/generic/backport-6.6/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-6.6/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/target/linux/generic/backport-6.6/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/target/linux/generic/backport-6.6/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/target/linux/generic/backport-6.6/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/target/linux/generic/backport-6.6/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch b/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch new file mode 100644 index 0000000000..3b68403690 --- /dev/null +++ b/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch @@ -0,0 +1,65 @@ +From 4bb7aac70b5d8a4bddf4ee0791b834f9f56883d2 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 20 Apr 2023 10:45:51 +0200 +Subject: [PATCH] net: phy: fix circular LEDS_CLASS dependencies + +The CONFIG_PHYLIB symbol is selected by a number of device drivers that +need PHY support, but it now has a dependency on CONFIG_LEDS_CLASS, +which may not be enabled, causing build failures. + +Avoid the risk of missing and circular dependencies by guarding the +phylib LED support itself in another Kconfig symbol that can only be +enabled if the dependency is met. + +This could be made a hidden symbol and always enabled when both CONFIG_OF +and CONFIG_LEDS_CLASS are reachable from the phylib, but there may be an +advantage in having users see this option when they have a misconfigured +kernel without built-in LED support. + +Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") +Signed-off-by: Arnd Bergmann +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20230420084624.3005701-1-arnd@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/Kconfig | 9 ++++++++- + drivers/net/phy/phy_device.c | 3 ++- + 2 files changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -18,7 +18,6 @@ menuconfig PHYLIB + depends on NETDEVICES + select MDIO_DEVICE + select MDIO_DEVRES +- depends on LEDS_CLASS || LEDS_CLASS=n + help + Ethernet controllers are usually attached to PHY + devices. This option provides infrastructure for +@@ -45,6 +44,14 @@ config LED_TRIGGER_PHY + Mbps OR Gbps OR link + for any speed known to the PHY. + ++config PHYLIB_LEDS ++ bool "Support probing LEDs from device tree" ++ depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB ++ depends on OF ++ default y ++ help ++ When LED class support is enabled, phylib can automatically ++ probe LED setting from device tree. + + config FIXED_PHY + tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs" +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3314,7 +3314,8 @@ static int phy_probe(struct device *dev) + /* Get the LEDs from the device tree, and instantiate standard + * LEDs for them. + */ +- err = of_phy_leds(phydev); ++ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) ++ err = of_phy_leds(phydev); + + out: + /* Re-assert the reset signal on error */ diff --git a/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch b/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch new file mode 100644 index 0000000000..622bb9e94a --- /dev/null +++ b/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch @@ -0,0 +1,43 @@ +From aed8fdad2152d946add50bec00a6b07c457bdcdf Mon Sep 17 00:00:00 2001 +From: Alexander Stein +Date: Mon, 24 Apr 2023 16:16:48 +0200 +Subject: [PATCH] net: phy: Fix reading LED reg property + +'reg' is always encoded in 32 bits, thus it has to be read using the +function with the corresponding bit width. + +Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") +Signed-off-by: Alexander Stein +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230424141648.317944-1-alexander.stein@ew.tq-group.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3075,6 +3075,7 @@ static int of_phy_led(struct phy_device + struct led_init_data init_data = {}; + struct led_classdev *cdev; + struct phy_led *phyled; ++ u32 index; + int err; + + phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); +@@ -3084,10 +3085,13 @@ static int of_phy_led(struct phy_device + cdev = &phyled->led_cdev; + phyled->phydev = phydev; + +- err = of_property_read_u8(led, "reg", &phyled->index); ++ err = of_property_read_u32(led, "reg", &index); + if (err) + return err; ++ if (index > U8_MAX) ++ return -EINVAL; + ++ phyled->index = index; + if (phydev->drv->led_brightness_set) + cdev->brightness_set_blocking = phy_led_set_brightness; + if (phydev->drv->led_blink_set) diff --git a/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch b/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch new file mode 100644 index 0000000000..80197e963b --- /dev/null +++ b/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch @@ -0,0 +1,67 @@ +From c938ab4da0eb1620ae3243b0b24c572ddfc318fc Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Sat, 17 Jun 2023 17:55:00 +0200 +Subject: [PATCH] net: phy: Manual remove LEDs to ensure correct ordering + +If the core is left to remove the LEDs via devm_, it is performed too +late, after the PHY driver is removed from the PHY. This results in +dereferencing a NULL pointer when the LED core tries to turn the LED +off before destroying the LED. + +Manually unregister the LEDs at a safe point in phy_remove. + +Cc: stable@vger.kernel.org +Reported-by: Florian Fainelli +Suggested-by: Florian Fainelli +Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") +Signed-off-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3068,6 +3068,15 @@ static int phy_led_blink_set(struct led_ + return err; + } + ++static void phy_leds_unregister(struct phy_device *phydev) ++{ ++ struct phy_led *phyled; ++ ++ list_for_each_entry(phyled, &phydev->leds, list) { ++ led_classdev_unregister(&phyled->led_cdev); ++ } ++} ++ + static int of_phy_led(struct phy_device *phydev, + struct device_node *led) + { +@@ -3101,7 +3110,7 @@ static int of_phy_led(struct phy_device + init_data.fwnode = of_fwnode_handle(led); + init_data.devname_mandatory = true; + +- err = devm_led_classdev_register_ext(dev, cdev, &init_data); ++ err = led_classdev_register_ext(dev, cdev, &init_data); + if (err) + return err; + +@@ -3130,6 +3139,7 @@ static int of_phy_leds(struct phy_device + err = of_phy_led(phydev, led); + if (err) { + of_node_put(led); ++ phy_leds_unregister(phydev); + return err; + } + } +@@ -3335,6 +3345,9 @@ static int phy_remove(struct device *dev + + cancel_delayed_work_sync(&phydev->state_queue); + ++ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) ++ phy_leds_unregister(phydev); ++ + phydev->state = PHY_DOWN; + + sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch b/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch new file mode 100644 index 0000000000..609115b04a --- /dev/null +++ b/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch @@ -0,0 +1,44 @@ +From af7320ecae0ce646fd2c4a88341a3fbc243553da Mon Sep 17 00:00:00 2001 +From: Yang Li +Date: Thu, 11 May 2023 15:08:20 +0800 +Subject: [PATCH] leds: trigger: netdev: Remove NULL check before dev_{put, + hold} + +The call netdev_{put, hold} of dev_{put, hold} will check NULL, +so there is no need to check before using dev_{put, hold}, +remove it to silence the warnings: + +./drivers/leds/trigger/ledtrig-netdev.c:291:3-10: WARNING: NULL check before dev_{put, hold} functions is not needed. +./drivers/leds/trigger/ledtrig-netdev.c:401:2-9: WARNING: NULL check before dev_{put, hold} functions is not needed. + +Reported-by: Abaci Robot +Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=4929 +Signed-off-by: Yang Li +Link: https://lore.kernel.org/r/20230511070820.52731-1-yang.lee@linux.alibaba.com +Signed-off-by: Lee Jones +--- + drivers/leds/trigger/ledtrig-netdev.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -462,8 +462,7 @@ static int netdev_trig_notify(struct not + get_device_state(trigger_data); + fallthrough; + case NETDEV_REGISTER: +- if (trigger_data->net_dev) +- dev_put(trigger_data->net_dev); ++ dev_put(trigger_data->net_dev); + dev_hold(dev); + trigger_data->net_dev = dev; + break; +@@ -594,8 +593,7 @@ static void netdev_trig_deactivate(struc + + cancel_delayed_work_sync(&trigger_data->work); + +- if (trigger_data->net_dev) +- dev_put(trigger_data->net_dev); ++ dev_put(trigger_data->net_dev); + + kfree(trigger_data); + } diff --git a/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch b/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch new file mode 100644 index 0000000000..2f7a6ced90 --- /dev/null +++ b/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch @@ -0,0 +1,31 @@ +From 97c5209b3d374a25ebdb4c2ea9e9c1b121768da0 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 14 Jun 2023 10:03:59 +0300 +Subject: [PATCH] leds: trigger: netdev: uninitialized variable in + netdev_trig_activate() + +The qca8k_cled_hw_control_get() function which implements ->hw_control_get +sets the appropriate bits but does not clear them. This leads to an +uninitialized variable bug. Fix this by setting mode to zero at the +start. + +Fixes: e0256648c831 ("net: dsa: qca8k: implement hw_control ops") +Signed-off-by: Dan Carpenter +Reviewed-by: Andrew Lunn +Acked-by: Lee Jones +Signed-off-by: David S. Miller +--- + drivers/leds/trigger/ledtrig-netdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -538,7 +538,7 @@ static void netdev_trig_work(struct work + static int netdev_trig_activate(struct led_classdev *led_cdev) + { + struct led_netdev_data *trigger_data; +- unsigned long mode; ++ unsigned long mode = 0; + struct device *dev; + int rc; + diff --git a/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch b/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch new file mode 100644 index 0000000000..dedf84c64b --- /dev/null +++ b/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch @@ -0,0 +1,57 @@ +From 7df1f14c04cbb1950e79c19793420f87227c3e80 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Tue, 8 Aug 2023 23:04:33 +0200 +Subject: [PATCH 1/4] led: trig: netdev: Fix requesting offload device + +When the netdev trigger is activates, it tries to determine what +device the LED blinks for, and what the current blink mode is. + +The documentation for hw_control_get() says: + + * Return 0 on success, a negative error number on failing parsing the + * initial mode. Error from this function is NOT FATAL as the device + * may be in a not supported initial state by the attached LED trigger. + */ + +For the Marvell PHY and the Armada 370-rd board, the initial LED blink +mode is not supported by the trigger, so it returns an error. This +resulted in not getting the device the LED is blinking for. As a +result, the device is unknown and offloaded is never performed. + +Change to condition to always get the device if offloading is +supported, and reduce the scope of testing for an error from +hw_control_get() to skip setting trigger internal state if there is an +error. + +Reviewed-by: Simon Horman +Signed-off-by: Andrew Lunn +Tested-by: Daniel Golle +Link: https://lore.kernel.org/r/20230808210436.838995-2-andrew@lunn.ch +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -564,15 +564,17 @@ static int netdev_trig_activate(struct l + /* Check if hw control is active by default on the LED. + * Init already enabled mode in hw control. + */ +- if (supports_hw_control(led_cdev) && +- !led_cdev->hw_control_get(led_cdev, &mode)) { ++ if (supports_hw_control(led_cdev)) { + dev = led_cdev->hw_control_get_device(led_cdev); + if (dev) { + const char *name = dev_name(dev); + + set_device_name(trigger_data, name, strlen(name)); + trigger_data->hw_control = true; +- trigger_data->mode = mode; ++ ++ rc = led_cdev->hw_control_get(led_cdev, &mode); ++ if (!rc) ++ trigger_data->mode = mode; + } + } + diff --git a/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch new file mode 100644 index 0000000000..505513a53f --- /dev/null +++ b/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -0,0 +1,149 @@ +From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Tue, 8 Aug 2023 23:04:34 +0200 +Subject: [PATCH 2/4] net: phy: phy_device: Call into the PHY driver to set LED + offload + +Linux LEDs can be requested to perform hardware accelerated blinking +to indicate link, RX, TX etc. Pass the rules for blinking to the PHY +driver, if it implements the ops needed to determine if a given +pattern can be offloaded, to offload it, and what the current offload +is. Additionally implement the op needed to get what device the LED is +for. + +Reviewed-by: Simon Horman +Signed-off-by: Andrew Lunn +Tested-by: Daniel Golle +Link: https://lore.kernel.org/r/20230808210436.838995-3-andrew@lunn.ch +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 33 +++++++++++++++++ + 2 files changed, 101 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3068,6 +3068,61 @@ static int phy_led_blink_set(struct led_ + return err; + } + ++static __maybe_unused struct device * ++phy_led_hw_control_get_device(struct led_classdev *led_cdev) ++{ ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ ++ if (phydev->attached_dev) ++ return &phydev->attached_dev->dev; ++ return NULL; ++} ++ ++static int __maybe_unused ++phy_led_hw_control_get(struct led_classdev *led_cdev, ++ unsigned long *rules) ++{ ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ int err; ++ ++ mutex_lock(&phydev->lock); ++ err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++ ++static int __maybe_unused ++phy_led_hw_control_set(struct led_classdev *led_cdev, ++ unsigned long rules) ++{ ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ int err; ++ ++ mutex_lock(&phydev->lock); ++ err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++ ++static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev, ++ unsigned long rules) ++{ ++ struct phy_led *phyled = to_phy_led(led_cdev); ++ struct phy_device *phydev = phyled->phydev; ++ int err; ++ ++ mutex_lock(&phydev->lock); ++ err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++ + static void phy_leds_unregister(struct phy_device *phydev) + { + struct phy_led *phyled; +@@ -3105,6 +3160,19 @@ static int of_phy_led(struct phy_device + cdev->brightness_set_blocking = phy_led_set_brightness; + if (phydev->drv->led_blink_set) + cdev->blink_set = phy_led_blink_set; ++ ++#ifdef CONFIG_LEDS_TRIGGERS ++ if (phydev->drv->led_hw_is_supported && ++ phydev->drv->led_hw_control_set && ++ phydev->drv->led_hw_control_get) { ++ cdev->hw_control_is_supported = phy_led_hw_is_supported; ++ cdev->hw_control_set = phy_led_hw_control_set; ++ cdev->hw_control_get = phy_led_hw_control_get; ++ cdev->hw_control_trigger = "netdev"; ++ } ++ ++ cdev->hw_control_get_device = phy_led_hw_control_get_device; ++#endif + cdev->max_brightness = 1; + init_data.devicename = dev_name(&phydev->mdio.dev); + init_data.fwnode = of_fwnode_handle(led); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1026,6 +1026,39 @@ struct phy_driver { + int (*led_blink_set)(struct phy_device *dev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off); ++ /** ++ * @led_hw_is_supported: Can the HW support the given rules. ++ * @dev: PHY device which has the LED ++ * @index: Which LED of the PHY device ++ * @rules The core is interested in these rules ++ * ++ * Return 0 if yes, -EOPNOTSUPP if not, or an error code. ++ */ ++ int (*led_hw_is_supported)(struct phy_device *dev, u8 index, ++ unsigned long rules); ++ /** ++ * @led_hw_control_set: Set the HW to control the LED ++ * @dev: PHY device which has the LED ++ * @index: Which LED of the PHY device ++ * @rules The rules used to control the LED ++ * ++ * Returns 0, or a an error code. ++ */ ++ int (*led_hw_control_set)(struct phy_device *dev, u8 index, ++ unsigned long rules); ++ /** ++ * @led_hw_control_get: Get how the HW is controlling the LED ++ * @dev: PHY device which has the LED ++ * @index: Which LED of the PHY device ++ * @rules Pointer to the rules used to control the LED ++ * ++ * Set *@rules to how the HW is currently blinking. Returns 0 ++ * on success, or a error code if the current blinking cannot ++ * be represented in rules, or some other error happens. ++ */ ++ int (*led_hw_control_get)(struct phy_device *dev, u8 index, ++ unsigned long *rules); ++ + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch b/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch new file mode 100644 index 0000000000..1300583b66 --- /dev/null +++ b/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch @@ -0,0 +1,344 @@ +From 460b0b648fab24f576c481424e0de5479ffb9786 Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Tue, 8 Aug 2023 23:04:35 +0200 +Subject: [PATCH 3/4] net: phy: marvell: Add support for offloading LED + blinking + +Add the code needed to indicate if a given blinking pattern can be +offloaded, to offload a pattern and to try to return the current +pattern. + +Reviewed-by: Simon Horman +Signed-off-by: Andrew Lunn +Tested-by: Daniel Golle +Link: https://lore.kernel.org/r/20230808210436.838995-4-andrew@lunn.ch +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/marvell.c | 281 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 281 insertions(+) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -2893,6 +2893,272 @@ static int m88e1318_led_blink_set(struct + MII_88E1318S_PHY_LED_FUNC, reg); + } + ++struct marvell_led_rules { ++ int mode; ++ unsigned long rules; ++}; ++ ++static const struct marvell_led_rules marvell_led0[] = { ++ { ++ .mode = 0, ++ .rules = BIT(TRIGGER_NETDEV_LINK), ++ }, ++ { ++ .mode = 1, ++ .rules = (BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 3, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 4, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 5, ++ .rules = BIT(TRIGGER_NETDEV_TX), ++ }, ++ { ++ .mode = 6, ++ .rules = BIT(TRIGGER_NETDEV_LINK), ++ }, ++ { ++ .mode = 7, ++ .rules = BIT(TRIGGER_NETDEV_LINK_1000), ++ }, ++ { ++ .mode = 8, ++ .rules = 0, ++ }, ++}; ++ ++static const struct marvell_led_rules marvell_led1[] = { ++ { ++ .mode = 1, ++ .rules = (BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 2, ++ .rules = (BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_RX)), ++ }, ++ { ++ .mode = 3, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 4, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 6, ++ .rules = (BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000)), ++ }, ++ { ++ .mode = 7, ++ .rules = BIT(TRIGGER_NETDEV_LINK_100), ++ }, ++ { ++ .mode = 8, ++ .rules = 0, ++ }, ++}; ++ ++static const struct marvell_led_rules marvell_led2[] = { ++ { ++ .mode = 0, ++ .rules = BIT(TRIGGER_NETDEV_LINK), ++ }, ++ { ++ .mode = 1, ++ .rules = (BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 3, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 4, ++ .rules = (BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)), ++ }, ++ { ++ .mode = 5, ++ .rules = BIT(TRIGGER_NETDEV_TX), ++ }, ++ { ++ .mode = 6, ++ .rules = (BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_1000)), ++ }, ++ { ++ .mode = 7, ++ .rules = BIT(TRIGGER_NETDEV_LINK_10), ++ }, ++ { ++ .mode = 8, ++ .rules = 0, ++ }, ++}; ++ ++static int marvell_find_led_mode(unsigned long rules, ++ const struct marvell_led_rules *marvell_rules, ++ int count, ++ int *mode) ++{ ++ int i; ++ ++ for (i = 0; i < count; i++) { ++ if (marvell_rules[i].rules == rules) { ++ *mode = marvell_rules[i].mode; ++ return 0; ++ } ++ } ++ return -EOPNOTSUPP; ++} ++ ++static int marvell_get_led_mode(u8 index, unsigned long rules, int *mode) ++{ ++ int ret; ++ ++ switch (index) { ++ case 0: ++ ret = marvell_find_led_mode(rules, marvell_led0, ++ ARRAY_SIZE(marvell_led0), mode); ++ break; ++ case 1: ++ ret = marvell_find_led_mode(rules, marvell_led1, ++ ARRAY_SIZE(marvell_led1), mode); ++ break; ++ case 2: ++ ret = marvell_find_led_mode(rules, marvell_led2, ++ ARRAY_SIZE(marvell_led2), mode); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int marvell_find_led_rules(unsigned long *rules, ++ const struct marvell_led_rules *marvell_rules, ++ int count, ++ int mode) ++{ ++ int i; ++ ++ for (i = 0; i < count; i++) { ++ if (marvell_rules[i].mode == mode) { ++ *rules = marvell_rules[i].rules; ++ return 0; ++ } ++ } ++ return -EOPNOTSUPP; ++} ++ ++static int marvell_get_led_rules(u8 index, unsigned long *rules, int mode) ++{ ++ int ret; ++ ++ switch (index) { ++ case 0: ++ ret = marvell_find_led_rules(rules, marvell_led0, ++ ARRAY_SIZE(marvell_led0), mode); ++ break; ++ case 1: ++ ret = marvell_find_led_rules(rules, marvell_led1, ++ ARRAY_SIZE(marvell_led1), mode); ++ break; ++ case 2: ++ ret = marvell_find_led_rules(rules, marvell_led2, ++ ARRAY_SIZE(marvell_led2), mode); ++ break; ++ default: ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} ++ ++static int m88e1318_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ int mode, ret; ++ ++ switch (index) { ++ case 0: ++ case 1: ++ case 2: ++ ret = marvell_get_led_mode(index, rules, &mode); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int m88e1318_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ int mode, ret, reg; ++ ++ switch (index) { ++ case 0: ++ case 1: ++ case 2: ++ ret = marvell_get_led_mode(index, rules, &mode); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ if (ret < 0) ++ return ret; ++ ++ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC); ++ if (reg < 0) ++ return reg; ++ ++ reg &= ~(0xf << (4 * index)); ++ reg |= mode << (4 * index); ++ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC, reg); ++} ++ ++static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ int mode, reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, ++ MII_88E1318S_PHY_LED_FUNC); ++ if (reg < 0) ++ return reg; ++ ++ mode = (reg >> (4 * index)) & 0xf; ++ ++ return marvell_get_led_rules(index, rules, mode); ++} ++ + static int marvell_probe(struct phy_device *phydev) + { + struct marvell_priv *priv; +@@ -3144,6 +3410,9 @@ static struct phy_driver marvell_drivers + .get_stats = marvell_get_stats, + .led_brightness_set = m88e1318_led_brightness_set, + .led_blink_set = m88e1318_led_blink_set, ++ .led_hw_is_supported = m88e1318_led_hw_is_supported, ++ .led_hw_control_set = m88e1318_led_hw_control_set, ++ .led_hw_control_get = m88e1318_led_hw_control_get, + }, + { + .phy_id = MARVELL_PHY_ID_88E1145, +@@ -3252,6 +3521,9 @@ static struct phy_driver marvell_drivers + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, + .led_blink_set = m88e1318_led_blink_set, ++ .led_hw_is_supported = m88e1318_led_hw_is_supported, ++ .led_hw_control_set = m88e1318_led_hw_control_set, ++ .led_hw_control_get = m88e1318_led_hw_control_get, + }, + { + .phy_id = MARVELL_PHY_ID_88E1540, +@@ -3280,6 +3552,9 @@ static struct phy_driver marvell_drivers + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, + .led_blink_set = m88e1318_led_blink_set, ++ .led_hw_is_supported = m88e1318_led_hw_is_supported, ++ .led_hw_control_set = m88e1318_led_hw_control_set, ++ .led_hw_control_get = m88e1318_led_hw_control_get, + }, + { + .phy_id = MARVELL_PHY_ID_88E1545, +@@ -3308,6 +3583,9 @@ static struct phy_driver marvell_drivers + .cable_test_get_status = marvell_vct7_cable_test_get_status, + .led_brightness_set = m88e1318_led_brightness_set, + .led_blink_set = m88e1318_led_blink_set, ++ .led_hw_is_supported = m88e1318_led_hw_is_supported, ++ .led_hw_control_set = m88e1318_led_hw_control_set, ++ .led_hw_control_get = m88e1318_led_hw_control_get, + }, + { + .phy_id = MARVELL_PHY_ID_88E3016, +@@ -3451,6 +3729,9 @@ static struct phy_driver marvell_drivers + .set_tunable = m88e1540_set_tunable, + .led_brightness_set = m88e1318_led_brightness_set, + .led_blink_set = m88e1318_led_blink_set, ++ .led_hw_is_supported = m88e1318_led_hw_is_supported, ++ .led_hw_control_set = m88e1318_led_hw_control_set, ++ .led_hw_control_get = m88e1318_led_hw_control_get, + }, + }; + diff --git a/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch b/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch new file mode 100644 index 0000000000..d6a69aa9ca --- /dev/null +++ b/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch @@ -0,0 +1,31 @@ +From e8fbcc47a8e935f36f044d85f21a99acecbd7bfb Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Tue, 8 Aug 2023 23:04:36 +0200 +Subject: [PATCH 4/4] leds: trig-netdev: Disable offload on deactivation of + trigger + +Ensure that the offloading of blinking is stopped when the trigger is +deactivated. Calling led_set_brightness() is documented as stopping +offload and setting the LED to a constant brightness. + +Suggested-by: Daniel Golle +Signed-off-by: Andrew Lunn +Reviewed-by: Simon Horman +Tested-by: Daniel Golle +Link: https://lore.kernel.org/r/20230808210436.838995-5-andrew@lunn.ch +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -595,6 +595,8 @@ static void netdev_trig_deactivate(struc + + cancel_delayed_work_sync(&trigger_data->work); + ++ led_set_brightness(led_cdev, LED_OFF); ++ + dev_put(trigger_data->net_dev); + + kfree(trigger_data); diff --git a/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch b/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch new file mode 100644 index 0000000000..f568c3f6ce --- /dev/null +++ b/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch @@ -0,0 +1,58 @@ +From c5d264d4b527c96ae8903376a4b195df47b05203 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:43 +0000 +Subject: [PATCH] of: base: add of_parse_phandle_with_optional_args() + +Add a new variant of the of_parse_phandle_with_args() which treats the +cells name as optional. If it's missing, it is assumed that the phandle +has no arguments. + +Up until now, a nvmem node didn't have any arguments, so all the device +trees haven't any '#*-cells' property. But there is a need for an +additional argument for the phandle, for which we need a '#*-cells' +property. Therefore, we need to support nvmem nodes with and without +this property. + +Signed-off-by: Michael Walle +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/of.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -1009,6 +1009,31 @@ static inline int of_parse_phandle_with_ + } + + /** ++ * of_parse_phandle_with_optional_args() - Find a node pointed by phandle in a list ++ * @np: pointer to a device tree node containing a list ++ * @list_name: property name that contains a list ++ * @cells_name: property name that specifies phandles' arguments count ++ * @index: index of a phandle to parse out ++ * @out_args: optional pointer to output arguments structure (will be filled) ++ * ++ * Same as of_parse_phandle_with_args() except that if the cells_name property ++ * is not found, cell_count of 0 is assumed. ++ * ++ * This is used to useful, if you have a phandle which didn't have arguments ++ * before and thus doesn't have a '#*-cells' property but is now migrated to ++ * having arguments while retaining backwards compatibility. ++ */ ++static inline int of_parse_phandle_with_optional_args(const struct device_node *np, ++ const char *list_name, ++ const char *cells_name, ++ int index, ++ struct of_phandle_args *out_args) ++{ ++ return __of_parse_phandle_with_args(np, list_name, cells_name, ++ 0, index, out_args); ++} ++ ++/** + * of_property_count_u8_elems - Count the number of u8 elements in a property + * + * @np: device node from which the property value is to be read. diff --git a/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch b/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch new file mode 100644 index 0000000000..66c29126b6 --- /dev/null +++ b/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch @@ -0,0 +1,34 @@ +From ff24fed10ba414d19579e26e60b126fad2f2bb07 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:44 +0000 +Subject: [PATCH] of: property: make #.*-cells optional for simple props + +Sometimes, future bindings for phandles will get additional arguments. +Thus the target node of the phandle will need a new #.*-cells property. +To be backwards compatible, this needs to be optional. + +Prepare the DEFINE_SIMPLE_PROPS() to handle the cells name as optional. + +Signed-off-by: Michael Walle +Tested-by: Miquel Raynal +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/property.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/of/property.c ++++ b/drivers/of/property.c +@@ -1146,8 +1146,8 @@ static struct device_node *parse_prop_ce + if (strcmp(prop_name, list_name)) + return NULL; + +- if (of_parse_phandle_with_args(np, list_name, cells_name, index, +- &sup_args)) ++ if (__of_parse_phandle_with_args(np, list_name, cells_name, 0, index, ++ &sup_args)) + return NULL; + + return sup_args.np; diff --git a/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch b/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch new file mode 100644 index 0000000000..07354d7da7 --- /dev/null +++ b/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch @@ -0,0 +1,30 @@ +From e2d8172043d2e50df19fcd59c11e5593de8188d7 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 6 Feb 2023 13:43:45 +0000 +Subject: [PATCH] of: property: add #nvmem-cell-cells property + +Bindings describe the new '#nvmem-cell-cells' property. Now that the +arguments count property is optional, we just add this property to the +nvmem-cells. + +Signed-off-by: Michael Walle +Tested-by: Miquel Raynal +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230206134356.839737-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/property.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/of/property.c ++++ b/drivers/of/property.c +@@ -1251,7 +1251,7 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-c + DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") + DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") + DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) +-DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) ++DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", "#nvmem-cell-cells") + DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") + DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) + DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) diff --git a/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch b/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch new file mode 100644 index 0000000000..8dc370618e --- /dev/null +++ b/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch @@ -0,0 +1,37 @@ +From 553bd29700145e1849698985e9800f14e967da49 Mon Sep 17 00:00:00 2001 +From: Alexander Stein +Date: Tue, 7 Feb 2023 12:05:29 +0100 +Subject: [PATCH] of: device: Ignore modalias of reused nodes + +If of_node is reused, do not use that node's modalias. This will hide +the name of the actual device. This is rather prominent in USB glue +drivers creating a platform device for the host controller. + +Signed-off-by: Alexander Stein +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20230207110531.1060252-2-alexander.stein@ew.tq-group.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -256,7 +256,7 @@ static ssize_t of_device_get_modalias(st + ssize_t csize; + ssize_t tsize; + +- if ((!dev) || (!dev->of_node)) ++ if ((!dev) || (!dev->of_node) || dev->of_node_reused) + return -ENODEV; + + /* Name & Type */ +@@ -379,7 +379,7 @@ int of_device_uevent_modalias(struct dev + { + int sl; + +- if ((!dev) || (!dev->of_node)) ++ if ((!dev) || (!dev->of_node) || dev->of_node_reused) + return -ENODEV; + + /* Devicetree modalias is tricky, we add it in 2 steps */ diff --git a/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch b/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch new file mode 100644 index 0000000000..dcdc2313ba --- /dev/null +++ b/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch @@ -0,0 +1,29 @@ +From 2295bed9bebe8d1eef276194fed5b5fbe89c5363 Mon Sep 17 00:00:00 2001 +From: Alexander Stein +Date: Tue, 7 Feb 2023 12:05:30 +0100 +Subject: [PATCH] of: device: Do not ignore error code in + of_device_uevent_modalias + +of_device_get_modalias might return an error code, propagate that one. +Otherwise the negative, signed integer is propagated to unsigned integer +for the comparison resulting in a huge 'sl' size. + +Signed-off-by: Alexander Stein +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20230207110531.1060252-3-alexander.stein@ew.tq-group.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -388,6 +388,8 @@ int of_device_uevent_modalias(struct dev + + sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], + sizeof(env->buf) - env->buflen); ++ if (sl < 0) ++ return sl; + if (sl >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += sl; diff --git a/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch b/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch new file mode 100644 index 0000000000..280ed9085c --- /dev/null +++ b/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch @@ -0,0 +1,103 @@ +From 5c3d15e127ebfc0754cd18def7124633b6d46672 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:15 +0100 +Subject: [PATCH] of: Update of_device_get_modalias() + +This function only needs a "struct device_node" to work, but for +convenience the author (and only user) of this helper did use a "struct +device" and put it in device.c. + +Let's convert this helper to take a "struct device node" instead. This +change asks for two additional changes: renaming it "of_modalias()" +to fit the current naming, and moving it outside of device.c which will +be done in a follow-up commit. + +Signed-off-by: Miquel Raynal +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -248,7 +248,7 @@ const void *of_device_get_match_data(con + } + EXPORT_SYMBOL(of_device_get_match_data); + +-static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) ++static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) + { + const char *compat; + char *c; +@@ -256,19 +256,16 @@ static ssize_t of_device_get_modalias(st + ssize_t csize; + ssize_t tsize; + +- if ((!dev) || (!dev->of_node) || dev->of_node_reused) +- return -ENODEV; +- + /* Name & Type */ + /* %p eats all alphanum characters, so %c must be used here */ +- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T', +- of_node_get_device_type(dev->of_node)); ++ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', ++ of_node_get_device_type(np)); + tsize = csize; + len -= csize; + if (str) + str += csize; + +- of_property_for_each_string(dev->of_node, "compatible", p, compat) { ++ of_property_for_each_string(np, "compatible", p, compat) { + csize = strlen(compat) + 1; + tsize += csize; + if (csize > len) +@@ -293,7 +290,10 @@ int of_device_request_module(struct devi + ssize_t size; + int ret; + +- size = of_device_get_modalias(dev, NULL, 0); ++ if (!dev || !dev->of_node) ++ return -ENODEV; ++ ++ size = of_modalias(dev->of_node, NULL, 0); + if (size < 0) + return size; + +@@ -304,7 +304,7 @@ int of_device_request_module(struct devi + if (!str) + return -ENOMEM; + +- of_device_get_modalias(dev, str, size); ++ of_modalias(dev->of_node, str, size); + str[size - 1] = '\0'; + ret = request_module(str); + kfree(str); +@@ -321,7 +321,12 @@ EXPORT_SYMBOL_GPL(of_device_request_modu + */ + ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) + { +- ssize_t sl = of_device_get_modalias(dev, str, len - 2); ++ ssize_t sl; ++ ++ if (!dev || !dev->of_node || dev->of_node_reused) ++ return -ENODEV; ++ ++ sl = of_modalias(dev->of_node, str, len - 2); + if (sl < 0) + return sl; + if (sl > len - 2) +@@ -386,8 +391,8 @@ int of_device_uevent_modalias(struct dev + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + +- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], +- sizeof(env->buf) - env->buflen); ++ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1], ++ sizeof(env->buf) - env->buflen); + if (sl < 0) + return sl; + if (sl >= (sizeof(env->buf) - env->buflen)) diff --git a/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch new file mode 100644 index 0000000000..671556fbaa --- /dev/null +++ b/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch @@ -0,0 +1,173 @@ +From 673aa1ed1c9b6710bf24e3f0957d85e2f46c77db Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:16 +0100 +Subject: [PATCH] of: Rename of_modalias_node() + +This helper does not produce a real modalias, but tries to get the +"product" compatible part of the "vendor,product" compatibles only. It +is far from creating a purely useful modalias string and does not seem +to be used like that directly anyway, so let's try to give this helper a +more meaningful name before moving there a real modalias helper (already +existing under of/device.c). + +Also update the various documentations to refer to the strings as +"aliases" rather than "modaliases" which has a real meaning in the Linux +kernel. + +There is no functional change. + +Cc: Rafael J. Wysocki +Cc: Len Brown +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: Thomas Zimmermann +Cc: Sebastian Reichel +Cc: Wolfram Sang +Cc: Mark Brown +Signed-off-by: Miquel Raynal +Reviewed-by: Rob Herring +Acked-by: Mark Brown +Signed-off-by: Srinivas Kandagatla +Acked-by: Sebastian Reichel +Link: https://lore.kernel.org/r/20230404172148.82422-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/bus.c | 7 ++++--- + drivers/gpu/drm/drm_mipi_dsi.c | 2 +- + drivers/hsi/hsi_core.c | 2 +- + drivers/i2c/busses/i2c-powermac.c | 2 +- + drivers/i2c/i2c-core-of.c | 2 +- + drivers/of/base.c | 18 +++++++++++------- + drivers/spi/spi.c | 4 ++-- + include/linux/of.h | 3 ++- + 8 files changed, 23 insertions(+), 17 deletions(-) + +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -806,9 +806,10 @@ static bool acpi_of_modalias(struct acpi + * @modalias: Pointer to buffer that modalias value will be copied into + * @len: Length of modalias buffer + * +- * This is a counterpart of of_modalias_node() for struct acpi_device objects. +- * If there is a compatible string for @adev, it will be copied to @modalias +- * with the vendor prefix stripped; otherwise, @default_id will be used. ++ * This is a counterpart of of_alias_from_compatible() for struct acpi_device ++ * objects. If there is a compatible string for @adev, it will be copied to ++ * @modalias with the vendor prefix stripped; otherwise, @default_id will be ++ * used. + */ + void acpi_set_modalias(struct acpi_device *adev, const char *default_id, + char *modalias, size_t len) +--- a/drivers/gpu/drm/drm_mipi_dsi.c ++++ b/drivers/gpu/drm/drm_mipi_dsi.c +@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_h + int ret; + u32 reg; + +- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { ++ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) { + drm_err(host, "modalias failure on %pOF\n", node); + return ERR_PTR(-EINVAL); + } +--- a/drivers/hsi/hsi_core.c ++++ b/drivers/hsi/hsi_core.c +@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struc + if (!cl) + return; + +- err = of_modalias_node(client, name, sizeof(name)); ++ err = of_alias_from_compatible(client, name, sizeof(name)); + if (err) + goto err; + +--- a/drivers/i2c/busses/i2c-powermac.c ++++ b/drivers/i2c/busses/i2c-powermac.c +@@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct + */ + + /* First try proper modalias */ +- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) { ++ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) { + snprintf(type, type_size, "MAC,%s", tmp); + return true; + } +--- a/drivers/i2c/i2c-core-of.c ++++ b/drivers/i2c/i2c-core-of.c +@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device + + memset(info, 0, sizeof(*info)); + +- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) { ++ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) { + dev_err(dev, "of_i2c: modalias failure on %pOF\n", node); + return -EINVAL; + } +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -1208,19 +1208,23 @@ struct device_node *of_find_matching_nod + EXPORT_SYMBOL(of_find_matching_node_and_match); + + /** +- * of_modalias_node - Lookup appropriate modalias for a device node ++ * of_alias_from_compatible - Lookup appropriate alias for a device node ++ * depending on compatible + * @node: pointer to a device tree node +- * @modalias: Pointer to buffer that modalias value will be copied into +- * @len: Length of modalias value ++ * @alias: Pointer to buffer that alias value will be copied into ++ * @len: Length of alias value + * + * Based on the value of the compatible property, this routine will attempt +- * to choose an appropriate modalias value for a particular device tree node. ++ * to choose an appropriate alias value for a particular device tree node. + * It does this by stripping the manufacturer prefix (as delimited by a ',') + * from the first entry in the compatible list property. + * ++ * Note: The matching on just the "product" side of the compatible is a relic ++ * from I2C and SPI. Please do not add any new user. ++ * + * Return: This routine returns 0 on success, <0 on failure. + */ +-int of_modalias_node(struct device_node *node, char *modalias, int len) ++int of_alias_from_compatible(const struct device_node *node, char *alias, int len) + { + const char *compatible, *p; + int cplen; +@@ -1229,10 +1233,10 @@ int of_modalias_node(struct device_node + if (!compatible || strlen(compatible) > cplen) + return -ENODEV; + p = strchr(compatible, ','); +- strscpy(modalias, p ? p + 1 : compatible, len); ++ strscpy(alias, p ? p + 1 : compatible, len); + return 0; + } +-EXPORT_SYMBOL_GPL(of_modalias_node); ++EXPORT_SYMBOL_GPL(of_alias_from_compatible); + + /** + * of_find_node_by_phandle - Find a node given a phandle +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -2330,8 +2330,8 @@ of_register_spi_device(struct spi_contro + } + + /* Select device driver */ +- rc = of_modalias_node(nc, spi->modalias, +- sizeof(spi->modalias)); ++ rc = of_alias_from_compatible(nc, spi->modalias, ++ sizeof(spi->modalias)); + if (rc < 0) { + dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc); + goto err_out; +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -362,7 +362,8 @@ extern int of_n_addr_cells(struct device + extern int of_n_size_cells(struct device_node *np); + extern const struct of_device_id *of_match_node( + const struct of_device_id *matches, const struct device_node *node); +-extern int of_modalias_node(struct device_node *node, char *modalias, int len); ++extern int of_alias_from_compatible(const struct device_node *node, char *alias, ++ int len); + extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args); + extern int __of_parse_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name, int cell_count, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch new file mode 100644 index 0000000000..39a84161a2 --- /dev/null +++ b/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch @@ -0,0 +1,160 @@ +From bd7a7ed774afd1a4174df34227626c95573be517 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:17 +0100 +Subject: [PATCH] of: Move of_modalias() to module.c + +Create a specific .c file for OF related module handling. +Move of_modalias() inside as a first step. + +The helper is exposed through of.h even though it is only used by core +files because the users from device.c will soon be split into an OF-only +helper in module.c as well as a device-oriented inline helper in +of_device.h. Putting this helper in of_private.h would require to +include of_private.h from of_device.h, which is not acceptable. + +Suggested-by: Rob Herring +Signed-off-by: Miquel Raynal +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/Makefile | 2 +- + drivers/of/device.c | 37 ------------------------------------- + drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + include/linux/of.h | 9 +++++++++ + 4 files changed, 54 insertions(+), 38 deletions(-) + create mode 100644 drivers/of/module.c + +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-obj-y = base.o device.o platform.o property.o ++obj-y = base.o device.o module.o platform.o property.o + obj-$(CONFIG_OF_KOBJ) += kobj.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -1,5 +1,4 @@ + // SPDX-License-Identifier: GPL-2.0 +-#include + #include + #include + #include +@@ -248,42 +247,6 @@ const void *of_device_get_match_data(con + } + EXPORT_SYMBOL(of_device_get_match_data); + +-static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) +-{ +- const char *compat; +- char *c; +- struct property *p; +- ssize_t csize; +- ssize_t tsize; +- +- /* Name & Type */ +- /* %p eats all alphanum characters, so %c must be used here */ +- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', +- of_node_get_device_type(np)); +- tsize = csize; +- len -= csize; +- if (str) +- str += csize; +- +- of_property_for_each_string(np, "compatible", p, compat) { +- csize = strlen(compat) + 1; +- tsize += csize; +- if (csize > len) +- continue; +- +- csize = snprintf(str, len, "C%s", compat); +- for (c = str; c; ) { +- c = strchr(c, ' '); +- if (c) +- *c++ = '_'; +- } +- len -= csize; +- str += csize; +- } +- +- return tsize; +-} +- + int of_device_request_module(struct device *dev) + { + char *str; +--- /dev/null ++++ b/drivers/of/module.c +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Linux kernel module helpers. ++ */ ++ ++#include ++#include ++#include ++ ++ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) ++{ ++ const char *compat; ++ char *c; ++ struct property *p; ++ ssize_t csize; ++ ssize_t tsize; ++ ++ /* Name & Type */ ++ /* %p eats all alphanum characters, so %c must be used here */ ++ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', ++ of_node_get_device_type(np)); ++ tsize = csize; ++ len -= csize; ++ if (str) ++ str += csize; ++ ++ of_property_for_each_string(np, "compatible", p, compat) { ++ csize = strlen(compat) + 1; ++ tsize += csize; ++ if (csize > len) ++ continue; ++ ++ csize = snprintf(str, len, "C%s", compat); ++ for (c = str; c; ) { ++ c = strchr(c, ' '); ++ if (c) ++ *c++ = '_'; ++ } ++ len -= csize; ++ str += csize; ++ } ++ ++ return tsize; ++} +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -374,6 +374,9 @@ extern int of_parse_phandle_with_args_ma + extern int of_count_phandle_with_args(const struct device_node *np, + const char *list_name, const char *cells_name); + ++/* module functions */ ++extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); ++ + /* phandle iterator functions */ + extern int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, +@@ -731,6 +734,12 @@ static inline int of_count_phandle_with_ + return -ENOSYS; + } + ++static inline ssize_t of_modalias(const struct device_node *np, char *str, ++ ssize_t len) ++{ ++ return -ENODEV; ++} ++ + static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, + const char *list_name, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch new file mode 100644 index 0000000000..046c1df561 --- /dev/null +++ b/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch @@ -0,0 +1,131 @@ +From e6506f06d5e82765666902ccf9e9162f3e31d518 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 4 Apr 2023 18:21:18 +0100 +Subject: [PATCH] of: Move the request module helper logic to module.c + +Depending on device.c for pure OF handling is considered +backwards. Let's extract the content of of_device_request_module() to +have the real logic under module.c. + +The next step will be to convert users of of_device_request_module() to +use the new helper. + +Signed-off-by: Miquel Raynal +Reviewed-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 25 ++----------------------- + drivers/of/module.c | 30 ++++++++++++++++++++++++++++++ + include/linux/of.h | 6 ++++++ + 3 files changed, 38 insertions(+), 23 deletions(-) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -8,7 +8,6 @@ + #include /* for bus_dma_region */ + #include + #include +-#include + #include + #include + #include +@@ -249,30 +248,10 @@ EXPORT_SYMBOL(of_device_get_match_data); + + int of_device_request_module(struct device *dev) + { +- char *str; +- ssize_t size; +- int ret; +- +- if (!dev || !dev->of_node) ++ if (!dev) + return -ENODEV; + +- size = of_modalias(dev->of_node, NULL, 0); +- if (size < 0) +- return size; +- +- /* Reserve an additional byte for the trailing '\0' */ +- size++; +- +- str = kmalloc(size, GFP_KERNEL); +- if (!str) +- return -ENOMEM; +- +- of_modalias(dev->of_node, str, size); +- str[size - 1] = '\0'; +- ret = request_module(str); +- kfree(str); +- +- return ret; ++ return of_request_module(dev->of_node); + } + EXPORT_SYMBOL_GPL(of_device_request_module); + +--- a/drivers/of/module.c ++++ b/drivers/of/module.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + #include + #include + +@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_ + + return tsize; + } ++ ++int of_request_module(const struct device_node *np) ++{ ++ char *str; ++ ssize_t size; ++ int ret; ++ ++ if (!np) ++ return -ENODEV; ++ ++ size = of_modalias(np, NULL, 0); ++ if (size < 0) ++ return size; ++ ++ /* Reserve an additional byte for the trailing '\0' */ ++ size++; ++ ++ str = kmalloc(size, GFP_KERNEL); ++ if (!str) ++ return -ENOMEM; ++ ++ of_modalias(np, str, size); ++ str[size - 1] = '\0'; ++ ret = request_module(str); ++ kfree(str); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(of_request_module); +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -376,6 +376,7 @@ extern int of_count_phandle_with_args(co + + /* module functions */ + extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); ++extern int of_request_module(const struct device_node *np); + + /* phandle iterator functions */ + extern int of_phandle_iterator_init(struct of_phandle_iterator *it, +@@ -739,6 +740,11 @@ static inline ssize_t of_modalias(const + { + return -ENODEV; + } ++ ++static inline int of_request_module(const struct device_node *np) ++{ ++ return -ENODEV; ++} + + static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, + const struct device_node *np, diff --git a/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch b/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch new file mode 100644 index 0000000000..3319f431ba --- /dev/null +++ b/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch @@ -0,0 +1,207 @@ +From 77faa07c185c969e742cbb3e6aa487a11b0b616c Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Tue, 30 Aug 2022 09:57:42 +0300 +Subject: [PATCH] dt-bindings: arm: qcom: document qcom,msm-id and + qcom,board-id + +The top level qcom,msm-id and qcom,board-id properties are utilized by +bootloaders on Qualcomm MSM platforms to determine which device tree +should be used and passed to the kernel. + +The commit b32e592d3c28 ("devicetree: bindings: Document qcom board +compatible format") from 2015 was a consensus during discussion about +upstreaming qcom,msm-id and qcom,board-id fields. There are however still +problems with that consensus: +1. It was reached 7 years ago but it turned out its implementation did + not reach all possible products. + +2. Initially additional tool (dtbTool) was needed for parsing these + fields to create a QCDT image consisting of multiple DTBs, later the + bootloaders were improved and they use these qcom,msm-id and + qcom,board-id properties directly. + +3. Extracting relevant information from the board compatible requires + this additional tool (dtbTool), which makes the build process more + complicated and not easily reproducible (DTBs are modified after the + kernel build). + +4. Some versions of Qualcomm bootloaders expect these properties even + when booting with a single DTB. The community is stuck with these + bootloaders thus they require properties in the DTBs. + +Since several upstreamed Qualcomm SoC-based boards require these +properties to properly boot and the properties are reportedly used by +bootloaders, document them along with the bindings header with constants +used by: bootloader, some DTS and socinfo driver. + +Link: https://lore.kernel.org/r/a3c932d1-a102-ce18-deea-18cbbd05ecab@linaro.org/ +Co-developed-by: Kumar Gala +Signed-off-by: Kumar Gala +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Rob Herring +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220830065744.161163-2-krzysztof.kozlowski@linaro.org +--- + include/dt-bindings/arm/qcom,ids.h | 155 +++++++++++++++++++++++++++++ + 1 file changed, 155 insertions(+) + create mode 100644 include/dt-bindings/arm/qcom,ids.h + +--- /dev/null ++++ b/include/dt-bindings/arm/qcom,ids.h +@@ -0,0 +1,155 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ ++/* ++ * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Linaro Ltd ++ * Author: Krzysztof Kozlowski based on previous work of Kumar Gala. ++ */ ++#ifndef _DT_BINDINGS_ARM_QCOM_IDS_H ++#define _DT_BINDINGS_ARM_QCOM_IDS_H ++ ++/* ++ * The MSM chipset and hardware revision used by Qualcomm bootloaders, DTS for ++ * older chipsets (qcom,msm-id) and in socinfo driver: ++ */ ++#define QCOM_ID_MSM8960 87 ++#define QCOM_ID_APQ8064 109 ++#define QCOM_ID_MSM8660A 122 ++#define QCOM_ID_MSM8260A 123 ++#define QCOM_ID_APQ8060A 124 ++#define QCOM_ID_MSM8974 126 ++#define QCOM_ID_MPQ8064 130 ++#define QCOM_ID_MSM8960AB 138 ++#define QCOM_ID_APQ8060AB 139 ++#define QCOM_ID_MSM8260AB 140 ++#define QCOM_ID_MSM8660AB 141 ++#define QCOM_ID_MSM8626 145 ++#define QCOM_ID_MSM8610 147 ++#define QCOM_ID_APQ8064AB 153 ++#define QCOM_ID_MSM8226 158 ++#define QCOM_ID_MSM8526 159 ++#define QCOM_ID_MSM8110 161 ++#define QCOM_ID_MSM8210 162 ++#define QCOM_ID_MSM8810 163 ++#define QCOM_ID_MSM8212 164 ++#define QCOM_ID_MSM8612 165 ++#define QCOM_ID_MSM8112 166 ++#define QCOM_ID_MSM8225Q 168 ++#define QCOM_ID_MSM8625Q 169 ++#define QCOM_ID_MSM8125Q 170 ++#define QCOM_ID_APQ8064AA 172 ++#define QCOM_ID_APQ8084 178 ++#define QCOM_ID_APQ8074 184 ++#define QCOM_ID_MSM8274 185 ++#define QCOM_ID_MSM8674 186 ++#define QCOM_ID_MSM8974PRO_AC 194 ++#define QCOM_ID_MSM8126 198 ++#define QCOM_ID_APQ8026 199 ++#define QCOM_ID_MSM8926 200 ++#define QCOM_ID_MSM8326 205 ++#define QCOM_ID_MSM8916 206 ++#define QCOM_ID_MSM8994 207 ++#define QCOM_ID_APQ8074PRO_AA 208 ++#define QCOM_ID_APQ8074PRO_AB 209 ++#define QCOM_ID_APQ8074PRO_AC 210 ++#define QCOM_ID_MSM8274PRO_AA 211 ++#define QCOM_ID_MSM8274PRO_AB 212 ++#define QCOM_ID_MSM8274PRO_AC 213 ++#define QCOM_ID_MSM8674PRO_AA 214 ++#define QCOM_ID_MSM8674PRO_AB 215 ++#define QCOM_ID_MSM8674PRO_AC 216 ++#define QCOM_ID_MSM8974PRO_AA 217 ++#define QCOM_ID_MSM8974PRO_AB 218 ++#define QCOM_ID_APQ8028 219 ++#define QCOM_ID_MSM8128 220 ++#define QCOM_ID_MSM8228 221 ++#define QCOM_ID_MSM8528 222 ++#define QCOM_ID_MSM8628 223 ++#define QCOM_ID_MSM8928 224 ++#define QCOM_ID_MSM8510 225 ++#define QCOM_ID_MSM8512 226 ++#define QCOM_ID_MSM8936 233 ++#define QCOM_ID_MSM8939 239 ++#define QCOM_ID_APQ8036 240 ++#define QCOM_ID_APQ8039 241 ++#define QCOM_ID_MSM8996 246 ++#define QCOM_ID_APQ8016 247 ++#define QCOM_ID_MSM8216 248 ++#define QCOM_ID_MSM8116 249 ++#define QCOM_ID_MSM8616 250 ++#define QCOM_ID_MSM8992 251 ++#define QCOM_ID_APQ8094 253 ++#define QCOM_ID_MDM9607 290 ++#define QCOM_ID_APQ8096 291 ++#define QCOM_ID_MSM8998 292 ++#define QCOM_ID_MSM8953 293 ++#define QCOM_ID_MDM8207 296 ++#define QCOM_ID_MDM9207 297 ++#define QCOM_ID_MDM9307 298 ++#define QCOM_ID_MDM9628 299 ++#define QCOM_ID_APQ8053 304 ++#define QCOM_ID_MSM8996SG 305 ++#define QCOM_ID_MSM8996AU 310 ++#define QCOM_ID_APQ8096AU 311 ++#define QCOM_ID_APQ8096SG 312 ++#define QCOM_ID_SDM660 317 ++#define QCOM_ID_SDM630 318 ++#define QCOM_ID_APQ8098 319 ++#define QCOM_ID_SDM845 321 ++#define QCOM_ID_MDM9206 322 ++#define QCOM_ID_IPQ8074 323 ++#define QCOM_ID_SDA660 324 ++#define QCOM_ID_SDM658 325 ++#define QCOM_ID_SDA658 326 ++#define QCOM_ID_SDA630 327 ++#define QCOM_ID_SDM450 338 ++#define QCOM_ID_SDA845 341 ++#define QCOM_ID_IPQ8072 342 ++#define QCOM_ID_IPQ8076 343 ++#define QCOM_ID_IPQ8078 344 ++#define QCOM_ID_SDM636 345 ++#define QCOM_ID_SDA636 346 ++#define QCOM_ID_SDM632 349 ++#define QCOM_ID_SDA632 350 ++#define QCOM_ID_SDA450 351 ++#define QCOM_ID_SM8250 356 ++#define QCOM_ID_IPQ8070 375 ++#define QCOM_ID_IPQ8071 376 ++#define QCOM_ID_IPQ8072A 389 ++#define QCOM_ID_IPQ8074A 390 ++#define QCOM_ID_IPQ8076A 391 ++#define QCOM_ID_IPQ8078A 392 ++#define QCOM_ID_SM6125 394 ++#define QCOM_ID_IPQ8070A 395 ++#define QCOM_ID_IPQ8071A 396 ++#define QCOM_ID_IPQ6018 402 ++#define QCOM_ID_IPQ6028 403 ++#define QCOM_ID_IPQ6000 421 ++#define QCOM_ID_IPQ6010 422 ++#define QCOM_ID_SC7180 425 ++#define QCOM_ID_SM6350 434 ++#define QCOM_ID_SM8350 439 ++#define QCOM_ID_SC8280XP 449 ++#define QCOM_ID_IPQ6005 453 ++#define QCOM_ID_QRB5165 455 ++#define QCOM_ID_SM8450 457 ++#define QCOM_ID_SM7225 459 ++#define QCOM_ID_SA8295P 460 ++#define QCOM_ID_SA8540P 461 ++#define QCOM_ID_SM8450_2 480 ++#define QCOM_ID_SM8450_3 482 ++#define QCOM_ID_SC7280 487 ++#define QCOM_ID_SC7180P 495 ++#define QCOM_ID_SM6375 507 ++ ++/* ++ * The board type and revision information, used by Qualcomm bootloaders and ++ * DTS for older chipsets (qcom,board-id): ++ */ ++#define QCOM_BOARD_ID(a, major, minor) \ ++ (((major & 0xff) << 16) | ((minor & 0xff) << 8) | QCOM_BOARD_ID_##a) ++ ++#define QCOM_BOARD_ID_MTP 8 ++#define QCOM_BOARD_ID_DRAGONBOARD 10 ++#define QCOM_BOARD_ID_SBC 24 ++ ++#endif /* _DT_BINDINGS_ARM_QCOM_IDS_H */ diff --git a/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch b/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch new file mode 100644 index 0000000000..394087a27a --- /dev/null +++ b/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch @@ -0,0 +1,171 @@ +From 7cbff3c3f867ff3b24de674f44ca03f54e416a37 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 31 Dec 2022 00:27:42 +0100 +Subject: [PATCH] soc: qcom: socinfo: move SMEM item struct and defines to a + header + +Move SMEM item struct and related defines to a header in order to be able +to reuse them in the Qualcomm NVMEM CPUFreq driver instead of duplicating +them. + +Signed-off-by: Robert Marko +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526204802.3081168-1-robimarko@gmail.com +--- + drivers/soc/qcom/socinfo.c | 58 +-------------------------- + include/linux/soc/qcom/socinfo.h | 67 ++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 57 deletions(-) + create mode 100644 include/linux/soc/qcom/socinfo.h + +--- a/drivers/soc/qcom/socinfo.c ++++ b/drivers/soc/qcom/socinfo.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -25,15 +26,6 @@ + #define SOCINFO_MINOR(ver) ((ver) & 0xffff) + #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) + +-#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 +-#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 +- +-/* +- * SMEM item id, used to acquire handles to respective +- * SMEM region. +- */ +-#define SMEM_HW_SW_BUILD_ID 137 +- + #ifdef CONFIG_DEBUG_FS + #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 + #define SMEM_IMAGE_VERSION_SIZE 4096 +@@ -116,54 +108,6 @@ static const char *const pmic_models[] = + }; + #endif /* CONFIG_DEBUG_FS */ + +-/* Socinfo SMEM item structure */ +-struct socinfo { +- __le32 fmt; +- __le32 id; +- __le32 ver; +- char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; +- /* Version 2 */ +- __le32 raw_id; +- __le32 raw_ver; +- /* Version 3 */ +- __le32 hw_plat; +- /* Version 4 */ +- __le32 plat_ver; +- /* Version 5 */ +- __le32 accessory_chip; +- /* Version 6 */ +- __le32 hw_plat_subtype; +- /* Version 7 */ +- __le32 pmic_model; +- __le32 pmic_die_rev; +- /* Version 8 */ +- __le32 pmic_model_1; +- __le32 pmic_die_rev_1; +- __le32 pmic_model_2; +- __le32 pmic_die_rev_2; +- /* Version 9 */ +- __le32 foundry_id; +- /* Version 10 */ +- __le32 serial_num; +- /* Version 11 */ +- __le32 num_pmics; +- __le32 pmic_array_offset; +- /* Version 12 */ +- __le32 chip_family; +- __le32 raw_device_family; +- __le32 raw_device_num; +- /* Version 13 */ +- __le32 nproduct_id; +- char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; +- /* Version 14 */ +- __le32 num_clusters; +- __le32 ncluster_array_offset; +- __le32 num_defective_parts; +- __le32 ndefective_parts_array_offset; +- /* Version 15 */ +- __le32 nmodem_supported; +-}; +- + #ifdef CONFIG_DEBUG_FS + struct socinfo_params { + u32 raw_device_family; +--- /dev/null ++++ b/include/linux/soc/qcom/socinfo.h +@@ -0,0 +1,67 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017-2019, Linaro Ltd. ++ */ ++ ++#ifndef __QCOM_SOCINFO_H__ ++#define __QCOM_SOCINFO_H__ ++ ++/* ++ * SMEM item id, used to acquire handles to respective ++ * SMEM region. ++ */ ++#define SMEM_HW_SW_BUILD_ID 137 ++ ++#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 ++#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 ++ ++/* Socinfo SMEM item structure */ ++struct socinfo { ++ __le32 fmt; ++ __le32 id; ++ __le32 ver; ++ char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; ++ /* Version 2 */ ++ __le32 raw_id; ++ __le32 raw_ver; ++ /* Version 3 */ ++ __le32 hw_plat; ++ /* Version 4 */ ++ __le32 plat_ver; ++ /* Version 5 */ ++ __le32 accessory_chip; ++ /* Version 6 */ ++ __le32 hw_plat_subtype; ++ /* Version 7 */ ++ __le32 pmic_model; ++ __le32 pmic_die_rev; ++ /* Version 8 */ ++ __le32 pmic_model_1; ++ __le32 pmic_die_rev_1; ++ __le32 pmic_model_2; ++ __le32 pmic_die_rev_2; ++ /* Version 9 */ ++ __le32 foundry_id; ++ /* Version 10 */ ++ __le32 serial_num; ++ /* Version 11 */ ++ __le32 num_pmics; ++ __le32 pmic_array_offset; ++ /* Version 12 */ ++ __le32 chip_family; ++ __le32 raw_device_family; ++ __le32 raw_device_num; ++ /* Version 13 */ ++ __le32 nproduct_id; ++ char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; ++ /* Version 14 */ ++ __le32 num_clusters; ++ __le32 ncluster_array_offset; ++ __le32 num_defective_parts; ++ __le32 ndefective_parts_array_offset; ++ /* Version 15 */ ++ __le32 nmodem_supported; ++}; ++ ++#endif diff --git a/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch b/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch new file mode 100644 index 0000000000..7c7c3f3635 --- /dev/null +++ b/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch @@ -0,0 +1,55 @@ +From 9f1bbff157a69db7684f5da2f73b2325c638a90e Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 26 May 2023 22:47:59 +0200 +Subject: [PATCH] soc: qcom: smem: Switch to EXPORT_SYMBOL_GPL() + +SMEM has been GPL licensed from the start, and there is no reason to use +EXPORT_SYMBOL() so switch to the GPL version. + +Signed-off-by: Robert Marko +Reviewed-by: Konrad Dybcio +Reviewed-by: Trilok Soni +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526204802.3081168-2-robimarko@gmail.com +--- + drivers/soc/qcom/smem.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/soc/qcom/smem.c ++++ b/drivers/soc/qcom/smem.c +@@ -500,7 +500,7 @@ int qcom_smem_alloc(unsigned host, unsig + + return ret; + } +-EXPORT_SYMBOL(qcom_smem_alloc); ++EXPORT_SYMBOL_GPL(qcom_smem_alloc); + + static void *qcom_smem_get_global(struct qcom_smem *smem, + unsigned item, +@@ -674,7 +674,7 @@ void *qcom_smem_get(unsigned host, unsig + return ptr; + + } +-EXPORT_SYMBOL(qcom_smem_get); ++EXPORT_SYMBOL_GPL(qcom_smem_get); + + /** + * qcom_smem_get_free_space() - retrieve amount of free space in a partition +@@ -719,7 +719,7 @@ int qcom_smem_get_free_space(unsigned ho + + return ret; + } +-EXPORT_SYMBOL(qcom_smem_get_free_space); ++EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); + + static bool addr_in_range(void __iomem *base, size_t size, void *addr) + { +@@ -770,7 +770,7 @@ phys_addr_t qcom_smem_virt_to_phys(void + + return 0; + } +-EXPORT_SYMBOL(qcom_smem_virt_to_phys); ++EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); + + static int qcom_smem_get_sbl_version(struct qcom_smem *smem) + { diff --git a/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch b/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch new file mode 100644 index 0000000000..4a816bb0f9 --- /dev/null +++ b/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch @@ -0,0 +1,70 @@ +From c3ecf2602a32d9b9e5fc997076c0d2836495c085 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 26 May 2023 22:48:00 +0200 +Subject: [PATCH] soc: qcom: smem: introduce qcom_smem_get_soc_id() + +Introduce a helper to return the SoC SMEM ID, which is used to identify the +exact SoC model as there may be differences in the same SoC family. + +Currently, cpufreq-nvmem does this completely in the driver and there has +been more interest expresed for other drivers to use this information so +lets expose a common helper to prevent redoing it in individual drivers +since this field is present on every SMEM table version. + +Signed-off-by: Robert Marko +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526204802.3081168-3-robimarko@gmail.com +--- + drivers/soc/qcom/smem.c | 23 +++++++++++++++++++++++ + include/linux/soc/qcom/smem.h | 2 ++ + 2 files changed, 25 insertions(+) + +--- a/drivers/soc/qcom/smem.c ++++ b/drivers/soc/qcom/smem.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + /* + * The Qualcomm shared memory system is a allocate only heap structure that +@@ -772,6 +773,28 @@ phys_addr_t qcom_smem_virt_to_phys(void + } + EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); + ++/** ++ * qcom_smem_get_soc_id() - return the SoC ID ++ * @id: On success, we return the SoC ID here. ++ * ++ * Look up SoC ID from HW/SW build ID and return it. ++ * ++ * Return: 0 on success, negative errno on failure. ++ */ ++int qcom_smem_get_soc_id(u32 *id) ++{ ++ struct socinfo *info; ++ ++ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); ++ if (IS_ERR(info)) ++ return PTR_ERR(info); ++ ++ *id = __le32_to_cpu(info->id); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); ++ + static int qcom_smem_get_sbl_version(struct qcom_smem *smem) + { + struct smem_header *header; +--- a/include/linux/soc/qcom/smem.h ++++ b/include/linux/soc/qcom/smem.h +@@ -11,4 +11,6 @@ int qcom_smem_get_free_space(unsigned ho + + phys_addr_t qcom_smem_virt_to_phys(void *p); + ++int qcom_smem_get_soc_id(u32 *id); ++ + #endif diff --git a/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch b/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch new file mode 100644 index 0000000000..9560122ccd --- /dev/null +++ b/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch @@ -0,0 +1,51 @@ +From 2b8634d1468ff498cc91b6adf993c27ae6fa079d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 26 May 2023 22:48:01 +0200 +Subject: [PATCH] cpufreq: qcom-nvmem: use SoC ID-s from bindings + +SMEM SoC ID-s are now stored in DT bindings so lets use those instead of +defining them in the driver again. + +Signed-off-by: Robert Marko +Reviewed-by: Konrad Dybcio +Reviewed-by: Bjorn Andersson +Acked-by: Viresh Kumar +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526204802.3081168-4-robimarko@gmail.com +--- + drivers/cpufreq/qcom-cpufreq-nvmem.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -31,12 +31,7 @@ + + #define MSM_ID_SMEM 137 + +-enum _msm_id { +- MSM8996V3 = 0xF6ul, +- APQ8096V3 = 0x123ul, +- MSM8996SG = 0x131ul, +- APQ8096SG = 0x138ul, +-}; ++#include + + enum _msm8996_version { + MSM8996_V3, +@@ -154,12 +149,12 @@ static enum _msm8996_version qcom_cpufre + msm_id++; + + switch ((enum _msm_id)*msm_id) { +- case MSM8996V3: +- case APQ8096V3: ++ case QCOM_ID_MSM8996: ++ case QCOM_ID_APQ8096: + version = MSM8996_V3; + break; +- case MSM8996SG: +- case APQ8096SG: ++ case QCOM_ID_MSM8996SG: ++ case QCOM_ID_APQ8096SG: + version = MSM8996_SG; + break; + default: diff --git a/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch b/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch new file mode 100644 index 0000000000..4f37d672ba --- /dev/null +++ b/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch @@ -0,0 +1,109 @@ +From e7992615acacc27baeec310197108143afc77337 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 26 May 2023 22:48:02 +0200 +Subject: [PATCH] cpufreq: qcom-nvmem: use helper to get SMEM SoC ID + +Now that SMEM exports a helper to get the SMEM SoC ID lets utilize it. +Currently qcom_cpufreq_get_msm_id() is encoding the returned SMEM SoC ID +into an enum, however there is no reason to do so and we can just match +directly on the SMEM SoC ID as returned by qcom_smem_get_soc_id(). + +Signed-off-by: Robert Marko +Acked-by: Viresh Kumar +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526204802.3081168-5-robimarko@gmail.com +--- + drivers/cpufreq/qcom-cpufreq-nvmem.c | 56 +++++----------------------- + 1 file changed, 10 insertions(+), 46 deletions(-) + +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -29,16 +29,8 @@ + #include + #include + +-#define MSM_ID_SMEM 137 +- + #include + +-enum _msm8996_version { +- MSM8996_V3, +- MSM8996_SG, +- NUM_OF_MSM8996_VERSIONS, +-}; +- + struct qcom_cpufreq_drv; + + struct qcom_cpufreq_match_data { +@@ -135,60 +127,32 @@ static void get_krait_bin_format_b(struc + dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver); + } + +-static enum _msm8996_version qcom_cpufreq_get_msm_id(void) +-{ +- size_t len; +- u32 *msm_id; +- enum _msm8996_version version; +- +- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); +- if (IS_ERR(msm_id)) +- return NUM_OF_MSM8996_VERSIONS; +- +- /* The first 4 bytes are format, next to them is the actual msm-id */ +- msm_id++; +- +- switch ((enum _msm_id)*msm_id) { +- case QCOM_ID_MSM8996: +- case QCOM_ID_APQ8096: +- version = MSM8996_V3; +- break; +- case QCOM_ID_MSM8996SG: +- case QCOM_ID_APQ8096SG: +- version = MSM8996_SG; +- break; +- default: +- version = NUM_OF_MSM8996_VERSIONS; +- } +- +- return version; +-} +- + static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, + struct nvmem_cell *speedbin_nvmem, + char **pvs_name, + struct qcom_cpufreq_drv *drv) + { + size_t len; ++ u32 msm_id; + u8 *speedbin; +- enum _msm8996_version msm8996_version; ++ int ret; + *pvs_name = NULL; + +- msm8996_version = qcom_cpufreq_get_msm_id(); +- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { +- dev_err(cpu_dev, "Not Snapdragon 820/821!"); +- return -ENODEV; +- } ++ ret = qcom_smem_get_soc_id(&msm_id); ++ if (ret) ++ return ret; + + speedbin = nvmem_cell_read(speedbin_nvmem, &len); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + +- switch (msm8996_version) { +- case MSM8996_V3: ++ switch (msm_id) { ++ case QCOM_ID_MSM8996: ++ case QCOM_ID_APQ8096: + drv->versions = 1 << (unsigned int)(*speedbin); + break; +- case MSM8996_SG: ++ case QCOM_ID_MSM8996SG: ++ case QCOM_ID_APQ8096SG: + drv->versions = 1 << ((unsigned int)(*speedbin) + 4); + break; + default: diff --git a/target/linux/generic/backport-6.6/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch b/target/linux/generic/backport-6.6/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch new file mode 100644 index 0000000000..ddda6e4e78 --- /dev/null +++ b/target/linux/generic/backport-6.6/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch @@ -0,0 +1,93 @@ +From edd25a77e69b7c546c28077e5dffe72c54c0afe8 Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Thu, 21 Sep 2023 22:18:12 +0200 +Subject: [PATCH 2/4] rtc: rtc7301: Support byte-addressed IO + +The old RTC7301 driver in OpenWrt used byte access, but the +current mainline Linux driver uses 32bit word access. + +Make this configurable using device properties using the +standard property "reg-io-width" in e.g. device tree. + +This is needed for the USRobotics USR8200 which has the +chip connected using byte accesses. + +Debugging and testing by Howard Harte. + +Signed-off-by: Linus Walleij +--- + drivers/rtc/rtc-r7301.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-r7301.c ++++ b/drivers/rtc/rtc-r7301.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -55,12 +56,23 @@ struct rtc7301_priv { + u8 bank; + }; + +-static const struct regmap_config rtc7301_regmap_config = { ++/* ++ * When the device is memory-mapped, some platforms pack the registers into ++ * 32-bit access using the lower 8 bits at each 4-byte stride, while others ++ * expose them as simply consecutive bytes. ++ */ ++static const struct regmap_config rtc7301_regmap_32_config = { + .reg_bits = 32, + .val_bits = 8, + .reg_stride = 4, + }; + ++static const struct regmap_config rtc7301_regmap_8_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .reg_stride = 1, ++}; ++ + static u8 rtc7301_read(struct rtc7301_priv *priv, unsigned int reg) + { + int reg_stride = regmap_get_reg_stride(priv->regmap); +@@ -356,7 +368,9 @@ static int __init rtc7301_rtc_probe(stru + void __iomem *regs; + struct rtc7301_priv *priv; + struct rtc_device *rtc; ++ static const struct regmap_config *mapconf; + int ret; ++ u32 val; + + priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -366,8 +380,25 @@ static int __init rtc7301_rtc_probe(stru + if (IS_ERR(regs)) + return PTR_ERR(regs); + ++ ret = device_property_read_u32(&dev->dev, "reg-io-width", &val); ++ if (ret) ++ /* Default to 32bit accesses */ ++ val = 4; ++ ++ switch (val) { ++ case 1: ++ mapconf = &rtc7301_regmap_8_config; ++ break; ++ case 4: ++ mapconf = &rtc7301_regmap_32_config; ++ break; ++ default: ++ dev_err(&dev->dev, "invalid reg-io-width %d\n", val); ++ return -EINVAL; ++ } ++ + priv->regmap = devm_regmap_init_mmio(&dev->dev, regs, +- &rtc7301_regmap_config); ++ mapconf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + diff --git a/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch b/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch new file mode 100644 index 0000000000..2969462838 --- /dev/null +++ b/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch @@ -0,0 +1,82 @@ +From 49e5663b505070424e18099841943f34342aa405 Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Sun, 24 Sep 2023 01:09:01 +0200 +Subject: [PATCH] net: phy: amd: Support the Altima AMI101L + +The Altima AC101L is obviously compatible with the AMD PHY, +as seen by reading the datasheet. + +Datasheet: https://docs.broadcom.com/doc/AC101L-DS05-405-RDS.pdf + +Signed-off-by: Linus Walleij +--- + drivers/net/phy/Kconfig | 4 ++-- + drivers/net/phy/amd.c | 33 +++++++++++++++++++++++---------- + 2 files changed, 25 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -72,9 +72,9 @@ config SFP + comment "MII PHY device drivers" + + config AMD_PHY +- tristate "AMD PHYs" ++ tristate "AMD and Altima PHYs" + help +- Currently supports the am79c874 ++ Currently supports the AMD am79c874 and Altima AC101L. + + config MESON_GXL_PHY + tristate "Amlogic Meson GXL Internal PHY" +--- a/drivers/net/phy/amd.c ++++ b/drivers/net/phy/amd.c +@@ -13,6 +13,7 @@ + #include + #include + ++#define PHY_ID_AC101L 0x00225520 + #define PHY_ID_AM79C874 0x0022561b + + #define MII_AM79C_IR 17 /* Interrupt Status/Control Register */ +@@ -87,19 +88,31 @@ static irqreturn_t am79c_handle_interrup + return IRQ_HANDLED; + } + +-static struct phy_driver am79c_driver[] = { { +- .phy_id = PHY_ID_AM79C874, +- .name = "AM79C874", +- .phy_id_mask = 0xfffffff0, +- /* PHY_BASIC_FEATURES */ +- .config_init = am79c_config_init, +- .config_intr = am79c_config_intr, +- .handle_interrupt = am79c_handle_interrupt, +-} }; ++static struct phy_driver am79c_drivers[] = { ++ { ++ .phy_id = PHY_ID_AM79C874, ++ .name = "AM79C874", ++ .phy_id_mask = 0xfffffff0, ++ /* PHY_BASIC_FEATURES */ ++ .config_init = am79c_config_init, ++ .config_intr = am79c_config_intr, ++ .handle_interrupt = am79c_handle_interrupt, ++ }, ++ { ++ .phy_id = PHY_ID_AC101L, ++ .name = "AC101L", ++ .phy_id_mask = 0xfffffff0, ++ /* PHY_BASIC_FEATURES */ ++ .config_init = am79c_config_init, ++ .config_intr = am79c_config_intr, ++ .handle_interrupt = am79c_handle_interrupt, ++ }, ++}; + +-module_phy_driver(am79c_driver); ++module_phy_driver(am79c_drivers); + + static struct mdio_device_id __maybe_unused amd_tbl[] = { ++ { PHY_ID_AC101L, 0xfffffff0 }, + { PHY_ID_AM79C874, 0xfffffff0 }, + { } + }; diff --git a/target/linux/generic/backport-6.6/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch b/target/linux/generic/backport-6.6/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch new file mode 100644 index 0000000000..b71df6fa57 --- /dev/null +++ b/target/linux/generic/backport-6.6/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch @@ -0,0 +1,29 @@ +From a067943129b4ec6b835e02cfd5fbef01093c1471 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sun, 8 Oct 2023 16:40:13 +0200 +Subject: [PATCH] leds: core: Add more colors from DT bindings to led_colors + +The colors are already part of DT bindings. Make sure the kernel is +able to convert them to strings. + +Signed-off-by: Ondrej Jirman +Link: https://lore.kernel.org/r/20231008144014.1180334-1-megi@xff.cz +Signed-off-by: Lee Jones +--- + drivers/leds/led-core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/leds/led-core.c ++++ b/drivers/leds/led-core.c +@@ -36,6 +36,11 @@ const char * const led_colors[LED_COLOR_ + [LED_COLOR_ID_IR] = "ir", + [LED_COLOR_ID_MULTI] = "multicolor", + [LED_COLOR_ID_RGB] = "rgb", ++ [LED_COLOR_ID_PURPLE] = "purple", ++ [LED_COLOR_ID_ORANGE] = "orange", ++ [LED_COLOR_ID_PINK] = "pink", ++ [LED_COLOR_ID_CYAN] = "cyan", ++ [LED_COLOR_ID_LIME] = "lime", + }; + EXPORT_SYMBOL_GPL(led_colors); + diff --git a/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch b/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch new file mode 100644 index 0000000000..1c8e014a1a --- /dev/null +++ b/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch @@ -0,0 +1,111 @@ +From bc8e1da69a68d9871773b657d18400a7941cbdef Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 28 Nov 2023 04:00:10 +0000 +Subject: [PATCH] leds: trigger: netdev: Extend speeds up to 10G + +Add 2.5G, 5G and 10G as available speeds to the netdev LED trigger. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/99e7d3304c6bba7f4863a4a80764a869855f2085.1701143925.git.daniel@makrotopia.org +Signed-off-by: Lee Jones +--- + drivers/leds/trigger/ledtrig-netdev.c | 32 ++++++++++++++++++++++++++- + include/linux/leds.h | 3 +++ + 2 files changed, 34 insertions(+), 1 deletion(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -99,6 +99,18 @@ static void set_baseline_state(struct le + trigger_data->link_speed == SPEED_1000) + blink_on = true; + ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_2500) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_5000) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_10000) ++ blink_on = true; ++ + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && + trigger_data->duplex == DUPLEX_HALF) + blink_on = true; +@@ -286,6 +298,9 @@ static ssize_t netdev_led_attr_show(stru + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_LINK_2500: ++ case TRIGGER_NETDEV_LINK_5000: ++ case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: +@@ -316,6 +331,9 @@ static ssize_t netdev_led_attr_store(str + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_LINK_2500: ++ case TRIGGER_NETDEV_LINK_5000: ++ case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: +@@ -334,7 +352,10 @@ static ssize_t netdev_led_attr_store(str + if (test_bit(TRIGGER_NETDEV_LINK, &mode) && + (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &mode) || +- test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) ++ test_bit(TRIGGER_NETDEV_LINK_1000, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_2500, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_5000, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_10000, &mode))) + return -EINVAL; + + cancel_delayed_work_sync(&trigger_data->work); +@@ -364,6 +385,9 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD + DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); + DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); + DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); ++DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500); ++DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000); ++DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000); + DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); + DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); + DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); +@@ -422,6 +446,9 @@ static struct attribute *netdev_trig_att + &dev_attr_link_10.attr, + &dev_attr_link_100.attr, + &dev_attr_link_1000.attr, ++ &dev_attr_link_2500.attr, ++ &dev_attr_link_5000.attr, ++ &dev_attr_link_10000.attr, + &dev_attr_full_duplex.attr, + &dev_attr_half_duplex.attr, + &dev_attr_rx.attr, +@@ -519,6 +546,9 @@ static void netdev_trig_work(struct work + test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); + interval = jiffies_to_msecs( +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -533,6 +533,9 @@ enum led_trigger_netdev_modes { + TRIGGER_NETDEV_LINK_10, + TRIGGER_NETDEV_LINK_100, + TRIGGER_NETDEV_LINK_1000, ++ TRIGGER_NETDEV_LINK_2500, ++ TRIGGER_NETDEV_LINK_5000, ++ TRIGGER_NETDEV_LINK_10000, + TRIGGER_NETDEV_HALF_DUPLEX, + TRIGGER_NETDEV_FULL_DUPLEX, + TRIGGER_NETDEV_TX, diff --git a/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch new file mode 100644 index 0000000000..0182e6d1a2 --- /dev/null +++ b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch @@ -0,0 +1,98 @@ +From 7ae215ee7bb855f13c80565470fc7f67db4ba82f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 25 Jan 2024 21:36:59 +0100 +Subject: [PATCH 3/5] net: phy: add support for PHY LEDs polarity modes + +Add support for PHY LEDs polarity modes. Some PHY require LED to be set +to active low to be turned ON. Adds support for this by declaring +active-low property in DT. + +PHY driver needs to declare .led_polarity_set() to configure LED +polarity modes. Function will pass the index with the LED index and a +bitmap with all the required modes to set. + +Current supported modes are: +- active-low with the flag PHY_LED_ACTIVE_LOW. LED is set to active-low + to turn it ON. +- inactive-high-impedance with the flag PHY_LED_INACTIVE_HIGH_IMPEDANCE. + LED is set to high impedance to turn it OFF. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 16 ++++++++++++++++ + include/linux/phy.h | 22 ++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3138,6 +3138,7 @@ static int of_phy_led(struct phy_device + struct device *dev = &phydev->mdio.dev; + struct led_init_data init_data = {}; + struct led_classdev *cdev; ++ unsigned long modes = 0; + struct phy_led *phyled; + u32 index; + int err; +@@ -3155,6 +3156,21 @@ static int of_phy_led(struct phy_device + if (index > U8_MAX) + return -EINVAL; + ++ if (of_property_read_bool(led, "active-low")) ++ set_bit(PHY_LED_ACTIVE_LOW, &modes); ++ if (of_property_read_bool(led, "inactive-high-impedance")) ++ set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes); ++ ++ if (modes) { ++ /* Return error if asked to set polarity modes but not supported */ ++ if (!phydev->drv->led_polarity_set) ++ return -EINVAL; ++ ++ err = phydev->drv->led_polarity_set(phydev, index, modes); ++ if (err) ++ return err; ++ } ++ + phyled->index = index; + if (phydev->drv->led_brightness_set) + cdev->brightness_set_blocking = phy_led_set_brightness; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -791,6 +791,15 @@ struct phy_led { + + #define to_phy_led(d) container_of(d, struct phy_led, led_cdev) + ++/* Modes for PHY LED configuration */ ++enum phy_led_modes { ++ PHY_LED_ACTIVE_LOW = 0, ++ PHY_LED_INACTIVE_HIGH_IMPEDANCE = 1, ++ ++ /* keep it last */ ++ __PHY_LED_MODES_NUM, ++}; ++ + /** + * struct phy_driver - Driver structure for a particular PHY type + * +@@ -1059,6 +1068,19 @@ struct phy_driver { + int (*led_hw_control_get)(struct phy_device *dev, u8 index, + unsigned long *rules); + ++ /** ++ * @led_polarity_set: Set the LED polarity modes ++ * @dev: PHY device which has the LED ++ * @index: Which LED of the PHY device ++ * @modes: bitmap of LED polarity modes ++ * ++ * Configure LED with all the required polarity modes in @modes ++ * to make it correctly turn ON or OFF. ++ * ++ * Returns 0, or an error code. ++ */ ++ int (*led_polarity_set)(struct phy_device *dev, int index, ++ unsigned long modes); + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch b/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch new file mode 100644 index 0000000000..cbb9172032 --- /dev/null +++ b/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch @@ -0,0 +1,170 @@ +From fe2b1226656afae56702d1d84c6900f6b67df297 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Fri, 1 Dec 2023 11:23:22 +0100 +Subject: [PATCH] leds: trigger: netdev: fix RTNL handling to prevent potential + deadlock + +When working on LED support for r8169 I got the following lockdep +warning. Easiest way to prevent this scenario seems to be to take +the RTNL lock before the trigger_data lock in set_device_name(). + +====================================================== +WARNING: possible circular locking dependency detected +6.7.0-rc2-next-20231124+ #2 Not tainted +------------------------------------------------------ +bash/383 is trying to acquire lock: +ffff888103aa1c68 (&trigger_data->lock){+.+.}-{3:3}, at: netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + +but task is already holding lock: +ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +-> #1 (rtnl_mutex){+.+.}-{3:3}: + __mutex_lock+0x9b/0xb50 + mutex_lock_nested+0x16/0x20 + rtnl_lock+0x12/0x20 + set_device_name+0xa9/0x120 [ledtrig_netdev] + netdev_trig_activate+0x1a1/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 + +-> #0 (&trigger_data->lock){+.+.}-{3:3}: + __lock_acquire+0x1459/0x25a0 + lock_acquire+0xc8/0x2d0 + __mutex_lock+0x9b/0xb50 + mutex_lock_nested+0x16/0x20 + netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + call_netdevice_register_net_notifiers+0x5a/0x100 + register_netdevice_notifier+0x85/0x120 + netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 + +other info that might help us debug this: + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(rtnl_mutex); + lock(&trigger_data->lock); + lock(rtnl_mutex); + lock(&trigger_data->lock); + + *** DEADLOCK *** + +8 locks held by bash/383: + #0: ffff888103ff33f0 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x6c/0xf0 + #1: ffff888103aa1e88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x114/0x210 + #2: ffff8881036f1890 (kn->active#82){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x11d/0x210 + #3: ffff888108e2c358 (&led_cdev->led_access){+.+.}-{3:3}, at: led_trigger_write+0x30/0x140 + #4: ffffffff8cdd9e10 (triggers_list_lock){++++}-{3:3}, at: led_trigger_write+0x75/0x140 + #5: ffff888108e2c270 (&led_cdev->trigger_lock){++++}-{3:3}, at: led_trigger_write+0xe3/0x140 + #6: ffffffff8cdde3d0 (pernet_ops_rwsem){++++}-{3:3}, at: register_netdevice_notifier+0x1c/0x120 + #7: ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 + +stack backtrace: +CPU: 0 PID: 383 Comm: bash Not tainted 6.7.0-rc2-next-20231124+ #2 +Hardware name: Default string Default string/Default string, BIOS ADLN.M6.SODIMM.ZB.CY.015 08/08/2023 +Call Trace: + + dump_stack_lvl+0x5c/0xd0 + dump_stack+0x10/0x20 + print_circular_bug+0x2dd/0x410 + check_noncircular+0x131/0x150 + __lock_acquire+0x1459/0x25a0 + lock_acquire+0xc8/0x2d0 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + __mutex_lock+0x9b/0xb50 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + ? __this_cpu_preempt_check+0x13/0x20 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + ? __cancel_work_timer+0x11c/0x1b0 + ? __mutex_lock+0x123/0xb50 + mutex_lock_nested+0x16/0x20 + ? mutex_lock_nested+0x16/0x20 + netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + call_netdevice_register_net_notifiers+0x5a/0x100 + register_netdevice_notifier+0x85/0x120 + netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + ? preempt_count_add+0x49/0xc0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 +RIP: 0033:0x7f269055d034 +Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d 35 c3 0d 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 48 89 54 24 18 48 +RSP: 002b:00007ffddb7ef748 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 00007f269055d034 +RDX: 0000000000000007 RSI: 000055bf5f4af3c0 RDI: 0000000000000001 +RBP: 000055bf5f4af3c0 R08: 0000000000000073 R09: 0000000000000001 +R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000007 +R13: 00007f26906325c0 R14: 00007f269062ff20 R15: 0000000000000000 + + +Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") +Cc: stable@vger.kernel.org +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Acked-by: Lee Jones +Link: https://lore.kernel.org/r/fb5c8294-2a10-4bf5-8f10-3d2b77d2757e@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -235,6 +235,11 @@ static int set_device_name(struct led_ne + { + cancel_delayed_work_sync(&trigger_data->work); + ++ /* ++ * Take RTNL lock before trigger_data lock to prevent potential ++ * deadlock with netdev notifier registration. ++ */ ++ rtnl_lock(); + mutex_lock(&trigger_data->lock); + + if (trigger_data->net_dev) { +@@ -254,16 +259,14 @@ static int set_device_name(struct led_ne + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; + trigger_data->duplex = DUPLEX_UNKNOWN; +- if (trigger_data->net_dev != NULL) { +- rtnl_lock(); ++ if (trigger_data->net_dev) + get_device_state(trigger_data); +- rtnl_unlock(); +- } + + trigger_data->last_activity = 0; + + set_baseline_state(trigger_data); + mutex_unlock(&trigger_data->lock); ++ rtnl_unlock(); + + return 0; + } diff --git a/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch b/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch new file mode 100644 index 0000000000..51b4bbbfcb --- /dev/null +++ b/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch @@ -0,0 +1,43 @@ +From 9b78d919632b7149d311aaad5a977e4b48b10321 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Wed, 26 Apr 2023 10:15:31 +0200 +Subject: [PATCH] net: phy: hide the PHYLIB_LEDS knob + +commit 4bb7aac70b5d ("net: phy: fix circular LEDS_CLASS dependencies") +solved a build failure, but introduces a new config knob with a default +'y' value: PHYLIB_LEDS. + +The latter is against the current new config policy. The exception +was raised to allow the user to catch bad configurations without led +support. + +Anyway the current definition of PHYLIB_LEDS does not fit the above +goal: if LEDS_CLASS is disabled, the new config will be available +only with PHYLIB disabled, too. + +Hide the mentioned config, to preserve the randconfig testing done so +far, while respecting the mentioned policy. + +Suggested-by: Andrew Lunn +Suggested-by: Arnd Bergmann +Signed-off-by: Paolo Abeni +Link: https://lore.kernel.org/r/d82489be8ed911c383c3447e9abf469995ccf39a.1682496488.git.pabeni@redhat.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/Kconfig | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -45,10 +45,8 @@ config LED_TRIGGER_PHY + for any speed known to the PHY. + + config PHYLIB_LEDS +- bool "Support probing LEDs from device tree" ++ def_bool OF + depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB +- depends on OF +- default y + help + When LED class support is enabled, phylib can automatically + probe LED setting from device tree. diff --git a/target/linux/generic/backport-6.6/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch b/target/linux/generic/backport-6.6/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch new file mode 100644 index 0000000000..8d391678ff --- /dev/null +++ b/target/linux/generic/backport-6.6/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch @@ -0,0 +1,55 @@ +From 12ce20e02e532f101b725d71c52a36c5cc8ad1e6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 4 Feb 2024 00:54:01 +0100 +Subject: [PATCH] leds: trigger: netdev: Fix kernel panic on interface rename + trig notify + +Commit d5e01266e7f5 ("leds: trigger: netdev: add additional specific link +speed mode") in the various changes, reworked the way to set the LINKUP +mode in commit cee4bd16c319 ("leds: trigger: netdev: Recheck +NETDEV_LED_MODE_LINKUP on dev rename") and moved it to a generic function. + +This changed the logic where, in the previous implementation the dev +from the trigger event was used to check if the carrier was ok, but in +the new implementation with the generic function, the dev in +trigger_data is used instead. + +This is problematic and cause a possible kernel panic due to the fact +that the dev in the trigger_data still reference the old one as the +new one (passed from the trigger event) still has to be hold and saved +in the trigger_data struct (done in the NETDEV_REGISTER case). + +On calling of get_device_state(), an invalid net_dev is used and this +cause a kernel panic. + +To handle this correctly, move the call to get_device_state() after the +new net_dev is correctly set in trigger_data (in the NETDEV_REGISTER +case) and correctly parse the new dev. + +Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") +Cc: stable@vger.kernel.org +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240203235413.1146-1-ansuelsmth@gmail.com +Signed-off-by: Lee Jones +--- + drivers/leds/trigger/ledtrig-netdev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -489,12 +489,12 @@ static int netdev_trig_notify(struct not + trigger_data->duplex = DUPLEX_UNKNOWN; + switch (evt) { + case NETDEV_CHANGENAME: +- get_device_state(trigger_data); +- fallthrough; + case NETDEV_REGISTER: + dev_put(trigger_data->net_dev); + dev_hold(dev); + trigger_data->net_dev = dev; ++ if (evt == NETDEV_CHANGENAME) ++ get_device_state(trigger_data); + break; + case NETDEV_UNREGISTER: + dev_put(trigger_data->net_dev); diff --git a/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch b/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch new file mode 100644 index 0000000000..38fbc3a3d7 --- /dev/null +++ b/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch @@ -0,0 +1,40 @@ +From dbf70fc204d2fbb0d8ad8f42038a60846502efda Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 10 Oct 2022 13:51:09 +0300 +Subject: [PATCH] mtd: spinand: winbond: fix flash identification + +Winbond uses 3 bytes to identify flash: vendor_id, dev_id_0, dev_id_1, +but current driver uses only first 2 bytes of it for devices +identification. As result Winbond W25N02KV flash (id_bytes: EF, AA, 22) +is identified as W25N01GV (id_bytes: EF, AA, 21). + +Fix this by adding missed identification bytes. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: Frieder Schrempf +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-1-mikhail.kshevetskiy@iopsys.eu +--- + drivers/mtd/nand/spi/winbond.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/nand/spi/winbond.c ++++ b/drivers/mtd/nand/spi/winbond.c +@@ -76,7 +76,7 @@ static int w25m02gv_select_target(struct + + static const struct spinand_info winbond_spinand_table[] = { + SPINAND_INFO("W25M02GV", +- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab), ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -86,7 +86,7 @@ static const struct spinand_info winbond + SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), + SPINAND_SELECT_TARGET(w25m02gv_select_target)), + SPINAND_INFO("W25N01GV", +- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa), ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, diff --git a/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch b/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch new file mode 100644 index 0000000000..d75a1acc57 --- /dev/null +++ b/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch @@ -0,0 +1,106 @@ +From 6154c7a583483d7b69f53bea868efdc369edd563 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 10 Oct 2022 13:51:10 +0300 +Subject: [PATCH] mtd: spinand: winbond: add Winbond W25N02KV flash support + +Add support of Winbond W25N02KV flash + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: Frieder Schrempf +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-2-mikhail.kshevetskiy@iopsys.eu +--- + drivers/mtd/nand/spi/winbond.c | 75 ++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +--- a/drivers/mtd/nand/spi/winbond.c ++++ b/drivers/mtd/nand/spi/winbond.c +@@ -74,6 +74,72 @@ static int w25m02gv_select_target(struct + return spi_mem_exec_op(spinand->spimem, &op); + } + ++static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = 64 + (16 * section); ++ region->length = 13; ++ ++ return 0; ++} ++ ++static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 2; ++ region->length = 14; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { ++ .ecc = w25n02kv_ooblayout_ecc, ++ .free = w25n02kv_ooblayout_free, ++}; ++ ++static int w25n02kv_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ struct nand_device *nand = spinand_to_nand(spinand); ++ u8 mbf = 0; ++ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); ++ ++ switch (status & STATUS_ECC_MASK) { ++ case STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ case STATUS_ECC_HAS_BITFLIPS: ++ /* ++ * Let's try to retrieve the real maximum number of bitflips ++ * in order to avoid forcing the wear-leveling layer to move ++ * data around if it's not necessary. ++ */ ++ if (spi_mem_exec_op(spinand->spimem, &op)) ++ return nanddev_get_ecc_conf(nand)->strength; ++ ++ mbf >>= 4; ++ ++ if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) ++ return nanddev_get_ecc_conf(nand)->strength; ++ ++ return mbf; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static const struct spinand_info winbond_spinand_table[] = { + SPINAND_INFO("W25M02GV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), +@@ -94,6 +160,15 @@ static const struct spinand_info winbond + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), ++ SPINAND_INFO("W25N02KV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + }; + + static int winbond_spinand_init(struct spinand_device *spinand) diff --git a/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch b/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch new file mode 100644 index 0000000000..2f408f5a30 --- /dev/null +++ b/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch @@ -0,0 +1,49 @@ +From f5a05060670a4d8d6523afc7963eb559c2e3615f Mon Sep 17 00:00:00 2001 +From: Olivier Maignial +Date: Fri, 23 Jun 2023 17:33:37 +0200 +Subject: [PATCH] mtd: spinand: winbond: Fix ecc_get_status + +Reading ECC status is failing. + +w25n02kv_ecc_get_status() is using on-stack buffer for +SPINAND_GET_FEATURE_OP() output. It is not suitable for +DMA needs of spi-mem. + +Fix this by using the spi-mem operations dedicated buffer +spinand->scratchbuf. + +See +spinand->scratchbuf: +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/mtd/spinand.h?h=v6.3#n418 +spi_mem_check_op(): +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/spi/spi-mem.c?h=v6.3#n199 + +Fixes: 6154c7a58348 ("mtd: spinand: winbond: add Winbond W25N02KV flash support") +Cc: stable@vger.kernel.org +Signed-off-by: Olivier Maignial +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/DB4P250MB1032EDB9E36B764A33769039FE23A@DB4P250MB1032.EURP250.PROD.OUTLOOK.COM +--- + drivers/mtd/nand/spi/winbond.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/nand/spi/winbond.c ++++ b/drivers/mtd/nand/spi/winbond.c +@@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struc + { + struct nand_device *nand = spinand_to_nand(spinand); + u8 mbf = 0; +- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); ++ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); + + switch (status & STATUS_ECC_MASK) { + case STATUS_ECC_NO_BITFLIPS: +@@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struc + if (spi_mem_exec_op(spinand->spimem, &op)) + return nanddev_get_ecc_conf(nand)->strength; + +- mbf >>= 4; ++ mbf = *(spinand->scratchbuf) >> 4; + + if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) + return nanddev_get_ecc_conf(nand)->strength; diff --git a/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch new file mode 100644 index 0000000000..5094a6d774 --- /dev/null +++ b/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -0,0 +1,139 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sMUeie/T" +Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84BB8D6D + for ; Wed, 6 Dec 2023 15:16:16 -0800 (PST) +Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-db5416d0fccso403298276.1 + for ; Wed, 06 Dec 2023 15:16:16 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20230601; t=1701904575; x=1702509375; darn=vger.kernel.org; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=sMUeie/TxdytzC0EyT11QWi1TqTtiv7KCTs1F2vLmUUvPKNA3+1MHFo8ECW+0gQuDE + FGrgdZKGK5mXQgkF0N3JiSLvKO8tpQOIB57JLCG5IVy5dr2vVv0ExU3Dag2Cc4oBIBIO + w/cH95O1oPlvluIpATmAsxenVr7mFomU63BqYiRGLaEhWeb2hJ636GO8lubtsDfdFFoi + GPOL2tQwV93VnqmywBBpFaNAULN0UoCFhfkKv5prvpkXq19sWI7zyorVZ+rdTYem5m4T + dXsDaLXPtC3Dh2JOad1duSQIah/wCHYYUcV3IoFhwj2y0Uk/TTCrnZPORweSADcEy6Ho + vDrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1701904575; x=1702509375; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=Dmc6aSntxPlxAk72zVO1G9WoZnFtLolxENlLscYYAHG3VE+PQ8gGN2rPzcGoKb2Btb + 4b0PvjOzSlPQyghahdhdlz04RtAeeGG/MkfNiYjFql5OifIoovb51kroiPYrVsa7Ps7Y + +Pxug0+NPdTm5s9TNz940ZKl3GRME8UTmVxpWJRX03XMOqb6Wgsh2SK9ahXKc4yRsi62 + 3a3J72WmmSgvimxwM/99fXwvoUQpiv2J1xCoqc1Ng4q4qSuZvzmHN7ZTGaUhLxOqLeLK + 3W4RKHW6rZ7UjppuB6I3NXW+D344By2rdKp1sRXpjdQ0GS3YUcvlRETcJBXJudHfQP5Y + CLOw== +X-Gm-Message-State: AOJu0YzdCTLdwny+N99zeMgyKqFsEZhfIhL2cbgKA6zC1U/OLkxxRLoM + XrYVBC9DmxCGmP4o+M/Z/kHUew/9faHlCiLGxw== +X-Google-Smtp-Source: AGHT+IFRXxBV6JuX5Cl/k2o1+WKkCwkR8j20MJSkmoGCedPAtqFttH8OVh1/6vdfnq8MPN++A2h89peZQhyG8OsJ8A== +X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) + (user=justinstitt job=sendgmr) by 2002:a25:dac7:0:b0:da0:3117:f35 with SMTP + id n190-20020a25dac7000000b00da031170f35mr28652ybf.3.1701904575576; Wed, 06 + Dec 2023 15:16:15 -0800 (PST) +Date: Wed, 06 Dec 2023 23:16:10 +0000 +In-Reply-To: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +Precedence: bulk +X-Mailing-List: bpf@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +Mime-Version: 1.0 +References: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= +X-Developer-Signature: v=1; a=ed25519-sha256; t=1701904573; l=1840; + i=justinstitt@google.com; s=20230717; h=from:subject:message-id; + bh=UMdetIL2ZsPIkSodqhw2fM21NHJVjCu0lRImFuNhVoM=; b=a8rMnXfVVQ5gsxHWG4WRMwOLxZgflqXZtNuKx26vv4DwYvvCtCiYjl3f1frOjV/Ul2kaxq5g/ + b/UOv678JKCDASVokxG5GJifAnU7/kqRxdhcwfRkrD8RUfcsmiZOfyF +X-Mailer: b4 0.12.3 +Message-ID: <20231206-ethtool_puts_impl-v5-1-5a2528e17bf8@google.com> +Subject: [PATCH net-next v5 1/3] ethtool: Implement ethtool_puts() +From: justinstitt@google.com +To: "David S. Miller" , Eric Dumazet , + Jakub Kicinski , Paolo Abeni , Shay Agroskin , + Arthur Kiyanovski , David Arinzon , Noam Dagan , + Saeed Bishara , Rasesh Mody , + Sudarsana Kalluru , GR-Linux-NIC-Dev@marvell.com, + Dimitris Michailidis , Yisen Zhuang , + Salil Mehta , Jesse Brandeburg , + Tony Nguyen , Louis Peens , + Shannon Nelson , Brett Creeley , drivers@pensando.io, + "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , + Dexuan Cui , Ronak Doshi , + VMware PV-Drivers Reviewers , Andy Whitcroft , Joe Perches , + Dwaipayan Ray , Lukas Bulwahn , + Hauke Mehrtens , Andrew Lunn , + Florian Fainelli , Vladimir Oltean , + "=?utf-8?q?Ar=C4=B1n=C3=A7_=C3=9CNAL?=" , Daniel Golle , + Landen Chao , DENG Qingfang , + Sean Wang , Matthias Brugger , + AngeloGioacchino Del Regno , + Linus Walleij , + "=?utf-8?q?Alvin_=C5=A0ipraga?=" , Wei Fang , + Shenwei Wang , Clark Wang , + NXP Linux Team , Lars Povlsen , + Steen Hegelund , Daniel Machon , + UNGLinuxDriver@microchip.com, Jiawen Wu , + Mengyuan Lou , Heiner Kallweit , + Russell King , Alexei Starovoitov , + Daniel Borkmann , Jesper Dangaard Brouer , + John Fastabend +Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, + Nick Desaulniers , Nathan Chancellor , + Kees Cook , intel-wired-lan@lists.osuosl.org, + oss-drivers@corigine.com, linux-hyperv@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, + bpf@vger.kernel.org, Justin Stitt +Content-Type: text/plain; charset="utf-8" + +Use strscpy() to implement ethtool_puts(). + +Functionally the same as ethtool_sprintf() when it's used with two +arguments or with just "%s" format specifier. + +Signed-off-by: Justin Stitt +--- + include/linux/ethtool.h | 13 +++++++++++++ + net/ethtool/ioctl.c | 7 +++++++ + 2 files changed, 20 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -843,4 +843,17 @@ int ethtool_get_phc_vclocks(struct net_d + * next string. + */ + extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); ++ ++/** ++ * ethtool_puts - Write string to ethtool string data ++ * @data: Pointer to a pointer to the start of string to update ++ * @str: String to write ++ * ++ * Write string to *data without a trailing newline. Update *data ++ * to point at start of next string. ++ * ++ * Prefer this function to ethtool_sprintf() when given only ++ * two arguments or if @fmt is just "%s". ++ */ ++extern void ethtool_puts(u8 **data, const char *str); + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1974,6 +1974,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * + } + EXPORT_SYMBOL(ethtool_sprintf); + ++void ethtool_puts(u8 **data, const char *str) ++{ ++ strscpy(*data, str, ETH_GSTRING_LEN); ++ *data += ETH_GSTRING_LEN; ++} ++EXPORT_SYMBOL(ethtool_puts); ++ + static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + { + struct ethtool_value id; diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 new file mode 100644 index 0000000000..34a6503ce0 --- /dev/null +++ b/target/linux/generic/config-6.6 @@ -0,0 +1,7936 @@ +# CONFIG_104_QUAD_8 is not set +CONFIG_32BIT=y +CONFIG_64BIT_TIME=y +# CONFIG_6LOWPAN is not set +# CONFIG_6LOWPAN_DEBUGFS is not set +# CONFIG_6PACK is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_9P_FS is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_AB8500_CORE is not set +# CONFIG_ABP060MG is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_ACENIC is not set +# CONFIG_ACERHDF is not set +# CONFIG_ACER_WIRELESS is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_ACPI_ALS is not set +# CONFIG_ACPI_APEI is not set +# CONFIG_ACPI_APEI_PCIEAER is not set +# CONFIG_ACPI_BUTTON is not set +# CONFIG_ACPI_CONFIGFS is not set +# CONFIG_ACPI_CUSTOM_METHOD is not set +# CONFIG_ACPI_EXTLOG is not set +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_NFIT is not set +# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set +# CONFIG_ACPI_TABLE_UPGRADE is not set +# CONFIG_ACPI_VIDEO is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD3552R is not set +# CONFIG_AD5064 is not set +# CONFIG_AD5110 is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_AD5272 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5593R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5696_I2C is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5933 is not set +# CONFIG_AD7091R5 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD74413R is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD7606_IFACE_PARALLEL is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7746 is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD799X is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9467 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADA4250 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_ADE7854 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADIN1100_PHY is not set +# CONFIG_ADIN1110 is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADI_AXI_ADC is not set +# CONFIG_ADJD_S311 is not set +# CONFIG_ADM6996_PHY is not set +# CONFIG_ADM8211 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV1014 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADMV8818 is not set +# CONFIG_ADRF6780 is not set +# CONFIG_ADT7316 is not set +# CONFIG_ADUX1020 is not set +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_ADXL313_I2C is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_I2C is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_I2C is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_I2C is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL372_I2C is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +CONFIG_AEABI=y +# CONFIG_AFE4403 is not set +# CONFIG_AFE4404 is not set +# CONFIG_AFFS_FS is not set +# CONFIG_AFS_DEBUG_CURSOR is not set +# CONFIG_AFS_FS is not set +# CONFIG_AF_KCM is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_RXRPC_INJECT_LOSS is not set +# CONFIG_AF_RXRPC_IPV6 is not set +CONFIG_AF_UNIX_OOB=y +# CONFIG_AGP is not set +# CONFIG_AHCI_BRCM is not set +# CONFIG_AHCI_CEVA is not set +# CONFIG_AHCI_DWC is not set +# CONFIG_AHCI_IMX is not set +# CONFIG_AHCI_MVEBU is not set +# CONFIG_AHCI_QORIQ is not set +# CONFIG_AHCI_XGENE is not set +CONFIG_AIO=y +# CONFIG_AIR_EN8811H_PHY is not set +# CONFIG_AIRO is not set +# CONFIG_AIRO_CS is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_AK09911 is not set +# CONFIG_AK8974 is not set +# CONFIG_AK8975 is not set +# CONFIG_AL3010 is not set +# CONFIG_AL3320A is not set +# CONFIG_ALIM7101_WDT is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_ALTERA_MBOX is not set +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_ALTERA_STAPL is not set +# CONFIG_ALTERA_TSE is not set +# CONFIG_ALX is not set +# CONFIG_AL_FIC is not set +# CONFIG_AM2315 is not set +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_AMD_MEM_ENCRYPT is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_AMD_XGBE_HAVE_ECC is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_AMILO_RFKILL is not set +# CONFIG_AMPERE_ERRATUM_AC03_CPU_38 is not set +# CONFIG_AMT is not set +# CONFIG_ANDROID is not set +# CONFIG_ANDROID_BINDER_IPC is not set +CONFIG_ANON_INODES=y +# CONFIG_ANON_VMA_NAME is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_APDS9960 is not set +# CONFIG_APM8018X is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_APPLE_PROPERTIES is not set +# CONFIG_APPLICOM is not set +# CONFIG_AQTION is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AR5523 is not set +# CONFIG_AR7 is not set +# CONFIG_AR8216_PHY is not set +# CONFIG_AR8216_PHY_LEDS is not set +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AGILEX is not set +# CONFIG_ARCH_AIROHA is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_ARTPEC is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_AXXIA is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM4908 is not set +# CONFIG_ARCH_BCMBCA is not set +# CONFIG_ARCH_BCM_21664 is not set +# CONFIG_ARCH_BCM_23550 is not set +# CONFIG_ARCH_BCM_281XX is not set +# CONFIG_ARCH_BCM_5301X is not set +# CONFIG_ARCH_BCM_53573 is not set +# CONFIG_ARCH_BCM_63XX is not set +# CONFIG_ARCH_BCM_CYGNUS is not set +# CONFIG_ARCH_BCM_HR2 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BCM_NSP is not set +# CONFIG_ARCH_BERLIN is not set +CONFIG_ARCH_BINFMT_ELF_STATE=y +# CONFIG_ARCH_BITMAIN is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_DIGICOLOR is not set +# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_EXYNOS is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +# CONFIG_ARCH_FOOTBRIDGE is not set +CONFIG_ARCH_FORCE_MAX_ORDER=11 +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_HPE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MILBEAUT is not set +CONFIG_ARCH_MMAP_RND_BITS=8 +CONFIG_ARCH_MMAP_RND_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_MSTARV7 is not set +# CONFIG_ARCH_MULTIPLATFORM is not set +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set +# CONFIG_ARCH_NETX is not set +# 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 +# CONFIG_ARCH_OMAP2PLUS is not set +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_OXNAS is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_RANDOM is not set +# CONFIG_ARCH_RDA is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_S32 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_SUNPLUS is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TANGO is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_VULCAN is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_WANTS_THP_SWAP is not set +# CONFIG_ARCH_WM8505 is not set +# CONFIG_ARCH_WM8750 is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_ARCNET is not set +# CONFIG_ARC_EMAC is not set +# CONFIG_ARC_IRQ_NO_AUTOSAVE is not set +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_AMU_EXTN is not set +# CONFIG_ARM64_BTI is not set +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_ARM64_E0PD is not set +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_ARM64_ERRATUM_1165522 is not set +# CONFIG_ARM64_ERRATUM_1286807 is not set +# CONFIG_ARM64_ERRATUM_1319367 is not set +# CONFIG_ARM64_ERRATUM_1418040 is not set +# CONFIG_ARM64_ERRATUM_1463225 is not set +# CONFIG_ARM64_ERRATUM_1508412 is not set +# CONFIG_ARM64_ERRATUM_1530923 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_ARM64_ERRATUM_1742098 is not set +# CONFIG_ARM64_ERRATUM_2051678 is not set +# CONFIG_ARM64_ERRATUM_2054223 is not set +# CONFIG_ARM64_ERRATUM_2067961 is not set +# CONFIG_ARM64_ERRATUM_2077057 is not set +# CONFIG_ARM64_ERRATUM_2441007 is not set +# CONFIG_ARM64_ERRATUM_2441009 is not set +# CONFIG_ARM64_ERRATUM_2658417 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_834220 is not set +# CONFIG_ARM64_ERRATUM_843419 is not set +# CONFIG_ARM64_ERRATUM_845719 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_ARM64_ERRATUM_2966298 is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_LSE_ATOMICS 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 +# CONFIG_ARM64_PSEUDO_NMI is not set +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_PTR_AUTH is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_RELOC_TEST is not set +# CONFIG_ARM64_SME is not set +# CONFIG_ARM64_SVE is not set +CONFIG_ARM64_SW_TTBR0_PAN=y +# CONFIG_ARM64_TLB_RANGE is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_USE_LSE_ATOMICS is not set +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VHE is not set +# CONFIG_ARM_APPENDED_DTB is not set +# CONFIG_ARM_ARCH_TIMER is not set +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_CCI is not set +# CONFIG_ARM_CCI400_PMU is not set +# CONFIG_ARM_CCI5xx_PMU is not set +# CONFIG_ARM_CCI_PMU is not set +# CONFIG_ARM_CCN is not set +# CONFIG_ARM_CMN is not set +# CONFIG_ARM_CPUIDLE is not set +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_ARM_CRYPTO is not set +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_ARM_ERRATA_326103 is not set +# CONFIG_ARM_ERRATA_364296 is not set +# CONFIG_ARM_ERRATA_411920 is not set +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764319 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_ARM_ERRATA_773022 is not set +# CONFIG_ARM_ERRATA_775420 is not set +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_814220 is not set +# CONFIG_ARM_ERRATA_818325_852422 is not set +# CONFIG_ARM_ERRATA_821420 is not set +# CONFIG_ARM_ERRATA_825619 is not set +# CONFIG_ARM_ERRATA_852421 is not set +# CONFIG_ARM_ERRATA_852423 is not set +# CONFIG_ARM_ERRATA_857271 is not set +# CONFIG_ARM_ERRATA_857272 is not set +# CONFIG_ARM_FFA_TRANSPORT is not set +CONFIG_ARM_GIC_MAX_NR=1 +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_ARM_LPAE is not set +# CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set +# CONFIG_ARM_MHU 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 +# CONFIG_ARM_PSCI_CPUIDLE is not set +# CONFIG_ARM_PTDUMP_DEBUGFS is not set +# CONFIG_ARM_SBSA_WATCHDOG is not set +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set +# CONFIG_ARM_SDE_INTERFACE is not set +# CONFIG_ARM_SMCCC_SOC_ID is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_ARM_SPE_PMU is not set +# CONFIG_ARM_THUMBEE is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_AS3935 is not set +# CONFIG_AS73211 is not set +# CONFIG_ASM9260_TIMER is not set +# CONFIG_ASN1 is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_ASUS_WIRELESS is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AT91_SAMA5D2_ADC is not set +# CONFIG_ATA is not set +# CONFIG_ATAGS is not set +CONFIG_ATAGS_PROC=y +# CONFIG_ATALK is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_ATA_ACPI is not set +CONFIG_ATA_BMDMA=y +# CONFIG_ATA_FORCE is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_ATA_LEDS is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +# CONFIG_ATA_VERBOSE_ERROR is not set +# CONFIG_ATH10K is not set +# CONFIG_ATH25 is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH6KL is not set +# CONFIG_ATH79 is not set +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1C is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL2 is not set +# CONFIG_ATLAS_EZO_SENSOR is not set +# CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_ATM is not set +# CONFIG_ATMEL is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_BR2684 is not set +CONFIG_ATM_BR2684_IPFILTER=y +# CONFIG_ATM_CLIP is not set +CONFIG_ATM_CLIP_NO_ICMP=y +# CONFIG_ATM_DRIVERS is not set +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_FORE200E is not set +# CONFIG_ATM_HE is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_LANE is not set +# CONFIG_ATM_MPOA is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_SOLOS is not set +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ATP is not set +# CONFIG_AUDIT is not set +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set +# CONFIG_AURORA_NB8800 is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTO_ZRELADDR is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_AX25 is not set +# CONFIG_AX25_DAMA_SLAVE is not set +# CONFIG_AX88796 is not set +# CONFIG_AX88796B_PHY is not set +# CONFIG_AXP20X_ADC is not set +# CONFIG_AXP20X_POWER is not set +# CONFIG_AXP288_ADC is not set +# CONFIG_AXP288_FUEL_GAUGE is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_B44 is not set +# CONFIG_B53 is not set +# CONFIG_B53_MDIO_DRIVER is not set +# CONFIG_B53_MMAP_DRIVER is not set +# CONFIG_B53_SERDES is not set +# CONFIG_B53_SPI_DRIVER is not set +# CONFIG_B53_SRAB_DRIVER is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_APPLE is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_BACKLIGHT_LED is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_PANDORA is not set +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BACKLIGHT_RPI is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BACKTRACE_VERBOSE is not set +# CONFIG_BAREUDP is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +# CONFIG_BATMAN_ADV is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_BQ27XXX_HDQ is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_GOLDFISH is not set +# CONFIG_BATTERY_LEGO_EV3 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1721X is not set +# CONFIG_BATTERY_RT5033 is not set +# CONFIG_BATTERY_SAMSUNG_SDI is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_UG3105 is not set +# CONFIG_BAYCOM_EPP is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BCACHE is not set +# CONFIG_BCM2712_MIP is not set +# CONFIG_BCM47XX is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_BCM63XX is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_BCM7038_L1_IRQ is not set +# CONFIG_BCM7038_WDT is not set +# CONFIG_BCM7120_L2_IRQ is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM84881_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_BCMA is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMGENET is not set +# CONFIG_BCM_IPROC_ADC is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_BCM_VK is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BE2NET is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_BGMAC is not set +# CONFIG_BH1750 is not set +# CONFIG_BH1780 is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_BIG_LITTLE is not set +CONFIG_BINARY_PRINTF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_ELF_FDPIC is not set +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_SCRIPT=y +CONFIG_BITREVERSE=y +# CONFIG_BLK_CGROUP_IOCOST is not set +# CONFIG_BLK_CGROUP_IOLATENCY is not set +# CONFIG_BLK_CGROUP_IOPRIO is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_DEBUG_FS is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_BLK_DEV_4DRIVES is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI14XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_ATIIXP is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_CS5535 is not set +# CONFIG_BLK_DEV_CS5536 is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_DELKIN is not set +# CONFIG_BLK_DEV_DM is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_DTC2278 is not set +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_HT6560B is not set +# CONFIG_BLK_DEV_IDEACPI is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEPNP is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDE_AU1XXX is not set +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_IT8172 is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_PLATFORM is not set +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_BLK_DEV_QD65XX is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_SD is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_THROTTLING is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_UBLK is not set +# CONFIG_BLK_DEV_UMC8672 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_INLINE_ENCRYPTION is not set +# CONFIG_BLK_NVMEM is not set +# CONFIG_BLK_SED_OPAL is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLOCK=y +# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set +# CONFIG_BMA180 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMA400 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_BMC150_MAGN_I2C is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BME680 is not set +# CONFIG_BMG160 is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_BMI160_I2C is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BMIPS_GENERIC is not set +# CONFIG_BMP280 is not set +# CONFIG_BNA is not set +# CONFIG_BNX2 is not set +# CONFIG_BNX2X is not set +# CONFIG_BNX2X_SRIOV is not set +# CONFIG_BNXT is not set +# CONFIG_BONDING is not set +# CONFIG_BOOKE_WDT is not set +CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +# CONFIG_BOOTTIME_TRACING is not set +# CONFIG_BOOT_CONFIG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOOT_RAW=y +# CONFIG_BOSCH_BNO055_I2C is not set +# CONFIG_BOSCH_BNO055_SERIAL is not set +# CONFIG_BOUNCE is not set +CONFIG_BPF=y +# CONFIG_BPFILTER is not set +CONFIG_BPF_JIT=y +# CONFIG_BPF_JIT_ALWAYS_ON is not set +CONFIG_BPF_JIT_DEFAULT_ON=y +# CONFIG_BPF_PRELOAD is not set +# CONFIG_BPF_STREAM_PARSER is not set +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_UNPRIV_DEFAULT_OFF=y +# CONFIG_BPQETHER is not set +CONFIG_BQL=y +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_BRCMFMAC is not set +# CONFIG_BRCMSMAC is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_BRCMSTB_L2_IRQ is not set +CONFIG_BRIDGE=y +# CONFIG_BRIDGE_CFM is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_BROUTE is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_MRP is not set +# CONFIG_BRIDGE_NETFILTER is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +CONFIG_BRIDGE_VLAN_FILTERING=y +# CONFIG_BROADCOM_PHY is not set +CONFIG_BROKEN_ON_SMP=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_BT is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_BTRFS_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS_REF_VERIFY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BT_AOSPEXT is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_CMTP is not set +# CONFIG_BT_FEATURE_DEBUG is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_HCIBTUSB_RTL is not set +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_AG6XX is not set +# CONFIG_BT_HCIUART_ATH3K is not set +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_HCIUART_QCA is not set +# CONFIG_BT_HCIUART_RTL is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_HIDP is not set +# CONFIG_BT_HS is not set +# CONFIG_BT_LE is not set +# CONFIG_BT_LEDS is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MSFTEXT is not set +# CONFIG_BT_MTKSDIO is not set +# CONFIG_BT_MTKUART is not set +# CONFIG_BT_RFCOMM is not set +CONFIG_BT_RFCOMM_TTY=y +# CONFIG_BT_SELFTEST is not set +# CONFIG_BT_VIRTIO is not set +CONFIG_BUG=y +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_BUILDTIME_TABLE_SORT=y +# CONFIG_BUILD_BIN2C is not set +CONFIG_BUILD_SALT="" +# CONFIG_C2PORT is not set +CONFIG_CACHE_L2X0_PMU=y +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_CAIF is not set +# CONFIG_CAN is not set +# CONFIG_CAN_BCM is not set +# CONFIG_CAN_CAN327 is not set +# CONFIG_CAN_CTUCANFD_PCI is not set +# CONFIG_CAN_CTUCANFD_PLATFORM is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_CAN_DEV is not set +# CONFIG_CAN_ESD_USB is not set +# CONFIG_CAN_ETAS_ES58X is not set +# CONFIG_CAN_GS_USB is not set +# CONFIG_CAN_GW is not set +# CONFIG_CAN_HI311X is not set +# CONFIG_CAN_IFI_CANFD is not set +# CONFIG_CAN_ISOTP is not set +# CONFIG_CAN_J1939 is not set +# CONFIG_CAN_KVASER_PCIEFD is not set +# CONFIG_CAN_MCBA_USB is not set +# CONFIG_CAN_MCP251XFD is not set +# CONFIG_CAN_M_CAN is not set +# CONFIG_CAN_NETLINK is not set +# CONFIG_CAN_PEAK_PCIEFD is not set +# CONFIG_CAN_RAW is not set +# CONFIG_CAN_RCAR is not set +# CONFIG_CAN_RCAR_CANFD is not set +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_SUN4I is not set +# CONFIG_CAN_UCAN is not set +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_VXCAN is not set +# CONFIG_CAPI_AVM is not set +# CONFIG_CAPI_EICON is not set +# CONFIG_CAPI_TRACE is not set +CONFIG_CARDBUS=y +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_CARL9170 is not set +# CONFIG_CASSINI is not set +# CONFIG_CAVIUM_CPT is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23144 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_CAVIUM_OCTEON_SOC is not set +# CONFIG_CAVIUM_PTP is not set +# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set +# CONFIG_CB710_CORE is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_CCS811 is not set +CONFIG_CC_CAN_LINK=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_CFG80211 is not set +# 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 +# CONFIG_CHARGER_ADP5061 is not set +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ2515X is not set +# CONFIG_CHARGER_BQ256XX is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_LT3651 is not set +# CONFIG_CHARGER_LTC3651 is not set +# CONFIG_CHARGER_LTC4162L is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_MAX77976 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_QCOM_SMBB is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_TWL4030 is not set +# CONFIG_CHARGER_UCS1002 is not set +# CONFIG_CHASH_SELFTEST is not set +# CONFIG_CHASH_STATS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_ACL is not set +CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y +# CONFIG_CIFS_DEBUG is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_FSCACHE is not set +# CONFIG_CIFS_NFSD_EXPORT is not set +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_SMB2 is not set +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_STATS2 is not set +# CONFIG_CIFS_SWN_UPCALL is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_XATTR=y +# CONFIG_CIO_DAC is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CLKSRC_PISTACHIO is not set +# CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_CLK_GFM_LPASS_SM8250 is not set +# CONFIG_CLK_HSDK is not set +# CONFIG_CLK_ICST is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_CLK_SP810 is not set +# CONFIG_CLOCK_THERMAL is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM3605 is not set +# CONFIG_CM36651 is not set +# CONFIG_CMA is not set +CONFIG_CMDLINE="" +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_CMDLINE_FROM_BOOTLOADER is not set +# CONFIG_CMDLINE_PARTITION is not set +# CONFIG_CNIC is not set +# CONFIG_CODA_FS is not set +# CONFIG_CODE_PATCHING_SELFTEST is not set +# CONFIG_COMEDI is not set +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set +# CONFIG_COMMON_CLK_BOSTON is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_FIXED_MMIO is not set +# CONFIG_COMMON_CLK_IPROC is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +# CONFIG_COMMON_CLK_MT6765 is not set +# CONFIG_COMMON_CLK_MT8167 is not set +# CONFIG_COMMON_CLK_MT8167_AUDSYS is not set +# CONFIG_COMMON_CLK_MT8167_IMGSYS is not set +# CONFIG_COMMON_CLK_MT8167_MFGCFG is not set +# CONFIG_COMMON_CLK_MT8167_MMSYS is not set +# CONFIG_COMMON_CLK_MT8167_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8192 is not set +# CONFIG_COMMON_CLK_NXP is not set +# CONFIG_COMMON_CLK_PIC32 is not set +# CONFIG_COMMON_CLK_PISTACHIO is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_COMMON_CLK_RP1 is not set +# CONFIG_COMMON_CLK_RP1_SDIO is not set +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI5341 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_VC7 is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_COMPACTION=y +# CONFIG_COMPAL_LAPTOP is not set +# CONFIG_COMPAT is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_COMPILE_TEST is not set +# CONFIG_CONFIGFS_FS is not set +# CONFIG_CONNECTOR is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_CONSTRUCTORS=y +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_COPS is not set +# CONFIG_CORDIC is not set +# CONFIG_COREDUMP is not set +# CONFIG_CORESIGHT is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_COUNTER is not set +# CONFIG_CPA_DEBUG is not set +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_THERMAL is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND is not set +# CONFIG_CPU_IDLE is not set +# CONFIG_CPU_IDLE_GOV_LADDER is not set +# CONFIG_CPU_IDLE_GOV_MENU is not set +# 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 +# CONFIG_CRAMFS is not set +CONFIG_CRAMFS_BLOCKDEV=y +# CONFIG_CRAMFS_MTD is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_CRC32_BIT is not set +CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_SELFTEST is not set +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SLICEBY8 is not set +# CONFIG_CRC4 is not set +# CONFIG_CRC64 is not set +# CONFIG_CRC64_ROCKSOFT is not set +# CONFIG_CRC7 is not set +# CONFIG_CRC8 is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CROSS_COMPILE="" +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AEGIS128L is not set +# CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2 is not set +# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set +# CONFIG_CRYPTO_AEGIS256 is not set +# CONFIG_CRYPTO_AEGIS256_AESNI_SSE2 is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_586 is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_ARM64 is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +# CONFIG_CRYPTO_AES_ARM64_CE is not set +# CONFIG_CRYPTO_AES_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_AES_ARM_BS is not set +# CONFIG_CRYPTO_AES_ARM_CE is not set +# CONFIG_CRYPTO_AES_NI_INTEL is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2B_NEON is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLAKE2S_X86 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +CONFIG_CRYPTO_CCM=y +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_CHACHA20_X86_64 is not set +# CONFIG_CRYPTO_CHACHA_MIPS is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CRC32C_INTEL is not set +# CONFIG_CRYPTO_CRC32_ARM_CE is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM_CE is not set +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_CURVE25519_NEON is not set +# CONFIG_CRYPTO_CURVE25519_X86 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_CRYPTO_DEV_ATMEL_AES is not set +# CONFIG_CRYPTO_DEV_ATMEL_AUTHENC is not set +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_ATMEL_TDES is not set +# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_HISI_SEC is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set +# CONFIG_CRYPTO_DEV_MARVELL_CESA is not set +# CONFIG_CRYPTO_DEV_MEDIATEK is not set +# CONFIG_CRYPTO_DEV_MV_CESA is not set +# CONFIG_CRYPTO_DEV_MXC_SCC is not set +# CONFIG_CRYPTO_DEV_MXS_DCP is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_OCTEONTX_CPT is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_S5P is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_CRYPTO_DEV_SP_PSP is not set +# CONFIG_CRYPTO_DEV_TALITOS is not set +# CONFIG_CRYPTO_DEV_VIRTIO is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_GHASH_ARM64_CE is not set +# CONFIG_CRYPTO_GHASH_ARM_CE is not set +# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_KHAZAD is not set +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_ARC4=y +# CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC is not set +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +# CONFIG_CRYPTO_LIB_POLY1305 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_MORUS1280 is not set +# CONFIG_CRYPTO_MORUS1280_AVX2 is not set +# CONFIG_CRYPTO_MORUS1280_SSE2 is not set +# CONFIG_CRYPTO_MORUS640 is not set +# CONFIG_CRYPTO_MORUS640_SSE2 is not set +# CONFIG_CRYPTO_NHPOLY1305_NEON is not set +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCOMP is not set +# CONFIG_CRYPTO_PCOMP2 is not set +CONFIG_CRYPTO_PCRYPT=y +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_POLY1305_MIPS is not set +# CONFIG_CRYPTO_POLY1305_NEON is not set +# CONFIG_CRYPTO_POLY1305_X86_64 is not set +# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RNG is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA1_ARM64_CE is not set +# CONFIG_CRYPTO_SHA1_ARM_CE is not set +# CONFIG_CRYPTO_SHA1_ARM_NEON is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA256_ARM64 is not set +# CONFIG_CRYPTO_SHA2_ARM64_CE is not set +# CONFIG_CRYPTO_SHA2_ARM_CE is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA3_ARM64 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SHA512_ARM64 is not set +# CONFIG_CRYPTO_SHA512_ARM64_CE is not set +# CONFIG_CRYPTO_SIMD is not set +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_SM3_NEON is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_SM4_ARM64_CE is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_SPECK is not set +# CONFIG_CRYPTO_STATS is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_TWOFISH_586 is not set +# CONFIG_CRYPTO_TWOFISH_COMMON is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_ZSTD is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_CS89x0 is not set +# CONFIG_CS89x0_PLATFORM is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# CONFIG_CUSE is not set +# CONFIG_CW1200 is not set +# CONFIG_CXD2880_SPI_DRV is not set +# CONFIG_CXL_AFU_DRIVER_OPS is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_BUS is not set +# CONFIG_CXL_EEH is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_LIB is not set +# CONFIG_CYPRESS_FIRMWARE is not set +# CONFIG_DA280 is not set +# CONFIG_DA311 is not set +# CONFIG_DAMON is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DAX is not set +# CONFIG_DCB is not set +# CONFIG_DDR is not set +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_EFI is not set +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_INFO_BTF is not set +# CONFIG_DEBUG_INFO_COMPRESSED is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y +# CONFIG_DEBUG_INFO_NONE is not set +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_IRQFLAGS is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KMAP_LOCAL is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_KOBJECT_RELEASE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_LL_UART_8250 is not set +# CONFIG_DEBUG_LL_UART_PL01X is not set +# CONFIG_DEBUG_LOCKDEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MAPLE_TREE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_MISC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NET is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_RSEQ is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_UART_8250_PALMCHIP is not set +# CONFIG_DEBUG_UART_8250_WORD is not set +# CONFIG_DEBUG_UART_BCM63XX is not set +# CONFIG_DEBUG_UART_FLOW_CONTROL is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGFLAGS is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +# CONFIG_DEBUG_VM_RB is not set +# CONFIG_DEBUG_VM_VMACACHE is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_WX is not set +# CONFIG_DEBUG_ZBOOT is not set +# CONFIG_DECNET is not set +# CONFIG_DEFAULT_CODEL is not set +CONFIG_DEFAULT_CUBIC=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_FQ is not set +CONFIG_DEFAULT_FQ_CODEL=y +# CONFIG_DEFAULT_FQ_PIE is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_DEFAULT_NET_SCH="fq_codel" +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_PFIFO_FAST is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_SECURITY="" +CONFIG_DEFAULT_SECURITY_DAC=y +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SFQ is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_DELL_LAPTOP is not set +# CONFIG_DELL_RBTN is not set +# CONFIG_DELL_SMBIOS is not set +# CONFIG_DELL_SMO8800 is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_DEVKMEM is not set +# CONFIG_DEVMEM is not set +CONFIG_DEVPORT=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_DEVTMPFS is not set +# CONFIG_DEVTMPFS_MOUNT is not set +# CONFIG_DEVTMPFS_SAFE is not set +# CONFIG_DEV_DAX is not set +# CONFIG_DGAP is not set +# CONFIG_DGNC is not set +# CONFIG_DHT11 is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_DISPLAY_CONNECTOR_ANALOG_TV is not set +# CONFIG_DISPLAY_CONNECTOR_DVI is not set +# CONFIG_DISPLAY_CONNECTOR_HDMI is not set +# CONFIG_DISPLAY_ENCODER_TFP410 is not set +# CONFIG_DISPLAY_ENCODER_TPD12S015 is not set +# CONFIG_DISPLAY_PANEL_DPI is not set +# CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DL2K is not set +# CONFIG_DLHL60D is not set +# CONFIG_DLM is not set +# CONFIG_DM9000 is not set +# CONFIG_DM9051 is not set +# CONFIG_DMABUF_DEBUG is not set +# CONFIG_DMABUF_HEAPS is not set +# CONFIG_DMABUF_MOVE_NOTIFY is not set +# CONFIG_DMABUF_SELFTESTS is not set +# CONFIG_DMABUF_SYSFS_STATS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMARD06 is not set +# CONFIG_DMARD09 is not set +# CONFIG_DMARD10 is not set +# CONFIG_DMASCC is not set +# CONFIG_DMATEST is not set +# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_COHERENT_POOL=y +CONFIG_DMA_DECLARE_COHERENT=y +# CONFIG_DMA_ENGINE is not set +# CONFIG_DMA_FENCE_TRACE is not set +# CONFIG_DMA_JZ4780 is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_DMA_NONCOHERENT_MMAP=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_PERNUMA_CMA is not set +# CONFIG_DMA_RESTRICTED_POOL is not set +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_CLONE is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_DUST is not set +# CONFIG_DM_EBS is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_LOG_USERSPACE is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_DM_MQ_DEFAULT is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_UNSTRIPED is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_WRITECACHE is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DNET is not set +# CONFIG_DNOTIFY is not set +# CONFIG_DNS_RESOLVER is not set +CONFIG_DOUBLEFAULT=y +# CONFIG_DP83640_PHY is not set +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83869_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_DPOT_DAC is not set +# CONFIG_DPS310 is not set +CONFIG_DQL=y +# CONFIG_DRAGONRISE_FF is not set +# CONFIG_DRM is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_AMDGPU_CIK is not set +# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set +# CONFIG_DRM_AMDGPU_SI is not set +# CONFIG_DRM_AMDGPU_USERPTR is not set +# CONFIG_DRM_AMD_ACP is not set +# CONFIG_DRM_AMD_DC_DCN2_0 is not set +# CONFIG_DRM_AMD_DC_DCN3_0 is not set +# CONFIG_DRM_AMD_DC_HDCP is not set +# CONFIG_DRM_AMD_DC_SI is not set +# CONFIG_DRM_AMD_SECURE_DISPLAY is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_ARMADA is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_ATMEL_HLCDC is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MM is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set +# CONFIG_DRM_DEBUG_SELFTEST is not set +# CONFIG_DRM_DISPLAY_CONNECTOR is not set +# CONFIG_DRM_DP_AUX_CHARDEV is not set +# CONFIG_DRM_DP_CEC is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_DW_HDMI_CEC is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_FBDEV_EMULATION is not set +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +# CONFIG_DRM_FSL_DCU is not set +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_GUD is not set +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I915 is not set +# CONFIG_DRM_IMX_LCDIF is not set +# CONFIG_DRM_ITE_IT6505 is not set +# CONFIG_DRM_ITE_IT66121 is not set +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_LEGACY is not set +# CONFIG_DRM_LIB_RANDOM is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_LOGICVC is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9211 is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_LVDS_ENCODER is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_MCDE is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_MXSFB is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_OMAP is not set +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set +# CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_DSI_CM is not set +# CONFIG_DRM_PANEL_EBBG_FT8719 is not set +# CONFIG_DRM_PANEL_EDP is not set +# CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9806E is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_JDI_R63452 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set +# CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_MIPI_DBI is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +# CONFIG_DRM_PANEL_NEWVISION_NV3052C is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35560 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_ROCKTECH_JH057N00900 is not set +# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SHARP_LS060T1SX01 is not set +# CONFIG_DRM_PANEL_SIMPLE is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX424AKP is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_TPO_Y17P is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_WAVESHARE_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set +# CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_RADEON_USERPTR is not set +# CONFIG_DRM_RCAR_DW_HDMI is not set +# CONFIG_DRM_RCAR_LVDS is not set +# CONFIG_DRM_RCAR_USE_LVDS is not set +# CONFIG_DRM_RCAR_USE_MIPI_DSI is not set +# CONFIG_DRM_ROCKCHIP is not set +# CONFIG_DRM_RP1_DPI is not set +# CONFIG_DRM_RP1_DSI is not set +# CONFIG_DRM_RP1_VEC is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SIMPLEDRM is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_SSD130X is not set +# CONFIG_DRM_STI is not set +# CONFIG_DRM_STM is not set +# CONFIG_DRM_SUN4I is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_TINYDRM is not set +# CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TVE200 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_V3D is not set +# CONFIG_DRM_VBOXVIDEO is not set +# CONFIG_DRM_VC4_HDMI_CEC is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VIRTIO_GPU is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_DRM_VMWGFX is not set +# CONFIG_DRM_XEN is not set +# CONFIG_DRM_XEN_FRONTEND is not set +# CONFIG_DS1682 is not set +# CONFIG_DS1803 is not set +# CONFIG_DS4424 is not set +# CONFIG_DST_CACHE is not set +# CONFIG_DTLK is not set +# CONFIG_DUMMY is not set +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +# CONFIG_DUMMY_IRQ is not set +# CONFIG_DVB_A8293 is not set +# CONFIG_DVB_AF9013 is not set +# CONFIG_DVB_AF9033 is not set +# CONFIG_DVB_AS102 is not set +# CONFIG_DVB_ASCOT2E is not set +# CONFIG_DVB_ATBM8830 is not set +# CONFIG_DVB_AU8522_DTV is not set +# CONFIG_DVB_AU8522_V4L is not set +# CONFIG_DVB_B2C2_FLEXCOP_PCI is not set +# CONFIG_DVB_B2C2_FLEXCOP_USB is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DVB_CX22700 is not set +# CONFIG_DVB_CX22702 is not set +# CONFIG_DVB_CX24110 is not set +# CONFIG_DVB_CX24116 is not set +# CONFIG_DVB_CX24117 is not set +# CONFIG_DVB_CX24120 is not set +# CONFIG_DVB_CX24123 is not set +# CONFIG_DVB_CXD2099 is not set +# CONFIG_DVB_CXD2820R is not set +# CONFIG_DVB_CXD2841ER is not set +# CONFIG_DVB_CXD2880 is not set +# CONFIG_DVB_DDBRIDGE is not set +# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set +# CONFIG_DVB_DIB8000 is not set +# CONFIG_DVB_DIB9000 is not set +# CONFIG_DVB_DRX39XYJ is not set +# CONFIG_DVB_DRXD is not set +# CONFIG_DVB_DRXK is not set +# CONFIG_DVB_DS3000 is not set +# CONFIG_DVB_DUMMY_FE is not set +# CONFIG_DVB_DYNAMIC_MINORS is not set +# CONFIG_DVB_EC100 is not set +# CONFIG_DVB_FIREDTV is not set +# CONFIG_DVB_HELENE is not set +# CONFIG_DVB_HORUS3A is not set +# CONFIG_DVB_ISL6405 is not set +# CONFIG_DVB_ISL6421 is not set +# CONFIG_DVB_ISL6423 is not set +# CONFIG_DVB_IX2505V is not set +# CONFIG_DVB_L64781 is not set +# CONFIG_DVB_LG2160 is not set +# CONFIG_DVB_LGDT3305 is not set +# CONFIG_DVB_LGDT3306A is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_DVB_LGS8GL5 is not set +# CONFIG_DVB_LGS8GXX is not set +# CONFIG_DVB_LNBH25 is not set +# CONFIG_DVB_LNBH29 is not set +# CONFIG_DVB_LNBP21 is not set +# CONFIG_DVB_LNBP22 is not set +# CONFIG_DVB_M88DS3103 is not set +# CONFIG_DVB_M88RS2000 is not set +CONFIG_DVB_MAX_ADAPTERS=16 +# CONFIG_DVB_MB86A16 is not set +# CONFIG_DVB_MB86A20S is not set +# CONFIG_DVB_MMAP is not set +# CONFIG_DVB_MN88443X is not set +# CONFIG_DVB_MN88472 is not set +# CONFIG_DVB_MN88473 is not set +# CONFIG_DVB_MT312 is not set +# CONFIG_DVB_MT352 is not set +# CONFIG_DVB_MXL5XX is not set +# CONFIG_DVB_MXL692 is not set +# CONFIG_DVB_NET is not set +# CONFIG_DVB_NETUP_UNIDVB is not set +# CONFIG_DVB_NGENE is not set +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_NXT6000 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_PLATFORM_DRIVERS is not set +# CONFIG_DVB_PLL is not set +# CONFIG_DVB_PLUTO2 is not set +# CONFIG_DVB_PT1 is not set +# CONFIG_DVB_PT3 is not set +# CONFIG_DVB_RTL2830 is not set +# CONFIG_DVB_RTL2832 is not set +# CONFIG_DVB_RTL2832_SDR is not set +# CONFIG_DVB_S5H1409 is not set +# CONFIG_DVB_S5H1411 is not set +# CONFIG_DVB_S5H1420 is not set +# CONFIG_DVB_S5H1432 is not set +# CONFIG_DVB_S921 is not set +# CONFIG_DVB_SI2165 is not set +# CONFIG_DVB_SI2168 is not set +# CONFIG_DVB_SI21XX is not set +# CONFIG_DVB_SP2 is not set +# CONFIG_DVB_SP8870 is not set +# CONFIG_DVB_SP887X is not set +# CONFIG_DVB_STB0899 is not set +# CONFIG_DVB_STB6000 is not set +# CONFIG_DVB_STB6100 is not set +# CONFIG_DVB_STV0288 is not set +# CONFIG_DVB_STV0297 is not set +# CONFIG_DVB_STV0299 is not set +# CONFIG_DVB_STV0367 is not set +# CONFIG_DVB_STV0900 is not set +# CONFIG_DVB_STV090x is not set +# CONFIG_DVB_STV0910 is not set +# CONFIG_DVB_STV6110 is not set +# CONFIG_DVB_STV6110x is not set +# CONFIG_DVB_STV6111 is not set +# CONFIG_DVB_TC90522 is not set +# CONFIG_DVB_TDA10021 is not set +# CONFIG_DVB_TDA10023 is not set +# CONFIG_DVB_TDA10048 is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_TDA10071 is not set +# CONFIG_DVB_TDA10086 is not set +# CONFIG_DVB_TDA18271C2DD is not set +# CONFIG_DVB_TDA665x is not set +# CONFIG_DVB_TDA8083 is not set +# CONFIG_DVB_TDA8261 is not set +# CONFIG_DVB_TDA826X is not set +# CONFIG_DVB_TEST_DRIVERS is not set +# CONFIG_DVB_TS2020 is not set +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set +# CONFIG_DVB_TUA6100 is not set +# CONFIG_DVB_TUNER_CX24113 is not set +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set +# CONFIG_DVB_TUNER_ITD1000 is not set +# CONFIG_DVB_ULE_DEBUG is not set +# CONFIG_DVB_USB is not set +# CONFIG_DVB_USB_V2 is not set +# CONFIG_DVB_VES1820 is not set +# CONFIG_DVB_VES1X93 is not set +# CONFIG_DVB_ZD1301_DEMOD is not set +# CONFIG_DVB_ZL10036 is not set +# CONFIG_DVB_ZL10039 is not set +# CONFIG_DVB_ZL10353 is not set +# CONFIG_DWC_XLGMAC is not set +# CONFIG_DWMAC_DWC_QOS_ETH is not set +# CONFIG_DWMAC_INTEL_PLAT is not set +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LOONGSON is not set +# CONFIG_DWMAC_LPC18XX is not set +# CONFIG_DWMAC_MESON is not set +# CONFIG_DWMAC_ROCKCHIP is not set +# CONFIG_DWMAC_SOCFPGA is not set +# CONFIG_DWMAC_STI is not set +# CONFIG_DW_AXI_DMAC is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_DW_EDMA is not set +# CONFIG_DW_EDMA_PCIE is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_DW_XDATA_PCIE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DYNAMIC_DEBUG_CORE is not set +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_HWTS is not set +# CONFIG_EARLY_PRINTK_8250 is not set +# CONFIG_EARLY_PRINTK_USB_XDBC is not set +# CONFIG_EBC_C384_WDT is not set +# CONFIG_ECHO is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_EDAC is not set +# CONFIG_EEEPC_LAPTOP is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_DIGSY_MTC_CFG is not set +# CONFIG_EEPROM_EE1004 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EFI is not set +CONFIG_EFI_PARTITION=y +# CONFIG_EFI_VARS_PSTORE is not set +# CONFIG_EFS_FS is not set +CONFIG_ELFCORE=y +# CONFIG_ELF_CORE is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_EMBEDDED=y +# CONFIG_EM_TIMER_STI is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENA_ETHERNET is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_ENERGY_MODEL is not set +# CONFIG_ENIC is not set +# CONFIG_ENVELOPE_DETECTOR is not set +# CONFIG_EPAPR_PARAVIRT is not set +# CONFIG_EPIC100 is not set +CONFIG_EPOLL=y +# CONFIG_EQUALIZER is not set +# CONFIG_EROFS_FS is not set +# CONFIG_ET131X is not set +CONFIG_ETHERNET=y +# CONFIG_ETHOC is not set +CONFIG_ETHTOOL_NETLINK=y +CONFIG_EVENTFD=y +# CONFIG_EVM is not set +# CONFIG_EXFAT_FS is not set +CONFIG_EXPERT=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +# CONFIG_EXT2_FS is not set +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_FS is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON is not set +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_ARIZONA is not set +# CONFIG_EXTCON_AXP288 is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_INTEL_INT3496 is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USBC_TUSB320 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_EXTRA_FIRMWARE="" +CONFIG_EXTRA_TARGETS="" +# CONFIG_EXYNOS_ADC is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_FAULT_INJECTION is not set +# CONFIG_F2FS_FS is not set +# CONFIG_F2FS_FS_COMPRESSION is not set +# CONFIG_F2FS_FS_ENCRYPTION is not set +# CONFIG_F2FS_FS_POSIX_ACL is not set +# CONFIG_F2FS_FS_SECURITY is not set +CONFIG_F2FS_FS_XATTR=y +# CONFIG_F2FS_IOSTAT is not set +# CONFIG_F2FS_IO_TRACE is not set +CONFIG_F2FS_STAT_FS=y +# CONFIG_F2FS_UNFAIR_RWSEM is not set +# CONFIG_FAILOVER is not set +# CONFIG_FAIR_GROUP_SCHED is not set +# CONFIG_FANOTIFY is not set +# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_FAT_FS is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FB is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_ATMEL is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_BIG_ENDIAN is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_BOTH_ENDIAN is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_DA8XX is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_FLEX is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_FSL_DIU is not set +# CONFIG_FB_GEODE is not set +# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_IMX is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_LE80578 is not set +# CONFIG_FB_LITTLE_ENDIAN is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_MXS is not set +# CONFIG_FB_N411 is not set +# CONFIG_FB_NEOMAGIC is not set +CONFIG_FB_NOTIFY=y +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_OF is not set +# CONFIG_FB_OMAP2 is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_PS3 is not set +# CONFIG_FB_PXA is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_RPISENSE is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_SM712 is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_TFT is not set +# CONFIG_FB_TFT_AGM1264K_FL is not set +# CONFIG_FB_TFT_BD663474 is not set +# CONFIG_FB_TFT_FBTFT_DEVICE is not set +# CONFIG_FB_TFT_HX8340BN is not set +# CONFIG_FB_TFT_HX8347D is not set +# CONFIG_FB_TFT_HX8353D is not set +# CONFIG_FB_TFT_HX8357D is not set +# CONFIG_FB_TFT_ILI9163 is not set +# CONFIG_FB_TFT_ILI9320 is not set +# CONFIG_FB_TFT_ILI9325 is not set +# CONFIG_FB_TFT_ILI9340 is not set +# CONFIG_FB_TFT_ILI9341 is not set +# CONFIG_FB_TFT_ILI9481 is not set +# CONFIG_FB_TFT_ILI9486 is not set +# CONFIG_FB_TFT_PCD8544 is not set +# CONFIG_FB_TFT_RA8875 is not set +# CONFIG_FB_TFT_S6D02A1 is not set +# CONFIG_FB_TFT_S6D1121 is not set +# CONFIG_FB_TFT_SEPS525 is not set +# CONFIG_FB_TFT_SH1106 is not set +# CONFIG_FB_TFT_SSD1289 is not set +# CONFIG_FB_TFT_SSD1305 is not set +# CONFIG_FB_TFT_SSD1306 is not set +# CONFIG_FB_TFT_SSD1325 is not set +# CONFIG_FB_TFT_SSD1331 is not set +# CONFIG_FB_TFT_SSD1351 is not set +# CONFIG_FB_TFT_ST7735R is not set +# CONFIG_FB_TFT_ST7789V is not set +# CONFIG_FB_TFT_TINYLCD is not set +# CONFIG_FB_TFT_TLS8204 is not set +# CONFIG_FB_TFT_UC1611 is not set +# CONFIG_FB_TFT_UC1701 is not set +# CONFIG_FB_TFT_UPD161704 is not set +# CONFIG_FB_TFT_WATTEROTT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_VIA is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_XGI is not set +# CONFIG_FCOE is not set +# CONFIG_FCOE_FNIC is not set +# CONFIG_FDDI is not set +# CONFIG_FEALNX is not set +# CONFIG_FENCE_TRACE is not set +# CONFIG_FHANDLE is not set +CONFIG_FIB_RULES=y +# CONFIG_FIELDBUS_DEV is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FIXED_PHY is not set +CONFIG_FLATMEM=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_FM10K is not set +# CONFIG_FMC is not set +# CONFIG_FONTS is not set +# CONFIG_FONT_6x8 is not set +# CONFIG_FONT_TER16x32 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_FORCE_NR_CPUS is not set +CONFIG_FORTIFY_SOURCE=y +# CONFIG_FPGA is not set +# CONFIG_FPROBE is not set +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_FREEZER is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_FSCACHE is not set +# CONFIG_FSI is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_FSL_ENETC is not set +# CONFIG_FSL_ENETC_IERB is not set +# CONFIG_FSL_ENETC_MDIO is not set +# CONFIG_FSL_ENETC_VF is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_FSL_PQ_MDIO is not set +# CONFIG_FSL_QDMA is not set +# CONFIG_FSL_RCPM is not set +# CONFIG_FSL_XGMAC_MDIO is not set +CONFIG_FSNOTIFY=y +# CONFIG_FS_DAX is not set +# CONFIG_FS_ENCRYPTION is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_FS_VERITY is not set +# CONFIG_FTGMAC100 is not set +# CONFIG_FTL is not set +# CONFIG_FTMAC100 is not set +# CONFIG_FTRACE is not set +# CONFIG_FTRACE_RECORD_RECURSION is not set +# CONFIG_FTRACE_SORT_STARTUP_TEST is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_FTR_FIXUP_SELFTEST is not set +# CONFIG_FTWDT010_WATCHDOG is not set +# CONFIG_FUJITSU_ERRATUM_010001 is not set +# CONFIG_FUJITSU_ES is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_FUNCTION_ERROR_INJECTION is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_FUN_ETH is not set +# CONFIG_FUSE_FS is not set +# CONFIG_FUSION is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set +# CONFIG_FUSION_SPI is not set +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_FW_LOADER=y +# CONFIG_FW_LOADER_COMPRESS is not set +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_UPLOAD is not set +# CONFIG_FXAS21002C is not set +# CONFIG_FXLS8962AF_I2C is not set +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_FXOS8700_I2C is not set +# CONFIG_FXOS8700_SPI is not set +CONFIG_GACT_PROB=y +# CONFIG_GADGET_UAC1 is not set +# CONFIG_GAMEPORT is not set +# CONFIG_GATEWORKS_GW16083 is not set +# CONFIG_GCC_PLUGINS is not set +# CONFIG_GCOV is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_GDB_SCRIPTS is not set +# CONFIG_GEMINI_ETHERNET is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_GENERIC_ADC_THERMAL is not set +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_HWEIGHT=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_GENERIC_IRQ_IPI=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_NET_UTILS=y +# CONFIG_GENERIC_PHY is not set +CONFIG_GENERIC_PTDUMP=y +CONFIG_GENERIC_VDSO_TIME_NS=y +# CONFIG_GENEVE is not set +# CONFIG_GENWQE is not set +# CONFIG_GFS2_FS is not set +# CONFIG_GIGASET_CAPI is not set +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_DUMMYLL is not set +# CONFIG_GLOB_SELFTEST is not set +# CONFIG_GNSS is not set +# CONFIG_GOLDFISH is not set +# CONFIG_GOOGLE_FIRMWARE is not set +# CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT is not set +# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set +# CONFIG_GOOGLE_SMI is not set +# CONFIG_GP2AP002 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_GPD_POCKET_FAN is not set +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +# CONFIG_GPIO_104_DIO_48E is not set +# CONFIG_GPIO_104_IDIO_16 is not set +# CONFIG_GPIO_104_IDI_48 is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_AGGREGATOR is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_AMDPT is not set +# CONFIG_GPIO_AMD_FCH is not set +# CONFIG_GPIO_BCM_KONA is not set +# CONFIG_GPIO_BRCMSTB is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_CADENCE is not set +# CONFIG_GPIO_CASCADE is not set +# CONFIG_GPIO_CDEV is not set +# CONFIG_GPIO_CDEV_V1 is not set +# CONFIG_GPIO_CS5535 is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_EXAR is not set +# CONFIG_GPIO_F7188X is not set +# CONFIG_GPIO_FTGPIO010 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GPIO_MM is not set +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_ICH is not set +# CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LOGICVC is not set +# CONFIG_GPIO_LYNXPOINT is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_MPC8XXX is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCA9570 is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_PCH is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_PWM is not set +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_RDC321X is not set +# CONFIG_GPIO_SAMA5D2_PIOBU is not set +# CONFIG_GPIO_SCH is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SIFIVE is not set +# CONFIG_GPIO_SIM is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_SYSCON is not set +CONFIG_GPIO_SYSFS=y +# CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_VIRTIO is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_GPIO_WINBOND is not set +# CONFIG_GPIO_WS16C48 is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_GPIO_ZEVIO is not set +# CONFIG_GPIO_ZX is not set +# CONFIG_GP_PCI1XXXX is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_GREYBUS is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_GTP is not set +# CONFIG_GUP_BENCHMARK is not set +# CONFIG_GUP_TEST is not set +# CONFIG_GVE is not set +# CONFIG_HABANA_AI is not set +# CONFIG_HAMACHI is not set +# CONFIG_HAMRADIO is not set +# CONFIG_HAPPYMEAL is not set +CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_FALLBACK is not set +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_HARDEN_BRANCH_HISTORY=y +CONFIG_HARDEN_EL2_VECTORS=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +# CONFIG_HCALL_STATS is not set +# CONFIG_HDC100X is not set +# CONFIG_HDC2010 is not set +# CONFIG_HDLC is not set +# CONFIG_HDLC_CISCO is not set +# CONFIG_HDLC_FR is not set +# CONFIG_HDLC_PPP is not set +# CONFIG_HDLC_RAW is not set +# CONFIG_HDLC_RAW_ETH is not set +# CONFIG_HDMI_LPE_AUDIO is not set +# CONFIG_HDQ_MASTER_OMAP is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_HEADER_TEST is not set +# CONFIG_HERMES is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_HFSPLUS_FS_POSIX_ACL is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFS_FS_POSIX_ACL is not set +# CONFIG_HI6421V600_IRQ is not set +# CONFIG_HI8435 is not set +# CONFIG_HIBERNATION is not set +# CONFIG_HID is not set +# CONFIG_HIDRAW is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_ACRUX_FF is not set +# CONFIG_HID_ALPS is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_ASUS is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_BIGBEN_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_ELAN is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_FT260 is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GENERIC is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_GLORIOUS is not set +# CONFIG_HID_GOOGLE_HAMMER is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LETSKETCH is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_LOGITECH_DJ is not set +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MCP2221 is not set +# CONFIG_HID_MEGAWORLD_FF is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NINTENDO is not set +# CONFIG_HID_NTI is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PID is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PLAYSTATION is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_PXRC is not set +# CONFIG_HID_RAZER is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SEMITEK is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_SIGMAMICRO is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPRE is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_U2FZERO is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VIVALDI is not set +# CONFIG_HID_VRC2 is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XIAOMI is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HIGHMEM is not set +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_HINIC is not set +# CONFIG_HIP04_ETH is not set +# CONFIG_HIPPI is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_HISI_DMA is not set +# CONFIG_HISI_FEMAC is not set +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_HISI_PCIE_PMU is not set +# CONFIG_HISI_PTT is not set +# CONFIG_HIST_TRIGGERS_DEBUG is not set +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HMC425 is not set +# CONFIG_HMC6352 is not set +# CONFIG_HNS is not set +# CONFIG_HNS3 is not set +# CONFIG_HNS3_PMU is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HOSTAP is not set +# CONFIG_HOSTAP_CS is not set +# CONFIG_HOSTAP_PCI is not set +# CONFIG_HOSTAP_PLX is not set +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HP03 is not set +# CONFIG_HP100 is not set +# CONFIG_HP206C is not set +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 +# CONFIG_HSR is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTE is not set +# CONFIG_HTS221 is not set +# CONFIG_HTU21 is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_HVC_DCC is not set +# CONFIG_HVC_UDBG is not set +# CONFIG_HWLAT_TRACER is not set +# CONFIG_HWMON is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON_VID is not set +# CONFIG_HWSPINLOCK is not set +# CONFIG_HWSPINLOCK_OMAP is not set +CONFIG_HW_PERF_EVENTS=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_ARM_SMCCC_TRNG is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_BA431 is not set +# CONFIG_HW_RANDOM_BCM2835 is not set +# CONFIG_HW_RANDOM_CAVIUM is not set +# CONFIG_HW_RANDOM_CCTRNG is not set +# CONFIG_HW_RANDOM_CN10K is not set +# CONFIG_HW_RANDOM_EXYNOS is not set +# CONFIG_HW_RANDOM_GEODE is not set +# CONFIG_HW_RANDOM_INTEL is not set +# CONFIG_HW_RANDOM_IPROC_RNG200 is not set +# CONFIG_HW_RANDOM_MTK is not set +# CONFIG_HW_RANDOM_OMAP is not set +# CONFIG_HW_RANDOM_OMAP3_ROM is not set +# CONFIG_HW_RANDOM_PPC4XX is not set +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_VIA is not set +# CONFIG_HW_RANDOM_VIRTIO is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +# CONFIG_HX711 is not set +# CONFIG_HYPERV is not set +# CONFIG_HYPERV_TSCPAGE is not set +# CONFIG_HYSDN is not set +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_200 is not set +# CONFIG_HZ_24 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_48 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_PERIODIC is not set +# CONFIG_I2C is not set +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCA is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_AU1550 is not set +# CONFIG_I2C_BCM2835 is not set +# CONFIG_I2C_BCM_IPROC is not set +# CONFIG_I2C_BRCMSTB is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_COMPAT is not set +# CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_SLAVE is not set +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_EG20T is not set +# CONFIG_I2C_ELEKTOR is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_HID is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_IBM_IIC is not set +# CONFIG_I2C_IMG is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_ISMT is not set +# CONFIG_I2C_JZ4780 is not set +# CONFIG_I2C_MLXCPLD is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_MT65XX is not set +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_MV64XXX is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_OCTEON is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PCA_ISA is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PCI1XXXX is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_PXA_SLAVE is not set +# CONFIG_I2C_RCAR is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_S3C2410 is not set +# CONFIG_I2C_SCMI is not set +# CONFIG_I2C_SH_MOBILE is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_SLAVE_EEPROM is not set +# CONFIG_I2C_SMBUS is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_THUNDERX is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VERSATILE is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VIRTIO is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I3C is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_IAQCORE is not set +# CONFIG_IBM_ASM is not set +# CONFIG_IBM_EMAC_DEBUG is not set +# CONFIG_IBM_EMAC_EMAC4 is not set +# CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_EMAC_MAL_COMMON_ERR is not set +# CONFIG_IBM_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_EMAC_RGMII is not set +# CONFIG_IBM_EMAC_TAH is not set +# CONFIG_IBM_EMAC_ZMII is not set +# CONFIG_ICE is not set +# CONFIG_ICP10100 is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ICST is not set +# CONFIG_IDE is not set +# CONFIG_IDEAPAD_LAPTOP is not set +# CONFIG_IDE_GD is not set +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +# CONFIG_IEEE802154 is not set +# CONFIG_IEEE802154_ADF7242 is not set +# CONFIG_IEEE802154_ATUSB is not set +# CONFIG_IEEE802154_CA8210 is not set +# CONFIG_IEEE802154_HWSIM is not set +# CONFIG_IEEE802154_MCR20A is not set +# CONFIG_IFB is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IGC is not set +# CONFIG_IIO is not set +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_BUFFER_CB is not set +# CONFIG_IIO_BUFFER_DMA is not set +# CONFIG_IIO_BUFFER_DMAENGINE is not set +# CONFIG_IIO_BUFFER_HDC2010 is not set +# CONFIG_IIO_BUFFER_HW_CONSUMER is not set +# CONFIG_IIO_CONFIGFS is not set +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +# CONFIG_IIO_CROS_EC_ACCEL_LEGACY is not set +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +# CONFIG_IIO_MUX is not set +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_RESCALE is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_ST_LSM9DS0 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_IIO_SW_DEVICE is not set +# CONFIG_IIO_SW_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_TRIGGER is not set +# CONFIG_IIO_TRIGGERED_EVENT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_IKCONFIG_PROC is not set +# CONFIG_IKHEADERS is not set +# CONFIG_IMA is not set +# CONFIG_IMAGE_CMDLINE_HACK is not set +# CONFIG_IMGPDC_WDT is not set +# CONFIG_IMG_MDC_DMA is not set +# CONFIG_IMX7D_ADC is not set +# CONFIG_IMX8QXP_ADC is not set +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_IMX_THERMAL is not set +# CONFIG_INA2XX_ADC is not set +# CONFIG_INDIRECT_PIO is not set +CONFIG_INET=y +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_ESPINTCP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_DIAG is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_ESPINTCP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 +# CONFIG_INET_TCP_DIAG is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INFINIBAND is not set +# CONFIG_INFTL is not set +# CONFIG_INGENIC_ADC is not set +# CONFIG_INGENIC_CGU_JZ4725B is not set +# CONFIG_INGENIC_CGU_JZ4740 is not set +# CONFIG_INGENIC_CGU_JZ4760 is not set +# CONFIG_INGENIC_CGU_JZ4770 is not set +# CONFIG_INGENIC_CGU_JZ4780 is not set +# CONFIG_INGENIC_CGU_X1000 is not set +# CONFIG_INGENIC_CGU_X1830 is not set +# CONFIG_INGENIC_OST is not set +# CONFIG_INGENIC_SYSOST is not set +# CONFIG_INGENIC_TCU_CLK is not set +# CONFIG_INGENIC_TCU_IRQ is not set +# CONFIG_INGENIC_TIMER is not set +# CONFIG_INITRAMFS_PRESERVE_MTIME is not set +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +# CONFIG_INIT_STACK_ALL_PATTERN is not set +# CONFIG_INIT_STACK_ALL_ZERO is not set +CONFIG_INIT_STACK_NONE=y +CONFIG_INOTIFY_USER=y +# CONFIG_INPUT is not set +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_APANEL is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_ATLAS_BTNS is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_AXP20X_PEK is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +# CONFIG_INPUT_IBM_PANEL is not set +# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set +# CONFIG_INPUT_IQS7222 is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_LEDS is not set +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MAX8997_HAPTIC is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_MSM_VIBRATOR is not set +# CONFIG_INPUT_PALMAS_PWRBUTTON is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PCSPKR is not set +# CONFIG_INPUT_PM8941_PWRKEY is not set +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_RASPBERRYPI_BUTTON is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_TPS65218_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_VIBRA is not set +# CONFIG_INPUT_TWL6040_VIBRA is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_WISTRON_BTNS is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INT340X_THERMAL is not set +# CONFIG_INTEGRITY is not set +# CONFIG_INTEGRITY_AUDIT is not set +# CONFIG_INTEGRITY_SIGNATURE is not set +# CONFIG_INTEL_ATOMISP2_LED is not set +# CONFIG_INTEL_ATOMISP2_PM is not set +# CONFIG_INTEL_CHT_INT33FE is not set +# CONFIG_INTEL_HID_EVENT is not set +# CONFIG_INTEL_IDLE is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_INTEL_INT0002_VGPIO is not set +# CONFIG_INTEL_IOATDMA is not set +# CONFIG_INTEL_ISH_HID is not set +# CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set +# CONFIG_INTEL_MEI_TXE is not set +# CONFIG_INTEL_MIC_CARD is not set +# CONFIG_INTEL_MIC_HOST is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_INTEL_OAKTRAIL is not set +# CONFIG_INTEL_PMC_CORE is not set +# CONFIG_INTEL_PUNIT_IPC is not set +# CONFIG_INTEL_RST is not set +# CONFIG_INTEL_SMARTCONNECT is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set +# CONFIG_INTEL_SOC_PMIC_CHTWC is not set +# CONFIG_INTEL_TH is not set +# CONFIG_INTEL_VBTN is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_INV_ICM42600_I2C is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_MPU6050_I2C is not set +# CONFIG_INV_MPU6050_IIO is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_IONIC is not set +# CONFIG_IOSCHED_BFQ is not set +# CONFIG_IOSM is not set +CONFIG_IO_STRICT_DEVMEM=y +# CONFIG_IO_URING is not set +CONFIG_IO_WQ=y +# CONFIG_IP17XX_PHY is not set +# CONFIG_IP5XXX_POWER is not set +# CONFIG_IP6_NF_FILTER is not set +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_IP6_NF_MANGLE is not set +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_SRH is not set +# CONFIG_IP6_NF_NAT is not set +# CONFIG_IP6_NF_RAW is not set +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP6_NF_TARGET_HL is not set +# CONFIG_IP6_NF_TARGET_MASQUERADE is not set +# CONFIG_IP6_NF_TARGET_REJECT is not set +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_IPC_NS is not set +# CONFIG_IPMB_DEVICE_INTERFACE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IPV6 is not set +# CONFIG_IPV6_FOU is not set +# CONFIG_IPV6_FOU_TUNNEL is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_ROUTE_INFO is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_SIT_6RD is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_VTI is not set +# CONFIG_IPVLAN is not set +# CONFIG_IPVTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2200 is not set +# CONFIG_IPW2200_DEBUG is not set +CONFIG_IPW2200_MONITOR=y +# CONFIG_IPW2200_PROMISCUOUS is not set +# CONFIG_IPW2200_QOS is not set +# CONFIG_IPW2200_RADIOTAP is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_IPX is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_DCCP is not set +# CONFIG_IP_FIB_TRIE_STATS is not set +# CONFIG_IP_MROUTE is not set +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_NF_ARPFILTER is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_ARP_MANGLE is not set +# CONFIG_IP_NF_FILTER is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RPFILTER is not set +# CONFIG_IP_NF_MATCH_TTL is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_SECURITY is not set +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_MASQUERADE is not set +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +# CONFIG_IP_NF_TARGET_TTL is not set +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_SCTP is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_SET_HASH_IPMAC is not set +# CONFIG_IP_VS is not set +# CONFIG_IP_VS_MH is not set +CONFIG_IP_VS_MH_TAB_INDEX=10 +# CONFIG_IP_VS_TWOS is not set +# CONFIG_IRDA is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_IRQ_ALL_CPUS is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_IRQ_POLL is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_IR_GPIO_CIR is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_IMG is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_IMON_RAW is not set +# CONFIG_IR_JVC_DECODER is not set +# CONFIG_IR_LIRC_CODEC is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_NEC_DECODER is not set +# CONFIG_IR_RC5_DECODER is not set +# CONFIG_IR_RC6_DECODER is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_SERIAL is not set +# CONFIG_IR_SIR is not set +# CONFIG_IR_SONY_DECODER is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_TOY is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_ISA_BUS is not set +# CONFIG_ISA_BUS_API is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_ISCSI_TCP is not set +CONFIG_ISDN=y +# CONFIG_ISDN_AUDIO is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_CAPI_CAPIDRV is not set +# CONFIG_ISDN_DIVERSION is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +# CONFIG_ISDN_DRV_GIGASET is not set +# CONFIG_ISDN_DRV_HISAX is not set +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_LOOP is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_I4L is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_ISL29125 is not set +# CONFIG_ISL29501 is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_ISS4xx is not set +# CONFIG_ITG3200 is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_JAILHOUSE_GUEST is not set +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_POSIX_ACL is not set +# CONFIG_JFFS2_FS_SECURITY is not set +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_LZMA=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_ZLIB is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_JME is not set +CONFIG_JOLIET=y +# CONFIG_JSA1212 is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_JZ4740_WDT is not set +# CONFIG_JZ4770_PHY is not set +# CONFIG_KALLSYMS is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +# CONFIG_KALLSYMS_UNCOMPRESSED is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_KASAN is not set +# CONFIG_KASAN_MODULE_TEST is not set +CONFIG_KASAN_STACK=y +# CONFIG_KCMP is not set +# CONFIG_KCOV is not set +CONFIG_KCOV_IRQ_AREA_SIZE=0x40000 +# CONFIG_KCSAN is not set +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_CAT is not set +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZ4 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_KERNEL_MODE_NEON=y +CONFIG_KERNEL_XZ=y +# CONFIG_KERNEL_ZSTD is not set +CONFIG_KERNFS=y +# CONFIG_KEXEC is not set +# CONFIG_KEXEC_FILE is not set +# CONFIG_KEXEC_SIG is not set +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_APPLESPI is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_MT6779 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_PXA27x is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_SH_KEYSC is not set +# CONFIG_KEYBOARD_SNVS_PWRKEY is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_TEGRA is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS is not set +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_KFENCE is not set +# CONFIG_KGDB is not set +# CONFIG_KMEMCHECK is not set +# CONFIG_KMX61 is not set +# CONFIG_KPC2000 is not set +# CONFIG_KPROBES is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +# CONFIG_KPROBE_EVENT_GEN_TEST is not set +# CONFIG_KS7010 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSM is not set +# CONFIG_KSZ884X_PCI is not set +# CONFIG_KUNIT is not set +CONFIG_KUSER_HELPERS=y +# CONFIG_KVM_AMD is not set +# CONFIG_KVM_AMD_SEV is not set +# CONFIG_KVM_GUEST is not set +# CONFIG_KVM_INTEL is not set +# CONFIG_KVM_WERROR is not set +# CONFIG_KVM_XEN is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_KXSD9 is not set +# CONFIG_L2TP is not set +# CONFIG_L2TP_ETH is not set +# CONFIG_L2TP_IP is not set +# CONFIG_L2TP_V3 is not set +# CONFIG_LAN743X is not set +# CONFIG_LAN966X_SWITCH is not set +# CONFIG_LANMEDIA is not set +# CONFIG_LANTIQ is not set +# CONFIG_LAPB is not set +# CONFIG_LASAT is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_LBDAF=y +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_LCD_HX8357 is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_OTM3225A is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LDISC_AUTOLOAD=y +# CONFIG_LDM_PARTITION is not set +CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y +# CONFIG_LD_HEAD_STUB_CATCH is not set +# CONFIG_LEDS_AN30259A is not set +# CONFIG_LEDS_APU is not set +# CONFIG_LEDS_AW2013 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +CONFIG_LEDS_CLASS_MULTICOLOR=y +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_EL15203000 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP50XX is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP55XX_COMMON is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_MLXCPLD is not set +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_NIC78BX is not set +# CONFIG_LEDS_NS2 is not set +# CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_PWM_MULTICOLOR is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_SPI_BYTE is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TI_LMU_COMMON is not set +# CONFIG_LEDS_TLC591XX is not set +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_AUDIO is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +# CONFIG_LEDS_TRIGGER_DISK is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_MTD is not set +CONFIG_LEDS_TRIGGER_NETDEV=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_PANIC is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_TTY is not set +# CONFIG_LEDS_TURRIS_OMNIA is not set +# CONFIG_LEDS_USER is not set +# CONFIG_LED_TRIGGER_PHY is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_LGUEST is not set +# CONFIG_LIB80211 is not set +# CONFIG_LIB80211_CRYPT_CCMP is not set +# CONFIG_LIB80211_CRYPT_TKIP is not set +# CONFIG_LIB80211_CRYPT_WEP is not set +# CONFIG_LIB80211_DEBUG is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_LIBERTAS_USB is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_LIBIPW_DEBUG is not set +# CONFIG_LIBNVDIMM is not set +CONFIG_LIB_MEMNEQ=y +# CONFIG_LIDAR_LITE_V2 is not set +CONFIG_LINEAR_RANGES=y +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +# CONFIG_LIRC is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_LITEX_LITEETH is not set +# CONFIG_LITEX_SOC_CONTROLLER is not set +# CONFIG_LIVEPATCH is not set +# CONFIG_LKDTM is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_LMK04832 is not set +# CONFIG_LMP91000 is not set +# CONFIG_LNET is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_LOCKD is not set +CONFIG_LOCKDEP_BITS=15 +CONFIG_LOCKDEP_CHAINS_BITS=16 +CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12 +CONFIG_LOCKDEP_STACK_TRACE_BITS=19 +CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +CONFIG_LOCK_MM_AND_FIND_VMA=y +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_LOCK_EVENT_COUNTS is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_LOGFS is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_LOGO is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_LOONGSON_MC146818 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_LP_CONSOLE is not set +CONFIG_LRU_GEN=y +CONFIG_LRU_GEN_ENABLED=y +# CONFIG_LRU_GEN_STATS is not set +# CONFIG_LSI_ET1011C_PHY is not set +CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" +CONFIG_LSM_MMAP_MIN_ADDR=65536 +# CONFIG_LTC1660 is not set +# CONFIG_LTC2471 is not set +# CONFIG_LTC2485 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2497 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2688 is not set +# CONFIG_LTC2983 is not set +# CONFIG_LTE_GDM724X is not set +CONFIG_LTO_NONE=y +# CONFIG_LTPC is not set +# CONFIG_LTR501 is not set +# CONFIG_LTRF216A is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_LV0104CS is not set +# CONFIG_LWTUNNEL is not set +# CONFIG_LXT_PHY is not set +# CONFIG_LZ4HC_COMPRESS is not set +# CONFIG_LZ4_COMPRESS is not set +# CONFIG_LZ4_DECOMPRESS is not set +CONFIG_LZMA_COMPRESS=y +CONFIG_LZMA_DECOMPRESS=y +# CONFIG_LZO_COMPRESS is not set +# CONFIG_LZO_DECOMPRESS is not set +# CONFIG_M62332 is not set +# CONFIG_MAC80211 is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_MACB is not set +# CONFIG_MACH_ASM9260 is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_INGENIC is not set +# CONFIG_MACH_INGENIC_SOC is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_JZ4740 is not set +# CONFIG_MACH_LOONGSON2EF is not set +# CONFIG_MACH_LOONGSON32 is not set +# CONFIG_MACH_LOONGSON64 is not set +# CONFIG_MACH_NINTENDO64 is not set +# CONFIG_MACH_PIC32 is not set +# CONFIG_MACH_PISTACHIO is not set +# CONFIG_MACH_REALTEK_RTL is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MACH_XILFPGA is not set +# CONFIG_MACINTOSH_DRIVERS is not set +# CONFIG_MACSEC is not set +# CONFIG_MACVLAN is not set +# CONFIG_MACVTAP is not set +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MAG3110 is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +# CONFIG_MAGIC_SYSRQ_SERIAL is not set +CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" +# CONFIG_MAILBOX is not set +# CONFIG_MANAGER_SBS is not set +# CONFIG_MANDATORY_FILE_LOCKING is not set +# CONFIG_MANGLE_BOOTARGS is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88X2222_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MAX30100 is not set +# CONFIG_MAX30102 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MAX44000 is not set +# CONFIG_MAX44009 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5432 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_MAX9611 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MAXLINEAR_GPHY is not set +CONFIG_MAY_USE_DEVLINK=y +# CONFIG_MB1232 is not set +# CONFIG_MC3230 is not set +# CONFIG_MCB is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP4018 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4531 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MCPM is not set +# CONFIG_MCTP is not set +# CONFIG_MD is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set +# CONFIG_MDIO_DEVICE is not set +# CONFIG_MDIO_DEVRES is not set +# CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_IPQ4019 is not set +# CONFIG_MDIO_IPQ8064 is not set +# CONFIG_MDIO_MSCC_MIIM is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_THUNDER is not set +# CONFIG_MDIO_XPCS is not set +# CONFIG_MDM_GCC_9607 is not set +# CONFIG_MD_FAULTY is not set +# CONFIG_MEDIATEK_GE_PHY is not set +# CONFIG_MEDIATEK_MT6577_AUXADC is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_ATTACH is not set +# CONFIG_MEDIA_CAMERA_SUPPORT is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set +# CONFIG_MEDIA_CONTROLLER is not set +# CONFIG_MEDIA_CONTROLLER_DVB is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +# CONFIG_MEDIA_PLATFORM_DRIVERS is not set +# CONFIG_MEDIA_PLATFORM_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +# CONFIG_MEDIA_SUPPORT is not set +# CONFIG_MEDIA_SUPPORT_FILTER is not set +# CONFIG_MEDIA_TEST_SUPPORT is not set +# CONFIG_MEDIA_TUNER_E4000 is not set +# CONFIG_MEDIA_TUNER_FC0011 is not set +# CONFIG_MEDIA_TUNER_FC0012 is not set +# CONFIG_MEDIA_TUNER_FC0013 is not set +# CONFIG_MEDIA_TUNER_FC2580 is not set +# CONFIG_MEDIA_TUNER_IT913X is not set +# CONFIG_MEDIA_TUNER_M88RS6000T is not set +# CONFIG_MEDIA_TUNER_MAX2165 is not set +# CONFIG_MEDIA_TUNER_MC44S803 is not set +# CONFIG_MEDIA_TUNER_MSI001 is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2063 is not set +# CONFIG_MEDIA_TUNER_MT20XX is not set +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MXL301RF is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set +# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_R820T is not set +# CONFIG_MEDIA_TUNER_SI2157 is not set +# CONFIG_MEDIA_TUNER_SIMPLE is not set +# CONFIG_MEDIA_TUNER_TDA18212 is not set +# CONFIG_MEDIA_TUNER_TDA18218 is not set +# CONFIG_MEDIA_TUNER_TDA18250 is not set +# CONFIG_MEDIA_TUNER_TDA18271 is not set +# CONFIG_MEDIA_TUNER_TDA827X is not set +# CONFIG_MEDIA_TUNER_TDA8290 is not set +# CONFIG_MEDIA_TUNER_TDA9887 is not set +# CONFIG_MEDIA_TUNER_TEA5761 is not set +# CONFIG_MEDIA_TUNER_TEA5767 is not set +# CONFIG_MEDIA_TUNER_TUA9001 is not set +# CONFIG_MEDIA_TUNER_XC2028 is not set +# CONFIG_MEDIA_TUNER_XC4000 is not set +# CONFIG_MEDIA_TUNER_XC5000 is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_MELLANOX_PLATFORM is not set +CONFIG_MEMBARRIER=y +# CONFIG_MEMORY is not set +# CONFIG_MEMORY_FAILURE is not set +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMSTICK is not set +# CONFIG_MEMTEST is not set +# CONFIG_MEN_A21_WDT is not set +# CONFIG_MESON_SM is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_AC100 is not set +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_ATC260X_I2C is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set +# CONFIG_MFD_GATEWORKS_GSC is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_INTEL_PMT is not set +# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set +# CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_LOCHNAGAR is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MAX77650 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77714 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6370 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_NTXEC is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_OMAP_USB_HOST is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_PM8921_CORE is not set +# CONFIG_MFD_PM8XXX is not set +# CONFIG_MFD_QCOM_PM8008 is not set +# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_ROHM_BD70528 is not set +# CONFIG_MFD_ROHM_BD71828 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_RP1 is not set +# CONFIG_MFD_RPISENSE_CORE is not set +# CONFIG_MFD_RSMU_I2C is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_RT4831 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RT5120 is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SL28CPLD is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_STMFX is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_STPMIC1 is not set +# CONFIG_MFD_SY7636A is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS68470 is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MG_DISK is not set +# CONFIG_MHI_BUS is not set +# CONFIG_MHI_BUS_DEBUG is not set +# CONFIG_MHI_BUS_EP is not set +# CONFIG_MHI_BUS_PCI_GENERIC is not set +# CONFIG_MHI_NET is not set +# CONFIG_MHI_WWAN_CTRL is not set +# CONFIG_MHI_WWAN_MBIM is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_KSZ is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROCHIP_PIT64B is not set +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_MIGRATION is not set +CONFIG_MII=y +# CONFIG_MIKROTIK is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_MINIX_FS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MIPS32_N32 is not set +# CONFIG_MIPS32_O32 is not set +# CONFIG_MIPS_ALCHEMY is not set +# CONFIG_MIPS_CDMM is not set +# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set +# CONFIG_MIPS_CMDLINE_FROM_DTB is not set +# CONFIG_MIPS_CMP is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MIPS_CPS is not set +# CONFIG_MIPS_ELF_APPENDED_DTB is not set +# CONFIG_MIPS_FPU_EMULATOR is not set +# CONFIG_MIPS_FP_SUPPORT is not set +# CONFIG_MIPS_GENERIC is not set +# CONFIG_MIPS_GENERIC_KERNEL is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_O32_FP64_SUPPORT is not set +# CONFIG_MIPS_PARAVIRT is not set +# CONFIG_MIPS_PLATFORM_DEVICES is not set +# CONFIG_MIPS_RAW_APPENDED_DTB is not set +# CONFIG_MIPS_SEAD3 is not set +# CONFIG_MIPS_VA_BITS_48 is not set +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_MISC_ALCOR_PCI is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_MISDN is not set +# CONFIG_MISDN_AVMFRITZ is not set +# CONFIG_MISDN_HFCPCI is not set +# CONFIG_MISDN_HFCUSB is not set +# CONFIG_MISDN_INFINEON is not set +# CONFIG_MISDN_NETJET is not set +# CONFIG_MISDN_SPEEDFAX is not set +# CONFIG_MISDN_W6692 is not set +CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y +# CONFIG_MKISS is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLX5_EN_MACSEC is not set +# CONFIG_MLX5_SF is not set +# CONFIG_MLX5_VFIO_PCI is not set +# CONFIG_MLX90614 is not set +# CONFIG_MLX90632 is not set +# CONFIG_MLXFW is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLX_CPLD_PLATFORM is not set +# CONFIG_MLX_PLATFORM is not set +# CONFIG_MMA7455_I2C is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMA7660 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MMC is not set +# CONFIG_MMC35240 is not set +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_AU1X is not set +# CONFIG_MMC_BLOCK is not set +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_MMC_CAVIUM_THUNDERX is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_JZ4740 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_MVSDIO is not set +# CONFIG_MMC_S3C is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SDHCI_ACPI is not set +# CONFIG_MMC_SDHCI_AM654 is not set +# CONFIG_MMC_SDHCI_BCM_KONA is not set +# CONFIG_MMC_SDHCI_BRCMSTB is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_SDHCI_IPROC is not set +# CONFIG_MMC_SDHCI_MILBEAUT is not set +# CONFIG_MMC_SDHCI_MSM is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_ASPEED is not set +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_OF_ESDHC is not set +# CONFIG_MMC_SDHCI_OF_HLWD is not set +# CONFIG_MMC_SDHCI_OMAP is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_S3C is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDRICOH_CS is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_STM32_SDMMC is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMIOTRACE is not set +CONFIG_MMU=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MODPROBE_PATH="/sbin/modprobe" +CONFIG_MODULES=y +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_COMPRESS_GZIP is not set +CONFIG_MODULE_COMPRESS_NONE=y +# CONFIG_MODULE_COMPRESS_XZ is not set +# CONFIG_MODULE_COMPRESS_ZSTD is not set +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_MODULE_STRIPPED=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MOST is not set +# CONFIG_MOTORCOMM_PHY is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_PS2_FOCALTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_MOXTET is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL115_I2C is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MPL3115 is not set +# CONFIG_MPLS is not set +# CONFIG_MPLS_IPTUNNEL is not set +# CONFIG_MPLS_ROUTING is not set +# CONFIG_MPTCP is not set +# CONFIG_MPU3050_I2C is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_MSA311 is not set +# CONFIG_MSCC_OCELOT_SWITCH is not set +# CONFIG_MSDOS_FS is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_MSE102X is not set +# CONFIG_MSI_BITMAP_SELFTEST is not set +# CONFIG_MSI_LAPTOP is not set +# CONFIG_MSM_GCC_8953 is not set +# CONFIG_MSM_MMCC_8994 is not set +# CONFIG_MST_IRQ is not set +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_HYPERBUS is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_LATCH_ADDR is not set +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +# CONFIG_MTD_M25P80 is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +# CONFIG_MTD_MT81xx_NOR is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_MYLOADER_PARTS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_NAND_AMS_DELTA is not set +# CONFIG_MTD_NAND_AR934X is not set +# CONFIG_MTD_NAND_AR934X_HW_ECC is not set +# CONFIG_MTD_NAND_ARASAN is not set +# CONFIG_MTD_NAND_ATMEL is not set +# CONFIG_MTD_NAND_AU1550 is not set +# CONFIG_MTD_NAND_BCH is not set +# CONFIG_MTD_NAND_BF5XX is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_BRCMNAND_BCM63XX is not set +# CONFIG_MTD_NAND_BRCMNAND_BCMBCA is not set +# CONFIG_MTD_NAND_BRCMNAND_BRCMSTB is not set +# CONFIG_MTD_NAND_BRCMNAND_IPROC is not set +# CONFIG_MTD_NAND_CADENCE is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_CM_X270 is not set +# CONFIG_MTD_NAND_CS553X is not set +# CONFIG_MTD_NAND_DAVINCI is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_DENALI_PCI is not set +CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_ECC is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_NAND_ECC_MXIC is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_ECC_SW_BCH is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set +# CONFIG_MTD_NAND_FSL_ELBC is not set +# CONFIG_MTD_NAND_FSL_IFC is not set +# CONFIG_MTD_NAND_FSL_UPM is not set +# CONFIG_MTD_NAND_FSMC is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_GPMI_NAND is not set +# CONFIG_MTD_NAND_HISI504 is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_INTEL_LGM is not set +# CONFIG_MTD_NAND_JZ4740 is not set +# CONFIG_MTD_NAND_MPC5121_NFC is not set +# CONFIG_MTD_NAND_MTK is not set +# CONFIG_MTD_NAND_MTK_BMT is not set +# CONFIG_MTD_NAND_MXC is not set +# CONFIG_MTD_NAND_MXIC is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_NDFC is not set +# CONFIG_MTD_NAND_NUC900 is not set +# CONFIG_MTD_NAND_OMAP2 is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +# CONFIG_MTD_NAND_ORION is not set +# CONFIG_MTD_NAND_PASEMI is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_PXA3xx is not set +# CONFIG_MTD_NAND_RB4XX is not set +# CONFIG_MTD_NAND_RB750 is not set +# CONFIG_MTD_NAND_RB91X is not set +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_S3C2410 is not set +# CONFIG_MTD_NAND_SHARPSL is not set +# CONFIG_MTD_NAND_SH_FLCTL is not set +# CONFIG_MTD_NAND_SOCRATES is not set +# CONFIG_MTD_NAND_TMIO is not set +# CONFIG_MTD_NAND_TXX9NDFMC is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_PARSER_TRX is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PHYSMAP_GEMINI is not set +# CONFIG_MTD_PHYSMAP_GPIO_ADDR is not set +# CONFIG_MTD_PHYSMAP_IXP4XX is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set +# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set +# CONFIG_MTD_PHYSMAP_VERSATILE is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_RAW_NAND is not set +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_ROM is not set +CONFIG_MTD_ROOTFS_ROOT_DEV=y +# CONFIG_MTD_ROUTERBOOT_PARTS is not set +# CONFIG_MTD_SERCOMM_PARTS is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_MTD_SPI_NAND is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +# CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE is not set +CONFIG_MTD_SPLIT=y +# CONFIG_MTD_SPLIT_BCM63XX_FW is not set +# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set +# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_ELF_FW is not set +# CONFIG_MTD_SPLIT_EVA_FW is not set +# CONFIG_MTD_SPLIT_FIRMWARE is not set +CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" +# CONFIG_MTD_SPLIT_FIT_FW is not set +# CONFIG_MTD_SPLIT_H3C_VFS is not set +# CONFIG_MTD_SPLIT_JIMAGE_FW is not set +# CONFIG_MTD_SPLIT_LZMA_FW is not set +# CONFIG_MTD_SPLIT_MINOR_FW is not set +# CONFIG_MTD_SPLIT_SEAMA_FW is not set +# CONFIG_MTD_SPLIT_SEIL_FW is not set +CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y +CONFIG_MTD_SPLIT_SUPPORT=y +# CONFIG_MTD_SPLIT_TPLINK_FW is not set +# CONFIG_MTD_SPLIT_TRX_FW is not set +# CONFIG_MTD_SPLIT_UIMAGE_FW is not set +# CONFIG_MTD_SPLIT_WRGG_FW is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_UBI is not set +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_NVMEM is not set +# CONFIG_MTD_UIMAGE_SPLIT is not set +# CONFIG_MTD_VIRT_CONCAT is not set +# CONFIG_MTK_DEVAPC is not set +# CONFIG_MTK_MMC is not set +# CONFIG_MTK_MMSYS is not set +# CONFIG_MTK_T7XX is not set +# CONFIG_MTK_THERMAL is not set +# CONFIG_MULTIPLEXER is not set +CONFIG_MULTIUSER=y +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_MUX_ADG792A is not set +# CONFIG_MUX_ADGS1408 is not set +# CONFIG_MUX_GPIO is not set +# CONFIG_MUX_MMIO is not set +# CONFIG_MV643XX_ETH is not set +# CONFIG_MVMDIO is not set +# CONFIG_MVNETA_BM is not set +# CONFIG_MVSW61XX_PHY is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_MWAVE is not set +# CONFIG_MWL8K is not set +# CONFIG_MXC4005 is not set +# CONFIG_MXC6255 is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NATSEMI is not set +# CONFIG_NAU7802 is not set +# CONFIG_NBPFAXI_DMA is not set +# CONFIG_NCP_FS is not set +# CONFIG_NE2000 is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NEC_MARKEINS is not set +CONFIG_NET=y +# CONFIG_NETCONSOLE is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVSIM is not set +# CONFIG_NETFILTER is not set +# CONFIG_NETFILTER_ADVANCED is not set +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_EGRESS is not set +# CONFIG_NETFILTER_INGRESS is not set +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +# CONFIG_NETFILTER_NETLINK_HOOK is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NETFILTER_NETLINK_OSF is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_NETFILTER_XTABLES_COMPAT is not set +# CONFIG_NETFILTER_XT_CONNMARK is not set +# CONFIG_NETFILTER_XT_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +# CONFIG_NETFILTER_XT_MATCH_STATE is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_CT is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_LOG is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set +# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +# CONFIG_NETFS_STATS is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NETROM is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NET_9P is not set +# CONFIG_NET_ACT_BPF is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_ACT_CT is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_GATE is not set +# CONFIG_NET_ACT_IFE is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_MPLS is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_SAMPLE is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_SKBMOD is not set +# CONFIG_NET_ACT_TUNNEL_KEY is not set +# CONFIG_NET_ACT_VLAN is not set +CONFIG_NET_CADENCE=y +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_FW is not set +CONFIG_NET_CLS_IND=y +# CONFIG_NET_CLS_MATCHALL is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_U32 is not set +CONFIG_NET_CORE=y +# CONFIG_NET_DEVLINK is not set +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_NET_DSA is not set +# CONFIG_NET_DSA_AR9331 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_NET_DSA_LANTIQ_GSWIP is not set +# CONFIG_NET_DSA_LEGACY is not set +# CONFIG_NET_DSA_LOOP is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ8795 is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON is not set +# CONFIG_NET_DSA_MSCC_FELIX is not set +# CONFIG_NET_DSA_MSCC_SEVILLE is not set +# CONFIG_NET_DSA_MT7530 is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6XXX_PTP is not set +# CONFIG_NET_DSA_QCA8K is not set +# CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT is not set +# CONFIG_NET_DSA_REALTEK is not set +# CONFIG_NET_DSA_REALTEK_SMI is not set +# CONFIG_NET_DSA_SJA1105 is not set +# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set +# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set +# CONFIG_NET_DSA_TAG_8021Q is not set +# CONFIG_NET_DSA_TAG_AR9331 is not set +# CONFIG_NET_DSA_TAG_BRCM is not set +# CONFIG_NET_DSA_TAG_BRCM_LEGACY is not set +# CONFIG_NET_DSA_TAG_BRCM_PREPEND is not set +# CONFIG_NET_DSA_TAG_DSA is not set +# CONFIG_NET_DSA_TAG_EDSA is not set +# CONFIG_NET_DSA_TAG_GSWIP is not set +# CONFIG_NET_DSA_TAG_HELLCREEK is not set +# CONFIG_NET_DSA_TAG_KSZ is not set +# CONFIG_NET_DSA_TAG_LAN9303 is not set +# CONFIG_NET_DSA_TAG_MTK is not set +# CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set +# CONFIG_NET_DSA_TAG_QCA is not set +# CONFIG_NET_DSA_TAG_RTL4_A is not set +# CONFIG_NET_DSA_TAG_RTL8_4 is not set +# CONFIG_NET_DSA_TAG_RZN1_A5PSW is not set +# CONFIG_NET_DSA_TAG_SJA1105 is not set +# CONFIG_NET_DSA_TAG_TRAILER is not set +# CONFIG_NET_DSA_TAG_XRS700X is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX_SPI is not set +# CONFIG_NET_DSA_XRS700X_I2C is not set +# CONFIG_NET_DSA_XRS700X_MDIO is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_EMATCH_CANID is not set +# CONFIG_NET_EMATCH_CMP is not set +# CONFIG_NET_EMATCH_IPT is not set +# CONFIG_NET_EMATCH_META is not set +# CONFIG_NET_EMATCH_NBYTE is not set +CONFIG_NET_EMATCH_STACK=32 +# CONFIG_NET_EMATCH_TEXT is not set +# CONFIG_NET_EMATCH_U32 is not set +# CONFIG_NET_FAILOVER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_NET_IFE is not set +# CONFIG_NET_IPGRE is not set +CONFIG_NET_IPGRE_BROADCAST=y +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_IP_TUNNEL is not set +# CONFIG_NET_KEY is not set +# CONFIG_NET_KEY_MIGRATE is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_MEDIATEK_STAR_EMAC is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_NET_NCSI is not set +# CONFIG_NET_NSH is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_NET_PTP_CLASSIFY is not set +CONFIG_NET_RX_BUSY_POLL=y +# CONFIG_NET_SB1000 is not set +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CAKE is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_DEFAULT=y +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_ETS is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_NET_SCH_FQ is not set +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ_PIE is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCTPPROBE is not set +# CONFIG_NET_SELFTESTS is not set +CONFIG_NET_SOCK_MSG=y +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_TCPPROBE is not set +# CONFIG_NET_TC_SKB_EXT is not set +# CONFIG_NET_TEAM is not set +# CONFIG_NET_TULIP is not set +# CONFIG_NET_UDP_TUNNEL is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_NET_VENDOR_8390=y +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_NET_VENDOR_ADI=y +CONFIG_NET_VENDOR_AGERE=y +CONFIG_NET_VENDOR_ALACRITECH=y +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_NET_VENDOR_AMD=y +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_NET_VENDOR_ARC=y +# CONFIG_NET_VENDOR_ASIX is not set +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_NET_VENDOR_AURORA=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_NET_VENDOR_CADENCE=y +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_NET_VENDOR_CISCO=y +CONFIG_NET_VENDOR_CORTINA=y +# CONFIG_NET_VENDOR_DAVICOM is not set +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_VENDOR_DLINK=y +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_NET_VENDOR_ENGLEDER is not set +CONFIG_NET_VENDOR_EXAR=y +CONFIG_NET_VENDOR_EZCHIP=y +CONFIG_NET_VENDOR_FARADAY=y +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_NET_VENDOR_FUJITSU=y +# CONFIG_NET_VENDOR_FUNGIBLE is not set +CONFIG_NET_VENDOR_GOOGLE=y +CONFIG_NET_VENDOR_HISILICON=y +CONFIG_NET_VENDOR_HP=y +CONFIG_NET_VENDOR_HUAWEI=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_NET_VENDOR_LITEX is not set +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MELLANOX=y +CONFIG_NET_VENDOR_MICREL=y +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_NET_VENDOR_MICROSEMI=y +# CONFIG_NET_VENDOR_MICROSOFT is not set +CONFIG_NET_VENDOR_MYRI=y +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_NETERION=y +CONFIG_NET_VENDOR_NETRONOME=y +CONFIG_NET_VENDOR_NI=y +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_NET_VENDOR_OKI=y +CONFIG_NET_VENDOR_PACKET_ENGINES=y +CONFIG_NET_VENDOR_PENSANDO=y +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_NET_VENDOR_QUALCOMM=y +CONFIG_NET_VENDOR_RDC=y +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +CONFIG_NET_VENDOR_SIS=y +CONFIG_NET_VENDOR_SMSC=y +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_SOLARFLARE=y +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_NET_VENDOR_SUN=y +CONFIG_NET_VENDOR_SYNOPSYS=y +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_NET_VENDOR_TI=y +CONFIG_NET_VENDOR_TOSHIBA=y +# CONFIG_NET_VENDOR_VERTEXCOM is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_NET_VENDOR_WANGXUN is not set +CONFIG_NET_VENDOR_WIZNET=y +CONFIG_NET_VENDOR_XILINX=y +CONFIG_NET_VENDOR_XIRCOM=y +# CONFIG_NET_VRF is not set +# CONFIG_NET_XGENE is not set +CONFIG_NEW_LEDS=y +# CONFIG_NFC is not set +# CONFIG_NFP is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V2_ACL is not set +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NFS_ACL_SUPPORT is not set +CONFIG_NFS_COMMON=y +# CONFIG_NFS_DISABLE_UDP_SUPPORT is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_FSCACHE is not set +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_V4_1 is not set +# CONFIG_NFTL is not set +# CONFIG_NFT_BRIDGE_META is not set +# CONFIG_NFT_BRIDGE_REJECT is not set +# CONFIG_NFT_CONNLIMIT is not set +# CONFIG_NFT_DUP_IPV4 is not set +# CONFIG_NFT_DUP_IPV6 is not set +# CONFIG_NFT_FIB_IPV4 is not set +# CONFIG_NFT_FIB_IPV6 is not set +# CONFIG_NFT_FIB_NETDEV is not set +# CONFIG_NFT_FLOW_OFFLOAD is not set +# CONFIG_NFT_OBJREF is not set +# CONFIG_NFT_OSF is not set +# CONFIG_NFT_REJECT_NETDEV is not set +# CONFIG_NFT_RT is not set +# CONFIG_NFT_SET_BITMAP is not set +# CONFIG_NFT_SOCKET is not set +# CONFIG_NFT_SYNPROXY is not set +# CONFIG_NFT_TPROXY is not set +# CONFIG_NFT_TUNNEL is not set +# CONFIG_NFT_XFRM is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_BRIDGE is not set +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_LABELS is not set +# CONFIG_NF_CONNTRACK_MARK is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SECMARK is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CONNTRACK_ZONES is not set +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_HELPER is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_GRE is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_FLOW_TABLE is not set +# CONFIG_NF_FLOW_TABLE_PROCFS is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_BRIDGE is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_LOG_NETDEV is not set +# CONFIG_NF_LOG_SYSLOG is not set +# CONFIG_NF_NAT is not set +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_FTP is not set +# CONFIG_NF_NAT_H323 is not set +# CONFIG_NF_NAT_IRC is not set +# CONFIG_NF_NAT_NEEDED is not set +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_PROTO_GRE is not set +# CONFIG_NF_NAT_SIP is not set +# CONFIG_NF_NAT_SNMP_BASIC is not set +# CONFIG_NF_NAT_TFTP is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_TABLES is not set +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_TABLES_BRIDGE=y +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_IPV4=y +CONFIG_NF_TABLES_IPV6=y +CONFIG_NF_TABLES_NETDEV=y +# CONFIG_NF_TABLES_SET is not set +# CONFIG_NF_TPROXY_IPV4 is not set +# CONFIG_NF_TPROXY_IPV6 is not set +# CONFIG_NGBE is not set +# CONFIG_NI65 is not set +# CONFIG_NI903X_WDT is not set +# CONFIG_NIC7018_WDT is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_NIU is not set +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +CONFIG_NLATTR=y +# CONFIG_NLMON is not set +# CONFIG_NLM_XLP_BOARD is not set +# CONFIG_NLM_XLR_BOARD is not set +# CONFIG_NLS is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_NMI_LOG_BUF_SHIFT=13 +# CONFIG_NOA1305 is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_NORTEL_HERMES is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set +# CONFIG_NOZOMI is not set +# CONFIG_NO_BOOTMEM is not set +# CONFIG_NO_HZ is not set +# CONFIG_NO_HZ_FULL is not set +# CONFIG_NO_HZ_IDLE is not set +# CONFIG_NS83820 is not set +# CONFIG_NTB is not set +# CONFIG_NTFS3_64BIT_CLUSTER is not set +# CONFIG_NTFS3_FS is not set +# CONFIG_NTFS3_FS_POSIX_ACL is not set +# CONFIG_NTFS3_LZX_XPRESS is not set +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_NTP_PPS is not set +# CONFIG_NULL_TTY is not set +# CONFIG_NUMA is not set +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set +# CONFIG_NVM is not set +# CONFIG_NVMEM is not set +# CONFIG_NVMEM_BCM_OCOTP is not set +# CONFIG_NVMEM_IMX_OCOTP is not set +# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set +# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set +# CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_NVMEM_RMEM is not set +# CONFIG_NVMEM_SYSFS is not set +# CONFIG_NVMEM_U_BOOT_ENV is not set +# CONFIG_NVME_AUTH is not set +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TARGET is not set +# CONFIG_NVME_TCP is not set +# CONFIG_NVME_VERBOSE_ERRORS is not set +# CONFIG_NVRAM is not set +# CONFIG_NV_TCO is not set +# CONFIG_NXP_C45_TJA11XX_PHY is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_N_GSM is not set +# CONFIG_OABI_COMPAT is not set +# CONFIG_OBS600 is not set +# 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 +# CONFIG_OID_REGISTRY is not set +# CONFIG_OMAP2_DSS_DEBUG is not set +# CONFIG_OMAP2_DSS_DEBUGFS is not set +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP_OCP2SCP is not set +# CONFIG_OMAP_USB2 is not set +# CONFIG_OMFS_FS is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_OPEN_DICE is not set +# CONFIG_OPROFILE is not set +# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set +# CONFIG_OPT3001 is not set +CONFIG_OPTIMIZE_INLINING=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ORION_WATCHDOG is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_OSNOISE_TRACER is not set +CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_INDEX is not set +# CONFIG_OVERLAY_FS_METACOPY is not set +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +CONFIG_OVERLAY_FS_XINO_AUTO=y +# CONFIG_OWL_LOADER is not set +# CONFIG_P54_COMMON is not set +# CONFIG_PA12203001 is not set +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +# CONFIG_PACKING is not set +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_PAGE_POOL is not set +# CONFIG_PAGE_POOL_STATS is not set +# CONFIG_PAGE_REPORTING is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_TABLE_CHECK is not set +# CONFIG_PALMAS_GPADC is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_PANEL is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=1 +# CONFIG_PANTHERLORD_FF is not set +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +# CONFIG_PARPORT is not set +# CONFIG_PARPORT_1284 is not set +# CONFIG_PARPORT_AX88796 is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_PC is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARASAN_CF is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CS5535 is not set +# CONFIG_PATA_CS5536 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IMX is not set +# CONFIG_PATA_ISAPNP is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OCTEON_CF is not set +# CONFIG_PATA_OF_PLATFORM is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PCMCIA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_QDI is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_WINBOND_VLB is not set +# CONFIG_PC104 is not set +# CONFIG_PC300TOO is not set +# CONFIG_PCCARD is not set +# CONFIG_PCH_DMA is not set +# CONFIG_PCH_GBE is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_PCI is not set +# CONFIG_PCI200SYN is not set +# CONFIG_PCIEAER is not set +# CONFIG_PCIEAER_INJECT is not set +# CONFIG_PCIEASPM is not set +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCIE_AL is not set +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCIE_ARMADA_8K is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_PEER2PEER is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_TUNE_OFF is not set +# CONFIG_PCIE_BW is not set +# CONFIG_PCIE_CADENCE_HOST is not set +# CONFIG_PCIE_CADENCE_PLAT_HOST is not set +# CONFIG_PCIE_DPC is not set +# CONFIG_PCIE_DW_PLAT is not set +# CONFIG_PCIE_DW_PLAT_HOST is not set +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIE_IPROC is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_PCIE_LAYERSCAPE_GEN4 is not set +# CONFIG_PCIE_MEDIATEK_GEN3 is not set +# CONFIG_PCIE_MICROCHIP_HOST is not set +# CONFIG_PCIE_PTM is not set +# CONFIG_PCIE_XILINX is not set +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_PCI_ATMEL is not set +# CONFIG_PCI_CNB20LE_QUIRK is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set +# CONFIG_PCI_ENDPOINT is not set +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_PCI_FTPCI100 is not set +# CONFIG_PCI_HERMES is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_J721E_HOST is not set +# CONFIG_PCI_LAYERSCAPE is not set +# CONFIG_PCI_MESON is not set +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCI_PF_STUB is not set +# CONFIG_PCI_PRI is not set +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_SW_SWITCHTEC is not set +CONFIG_PCI_SYSCALL=y +# CONFIG_PCI_V3_SEMI is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCMCIA is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_ATMEL is not set +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_PCMCIA_LOAD_CIS is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_SPECTRUM is not set +# CONFIG_PCMCIA_SYM53C500 is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_XIRCOM is not set +# CONFIG_PCNET32 is not set +# CONFIG_PCPU_DEV_REFCNT is not set +# CONFIG_PCSPKR_PLATFORM is not set +# CONFIG_PCS_MTK_USXGMII is not set +# CONFIG_PCS_XPCS is not set +# CONFIG_PD6729 is not set +# CONFIG_PDA_POWER is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_PECI is not set +# CONFIG_PERCPU_STATS is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_EVENTS_AMD_POWER is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_PHANTOM is not set +# CONFIG_PHONET is not set +# CONFIG_PHYLIB is not set +# CONFIG_PHYLIB_LEDS is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PHY_BRCM_USB is not set +# CONFIG_PHY_CADENCE_DP is not set +# CONFIG_PHY_CADENCE_DPHY is not set +# CONFIG_PHY_CADENCE_DPHY_RX is not set +# CONFIG_PHY_CADENCE_SALVO is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CAN_TRANSCEIVER is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set +# CONFIG_PHY_FSL_IMX8MQ_USB is not set +# CONFIG_PHY_INGENIC_USB is not set +# CONFIG_PHY_INTEL_KEEMBAY_EMMC is not set +# CONFIG_PHY_LAN966X_SERDES is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +# CONFIG_PHY_MIXEL_MIPI_DPHY is not set +# CONFIG_PHY_MTK_HDMI is not set +# CONFIG_PHY_MTK_MIPI_DSI is not set +# CONFIG_PHY_MTK_XFI_TPHY is not set +# CONFIG_PHY_MVEBU_CP110_UTMI is not set +# CONFIG_PHY_OCELOT_SERDES is not set +# CONFIG_PHY_PISTACHIO_USB is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_QCOM_DWC3 is not set +# CONFIG_PHY_QCOM_USB_HS is not set +# CONFIG_PHY_QCOM_USB_HSIC is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_TUSB1210 is not set +# CONFIG_PHY_XGENE is not set +# CONFIG_PI433 is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_PID_NS is not set +CONFIG_PINCONF=y +# CONFIG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_AXP209 is not set +# CONFIG_PINCTRL_BCM2712 is not set +# CONFIG_PINCTRL_CEDARFORK is not set +# CONFIG_PINCTRL_CY8C95X0 is not set +# CONFIG_PINCTRL_EXYNOS is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set +# CONFIG_PINCTRL_ICELAKE is not set +# CONFIG_PINCTRL_INGENIC is not set +# CONFIG_PINCTRL_LPASS_LPI is not set +# CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set +# CONFIG_PINCTRL_MSM8953 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_MT6779 is not set +# CONFIG_PINCTRL_MT8167 is not set +# CONFIG_PINCTRL_MT8192 is not set +# CONFIG_PINCTRL_MT8195 is not set +# CONFIG_PINCTRL_MT8365 is not set +# CONFIG_PINCTRL_MTK_V2 is not set +# CONFIG_PINCTRL_OCELOT is not set +# CONFIG_PINCTRL_PISTACHIO is not set +# CONFIG_PINCTRL_RP1 is not set +# CONFIG_PINCTRL_SC7280 is not set +# CONFIG_PINCTRL_SC8180X is not set +# CONFIG_PINCTRL_SDX55 is not set +CONFIG_PINCTRL_SINGLE=y +# CONFIG_PINCTRL_SM6115 is not set +# CONFIG_PINCTRL_SM6125 is not set +# CONFIG_PINCTRL_SM8350 is not set +# CONFIG_PINCTRL_STMFX is not set +# CONFIG_PINCTRL_SX150X is not set +# CONFIG_PING is not set +CONFIG_PINMUX=y +# CONFIG_PKCS7_MESSAGE_PARSER is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PL330_DMA is not set +# CONFIG_PLATFORM_MHU is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_PLIP is not set +# CONFIG_PLX_DMA is not set +# CONFIG_PLX_HERMES is not set +# CONFIG_PM is not set +# CONFIG_PMBUS is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMS7003 is not set +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_PM_USERSPACE_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_POSIX_TIMERS=y +# CONFIG_POWERCAP is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_RESET_BRCMKONA is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LINKSTATION is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_PIIX4_POWEROFF is not set +# CONFIG_POWER_RESET_QNAP is not set +# CONFIG_POWER_RESET_REGULATOR is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_POWER_RESET_VERSATILE is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_POWER_SUPPLY_HWMON is not set +# CONFIG_PPC4xx_GPIO is not set +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_256K_PAGES is not set +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_64K_PAGES is not set +# CONFIG_PPC_DISABLE_WERROR is not set +# CONFIG_PPC_EMULATED_STATS is not set +# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set +# CONFIG_PPC_QUEUED_SPINLOCKS is not set +# CONFIG_PPP is not set +# CONFIG_PPPOATM is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_FILTER=y +# CONFIG_PPP_MPPE is not set +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPS is not set +# CONFIG_PPS_CLIENT_GPIO is not set +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set +# CONFIG_PPS_DEBUG is not set +# CONFIG_PPTP is not set +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_DYNAMIC is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PRESTERA is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_PRIME_NUMBERS is not set +CONFIG_PRINTK=y +# CONFIG_PRINTK_CALLER is not set +# CONFIG_PRINTK_INDEX is not set +CONFIG_PRINTK_NMI=y +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +# CONFIG_PRINTK_TIME is not set +CONFIG_PRINT_STACK_DEPTH=64 +# CONFIG_PRISM2_USB is not set +# CONFIG_PRISM54 is not set +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +# CONFIG_PROC_PAGE_MONITOR is not set +# CONFIG_PROC_STRIPPED is not set +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILING is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_PROVE_RAW_LOCK_NESTING is not set +# CONFIG_PROVE_RCU is not set +# CONFIG_PROVE_RCU_LIST is not set +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_PSAMPLE is not set +# CONFIG_PSB6970_PHY is not set +# CONFIG_PSE_CONTROLLER is not set +# CONFIG_PSI is not set +# CONFIG_PSTORE is not set +# CONFIG_PSTORE_842_COMPRESS is not set +# CONFIG_PSTORE_BLK is not set +# CONFIG_PSTORE_COMPRESS is not set +# CONFIG_PSTORE_CONSOLE is not set +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +# CONFIG_PSTORE_DEFLATE_COMPRESS is not set +# CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_FTRACE is not set +# CONFIG_PSTORE_LZ4HC_COMPRESS is not set +# CONFIG_PSTORE_LZ4_COMPRESS is not set +# CONFIG_PSTORE_LZO_COMPRESS is not set +# CONFIG_PSTORE_PMSG is not set +# CONFIG_PSTORE_RAM is not set +# CONFIG_PSTORE_ZSTD_COMPRESS is not set +# CONFIG_PTDUMP_DEBUGFS is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set +# CONFIG_PTP_1588_CLOCK_IDTCM is not set +# CONFIG_PTP_1588_CLOCK_IXP46X is not set +# CONFIG_PTP_1588_CLOCK_KVM is not set +# CONFIG_PTP_1588_CLOCK_OCP is not set +# CONFIG_PTP_1588_CLOCK_PCH is not set +# CONFIG_PTP_1588_CLOCK_VMW is not set +# CONFIG_PUBLIC_KEY_ALGO_RSA is not set +# CONFIG_PVPANIC is not set +# CONFIG_PWM is not set +# CONFIG_PWM_ATMEL_TCB is not set +# CONFIG_PWM_CLK is not set +# CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_DWC is not set +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_IMG is not set +# CONFIG_PWM_JZ4740 is not set +# CONFIG_PWM_MEDIATEK is not set +# CONFIG_PWM_PCA9685 is not set +# CONFIG_PWM_RASPBERRYPI_POE is not set +# CONFIG_PWM_RP1 is not set +# CONFIG_PWM_XILINX is not set +CONFIG_PWRSEQ_EMMC=y +# CONFIG_PWRSEQ_SD8787 is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000 is not set +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCA7000_UART is not set +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA807X_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCOM_A7PLL is not set +# CONFIG_QCOM_BAM_DMUX is not set +# CONFIG_QCOM_EMAC is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_QCOM_GPI_DMA is not set +# CONFIG_QCOM_HIDMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_LMH is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_QCOM_SPMI_ADC5 is not set +# CONFIG_QCOM_SPMI_ADC_TM5 is not set +# CONFIG_QCOM_SPMI_IADC is not set +# CONFIG_QCOM_SPMI_TEMP_ALARM is not set +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_QCOM_SSC_BLOCK_BUS is not set +# CONFIG_QED is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_QORIQ_CPUFREQ is not set +# CONFIG_QORIQ_THERMAL is not set +# CONFIG_QRTR is not set +# CONFIG_QRTR_MHI is not set +# CONFIG_QRTR_TUN is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_QUEUED_LOCK_STAT is not set +# CONFIG_QUICC_ENGINE is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +# CONFIG_R3964 is not set +# CONFIG_R6040 is not set +# CONFIG_R8169 is not set +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +# CONFIG_R8723AU is not set +# CONFIG_RADIO_ADAPTERS is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +# CONFIG_RAID6_PQ_BENCHMARK is not set +# CONFIG_RAID_ATTRS is not set +# CONFIG_RALINK is not set +# CONFIG_RANDOM32_SELFTEST is not set +# CONFIG_RANDOMIZE_BASE is not set +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set +CONFIG_RANDOM_TRUST_BOOTLOADER=y +CONFIG_RANDOM_TRUST_CPU=y +# CONFIG_RANDSTRUCT_NONE is not set +# CONFIG_RAPIDIO is not set +# CONFIG_RAS is not set +# CONFIG_RASPBERRYPI_GPIOMEM is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_RCU_EXPERT is not set +CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +CONFIG_RCU_KTHREAD_PRIO=0 +CONFIG_RCU_NEED_SEGCBLIST=y +# CONFIG_RCU_PERF_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +# CONFIG_RCU_SCALE_TEST is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_STRICT_GRACE_PERIOD is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 +# CONFIG_RCU_TRACE is not set +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_RC_CORE is not set +# CONFIG_RC_DECODERS is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_RC_MAP is not set +# CONFIG_RC_XBOX_DVD is not set +# CONFIG_RDS is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_GZIP is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_ZSTD is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_READ_ONLY_THP_FOR_FS is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_REDWOOD is not set +# CONFIG_REED_SOLOMON is not set +# CONFIG_REED_SOLOMON_DEC8 is not set +# CONFIG_REED_SOLOMON_ENC8 is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_REGMAP is not set +# CONFIG_REGMAP_I2C is not set +# CONFIG_REGMAP_MMIO is not set +# CONFIG_REGMAP_SPI is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_88PG86X is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9121 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_FAN53880 is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX20086 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX77826 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8893 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MCP16502 is not set +# CONFIG_REGULATOR_MP5416 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MP886X is not set +# CONFIG_REGULATOR_MPQ7920 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_MT6359 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +# CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_RT5759 is not set +# CONFIG_REGULATOR_RT6160 is not set +# CONFIG_REGULATOR_RT6245 is not set +# CONFIG_REGULATOR_RTMV20 is not set +# CONFIG_REGULATOR_RTQ2134 is not set +# CONFIG_REGULATOR_RTQ6752 is not set +# CONFIG_REGULATOR_SLG51000 is not set +# CONFIG_REGULATOR_SY8106A is not set +# CONFIG_REGULATOR_SY8824X is not set +# CONFIG_REGULATOR_SY8827N is not set +# CONFIG_REGULATOR_TI_ABB is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS6286X is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_VCTRL is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_FS_POSIX_ACL is not set +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_RELAY is not set +# CONFIG_RELOCATABLE is not set +# CONFIG_REMOTEPROC is not set +# CONFIG_RENESAS_PHY is not set +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_BRCMSTB is not set +# CONFIG_RESET_BRCMSTB_RESCAL is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_RESET_IMX7 is not set +# CONFIG_RESET_INTEL_GW is not set +# CONFIG_RESET_LANTIQ is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SIMPLE is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_RESET_TEGRA_BPMP is not set +# CONFIG_RESET_TI_SYSCON is not set +# CONFIG_RESET_TI_TPS380X is not set +# CONFIG_RESET_ZYNQ is not set +# CONFIG_RFD77402 is not set +# CONFIG_RFD_FTL is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_FULL is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_LEDS is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RICHTEK_RTQ6056 is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_RMNET is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_ROCKER is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_ROSE is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_VIRTIO is not set +# CONFIG_RPMSG_WWAN_CTRL is not set +# CONFIG_RPR0521 is not set +# CONFIG_RSEQ is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_RTC_DEBUG is not set +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_ARMADA38X is not set +# CONFIG_RTC_DRV_AU1XXX is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_CADENCE is not set +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1307_CENTURY is not set +# CONFIG_RTC_DRV_DS1307_HWMON is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_EP93XX is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_GENERIC is not set +# CONFIG_RTC_DRV_GOLDFISH is not set +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_JZ4740 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MAX77686 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_MOXART is not set +# CONFIG_RTC_DRV_MPC5121 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_MT2712 is not set +# CONFIG_RTC_DRV_NCT3018Y is not set +# CONFIG_RTC_DRV_OMAP is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_PS3 is not set +# CONFIG_RTC_DRV_PT7C4338 is not set +# CONFIG_RTC_DRV_R7301 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_RTC7301 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_SD3078 is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_SUN6I is not set +# CONFIG_RTC_DRV_TEGRA is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_XGENE is not set +# CONFIG_RTC_DRV_ZYNQMP is not set +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_LIB=y +# CONFIG_RTC_NVMEM is not set +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_RTL8192E is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTL8306_PHY is not set +# CONFIG_RTL8366RB_PHY is not set +# CONFIG_RTL8366S_PHY is not set +# CONFIG_RTL8366_SMI is not set +# CONFIG_RTL8366_SMI_DEBUG_FS is not set +# CONFIG_RTL8367B_PHY is not set +# CONFIG_RTL8367_PHY is not set +# CONFIG_RTLLIB is not set +# CONFIG_RTL_CARDS is not set +# CONFIG_RTS5208 is not set +CONFIG_RT_MUTEXES=y +# CONFIG_RUNTIME_DEBUG is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_RV is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_RXKAD=y +# CONFIG_S2IO is not set +# CONFIG_SAMPLES is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_DWC is not set +# CONFIG_SATA_DWC_OLD_DMA is not set +# CONFIG_SATA_FSL is not set +# CONFIG_SATA_HIGHBANK is not set +# CONFIG_SATA_HOST is not set +# CONFIG_SATA_INIC162X is not set +CONFIG_SATA_MOBILE_LPM_POLICY=0 +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PMP is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_RCAR is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SBC_FITPC2_WATCHDOG is not set +CONFIG_SBITMAP=y +# CONFIG_SC92031 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_SCACHE_DEBUGFS is not set +# CONFIG_SCC is not set +# CONFIG_SCD30_CORE is not set +# CONFIG_SCD4X is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_CLUSTER is not set +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHED_HRTICK=y +# CONFIG_SCHED_MC is not set +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_SCHED_SMT is not set +CONFIG_SCHED_STACK_END_CHECK=y +# CONFIG_SCHED_TRACER is not set +# CONFIG_SCR24X is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_BNX2X_FCOE is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CHELSIO_FCOE is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_HISI_SAS is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_ISCI is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_LPFC is not set +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_MPI3MR is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVSAS_DEBUG is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_PMCRAID is not set +CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_VIRTIO is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SC_CAMCC_7180 is not set +# CONFIG_SC_DISPCC_7280 is not set +# CONFIG_SC_GCC_7280 is not set +# CONFIG_SC_GCC_8180X is not set +# CONFIG_SC_GPUCC_7280 is not set +# CONFIG_SC_GPUCC_8280XP is not set +# CONFIG_SC_VIDEOCC_7280 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SDM_GPUCC_660 is not set +# CONFIG_SDM_MMCC_660 is not set +# CONFIG_SDR_MAX2175 is not set +# CONFIG_SDR_PLATFORM_DRIVERS is not set +# CONFIG_SDX_GCC_55 is not set +# CONFIG_SD_ADC_MODULATOR is not set +# CONFIG_SECCOMP is not set +# CONFIG_SECCOMP_CACHE_DEBUG is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_APPARMOR is not set +CONFIG_SECURITY_DMESG_RESTRICT=y +# CONFIG_SECURITY_LANDLOCK is not set +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_SAFESETID is not set +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 +# CONFIG_SECURITY_SELINUX_DEVELOP is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_YAMA is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_SENSEAIR_SUNRISE_CO2 is not set +# CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SENSIRION_SGP40 is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM1266 is not set +# CONFIG_SENSORS_ADM1275 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AHT10 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATK0110 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_BEL_PFE is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BPA_RS600 is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU is not set +# CONFIG_SENSORS_DELL_SMM is not set +# CONFIG_SENSORS_DELTA_AHE50DC_FAN is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DPS920AB is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC2305 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_FSP_3Y is not set +# CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_GSC is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HMC5843 is not set +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_I5500 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_IBM_CFFPS is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA238 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_INSPUR_IPSPS is not set +# CONFIG_SENSORS_IR35221 is not set +# CONFIG_SENSORS_IR36021 is not set +# CONFIG_SENSORS_IR38064 is not set +# CONFIG_SENSORS_IRPS5401 is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_SENSORS_ISL68137 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LM25066 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_LT7182S is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2947_SPI is not set +# CONFIG_SENSORS_LTC2978 is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2992 is not set +# CONFIG_SENSORS_LTC3815 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LTQ_CPUTEMP is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX127 is not set +# CONFIG_SENSORS_MAX15301 is not set +# CONFIG_SENSORS_MAX16064 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX16601 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX20730 is not set +# CONFIG_SENSORS_MAX20751 is not set +# CONFIG_SENSORS_MAX31722 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX31760 is not set +# CONFIG_SENSORS_MAX31785 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MAX34440 is not set +# CONFIG_SENSORS_MAX6620 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX8688 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_MP2888 is not set +# CONFIG_SENSORS_MP2975 is not set +# CONFIG_SENSORS_MP5023 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT6775_I2C is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_NSA320 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set +# CONFIG_SENSORS_NZXT_SMART2 is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_PIM4328 is not set +# CONFIG_SENSORS_PLI1209BC is not set +# CONFIG_SENSORS_PM6764TR is not set +# CONFIG_SENSORS_PMBUS is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_PXE1610 is not set +# CONFIG_SENSORS_Q54SJ108A2 is not set +# CONFIG_SENSORS_RM3100_I2C is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSORS_RP1_ADC is not set +# CONFIG_SENSORS_SBRMI is not set +# CONFIG_SENSORS_SBTSI is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHT4x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_STPDDC60 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP464 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_TPS23861 is not set +# CONFIG_SENSORS_TPS40422 is not set +# CONFIG_SENSORS_TPS53679 is not set +# CONFIG_SENSORS_TPS546D24 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_SENSORS_UCD9000 is not set +# CONFIG_SENSORS_UCD9200 is not set +# CONFIG_SENSORS_VEXPRESS is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_XDPE122 is not set +# CONFIG_SENSORS_XDPE152 is not set +# CONFIG_SENSORS_XGENE is not set +# CONFIG_SENSORS_ZL6100 is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_16550A_VARIANTS=y +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_ASPEED_VUART is not set +# CONFIG_SERIAL_8250_BOCA is not set +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250_EXAR is not set +# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_FINTEK is not set +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +# CONFIG_SERIAL_8250_INGENIC is not set +# CONFIG_SERIAL_8250_LPSS is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_MID is not set +# CONFIG_SERIAL_8250_MOXA is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_PERICOM is not set +# CONFIG_SERIAL_8250_RSA is not set +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_BCM63XX is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_DEV_BUS is not set +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_SIFIVE is not set +# CONFIG_SERIAL_SPRD is not set +# CONFIG_SERIAL_STM32 is not set +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_UARTLITE is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIO is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_SUN4I_PS2 is not set +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +# CONFIG_SFC_SIENA is not set +# CONFIG_SFI is not set +# CONFIG_SFP is not set +# CONFIG_SF_PDMA is not set +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP30 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SGI_MFD_IOC3 is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SG_POOL is not set +# CONFIG_SG_SPLIT is not set +# CONFIG_SHADOW_CALL_STACK is not set +CONFIG_SHMEM=y +# CONFIG_SHRINKER_DEBUG is not set +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_SH_ETH is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_SI1133 is not set +# CONFIG_SI1145 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +CONFIG_SIGNALFD=y +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_SIMPLE_GPIO is not set +# CONFIG_SIMPLE_PM_BUS is not set +# CONFIG_SIOX is not set +# CONFIG_SIS190 is not set +# CONFIG_SIS900 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SKY2_DEBUG is not set +# CONFIG_SLAB is not set +CONFIG_SLABINFO=y +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SLAB_FREELIST_RANDOM=y +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLHC is not set +# CONFIG_SLICOSS is not set +# CONFIG_SLIMBUS is not set +# CONFIG_SLIP is not set +# CONFIG_SLOB is not set +CONFIG_SLUB=y +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_MEMCG_SYSFS_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SMARTJOYPLUS_FF is not set +# CONFIG_SMB_SERVER is not set +# CONFIG_SMC911X is not set +# CONFIG_SMC9194 is not set +# CONFIG_SMC91X is not set +# CONFIG_SMP is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_SMS_SDIO_DRV is not set +# CONFIG_SMS_USB_DRV is not set +# CONFIG_SM_CAMCC_8250 is not set +# CONFIG_SM_FTL is not set +# CONFIG_SM_GCC_6115 is not set +# CONFIG_SM_GCC_6125 is not set +# CONFIG_SM_GCC_6350 is not set +# CONFIG_SM_GCC_6375 is not set +# CONFIG_SM_GCC_8350 is not set +# CONFIG_SND is not set +# CONFIG_SND_AC97_POWER_SAVE is not set +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ADLIB is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_AMD_ACP_CONFIG is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_ASIHPI is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_ATMEL_AC97C is not set +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AUDIO_GRAPH_CARD is not set +# CONFIG_SND_AUDIO_GRAPH_CARD2 is not set +# CONFIG_SND_AUDIO_GRAPH_SCU_CARD is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_BCM2835 is not set +# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4236 is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5530 is not set +# CONFIG_SND_CS5535AUDIO is not set +# CONFIG_SND_CTL_FAST_LOOKUP is not set +# CONFIG_SND_CTL_INPUT_VALIDATION is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_DESIGNWARE_I2S is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_EDMA_SOC is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1688 is not set +# CONFIG_SND_ES18XX is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FIREWIRE is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_HDA_CODEC_CS8409 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDA_INTEL_DETECT_DMIC is not set +# CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM is not set +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_HWDEP is not set +# CONFIG_SND_I2S_HI6210_I2S is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +# CONFIG_SND_ISA is not set +# CONFIG_SND_JZ4740_SOC_I2S is not set +# CONFIG_SND_KIRKWOOD_SOC is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +CONFIG_SND_MAX_CARDS=16 +# CONFIG_SND_MIA is not set +# CONFIG_SND_MIPS is not set +# CONFIG_SND_MIRO is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MPC52xx_SOC_EFIKA is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_MXS_SOC is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_OPL3SA2 is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_OSSEMUL=y +# CONFIG_SND_OXYGEN is not set +CONFIG_SND_PCI=y +# CONFIG_SND_PCM is not set +# CONFIG_SND_PCMCIA is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_PCM_TIMER is not set +# CONFIG_SND_PCM_XRUN_DEBUG is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_PDAUDIOCF is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_POWERPC_SOC is not set +# CONFIG_SND_PPC is not set +CONFIG_SND_PROC_FS=y +# CONFIG_SND_RAWMIDI is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_RTCTIMER is not set +# CONFIG_SND_SB16 is not set +# CONFIG_SND_SB8 is not set +# CONFIG_SND_SBAWE is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_SERIAL_GENERIC is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SIMPLE_SCU_CARD is not set +# CONFIG_SND_SIS7019 is not set +# CONFIG_SND_SOC is not set +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_AD193X_I2C is not set +# CONFIG_SND_SOC_AD193X_SPI is not set +# CONFIG_SND_SOC_ADAU1372_I2C is not set +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_ADAU1761_I2C is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_ADAU7002 is not set +# CONFIG_SND_SOC_ADAU7118_HW is not set +# CONFIG_SND_SOC_ADAU7118_I2C is not set +# CONFIG_SND_SOC_ADI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4118 is not set +# CONFIG_SND_SOC_AK4375 is not set +# CONFIG_SND_SOC_AK4458 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_AK5558 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_AMD_ACP is not set +# CONFIG_SND_SOC_AMD_ACP3x is not set +# CONFIG_SND_SOC_AMD_ACP5x is not set +# CONFIG_SND_SOC_AMD_RENOIR is not set +# CONFIG_SND_SOC_AU1XAUDIO is not set +# CONFIG_SND_SOC_AU1XPSC is not set +# CONFIG_SND_SOC_AW8738 is not set +# CONFIG_SND_SOC_BD28623 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS35L33 is not set +# CONFIG_SND_SOC_CS35L34 is not set +# CONFIG_SND_SOC_CS35L35 is not set +# CONFIG_SND_SOC_CS35L36 is not set +# CONFIG_SND_SOC_CS35L41_I2C is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L45_I2C is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS4234 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L42 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS42L83 is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS43130 is not set +# CONFIG_SND_SOC_CS4341 is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CS53L30 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_DA7213 is not set +# CONFIG_SND_SOC_DIO2125 is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8326 is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_EUKREA_TLV320 is not set +# CONFIG_SND_SOC_FSL_ASOC_CARD is not set +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_AUD2HTX is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_RPMSG is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_XCVR is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_HDA is not set +# CONFIG_SND_SOC_ICS43432 is not set +# CONFIG_SND_SOC_IMG is not set +# CONFIG_SND_SOC_IMX_AUDMIX is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_IMX_CARD is not set +# CONFIG_SND_SOC_IMX_ES8328 is not set +# CONFIG_SND_SOC_IMX_HDMI is not set +# CONFIG_SND_SOC_IMX_RPMSG is not set +# CONFIG_SND_SOC_IMX_SPDIF is not set +# CONFIG_SND_SOC_IMX_WM8962 is not set +# CONFIG_SND_SOC_INNO_RK3036 is not set +# CONFIG_SND_SOC_INTEL_APL is not set +# CONFIG_SND_SOC_INTEL_BAYTRAIL is not set +# CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH is not set +# CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH is not set +# CONFIG_SND_SOC_INTEL_BXT_RT298_MACH is not set +# CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH is not set +# CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH is not set +# CONFIG_SND_SOC_INTEL_CATPT is not set +# CONFIG_SND_SOC_INTEL_CFL is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH is not set +# CONFIG_SND_SOC_INTEL_CML_H is not set +# CONFIG_SND_SOC_INTEL_CML_LP is not set +# CONFIG_SND_SOC_INTEL_CNL is not set +# CONFIG_SND_SOC_INTEL_GLK is not set +# CONFIG_SND_SOC_INTEL_HASWELL is not set +# CONFIG_SND_SOC_INTEL_KBL is not set +# CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH is not set +# CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH is not set +# CONFIG_SND_SOC_INTEL_KEEMBAY is not set +# CONFIG_SND_SOC_INTEL_SKL is not set +# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH is not set +# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH is not set +# CONFIG_SND_SOC_INTEL_SKL_RT286_MACH is not set +# CONFIG_SND_SOC_INTEL_SKYLAKE is not set +# CONFIG_SND_SOC_INTEL_SST is not set +CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y +# CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES is not set +# CONFIG_SND_SOC_JZ4725B_CODEC is not set +# CONFIG_SND_SOC_JZ4740_CODEC is not set +# CONFIG_SND_SOC_JZ4770_CODEC is not set +# CONFIG_SND_SOC_LPASS_RX_MACRO is not set +# CONFIG_SND_SOC_LPASS_TX_MACRO is not set +# CONFIG_SND_SOC_LPASS_VA_MACRO is not set +# CONFIG_SND_SOC_LPASS_WSA_MACRO is not set +# CONFIG_SND_SOC_MA120X0P is not set +# CONFIG_SND_SOC_MAX9759 is not set +# CONFIG_SND_SOC_MAX98088 is not set +# CONFIG_SND_SOC_MAX98357A is not set +# CONFIG_SND_SOC_MAX98373 is not set +# CONFIG_SND_SOC_MAX98373_I2C is not set +# CONFIG_SND_SOC_MAX98390 is not set +# CONFIG_SND_SOC_MAX98396 is not set +# CONFIG_SND_SOC_MAX98504 is not set +# CONFIG_SND_SOC_MAX98520 is not set +# CONFIG_SND_SOC_MAX9860 is not set +# CONFIG_SND_SOC_MAX9867 is not set +# CONFIG_SND_SOC_MAX98927 is not set +# CONFIG_SND_SOC_MEDIATEK is not set +# CONFIG_SND_SOC_MPC5200_AC97 is not set +# CONFIG_SND_SOC_MPC5200_I2S is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set +# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set +# CONFIG_SND_SOC_MT2701 is not set +# CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_MT6359 is not set +# CONFIG_SND_SOC_MT6359_ACCDET is not set +# CONFIG_SND_SOC_MT6660 is not set +# CONFIG_SND_SOC_MT6797 is not set +# CONFIG_SND_SOC_MT8173 is not set +# CONFIG_SND_SOC_MT8183 is not set +# CONFIG_SND_SOC_MT8186 is not set +# CONFIG_SND_SOC_MT8192 is not set +# CONFIG_SND_SOC_MT8195 is not set +# CONFIG_SND_SOC_MTK_BTCVSD is not set +# CONFIG_SND_SOC_NAU8315 is not set +# CONFIG_SND_SOC_NAU8540 is not set +# CONFIG_SND_SOC_NAU8810 is not set +# CONFIG_SND_SOC_NAU8821 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_SND_SOC_NAU8824 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1789_I2C is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM179X_I2C is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_I2C is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_I2C is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM5102A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_QCOM is not set +# CONFIG_SND_SOC_RK3328 is not set +# CONFIG_SND_SOC_RK817 is not set +# CONFIG_SND_SOC_ROCKCHIP is not set +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5659 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_RT9120 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIMPLE_MUX is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SOF_TOPLEVEL is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SRC4XXX_I2C is not set +# CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2518 is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS2562 is not set +# CONFIG_SND_SOC_TAS2764 is not set +# CONFIG_SND_SOC_TAS2770 is not set +# CONFIG_SND_SOC_TAS2780 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TAS5720 is not set +# CONFIG_SND_SOC_TAS5805M is not set +# CONFIG_SND_SOC_TAS6424 is not set +# CONFIG_SND_SOC_TDA7419 is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TFA989X is not set +# CONFIG_SND_SOC_TLV320ADC3XXX is not set +# CONFIG_SND_SOC_TLV320ADCX140 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_TSCS42XX is not set +# CONFIG_SND_SOC_TSCS454 is not set +# CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8731_I2C is not set +# CONFIG_SND_SOC_WM8731_SPI is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8782 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8940 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set +# CONFIG_SND_SOC_XILINX_I2S is not set +# CONFIG_SND_SOC_XILINX_SPDIF is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SOC_ZX_AUD96P22 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI is not set +# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI is not set +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_TEST_COMPONENT is not set +# CONFIG_SND_TIMER is not set +# CONFIG_SND_TRIDENT is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_US122L is not set +# CONFIG_SND_USB_USX2Y is not set +# CONFIG_SND_USB_VARIAX is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTIO is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_WAVEFRONT is not set +CONFIG_SND_X86=y +# CONFIG_SND_XEN_FRONTEND is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SNI_RM is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_SOCK_CGROUP_DATA is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_BRCMSTB is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_SOC_HAS_OMAP2_SDRC is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_TI is not set +# CONFIG_SOFTLOCKUP_DETECTOR is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SONYPI is not set +# CONFIG_SONY_LAPTOP is not set +# CONFIG_SOUND is not set +# CONFIG_SOUNDWIRE is not set +# CONFIG_SOUND_OSS_CORE is not set +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +# CONFIG_SOUND_PRIME is not set +# CONFIG_SP5100_TCO is not set +# CONFIG_SPARSEMEM_MANUAL is not set +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +# CONFIG_SPARSE_IRQ is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_SPEAKUP is not set +# CONFIG_SPI is not set +# CONFIG_SPINLOCK_TEST is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AU1550 is not set +# CONFIG_SPI_AX88796C is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BCM2835 is not set +# CONFIG_SPI_BCM63XX_HSSPI is not set +# CONFIG_SPI_BCM_QSPI is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_BUTTERFLY is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_DSPI is not set +# CONFIG_SPI_FSL_ESPI is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_GPIO_OLD is not set +# CONFIG_SPI_IMG_SPFI is not set +# CONFIG_SPI_LANTIQ_SSC is not set +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_SPI_MEM is not set +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MPC52xx is not set +# CONFIG_SPI_MPC52xx_PSC is not set +# CONFIG_SPI_MTK_QUADSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OCTEON is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_ORION is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PPC4xx is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_QCOM_QSPI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_S3C64XX is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_THUNDERX is not set +# CONFIG_SPI_TI_QSPI is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_XWAY is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_SPMI is not set +# CONFIG_SPS30 is not set +# CONFIG_SPS30_I2C is not set +# CONFIG_SPS30_SERIAL is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_EMBEDDED=y +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_ZLIB is not set +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SRAM is not set +# CONFIG_SRF04 is not set +# CONFIG_SRF08 is not set +# CONFIG_SSB is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB_SDIOHOST is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSFDC is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_STACKPROTECTOR_PER_TASK is not set +# CONFIG_STACKPROTECTOR_STRONG is not set +# CONFIG_STACKTRACE is not set +# CONFIG_STACKTRACE_BUILD_ID is not set +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_STACK_HASH_ORDER=20 +# CONFIG_STACK_TRACER is not set +# CONFIG_STACK_VALIDATION is not set +CONFIG_STAGING=y +# CONFIG_STAGING_BOARD is not set +# CONFIG_STAGING_GASKET_FRAMEWORK is not set +# CONFIG_STAGING_MEDIA is not set +CONFIG_STANDALONE=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_STDBINUTILS=y +# CONFIG_STE10XP is not set +# CONFIG_STE_MODEM_RPROC is not set +# CONFIG_STK3310 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set +# CONFIG_STM is not set +# CONFIG_STMMAC_ETH is not set +# CONFIG_STMMAC_PCI is not set +# CONFIG_STMMAC_PLATFORM is not set +# CONFIG_STMMAC_SELFTESTS is not set +# CONFIG_STMPE_ADC is not set +# CONFIG_STM_DUMMY is not set +# CONFIG_STM_SOURCE_CONSOLE is not set +CONFIG_STP=y +# CONFIG_STREAM_PARSER is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_STRICT_MODULE_RWX=y +# CONFIG_STRING_SELFTEST is not set +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_STX104 is not set +# CONFIG_ST_UVIS25 is not set +# CONFIG_SUN4I_GPADC is not set +# CONFIG_SUN50I_DE2_BUS is not set +# CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_SUNRPC is not set +# CONFIG_SUNRPC_DEBUG is not set +CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y +# CONFIG_SUNRPC_GSS is not set +# 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 +# CONFIG_SWCONFIG is not set +# CONFIG_SWCONFIG_B53 is not set +# CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set +# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set +# CONFIG_SWCONFIG_B53_SPI_DRIVER is not set +# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set +# CONFIG_SWCONFIG_LEDS is not set +# CONFIG_SW_SYNC is not set +# CONFIG_SX9310 is not set +# CONFIG_SX9324 is not set +# CONFIG_SX9360 is not set +# CONFIG_SX9500 is not set +# CONFIG_SXGBE_ETH is not set +CONFIG_SYMBOLIC_ERRNAME=y +# CONFIG_SYNCLINK_CS is not set +# CONFIG_SYNC_FILE is not set +# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set +# CONFIG_SYNTH_EVENTS is not set +# CONFIG_SYNTH_EVENT_GEN_TEST is not set +CONFIG_SYN_COOKIES=y +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_SYSCTL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSFS=y +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSV68_PARTITION is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_T5403 is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_TASKS_RCU is not set +# CONFIG_TASK_XACCT is not set +# CONFIG_TC35815 is not set +# CONFIG_TCG_ATMEL is not set +# CONFIG_TCG_CRB is not set +# CONFIG_TCG_FTPM_TEE is not set +# CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_NSC is not set +# CONFIG_TCG_ST33_I2C is not set +# CONFIG_TCG_TIS is not set +# CONFIG_TCG_TIS_I2C is not set +# CONFIG_TCG_TIS_I2C_ATMEL is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_TIS_SPI is not set +# CONFIG_TCG_TIS_ST33ZP24_I2C is not set +# CONFIG_TCG_TIS_ST33ZP24_SPI is not set +# CONFIG_TCG_TPM is not set +# CONFIG_TCG_VTPM_PROXY is not set +# CONFIG_TCG_XEN is not set +# CONFIG_TCIC is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BBR is not set +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_CDG is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_MD5SIG is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +# CONFIG_TEE is not set +# CONFIG_TEGRA_AHB is not set +# CONFIG_TEGRA_HOST1X is not set +# CONFIG_TEHUTI is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +# CONFIG_TEST_BITFIELD is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set +# CONFIG_TEST_DEBUG_VIRTUAL is not set +# CONFIG_TEST_DIV64 is not set +# CONFIG_TEST_DYNAMIC_DEBUG is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_KASAN_MODULE is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_LOCKUP is not set +# CONFIG_TEST_MAPLE_TREE is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_POWER is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SCANF is not set +# CONFIG_TEST_SIPHASH is not set +# CONFIG_TEST_SORT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UBSAN is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +CONFIG_TEXTSEARCH=y +# CONFIG_TEXTSEARCH_BM is not set +# CONFIG_TEXTSEARCH_FSM is not set +# CONFIG_TEXTSEARCH_KMP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_THERMAL_MMIO is not set +# CONFIG_THERMAL_NETLINK is not set +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +# CONFIG_THINKPAD_ACPI is not set +CONFIG_THIN_ARCHIVES=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_THUNDERBOLT is not set +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_RGX is not set +# CONFIG_THUNDER_NIC_VF is not set +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_TICK_ONESHOT=y +# CONFIG_TIFM_CORE is not set +# CONFIG_TIGON3 is not set +# CONFIG_TIMB_DMA is not set +CONFIG_TIMERFD=y +# CONFIG_TIMERLAT_TRACER is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_TIME_NS is not set +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9163 is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +CONFIG_TINY_RCU=y +# CONFIG_TIPC is not set +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_AM335X_ADC is not set +# CONFIG_TI_CPSW is not set +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TI_CPTS is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC5571 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_DAVINCI_CPDMA is not set +# CONFIG_TI_DAVINCI_MDIO is not set +# CONFIG_TI_ST is not set +# CONFIG_TI_SYSCON_RESET is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set +# CONFIG_TLAN is not set +# CONFIG_TLS is not set +# CONFIG_TLS_DEVICE is not set +# CONFIG_TLS_TOE is not set +# CONFIG_TMD_HERMES is not set +# CONFIG_TMP006 is not set +# CONFIG_TMP007 is not set +# CONFIG_TMP117 is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_TOSHIBA_HAPS is not set +# CONFIG_TOUCHSCREEN_88PM860X is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set +# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_I2C is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_SPI is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP_I2C is not set +# CONFIG_TOUCHSCREEN_CYTTSP_SPI is not set +# CONFIG_TOUCHSCREEN_DA9034 is not set +# CONFIG_TOUCHSCREEN_DA9052 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HP600 is not set +# CONFIG_TOUCHSCREEN_HP7XX is not set +# CONFIG_TOUCHSCREEN_HTCPEN is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set +# CONFIG_TOUCHSCREEN_IMAGIS is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set +# CONFIG_TOUCHSCREEN_IPROC is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_LPC32XX is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MC13783 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MIGOR is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MX25 is not set +# CONFIG_TOUCHSCREEN_MXS_LRADC is not set +# CONFIG_TOUCHSCREEN_PCAP is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_PROPERTIES is not set +# CONFIG_TOUCHSCREEN_RASPBERRYPI_FW is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set +# CONFIG_TOUCHSCREEN_S3C2410 is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_STMPE is not set +# CONFIG_TOUCHSCREEN_SUN4I is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TI_AM335X_TSC is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_TS4800 is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_TSC2007_IIO is not set +# CONFIG_TOUCHSCREEN_TSC200X_CORE is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_USB_3M is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_USB_DMC_TSC10 is not set +# CONFIG_TOUCHSCREEN_USB_E2I is not set +# CONFIG_TOUCHSCREEN_USB_EASYTOUCH is not set +# CONFIG_TOUCHSCREEN_USB_EGALAX is not set +# CONFIG_TOUCHSCREEN_USB_ELO is not set +# CONFIG_TOUCHSCREEN_USB_ETT_TC45USB is not set +# CONFIG_TOUCHSCREEN_USB_ETURBO is not set +# CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH is not set +# CONFIG_TOUCHSCREEN_USB_GOTOP is not set +# CONFIG_TOUCHSCREEN_USB_GUNZE is not set +# CONFIG_TOUCHSCREEN_USB_IDEALTEK is not set +# CONFIG_TOUCHSCREEN_USB_IRTOUCH is not set +# CONFIG_TOUCHSCREEN_USB_ITM is not set +# CONFIG_TOUCHSCREEN_USB_JASTEC is not set +# CONFIG_TOUCHSCREEN_USB_NEXIO is not set +# CONFIG_TOUCHSCREEN_USB_PANJIT is not set +# CONFIG_TOUCHSCREEN_USB_ZYTRONIC is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM831X is not set +# CONFIG_TOUCHSCREEN_WM9705 is not set +# CONFIG_TOUCHSCREEN_WM9712 is not set +# CONFIG_TOUCHSCREEN_WM9713 is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set +# CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TPL0102 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_TRACER_SNAPSHOT is not set +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_TRACE_EVENT_INJECT is not set +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_TRACE_MMIO_ACCESS is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_TRACING_EVENTS_GPIO is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_TRAD_SIGNALS=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_TREE_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set +# CONFIG_TRUSTED_FOUNDATIONS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_TRUSTED_KEYS_CAAM is not set +# CONFIG_TRUSTED_KEYS_TPM is not set +# CONFIG_TRUSTED_KEYS_TEE is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2591 is not set +# CONFIG_TSL2772 is not set +# CONFIG_TSL2x7x is not set +# CONFIG_TSL4531 is not set +# CONFIG_TSNEP is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +# CONFIG_TTPCI_EEPROM is not set +CONFIG_TTY=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_TUN is not set +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL4030_MADC is not set +# CONFIG_TWL6030_GPADC is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_TXGBE is not set +# CONFIG_TYPEC is not set +# CONFIG_TYPEC_DP_ALTMODE is not set +# CONFIG_TYPEC_TCPM is not set +# CONFIG_TYPEC_UCSI is not set +# CONFIG_TYPHOON is not set +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_UBIFS_ATIME_SUPPORT is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +# CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_LZO=y +# CONFIG_UBIFS_FS_SECURITY is not set +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +# CONFIG_UBSAN is not set +CONFIG_UBSAN_ALIGNMENT=y +CONFIG_UBSAN_BOOL=y +# CONFIG_UBSAN_DIV_ZERO is not set +CONFIG_UBSAN_ENUM=y +# CONFIG_UBSAN_MISC is not set +CONFIG_UBSAN_SHIFT=y +# CONFIG_UBSAN_UNREACHABLE is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_UCSI is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDMABUF is not set +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_UFS_FS is not set +# CONFIG_UHID is not set +CONFIG_UID16=y +# CONFIG_UIO is not set +# CONFIG_UIMAGE_FIT_BLK is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_UNICODE is not set +# CONFIG_UNISYSSPAR is not set +# CONFIG_UNISYS_VISORBUS is not set +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_UNIX_DIAG is not set +CONFIG_UNIX_SCM=y +# CONFIG_UNUSED_BOARD_FILES is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_UPROBES is not set +# CONFIG_UPROBE_EVENTS is not set +# CONFIG_US5182D is not set +# CONFIG_USB is not set +# CONFIG_USB4 is not set +# CONFIG_USBIP_CORE is not set +CONFIG_USBIP_VHCI_HC_PORTS=8 +CONFIG_USBIP_VHCI_NR_HCS=1 +# CONFIG_USBIP_VUDC is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AIRSPY is not set +CONFIG_USB_ALI_M5632=y +# CONFIG_USB_AMD5536UDC is not set +CONFIG_USB_AN2720=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_ATM is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +# CONFIG_USB_BDC_UDC is not set +CONFIG_USB_BELKIN=y +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_CHIPIDEA_GENERIC is not set +# CONFIG_USB_CHIPIDEA_IMX is not set +# CONFIG_USB_CHIPIDEA_MSM is not set +# CONFIG_USB_CHIPIDEA_PCI is not set +# CONFIG_USB_CHIPIDEA_TEGRA is not set +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_CXACRU is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DSBR is not set +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set +# CONFIG_USB_DWC2_HOST is not set +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC3_EXYNOS is not set +# CONFIG_USB_DWC3_HAPS is not set +# CONFIG_USB_DWC3_KEYSTONE is not set +# CONFIG_USB_DWC3_OF_SIMPLE is not set +# CONFIG_USB_DWC3_PCI is not set +# CONFIG_USB_DWC3_QCOM is not set +# CONFIG_USB_DWC3_ULPI is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_EHCI_ATH79 is not set +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_EHCI_HCD_AT91 is not set +# CONFIG_USB_EHCI_HCD_OMAP is not set +# CONFIG_USB_EHCI_HCD_PPC_OF is not set +# CONFIG_USB_EHCI_MSM is not set +# CONFIG_USB_EHCI_MV is not set +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_GADGET is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_VBUS_DRAW=2 +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_GSPCA is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_G_NOKIA is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_HACKRF is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_KC2190 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LGM_PHY is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_M5602 is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_MSI2500 is not set +# CONFIG_USB_MSM_OTG is not set +# CONFIG_USB_MTU3 is not set +# CONFIG_USB_MUSB_GADGET is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MXS_PHY is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_NET_AQC111 is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_EEM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_CDC_NCM is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_CH9200 is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_OHCI_HCD_PCI is not set +# CONFIG_USB_OHCI_HCD_PPC_OF is not set +# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set +# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_ONBOARD_HUB is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_PCI is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_PHY is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_PWC_INPUT_EVDEV is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_QCOM_EUD is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RAW_GADGET is not set +# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_RENESAS_USBHS is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ROLES_INTEL_XHCI is not set +# CONFIG_USB_ROLE_SWITCH is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_RTL8153_ECM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_DEBUG is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_F8153X is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_GARMIN is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7715_PARPORT is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SAFE_PADDED=y +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_UPD78F0730 is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_XR is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_SPEEDTOUCH is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TMC is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_UEAGLEATM is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_USS720 is not set +# CONFIG_USB_VIDEO_CLASS is not set +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +# CONFIG_USB_VL600 is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set +# CONFIG_USB_XEN_HCD is not set +# CONFIG_USB_XHCI_DBGCAP is not set +# CONFIG_USB_XHCI_HCD is not set +# CONFIG_USB_XHCI_MVEBU is not set +# CONFIG_USB_XHCI_PCI_RENESAS is not set +# CONFIG_USB_XUSBATM is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USELIB is not set +# CONFIG_USERFAULTFD is not set +# CONFIG_USERIO is not set +# CONFIG_USER_DECRYPTED_DATA is not set +# CONFIG_USE_OF is not set +# CONFIG_UTS_NS is not set +# CONFIG_UWB is not set +# CONFIG_U_SERIAL_CONSOLE is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +# CONFIG_VALIDATE_FS_PARSER is not set +# CONFIG_VBOXGUEST is not set +# CONFIG_VCNL3020 is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VCNL4035 is not set +# CONFIG_VCPU_STALL_DETECTOR is not set +# CONFIG_VDPA is not set +CONFIG_VDSO=y +# CONFIG_VEML6030 is not set +# CONFIG_VEML6070 is not set +# CONFIG_VETH is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_VF610_ADC is not set +# CONFIG_VF610_DAC is not set +# CONFIG_VFAT_FS is not set +# CONFIG_VFIO is not set +# CONFIG_VFIO_FSL_MC is not set +# CONFIG_VFIO_PLATFORM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VGA_ARB is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_VGA_SWITCHEROO is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +CONFIG_VHOST_MENU=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_VSOCK is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_VIDEO_AD5398 is not set +# CONFIG_VIDEO_AD5820 is not set +# CONFIG_VIDEO_AD9389B is not set +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_AK7375 is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_AM437X_VPFE is not set +# CONFIG_VIDEO_AR0521 is not set +# CONFIG_VIDEO_ARDUCAM_64MP is not set +# CONFIG_VIDEO_ARDUCAM_PIVARIETY is not set +# CONFIG_VIDEO_ASPEED is not set +# CONFIG_VIDEO_ATMEL_ISC is not set +# CONFIG_VIDEO_ATMEL_ISI is not set +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_BCM2835 is not set +# CONFIG_VIDEO_BCM2835_UNICAM is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_BU64754 is not set +# CONFIG_VIDEO_CADENCE is not set +# CONFIG_VIDEO_CADENCE_CSI2RX is not set +# CONFIG_VIDEO_CADENCE_CSI2TX is not set +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_VIDEO_CAMERA_SENSOR is not set +# CONFIG_VIDEO_CCS is not set +# CONFIG_VIDEO_COBALT is not set +# CONFIG_VIDEO_CODA is not set +# CONFIG_VIDEO_CODEC_BCM2835 is not set +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25821 is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_VIDEO_DT3155 is not set +# CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_DW9768 is not set +# CONFIG_VIDEO_DW9807_VCM is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_ET8EK8 is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HI556 is not set +# CONFIG_VIDEO_HI846 is not set +# CONFIG_VIDEO_HI847 is not set +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_IMX208 is not set +# CONFIG_VIDEO_IMX214 is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX258 is not set +# CONFIG_VIDEO_IMX274 is not set +# CONFIG_VIDEO_IMX290 is not set +# CONFIG_VIDEO_IMX296 is not set +# CONFIG_VIDEO_IMX319 is not set +# CONFIG_VIDEO_IMX334 is not set +# CONFIG_VIDEO_IMX335 is not set +# CONFIG_VIDEO_IMX355 is not set +# CONFIG_VIDEO_IMX412 is not set +# CONFIG_VIDEO_IMX477 is not set +# CONFIG_VIDEO_IMX519 is not set +# CONFIG_VIDEO_IMX708 is not set +# CONFIG_VIDEO_IMX8_JPEG is not set +# CONFIG_VIDEO_IMX_MIPI_CSIS 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 +# CONFIG_VIDEO_ISP_BCM2835 is not set +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_MT9M001 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9M111 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9T112 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_MT9V111 is not set +# CONFIG_VIDEO_MUX is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_OG01A1B is not set +# CONFIG_VIDEO_OMAP2_VOUT is not set +# CONFIG_VIDEO_OV02A10 is not set +# CONFIG_VIDEO_OV08D10 is not set +# CONFIG_VIDEO_OV13858 is not set +# CONFIG_VIDEO_OV13B10 is not set +# CONFIG_VIDEO_OV2311 is not set +# CONFIG_VIDEO_OV2640 is not set +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV2680 is not set +# CONFIG_VIDEO_OV2685 is not set +# CONFIG_VIDEO_OV2740 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV5648 is not set +# CONFIG_VIDEO_OV5670 is not set +# CONFIG_VIDEO_OV5675 is not set +# CONFIG_VIDEO_OV5693 is not set +# CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV64A40 is not set +# CONFIG_VIDEO_OV6650 is not set +# CONFIG_VIDEO_OV7251 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV772X is not set +# CONFIG_VIDEO_OV7740 is not set +# CONFIG_VIDEO_OV8856 is not set +# CONFIG_VIDEO_OV8865 is not set +# CONFIG_VIDEO_OV9281 is not set +# CONFIG_VIDEO_OV9282 is not set +# CONFIG_VIDEO_OV9640 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_OV9734 is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_RASPBERRYPI_PISP_BE is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +# CONFIG_VIDEO_RCAR_ISP is not set +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RDACM20 is not set +# CONFIG_VIDEO_RDACM21 is not set +# CONFIG_VIDEO_RJ54N1 is not set +# CONFIG_VIDEO_ROCKCHIP_ISP1 is not set +# CONFIG_VIDEO_RP1_CFE is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_SAA6588 is not set +# CONFIG_VIDEO_SAA6752HS is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_SAA7164 is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_SOLO6X10 is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set +# CONFIG_VIDEO_SUN4I_CSI is not set +# CONFIG_VIDEO_SUN6I_CSI is not set +# CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_STK1160_COMMON is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TDA1997X is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_THS8200 is not set +# CONFIG_VIDEO_TIMBERDALE is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_TM6000 is not set +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW5864 is not set +# CONFIG_VIDEO_TW68 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_USBTV is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_VIDEO_V4L2 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_VPX3220 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_XILINX is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_BLK_SCSI is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_VIRTIO_FS is not set +# CONFIG_VIRTIO_INPUT is not set +CONFIG_VIRTIO_MENU=y +# CONFIG_VIRTIO_MMIO is not set +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTUALIZATION is not set +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRT_TO_BUS=y +# CONFIG_VITESSE_PHY is not set +# CONFIG_VL53L0X_I2C is not set +# CONFIG_VL6180 is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_VMAP_STACK is not set +# CONFIG_VME_BUS is not set +# CONFIG_VMLINUX_MAP is not set +# CONFIG_VMSPLIT_1G is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_2G_OPT is not set +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 +# CONFIG_VORTEX is not set +# CONFIG_VSOCKETS is not set +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VT is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_VXFS_FS is not set +# CONFIG_VXGE is not set +# CONFIG_VXLAN is not set +# CONFIG_VZ89X is not set +# CONFIG_W1 is not set +# CONFIG_W1_CON is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_GPIO is not set +# CONFIG_W1_MASTER_MATROX is not set +# CONFIG_W1_MASTER_SGI is not set +# CONFIG_W1_SLAVE_DS2405 is not set +# CONFIG_W1_SLAVE_DS2406 is not set +# CONFIG_W1_SLAVE_DS2408 is not set +# CONFIG_W1_SLAVE_DS2413 is not set +# CONFIG_W1_SLAVE_DS2423 is not set +# CONFIG_W1_SLAVE_DS2430 is not set +# CONFIG_W1_SLAVE_DS2431 is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2438 is not set +# CONFIG_W1_SLAVE_DS250X is not set +# CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set +# CONFIG_W1_SLAVE_DS2805 is not set +# CONFIG_W1_SLAVE_DS28E04 is not set +# CONFIG_W1_SLAVE_DS28E17 is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W83627HF_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_W83977F_WDT is not set +# CONFIG_WAN is not set +# CONFIG_WANXL is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +# CONFIG_WATCHDOG_SYSFS is not set +# CONFIG_WATCH_QUEUE is not set +# CONFIG_WD80x3 is not set +# CONFIG_WDAT_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_WERROR is not set +# CONFIG_WEXT_CORE is not set +# CONFIG_WEXT_PRIV is not set +# CONFIG_WEXT_PROC is not set +# CONFIG_WEXT_SPY is not set +CONFIG_WILINK_PLATFORM_DATA=y +# CONFIG_WIMAX is not set +# CONFIG_WIREGUARD is not set +CONFIG_WIRELESS=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_WIRELESS_WDS is not set +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_WL1251 is not set +# CONFIG_WL12XX is not set +# CONFIG_WL18XX is not set +CONFIG_WLAN=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_PURELIFI is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_SILABS is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLCORE is not set +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WWAN is not set +# CONFIG_WWAN_HWSIM is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_X25 is not set +# CONFIG_X509_CERTIFICATE_PARSER is not set +# CONFIG_X86_PKG_TEMP_THERMAL is not set +CONFIG_X86_SYSFB=y +# CONFIG_XDP_SOCKETS is not set +# CONFIG_XEN is not set +# CONFIG_XEN_GRANT_DMA_ALLOC is not set +# CONFIG_XEN_PVCALLS_FRONTEND is not set +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y +CONFIG_XFRM=y +# CONFIG_XFRM_INTERFACE is not set +# CONFIG_XFRM_IPCOMP is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_USER is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_ONLINE_SCRUB is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_SUPPORT_V4 is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_EMACLITE is not set +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_XILINX_INTC is not set +# CONFIG_XILINX_LL_TEMAC is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_XILINX_VCU is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_XILINX_XADC is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_XILINX_ZYNQMP_DPDMA is not set +# CONFIG_XILLYBUS is not set +# CONFIG_XILLYUSB is not set +# CONFIG_XIL_AXIS_FIFO is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_XMON is not set +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_BCJ is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_MICROLZMA is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_SPARC is not set +# CONFIG_XZ_DEC_TEST is not set +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_YAM is not set +# CONFIG_YAMAHA_YAS530 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_YENTA is not set +# CONFIG_YENTA_O2 is not set +# CONFIG_YENTA_RICOH is not set +# CONFIG_YENTA_TI is not set +# CONFIG_YENTA_TOSHIBA is not set +# CONFIG_ZBUD is not set +# CONFIG_ZD1211RW is not set +# CONFIG_ZD1211RW_DEBUG is not set +# CONFIG_ZEROPLUS_FF is not set +# CONFIG_ZERO_CALL_USED_REGS is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +# CONFIG_ZISOFS is not set +# CONFIG_ZLIB_DEFLATE is not set +# CONFIG_ZLIB_INFLATE is not set +CONFIG_ZONE_DMA=y +# CONFIG_ZOPT2201 is not set +# CONFIG_ZPA2326 is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZRAM is not set +# CONFIG_ZRAM_DEF_COMP_842 is not set +# CONFIG_ZRAM_DEF_COMP_LZ4 is not set +# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set +# CONFIG_ZRAM_DEF_COMP_LZO is not set +# CONFIG_ZRAM_DEF_COMP_LZORLE is not set +# CONFIG_ZRAM_DEF_COMP_ZSTD is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_ZSWAP is not set +# CONFIG_ZX_TDM is not set diff --git a/target/linux/generic/hack-6.6/204-module_strip.patch b/target/linux/generic/hack-6.6/204-module_strip.patch new file mode 100644 index 0000000000..9fefd0bd6e --- /dev/null +++ b/target/linux/generic/hack-6.6/204-module_strip.patch @@ -0,0 +1,210 @@ +From a779a482fb9b9f8fcdf8b2519c789b4b9bb5dd05 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 16:56:48 +0200 +Subject: build: add a hack for removing non-essential module info + +Signed-off-by: Felix Fietkau +--- + include/linux/module.h | 13 ++++++++----- + include/linux/moduleparam.h | 15 ++++++++++++--- + init/Kconfig | 7 +++++++ + kernel/module.c | 5 ++++- + scripts/mod/modpost.c | 12 ++++++++++++ + 5 files changed, 43 insertions(+), 9 deletions(-) + +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -163,6 +163,7 @@ extern void cleanup_module(void); + + /* Generic info of form tag = "info" */ + #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info) ++#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info) + + /* For userspace: you can also call me... */ + #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) +@@ -232,12 +233,12 @@ extern void cleanup_module(void); + * Author(s), use "Name " or just "Name", for multiple + * authors use multiple MODULE_AUTHOR() statements/lines. + */ +-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) ++#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author) + + /* What your module does. */ +-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description) ++#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description) + +-#ifdef MODULE ++#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED) + /* Creates an alias so file2alias.c can find device table. */ + #define MODULE_DEVICE_TABLE(type, name) \ + extern typeof(name) __mod_##type##__##name##_device_table \ +@@ -264,7 +265,9 @@ extern typeof(name) __mod_##type##__##na + */ + + #if defined(MODULE) || !defined(CONFIG_SYSFS) +-#define MODULE_VERSION(_version) MODULE_INFO(version, _version) ++#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version) ++#elif defined(CONFIG_MODULE_STRIPPED) ++#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version) + #else + #define MODULE_VERSION(_version) \ + MODULE_INFO(version, _version); \ +@@ -287,7 +290,7 @@ extern typeof(name) __mod_##type##__##na + /* Optional firmware file (or files) needed by the module + * format is simply firmware file name. Multiple firmware + * files require multiple MODULE_FIRMWARE() specifiers */ +-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware) ++#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware) + + #define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, __stringify(ns)) + +--- a/include/linux/moduleparam.h ++++ b/include/linux/moduleparam.h +@@ -20,6 +20,16 @@ + /* Chosen so that structs with an unsigned long line up. */ + #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) + ++/* This struct is here for syntactic coherency, it is not used */ ++#define __MODULE_INFO_DISABLED(name) \ ++ struct __UNIQUE_ID(name) {} ++ ++#ifdef CONFIG_MODULE_STRIPPED ++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name) ++#else ++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info) ++#endif ++ + #define __MODULE_INFO(tag, name, info) \ + static const char __UNIQUE_ID(name)[] \ + __used __section(".modinfo") __aligned(1) \ +@@ -31,7 +41,7 @@ + /* One for each parameter, describing how to use it. Some files do + multiple of these per line, so can't just use MODULE_INFO. */ + #define MODULE_PARM_DESC(_parm, desc) \ +- __MODULE_INFO(parm, _parm, #_parm ":" desc) ++ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc) + + struct kernel_param; + +--- a/kernel/module/Kconfig ++++ b/kernel/module/Kconfig +@@ -290,4 +290,11 @@ config MODULES_TREE_LOOKUP + def_bool y + depends on PERF_EVENTS || TRACING || CFI_CLANG + ++config MODULE_STRIPPED ++ bool "Reduce module size" ++ depends on MODULES ++ help ++ Remove module parameter descriptions, author info, version, aliases, ++ device tables, etc. ++ + endif # MODULES +--- a/kernel/module/main.c ++++ b/kernel/module/main.c +@@ -988,6 +988,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE( + + static const char vermagic[] = VERMAGIC_STRING; + ++#if defined(CONFIG_MODVERSIONS) || !defined(CONFIG_MODULE_STRIPPED) + int try_to_force_load(struct module *mod, const char *reason) + { + #ifdef CONFIG_MODULE_FORCE_LOAD +@@ -999,6 +1000,7 @@ int try_to_force_load(struct module *mod + return -ENOEXEC; + #endif + } ++#endif + + static char *get_modinfo(const struct load_info *info, const char *tag); + static char *get_next_modinfo(const struct load_info *info, const char *tag, +@@ -1958,9 +1960,11 @@ static int setup_load_info(struct load_i + + static int check_modinfo(struct module *mod, struct load_info *info, int flags) + { +- const char *modmagic = get_modinfo(info, "vermagic"); + int err; + ++#ifndef CONFIG_MODULE_STRIPPED ++ const char *modmagic = get_modinfo(info, "vermagic"); ++ + if (flags & MODULE_INIT_IGNORE_VERMAGIC) + modmagic = NULL; + +@@ -1981,6 +1985,7 @@ static int check_modinfo(struct module * + mod->name); + add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); + } ++#endif + + check_modinfo_retpoline(mod, info); + +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -1785,7 +1785,9 @@ static void read_symbols(const char *mod + symname = remove_dot(info.strtab + sym->st_name); + + handle_symbol(mod, &info, sym, symname); ++#ifndef CONFIG_MODULE_STRIPPED + handle_moddevtable(mod, &info, sym, symname); ++#endif + } + + for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { +@@ -1948,8 +1950,10 @@ static void add_header(struct buffer *b, + buf_printf(b, "BUILD_SALT;\n"); + buf_printf(b, "BUILD_LTO_INFO;\n"); + buf_printf(b, "\n"); ++#ifndef CONFIG_MODULE_STRIPPED + buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); + buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); ++#endif + buf_printf(b, "\n"); + buf_printf(b, "__visible struct module __this_module\n"); + buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n"); +@@ -1963,8 +1967,10 @@ static void add_header(struct buffer *b, + buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n"); + buf_printf(b, "};\n"); + ++#ifndef CONFIG_MODULE_STRIPPED + if (!external_module) + buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); ++#endif + + buf_printf(b, + "\n" +@@ -1972,8 +1978,10 @@ static void add_header(struct buffer *b, + "MODULE_INFO(retpoline, \"Y\");\n" + "#endif\n"); + ++#ifndef CONFIG_MODULE_STRIPPED + if (strstarts(mod->name, "drivers/staging")) + buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); ++#endif + + if (strstarts(mod->name, "tools/testing")) + buf_printf(b, "\nMODULE_INFO(test, \"Y\");\n"); +@@ -2069,11 +2077,13 @@ static void add_depends(struct buffer *b + + static void add_srcversion(struct buffer *b, struct module *mod) + { ++#ifndef CONFIG_MODULE_STRIPPED + if (mod->srcversion[0]) { + buf_printf(b, "\n"); + buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", + mod->srcversion); + } ++#endif + } + + static void write_buf(struct buffer *b, const char *fname) +@@ -2159,7 +2169,9 @@ static void write_mod_c_file(struct modu + add_exported_symbols(&buf, mod); + add_versions(&buf, mod); + add_depends(&buf, mod); ++#ifndef CONFIG_MODULE_STRIPPED + add_moddevtable(&buf, mod); ++#endif + add_srcversion(&buf, mod); + + ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name); diff --git a/target/linux/generic/hack-6.6/205-kconfig-abort-configuration-on-unset-symbol.patch b/target/linux/generic/hack-6.6/205-kconfig-abort-configuration-on-unset-symbol.patch new file mode 100644 index 0000000000..df18507041 --- /dev/null +++ b/target/linux/generic/hack-6.6/205-kconfig-abort-configuration-on-unset-symbol.patch @@ -0,0 +1,41 @@ +From 310e8e04a05d9eb43fa9dd7f00143300afcaa37a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 11 Nov 2022 13:33:44 +0100 +Subject: [PATCH] kconfig: abort configuration on unset symbol + +When a target configuration has unset Kconfig symbols, the build will +fail when OpenWrt is compiled with V=s and stdin is connected to a tty. + +In case OpenWrt is compiled without either of these preconditions, the +build will succeed with the symbols in question being unset. + +Modify the kernel configuration in a way it fails on unset symbols +regardless of the aforementioned preconditions. + +Signed-off-by: David Bauer +--- + scripts/kconfig/conf.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/scripts/kconfig/conf.c ++++ b/scripts/kconfig/conf.c +@@ -338,6 +338,9 @@ static int conf_askvalue(struct symbol * + } + /* fall through */ + default: ++ if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) { ++ exit(1); ++ } + fflush(stdout); + xfgets(line, sizeof(line), stdin); + break; +@@ -520,6 +523,9 @@ static int conf_choice(struct menu *menu + } + /* fall through */ + case oldaskconfig: ++ if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) { ++ exit(1); ++ } + fflush(stdout); + xfgets(line, sizeof(line), stdin); + strip(line); diff --git a/target/linux/generic/hack-6.6/210-darwin_scripts_include.patch b/target/linux/generic/hack-6.6/210-darwin_scripts_include.patch new file mode 100644 index 0000000000..c9612536de --- /dev/null +++ b/target/linux/generic/hack-6.6/210-darwin_scripts_include.patch @@ -0,0 +1,3053 @@ +From db7c30dcd9a0391bf13b62c9f91e144d762ef43a Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Fri, 7 Jul 2017 17:00:49 +0200 +Subject: Add an OSX specific patch to make the kernel be compiled + +lede-commit: 3fc2a24f0422b2f55f9ed43f116db3111f700526 +Signed-off-by: Florian Fainelli +--- + scripts/kconfig/Makefile | 3 + + scripts/mod/elf.h | 3007 ++++++++++++++++++++++++++++++++++++++++++++ + scripts/mod/mk_elfconfig.c | 4 + + scripts/mod/modpost.h | 4 + + 4 files changed, 3018 insertions(+) + create mode 100644 scripts/mod/elf.h + +--- /dev/null ++++ b/scripts/mod/elf.h +@@ -0,0 +1,3007 @@ ++/* This file defines standard ELF types, structures, and macros. ++ Copyright (C) 1995-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _ELF_H ++#define _ELF_H 1 ++ ++/* Standard ELF types. */ ++ ++#include ++ ++/* Type for a 16-bit quantity. */ ++typedef uint16_t Elf32_Half; ++typedef uint16_t Elf64_Half; ++ ++/* Types for signed and unsigned 32-bit quantities. */ ++typedef uint32_t Elf32_Word; ++typedef int32_t Elf32_Sword; ++typedef uint32_t Elf64_Word; ++typedef int32_t Elf64_Sword; ++ ++/* Types for signed and unsigned 64-bit quantities. */ ++typedef uint64_t Elf32_Xword; ++typedef int64_t Elf32_Sxword; ++typedef uint64_t Elf64_Xword; ++typedef int64_t Elf64_Sxword; ++ ++/* Type of addresses. */ ++typedef uint32_t Elf32_Addr; ++typedef uint64_t Elf64_Addr; ++ ++/* Type of file offsets. */ ++typedef uint32_t Elf32_Off; ++typedef uint64_t Elf64_Off; ++ ++/* Type for section indices, which are 16-bit quantities. */ ++typedef uint16_t Elf32_Section; ++typedef uint16_t Elf64_Section; ++ ++/* Type for version symbol information. */ ++typedef Elf32_Half Elf32_Versym; ++typedef Elf64_Half Elf64_Versym; ++ ++ ++/* The ELF file header. This appears at the start of every ELF file. */ ++ ++#define EI_NIDENT (16) ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf32_Half e_type; /* Object file type */ ++ Elf32_Half e_machine; /* Architecture */ ++ Elf32_Word e_version; /* Object file version */ ++ Elf32_Addr e_entry; /* Entry point virtual address */ ++ Elf32_Off e_phoff; /* Program header table file offset */ ++ Elf32_Off e_shoff; /* Section header table file offset */ ++ Elf32_Word e_flags; /* Processor-specific flags */ ++ Elf32_Half e_ehsize; /* ELF header size in bytes */ ++ Elf32_Half e_phentsize; /* Program header table entry size */ ++ Elf32_Half e_phnum; /* Program header table entry count */ ++ Elf32_Half e_shentsize; /* Section header table entry size */ ++ Elf32_Half e_shnum; /* Section header table entry count */ ++ Elf32_Half e_shstrndx; /* Section header string table index */ ++} Elf32_Ehdr; ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf64_Half e_type; /* Object file type */ ++ Elf64_Half e_machine; /* Architecture */ ++ Elf64_Word e_version; /* Object file version */ ++ Elf64_Addr e_entry; /* Entry point virtual address */ ++ Elf64_Off e_phoff; /* Program header table file offset */ ++ Elf64_Off e_shoff; /* Section header table file offset */ ++ Elf64_Word e_flags; /* Processor-specific flags */ ++ Elf64_Half e_ehsize; /* ELF header size in bytes */ ++ Elf64_Half e_phentsize; /* Program header table entry size */ ++ Elf64_Half e_phnum; /* Program header table entry count */ ++ Elf64_Half e_shentsize; /* Section header table entry size */ ++ Elf64_Half e_shnum; /* Section header table entry count */ ++ Elf64_Half e_shstrndx; /* Section header string table index */ ++} Elf64_Ehdr; ++ ++/* Fields in the e_ident array. The EI_* macros are indices into the ++ array. The macros under each EI_* macro are the values the byte ++ may have. */ ++ ++#define EI_MAG0 0 /* File identification byte 0 index */ ++#define ELFMAG0 0x7f /* Magic number byte 0 */ ++ ++#define EI_MAG1 1 /* File identification byte 1 index */ ++#define ELFMAG1 'E' /* Magic number byte 1 */ ++ ++#define EI_MAG2 2 /* File identification byte 2 index */ ++#define ELFMAG2 'L' /* Magic number byte 2 */ ++ ++#define EI_MAG3 3 /* File identification byte 3 index */ ++#define ELFMAG3 'F' /* Magic number byte 3 */ ++ ++/* Conglomeration of the identification bytes, for easy testing as a word. */ ++#define ELFMAG "\177ELF" ++#define SELFMAG 4 ++ ++#define EI_CLASS 4 /* File class byte index */ ++#define ELFCLASSNONE 0 /* Invalid class */ ++#define ELFCLASS32 1 /* 32-bit objects */ ++#define ELFCLASS64 2 /* 64-bit objects */ ++#define ELFCLASSNUM 3 ++ ++#define EI_DATA 5 /* Data encoding byte index */ ++#define ELFDATANONE 0 /* Invalid data encoding */ ++#define ELFDATA2LSB 1 /* 2's complement, little endian */ ++#define ELFDATA2MSB 2 /* 2's complement, big endian */ ++#define ELFDATANUM 3 ++ ++#define EI_VERSION 6 /* File version byte index */ ++ /* Value must be EV_CURRENT */ ++ ++#define EI_OSABI 7 /* OS ABI identification */ ++#define ELFOSABI_NONE 0 /* UNIX System V ABI */ ++#define ELFOSABI_SYSV 0 /* Alias. */ ++#define ELFOSABI_HPUX 1 /* HP-UX */ ++#define ELFOSABI_NETBSD 2 /* NetBSD. */ ++#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ ++#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ ++#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ ++#define ELFOSABI_AIX 7 /* IBM AIX. */ ++#define ELFOSABI_IRIX 8 /* SGI Irix. */ ++#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ ++#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ ++#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ ++#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ ++#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ ++#define ELFOSABI_ARM 97 /* ARM */ ++#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ ++ ++#define EI_ABIVERSION 8 /* ABI version */ ++ ++#define EI_PAD 9 /* Byte index of padding bytes */ ++ ++/* Legal values for e_type (object file type). */ ++ ++#define ET_NONE 0 /* No file type */ ++#define ET_REL 1 /* Relocatable file */ ++#define ET_EXEC 2 /* Executable file */ ++#define ET_DYN 3 /* Shared object file */ ++#define ET_CORE 4 /* Core file */ ++#define ET_NUM 5 /* Number of defined types */ ++#define ET_LOOS 0xfe00 /* OS-specific range start */ ++#define ET_HIOS 0xfeff /* OS-specific range end */ ++#define ET_LOPROC 0xff00 /* Processor-specific range start */ ++#define ET_HIPROC 0xffff /* Processor-specific range end */ ++ ++/* Legal values for e_machine (architecture). */ ++ ++#define EM_NONE 0 /* No machine */ ++#define EM_M32 1 /* AT&T WE 32100 */ ++#define EM_SPARC 2 /* SUN SPARC */ ++#define EM_386 3 /* Intel 80386 */ ++#define EM_68K 4 /* Motorola m68k family */ ++#define EM_88K 5 /* Motorola m88k family */ ++#define EM_860 7 /* Intel 80860 */ ++#define EM_MIPS 8 /* MIPS R3000 big-endian */ ++#define EM_S370 9 /* IBM System/370 */ ++#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ ++ ++#define EM_PARISC 15 /* HPPA */ ++#define EM_VPP500 17 /* Fujitsu VPP500 */ ++#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ ++#define EM_960 19 /* Intel 80960 */ ++#define EM_PPC 20 /* PowerPC */ ++#define EM_PPC64 21 /* PowerPC 64-bit */ ++#define EM_S390 22 /* IBM S390 */ ++ ++#define EM_V800 36 /* NEC V800 series */ ++#define EM_FR20 37 /* Fujitsu FR20 */ ++#define EM_RH32 38 /* TRW RH-32 */ ++#define EM_RCE 39 /* Motorola RCE */ ++#define EM_ARM 40 /* ARM */ ++#define EM_FAKE_ALPHA 41 /* Digital Alpha */ ++#define EM_SH 42 /* Hitachi SH */ ++#define EM_SPARCV9 43 /* SPARC v9 64-bit */ ++#define EM_TRICORE 44 /* Siemens Tricore */ ++#define EM_ARC 45 /* Argonaut RISC Core */ ++#define EM_H8_300 46 /* Hitachi H8/300 */ ++#define EM_H8_300H 47 /* Hitachi H8/300H */ ++#define EM_H8S 48 /* Hitachi H8S */ ++#define EM_H8_500 49 /* Hitachi H8/500 */ ++#define EM_IA_64 50 /* Intel Merced */ ++#define EM_MIPS_X 51 /* Stanford MIPS-X */ ++#define EM_COLDFIRE 52 /* Motorola Coldfire */ ++#define EM_68HC12 53 /* Motorola M68HC12 */ ++#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ ++#define EM_PCP 55 /* Siemens PCP */ ++#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ ++#define EM_NDR1 57 /* Denso NDR1 microprocessor */ ++#define EM_STARCORE 58 /* Motorola Start*Core processor */ ++#define EM_ME16 59 /* Toyota ME16 processor */ ++#define EM_ST100 60 /* STMicroelectronic ST100 processor */ ++#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ ++#define EM_X86_64 62 /* AMD x86-64 architecture */ ++#define EM_PDSP 63 /* Sony DSP Processor */ ++ ++#define EM_FX66 66 /* Siemens FX66 microcontroller */ ++#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ ++#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ ++#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ ++#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ ++#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ ++#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ ++#define EM_SVX 73 /* Silicon Graphics SVx */ ++#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ ++#define EM_VAX 75 /* Digital VAX */ ++#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ ++#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ ++#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ ++#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ ++#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ ++#define EM_HUANY 81 /* Harvard University machine-independent object files */ ++#define EM_PRISM 82 /* SiTera Prism */ ++#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ ++#define EM_FR30 84 /* Fujitsu FR30 */ ++#define EM_D10V 85 /* Mitsubishi D10V */ ++#define EM_D30V 86 /* Mitsubishi D30V */ ++#define EM_V850 87 /* NEC v850 */ ++#define EM_M32R 88 /* Mitsubishi M32R */ ++#define EM_MN10300 89 /* Matsushita MN10300 */ ++#define EM_MN10200 90 /* Matsushita MN10200 */ ++#define EM_PJ 91 /* picoJava */ ++#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ ++#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ ++#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ ++#define EM_TILEPRO 188 /* Tilera TILEPro */ ++#define EM_TILEGX 191 /* Tilera TILE-Gx */ ++#define EM_NUM 192 ++ ++/* If it is necessary to assign new unofficial EM_* values, please ++ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the ++ chances of collision with official or non-GNU unofficial values. */ ++ ++#define EM_ALPHA 0x9026 ++ ++/* Legal values for e_version (version). */ ++ ++#define EV_NONE 0 /* Invalid ELF version */ ++#define EV_CURRENT 1 /* Current version */ ++#define EV_NUM 2 ++ ++/* Section header. */ ++ ++typedef struct ++{ ++ Elf32_Word sh_name; /* Section name (string tbl index) */ ++ Elf32_Word sh_type; /* Section type */ ++ Elf32_Word sh_flags; /* Section flags */ ++ Elf32_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf32_Off sh_offset; /* Section file offset */ ++ Elf32_Word sh_size; /* Section size in bytes */ ++ Elf32_Word sh_link; /* Link to another section */ ++ Elf32_Word sh_info; /* Additional section information */ ++ Elf32_Word sh_addralign; /* Section alignment */ ++ Elf32_Word sh_entsize; /* Entry size if section holds table */ ++} Elf32_Shdr; ++ ++typedef struct ++{ ++ Elf64_Word sh_name; /* Section name (string tbl index) */ ++ Elf64_Word sh_type; /* Section type */ ++ Elf64_Xword sh_flags; /* Section flags */ ++ Elf64_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf64_Off sh_offset; /* Section file offset */ ++ Elf64_Xword sh_size; /* Section size in bytes */ ++ Elf64_Word sh_link; /* Link to another section */ ++ Elf64_Word sh_info; /* Additional section information */ ++ Elf64_Xword sh_addralign; /* Section alignment */ ++ Elf64_Xword sh_entsize; /* Entry size if section holds table */ ++} Elf64_Shdr; ++ ++/* Special section indices. */ ++ ++#define SHN_UNDEF 0 /* Undefined section */ ++#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ ++#define SHN_LOPROC 0xff00 /* Start of processor-specific */ ++#define SHN_BEFORE 0xff00 /* Order section before all others ++ (Solaris). */ ++#define SHN_AFTER 0xff01 /* Order section after all others ++ (Solaris). */ ++#define SHN_HIPROC 0xff1f /* End of processor-specific */ ++#define SHN_LOOS 0xff20 /* Start of OS-specific */ ++#define SHN_HIOS 0xff3f /* End of OS-specific */ ++#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ ++#define SHN_COMMON 0xfff2 /* Associated symbol is common */ ++#define SHN_XINDEX 0xffff /* Index is in extra table. */ ++#define SHN_HIRESERVE 0xffff /* End of reserved indices */ ++ ++/* Legal values for sh_type (section type). */ ++ ++#define SHT_NULL 0 /* Section header table entry unused */ ++#define SHT_PROGBITS 1 /* Program data */ ++#define SHT_SYMTAB 2 /* Symbol table */ ++#define SHT_STRTAB 3 /* String table */ ++#define SHT_RELA 4 /* Relocation entries with addends */ ++#define SHT_HASH 5 /* Symbol hash table */ ++#define SHT_DYNAMIC 6 /* Dynamic linking information */ ++#define SHT_NOTE 7 /* Notes */ ++#define SHT_NOBITS 8 /* Program space with no data (bss) */ ++#define SHT_REL 9 /* Relocation entries, no addends */ ++#define SHT_SHLIB 10 /* Reserved */ ++#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ ++#define SHT_INIT_ARRAY 14 /* Array of constructors */ ++#define SHT_FINI_ARRAY 15 /* Array of destructors */ ++#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ ++#define SHT_GROUP 17 /* Section group */ ++#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ ++#define SHT_NUM 19 /* Number of defined types. */ ++#define SHT_LOOS 0x60000000 /* Start OS-specific. */ ++#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ ++#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ ++#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ ++#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ ++#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ ++#define SHT_SUNW_move 0x6ffffffa ++#define SHT_SUNW_COMDAT 0x6ffffffb ++#define SHT_SUNW_syminfo 0x6ffffffc ++#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ ++#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ ++#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ ++#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ ++#define SHT_HIOS 0x6fffffff /* End OS-specific type */ ++#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define SHT_LOUSER 0x80000000 /* Start of application-specific */ ++#define SHT_HIUSER 0x8fffffff /* End of application-specific */ ++ ++/* Legal values for sh_flags (section flags). */ ++ ++#define SHF_WRITE (1 << 0) /* Writable */ ++#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ ++#define SHF_EXECINSTR (1 << 2) /* Executable */ ++#define SHF_MERGE (1 << 4) /* Might be merged */ ++#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ ++#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ ++#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ ++#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling ++ required */ ++#define SHF_GROUP (1 << 9) /* Section is member of a group. */ ++#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ ++#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ ++#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ ++#define SHF_ORDERED (1 << 30) /* Special ordering requirement ++ (Solaris). */ ++#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless ++ referenced or allocated (Solaris).*/ ++ ++/* Section group handling. */ ++#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ ++ ++/* Symbol table entry. */ ++ ++typedef struct ++{ ++ Elf32_Word st_name; /* Symbol name (string tbl index) */ ++ Elf32_Addr st_value; /* Symbol value */ ++ Elf32_Word st_size; /* Symbol size */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf32_Section st_shndx; /* Section index */ ++} Elf32_Sym; ++ ++typedef struct ++{ ++ Elf64_Word st_name; /* Symbol name (string tbl index) */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf64_Section st_shndx; /* Section index */ ++ Elf64_Addr st_value; /* Symbol value */ ++ Elf64_Xword st_size; /* Symbol size */ ++} Elf64_Sym; ++ ++/* The syminfo section if available contains additional information about ++ every dynamic symbol. */ ++ ++typedef struct ++{ ++ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf32_Half si_flags; /* Per symbol flags */ ++} Elf32_Syminfo; ++ ++typedef struct ++{ ++ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf64_Half si_flags; /* Per symbol flags */ ++} Elf64_Syminfo; ++ ++/* Possible values for si_boundto. */ ++#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ ++#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ ++#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ ++ ++/* Possible bitmasks for si_flags. */ ++#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ ++#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ ++#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ ++#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy ++ loaded */ ++/* Syminfo version values. */ ++#define SYMINFO_NONE 0 ++#define SYMINFO_CURRENT 1 ++#define SYMINFO_NUM 2 ++ ++ ++/* How to extract and insert information held in the st_info field. */ ++ ++#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) ++#define ELF32_ST_TYPE(val) ((val) & 0xf) ++#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) ++ ++/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ ++#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) ++#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) ++#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) ++ ++/* Legal values for ST_BIND subfield of st_info (symbol binding). */ ++ ++#define STB_LOCAL 0 /* Local symbol */ ++#define STB_GLOBAL 1 /* Global symbol */ ++#define STB_WEAK 2 /* Weak symbol */ ++#define STB_NUM 3 /* Number of defined types. */ ++#define STB_LOOS 10 /* Start of OS-specific */ ++#define STB_GNU_UNIQUE 10 /* Unique symbol. */ ++#define STB_HIOS 12 /* End of OS-specific */ ++#define STB_LOPROC 13 /* Start of processor-specific */ ++#define STB_HIPROC 15 /* End of processor-specific */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_NOTYPE 0 /* Symbol type is unspecified */ ++#define STT_OBJECT 1 /* Symbol is a data object */ ++#define STT_FUNC 2 /* Symbol is a code object */ ++#define STT_SECTION 3 /* Symbol associated with a section */ ++#define STT_FILE 4 /* Symbol's name is file name */ ++#define STT_COMMON 5 /* Symbol is a common data object */ ++#define STT_TLS 6 /* Symbol is thread-local data object*/ ++#define STT_NUM 7 /* Number of defined types. */ ++#define STT_LOOS 10 /* Start of OS-specific */ ++#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ ++#define STT_HIOS 12 /* End of OS-specific */ ++#define STT_LOPROC 13 /* Start of processor-specific */ ++#define STT_HIPROC 15 /* End of processor-specific */ ++ ++ ++/* Symbol table indices are found in the hash buckets and chain table ++ of a symbol hash table section. This special index value indicates ++ the end of a chain, meaning no further symbols are found in that bucket. */ ++ ++#define STN_UNDEF 0 /* End of a chain. */ ++ ++ ++/* How to extract and insert information held in the st_other field. */ ++ ++#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) ++ ++/* For ELF64 the definitions are the same. */ ++#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) ++ ++/* Symbol visibility specification encoded in the st_other field. */ ++#define STV_DEFAULT 0 /* Default symbol visibility rules */ ++#define STV_INTERNAL 1 /* Processor specific hidden class */ ++#define STV_HIDDEN 2 /* Sym unavailable in other modules */ ++#define STV_PROTECTED 3 /* Not preemptible, not exported */ ++ ++ ++/* Relocation table entry without addend (in section of type SHT_REL). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++} Elf32_Rel; ++ ++/* I have seen two different definitions of the Elf64_Rel and ++ Elf64_Rela structures, so we'll leave them out until Novell (or ++ whoever) gets their act together. */ ++/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++} Elf64_Rel; ++ ++/* Relocation table entry with addend (in section of type SHT_RELA). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++ Elf32_Sword r_addend; /* Addend */ ++} Elf32_Rela; ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++ Elf64_Sxword r_addend; /* Addend */ ++} Elf64_Rela; ++ ++/* How to extract and insert information held in the r_info field. */ ++ ++#define ELF32_R_SYM(val) ((val) >> 8) ++#define ELF32_R_TYPE(val) ((val) & 0xff) ++#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) ++ ++#define ELF64_R_SYM(i) ((i) >> 32) ++#define ELF64_R_TYPE(i) ((i) & 0xffffffff) ++#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) ++ ++/* Program segment header. */ ++ ++typedef struct ++{ ++ Elf32_Word p_type; /* Segment type */ ++ Elf32_Off p_offset; /* Segment file offset */ ++ Elf32_Addr p_vaddr; /* Segment virtual address */ ++ Elf32_Addr p_paddr; /* Segment physical address */ ++ Elf32_Word p_filesz; /* Segment size in file */ ++ Elf32_Word p_memsz; /* Segment size in memory */ ++ Elf32_Word p_flags; /* Segment flags */ ++ Elf32_Word p_align; /* Segment alignment */ ++} Elf32_Phdr; ++ ++typedef struct ++{ ++ Elf64_Word p_type; /* Segment type */ ++ Elf64_Word p_flags; /* Segment flags */ ++ Elf64_Off p_offset; /* Segment file offset */ ++ Elf64_Addr p_vaddr; /* Segment virtual address */ ++ Elf64_Addr p_paddr; /* Segment physical address */ ++ Elf64_Xword p_filesz; /* Segment size in file */ ++ Elf64_Xword p_memsz; /* Segment size in memory */ ++ Elf64_Xword p_align; /* Segment alignment */ ++} Elf64_Phdr; ++ ++/* Special value for e_phnum. This indicates that the real number of ++ program headers is too large to fit into e_phnum. Instead the real ++ value is in the field sh_info of section 0. */ ++ ++#define PN_XNUM 0xffff ++ ++/* Legal values for p_type (segment type). */ ++ ++#define PT_NULL 0 /* Program header table entry unused */ ++#define PT_LOAD 1 /* Loadable program segment */ ++#define PT_DYNAMIC 2 /* Dynamic linking information */ ++#define PT_INTERP 3 /* Program interpreter */ ++#define PT_NOTE 4 /* Auxiliary information */ ++#define PT_SHLIB 5 /* Reserved */ ++#define PT_PHDR 6 /* Entry for header table itself */ ++#define PT_TLS 7 /* Thread-local storage segment */ ++#define PT_NUM 8 /* Number of defined types */ ++#define PT_LOOS 0x60000000 /* Start of OS-specific */ ++#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ ++#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ ++#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ ++#define PT_LOSUNW 0x6ffffffa ++#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ ++#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ ++#define PT_HISUNW 0x6fffffff ++#define PT_HIOS 0x6fffffff /* End of OS-specific */ ++#define PT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define PT_HIPROC 0x7fffffff /* End of processor-specific */ ++ ++/* Legal values for p_flags (segment flags). */ ++ ++#define PF_X (1 << 0) /* Segment is executable */ ++#define PF_W (1 << 1) /* Segment is writable */ ++#define PF_R (1 << 2) /* Segment is readable */ ++#define PF_MASKOS 0x0ff00000 /* OS-specific */ ++#define PF_MASKPROC 0xf0000000 /* Processor-specific */ ++ ++/* Legal values for note segment descriptor types for core files. */ ++ ++#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ ++#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ ++#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ ++#define NT_PRXREG 4 /* Contains copy of prxregset struct */ ++#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ ++#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ ++#define NT_AUXV 6 /* Contains copy of auxv array */ ++#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ ++#define NT_ASRS 8 /* Contains copy of asrset struct */ ++#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ ++#define NT_PSINFO 13 /* Contains copy of psinfo struct */ ++#define NT_PRCRED 14 /* Contains copy of prcred struct */ ++#define NT_UTSNAME 15 /* Contains copy of utsname struct */ ++#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ ++#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ ++#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ ++#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ ++#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ ++#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ ++#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ ++#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ ++#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ ++#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ ++ ++/* Legal values for the note segment descriptor types for object files. */ ++ ++#define NT_VERSION 1 /* Contains a version string. */ ++ ++ ++/* Dynamic section entry. */ ++ ++typedef struct ++{ ++ Elf32_Sword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf32_Word d_val; /* Integer value */ ++ Elf32_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf32_Dyn; ++ ++typedef struct ++{ ++ Elf64_Sxword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf64_Xword d_val; /* Integer value */ ++ Elf64_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf64_Dyn; ++ ++/* Legal values for d_tag (dynamic entry type). */ ++ ++#define DT_NULL 0 /* Marks end of dynamic section */ ++#define DT_NEEDED 1 /* Name of needed library */ ++#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ ++#define DT_PLTGOT 3 /* Processor defined value */ ++#define DT_HASH 4 /* Address of symbol hash table */ ++#define DT_STRTAB 5 /* Address of string table */ ++#define DT_SYMTAB 6 /* Address of symbol table */ ++#define DT_RELA 7 /* Address of Rela relocs */ ++#define DT_RELASZ 8 /* Total size of Rela relocs */ ++#define DT_RELAENT 9 /* Size of one Rela reloc */ ++#define DT_STRSZ 10 /* Size of string table */ ++#define DT_SYMENT 11 /* Size of one symbol table entry */ ++#define DT_INIT 12 /* Address of init function */ ++#define DT_FINI 13 /* Address of termination function */ ++#define DT_SONAME 14 /* Name of shared object */ ++#define DT_RPATH 15 /* Library search path (deprecated) */ ++#define DT_SYMBOLIC 16 /* Start symbol search here */ ++#define DT_REL 17 /* Address of Rel relocs */ ++#define DT_RELSZ 18 /* Total size of Rel relocs */ ++#define DT_RELENT 19 /* Size of one Rel reloc */ ++#define DT_PLTREL 20 /* Type of reloc in PLT */ ++#define DT_DEBUG 21 /* For debugging; unspecified */ ++#define DT_TEXTREL 22 /* Reloc might modify .text */ ++#define DT_JMPREL 23 /* Address of PLT relocs */ ++#define DT_BIND_NOW 24 /* Process relocations of object */ ++#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ ++#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ ++#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ ++#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ ++#define DT_RUNPATH 29 /* Library search path */ ++#define DT_FLAGS 30 /* Flags for the object being loaded */ ++#define DT_ENCODING 32 /* Start of encoded range */ ++#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ ++#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ ++#define DT_NUM 34 /* Number used */ ++#define DT_LOOS 0x6000000d /* Start of OS-specific */ ++#define DT_HIOS 0x6ffff000 /* End of OS-specific */ ++#define DT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define DT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ ++ ++/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the ++ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's ++ approach. */ ++#define DT_VALRNGLO 0x6ffffd00 ++#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ ++#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ ++#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ ++#define DT_CHECKSUM 0x6ffffdf8 ++#define DT_PLTPADSZ 0x6ffffdf9 ++#define DT_MOVEENT 0x6ffffdfa ++#define DT_MOVESZ 0x6ffffdfb ++#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ ++#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting ++ the following DT_* entry. */ ++#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ ++#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ ++#define DT_VALRNGHI 0x6ffffdff ++#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ ++#define DT_VALNUM 12 ++ ++/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the ++ Dyn.d_un.d_ptr field of the Elf*_Dyn structure. ++ ++ If any adjustment is made to the ELF object after it has been ++ built these entries will need to be adjusted. */ ++#define DT_ADDRRNGLO 0x6ffffe00 ++#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ ++#define DT_TLSDESC_PLT 0x6ffffef6 ++#define DT_TLSDESC_GOT 0x6ffffef7 ++#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ ++#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ ++#define DT_CONFIG 0x6ffffefa /* Configuration information. */ ++#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ ++#define DT_AUDIT 0x6ffffefc /* Object auditing. */ ++#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ ++#define DT_MOVETAB 0x6ffffefe /* Move table. */ ++#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ ++#define DT_ADDRRNGHI 0x6ffffeff ++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ ++#define DT_ADDRNUM 11 ++ ++/* The versioning entry types. The next are defined as part of the ++ GNU extension. */ ++#define DT_VERSYM 0x6ffffff0 ++ ++#define DT_RELACOUNT 0x6ffffff9 ++#define DT_RELCOUNT 0x6ffffffa ++ ++/* These were chosen by Sun. */ ++#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ ++#define DT_VERDEF 0x6ffffffc /* Address of version definition ++ table */ ++#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ ++#define DT_VERNEED 0x6ffffffe /* Address of table with needed ++ versions */ ++#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ ++#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ ++#define DT_VERSIONTAGNUM 16 ++ ++/* Sun added these machine-independent extensions in the "processor-specific" ++ range. Be compatible. */ ++#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ ++#define DT_FILTER 0x7fffffff /* Shared object to get values from */ ++#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) ++#define DT_EXTRANUM 3 ++ ++/* Values of `d_un.d_val' in the DT_FLAGS entry. */ ++#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ ++#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ ++#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ ++#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ ++#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ ++ ++/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 ++ entry in the dynamic section. */ ++#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ ++#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ ++#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ ++#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ ++#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ ++#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ ++#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ ++#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ ++#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ ++#define DF_1_TRANS 0x00000200 ++#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ ++#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ ++#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ ++#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ ++#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ ++#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ ++#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ ++ ++/* Flags for the feature selection in DT_FEATURE_1. */ ++#define DTF_1_PARINIT 0x00000001 ++#define DTF_1_CONFEXP 0x00000002 ++ ++/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ ++#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ ++#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not ++ generally available. */ ++ ++/* Version definition sections. */ ++ ++typedef struct ++{ ++ Elf32_Half vd_version; /* Version revision */ ++ Elf32_Half vd_flags; /* Version information */ ++ Elf32_Half vd_ndx; /* Version Index */ ++ Elf32_Half vd_cnt; /* Number of associated aux entries */ ++ Elf32_Word vd_hash; /* Version name hash value */ ++ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf32_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf32_Verdef; ++ ++typedef struct ++{ ++ Elf64_Half vd_version; /* Version revision */ ++ Elf64_Half vd_flags; /* Version information */ ++ Elf64_Half vd_ndx; /* Version Index */ ++ Elf64_Half vd_cnt; /* Number of associated aux entries */ ++ Elf64_Word vd_hash; /* Version name hash value */ ++ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf64_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf64_Verdef; ++ ++ ++/* Legal values for vd_version (version revision). */ ++#define VER_DEF_NONE 0 /* No version */ ++#define VER_DEF_CURRENT 1 /* Current version */ ++#define VER_DEF_NUM 2 /* Given version number */ ++ ++/* Legal values for vd_flags (version information flags). */ ++#define VER_FLG_BASE 0x1 /* Version definition of file itself */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++/* Versym symbol index values. */ ++#define VER_NDX_LOCAL 0 /* Symbol is local. */ ++#define VER_NDX_GLOBAL 1 /* Symbol is global. */ ++#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ ++#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ ++ ++/* Auxialiary version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vda_name; /* Version or dependency names */ ++ Elf32_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf32_Verdaux; ++ ++typedef struct ++{ ++ Elf64_Word vda_name; /* Version or dependency names */ ++ Elf64_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf64_Verdaux; ++ ++ ++/* Version dependency section. */ ++ ++typedef struct ++{ ++ Elf32_Half vn_version; /* Version of structure */ ++ Elf32_Half vn_cnt; /* Number of associated aux entries */ ++ Elf32_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf32_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf32_Verneed; ++ ++typedef struct ++{ ++ Elf64_Half vn_version; /* Version of structure */ ++ Elf64_Half vn_cnt; /* Number of associated aux entries */ ++ Elf64_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf64_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf64_Verneed; ++ ++ ++/* Legal values for vn_version (version revision). */ ++#define VER_NEED_NONE 0 /* No version */ ++#define VER_NEED_CURRENT 1 /* Current version */ ++#define VER_NEED_NUM 2 /* Given version number */ ++ ++/* Auxiliary needed version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vna_hash; /* Hash value of dependency name */ ++ Elf32_Half vna_flags; /* Dependency specific information */ ++ Elf32_Half vna_other; /* Unused */ ++ Elf32_Word vna_name; /* Dependency name string offset */ ++ Elf32_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf32_Vernaux; ++ ++typedef struct ++{ ++ Elf64_Word vna_hash; /* Hash value of dependency name */ ++ Elf64_Half vna_flags; /* Dependency specific information */ ++ Elf64_Half vna_other; /* Unused */ ++ Elf64_Word vna_name; /* Dependency name string offset */ ++ Elf64_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf64_Vernaux; ++ ++ ++/* Legal values for vna_flags. */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++ ++/* Auxiliary vector. */ ++ ++/* This vector is normally only used by the program interpreter. The ++ usual definition in an ABI supplement uses the name auxv_t. The ++ vector is not usually defined in a standard file, but it ++ can't hurt. We rename it to avoid conflicts. The sizes of these ++ types are an arrangement between the exec server and the program ++ interpreter, so we don't fully specify them here. */ ++ ++typedef struct ++{ ++ uint32_t a_type; /* Entry type */ ++ union ++ { ++ uint32_t a_val; /* Integer value */ ++ /* We use to have pointer elements added here. We cannot do that, ++ though, since it does not work when using 32-bit definitions ++ on 64-bit platforms and vice versa. */ ++ } a_un; ++} Elf32_auxv_t; ++ ++typedef struct ++{ ++ uint64_t a_type; /* Entry type */ ++ union ++ { ++ uint64_t a_val; /* Integer value */ ++ /* We use to have pointer elements added here. We cannot do that, ++ though, since it does not work when using 32-bit definitions ++ on 64-bit platforms and vice versa. */ ++ } a_un; ++} Elf64_auxv_t; ++ ++/* Legal values for a_type (entry type). */ ++ ++#define AT_NULL 0 /* End of vector */ ++#define AT_IGNORE 1 /* Entry should be ignored */ ++#define AT_EXECFD 2 /* File descriptor of program */ ++#define AT_PHDR 3 /* Program headers for program */ ++#define AT_PHENT 4 /* Size of program header entry */ ++#define AT_PHNUM 5 /* Number of program headers */ ++#define AT_PAGESZ 6 /* System page size */ ++#define AT_BASE 7 /* Base address of interpreter */ ++#define AT_FLAGS 8 /* Flags */ ++#define AT_ENTRY 9 /* Entry point of program */ ++#define AT_NOTELF 10 /* Program is not ELF */ ++#define AT_UID 11 /* Real uid */ ++#define AT_EUID 12 /* Effective uid */ ++#define AT_GID 13 /* Real gid */ ++#define AT_EGID 14 /* Effective gid */ ++#define AT_CLKTCK 17 /* Frequency of times() */ ++ ++/* Some more special a_type values describing the hardware. */ ++#define AT_PLATFORM 15 /* String identifying platform. */ ++#define AT_HWCAP 16 /* Machine dependent hints about ++ processor capabilities. */ ++ ++/* This entry gives some information about the FPU initialization ++ performed by the kernel. */ ++#define AT_FPUCW 18 /* Used FPU control word. */ ++ ++/* Cache block sizes. */ ++#define AT_DCACHEBSIZE 19 /* Data cache block size. */ ++#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ ++#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ ++ ++/* A special ignored value for PPC, used by the kernel to control the ++ interpretation of the AUXV. Must be > 16. */ ++#define AT_IGNOREPPC 22 /* Entry should be ignored. */ ++ ++#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ ++ ++#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ ++ ++#define AT_RANDOM 25 /* Address of 16 random bytes. */ ++ ++#define AT_EXECFN 31 /* Filename of executable. */ ++ ++/* Pointer to the global system page used for system calls and other ++ nice things. */ ++#define AT_SYSINFO 32 ++#define AT_SYSINFO_EHDR 33 ++ ++/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains ++ log2 of line size; mask those to get cache size. */ ++#define AT_L1I_CACHESHAPE 34 ++#define AT_L1D_CACHESHAPE 35 ++#define AT_L2_CACHESHAPE 36 ++#define AT_L3_CACHESHAPE 37 ++ ++/* Note section contents. Each entry in the note section begins with ++ a header of a fixed form. */ ++ ++typedef struct ++{ ++ Elf32_Word n_namesz; /* Length of the note's name. */ ++ Elf32_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf32_Word n_type; /* Type of the note. */ ++} Elf32_Nhdr; ++ ++typedef struct ++{ ++ Elf64_Word n_namesz; /* Length of the note's name. */ ++ Elf64_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf64_Word n_type; /* Type of the note. */ ++} Elf64_Nhdr; ++ ++/* Known names of notes. */ ++ ++/* Solaris entries in the note section have this name. */ ++#define ELF_NOTE_SOLARIS "SUNW Solaris" ++ ++/* Note entries for GNU systems have this name. */ ++#define ELF_NOTE_GNU "GNU" ++ ++ ++/* Defined types of notes for Solaris. */ ++ ++/* Value of descriptor (one word) is desired pagesize for the binary. */ ++#define ELF_NOTE_PAGESIZE_HINT 1 ++ ++ ++/* Defined note types for GNU systems. */ ++ ++/* ABI information. The descriptor consists of words: ++ word 0: OS descriptor ++ word 1: major version of the ABI ++ word 2: minor version of the ABI ++ word 3: subminor version of the ABI ++*/ ++#define NT_GNU_ABI_TAG 1 ++#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ ++ ++/* Known OSes. These values can appear in word 0 of an ++ NT_GNU_ABI_TAG note section entry. */ ++#define ELF_NOTE_OS_LINUX 0 ++#define ELF_NOTE_OS_GNU 1 ++#define ELF_NOTE_OS_SOLARIS2 2 ++#define ELF_NOTE_OS_FREEBSD 3 ++ ++/* Synthetic hwcap information. The descriptor begins with two words: ++ word 0: number of entries ++ word 1: bitmask of enabled entries ++ Then follow variable-length entries, one byte followed by a ++ '\0'-terminated hwcap name string. The byte gives the bit ++ number to test if enabled, (1U << bit) & bitmask. */ ++#define NT_GNU_HWCAP 2 ++ ++/* Build ID bits as generated by ld --build-id. ++ The descriptor consists of any nonzero number of bytes. */ ++#define NT_GNU_BUILD_ID 3 ++ ++/* Version note generated by GNU gold containing a version string. */ ++#define NT_GNU_GOLD_VERSION 4 ++ ++ ++/* Move records. */ ++typedef struct ++{ ++ Elf32_Xword m_value; /* Symbol value. */ ++ Elf32_Word m_info; /* Size and index. */ ++ Elf32_Word m_poffset; /* Symbol offset. */ ++ Elf32_Half m_repeat; /* Repeat count. */ ++ Elf32_Half m_stride; /* Stride info. */ ++} Elf32_Move; ++ ++typedef struct ++{ ++ Elf64_Xword m_value; /* Symbol value. */ ++ Elf64_Xword m_info; /* Size and index. */ ++ Elf64_Xword m_poffset; /* Symbol offset. */ ++ Elf64_Half m_repeat; /* Repeat count. */ ++ Elf64_Half m_stride; /* Stride info. */ ++} Elf64_Move; ++ ++/* Macro to construct move records. */ ++#define ELF32_M_SYM(info) ((info) >> 8) ++#define ELF32_M_SIZE(info) ((unsigned char) (info)) ++#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) ++ ++#define ELF64_M_SYM(info) ELF32_M_SYM (info) ++#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) ++#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) ++ ++ ++/* Motorola 68k specific definitions. */ ++ ++/* Values for Elf32_Ehdr.e_flags. */ ++#define EF_CPU32 0x00810000 ++ ++/* m68k relocs. */ ++ ++#define R_68K_NONE 0 /* No reloc */ ++#define R_68K_32 1 /* Direct 32 bit */ ++#define R_68K_16 2 /* Direct 16 bit */ ++#define R_68K_8 3 /* Direct 8 bit */ ++#define R_68K_PC32 4 /* PC relative 32 bit */ ++#define R_68K_PC16 5 /* PC relative 16 bit */ ++#define R_68K_PC8 6 /* PC relative 8 bit */ ++#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ ++#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ ++#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ ++#define R_68K_GOT32O 10 /* 32 bit GOT offset */ ++#define R_68K_GOT16O 11 /* 16 bit GOT offset */ ++#define R_68K_GOT8O 12 /* 8 bit GOT offset */ ++#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ ++#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ ++#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ ++#define R_68K_PLT32O 16 /* 32 bit PLT offset */ ++#define R_68K_PLT16O 17 /* 16 bit PLT offset */ ++#define R_68K_PLT8O 18 /* 8 bit PLT offset */ ++#define R_68K_COPY 19 /* Copy symbol at runtime */ ++#define R_68K_GLOB_DAT 20 /* Create GOT entry */ ++#define R_68K_JMP_SLOT 21 /* Create PLT entry */ ++#define R_68K_RELATIVE 22 /* Adjust by program base */ ++#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ ++#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ ++#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ ++#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ ++#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ ++#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ ++#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ ++#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ ++#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ ++#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ ++#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ ++#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ ++#define R_68K_TLS_LE32 37 /* 32 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_LE16 38 /* 16 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_LE8 39 /* 8 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ ++#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ ++#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ ++/* Keep this the last entry. */ ++#define R_68K_NUM 43 ++ ++/* Intel 80386 specific definitions. */ ++ ++/* i386 relocs. */ ++ ++#define R_386_NONE 0 /* No reloc */ ++#define R_386_32 1 /* Direct 32 bit */ ++#define R_386_PC32 2 /* PC relative 32 bit */ ++#define R_386_GOT32 3 /* 32 bit GOT entry */ ++#define R_386_PLT32 4 /* 32 bit PLT address */ ++#define R_386_COPY 5 /* Copy symbol at runtime */ ++#define R_386_GLOB_DAT 6 /* Create GOT entry */ ++#define R_386_JMP_SLOT 7 /* Create PLT entry */ ++#define R_386_RELATIVE 8 /* Adjust by program base */ ++#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ ++#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ ++#define R_386_32PLT 11 ++#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ ++#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS ++ block offset */ ++#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block ++ offset */ ++#define R_386_TLS_LE 17 /* Offset relative to static TLS ++ block */ ++#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of ++ general dynamic thread local data */ ++#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of ++ local dynamic thread local data ++ in LE code */ ++#define R_386_16 20 ++#define R_386_PC16 21 ++#define R_386_8 22 ++#define R_386_PC8 23 ++#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic ++ thread local data */ ++#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ ++#define R_386_TLS_GD_CALL 26 /* Relocation for call to ++ __tls_get_addr() */ ++#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ ++#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic ++ thread local data in LE code */ ++#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ ++#define R_386_TLS_LDM_CALL 30 /* Relocation for call to ++ __tls_get_addr() in LDM code */ ++#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ ++#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ ++#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS ++ block offset */ ++#define R_386_TLS_LE_32 34 /* Negated offset relative to static ++ TLS block */ ++#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ ++#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ ++#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ ++/* 38? */ ++#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ ++#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS ++ descriptor for ++ relaxation. */ ++#define R_386_TLS_DESC 41 /* TLS descriptor containing ++ pointer to code and to ++ argument, returning the TLS ++ offset for the symbol. */ ++#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ ++/* Keep this the last entry. */ ++#define R_386_NUM 43 ++ ++/* SUN SPARC specific definitions. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ ++ ++/* Values for Elf64_Ehdr.e_flags. */ ++ ++#define EF_SPARCV9_MM 3 ++#define EF_SPARCV9_TSO 0 ++#define EF_SPARCV9_PSO 1 ++#define EF_SPARCV9_RMO 2 ++#define EF_SPARC_LEDATA 0x800000 /* little endian data */ ++#define EF_SPARC_EXT_MASK 0xFFFF00 ++#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ ++#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ ++#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ ++#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ ++ ++/* SPARC relocs. */ ++ ++#define R_SPARC_NONE 0 /* No reloc */ ++#define R_SPARC_8 1 /* Direct 8 bit */ ++#define R_SPARC_16 2 /* Direct 16 bit */ ++#define R_SPARC_32 3 /* Direct 32 bit */ ++#define R_SPARC_DISP8 4 /* PC relative 8 bit */ ++#define R_SPARC_DISP16 5 /* PC relative 16 bit */ ++#define R_SPARC_DISP32 6 /* PC relative 32 bit */ ++#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ ++#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ ++#define R_SPARC_HI22 9 /* High 22 bit */ ++#define R_SPARC_22 10 /* Direct 22 bit */ ++#define R_SPARC_13 11 /* Direct 13 bit */ ++#define R_SPARC_LO10 12 /* Truncated 10 bit */ ++#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ ++#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ ++#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ ++#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ ++#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ ++#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ ++#define R_SPARC_COPY 19 /* Copy symbol at runtime */ ++#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ ++#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ ++#define R_SPARC_RELATIVE 22 /* Adjust by program base */ ++#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ ++ ++/* Additional Sparc64 relocs. */ ++ ++#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ ++#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ ++#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ ++#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ ++#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ ++#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ ++#define R_SPARC_10 30 /* Direct 10 bit */ ++#define R_SPARC_11 31 /* Direct 11 bit */ ++#define R_SPARC_64 32 /* Direct 64 bit */ ++#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ ++#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ ++#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ ++#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ ++#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ ++#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ ++#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ ++#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ ++#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ ++#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ ++#define R_SPARC_7 43 /* Direct 7 bit */ ++#define R_SPARC_5 44 /* Direct 5 bit */ ++#define R_SPARC_6 45 /* Direct 6 bit */ ++#define R_SPARC_DISP64 46 /* PC relative 64 bit */ ++#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ ++#define R_SPARC_HIX22 48 /* High 22 bit complemented */ ++#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ ++#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ ++#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ ++#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ ++#define R_SPARC_REGISTER 53 /* Global register usage */ ++#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ ++#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ ++#define R_SPARC_TLS_GD_HI22 56 ++#define R_SPARC_TLS_GD_LO10 57 ++#define R_SPARC_TLS_GD_ADD 58 ++#define R_SPARC_TLS_GD_CALL 59 ++#define R_SPARC_TLS_LDM_HI22 60 ++#define R_SPARC_TLS_LDM_LO10 61 ++#define R_SPARC_TLS_LDM_ADD 62 ++#define R_SPARC_TLS_LDM_CALL 63 ++#define R_SPARC_TLS_LDO_HIX22 64 ++#define R_SPARC_TLS_LDO_LOX10 65 ++#define R_SPARC_TLS_LDO_ADD 66 ++#define R_SPARC_TLS_IE_HI22 67 ++#define R_SPARC_TLS_IE_LO10 68 ++#define R_SPARC_TLS_IE_LD 69 ++#define R_SPARC_TLS_IE_LDX 70 ++#define R_SPARC_TLS_IE_ADD 71 ++#define R_SPARC_TLS_LE_HIX22 72 ++#define R_SPARC_TLS_LE_LOX10 73 ++#define R_SPARC_TLS_DTPMOD32 74 ++#define R_SPARC_TLS_DTPMOD64 75 ++#define R_SPARC_TLS_DTPOFF32 76 ++#define R_SPARC_TLS_DTPOFF64 77 ++#define R_SPARC_TLS_TPOFF32 78 ++#define R_SPARC_TLS_TPOFF64 79 ++#define R_SPARC_GOTDATA_HIX22 80 ++#define R_SPARC_GOTDATA_LOX10 81 ++#define R_SPARC_GOTDATA_OP_HIX22 82 ++#define R_SPARC_GOTDATA_OP_LOX10 83 ++#define R_SPARC_GOTDATA_OP 84 ++#define R_SPARC_H34 85 ++#define R_SPARC_SIZE32 86 ++#define R_SPARC_SIZE64 87 ++#define R_SPARC_WDISP10 88 ++#define R_SPARC_JMP_IREL 248 ++#define R_SPARC_IRELATIVE 249 ++#define R_SPARC_GNU_VTINHERIT 250 ++#define R_SPARC_GNU_VTENTRY 251 ++#define R_SPARC_REV32 252 ++/* Keep this the last entry. */ ++#define R_SPARC_NUM 253 ++ ++/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ ++ ++#define DT_SPARC_REGISTER 0x70000001 ++#define DT_SPARC_NUM 2 ++ ++/* MIPS R3000 specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ ++#define EF_MIPS_PIC 2 /* Contains PIC code */ ++#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ ++#define EF_MIPS_XGOT 8 ++#define EF_MIPS_64BIT_WHIRL 16 ++#define EF_MIPS_ABI2 32 ++#define EF_MIPS_ABI_ON32 64 ++#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ ++ ++/* Legal values for MIPS architecture level. */ ++ ++#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* The following are non-official names and should not be used. */ ++ ++#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* Special section indices. */ ++ ++#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ ++#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ ++#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ ++#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ ++#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ ++#define SHT_MIPS_MSYM 0x70000001 ++#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ ++#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ ++#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ ++#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ ++#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ ++#define SHT_MIPS_PACKAGE 0x70000007 ++#define SHT_MIPS_PACKSYM 0x70000008 ++#define SHT_MIPS_RELD 0x70000009 ++#define SHT_MIPS_IFACE 0x7000000b ++#define SHT_MIPS_CONTENT 0x7000000c ++#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ ++#define SHT_MIPS_SHDR 0x70000010 ++#define SHT_MIPS_FDESC 0x70000011 ++#define SHT_MIPS_EXTSYM 0x70000012 ++#define SHT_MIPS_DENSE 0x70000013 ++#define SHT_MIPS_PDESC 0x70000014 ++#define SHT_MIPS_LOCSYM 0x70000015 ++#define SHT_MIPS_AUXSYM 0x70000016 ++#define SHT_MIPS_OPTSYM 0x70000017 ++#define SHT_MIPS_LOCSTR 0x70000018 ++#define SHT_MIPS_LINE 0x70000019 ++#define SHT_MIPS_RFDESC 0x7000001a ++#define SHT_MIPS_DELTASYM 0x7000001b ++#define SHT_MIPS_DELTAINST 0x7000001c ++#define SHT_MIPS_DELTACLASS 0x7000001d ++#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ ++#define SHT_MIPS_DELTADECL 0x7000001f ++#define SHT_MIPS_SYMBOL_LIB 0x70000020 ++#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ ++#define SHT_MIPS_TRANSLATE 0x70000022 ++#define SHT_MIPS_PIXIE 0x70000023 ++#define SHT_MIPS_XLATE 0x70000024 ++#define SHT_MIPS_XLATE_DEBUG 0x70000025 ++#define SHT_MIPS_WHIRL 0x70000026 ++#define SHT_MIPS_EH_REGION 0x70000027 ++#define SHT_MIPS_XLATE_OLD 0x70000028 ++#define SHT_MIPS_PDR_EXCEPTION 0x70000029 ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ ++#define SHF_MIPS_MERGE 0x20000000 ++#define SHF_MIPS_ADDR 0x40000000 ++#define SHF_MIPS_STRINGS 0x80000000 ++#define SHF_MIPS_NOSTRIP 0x08000000 ++#define SHF_MIPS_LOCAL 0x04000000 ++#define SHF_MIPS_NAMES 0x02000000 ++#define SHF_MIPS_NODUPE 0x01000000 ++ ++ ++/* Symbol tables. */ ++ ++/* MIPS specific values for `st_other'. */ ++#define STO_MIPS_DEFAULT 0x0 ++#define STO_MIPS_INTERNAL 0x1 ++#define STO_MIPS_HIDDEN 0x2 ++#define STO_MIPS_PROTECTED 0x3 ++#define STO_MIPS_PLT 0x8 ++#define STO_MIPS_SC_ALIGN_UNUSED 0xff ++ ++/* MIPS specific values for `st_info'. */ ++#define STB_MIPS_SPLIT_COMMON 13 ++ ++/* Entries found in sections of type SHT_MIPS_GPTAB. */ ++ ++typedef union ++{ ++ struct ++ { ++ Elf32_Word gt_current_g_value; /* -G value used for compilation */ ++ Elf32_Word gt_unused; /* Not used */ ++ } gt_header; /* First entry in section */ ++ struct ++ { ++ Elf32_Word gt_g_value; /* If this value were used for -G */ ++ Elf32_Word gt_bytes; /* This many bytes would be used */ ++ } gt_entry; /* Subsequent entries in section */ ++} Elf32_gptab; ++ ++/* Entry found in sections of type SHT_MIPS_REGINFO. */ ++ ++typedef struct ++{ ++ Elf32_Word ri_gprmask; /* General registers used */ ++ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ ++ Elf32_Sword ri_gp_value; /* $gp register value */ ++} Elf32_RegInfo; ++ ++/* Entries found in sections of type SHT_MIPS_OPTIONS. */ ++ ++typedef struct ++{ ++ unsigned char kind; /* Determines interpretation of the ++ variable part of descriptor. */ ++ unsigned char size; /* Size of descriptor, including header. */ ++ Elf32_Section section; /* Section header index of section affected, ++ 0 for global options. */ ++ Elf32_Word info; /* Kind-specific information. */ ++} Elf_Options; ++ ++/* Values for `kind' field in Elf_Options. */ ++ ++#define ODK_NULL 0 /* Undefined. */ ++#define ODK_REGINFO 1 /* Register usage information. */ ++#define ODK_EXCEPTIONS 2 /* Exception processing options. */ ++#define ODK_PAD 3 /* Section padding options. */ ++#define ODK_HWPATCH 4 /* Hardware workarounds performed */ ++#define ODK_FILL 5 /* record the fill value used by the linker. */ ++#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ ++#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ ++#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ ++ ++/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ ++ ++#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ ++#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ ++#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ ++#define OEX_SMM 0x20000 /* Force sequential memory mode? */ ++#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ ++#define OEX_PRECISEFP OEX_FPDBUG ++#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ ++ ++#define OEX_FPU_INVAL 0x10 ++#define OEX_FPU_DIV0 0x08 ++#define OEX_FPU_OFLO 0x04 ++#define OEX_FPU_UFLO 0x02 ++#define OEX_FPU_INEX 0x01 ++ ++/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ ++ ++#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ ++#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ ++#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ ++#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ ++ ++#define OPAD_PREFIX 0x1 ++#define OPAD_POSTFIX 0x2 ++#define OPAD_SYMBOL 0x4 ++ ++/* Entry found in `.options' section. */ ++ ++typedef struct ++{ ++ Elf32_Word hwp_flags1; /* Extra flags. */ ++ Elf32_Word hwp_flags2; /* Extra flags. */ ++} Elf_Options_Hw; ++ ++/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ ++ ++#define OHWA0_R4KEOP_CHECKED 0x00000001 ++#define OHWA1_R4KEOP_CLEAN 0x00000002 ++ ++/* MIPS relocs. */ ++ ++#define R_MIPS_NONE 0 /* No reloc */ ++#define R_MIPS_16 1 /* Direct 16 bit */ ++#define R_MIPS_32 2 /* Direct 32 bit */ ++#define R_MIPS_REL32 3 /* PC relative 32 bit */ ++#define R_MIPS_26 4 /* Direct 26 bit shifted */ ++#define R_MIPS_HI16 5 /* High 16 bit */ ++#define R_MIPS_LO16 6 /* Low 16 bit */ ++#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ ++#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ ++#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ ++#define R_MIPS_PC16 10 /* PC relative 16 bit */ ++#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ ++#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ ++ ++#define R_MIPS_SHIFT5 16 ++#define R_MIPS_SHIFT6 17 ++#define R_MIPS_64 18 ++#define R_MIPS_GOT_DISP 19 ++#define R_MIPS_GOT_PAGE 20 ++#define R_MIPS_GOT_OFST 21 ++#define R_MIPS_GOT_HI16 22 ++#define R_MIPS_GOT_LO16 23 ++#define R_MIPS_SUB 24 ++#define R_MIPS_INSERT_A 25 ++#define R_MIPS_INSERT_B 26 ++#define R_MIPS_DELETE 27 ++#define R_MIPS_HIGHER 28 ++#define R_MIPS_HIGHEST 29 ++#define R_MIPS_CALL_HI16 30 ++#define R_MIPS_CALL_LO16 31 ++#define R_MIPS_SCN_DISP 32 ++#define R_MIPS_REL16 33 ++#define R_MIPS_ADD_IMMEDIATE 34 ++#define R_MIPS_PJUMP 35 ++#define R_MIPS_RELGOT 36 ++#define R_MIPS_JALR 37 ++#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ ++#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ ++#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ ++#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ ++#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ ++#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ ++#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ ++#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ ++#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ ++#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ ++#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ ++#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ ++#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ ++#define R_MIPS_GLOB_DAT 51 ++#define R_MIPS_COPY 126 ++#define R_MIPS_JUMP_SLOT 127 ++/* Keep this the last entry. */ ++#define R_MIPS_NUM 128 ++ ++/* Legal values for p_type field of Elf32_Phdr. */ ++ ++#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ ++#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ ++#define PT_MIPS_OPTIONS 0x70000002 ++ ++/* Special program header types. */ ++ ++#define PF_MIPS_LOCAL 0x10000000 ++ ++/* Legal values for d_tag field of Elf32_Dyn. */ ++ ++#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ ++#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ ++#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ ++#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ ++#define DT_MIPS_FLAGS 0x70000005 /* Flags */ ++#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ ++#define DT_MIPS_MSYM 0x70000007 ++#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ ++#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ ++#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ ++#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ ++#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ ++#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ ++#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ ++#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ ++#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ ++#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ ++#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ ++#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in ++ DT_MIPS_DELTA_CLASS. */ ++#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ ++#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in ++ DT_MIPS_DELTA_INSTANCE. */ ++#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ ++#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in ++ DT_MIPS_DELTA_RELOC. */ ++#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta ++ relocations refer to. */ ++#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in ++ DT_MIPS_DELTA_SYM. */ ++#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the ++ class declaration. */ ++#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in ++ DT_MIPS_DELTA_CLASSSYM. */ ++#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ ++#define DT_MIPS_PIXIE_INIT 0x70000023 ++#define DT_MIPS_SYMBOL_LIB 0x70000024 ++#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 ++#define DT_MIPS_LOCAL_GOTIDX 0x70000026 ++#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 ++#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 ++#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ ++#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ ++#define DT_MIPS_DYNSTR_ALIGN 0x7000002b ++#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ ++#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve ++ function stored in GOT. */ ++#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added ++ by rld on dlopen() calls. */ ++#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ ++#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ ++#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ ++/* The address of .got.plt in an executable using the new non-PIC ABI. */ ++#define DT_MIPS_PLTGOT 0x70000032 ++/* The base of the PLT in an executable using the new non-PIC ABI if that ++ PLT is writable. For a non-writable PLT, this is omitted or has a zero ++ value. */ ++#define DT_MIPS_RWPLT 0x70000034 ++#define DT_MIPS_NUM 0x35 ++ ++/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ ++ ++#define RHF_NONE 0 /* No flags */ ++#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ ++#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ ++#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ ++#define RHF_NO_MOVE (1 << 3) ++#define RHF_SGI_ONLY (1 << 4) ++#define RHF_GUARANTEE_INIT (1 << 5) ++#define RHF_DELTA_C_PLUS_PLUS (1 << 6) ++#define RHF_GUARANTEE_START_INIT (1 << 7) ++#define RHF_PIXIE (1 << 8) ++#define RHF_DEFAULT_DELAY_LOAD (1 << 9) ++#define RHF_REQUICKSTART (1 << 10) ++#define RHF_REQUICKSTARTED (1 << 11) ++#define RHF_CORD (1 << 12) ++#define RHF_NO_UNRES_UNDEF (1 << 13) ++#define RHF_RLD_ORDER_SAFE (1 << 14) ++ ++/* Entries found in sections of type SHT_MIPS_LIBLIST. */ ++ ++typedef struct ++{ ++ Elf32_Word l_name; /* Name (string table index) */ ++ Elf32_Word l_time_stamp; /* Timestamp */ ++ Elf32_Word l_checksum; /* Checksum */ ++ Elf32_Word l_version; /* Interface version */ ++ Elf32_Word l_flags; /* Flags */ ++} Elf32_Lib; ++ ++typedef struct ++{ ++ Elf64_Word l_name; /* Name (string table index) */ ++ Elf64_Word l_time_stamp; /* Timestamp */ ++ Elf64_Word l_checksum; /* Checksum */ ++ Elf64_Word l_version; /* Interface version */ ++ Elf64_Word l_flags; /* Flags */ ++} Elf64_Lib; ++ ++ ++/* Legal values for l_flags. */ ++ ++#define LL_NONE 0 ++#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ ++#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ ++#define LL_REQUIRE_MINOR (1 << 2) ++#define LL_EXPORTS (1 << 3) ++#define LL_DELAY_LOAD (1 << 4) ++#define LL_DELTA (1 << 5) ++ ++/* Entries found in sections of type SHT_MIPS_CONFLICT. */ ++ ++typedef Elf32_Addr Elf32_Conflict; ++ ++ ++/* HPPA specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ ++#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ ++#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ ++#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ ++#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch ++ prediction. */ ++#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ ++#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ ++ ++/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ ++ ++#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ ++#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ ++#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ ++ ++/* Additional section indeces. */ ++ ++#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared ++ symbols in ANSI C. */ ++#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ ++#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ ++#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ ++#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ ++#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ ++ ++#define STT_HP_OPAQUE (STT_LOOS + 0x1) ++#define STT_HP_STUB (STT_LOOS + 0x2) ++ ++/* HPPA relocs. */ ++ ++#define R_PARISC_NONE 0 /* No reloc. */ ++#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ ++#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ ++#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ ++#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ ++#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ ++#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ ++#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ ++#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ ++#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ ++#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ ++#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ ++#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ ++#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ ++#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ ++#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ ++#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ ++#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ ++#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ ++#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ ++#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ ++#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ ++#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ ++#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ ++#define R_PARISC_FPTR64 64 /* 64 bits function address. */ ++#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ ++#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ ++#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ ++#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ ++#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ ++#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ ++#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ ++#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ ++#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ ++#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ ++#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ ++#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ ++#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ ++#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ ++#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ ++#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ ++#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ ++#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LORESERVE 128 ++#define R_PARISC_COPY 128 /* Copy relocation. */ ++#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ ++#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ ++#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ ++#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ ++#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ ++#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ ++#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ ++#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ ++#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_GNU_VTENTRY 232 ++#define R_PARISC_GNU_VTINHERIT 233 ++#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ ++#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ ++#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ ++#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ ++#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ ++#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ ++#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ ++#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ ++#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ ++#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ ++#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ ++#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ ++#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L ++#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R ++#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L ++#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R ++#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 ++#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 ++#define R_PARISC_HIRESERVE 255 ++ ++/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PT_HP_TLS (PT_LOOS + 0x0) ++#define PT_HP_CORE_NONE (PT_LOOS + 0x1) ++#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) ++#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) ++#define PT_HP_CORE_COMM (PT_LOOS + 0x4) ++#define PT_HP_CORE_PROC (PT_LOOS + 0x5) ++#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) ++#define PT_HP_CORE_STACK (PT_LOOS + 0x7) ++#define PT_HP_CORE_SHM (PT_LOOS + 0x8) ++#define PT_HP_CORE_MMF (PT_LOOS + 0x9) ++#define PT_HP_PARALLEL (PT_LOOS + 0x10) ++#define PT_HP_FASTBIND (PT_LOOS + 0x11) ++#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) ++#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) ++#define PT_HP_STACK (PT_LOOS + 0x14) ++ ++#define PT_PARISC_ARCHEXT 0x70000000 ++#define PT_PARISC_UNWIND 0x70000001 ++ ++/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PF_PARISC_SBP 0x08000000 ++ ++#define PF_HP_PAGE_SIZE 0x00100000 ++#define PF_HP_FAR_SHARED 0x00200000 ++#define PF_HP_NEAR_SHARED 0x00400000 ++#define PF_HP_CODE 0x01000000 ++#define PF_HP_MODIFY 0x02000000 ++#define PF_HP_LAZYSWAP 0x04000000 ++#define PF_HP_SBP 0x08000000 ++ ++ ++/* Alpha specific definitions. */ ++ ++/* Legal values for e_flags field of Elf64_Ehdr. */ ++ ++#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ ++#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ ++ ++/* Legal values for sh_type field of Elf64_Shdr. */ ++ ++/* These two are primerily concerned with ECOFF debugging info. */ ++#define SHT_ALPHA_DEBUG 0x70000001 ++#define SHT_ALPHA_REGINFO 0x70000002 ++ ++/* Legal values for sh_flags field of Elf64_Shdr. */ ++ ++#define SHF_ALPHA_GPREL 0x10000000 ++ ++/* Legal values for st_other field of Elf64_Sym. */ ++#define STO_ALPHA_NOPV 0x80 /* No PV required. */ ++#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ ++ ++/* Alpha relocs. */ ++ ++#define R_ALPHA_NONE 0 /* No reloc */ ++#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ ++#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ ++#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ ++#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ ++#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ ++#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ ++#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ ++#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ ++#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ ++#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ ++#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ ++#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ ++#define R_ALPHA_TLS_GD_HI 28 ++#define R_ALPHA_TLSGD 29 ++#define R_ALPHA_TLS_LDM 30 ++#define R_ALPHA_DTPMOD64 31 ++#define R_ALPHA_GOTDTPREL 32 ++#define R_ALPHA_DTPREL64 33 ++#define R_ALPHA_DTPRELHI 34 ++#define R_ALPHA_DTPRELLO 35 ++#define R_ALPHA_DTPREL16 36 ++#define R_ALPHA_GOTTPREL 37 ++#define R_ALPHA_TPREL64 38 ++#define R_ALPHA_TPRELHI 39 ++#define R_ALPHA_TPRELLO 40 ++#define R_ALPHA_TPREL16 41 ++/* Keep this the last entry. */ ++#define R_ALPHA_NUM 46 ++ ++/* Magic values of the LITUSE relocation addend. */ ++#define LITUSE_ALPHA_ADDR 0 ++#define LITUSE_ALPHA_BASE 1 ++#define LITUSE_ALPHA_BYTOFF 2 ++#define LITUSE_ALPHA_JSR 3 ++#define LITUSE_ALPHA_TLS_GD 4 ++#define LITUSE_ALPHA_TLS_LDM 5 ++ ++/* Legal values for d_tag of Elf64_Dyn. */ ++#define DT_ALPHA_PLTRO (DT_LOPROC + 0) ++#define DT_ALPHA_NUM 1 ++ ++/* PowerPC specific declarations */ ++ ++/* Values for Elf32/64_Ehdr.e_flags. */ ++#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ ++ ++/* Cygnus local bits below */ ++#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ ++#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib ++ flag */ ++ ++/* PowerPC relocations defined by the ABIs */ ++#define R_PPC_NONE 0 ++#define R_PPC_ADDR32 1 /* 32bit absolute address */ ++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ ++#define R_PPC_ADDR16 3 /* 16bit absolute address */ ++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ ++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ ++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ ++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ ++#define R_PPC_ADDR14_BRTAKEN 8 ++#define R_PPC_ADDR14_BRNTAKEN 9 ++#define R_PPC_REL24 10 /* PC relative 26 bit */ ++#define R_PPC_REL14 11 /* PC relative 16 bit */ ++#define R_PPC_REL14_BRTAKEN 12 ++#define R_PPC_REL14_BRNTAKEN 13 ++#define R_PPC_GOT16 14 ++#define R_PPC_GOT16_LO 15 ++#define R_PPC_GOT16_HI 16 ++#define R_PPC_GOT16_HA 17 ++#define R_PPC_PLTREL24 18 ++#define R_PPC_COPY 19 ++#define R_PPC_GLOB_DAT 20 ++#define R_PPC_JMP_SLOT 21 ++#define R_PPC_RELATIVE 22 ++#define R_PPC_LOCAL24PC 23 ++#define R_PPC_UADDR32 24 ++#define R_PPC_UADDR16 25 ++#define R_PPC_REL32 26 ++#define R_PPC_PLT32 27 ++#define R_PPC_PLTREL32 28 ++#define R_PPC_PLT16_LO 29 ++#define R_PPC_PLT16_HI 30 ++#define R_PPC_PLT16_HA 31 ++#define R_PPC_SDAREL16 32 ++#define R_PPC_SECTOFF 33 ++#define R_PPC_SECTOFF_LO 34 ++#define R_PPC_SECTOFF_HI 35 ++#define R_PPC_SECTOFF_HA 36 ++ ++/* PowerPC relocations defined for the TLS access ABI. */ ++#define R_PPC_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ ++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ ++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ ++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ ++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ ++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ ++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ ++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ ++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ ++ ++/* The remaining relocs are from the Embedded ELF ABI, and are not ++ in the SVR4 ELF ABI. */ ++#define R_PPC_EMB_NADDR32 101 ++#define R_PPC_EMB_NADDR16 102 ++#define R_PPC_EMB_NADDR16_LO 103 ++#define R_PPC_EMB_NADDR16_HI 104 ++#define R_PPC_EMB_NADDR16_HA 105 ++#define R_PPC_EMB_SDAI16 106 ++#define R_PPC_EMB_SDA2I16 107 ++#define R_PPC_EMB_SDA2REL 108 ++#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ ++#define R_PPC_EMB_MRKREF 110 ++#define R_PPC_EMB_RELSEC16 111 ++#define R_PPC_EMB_RELST_LO 112 ++#define R_PPC_EMB_RELST_HI 113 ++#define R_PPC_EMB_RELST_HA 114 ++#define R_PPC_EMB_BIT_FLD 115 ++#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ ++ ++/* Diab tool relocations. */ ++#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ ++#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ ++#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ ++#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ ++#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ ++#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ ++ ++/* GNU extension to support local ifunc. */ ++#define R_PPC_IRELATIVE 248 ++ ++/* GNU relocs used in PIC code sequences. */ ++#define R_PPC_REL16 249 /* half16 (sym+add-.) */ ++#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ ++#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ ++#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ ++ ++/* This is a phony reloc to handle any old fashioned TOC16 references ++ that may still be in object files. */ ++#define R_PPC_TOC16 255 ++ ++/* PowerPC specific values for the Dyn d_tag field. */ ++#define DT_PPC_GOT (DT_LOPROC + 0) ++#define DT_PPC_NUM 1 ++ ++/* PowerPC64 relocations defined by the ABIs */ ++#define R_PPC64_NONE R_PPC_NONE ++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ ++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ ++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ ++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ ++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ ++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ ++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ ++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN ++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN ++#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ ++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ ++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN ++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN ++#define R_PPC64_GOT16 R_PPC_GOT16 ++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO ++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI ++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA ++ ++#define R_PPC64_COPY R_PPC_COPY ++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT ++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT ++#define R_PPC64_RELATIVE R_PPC_RELATIVE ++ ++#define R_PPC64_UADDR32 R_PPC_UADDR32 ++#define R_PPC64_UADDR16 R_PPC_UADDR16 ++#define R_PPC64_REL32 R_PPC_REL32 ++#define R_PPC64_PLT32 R_PPC_PLT32 ++#define R_PPC64_PLTREL32 R_PPC_PLTREL32 ++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO ++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI ++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA ++ ++#define R_PPC64_SECTOFF R_PPC_SECTOFF ++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO ++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI ++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA ++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ ++#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ ++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ ++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ ++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ ++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ ++#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ ++#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ ++#define R_PPC64_PLT64 45 /* doubleword64 L + A */ ++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ ++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ ++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ ++#define R_PPC64_TOC 51 /* doubleword64 .TOC */ ++#define R_PPC64_PLTGOT16 52 /* half16* M + A */ ++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ ++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ ++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ ++ ++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ ++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ ++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ ++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ ++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ ++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ ++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ ++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ ++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ ++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ ++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ ++ ++/* PowerPC64 relocations defined for the TLS access ABI. */ ++#define R_PPC64_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ ++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ ++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ ++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ ++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ ++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ ++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ ++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ ++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ ++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ ++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ ++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ ++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ ++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ ++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ ++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ ++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ ++ ++/* GNU extension to support local ifunc. */ ++#define R_PPC64_JMP_IREL 247 ++#define R_PPC64_IRELATIVE 248 ++#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ ++#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ ++#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ ++#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ ++ ++/* PowerPC64 specific values for the Dyn d_tag field. */ ++#define DT_PPC64_GLINK (DT_LOPROC + 0) ++#define DT_PPC64_OPD (DT_LOPROC + 1) ++#define DT_PPC64_OPDSZ (DT_LOPROC + 2) ++#define DT_PPC64_NUM 3 ++ ++ ++/* ARM specific declarations */ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++#define EF_ARM_RELEXEC 0x01 ++#define EF_ARM_HASENTRY 0x02 ++#define EF_ARM_INTERWORK 0x04 ++#define EF_ARM_APCS_26 0x08 ++#define EF_ARM_APCS_FLOAT 0x10 ++#define EF_ARM_PIC 0x20 ++#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ ++#define EF_ARM_NEW_ABI 0x80 ++#define EF_ARM_OLD_ABI 0x100 ++#define EF_ARM_SOFT_FLOAT 0x200 ++#define EF_ARM_VFP_FLOAT 0x400 ++#define EF_ARM_MAVERICK_FLOAT 0x800 ++ ++ ++/* Other constants defined in the ARM ELF spec. version B-01. */ ++/* NB. These conflict with values defined above. */ ++#define EF_ARM_SYMSARESORTED 0x04 ++#define EF_ARM_DYNSYMSUSESEGIDX 0x08 ++#define EF_ARM_MAPSYMSFIRST 0x10 ++#define EF_ARM_EABIMASK 0XFF000000 ++ ++/* Constants defined in AAELF. */ ++#define EF_ARM_BE8 0x00800000 ++#define EF_ARM_LE8 0x00400000 ++ ++#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) ++#define EF_ARM_EABI_UNKNOWN 0x00000000 ++#define EF_ARM_EABI_VER1 0x01000000 ++#define EF_ARM_EABI_VER2 0x02000000 ++#define EF_ARM_EABI_VER3 0x03000000 ++#define EF_ARM_EABI_VER4 0x04000000 ++#define EF_ARM_EABI_VER5 0x05000000 ++ ++/* Additional symbol types for Thumb. */ ++#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ ++#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ ++ ++/* ARM-specific values for sh_flags */ ++#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ ++#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined ++ in the input to a link step. */ ++ ++/* ARM-specific program header flags */ ++#define PF_ARM_SB 0x10000000 /* Segment contains the location ++ addressed by the static base. */ ++#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ ++#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ ++ ++/* Processor specific values for the Phdr p_type field. */ ++#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ ++ ++/* Processor specific values for the Shdr sh_type field. */ ++#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ ++#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ ++#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ ++ ++ ++/* ARM relocs. */ ++ ++#define R_ARM_NONE 0 /* No reloc */ ++#define R_ARM_PC24 1 /* PC relative 26 bit branch */ ++#define R_ARM_ABS32 2 /* Direct 32 bit */ ++#define R_ARM_REL32 3 /* PC relative 32 bit */ ++#define R_ARM_PC13 4 ++#define R_ARM_ABS16 5 /* Direct 16 bit */ ++#define R_ARM_ABS12 6 /* Direct 12 bit */ ++#define R_ARM_THM_ABS5 7 ++#define R_ARM_ABS8 8 /* Direct 8 bit */ ++#define R_ARM_SBREL32 9 ++#define R_ARM_THM_PC22 10 ++#define R_ARM_THM_PC8 11 ++#define R_ARM_AMP_VCALL9 12 ++#define R_ARM_SWI24 13 /* Obsolete static relocation. */ ++#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ ++#define R_ARM_THM_SWI8 14 ++#define R_ARM_XPC25 15 ++#define R_ARM_THM_XPC22 16 ++#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ ++#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ ++#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ ++#define R_ARM_COPY 20 /* Copy symbol at runtime */ ++#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ ++#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ ++#define R_ARM_RELATIVE 23 /* Adjust by program base */ ++#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ ++#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ ++#define R_ARM_GOT32 26 /* 32 bit GOT entry */ ++#define R_ARM_PLT32 27 /* 32 bit PLT address */ ++#define R_ARM_ALU_PCREL_7_0 32 ++#define R_ARM_ALU_PCREL_15_8 33 ++#define R_ARM_ALU_PCREL_23_15 34 ++#define R_ARM_LDR_SBREL_11_0 35 ++#define R_ARM_ALU_SBREL_19_12 36 ++#define R_ARM_ALU_SBREL_27_20 37 ++#define R_ARM_TLS_GOTDESC 90 ++#define R_ARM_TLS_CALL 91 ++#define R_ARM_TLS_DESCSEQ 92 ++#define R_ARM_THM_TLS_CALL 93 ++#define R_ARM_GNU_VTENTRY 100 ++#define R_ARM_GNU_VTINHERIT 101 ++#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ ++#define R_ARM_THM_PC9 103 /* thumb conditional branch */ ++#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic ++ thread local data */ ++#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic ++ thread local data */ ++#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS ++ block */ ++#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of ++ static TLS block offset */ ++#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static ++ TLS block */ ++#define R_ARM_THM_TLS_DESCSEQ 129 ++#define R_ARM_IRELATIVE 160 ++#define R_ARM_RXPC25 249 ++#define R_ARM_RSBREL32 250 ++#define R_ARM_THM_RPC22 251 ++#define R_ARM_RREL32 252 ++#define R_ARM_RABS22 253 ++#define R_ARM_RPC24 254 ++#define R_ARM_RBASE 255 ++/* Keep this the last entry. */ ++#define R_ARM_NUM 256 ++ ++/* IA-64 specific declarations. */ ++ ++/* Processor specific flags for the Ehdr e_flags field. */ ++#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ ++#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ ++#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ ++ ++/* Processor specific values for the Phdr p_type field. */ ++#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ ++#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ ++#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) ++#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) ++#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) ++ ++/* Processor specific flags for the Phdr p_flags field. */ ++#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Shdr sh_type field. */ ++#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ ++#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ ++ ++/* Processor specific flags for the Shdr sh_flags field. */ ++#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ ++#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Dyn d_tag field. */ ++#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) ++#define DT_IA_64_NUM 1 ++ ++/* IA-64 relocations. */ ++#define R_IA64_NONE 0x00 /* none */ ++#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ ++#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ ++#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ ++#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ ++#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ ++#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ ++#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ ++#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ ++#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ ++#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ ++#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ ++#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ ++#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ ++#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ ++#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ ++#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ ++#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ ++#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ ++#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ ++#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ ++#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ ++#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ ++#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ ++#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ ++#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ ++#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ ++#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ ++#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ ++#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ ++#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ ++#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ ++#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ ++#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ ++#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ ++#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ ++#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ ++#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ ++#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ ++#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ ++#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ ++#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ ++#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ ++#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ ++#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ ++#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ ++#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ ++#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ ++#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ ++#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ ++#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ ++#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ ++#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ ++#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ ++#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ ++#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ ++#define R_IA64_COPY 0x84 /* copy relocation */ ++#define R_IA64_SUB 0x85 /* Addend and symbol difference */ ++#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ ++#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ ++#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ ++#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ ++#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ ++#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ ++#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ ++#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ ++#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ ++#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ ++#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ ++#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ ++#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ ++#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ ++#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ ++#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ ++ ++/* SH specific declarations */ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++#define EF_SH_MACH_MASK 0x1f ++#define EF_SH_UNKNOWN 0x0 ++#define EF_SH1 0x1 ++#define EF_SH2 0x2 ++#define EF_SH3 0x3 ++#define EF_SH_DSP 0x4 ++#define EF_SH3_DSP 0x5 ++#define EF_SH4AL_DSP 0x6 ++#define EF_SH3E 0x8 ++#define EF_SH4 0x9 ++#define EF_SH2E 0xb ++#define EF_SH4A 0xc ++#define EF_SH2A 0xd ++#define EF_SH4_NOFPU 0x10 ++#define EF_SH4A_NOFPU 0x11 ++#define EF_SH4_NOMMU_NOFPU 0x12 ++#define EF_SH2A_NOFPU 0x13 ++#define EF_SH3_NOMMU 0x14 ++#define EF_SH2A_SH4_NOFPU 0x15 ++#define EF_SH2A_SH3_NOFPU 0x16 ++#define EF_SH2A_SH4 0x17 ++#define EF_SH2A_SH3E 0x18 ++ ++/* SH relocs. */ ++#define R_SH_NONE 0 ++#define R_SH_DIR32 1 ++#define R_SH_REL32 2 ++#define R_SH_DIR8WPN 3 ++#define R_SH_IND12W 4 ++#define R_SH_DIR8WPL 5 ++#define R_SH_DIR8WPZ 6 ++#define R_SH_DIR8BP 7 ++#define R_SH_DIR8W 8 ++#define R_SH_DIR8L 9 ++#define R_SH_SWITCH16 25 ++#define R_SH_SWITCH32 26 ++#define R_SH_USES 27 ++#define R_SH_COUNT 28 ++#define R_SH_ALIGN 29 ++#define R_SH_CODE 30 ++#define R_SH_DATA 31 ++#define R_SH_LABEL 32 ++#define R_SH_SWITCH8 33 ++#define R_SH_GNU_VTINHERIT 34 ++#define R_SH_GNU_VTENTRY 35 ++#define R_SH_TLS_GD_32 144 ++#define R_SH_TLS_LD_32 145 ++#define R_SH_TLS_LDO_32 146 ++#define R_SH_TLS_IE_32 147 ++#define R_SH_TLS_LE_32 148 ++#define R_SH_TLS_DTPMOD32 149 ++#define R_SH_TLS_DTPOFF32 150 ++#define R_SH_TLS_TPOFF32 151 ++#define R_SH_GOT32 160 ++#define R_SH_PLT32 161 ++#define R_SH_COPY 162 ++#define R_SH_GLOB_DAT 163 ++#define R_SH_JMP_SLOT 164 ++#define R_SH_RELATIVE 165 ++#define R_SH_GOTOFF 166 ++#define R_SH_GOTPC 167 ++/* Keep this the last entry. */ ++#define R_SH_NUM 256 ++ ++/* S/390 specific definitions. */ ++ ++/* Valid values for the e_flags field. */ ++ ++#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ ++ ++/* Additional s390 relocs */ ++ ++#define R_390_NONE 0 /* No reloc. */ ++#define R_390_8 1 /* Direct 8 bit. */ ++#define R_390_12 2 /* Direct 12 bit. */ ++#define R_390_16 3 /* Direct 16 bit. */ ++#define R_390_32 4 /* Direct 32 bit. */ ++#define R_390_PC32 5 /* PC relative 32 bit. */ ++#define R_390_GOT12 6 /* 12 bit GOT offset. */ ++#define R_390_GOT32 7 /* 32 bit GOT offset. */ ++#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ ++#define R_390_COPY 9 /* Copy symbol at runtime. */ ++#define R_390_GLOB_DAT 10 /* Create GOT entry. */ ++#define R_390_JMP_SLOT 11 /* Create PLT entry. */ ++#define R_390_RELATIVE 12 /* Adjust by program base. */ ++#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ ++#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ ++#define R_390_GOT16 15 /* 16 bit GOT offset. */ ++#define R_390_PC16 16 /* PC relative 16 bit. */ ++#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ ++#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ ++#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ ++#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ ++#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ ++#define R_390_64 22 /* Direct 64 bit. */ ++#define R_390_PC64 23 /* PC relative 64 bit. */ ++#define R_390_GOT64 24 /* 64 bit GOT offset. */ ++#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ ++#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ ++#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ ++#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ ++#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ ++#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ ++#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ ++#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ ++#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ ++#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ ++#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ ++#define R_390_TLS_GDCALL 38 /* Tag for function call in general ++ dynamic TLS code. */ ++#define R_390_TLS_LDCALL 39 /* Tag for function call in local ++ dynamic TLS code. */ ++#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ ++#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ ++#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS ++ block. */ ++#define R_390_20 57 /* Direct 20 bit. */ ++#define R_390_GOT20 58 /* 20 bit GOT offset. */ ++#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ ++#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ ++/* Keep this the last entry. */ ++#define R_390_NUM 62 ++ ++ ++/* CRIS relocations. */ ++#define R_CRIS_NONE 0 ++#define R_CRIS_8 1 ++#define R_CRIS_16 2 ++#define R_CRIS_32 3 ++#define R_CRIS_8_PCREL 4 ++#define R_CRIS_16_PCREL 5 ++#define R_CRIS_32_PCREL 6 ++#define R_CRIS_GNU_VTINHERIT 7 ++#define R_CRIS_GNU_VTENTRY 8 ++#define R_CRIS_COPY 9 ++#define R_CRIS_GLOB_DAT 10 ++#define R_CRIS_JUMP_SLOT 11 ++#define R_CRIS_RELATIVE 12 ++#define R_CRIS_16_GOT 13 ++#define R_CRIS_32_GOT 14 ++#define R_CRIS_16_GOTPLT 15 ++#define R_CRIS_32_GOTPLT 16 ++#define R_CRIS_32_GOTREL 17 ++#define R_CRIS_32_PLT_GOTREL 18 ++#define R_CRIS_32_PLT_PCREL 19 ++ ++#define R_CRIS_NUM 20 ++ ++ ++/* AMD x86-64 relocations. */ ++#define R_X86_64_NONE 0 /* No reloc */ ++#define R_X86_64_64 1 /* Direct 64 bit */ ++#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ ++#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ ++#define R_X86_64_PLT32 4 /* 32 bit PLT address */ ++#define R_X86_64_COPY 5 /* Copy symbol at runtime */ ++#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ ++#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ ++#define R_X86_64_RELATIVE 8 /* Adjust by program base */ ++#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative ++ offset to GOT */ ++#define R_X86_64_32 10 /* Direct 32 bit zero extended */ ++#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ ++#define R_X86_64_16 12 /* Direct 16 bit zero extended */ ++#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ ++#define R_X86_64_8 14 /* Direct 8 bit sign extended */ ++#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ ++#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ ++#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ ++#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ ++#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset ++ to two GOT entries for GD symbol */ ++#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset ++ to two GOT entries for LD symbol */ ++#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ ++#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset ++ to GOT entry for IE symbol */ ++#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ ++#define R_X86_64_PC64 24 /* PC relative 64 bit */ ++#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ ++#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative ++ offset to GOT */ ++#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ ++#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset ++ to GOT entry */ ++#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ ++#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ ++#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset ++ to PLT entry */ ++#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ ++#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ ++#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ ++#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS ++ descriptor. */ ++#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ ++#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ ++#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ ++ ++#define R_X86_64_NUM 39 ++ ++ ++/* AM33 relocations. */ ++#define R_MN10300_NONE 0 /* No reloc. */ ++#define R_MN10300_32 1 /* Direct 32 bit. */ ++#define R_MN10300_16 2 /* Direct 16 bit. */ ++#define R_MN10300_8 3 /* Direct 8 bit. */ ++#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ ++#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ ++#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ ++#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ ++#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ ++#define R_MN10300_24 9 /* Direct 24 bit. */ ++#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ ++#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ ++#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ ++#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ ++#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ ++#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ ++#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ ++#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ ++#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ ++#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ ++#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ ++#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ ++#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ ++#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ ++ ++#define R_MN10300_NUM 24 ++ ++ ++/* M32R relocs. */ ++#define R_M32R_NONE 0 /* No reloc. */ ++#define R_M32R_16 1 /* Direct 16 bit. */ ++#define R_M32R_32 2 /* Direct 32 bit. */ ++#define R_M32R_24 3 /* Direct 24 bit. */ ++#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ ++#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ ++#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ ++#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ ++#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ ++#define R_M32R_LO16 9 /* Low 16 bit. */ ++#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ ++#define R_M32R_GNU_VTINHERIT 11 ++#define R_M32R_GNU_VTENTRY 12 ++/* M32R relocs use SHT_RELA. */ ++#define R_M32R_16_RELA 33 /* Direct 16 bit. */ ++#define R_M32R_32_RELA 34 /* Direct 32 bit. */ ++#define R_M32R_24_RELA 35 /* Direct 24 bit. */ ++#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ ++#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ ++#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ ++#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ ++#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ ++#define R_M32R_LO16_RELA 41 /* Low 16 bit */ ++#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ ++#define R_M32R_RELA_GNU_VTINHERIT 43 ++#define R_M32R_RELA_GNU_VTENTRY 44 ++#define R_M32R_REL32 45 /* PC relative 32 bit. */ ++ ++#define R_M32R_GOT24 48 /* 24 bit GOT entry */ ++#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ ++#define R_M32R_COPY 50 /* Copy symbol at runtime */ ++#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ ++#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ ++#define R_M32R_RELATIVE 53 /* Adjust by program base */ ++#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ ++#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ ++#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned ++ low */ ++#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed ++ low */ ++#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ ++#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to ++ GOT with unsigned low */ ++#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to ++ GOT with signed low */ ++#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to ++ GOT */ ++#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT ++ with unsigned low */ ++#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT ++ with signed low */ ++#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ ++#define R_M32R_NUM 256 /* Keep this the last entry. */ ++ ++ ++/* TILEPro relocations. */ ++#define R_TILEPRO_NONE 0 /* No reloc */ ++#define R_TILEPRO_32 1 /* Direct 32 bit */ ++#define R_TILEPRO_16 2 /* Direct 16 bit */ ++#define R_TILEPRO_8 3 /* Direct 8 bit */ ++#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ ++#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ ++#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ ++#define R_TILEPRO_LO16 7 /* Low 16 bit */ ++#define R_TILEPRO_HI16 8 /* High 16 bit */ ++#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ ++#define R_TILEPRO_COPY 10 /* Copy relocation */ ++#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ ++#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ ++#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ ++#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ ++#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ ++#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ ++#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ ++#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ ++#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ ++#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ ++#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ ++#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ ++#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ ++#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ ++#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ ++#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ ++#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ ++#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ ++#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ ++#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ ++#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ ++#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ ++#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ ++#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ ++#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ ++#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ ++#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ ++#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ ++#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ ++#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ ++#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ ++#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ ++#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ ++#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ ++#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ ++#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ ++#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ ++#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ ++/* Relocs 56-59 are currently not defined. */ ++#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ ++#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ ++#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ ++#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ ++#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ ++#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ ++#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ ++#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ ++ ++#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ ++#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ ++ ++#define R_TILEPRO_NUM 130 ++ ++ ++/* TILE-Gx relocations. */ ++#define R_TILEGX_NONE 0 /* No reloc */ ++#define R_TILEGX_64 1 /* Direct 64 bit */ ++#define R_TILEGX_32 2 /* Direct 32 bit */ ++#define R_TILEGX_16 3 /* Direct 16 bit */ ++#define R_TILEGX_8 4 /* Direct 8 bit */ ++#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ ++#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ ++#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ ++#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ ++#define R_TILEGX_HW0 9 /* hword 0 16-bit */ ++#define R_TILEGX_HW1 10 /* hword 1 16-bit */ ++#define R_TILEGX_HW2 11 /* hword 2 16-bit */ ++#define R_TILEGX_HW3 12 /* hword 3 16-bit */ ++#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ ++#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ ++#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ ++#define R_TILEGX_COPY 16 /* Copy relocation */ ++#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ ++#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ ++#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ ++#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ ++#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ ++#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ ++#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ ++#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ ++#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ ++#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ ++#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ ++#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ ++#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ ++#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ ++#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ ++#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ ++#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ ++#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ ++#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ ++#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ ++#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ ++#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ ++#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ ++#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ ++#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ ++#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ ++#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ ++/* Relocs 66-71 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ ++/* Relocs 76-77 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ ++/* Relocs 90-91 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ ++/* Relocs 94-99 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ ++/* Relocs 104-105 are currently not defined. */ ++#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ ++#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ ++#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ ++#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ ++#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ ++#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ ++#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ ++#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ ++#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ ++#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ ++ ++#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ ++#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ ++ ++#define R_TILEGX_NUM 130 ++ ++#endif /* elf.h */ +--- a/scripts/mod/mk_elfconfig.c ++++ b/scripts/mod/mk_elfconfig.c +@@ -2,7 +2,11 @@ + #include + #include + #include ++#ifndef __APPLE__ + #include ++#else ++#include "elf.h" ++#endif + + int + main(int argc, char **argv) +--- a/scripts/mod/modpost.h ++++ b/scripts/mod/modpost.h +@@ -9,7 +9,11 @@ + #include + #include + #include ++#if !(defined(__APPLE__) || defined(__CYGWIN__)) + #include ++#else ++#include "elf.h" ++#endif + + #include "list.h" + #include "elfconfig.h" diff --git a/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch new file mode 100644 index 0000000000..50a6227148 --- /dev/null +++ b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch @@ -0,0 +1,22 @@ +From e44fc2af1ddc452b6659d08c16973d65c73b7d0a Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Wed, 5 Feb 2020 18:36:43 +0000 +Subject: [PATCH] file2alias: build on macos + +Signed-off-by: Kevin Darbyshire-Bryant +--- + scripts/mod/file2alias.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -38,6 +38,9 @@ typedef struct { + __u8 b[16]; + } guid_t; + ++#ifdef __APPLE__ ++#define uuid_t compat_uuid_t ++#endif + /* backwards compatibility, don't use in new code */ + typedef struct { + __u8 b[16]; diff --git a/target/linux/generic/hack-6.6/212-tools_portability.patch b/target/linux/generic/hack-6.6/212-tools_portability.patch new file mode 100644 index 0000000000..add281991e --- /dev/null +++ b/target/linux/generic/hack-6.6/212-tools_portability.patch @@ -0,0 +1,342 @@ +From 48232d3d931c95953ce2ddfe7da7bb164aef6a73 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:03:16 +0200 +Subject: fix portability of some includes files in tools/ used on the host + +Signed-off-by: Felix Fietkau +--- + tools/include/tools/be_byteshift.h | 4 ++++ + tools/include/tools/le_byteshift.h | 4 ++++ + tools/include/tools/linux_types.h | 22 ++++++++++++++++++++++ + 3 files changed, 30 insertions(+) + create mode 100644 tools/include/tools/linux_types.h + +--- a/tools/include/tools/be_byteshift.h ++++ b/tools/include/tools/be_byteshift.h +@@ -2,6 +2,10 @@ + #ifndef _TOOLS_BE_BYTESHIFT_H + #define _TOOLS_BE_BYTESHIFT_H + ++#ifndef __linux__ ++#include "linux_types.h" ++#endif ++ + #include + + static inline uint16_t __get_unaligned_be16(const uint8_t *p) +--- a/tools/include/tools/le_byteshift.h ++++ b/tools/include/tools/le_byteshift.h +@@ -2,6 +2,10 @@ + #ifndef _TOOLS_LE_BYTESHIFT_H + #define _TOOLS_LE_BYTESHIFT_H + ++#ifndef __linux__ ++#include "linux_types.h" ++#endif ++ + #include + + static inline uint16_t __get_unaligned_le16(const uint8_t *p) +--- /dev/null ++++ b/tools/include/tools/linux_types.h +@@ -0,0 +1,18 @@ ++#ifndef __LINUX_TYPES_H ++#define __LINUX_TYPES_H ++ ++#include ++ ++typedef int8_t __s8; ++typedef uint8_t __u8; ++ ++typedef int16_t __s16; ++typedef uint16_t __u16; ++ ++typedef int32_t __s32; ++typedef uint32_t __u32; ++ ++typedef int64_t __s64; ++typedef uint64_t __u64; ++ ++#endif +--- a/tools/include/linux/types.h ++++ b/tools/include/linux/types.h +@@ -10,8 +10,12 @@ + #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ + #endif + ++#ifndef __linux__ ++#include ++#else + #include + #include ++#endif + + struct page; + struct kmem_cache; +@@ -51,7 +55,9 @@ typedef __s8 s8; + #define __force + #define __user + #define __must_check ++#ifndef __cold + #define __cold ++#endif + + typedef __u16 __bitwise __le16; + typedef __u16 __bitwise __be16; +--- a/tools/perf/pmu-events/jevents.py ++++ b/tools/perf/pmu-events/jevents.py +@@ -684,6 +684,7 @@ def main() -> None: + #include "util/header.h" + #include "util/pmu.h" + #include ++#include + #include + + struct compact_pmu_event { +--- a/tools/arch/x86/include/asm/insn.h ++++ b/tools/arch/x86/include/asm/insn.h +@@ -7,8 +7,8 @@ + * Copyright (C) IBM Corporation, 2009 + */ + +-#include + /* insn_attr_t is defined in inat.h */ ++#include + #include "inat.h" /* __ignore_sync_check__ */ + + #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN) +--- a/tools/arch/x86/include/asm/orc_types.h ++++ b/tools/arch/x86/include/asm/orc_types.h +@@ -40,7 +40,6 @@ + #define ORC_REG_MAX 15 + + #ifndef __ASSEMBLY__ +-#include + + /* + * This struct is more or less a vastly simplified version of the DWARF Call +@@ -53,12 +52,12 @@ + struct orc_entry { + s16 sp_offset; + s16 bp_offset; +-#if defined(__LITTLE_ENDIAN_BITFIELD) ++#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned sp_reg:4; + unsigned bp_reg:4; + unsigned type:2; + unsigned end:1; +-#elif defined(__BIG_ENDIAN_BITFIELD) ++#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned bp_reg:4; + unsigned sp_reg:4; + unsigned unused:5; +--- a/tools/arch/x86/lib/insn.c ++++ b/tools/arch/x86/lib/insn.c +@@ -15,7 +15,11 @@ + #include "../include/asm/insn.h" /* __ignore_sync_check__ */ + #include "../include/asm-generic/unaligned.h" /* __ignore_sync_check__ */ + ++#ifdef __KERNEL__ + #include ++#else ++#include ++#endif + #include + + #include "../include/asm/emulate_prefix.h" /* __ignore_sync_check__ */ +--- a/tools/include/asm-generic/bitops/fls.h ++++ b/tools/include/asm-generic/bitops/fls.h +@@ -2,6 +2,8 @@ + #ifndef _ASM_GENERIC_BITOPS_FLS_H_ + #define _ASM_GENERIC_BITOPS_FLS_H_ + ++#include ++ + /** + * fls - find last (most-significant) bit set + * @x: the word to search +@@ -10,7 +12,7 @@ + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ + +-static __always_inline int fls(unsigned int x) ++static __always_inline int __generic_fls(unsigned int x) + { + int r = 32; + +@@ -38,5 +40,6 @@ static __always_inline int fls(unsigned + } + return r; + } ++#define fls __generic_fls + + #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */ +--- a/tools/include/asm-generic/bitsperlong.h ++++ b/tools/include/asm-generic/bitsperlong.h +@@ -4,11 +4,13 @@ + + #include + ++#ifndef BITS_PER_LONG + #ifdef __SIZEOF_LONG__ + #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) + #else + #define BITS_PER_LONG __WORDSIZE + #endif ++#endif + + #if BITS_PER_LONG != __BITS_PER_LONG + #error Inconsistent word size. Check asm/bitsperlong.h +--- a/tools/include/linux/rbtree.h ++++ b/tools/include/linux/rbtree.h +@@ -18,7 +18,6 @@ + #define __TOOLS_LINUX_PERF_RBTREE_H + + #include +-#include + + struct rb_node { + unsigned long __rb_parent_color; +--- a/tools/objtool/Makefile ++++ b/tools/objtool/Makefile +@@ -4,7 +4,7 @@ include ../scripts/Makefile.arch + + # always use the host compiler + AR = $(HOSTAR) +-CC = $(HOSTCC) ++CC = $(HOSTCC) $(HOST_EXTRACFLAGS) + LD = $(HOSTLD) + + ifeq ($(srctree),) +@@ -43,6 +43,7 @@ BUILD_ORC := n + + ifeq ($(SRCARCH),x86) + BUILD_ORC := y ++ CFLAGS += -DBUILD_ORC + endif + + export BUILD_ORC +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1164,11 +1164,12 @@ static int add_ignore_alternatives(struc + return 0; + } + ++#ifndef BUILD_ORC + /* + * Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol + * will be added to the .retpoline_sites section. + */ +-__weak bool arch_is_retpoline(struct symbol *sym) ++bool arch_is_retpoline(struct symbol *sym) + { + return false; + } +@@ -1177,7 +1178,7 @@ __weak bool arch_is_retpoline(struct sym + * Symbols that replace INSN_RETURN, every (tail) call to such a symbol + * will be added to the .return_sites section. + */ +-__weak bool arch_is_rethunk(struct symbol *sym) ++bool arch_is_rethunk(struct symbol *sym) + { + return false; + } +@@ -1186,10 +1187,11 @@ __weak bool arch_is_rethunk(struct symbo + * Symbols that are embedded inside other instructions, because sometimes crazy + * code exists. These are mostly ignored for validation purposes. + */ +-__weak bool arch_is_embedded_insn(struct symbol *sym) ++bool arch_is_embedded_insn(struct symbol *sym) + { + return false; + } ++#endif + + #define NEGATIVE_RELOC ((void *)-1L) + +--- a/tools/objtool/include/objtool/objtool.h ++++ b/tools/objtool/include/objtool/objtool.h +@@ -12,7 +12,9 @@ + + #include + ++#ifndef __weak + #define __weak __attribute__((weak)) ++#endif + + struct pv_state { + bool clean; +--- a/tools/objtool/orc_dump.c ++++ b/tools/objtool/orc_dump.c +@@ -5,10 +5,10 @@ + + #include + #include +-#include + #include + #include + #include ++#include + + static const char *reg_name(unsigned int reg) + { +--- a/tools/objtool/orc_gen.c ++++ b/tools/objtool/orc_gen.c +@@ -7,11 +7,11 @@ + #include + + #include +-#include + + #include + #include + #include ++#include + + static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, + struct instruction *insn) +--- a/tools/objtool/special.c ++++ b/tools/objtool/special.c +@@ -54,9 +54,11 @@ struct special_entry entries[] = { + {}, + }; + +-void __weak arch_handle_alternative(unsigned short feature, struct special_alt *alt) ++#ifndef BUILD_ORC ++void arch_handle_alternative(unsigned short feature, struct special_alt *alt) + { + } ++#endif + + static void reloc_to_sec_off(struct reloc *reloc, struct section **sec, + unsigned long *off) +--- a/tools/objtool/weak.c ++++ b/tools/objtool/weak.c +@@ -15,12 +15,14 @@ + return ENOSYS; \ + }) + +-int __weak orc_dump(const char *_objname) ++#ifndef BUILD_ORC ++int orc_dump(const char *_objname) + { + UNSUPPORTED("ORC"); + } + +-int __weak orc_create(struct objtool_file *file) ++int orc_create(struct objtool_file *file) + { + UNSUPPORTED("ORC"); + } ++#endif +--- a/tools/scripts/Makefile.include ++++ b/tools/scripts/Makefile.include +@@ -92,7 +92,7 @@ LLVM_OBJCOPY ?= llvm-objcopy + LLVM_STRIP ?= llvm-strip + + ifeq ($(CC_NO_CLANG), 1) +-EXTRA_WARNINGS += -Wstrict-aliasing=3 ++# EXTRA_WARNINGS += -Wstrict-aliasing=3 + + else ifneq ($(CROSS_COMPILE),) + # Allow userspace to override CLANG_CROSS_FLAGS to specify their own diff --git a/target/linux/generic/hack-6.6/214-spidev_h_portability.patch b/target/linux/generic/hack-6.6/214-spidev_h_portability.patch new file mode 100644 index 0000000000..db754a2903 --- /dev/null +++ b/target/linux/generic/hack-6.6/214-spidev_h_portability.patch @@ -0,0 +1,24 @@ +From be9be95ff10e16a5b4ad36f903978d0cc5747024 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:04:08 +0200 +Subject: kernel: fix linux/spi/spidev.h portability issues with musl + +Felix will try to get this define included into musl + +lede-commit: 795e7cf60de19e7a076a46874fab7bb88b43bbff +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/spi/spidev.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/uapi/linux/spi/spidev.h ++++ b/include/uapi/linux/spi/spidev.h +@@ -93,7 +93,7 @@ struct spi_ioc_transfer { + + /* not all platforms use or _IOC_TYPECHECK() ... */ + #define SPI_MSGSIZE(N) \ +- ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ++ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << 13)) \ + ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0) + #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) + diff --git a/target/linux/generic/hack-6.6/220-arm-gc_sections.patch b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch new file mode 100644 index 0000000000..a6a6c7cf2c --- /dev/null +++ b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch @@ -0,0 +1,123 @@ +From e3d8676f5722b7622685581e06e8f53e6138e3ab Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 15 Jul 2017 23:42:36 +0200 +Subject: use -ffunction-sections, -fdata-sections and --gc-sections + +In combination with kernel symbol export stripping this significantly reduces +the kernel image size. Used on both ARM and MIPS architectures. + +Signed-off-by: Felix Fietkau +Signed-off-by: Jonas Gorski +Signed-off-by: Gabor Juhos +--- +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -124,6 +124,7 @@ config ARM + select HAVE_VIRT_CPU_ACCOUNTING_GEN + select IRQ_FORCED_THREADING + select LOCK_MM_AND_FIND_VMA ++ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION + select MODULES_USE_ELF_REL + select NEED_DMA_MAP_STATE + select OF_EARLY_FLATTREE if OF +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -91,6 +91,7 @@ endif + ifeq ($(CONFIG_USE_OF),y) + OBJS += $(libfdt_objs) fdt_check_mem_start.o + endif ++KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL)) + + OBJS += lib1funcs.o ashldi3.o bswapsdi2.o + +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -75,7 +75,7 @@ SECTIONS + . = ALIGN(4); + __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { + __start___ex_table = .; +- ARM_MMU_KEEP(*(__ex_table)) ++ KEEP(*(__ex_table)) + __stop___ex_table = .; + } + +@@ -100,24 +100,24 @@ SECTIONS + } + .init.arch.info : { + __arch_info_begin = .; +- *(.arch.info.init) ++ KEEP(*(.arch.info.init)) + __arch_info_end = .; + } + .init.tagtable : { + __tagtable_begin = .; +- *(.taglist.init) ++ KEEP(*(.taglist.init)) + __tagtable_end = .; + } + #ifdef CONFIG_SMP_ON_UP + .init.smpalt : { + __smpalt_begin = .; +- *(.alt.smp.init) ++ KEEP(*(.alt.smp.init)) + __smpalt_end = .; + } + #endif + .init.pv_table : { + __pv_table_begin = .; +- *(.pv_table) ++ KEEP(*(.pv_table)) + __pv_table_end = .; + } + +--- a/arch/arm/include/asm/vmlinux.lds.h ++++ b/arch/arm/include/asm/vmlinux.lds.h +@@ -42,13 +42,13 @@ + #define PROC_INFO \ + . = ALIGN(4); \ + __proc_info_begin = .; \ +- *(.proc.info.init) \ ++ KEEP(*(.proc.info.init)) \ + __proc_info_end = .; + + #define IDMAP_TEXT \ + ALIGN_FUNCTION(); \ + __idmap_text_start = .; \ +- *(.idmap.text) \ ++ KEEP(*(.idmap.text)) \ + __idmap_text_end = .; \ + + #define ARM_DISCARD \ +@@ -109,12 +109,12 @@ + . = ALIGN(8); \ + .ARM.unwind_idx : { \ + __start_unwind_idx = .; \ +- *(.ARM.exidx*) \ ++ KEEP(*(.ARM.exidx*)) \ + __stop_unwind_idx = .; \ + } \ + .ARM.unwind_tab : { \ + __start_unwind_tab = .; \ +- *(.ARM.extab*) \ ++ KEEP(*(.ARM.extab*)) \ + __stop_unwind_tab = .; \ + } + +@@ -126,7 +126,7 @@ + __vectors_lma = .; \ + OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \ + .vectors { \ +- *(.vectors) \ ++ KEEP(*(.vectors)) \ + } \ + .vectors.bhb.loop8 { \ + *(.vectors.bhb.loop8) \ +@@ -144,7 +144,7 @@ + \ + __stubs_lma = .; \ + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) { \ +- *(.stubs) \ ++ KEEP(*(.stubs)) \ + } \ + ARM_LMA(__stubs, .stubs); \ + . = __stubs_lma + SIZEOF(.stubs); \ diff --git a/target/linux/generic/hack-6.6/221-module_exports.patch b/target/linux/generic/hack-6.6/221-module_exports.patch new file mode 100644 index 0000000000..967510bcb6 --- /dev/null +++ b/target/linux/generic/hack-6.6/221-module_exports.patch @@ -0,0 +1,126 @@ +From b14784e7883390c20ed3ff904892255404a5914b Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:05:53 +0200 +Subject: add an optional config option for stripping all unnecessary symbol exports from the kernel image + +lede-commit: bb5a40c64b7c4f4848509fa0a6625055fc9e66cc +Signed-off-by: Felix Fietkau +--- + include/asm-generic/vmlinux.lds.h | 18 +++++++++++++++--- + include/linux/export.h | 9 ++++++++- + scripts/Makefile.build | 2 +- + 3 files changed, 24 insertions(+), 5 deletions(-) + +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -81,6 +81,16 @@ + #define RO_EXCEPTION_TABLE + #endif + ++#ifndef SYMTAB_KEEP ++#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*))) ++#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*))) ++#endif ++ ++#ifndef SYMTAB_DISCARD ++#define SYMTAB_DISCARD ++#define SYMTAB_DISCARD_GPL ++#endif ++ + /* Align . to a 8 byte boundary equals to maximum function alignment. */ + #define ALIGN_FUNCTION() . = ALIGN(8) + +@@ -511,14 +521,14 @@ + /* Kernel symbol table: Normal symbols */ \ + __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ + __start___ksymtab = .; \ +- KEEP(*(SORT(___ksymtab+*))) \ ++ SYMTAB_KEEP \ + __stop___ksymtab = .; \ + } \ + \ + /* Kernel symbol table: GPL-only symbols */ \ + __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ + __start___ksymtab_gpl = .; \ +- KEEP(*(SORT(___ksymtab_gpl+*))) \ ++ SYMTAB_KEEP_GPL \ + __stop___ksymtab_gpl = .; \ + } \ + \ +@@ -538,7 +548,7 @@ + \ + /* Kernel symbol table: strings */ \ + __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ +- *(__ksymtab_strings) \ ++ *(__ksymtab_strings+*) \ + } \ + \ + /* __*init sections */ \ +@@ -1042,6 +1052,8 @@ + #define COMMON_DISCARDS \ + SANITIZER_DISCARDS \ + PATCHABLE_DISCARDS \ ++ SYMTAB_DISCARD \ ++ SYMTAB_DISCARD_GPL \ + *(.discard) \ + *(.discard.*) \ + *(.modinfo) \ +--- a/include/linux/export.h ++++ b/include/linux/export.h +@@ -72,6 +72,12 @@ struct kernel_symbol { + + #else + ++#ifdef MODULE ++#define __EXPORT_SUFFIX(sym) ++#else ++#define __EXPORT_SUFFIX(sym) "+" #sym ++#endif ++ + /* + * For every exported symbol, do the following: + * +@@ -87,7 +93,7 @@ struct kernel_symbol { + extern typeof(sym) sym; \ + extern const char __kstrtab_##sym[]; \ + extern const char __kstrtabns_##sym[]; \ +- asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ ++ asm(" .section \"__ksymtab_strings" __EXPORT_SUFFIX(sym) "\",\"aMS\",%progbits,1 \n" \ + "__kstrtab_" #sym ": \n" \ + " .asciz \"" #sym "\" \n" \ + "__kstrtabns_" #sym ": \n" \ +--- a/include/asm-generic/export.h ++++ b/include/asm-generic/export.h +@@ -31,6 +31,12 @@ + #endif + .endm + ++#ifdef MODULE ++#define __EXPORT_SUFFIX(name) ++#else ++#define __EXPORT_SUFFIX(name) + #name ++#endif ++ + /* + * note on .section use: we specify progbits since usage of the "M" (SHF_MERGE) + * section flag requires it. Use '%progbits' instead of '@progbits' since the +@@ -44,7 +50,7 @@ + __ksymtab_\name: + __put \val, __kstrtab_\name + .previous +- .section __ksymtab_strings,"aMS",%progbits,1 ++ .section __ksymtab_strings __EXPORT_SUFFIX(name),"aMS",%progbits,1 + __kstrtab_\name: + .asciz "\name" + .previous +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -388,7 +388,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa + # Linker scripts preprocessor (.lds.S -> .lds) + # --------------------------------------------------------------------------- + quiet_cmd_cpp_lds_S = LDS $@ +- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \ ++ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -U$(ARCH) \ + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< + + $(obj)/%.lds: $(src)/%.lds.S FORCE diff --git a/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch new file mode 100644 index 0000000000..55530c5c7e --- /dev/null +++ b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch @@ -0,0 +1,38 @@ +From b3d00b452467f621317953d9e4c6f9ae8dcfd271 Mon Sep 17 00:00:00 2001 +From: Imre Kaloz +Date: Fri, 7 Jul 2017 17:06:55 +0200 +Subject: use the openwrt lzma options for now + +lede-commit: 548de949f392049420a6a1feeef118b30ab8ea8c +Signed-off-by: Imre Kaloz +--- + lib/decompress.c | 1 + + scripts/Makefile.lib | 2 +- + usr/gen_initramfs_list.sh | 10 +++++----- + 3 files changed, 7 insertions(+), 6 deletions(-) + +--- a/lib/decompress.c ++++ b/lib/decompress.c +@@ -53,6 +53,7 @@ static const struct compress_format comp + { {0x1f, 0x9e}, "gzip", gunzip }, + { {0x42, 0x5a}, "bzip2", bunzip2 }, + { {0x5d, 0x00}, "lzma", unlzma }, ++ { {0x6d, 0x00}, "lzma-openwrt", unlzma }, + { {0xfd, 0x37}, "xz", unxz }, + { {0x89, 0x4c}, "lzo", unlzo }, + { {0x02, 0x21}, "lz4", unlz4 }, +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -443,10 +443,10 @@ quiet_cmd_bzip2_with_size = BZIP2 $@ + # --------------------------------------------------------------------------- + + quiet_cmd_lzma = LZMA $@ +- cmd_lzma = cat $(real-prereqs) | $(LZMA) -9 > $@ ++ cmd_lzma = cat $(real-prereqs) | $(LZMA) e -d20 -lc1 -lp2 -pb2 -eos -si -so > $@ + + quiet_cmd_lzma_with_size = LZMA $@ +- cmd_lzma_with_size = { cat $(real-prereqs) | $(LZMA) -9; $(size_append); } > $@ ++ cmd_lzma_with_size = { cat $(real-prereqs) | $(LZMA) e -d20 -lc1 -lp2 -pb2 -eos -si -so; $(size_append); } > $@ + + quiet_cmd_lzo = LZO $@ + cmd_lzo = cat $(real-prereqs) | $(KLZOP) -9 > $@ diff --git a/target/linux/generic/hack-6.6/250-netfilter_depends.patch b/target/linux/generic/hack-6.6/250-netfilter_depends.patch new file mode 100644 index 0000000000..fbb5a61157 --- /dev/null +++ b/target/linux/generic/hack-6.6/250-netfilter_depends.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Subject: hack: net: remove bogus netfilter dependencies + +lede-commit: 589d2a377dee27d206fc3725325309cf649e4df6 +Signed-off-by: Felix Fietkau +--- + net/netfilter/Kconfig | 2 -- + 1 file changed, 2 deletions(-) + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -253,7 +253,6 @@ config NF_CONNTRACK_FTP + + config NF_CONNTRACK_H323 + tristate "H.323 protocol support" +- depends on IPV6 || IPV6=n + depends on NETFILTER_ADVANCED + help + H.323 is a VoIP signalling protocol from ITU-T. As one of the most +@@ -1118,7 +1117,6 @@ config NETFILTER_XT_TARGET_SECMARK + + config NETFILTER_XT_TARGET_TCPMSS + tristate '"TCPMSS" target support' +- depends on IPV6 || IPV6=n + default m if NETFILTER_ADVANCED=n + help + This option adds a `TCPMSS' target, which allows you to alter the diff --git a/target/linux/generic/hack-6.6/251-kconfig.patch b/target/linux/generic/hack-6.6/251-kconfig.patch new file mode 100644 index 0000000000..fcf4eaf6e8 --- /dev/null +++ b/target/linux/generic/hack-6.6/251-kconfig.patch @@ -0,0 +1,157 @@ +From da3c50704f14132f4adf80d48e9a4cd5d46e54c9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 7 Jul 2017 17:09:21 +0200 +Subject: kconfig: owrt specifc dependencies + +Signed-off-by: John Crispin +--- + crypto/Kconfig | 10 +++++----- + drivers/bcma/Kconfig | 1 + + drivers/ssb/Kconfig | 3 ++- + lib/Kconfig | 8 ++++---- + net/netfilter/Kconfig | 2 +- + net/wireless/Kconfig | 17 ++++++++++------- + sound/core/Kconfig | 4 ++-- + 7 files changed, 25 insertions(+), 20 deletions(-) + +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -55,7 +55,7 @@ config CRYPTO_FIPS_VERSION + By default the KERNELRELEASE value is used. + + config CRYPTO_ALGAPI +- tristate ++ tristate "ALGAPI" + select CRYPTO_ALGAPI2 + help + This option provides the API for cryptographic algorithms. +@@ -64,7 +64,7 @@ config CRYPTO_ALGAPI2 + tristate + + config CRYPTO_AEAD +- tristate ++ tristate "AEAD" + select CRYPTO_AEAD2 + select CRYPTO_ALGAPI + +@@ -75,7 +75,7 @@ config CRYPTO_AEAD2 + select CRYPTO_RNG2 + + config CRYPTO_SKCIPHER +- tristate ++ tristate "SKCIPHER" + select CRYPTO_SKCIPHER2 + select CRYPTO_ALGAPI + +@@ -85,7 +85,7 @@ config CRYPTO_SKCIPHER2 + select CRYPTO_RNG2 + + config CRYPTO_HASH +- tristate ++ tristate "HASH" + select CRYPTO_HASH2 + select CRYPTO_ALGAPI + +@@ -94,7 +94,7 @@ config CRYPTO_HASH2 + select CRYPTO_ALGAPI2 + + config CRYPTO_RNG +- tristate ++ tristate "RNG" + select CRYPTO_RNG2 + select CRYPTO_ALGAPI + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -16,6 +16,7 @@ if BCMA + # Support for Block-I/O. SELECT this from the driver that needs it. + config BCMA_BLOCKIO + bool ++ default y + + config BCMA_HOST_PCI_POSSIBLE + bool +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -29,6 +29,7 @@ config SSB_SPROM + config SSB_BLOCKIO + bool + depends on SSB ++ default y + + config SSB_PCIHOST_POSSIBLE + bool +@@ -49,7 +50,7 @@ config SSB_PCIHOST + config SSB_B43_PCI_BRIDGE + bool + depends on SSB_PCIHOST +- default n ++ default y + + config SSB_PCMCIAHOST_POSSIBLE + bool +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -457,16 +457,16 @@ config BCH_CONST_T + # Textsearch support is select'ed if needed + # + config TEXTSEARCH +- bool ++ bool "Textsearch support" + + config TEXTSEARCH_KMP +- tristate ++ tristate "Textsearch KMP" + + config TEXTSEARCH_BM +- tristate ++ tristate "Textsearch BM" + + config TEXTSEARCH_FSM +- tristate ++ tristate "Textsearch FSM" + + config BTREE + bool +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -22,7 +22,7 @@ config NETFILTER_SKIP_EGRESS + def_bool NETFILTER_EGRESS && (NET_CLS_ACT || IFB) + + config NETFILTER_NETLINK +- tristate ++ tristate "Netfilter NFNETLINK interface" + + config NETFILTER_FAMILY_BRIDGE + bool +--- a/sound/core/Kconfig ++++ b/sound/core/Kconfig +@@ -17,7 +17,7 @@ config SND_DMAENGINE_PCM + tristate + + config SND_HWDEP +- tristate ++ tristate "Sound hardware support" + + config SND_SEQ_DEVICE + tristate +@@ -27,7 +27,7 @@ config SND_RAWMIDI + select SND_SEQ_DEVICE if SND_SEQUENCER != n + + config SND_COMPRESS_OFFLOAD +- tristate ++ tristate "Compression offloading support" + + config SND_JACK + bool +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -430,7 +430,7 @@ config NET_DEVLINK + default n + + config PAGE_POOL +- bool ++ bool "Page pool support" + + config PAGE_POOL_STATS + default n diff --git a/target/linux/generic/hack-6.6/253-ksmbd-config.patch b/target/linux/generic/hack-6.6/253-ksmbd-config.patch new file mode 100644 index 0000000000..a57c914180 --- /dev/null +++ b/target/linux/generic/hack-6.6/253-ksmbd-config.patch @@ -0,0 +1,32 @@ +From dcd966fa7ca63f38cf7147e1184d13d66e2ca340 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:33:30 +0200 +Subject: [PATCH] Kconfig: add tristate for OID and ASNI string + +--- + init/Kconfig | 2 +- + lib/Kconfig | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -2013,7 +2013,7 @@ config PADATA + bool + + config ASN1 +- tristate ++ tristate "ASN1" + help + Build a simple ASN.1 grammar compiler that produces a bytecode output + that can be interpreted by the ASN.1 stream decoder and used to +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -637,7 +637,7 @@ config LIBFDT + bool + + config OID_REGISTRY +- tristate ++ tristate "OID" + help + Enable fast lookup object identifier registry. + diff --git a/target/linux/generic/hack-6.6/259-regmap_dynamic.patch b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch new file mode 100644 index 0000000000..8d25f59ce2 --- /dev/null +++ b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch @@ -0,0 +1,144 @@ +From 811d9e2268a62b830cfe93cd8bc929afcb8b198b Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 15 Jul 2017 21:12:38 +0200 +Subject: kernel: move regmap bloat out of the kernel image if it is only being used in modules + +lede-commit: 96f39119815028073583e4fca3a9c5fe9141e998 +Signed-off-by: Felix Fietkau +--- + drivers/base/regmap/Kconfig | 15 ++++++++++----- + drivers/base/regmap/Makefile | 12 ++++++++---- + drivers/base/regmap/regmap.c | 3 +++ + include/linux/regmap.h | 2 +- + 4 files changed, 22 insertions(+), 10 deletions(-) + +--- a/drivers/base/regmap/Kconfig ++++ b/drivers/base/regmap/Kconfig +@@ -4,10 +4,9 @@ + # subsystems should select the appropriate symbols. + + config REGMAP +- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) + select IRQ_DOMAIN if REGMAP_IRQ + select MDIO_BUS if REGMAP_MDIO +- bool ++ tristate + + config REGCACHE_COMPRESSED + select LZO_COMPRESS +@@ -15,53 +14,67 @@ config REGCACHE_COMPRESSED + bool + + config REGMAP_AC97 ++ select REGMAP + tristate + + config REGMAP_I2C ++ select REGMAP + tristate + depends on I2C + + config REGMAP_SLIMBUS ++ select REGMAP + tristate + depends on SLIMBUS + + config REGMAP_SPI ++ select REGMAP + tristate + depends on SPI + + config REGMAP_SPMI ++ select REGMAP + tristate + depends on SPMI + + config REGMAP_W1 ++ select REGMAP + tristate + depends on W1 + + config REGMAP_MDIO ++ select REGMAP + tristate + + config REGMAP_MMIO ++ select REGMAP + tristate + + config REGMAP_IRQ ++ select REGMAP + bool + + config REGMAP_SOUNDWIRE ++ select REGMAP + tristate + depends on SOUNDWIRE + + config REGMAP_SOUNDWIRE_MBQ ++ select REGMAP + tristate + depends on SOUNDWIRE + + config REGMAP_SCCB ++ select REGMAP + tristate + depends on I2C + + config REGMAP_I3C ++ select REGMAP + tristate + depends on I3C + + config REGMAP_SPI_AVMM ++ select REGMAP + tristate + depends on SPI +--- a/drivers/base/regmap/Makefile ++++ b/drivers/base/regmap/Makefile +@@ -2,10 +2,14 @@ + # For include/trace/define_trace.h to include trace.h + CFLAGS_regmap.o := -I$(src) + +-obj-$(CONFIG_REGMAP) += regmap.o regcache.o +-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o +-obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o +-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o ++regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o ++ifdef CONFIG_DEBUG_FS ++regmap-core-objs += regmap-debugfs.o ++endif ++ifdef CONFIG_REGCACHE_COMPRESSED ++regmap-core-objs += regcache-lzo.o ++endif ++obj-$(CONFIG_REGMAP) += regmap-core.o + obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o + obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o + obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3513,3 +3514,5 @@ static int __init regmap_initcall(void) + return 0; + } + postcore_initcall(regmap_initcall); ++ ++MODULE_LICENSE("GPL"); +--- a/include/linux/regmap.h ++++ b/include/linux/regmap.h +@@ -180,7 +180,7 @@ struct reg_sequence { + __ret ?: __tmp; \ + }) + +-#ifdef CONFIG_REGMAP ++#if IS_REACHABLE(CONFIG_REGMAP) + + enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ diff --git a/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch b/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch new file mode 100644 index 0000000000..7ea517496e --- /dev/null +++ b/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch @@ -0,0 +1,52 @@ +From fd1799b0bf5efa46dd3e6dfbbf3955564807e508 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:12:51 +0200 +Subject: kernel: prevent cryptomgr from pulling in useless extra dependencies for tests that are not run + +Reduces kernel size after LZMA by about 5k on MIPS + +lede-commit: 044c316167e076479a344c59905e5b435b84a77f +Signed-off-by: Felix Fietkau +--- + crypto/Kconfig | 13 ++++++------- + crypto/algboss.c | 4 ++++ + 2 files changed, 10 insertions(+), 7 deletions(-) + +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -142,13 +142,13 @@ config CRYPTO_MANAGER + cbc(aes). + + config CRYPTO_MANAGER2 +- def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y) +- select CRYPTO_AEAD2 +- select CRYPTO_HASH2 +- select CRYPTO_SKCIPHER2 +- select CRYPTO_AKCIPHER2 +- select CRYPTO_KPP2 +- select CRYPTO_ACOMP2 ++ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS) ++ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_SKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_ACOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS + + config CRYPTO_USER + tristate "Userspace cryptographic algorithm configuration" +--- a/crypto/algboss.c ++++ b/crypto/algboss.c +@@ -211,8 +211,12 @@ static int cryptomgr_schedule_test(struc + type = alg->cra_flags; + + /* Do not test internal algorithms. */ ++#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS ++ type |= CRYPTO_ALG_TESTED; ++#else + if (type & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_TESTED; ++#endif + + param->type = type; + diff --git a/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch new file mode 100644 index 0000000000..01829b2d51 --- /dev/null +++ b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch @@ -0,0 +1,24 @@ +From 241e5d3f7b0dd3c01f8c7fa83cbc9a3882286d53 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:35:18 +0200 +Subject: [PATCH] lib/crypto: add tristate string for ARC4 + +This makes it possible to select CONFIG_CRYPTO_LIB_ARC4 directly. We +need this to be able to compile this into the kernel and make use of it +from backports. + +--- + lib/crypto/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/lib/crypto/Kconfig ++++ b/lib/crypto/Kconfig +@@ -9,7 +9,7 @@ config CRYPTO_LIB_AES + tristate + + config CRYPTO_LIB_ARC4 +- tristate ++ tristate "ARC4 cipher library" + + config CRYPTO_ARCH_HAVE_LIB_BLAKE2S + bool diff --git a/target/linux/generic/hack-6.6/280-rfkill-stubs.patch b/target/linux/generic/hack-6.6/280-rfkill-stubs.patch new file mode 100644 index 0000000000..7a650d132e --- /dev/null +++ b/target/linux/generic/hack-6.6/280-rfkill-stubs.patch @@ -0,0 +1,84 @@ +From 236c1acdfef5958010ac9814a9872e0a46fd78ee Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 7 Jul 2017 17:13:44 +0200 +Subject: rfkill: add fake rfkill support + +allow building of modules depending on RFKILL even if RFKILL is not enabled. + +Signed-off-by: John Crispin +--- + include/linux/rfkill.h | 2 +- + net/Makefile | 2 +- + net/rfkill/Kconfig | 14 +++++++++----- + net/rfkill/Makefile | 2 +- + 4 files changed, 12 insertions(+), 8 deletions(-) + +--- a/include/linux/rfkill.h ++++ b/include/linux/rfkill.h +@@ -64,7 +64,7 @@ struct rfkill_ops { + int (*set_block)(void *data, bool blocked); + }; + +-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) ++#if defined(CONFIG_RFKILL_FULL) || defined(CONFIG_RFKILL_FULL_MODULE) + /** + * rfkill_alloc - Allocate rfkill structure + * @name: name of the struct -- the string is not copied internally +--- a/net/Makefile ++++ b/net/Makefile +@@ -52,7 +52,7 @@ obj-$(CONFIG_TIPC) += tipc/ + obj-$(CONFIG_NETLABEL) += netlabel/ + obj-$(CONFIG_IUCV) += iucv/ + obj-$(CONFIG_SMC) += smc/ +-obj-$(CONFIG_RFKILL) += rfkill/ ++obj-$(CONFIG_RFKILL_FULL) += rfkill/ + obj-$(CONFIG_NET_9P) += 9p/ + obj-$(CONFIG_CAIF) += caif/ + obj-$(CONFIG_DCB) += dcb/ +--- a/net/rfkill/Kconfig ++++ b/net/rfkill/Kconfig +@@ -2,7 +2,11 @@ + # + # RF switch subsystem configuration + # +-menuconfig RFKILL ++config RFKILL ++ bool ++ default y ++ ++menuconfig RFKILL_FULL + tristate "RF switch subsystem support" + help + Say Y here if you want to have control over RF switches +@@ -14,19 +18,19 @@ menuconfig RFKILL + # LED trigger support + config RFKILL_LEDS + bool +- depends on RFKILL ++ depends on RFKILL_FULL + depends on LEDS_TRIGGERS = y || RFKILL = LEDS_TRIGGERS + default y + + config RFKILL_INPUT + bool "RF switch input support" if EXPERT +- depends on RFKILL ++ depends on RFKILL_FULL + depends on INPUT = y || RFKILL = INPUT + default y if !EXPERT + + config RFKILL_GPIO + tristate "GPIO RFKILL driver" +- depends on RFKILL ++ depends on RFKILL_FULL + depends on GPIOLIB || COMPILE_TEST + default n + help +--- a/net/rfkill/Makefile ++++ b/net/rfkill/Makefile +@@ -5,5 +5,5 @@ + + rfkill-y += core.o + rfkill-$(CONFIG_RFKILL_INPUT) += input.o +-obj-$(CONFIG_RFKILL) += rfkill.o ++obj-$(CONFIG_RFKILL_FULL) += rfkill.o + obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o diff --git a/target/linux/generic/hack-6.6/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/target/linux/generic/hack-6.6/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch new file mode 100644 index 0000000000..f21f200136 --- /dev/null +++ b/target/linux/generic/hack-6.6/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch @@ -0,0 +1,64 @@ +From: Ben Menchaca +Date: Fri, 7 Jun 2013 18:35:22 -0500 +Subject: MIPS: r4k_cache: use more efficient cache blast + +Optimize the compiler output for larger cache blast cases that are +common for DMA-based networking. + +Signed-off-by: Ben Menchaca +Signed-off-by: Felix Fietkau +--- +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -286,14 +286,46 @@ static inline void prot##extra##blast_## + unsigned long end) \ + { \ + unsigned long lsize = cpu_##desc##_line_size(); \ ++ unsigned long lsize_2 = lsize * 2; \ ++ unsigned long lsize_3 = lsize * 3; \ ++ unsigned long lsize_4 = lsize * 4; \ ++ unsigned long lsize_5 = lsize * 5; \ ++ unsigned long lsize_6 = lsize * 6; \ ++ unsigned long lsize_7 = lsize * 7; \ ++ unsigned long lsize_8 = lsize * 8; \ + unsigned long addr = start & ~(lsize - 1); \ +- unsigned long aend = (end - 1) & ~(lsize - 1); \ ++ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ ++ int lines = (aend - addr) / lsize; \ + \ +- while (1) { \ ++ while (lines >= 8) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ prot##cache_op(hitop, addr + lsize_4); \ ++ prot##cache_op(hitop, addr + lsize_5); \ ++ prot##cache_op(hitop, addr + lsize_6); \ ++ prot##cache_op(hitop, addr + lsize_7); \ ++ addr += lsize_8; \ ++ lines -= 8; \ ++ } \ ++ \ ++ if (lines & 0x4) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ addr += lsize_4; \ ++ } \ ++ \ ++ if (lines & 0x2) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ addr += lsize_2; \ ++ } \ ++ \ ++ if (lines & 0x1) { \ + prot##cache_op(hitop, addr); \ +- if (addr == aend) \ +- break; \ +- addr += lsize; \ + } \ + } + diff --git a/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch new file mode 100644 index 0000000000..c82ca3edd8 --- /dev/null +++ b/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -0,0 +1,112 @@ +From 0bccc3722bdd88e8ae995e77ef9f7b77ee4cbdee Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 7 Apr 2021 22:45:54 +0100 +Subject: [PATCH 2/2] mtd: blktrans: call add disks after mtd device +To: linux-mtd@lists.infradead.org +Cc: Vignesh Raghavendra , + Richard Weinberger , + Miquel Raynal , + David Woodhouse + +Calling device_add_disk while holding mtd_table_mutex leads +to deadlock in case part_bits!=0 as block partition parsers +will try to open the newly created disks, trying to acquire +mutex once again. +Move device_add_disk to additional function called after +add partitions of an MTD device have been added and locks +have been released. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/mtd_blkdevs.c | 33 ++++++++++++++++++++++++++------- + drivers/mtd/mtdcore.c | 3 +++ + include/linux/mtd/blktrans.h | 1 + + 3 files changed, 30 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -386,19 +386,8 @@ int add_mtd_blktrans_dev(struct mtd_blkt + if (new->readonly) + set_disk_ro(gd, 1); + +- ret = device_add_disk(&new->mtd->dev, gd, NULL); +- if (ret) +- goto out_cleanup_disk; +- +- if (new->disk_attributes) { +- ret = sysfs_create_group(&disk_to_dev(gd)->kobj, +- new->disk_attributes); +- WARN_ON(ret); +- } + return 0; + +-out_cleanup_disk: +- put_disk(new->disk); + out_free_tag_set: + blk_mq_free_tag_set(new->tag_set); + out_kfree_tag_set: +@@ -408,6 +397,35 @@ out_list_del: + return ret; + } + ++void register_mtd_blktrans_devs(void) ++{ ++ struct mtd_blktrans_ops *tr; ++ struct mtd_blktrans_dev *dev, *next; ++ int ret; ++ ++ list_for_each_entry(tr, &blktrans_majors, list) { ++ list_for_each_entry_safe(dev, next, &tr->devs, list) { ++ if (disk_live(dev->disk)) ++ continue; ++ ++ ret = device_add_disk(&dev->mtd->dev, dev->disk, NULL); ++ if (ret) ++ goto out_cleanup_disk; ++ ++ if (dev->disk_attributes) { ++ ret = sysfs_create_group(&disk_to_dev(dev->disk)->kobj, ++ dev->disk_attributes); ++ WARN_ON(ret); ++ } ++ } ++ } ++ ++ return; ++ ++out_cleanup_disk: ++ put_disk(dev->disk); ++} ++ + int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) + { + unsigned long flags; +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -32,6 +32,7 @@ + + #include + #include ++#include + + #include "mtdcore.h" + +@@ -1098,6 +1099,8 @@ int mtd_device_parse_register(struct mtd + register_reboot_notifier(&mtd->reboot_notifier); + } + ++ register_mtd_blktrans_devs(); ++ + out: + if (ret) { + nvmem_unregister(mtd->otp_user_nvmem); +--- a/include/linux/mtd/blktrans.h ++++ b/include/linux/mtd/blktrans.h +@@ -76,6 +76,7 @@ extern int deregister_mtd_blktrans(struc + extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); + extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); + extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev); ++extern void register_mtd_blktrans_devs(void); + + /** + * module_mtd_blktrans() - Helper macro for registering a mtd blktrans driver diff --git a/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch new file mode 100644 index 0000000000..7c7e4c814e --- /dev/null +++ b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch @@ -0,0 +1,24 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 7 Nov 2022 23:48:24 +0100 +Subject: [PATCH] mtd: support OpenWrt's MTD_ROOTFS_ROOT_DEV +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows setting ROOT_DEV to MTD partition named "rootfs". + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -773,7 +773,8 @@ int add_mtd_device(struct mtd_info *mtd) + + mutex_unlock(&mtd_table_mutex); + +- if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) { ++ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL) || ++ (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && !strcmp(mtd->name, "rootfs") && ROOT_DEV == 0)) { + if (IS_BUILTIN(CONFIG_MTD)) { + pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); diff --git a/target/linux/generic/hack-6.6/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-6.6/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch new file mode 100644 index 0000000000..965a331a19 --- /dev/null +++ b/target/linux/generic/hack-6.6/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -0,0 +1,120 @@ +From 6fa9e3678eb002246df1280322b6a024853950a5 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 11 Oct 2021 00:53:14 +0200 +Subject: [PATCH] drivers: mtd: parsers: add nvmem support to cmdlinepart + +Assuming cmdlinepart is only one level deep partition scheme and that +static partition are also defined in DTS, we can assign an of_node for +partition declared from bootargs. cmdlinepart have priority than +fiexed-partition parser so in this specific case the parser doesn't +assign an of_node. Fix this by searching a defined of_node using a +similar fixed_partition parser and if a partition is found with the same +label, check that it has the same offset and size and return the DT +of_node to correctly use NVMEM cells. + +Signed-off-by: Ansuel Smith +--- + drivers/mtd/parsers/cmdlinepart.c | 71 +++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +--- a/drivers/mtd/parsers/cmdlinepart.c ++++ b/drivers/mtd/parsers/cmdlinepart.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + /* debug macro */ + #if 0 +@@ -323,6 +324,68 @@ static int mtdpart_setup_real(char *s) + return 0; + } + ++static int search_fixed_partition(struct mtd_info *master, ++ struct mtd_partition *target_part, ++ struct mtd_partition *fixed_part) ++{ ++ struct device_node *mtd_node; ++ struct device_node *ofpart_node; ++ struct device_node *pp; ++ struct mtd_partition part; ++ const char *partname; ++ ++ mtd_node = mtd_get_of_node(master); ++ if (!mtd_node) ++ return -EINVAL; ++ ++ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); ++ ++ for_each_child_of_node(ofpart_node, pp) { ++ const __be32 *reg; ++ int len; ++ int a_cells, s_cells; ++ ++ reg = of_get_property(pp, "reg", &len); ++ if (!reg) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ continue; ++ } ++ ++ a_cells = of_n_addr_cells(pp); ++ s_cells = of_n_size_cells(pp); ++ if (len / 4 != a_cells + s_cells) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ continue; ++ } ++ ++ part.offset = of_read_number(reg, a_cells); ++ part.size = of_read_number(reg + a_cells, s_cells); ++ part.of_node = pp; ++ ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ part.name = partname; ++ ++ if (!strncmp(target_part->name, part.name, len)) { ++ if (part.offset != target_part->offset) ++ return -EINVAL; ++ ++ if (part.size != target_part->size) ++ return -EINVAL; ++ ++ memcpy(fixed_part, &part, sizeof(struct mtd_partition)); ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ + /* + * Main function to be called from the MTD mapping driver/device to + * obtain the partitioning information. At this point the command line +@@ -338,6 +401,7 @@ static int parse_cmdline_partitions(stru + int i, err; + struct cmdline_mtd_partition *part; + const char *mtd_id = master->name; ++ struct mtd_partition fixed_part; + + /* parse command line */ + if (!cmdline_parsed) { +@@ -382,6 +446,13 @@ static int parse_cmdline_partitions(stru + sizeof(*part->parts) * (part->num_parts - i)); + i--; + } ++ ++ err = search_fixed_partition(master, &part->parts[i], &fixed_part); ++ if (!err) { ++ part->parts[i].of_node = fixed_part.of_node; ++ pr_info("Found partition defined in DT for %s. Assigning OF node to support nvmem.", ++ part->parts[i].name); ++ } + } + + *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts, diff --git a/target/linux/generic/hack-6.6/430-mtk-bmt-support.patch b/target/linux/generic/hack-6.6/430-mtk-bmt-support.patch new file mode 100644 index 0000000000..1e69ee6446 --- /dev/null +++ b/target/linux/generic/hack-6.6/430-mtk-bmt-support.patch @@ -0,0 +1,33 @@ +From ac84397efb3b3868c71c10ad7521161773228a17 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:41:44 +0200 +Subject: [PATCH] mtd/nand: add MediaTek NAND bad block managment table + +--- + drivers/mtd/nand/Kconfig | 4 ++++ + drivers/mtd/nand/Makefile | 1 + + 2 files changed, 5 insertions(+) + +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -46,6 +46,10 @@ config MTD_NAND_ECC_SW_BCH + ECC codes. They are used with NAND devices requiring more than 1 bit + of error correction. + ++config MTD_NAND_MTK_BMT ++ bool "Support MediaTek NAND Bad-block Management Table" ++ default n ++ + config MTD_NAND_ECC_MXIC + bool "Macronix external hardware ECC engine" + depends on HAS_IOMEM +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -3,6 +3,7 @@ + nandcore-objs := core.o bbt.o + obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o + obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o ++obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o + + obj-y += onenand/ + obj-y += raw/ diff --git a/target/linux/generic/hack-6.6/645-netfilter-connmark-introduce-set-dscpmark.patch b/target/linux/generic/hack-6.6/645-netfilter-connmark-introduce-set-dscpmark.patch new file mode 100644 index 0000000000..444f8edfea --- /dev/null +++ b/target/linux/generic/hack-6.6/645-netfilter-connmark-introduce-set-dscpmark.patch @@ -0,0 +1,214 @@ +From eda40b8c8c82e0f2789d6bc8bf63846dce2e8f32 Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Sat, 23 Mar 2019 09:29:49 +0000 +Subject: [PATCH] netfilter: connmark: introduce set-dscpmark + +set-dscpmark is a method of storing the DSCP of an ip packet into +conntrack mark. In combination with a suitable tc filter action +(act_ctinfo) DSCP values are able to be stored in the mark on egress and +restored on ingress across links that otherwise alter or bleach DSCP. + +This is useful for qdiscs such as CAKE which are able to shape according +to policies based on DSCP. + +Ingress classification is traditionally a challenging task since +iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT +lookups, hence are unable to see internal IPv4 addresses as used on the +typical home masquerading gateway. + +x_tables CONNMARK set-dscpmark target solves the problem of storing the +DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc +action to restore. + +The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a +32bit 'statemask'. The dscp mask must be 6 contiguous bits and +represents the area where the DSCP will be stored in the connmark. The +state mask is a minimum 1 bit length mask that must not overlap with the +dscpmask. It represents a flag which is set when the DSCP has been +stored in the conntrack mark. This is useful to implement a 'one shot' +iptables based classification where the 'complicated' iptables rules are +only run once to classify the connection on initial (egress) packet and +subsequent packets are all marked/restored with the same DSCP. A state +mask of zero disables the setting of a status bit/s. + +example syntax with a suitably modified iptables user space application: + +iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000 + +Would store the DSCP in the top 6 bits of the 32bit mark field, and use +the LSB of the top byte as the 'DSCP has been stored' marker. + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + ^ ^ + | | + ---| Conditional flag + | set this when dscp +|-ip diffserv-| stored in mark +| 6 bits | +|-------------| + +an identically configured tc action to restore looks like: + +tc filter show dev eth0 ingress +filter parent ffff: protocol all pref 10 u32 chain 0 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw + match 00000000/00000000 at 0 + action order 1: ctinfo zone 0 pipe + index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 + + action order 2: mirred (Egress Redirect to device ifb4eth0) stolen + index 1 ref 1 bind 1 + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + | | + | | + ---| Conditional flag + v only restore if set +|-ip diffserv-| +| 6 bits | +|-------------| + +Signed-off-by: Kevin Darbyshire-Bryant +--- + include/uapi/linux/netfilter/xt_connmark.h | 10 ++++ + net/netfilter/xt_connmark.c | 55 ++++++++++++++++++---- + 2 files changed, 57 insertions(+), 8 deletions(-) + +--- a/include/uapi/linux/netfilter/xt_connmark.h ++++ b/include/uapi/linux/netfilter/xt_connmark.h +@@ -15,6 +15,11 @@ enum { + }; + + enum { ++ XT_CONNMARK_VALUE = (1 << 0), ++ XT_CONNMARK_DSCP = (1 << 1) ++}; ++ ++enum { + D_SHIFT_LEFT = 0, + D_SHIFT_RIGHT, + }; +@@ -29,6 +34,11 @@ struct xt_connmark_tginfo2 { + __u8 shift_dir, shift_bits, mode; + }; + ++struct xt_connmark_tginfo3 { ++ __u32 ctmark, ctmask, nfmask; ++ __u8 shift_dir, shift_bits, mode, func; ++}; ++ + struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +--- a/net/netfilter/xt_connmark.c ++++ b/net/netfilter/xt_connmark.c +@@ -24,13 +24,13 @@ MODULE_ALIAS("ipt_connmark"); + MODULE_ALIAS("ip6t_connmark"); + + static unsigned int +-connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) ++connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo3 *info) + { + enum ip_conntrack_info ctinfo; + u_int32_t new_targetmark; + struct nf_conn *ct; + u_int32_t newmark; +- u_int32_t oldmark; ++ u_int8_t dscp; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) +@@ -38,13 +38,24 @@ connmark_tg_shift(struct sk_buff *skb, c + + switch (info->mode) { + case XT_CONNMARK_SET: +- oldmark = READ_ONCE(ct->mark); +- newmark = (oldmark & ~info->ctmask) ^ info->ctmark; +- if (info->shift_dir == D_SHIFT_RIGHT) +- newmark >>= info->shift_bits; +- else +- newmark <<= info->shift_bits; ++ newmark = READ_ONCE(ct->mark); ++ if (info->func & XT_CONNMARK_VALUE) { ++ newmark = (newmark & ~info->ctmask) ^ info->ctmark; ++ if (info->shift_dir == D_SHIFT_RIGHT) ++ newmark >>= info->shift_bits; ++ else ++ newmark <<= info->shift_bits; ++ } else if (info->func & XT_CONNMARK_DSCP) { ++ if (skb->protocol == htons(ETH_P_IP)) ++ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; ++ else if (skb->protocol == htons(ETH_P_IPV6)) ++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; ++ else /* protocol doesn't have diffserv */ ++ break; + ++ newmark = (newmark & ~info->ctmark) | ++ (info->ctmask | (dscp << info->shift_bits)); ++ } + if (READ_ONCE(ct->mark) != newmark) { + WRITE_ONCE(ct->mark, newmark); + nf_conntrack_event_cache(IPCT_MARK, ct); +@@ -83,20 +94,36 @@ static unsigned int + connmark_tg(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo1 *info = par->targinfo; +- const struct xt_connmark_tginfo2 info2 = { ++ const struct xt_connmark_tginfo3 info3 = { + .ctmark = info->ctmark, + .ctmask = info->ctmask, + .nfmask = info->nfmask, + .mode = info->mode, ++ .func = XT_CONNMARK_VALUE + }; + +- return connmark_tg_shift(skb, &info2); ++ return connmark_tg_shift(skb, &info3); + } + + static unsigned int + connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo2 *info = par->targinfo; ++ const struct xt_connmark_tginfo3 info3 = { ++ .ctmark = info->ctmark, ++ .ctmask = info->ctmask, ++ .nfmask = info->nfmask, ++ .mode = info->mode, ++ .func = XT_CONNMARK_VALUE ++ }; ++ ++ return connmark_tg_shift(skb, &info3); ++} ++ ++static unsigned int ++connmark_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_connmark_tginfo3 *info = par->targinfo; + + return connmark_tg_shift(skb, info); + } +@@ -167,6 +194,16 @@ static struct xt_target connmark_tg_reg[ + .targetsize = sizeof(struct xt_connmark_tginfo2), + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, ++ }, ++ { ++ .name = "CONNMARK", ++ .revision = 3, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_tg_check, ++ .target = connmark_tg_v3, ++ .targetsize = sizeof(struct xt_connmark_tginfo3), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, + } + }; + diff --git a/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch new file mode 100644 index 0000000000..59a5fb4d91 --- /dev/null +++ b/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -0,0 +1,803 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 15:56:02 +0100 +Subject: [PATCH] netfilter: add xt_FLOWOFFLOAD target + +Signed-off-by: Felix Fietkau +--- + create mode 100644 net/netfilter/xt_OFFLOAD.c + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -1023,6 +1023,15 @@ config NETFILTER_XT_TARGET_NOTRACK + depends on NETFILTER_ADVANCED + select NETFILTER_XT_TARGET_CT + ++config NETFILTER_XT_TARGET_FLOWOFFLOAD ++ tristate '"FLOWOFFLOAD" target support' ++ depends on NF_FLOW_TABLE ++ depends on NETFILTER_INGRESS ++ help ++ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload ++ module to speed up processing of packets by bypassing the usual ++ netfilter chains ++ + config NETFILTER_XT_TARGET_RATEEST + tristate '"RATEEST" target support' + depends on NETFILTER_ADVANCED +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -154,6 +154,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF + obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o + obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o ++obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o +--- /dev/null ++++ b/net/netfilter/xt_FLOWOFFLOAD.c +@@ -0,0 +1,702 @@ ++/* ++ * Copyright (C) 2018-2021 Felix Fietkau ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct xt_flowoffload_hook { ++ struct hlist_node list; ++ struct nf_hook_ops ops; ++ struct net *net; ++ bool registered; ++ bool used; ++}; ++ ++struct xt_flowoffload_table { ++ struct nf_flowtable ft; ++ struct hlist_head hooks; ++ struct delayed_work work; ++}; ++ ++struct nf_forward_info { ++ const struct net_device *indev; ++ const struct net_device *outdev; ++ const struct net_device *hw_outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; ++ u8 ingress_vlans; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ enum flow_offload_xmit_type xmit_type; ++}; ++ ++static DEFINE_SPINLOCK(hooks_lock); ++ ++struct xt_flowoffload_table flowtable[2]; ++ ++static unsigned int ++xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct vlan_ethhdr *veth; ++ __be16 proto; ++ ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ proto = veth->h_vlan_encapsulated_proto; ++ break; ++ case htons(ETH_P_PPP_SES): ++ proto = nf_flow_pppoe_proto(skb); ++ break; ++ default: ++ proto = skb->protocol; ++ break; ++ } ++ ++ switch (proto) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static int ++xt_flowoffload_create_hook(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ struct nf_hook_ops *ops; ++ ++ hook = kzalloc(sizeof(*hook), GFP_ATOMIC); ++ if (!hook) ++ return -ENOMEM; ++ ++ ops = &hook->ops; ++ ops->pf = NFPROTO_NETDEV; ++ ops->hooknum = NF_NETDEV_INGRESS; ++ ops->priority = 10; ++ ops->priv = &table->ft; ++ ops->hook = xt_flowoffload_net_hook; ++ ops->dev = dev; ++ ++ hlist_add_head(&hook->list, &table->hooks); ++ mod_delayed_work(system_power_efficient_wq, &table->work, 0); ++ ++ return 0; ++} ++ ++static struct xt_flowoffload_hook * ++flow_offload_lookup_hook(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->ops.dev == dev) ++ return hook; ++ } ++ ++ return NULL; ++} ++ ++static void ++xt_flowoffload_check_device(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ if (!dev) ++ return; ++ ++ spin_lock_bh(&hooks_lock); ++ hook = flow_offload_lookup_hook(table, dev); ++ if (hook) ++ hook->used = true; ++ else ++ xt_flowoffload_create_hook(table, dev); ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_register_hooks(struct xt_flowoffload_table *table) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->registered) ++ continue; ++ ++ hook->registered = true; ++ hook->net = dev_net(hook->ops.dev); ++ spin_unlock_bh(&hooks_lock); ++ nf_register_net_hook(hook->net, &hook->ops); ++ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD) ++ table->ft.type->setup(&table->ft, hook->ops.dev, ++ FLOW_BLOCK_BIND); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static bool ++xt_flowoffload_cleanup_hooks(struct xt_flowoffload_table *table) ++{ ++ struct xt_flowoffload_hook *hook; ++ bool active = false; ++ ++restart: ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->used || !hook->registered) { ++ active = true; ++ continue; ++ } ++ ++ hlist_del(&hook->list); ++ spin_unlock_bh(&hooks_lock); ++ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD) ++ table->ft.type->setup(&table->ft, hook->ops.dev, ++ FLOW_BLOCK_UNBIND); ++ nf_unregister_net_hook(hook->net, &hook->ops); ++ kfree(hook); ++ goto restart; ++ } ++ spin_unlock_bh(&hooks_lock); ++ ++ return active; ++} ++ ++static void ++xt_flowoffload_check_hook(struct nf_flowtable *flowtable, ++ struct flow_offload *flow, void *data) ++{ ++ struct xt_flowoffload_table *table; ++ struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple; ++ struct flow_offload_tuple *tuple1 = &flow->tuplehash[1].tuple; ++ struct xt_flowoffload_hook *hook; ++ ++ table = container_of(flowtable, struct xt_flowoffload_table, ft); ++ ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->ops.dev->ifindex != tuple0->iifidx && ++ hook->ops.dev->ifindex != tuple1->iifidx) ++ continue; ++ ++ hook->used = true; ++ } ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_hook_work(struct work_struct *work) ++{ ++ struct xt_flowoffload_table *table; ++ struct xt_flowoffload_hook *hook; ++ int err; ++ ++ table = container_of(work, struct xt_flowoffload_table, work.work); ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_register_hooks(table); ++ hlist_for_each_entry(hook, &table->hooks, list) ++ hook->used = false; ++ spin_unlock_bh(&hooks_lock); ++ ++ err = nf_flow_table_iterate(&table->ft, xt_flowoffload_check_hook, ++ NULL); ++ if (err && err != -EAGAIN) ++ goto out; ++ ++ if (!xt_flowoffload_cleanup_hooks(table)) ++ return; ++ ++out: ++ queue_delayed_work(system_power_efficient_wq, &table->work, HZ); ++} ++ ++static bool ++xt_flowoffload_skip(struct sk_buff *skb, int family) ++{ ++ if (skb_sec_path(skb)) ++ return true; ++ ++ if (family == NFPROTO_IPV4) { ++ const struct ip_options *opt = &(IPCB(skb)->opt); ++ ++ if (unlikely(opt->optlen)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static enum flow_offload_xmit_type nf_xmit_type(struct dst_entry *dst) ++{ ++ if (dst_xfrm(dst)) ++ return FLOW_OFFLOAD_XMIT_XFRM; ++ ++ return FLOW_OFFLOAD_XMIT_NEIGH; ++} ++ ++static void nf_default_forward_path(struct nf_flow_route *route, ++ struct dst_entry *dst_cache, ++ enum ip_conntrack_dir dir, ++ struct net_device **dev) ++{ ++ dev[!dir] = dst_cache->dev; ++ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; ++ route->tuple[dir].dst = dst_cache; ++ route->tuple[dir].xmit_type = nf_xmit_type(dst_cache); ++} ++ ++static bool nf_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ ++static void nf_dev_path_info(const struct net_device_path_stack *stack, ++ struct nf_forward_info *info, ++ unsigned char *ha) ++{ ++ const struct net_device_path *path; ++ int i; ++ ++ memcpy(info->h_dest, ha, ETH_ALEN); ++ ++ for (i = 0; i < stack->num_paths; i++) { ++ path = &stack->path[i]; ++ switch (path->type) { ++ case DEV_PATH_ETHERNET: ++ case DEV_PATH_DSA: ++ case DEV_PATH_VLAN: ++ case DEV_PATH_PPPOE: ++ info->indev = path->dev; ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ if (path->type == DEV_PATH_ETHERNET) ++ break; ++ if (path->type == DEV_PATH_DSA) { ++ i = stack->num_paths; ++ break; ++ } ++ ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; ++ break; ++ } ++ if (!info->outdev) ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; ++ if (path->type == DEV_PATH_PPPOE) ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); ++ break; ++ case DEV_PATH_BRIDGE: ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; ++ case DEV_PATH_BR_VLAN_TAG: ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG: ++ info->num_encaps--; ++ break; ++ case DEV_PATH_BR_VLAN_KEEP: ++ break; ++ } ++ break; ++ default: ++ info->indev = NULL; ++ break; ++ } ++ } ++ if (!info->outdev) ++ info->outdev = info->indev; ++ ++ info->hw_outdev = info->indev; ++ ++ if (nf_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; ++} ++ ++static int nf_dev_fill_forward_path(const struct nf_flow_route *route, ++ const struct dst_entry *dst_cache, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, u8 *ha, ++ struct net_device_path_stack *stack) ++{ ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device *dev = dst_cache->dev; ++ struct neighbour *n; ++ u8 nud_state; ++ ++ if (!nf_is_valid_ether_device(dev)) ++ goto out; ++ ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -1; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return -1; ++ ++out: ++ return dev_fill_forward_path(dev, ha, stack); ++} ++ ++static void nf_dev_forward_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device **devs) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ struct net_device_path_stack stack; ++ struct nf_forward_info info = {}; ++ unsigned char ha[ETH_ALEN]; ++ int i; ++ ++ if (nf_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) ++ nf_dev_path_info(&stack, &info, ha); ++ ++ devs[!dir] = (struct net_device *)info.indev; ++ if (!info.indev) ++ return; ++ ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; ++ } ++ route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; ++ ++ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; ++ route->tuple[dir].xmit_type = info.xmit_type; ++ } ++} ++ ++static int ++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, ++ const struct xt_action_param *par, ++ struct nf_flow_route *route, enum ip_conntrack_dir dir, ++ struct net_device **devs) ++{ ++ struct dst_entry *this_dst = skb_dst(skb); ++ struct dst_entry *other_dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++ switch (xt_family(par)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ fl.u.ip4.flowi4_oif = xt_in(par)->ifindex; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; ++ fl.u.ip6.flowi6_oif = xt_in(par)->ifindex; ++ break; ++ } ++ ++ if (!dst_hold_safe(this_dst)) ++ return -ENOENT; ++ ++ nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par)); ++ if (!other_dst) { ++ dst_release(this_dst); ++ return -ENOENT; ++ } ++ ++ nf_default_forward_path(route, this_dst, dir, devs); ++ nf_default_forward_path(route, other_dst, !dir, devs); ++ ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && ++ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { ++ nf_dev_forward_path(route, ct, dir, devs); ++ nf_dev_forward_path(route, ct, !dir, devs); ++ } ++ ++ return 0; ++} ++ ++static unsigned int ++flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ struct xt_flowoffload_table *table; ++ const struct xt_flowoffload_target_info *info = par->targinfo; ++ struct tcphdr _tcph, *tcph = NULL; ++ enum ip_conntrack_info ctinfo; ++ enum ip_conntrack_dir dir; ++ struct nf_flow_route route = {}; ++ struct flow_offload *flow = NULL; ++ struct net_device *devs[2] = {}; ++ struct nf_conn *ct; ++ struct net *net; ++ ++ if (xt_flowoffload_skip(skb, xt_family(par))) ++ return XT_CONTINUE; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++ return XT_CONTINUE; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { ++ case IPPROTO_TCP: ++ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) ++ return XT_CONTINUE; ++ ++ tcph = skb_header_pointer(skb, par->thoff, ++ sizeof(_tcph), &_tcph); ++ if (unlikely(!tcph || tcph->fin || tcph->rst)) ++ return XT_CONTINUE; ++ break; ++ case IPPROTO_UDP: ++ break; ++ default: ++ return XT_CONTINUE; ++ } ++ ++ if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || ++ ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH)) ++ return XT_CONTINUE; ++ ++ if (!nf_ct_is_confirmed(ct)) ++ return XT_CONTINUE; ++ ++ devs[dir] = xt_out(par); ++ devs[!dir] = xt_in(par); ++ ++ if (!devs[dir] || !devs[!dir]) ++ return XT_CONTINUE; ++ ++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return XT_CONTINUE; ++ ++ dir = CTINFO2DIR(ctinfo); ++ ++ if (xt_flowoffload_route(skb, ct, par, &route, dir, devs) < 0) ++ goto err_flow_route; ++ ++ flow = flow_offload_alloc(ct); ++ if (!flow) ++ goto err_flow_alloc; ++ ++ flow_offload_route_init(flow, &route); ++ ++ if (tcph) { ++ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ } ++ ++ table = &flowtable[!!(info->flags & XT_FLOWOFFLOAD_HW)]; ++ ++ net = read_pnet(&table->ft.net); ++ if (!net) ++ write_pnet(&table->ft.net, xt_net(par)); ++ ++ __set_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags); ++ if (flow_offload_add(&table->ft, flow) < 0) ++ goto err_flow_add; ++ ++ xt_flowoffload_check_device(table, devs[0]); ++ xt_flowoffload_check_device(table, devs[1]); ++ ++ return XT_CONTINUE; ++ ++err_flow_add: ++ flow_offload_free(flow); ++err_flow_alloc: ++ dst_release(route.tuple[dir].dst); ++ dst_release(route.tuple[!dir].dst); ++err_flow_route: ++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); ++ ++ return XT_CONTINUE; ++} ++ ++static int flowoffload_chk(const struct xt_tgchk_param *par) ++{ ++ struct xt_flowoffload_target_info *info = par->targinfo; ++ ++ if (info->flags & ~XT_FLOWOFFLOAD_MASK) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static struct xt_target offload_tg_reg __read_mostly = { ++ .family = NFPROTO_UNSPEC, ++ .name = "FLOWOFFLOAD", ++ .revision = 0, ++ .targetsize = sizeof(struct xt_flowoffload_target_info), ++ .usersize = sizeof(struct xt_flowoffload_target_info), ++ .checkentry = flowoffload_chk, ++ .target = flowoffload_tg, ++ .me = THIS_MODULE, ++}; ++ ++static int flow_offload_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct xt_flowoffload_hook *hook0, *hook1; ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_UNREGISTER) ++ return NOTIFY_DONE; ++ ++ spin_lock_bh(&hooks_lock); ++ hook0 = flow_offload_lookup_hook(&flowtable[0], dev); ++ if (hook0) ++ hlist_del(&hook0->list); ++ ++ hook1 = flow_offload_lookup_hook(&flowtable[1], dev); ++ if (hook1) ++ hlist_del(&hook1->list); ++ spin_unlock_bh(&hooks_lock); ++ ++ if (hook0) { ++ nf_unregister_net_hook(hook0->net, &hook0->ops); ++ kfree(hook0); ++ } ++ ++ if (hook1) { ++ nf_unregister_net_hook(hook1->net, &hook1->ops); ++ kfree(hook1); ++ } ++ ++ nf_flow_table_cleanup(dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = flow_offload_netdev_event, ++}; ++ ++static int nf_flow_rule_route_inet(struct net *net, ++ struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, ++ struct nf_flow_rule *flow_rule) ++{ ++ const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; ++ int err; ++ ++ switch (flow_tuple->l3proto) { ++ case NFPROTO_IPV4: ++ err = nf_flow_rule_route_ipv4(net, flow, dir, flow_rule); ++ break; ++ case NFPROTO_IPV6: ++ err = nf_flow_rule_route_ipv6(net, flow, dir, flow_rule); ++ break; ++ default: ++ err = -1; ++ break; ++ } ++ ++ return err; ++} ++ ++static struct nf_flowtable_type flowtable_inet = { ++ .family = NFPROTO_INET, ++ .init = nf_flow_table_init, ++ .setup = nf_flow_table_offload_setup, ++ .action = nf_flow_rule_route_inet, ++ .free = nf_flow_table_free, ++ .hook = xt_flowoffload_net_hook, ++ .owner = THIS_MODULE, ++}; ++ ++static int init_flowtable(struct xt_flowoffload_table *tbl) ++{ ++ INIT_DELAYED_WORK(&tbl->work, xt_flowoffload_hook_work); ++ tbl->ft.type = &flowtable_inet; ++ tbl->ft.flags = NF_FLOWTABLE_COUNTER; ++ ++ return nf_flow_table_init(&tbl->ft); ++} ++ ++static int __init xt_flowoffload_tg_init(void) ++{ ++ int ret; ++ ++ register_netdevice_notifier(&flow_offload_netdev_notifier); ++ ++ ret = init_flowtable(&flowtable[0]); ++ if (ret) ++ return ret; ++ ++ ret = init_flowtable(&flowtable[1]); ++ if (ret) ++ goto cleanup; ++ ++ flowtable[1].ft.flags |= NF_FLOWTABLE_HW_OFFLOAD; ++ ++ ret = xt_register_target(&offload_tg_reg); ++ if (ret) ++ goto cleanup2; ++ ++ return 0; ++ ++cleanup2: ++ nf_flow_table_free(&flowtable[1].ft); ++cleanup: ++ nf_flow_table_free(&flowtable[0].ft); ++ return ret; ++} ++ ++static void __exit xt_flowoffload_tg_exit(void) ++{ ++ xt_unregister_target(&offload_tg_reg); ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ nf_flow_table_free(&flowtable[0].ft); ++ nf_flow_table_free(&flowtable[1].ft); ++} ++ ++MODULE_LICENSE("GPL"); ++module_init(xt_flowoffload_tg_init); ++module_exit(xt_flowoffload_tg_exit); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -374,8 +373,7 @@ flow_offload_lookup(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + +-static int +-nf_flow_table_iterate(struct nf_flowtable *flow_table, ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, + void (*iter)(struct nf_flowtable *flowtable, + struct flow_offload *flow, void *data), + void *data) +@@ -436,6 +434,7 @@ static void nf_flow_offload_gc_step(stru + nf_flow_offload_stats(flow_table, flow); + } + } ++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); + + void nf_flow_table_gc_run(struct nf_flowtable *flow_table) + { +--- /dev/null ++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _XT_FLOWOFFLOAD_H ++#define _XT_FLOWOFFLOAD_H ++ ++#include ++ ++enum { ++ XT_FLOWOFFLOAD_HW = 1 << 0, ++ ++ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW ++}; ++ ++struct xt_flowoffload_target_info { ++ __u32 flags; ++}; ++ ++#endif /* _XT_FLOWOFFLOAD_H */ +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -293,6 +293,11 @@ void nf_flow_table_free(struct nf_flowta + + void flow_offload_teardown(struct flow_offload *flow); + ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct nf_flowtable *flowtable, ++ struct flow_offload *flow, void *data), ++ void *data); ++ + void nf_flow_snat_port(const struct flow_offload *flow, + struct sk_buff *skb, unsigned int thoff, + u8 protocol, enum flow_offload_tuple_dir dir); diff --git a/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch b/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch new file mode 100644 index 0000000000..fd7d5346ad --- /dev/null +++ b/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch @@ -0,0 +1,24 @@ +From 6d3bc769657b0ee7c7506dad9911111c4226a7ea Mon Sep 17 00:00:00 2001 +From: Imre Kaloz +Date: Fri, 7 Jul 2017 17:21:05 +0200 +Subject: mac80211: increase wireless mesh header size + +lede-commit 3d4466cfd8f75f717efdb1f96fdde3c70d865fc1 +Signed-off-by: Imre Kaloz +--- + include/linux/netdevice.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -149,8 +149,8 @@ static inline bool dev_xmit_complete(int + + #if defined(CONFIG_HYPERV_NET) + # define LL_MAX_HEADER 128 +-#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) +-# if defined(CONFIG_MAC80211_MESH) ++#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) || 1 ++# if defined(CONFIG_MAC80211_MESH) || 1 + # define LL_MAX_HEADER 128 + # else + # define LL_MAX_HEADER 96 diff --git a/target/linux/generic/hack-6.6/660-fq_codel_defaults.patch b/target/linux/generic/hack-6.6/660-fq_codel_defaults.patch new file mode 100644 index 0000000000..b923a2d206 --- /dev/null +++ b/target/linux/generic/hack-6.6/660-fq_codel_defaults.patch @@ -0,0 +1,27 @@ +From a6ccb238939b25851474a279b20367fd24a0e816 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:21:53 +0200 +Subject: hack: net: fq_codel: tune defaults for small devices + +Assume that x86_64 devices always have a big memory and do not need this +optimization compared to devices with only 32 MB or 64 MB RAM. + +Signed-off-by: Felix Fietkau +--- + net/sched/sch_fq_codel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -471,7 +471,11 @@ static int fq_codel_init(struct Qdisc *s + + sch->limit = 10*1024; + q->flows_cnt = 1024; ++#ifdef CONFIG_X86_64 + q->memory_limit = 32 << 20; /* 32 MBytes */ ++#else ++ q->memory_limit = 4 << 20; /* 4 MBytes */ ++#endif + q->drop_batch_size = 64; + q->quantum = psched_mtu(qdisc_dev(sch)); + INIT_LIST_HEAD(&q->new_flows); diff --git a/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch b/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch new file mode 100644 index 0000000000..fe94a9da0c --- /dev/null +++ b/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch @@ -0,0 +1,25 @@ +From 804fbb3f2ec9283f7b778e057a68bfff440a0be6 Mon Sep 17 00:00:00 2001 +From: Rui Salvaterra +Date: Wed, 30 Mar 2022 22:51:55 +0100 +Subject: [PATCH] kernel: ct: size the hashtable more adequately + +To set the default size of the connection tracking hash table, a divider of +16384 becomes inadequate for a router handling lots of connections. Divide by +2048 instead, making the default size scale better with the available RAM. + +Signed-off-by: Rui Salvaterra +--- + net/netfilter/nf_conntrack_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -2705,7 +2705,7 @@ int nf_conntrack_init_start(void) + + if (!nf_conntrack_htable_size) { + nf_conntrack_htable_size +- = (((nr_pages << PAGE_SHIFT) / 16384) ++ = (((nr_pages << PAGE_SHIFT) / 2048) + / sizeof(struct hlist_head)); + if (BITS_PER_LONG >= 64 && + nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE))) diff --git a/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch new file mode 100644 index 0000000000..673082d840 --- /dev/null +++ b/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch @@ -0,0 +1,131 @@ +From 36e516290611e613aa92996cb4339561452695b4 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:24:23 +0200 +Subject: net: swconfig: adds openwrt switch layer + +Signed-off-by: Felix Fietkau +--- + drivers/net/phy/Kconfig | 83 +++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/Makefile | 15 +++++++++ + include/uapi/linux/Kbuild | 1 + + 3 files changed, 99 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -67,6 +67,80 @@ config SFP + depends on HWMON || HWMON=n + select MDIO_I2C + ++comment "Switch configuration API + drivers" ++ ++config SWCONFIG ++ tristate "Switch configuration API" ++ help ++ Switch configuration API using netlink. This allows ++ you to configure the VLAN features of certain switches. ++ ++config SWCONFIG_LEDS ++ bool "Switch LED trigger support" ++ depends on (SWCONFIG && LEDS_TRIGGERS) ++ ++config ADM6996_PHY ++ tristate "Driver for ADM6996 switches" ++ select SWCONFIG ++ help ++ Currently supports the ADM6996FC and ADM6996M switches. ++ Support for FC is very limited. ++ ++config AR8216_PHY ++ tristate "Driver for Atheros AR8216/8327 switches" ++ select SWCONFIG ++ select ETHERNET_PACKET_MANGLE ++ ++config AR8216_PHY_LEDS ++ bool "Atheros AR8216 switch LED support" ++ depends on (AR8216_PHY && LEDS_CLASS) ++ ++source "drivers/net/phy/b53/Kconfig" ++ ++config IP17XX_PHY ++ tristate "Driver for IC+ IP17xx switches" ++ select SWCONFIG ++ ++config PSB6970_PHY ++ tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch" ++ select SWCONFIG ++ ++config RTL8306_PHY ++ tristate "Driver for Realtek RTL8306S switches" ++ select SWCONFIG ++ ++config RTL8366_SMI ++ tristate "Driver for the RTL8366 SMI interface" ++ depends on GPIOLIB ++ help ++ This module implements the SMI interface protocol which is used ++ by some RTL8366 ethernet switch devices via the generic GPIO API. ++ ++if RTL8366_SMI ++ ++config RTL8366_SMI_DEBUG_FS ++ bool "RTL8366 SMI interface debugfs support" ++ depends on DEBUG_FS ++ default n ++ ++config RTL8366S_PHY ++ tristate "Driver for the Realtek RTL8366S switch" ++ select SWCONFIG ++ ++config RTL8366RB_PHY ++ tristate "Driver for the Realtek RTL8366RB switch" ++ select SWCONFIG ++ ++config RTL8367_PHY ++ tristate "Driver for the Realtek RTL8367R/M switches" ++ select SWCONFIG ++ ++config RTL8367B_PHY ++ tristate "Driver fot the Realtek RTL8367R-VB switch" ++ select SWCONFIG ++ ++endif # RTL8366_SMI ++ + comment "MII PHY device drivers" + + config AIR_EN8811H_PHY +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -24,6 +24,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ + obj-$(CONFIG_PHYLINK) += phylink.o + obj-$(CONFIG_PHYLIB) += libphy.o + ++obj-$(CONFIG_SWCONFIG) += swconfig.o ++obj-$(CONFIG_ADM6996_PHY) += adm6996.o ++obj-$(CONFIG_AR8216_PHY) += ar8xxx.o ++ar8xxx-y += ar8216.o ++ar8xxx-y += ar8327.o ++obj-$(CONFIG_SWCONFIG_B53) += b53/ ++obj-$(CONFIG_IP17XX_PHY) += ip17xx.o ++obj-$(CONFIG_PSB6970_PHY) += psb6970.o ++obj-$(CONFIG_RTL8306_PHY) += rtl8306.o ++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o ++obj-$(CONFIG_RTL8366S_PHY) += rtl8366s.o ++obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb.o ++obj-$(CONFIG_RTL8367_PHY) += rtl8367.o ++obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o ++ + obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o + + obj-$(CONFIG_SFP) += sfp.o +--- a/include/linux/platform_data/b53.h ++++ b/include/linux/platform_data/b53.h +@@ -29,6 +29,9 @@ struct b53_platform_data { + u32 chip_id; + u16 enabled_ports; + ++ /* allow to specify an ethX alias */ ++ const char *alias; ++ + /* only used by MMAP'd driver */ + unsigned big_endian:1; + void __iomem *regs; diff --git a/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch new file mode 100644 index 0000000000..f09ad117b0 --- /dev/null +++ b/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -0,0 +1,21 @@ +From ebd924d773223593142d417c41d4ee6fa16f1805 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:45:56 +0200 +Subject: [PATCH] net/dsa/mv88e6xxx: disable ATU violation + +--- + drivers/net/dsa/mv88e6xxx/chip.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3488,6 +3488,9 @@ static int mv88e6xxx_setup_port(struct m + else + reg = 1 << port; + ++ /* Disable ATU member violation interrupt */ ++ reg |= MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG; ++ + err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, + reg); + if (err) diff --git a/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch new file mode 100644 index 0000000000..b0be9dfdcb --- /dev/null +++ b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch @@ -0,0 +1,167 @@ +From ffe387740bbe88dd88bbe04d6375902708003d6e Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:25:00 +0200 +Subject: net: add packet mangeling + +ar8216 switches have a hardware bug, which renders normal 802.1q support +unusable. Packet mangling is required to fix up the vlan for incoming +packets. + +Signed-off-by: Felix Fietkau +--- + include/linux/netdevice.h | 11 +++++++++++ + include/linux/skbuff.h | 14 ++++---------- + net/Kconfig | 6 ++++++ + net/core/dev.c | 20 +++++++++++++++----- + net/core/skbuff.c | 17 +++++++++++++++++ + net/ethernet/eth.c | 6 ++++++ + 6 files changed, 59 insertions(+), 15 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1730,6 +1730,7 @@ enum netdev_priv_flags { + /* was IFF_LIVE_RENAME_OK */ + IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), + IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), ++ IFF_NO_IP_ALIGN = BIT_ULL(33), + }; + + #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN +@@ -1763,6 +1764,7 @@ enum netdev_priv_flags { + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE + #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER + #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR ++#define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN + + /* Specifies the type of the struct net_device::ml_priv pointer */ + enum netdev_ml_priv_type { +@@ -2131,6 +2133,11 @@ struct net_device { + const struct tlsdev_ops *tlsdev_ops; + #endif + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ void (*eth_mangle_rx)(struct net_device *dev, struct sk_buff *skb); ++ struct sk_buff *(*eth_mangle_tx)(struct net_device *dev, struct sk_buff *skb); ++#endif ++ + const struct header_ops *header_ops; + + unsigned char operstate; +@@ -2206,6 +2213,10 @@ struct net_device { + struct mctp_dev __rcu *mctp_ptr; + #endif + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ void *phy_ptr; /* PHY device specific data */ ++#endif ++ + /* + * Cache lines mostly used on receive path (including eth_type_trans()) + */ +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -3040,6 +3040,10 @@ static inline int pskb_trim(struct sk_bu + return (len < skb->len) ? __pskb_trim(skb, len) : 0; + } + ++extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length, gfp_t gfp); ++ ++ + /** + * pskb_trim_unique - remove end from a paged unique (not cloned) buffer + * @skb: buffer to alter +@@ -3189,16 +3193,6 @@ static inline struct sk_buff *dev_alloc_ + } + + +-static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, +- unsigned int length, gfp_t gfp) +-{ +- struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); +- +- if (NET_IP_ALIGN && skb) +- skb_reserve(skb, NET_IP_ALIGN); +- return skb; +-} +- + static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, + unsigned int length) + { +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -26,6 +26,12 @@ menuconfig NET + + if NET + ++config ETHERNET_PACKET_MANGLE ++ bool ++ help ++ This option can be selected by phy drivers that need to mangle ++ packets going in or out of an ethernet device. ++ + config WANT_COMPAT_NETLINK_MESSAGES + bool + help +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3607,6 +3607,11 @@ static int xmit_one(struct sk_buff *skb, + if (dev_nit_active(dev)) + dev_queue_xmit_nit(skb, dev); + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev->eth_mangle_tx && !(skb = dev->eth_mangle_tx(dev, skb))) ++ return NETDEV_TX_OK; ++#endif ++ + len = skb->len; + trace_net_dev_start_xmit(skb, dev); + rc = netdev_start_xmit(skb, dev, txq, more); +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -709,6 +710,22 @@ skb_fail: + } + EXPORT_SYMBOL(__napi_alloc_skb); + ++struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length, gfp_t gfp) ++{ ++ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); ++ ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN)) ++ return skb; ++#endif ++ ++ if (NET_IP_ALIGN && skb) ++ skb_reserve(skb, NET_IP_ALIGN); ++ return skb; ++} ++EXPORT_SYMBOL(__netdev_alloc_skb_ip_align); ++ + void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, + int size, unsigned int truesize) + { +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -171,6 +171,12 @@ __be16 eth_type_trans(struct sk_buff *sk + const struct ethhdr *eth; + + skb->dev = dev; ++ ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev->eth_mangle_rx) ++ dev->eth_mangle_rx(dev, skb); ++#endif ++ + skb_reset_mac_header(skb); + + eth = (struct ethhdr *)skb->data; diff --git a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch new file mode 100644 index 0000000000..faaa40f9bd --- /dev/null +++ b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -0,0 +1,148 @@ +From 5f62951fba63a9f9cfff564209426bdea5fcc371 Mon Sep 17 00:00:00 2001 +From: Alex Marginean +Date: Tue, 27 Aug 2019 15:16:56 +0300 +Subject: [PATCH] drivers: net: phy: aquantia: enable AQR112 and AQR412 + +Adds support for AQR112 and AQR412 which is mostly based on existing code +with the addition of code configuring the protocol on system side. +This allows changing the system side protocol without having to deploy a +different firmware on the PHY. + +Signed-off-by: Alex Marginean +--- + drivers/net/phy/aquantia/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 88 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -27,6 +27,8 @@ + #define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQR813 0x31c31cb2 ++#define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR412 0x03a1b712 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -99,6 +101,29 @@ + #define AQR107_OP_IN_PROG_SLEEP 1000 + #define AQR107_OP_IN_PROG_TIMEOUT 100000 + ++/* registers in MDIO_MMD_VEND1 region */ ++#define AQUANTIA_VND1_GLOBAL_SC 0x000 ++#define AQUANTIA_VND1_GLOBAL_SC_LP BIT(0xb) ++ ++/* global start rate, the protocol associated with this speed is used by default ++ * on SI. ++ */ ++#define AQUANTIA_VND1_GSTART_RATE 0x31a ++#define AQUANTIA_VND1_GSTART_RATE_OFF 0 ++#define AQUANTIA_VND1_GSTART_RATE_100M 1 ++#define AQUANTIA_VND1_GSTART_RATE_1G 2 ++#define AQUANTIA_VND1_GSTART_RATE_10G 3 ++#define AQUANTIA_VND1_GSTART_RATE_2_5G 4 ++#define AQUANTIA_VND1_GSTART_RATE_5G 5 ++ ++/* SYSCFG registers for 100M, 1G, 2.5G, 5G, 10G */ ++#define AQUANTIA_VND1_GSYSCFG_BASE 0x31b ++#define AQUANTIA_VND1_GSYSCFG_100M 0 ++#define AQUANTIA_VND1_GSYSCFG_1G 1 ++#define AQUANTIA_VND1_GSYSCFG_2_5G 2 ++#define AQUANTIA_VND1_GSYSCFG_5G 3 ++#define AQUANTIA_VND1_GSYSCFG_10G 4 ++ + struct aqr107_hw_stat { + const char *name; + int reg; +@@ -230,6 +255,51 @@ static int aqr_config_aneg(struct phy_de + return genphy_c45_check_and_restart_aneg(phydev, changed); + } + ++static struct { ++ u16 syscfg; ++ int cnt; ++ u16 start_rate; ++} aquantia_syscfg[PHY_INTERFACE_MODE_MAX] = { ++ [PHY_INTERFACE_MODE_SGMII] = {0x04b, AQUANTIA_VND1_GSYSCFG_1G, ++ AQUANTIA_VND1_GSTART_RATE_1G}, ++ [PHY_INTERFACE_MODE_2500BASEX] = {0x144, AQUANTIA_VND1_GSYSCFG_2_5G, ++ AQUANTIA_VND1_GSTART_RATE_2_5G}, ++ [PHY_INTERFACE_MODE_XGMII] = {0x100, AQUANTIA_VND1_GSYSCFG_10G, ++ AQUANTIA_VND1_GSTART_RATE_10G}, ++ [PHY_INTERFACE_MODE_USXGMII] = {0x080, AQUANTIA_VND1_GSYSCFG_10G, ++ AQUANTIA_VND1_GSTART_RATE_10G}, ++}; ++ ++/* Sets up protocol on system side before calling aqr_config_aneg */ ++static int aqr_config_aneg_set_prot(struct phy_device *phydev) ++{ ++ int if_type = phydev->interface; ++ int i; ++ ++ if (!aquantia_syscfg[if_type].cnt) ++ return 0; ++ ++ /* set PHY in low power mode so we can configure protocols */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, ++ AQUANTIA_VND1_GLOBAL_SC_LP); ++ mdelay(10); ++ ++ /* set the default rate to enable the SI link */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, ++ aquantia_syscfg[if_type].start_rate); ++ ++ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ AQUANTIA_VND1_GSYSCFG_BASE + i, ++ aquantia_syscfg[if_type].syscfg); ++ ++ /* wake PHY back up */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); ++ mdelay(10); ++ ++ return aqr_config_aneg(phydev); ++} ++ + static int aqr_config_intr(struct phy_device *phydev) + { + bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +@@ -860,6 +930,30 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112), ++ .name = "Aquantia AQR112", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR412), ++ .name = "Aquantia AQR412", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -877,6 +971,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { } + }; + diff --git a/target/linux/generic/hack-6.6/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-6.6/723-net-phy-aquantia-fix-system-side-protocol-mi.patch new file mode 100644 index 0000000000..72a70ebc14 --- /dev/null +++ b/target/linux/generic/hack-6.6/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -0,0 +1,34 @@ +From 5f008cb22f60da4e10375f22266c1a4e20b1252e Mon Sep 17 00:00:00 2001 +From: Alex Marginean +Date: Fri, 20 Sep 2019 18:22:52 +0300 +Subject: [PATCH] drivers: net: phy: aquantia: fix system side protocol + misconfiguration + +Do not set up protocols for speeds that are not supported by FW. Enabling +these protocols leads to link issues on system side. + +Signed-off-by: Alex Marginean +--- + drivers/net/phy/aquantia/aquantia_main.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -288,10 +288,16 @@ static int aqr_config_aneg_set_prot(stru + phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, + aquantia_syscfg[if_type].start_rate); + +- for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) ++ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) { ++ u16 reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ++ AQUANTIA_VND1_GSYSCFG_BASE + i); ++ if (!reg) ++ continue; ++ + phy_write_mmd(phydev, MDIO_MMD_VEND1, + AQUANTIA_VND1_GSYSCFG_BASE + i, + aquantia_syscfg[if_type].syscfg); ++ } + + /* wake PHY back up */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); diff --git a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch new file mode 100644 index 0000000000..d83cc48a33 --- /dev/null +++ b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -0,0 +1,63 @@ +From 3b92ee7b7899b6beffb2b484c58326e36612a873 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 23 Dec 2021 14:52:56 +0000 +Subject: [PATCH] net: phy: aquantia: add PHY_ID for AQR112R + +As advised by Ian Chang this PHY is used in Puzzle devices. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -29,6 +29,8 @@ + #define PHY_ID_AQR813 0x31c31cb2 + #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 ++#define PHY_ID_AQR112C 0x03a1b790 ++#define PHY_ID_AQR112R 0x31c31d12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -960,6 +962,30 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), ++ .name = "Aquantia AQR112C", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112R), ++ .name = "Aquantia AQR112R", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -979,6 +1005,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, + { } + }; + diff --git a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch new file mode 100644 index 0000000000..a2bd3a3dbb --- /dev/null +++ b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch @@ -0,0 +1,53 @@ +From 880d1311335120f64447ca9d11933872d734e19a Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 27 Mar 2023 18:41:54 +0100 +Subject: [PATCH] generic: pcs-mtk-lynxi: add hack to use 2500Base-X without AN + +Using 2500Base-T SFP modules e.g. on the BananaPi R3 requires manually +disabling auto-negotiation, e.g. using ethtool. While a proper fix +using SFP quirks is being discussed upstream, bring a work-around to +restore user experience to what it was before the switch to the +dedicated SGMII PCS driver. + +Signed-off-by: Daniel Golle + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru + struct phylink_link_state *state) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); +- unsigned int bm, adv; ++ unsigned int bm, bmsr, adv; + + /* Read the BMSR and LPA */ + regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); +- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); ++ bmsr = FIELD_GET(SGMII_BMSR, bm); ++ ++ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { ++ state->link = !!(bmsr & BMSR_LSTATUS); ++ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); ++ state->speed = SPEED_2500; ++ state->duplex = DUPLEX_FULL; + +- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), +- FIELD_GET(SGMII_LPA, adv)); ++ return; ++ } ++ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); ++ phylink_mii_c22_pcs_decode_state(state, bmsr, FIELD_GET(SGMII_LPA, adv)); + } + + static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) +@@ -163,7 +172,8 @@ static int mtk_pcs_lynxi_config(struct p + if (neg_mode & PHYLINK_PCS_NEG_INBAND) + sgm_mode |= SGMII_REMOTE_FAULT_DIS; + +- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED && ++ interface != PHY_INTERFACE_MODE_2500BASEX) { + if (interface == PHY_INTERFACE_MODE_SGMII) + sgm_mode |= SGMII_SPEED_DUPLEX_AN; + bmcr = BMCR_ANENABLE; diff --git a/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch new file mode 100644 index 0000000000..48d4626ed6 --- /dev/null +++ b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch @@ -0,0 +1,74 @@ +From 82985725e071f2a5735052f18e109a32aeac3a0b Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 02:38:31 +0200 +Subject: [PATCH] net: usb: r8152: add LED configuration from OF + +This adds the ability to configure the LED configuration register using +OF. This way, the correct value for board specific LED configuration can +be determined. + +Signed-off-by: David Bauer +--- + drivers/net/usb/r8152.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -7034,6 +7035,22 @@ static void rtl_tally_reset(struct r8152 + ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); + } + ++static int r8152_led_configuration(struct r8152 *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->udev->dev.of_node, "realtek,led-data", ++ &led_data); ++ ++ if (ret) ++ return ret; ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data); ++ ++ return 0; ++} ++ + static void r8152b_init(struct r8152 *tp) + { + u32 ocp_data; +@@ -7075,6 +7092,8 @@ static void r8152b_init(struct r8152 *tp + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); + ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); + ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ r8152_led_configuration(tp); + } + + static void r8153_init(struct r8152 *tp) +@@ -7215,6 +7234,8 @@ static void r8153_init(struct r8152 *tp) + tp->coalesce = COALESCE_SLOW; + break; + } ++ ++ r8152_led_configuration(tp); + } + + static void r8153b_init(struct r8152 *tp) +@@ -7297,6 +7318,8 @@ static void r8153b_init(struct r8152 *tp + rtl_tally_reset(tp); + + tp->coalesce = 15000; /* 15 us */ ++ ++ r8152_led_configuration(tp); + } + + static void r8153c_init(struct r8152 *tp) diff --git a/target/linux/generic/hack-6.6/761-dt-bindings-net-add-RTL8152-binding-documentation.patch b/target/linux/generic/hack-6.6/761-dt-bindings-net-add-RTL8152-binding-documentation.patch new file mode 100644 index 0000000000..be262b993c --- /dev/null +++ b/target/linux/generic/hack-6.6/761-dt-bindings-net-add-RTL8152-binding-documentation.patch @@ -0,0 +1,54 @@ +From 3ee05f4aa64fc86af3be5bc176ba5808de9260a7 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 15:30:33 +0200 +Subject: [PATCH] dt-bindings: net: add RTL8152 binding documentation + +Add binding documentation for the Realtek RTL8152 / RTL8153 USB ethernet +adapters. + +Signed-off-by: David Bauer +--- + .../bindings/net/realtek,rtl8152.yaml | 36 +++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/realtek,rtl8152.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/realtek,rtl8152.yaml +@@ -0,0 +1,36 @@ ++# SPDX-License-Identifier: GPL-2.0 ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/realtek,rtl8152.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Realtek RTL8152/RTL8153 series USB ethernet ++ ++maintainers: ++ - David Bauer ++ ++properties: ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - realtek,rtl8152 ++ - realtek,rtl8153 ++ ++ reg: ++ description: The device number on the USB bus ++ ++ realtek,led-data: ++ description: Value to be written to the LED configuration register. ++ ++required: ++ - compatible ++ - reg ++ ++examples: ++ - | ++ usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ realtek,led-data = <0x87>; ++ }; +\ No newline at end of file diff --git a/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch new file mode 100644 index 0000000000..2724efa15e --- /dev/null +++ b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch @@ -0,0 +1,105 @@ +From 94b90966095f3fa625897e8f53d215882f6e19b3 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sat, 11 Mar 2023 17:00:01 +0100 +Subject: [PATCH] mxl-gpy: control LED reg from DT + +Add dynamic configuration for the LED control registers on MXL PHYs. + +This patch has been tested with MaxLinear GPY211C. It is unlikely to be +accepted upstream, as upstream plans on integrating their own framework +for handling these LEDs. + +For the time being, use this hack to configure PHY driven device-LEDs to +show the correct state. + +A possible alternative might be to expose the LEDs using the kernel LED +framework and bind it to the netdevice. This might also be upstreamable, +although it is a considerable extra amount of work. + +Signed-off-by: David Bauer +--- + drivers/net/phy/mxl-gpy.c | 37 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -33,6 +34,7 @@ + #define PHY_MIISTAT 0x18 /* MII state */ + #define PHY_IMASK 0x19 /* interrupt mask */ + #define PHY_ISTAT 0x1A /* interrupt status */ ++#define PHY_LED 0x1B /* LED control */ + #define PHY_FWV 0x1E /* firmware version */ + + #define PHY_MIISTAT_SPD_MASK GENMASK(2, 0) +@@ -56,10 +58,15 @@ + PHY_IMASK_ADSC | \ + PHY_IMASK_ANC) + ++#define PHY_LED_NUM_LEDS 4 ++ + #define PHY_FWV_REL_MASK BIT(15) + #define PHY_FWV_MAJOR_MASK GENMASK(11, 8) + #define PHY_FWV_MINOR_MASK GENMASK(7, 0) + ++/* LED */ ++#define VSPEC1_LED(x) (0x1 + x) ++ + /* SGMII */ + #define VSPEC1_SGMII_CTRL 0x08 + #define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */ +@@ -241,6 +248,35 @@ out: + return ret; + } + ++static int gpy_led_write(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 led_regs[PHY_LED_NUM_LEDS]; ++ int i, ret; ++ u16 val = 0xff00; ++ ++ if (!IS_ENABLED(CONFIG_OF_MDIO)) ++ return 0; ++ ++ if (of_property_read_u32_array(node, "mxl,led-config", led_regs, PHY_LED_NUM_LEDS)) ++ return 0; ++ ++ if (of_property_read_bool(node, "mxl,led-drive-vdd")) ++ val &= 0x0fff; ++ ++ /* Enable LED function handling on all ports*/ ++ phy_write(phydev, PHY_LED, val); ++ ++ /* Write LED register values */ ++ for (i = 0; i < PHY_LED_NUM_LEDS; i++) { ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(i), (u16)led_regs[i]); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int gpy_config_init(struct phy_device *phydev) + { + int ret; +@@ -252,7 +288,10 @@ static int gpy_config_init(struct phy_de + + /* Clear all pending interrupts */ + ret = phy_read(phydev, PHY_ISTAT); +- return ret < 0 ? ret : 0; ++ if (ret < 0) ++ return ret; ++ ++ return gpy_led_write(phydev); + } + + static bool gpy_has_broken_mdint(struct phy_device *phydev) diff --git a/target/linux/generic/hack-6.6/766-net-phy-mediatek-ge-add-LED-configuration-interface.patch b/target/linux/generic/hack-6.6/766-net-phy-mediatek-ge-add-LED-configuration-interface.patch new file mode 100644 index 0000000000..3405d5c535 --- /dev/null +++ b/target/linux/generic/hack-6.6/766-net-phy-mediatek-ge-add-LED-configuration-interface.patch @@ -0,0 +1,72 @@ +From cc225d163b5a4f7a0d1968298bf7927306646a47 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 28 Apr 2023 01:53:01 +0200 +Subject: [PATCH] net: phy: mediatek-ge: add LED configuration interface + +This adds a small hack similar to the one used for ar8xxx switches to +read a reg:value map for configuring the LED configuration registers. + +This allows OpenWrt to write device-specific LED action as well as blink +configurations. It is unlikely to be accepted upstream, as upstream +plans on integrating their own framework for handling these LEDs. + +Signed-off-by: David Bauer +--- + drivers/net/phy/mediatek-ge.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/drivers/net/phy/mediatek-ge.c ++++ b/drivers/net/phy/mediatek-ge.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0+ ++#include + #include + #include + #include +@@ -53,6 +54,36 @@ static int mt7530_phy_config_init(struct + return 0; + } + ++static int mt7530_led_config_of(struct phy_device *phydev) ++{ ++ struct device_node *np = phydev->mdio.dev.of_node; ++ const __be32 *paddr; ++ int len; ++ int i; ++ ++ paddr = of_get_property(np, "mediatek,led-config", &len); ++ if (!paddr) ++ return 0; ++ ++ if (len < (2 * sizeof(*paddr))) ++ return -EINVAL; ++ ++ len /= sizeof(*paddr); ++ ++ phydev_warn(phydev, "Configure LED registers (num=%d)\n", len); ++ for (i = 0; i < len - 1; i += 2) { ++ u32 reg; ++ u32 val; ++ ++ reg = be32_to_cpup(paddr + i); ++ val = be32_to_cpup(paddr + i + 1); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, val); ++ } ++ ++ return 0; ++} ++ + static int mt7531_phy_config_init(struct phy_device *phydev) + { + mtk_gephy_config_init(phydev); +@@ -65,6 +96,9 @@ static int mt7531_phy_config_init(struct + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); + ++ /* LED Config*/ ++ mt7530_led_config_of(phydev); ++ + return 0; + } + diff --git a/target/linux/generic/hack-6.6/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-6.6/773-bgmac-add-srab-switch.patch new file mode 100644 index 0000000000..633cacd1e7 --- /dev/null +++ b/target/linux/generic/hack-6.6/773-bgmac-add-srab-switch.patch @@ -0,0 +1,98 @@ +From 3cb240533ab787899dc7f17aa7d6c5b4810e2e58 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Fri, 7 Jul 2017 17:26:01 +0200 +Subject: bcm53xx: bgmac: use srab switch driver + +use the srab switch driver on these SoCs. + +Signed-off-by: Hauke Mehrtens +--- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 1 + + drivers/net/ethernet/broadcom/bgmac.c | 24 ++++++++++++++++++++++++ + drivers/net/ethernet/broadcom/bgmac.h | 4 ++++ + 3 files changed, 29 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -280,6 +280,7 @@ static int bgmac_probe(struct bcma_devic + bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; + bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; + bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; ++ bgmac->feature_flags |= BGMAC_FEAT_SRAB; + break; + default: + bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1408,6 +1409,17 @@ static const struct ethtool_ops bgmac_et + .set_link_ksettings = phy_ethtool_set_link_ksettings, + }; + ++static struct b53_platform_data bgmac_b53_pdata = { ++}; ++ ++static struct platform_device bgmac_b53_dev = { ++ .name = "b53-srab-switch", ++ .id = -1, ++ .dev = { ++ .platform_data = &bgmac_b53_pdata, ++ }, ++}; ++ + /************************************************** + * MII + **************************************************/ +@@ -1546,6 +1558,14 @@ int bgmac_enet_probe(struct bgmac *bgmac + + bgmac->in_init = false; + ++ if ((bgmac->feature_flags & BGMAC_FEAT_SRAB) && !bgmac_b53_pdata.regs) { ++ bgmac_b53_pdata.regs = ioremap(0x18007000, 0x1000); ++ ++ err = platform_device_register(&bgmac_b53_dev); ++ if (!err) ++ bgmac->b53_device = &bgmac_b53_dev; ++ } ++ + err = register_netdev(bgmac->net_dev); + if (err) { + dev_err(bgmac->dev, "Cannot register net device\n"); +@@ -1568,6 +1588,10 @@ EXPORT_SYMBOL_GPL(bgmac_enet_probe); + + void bgmac_enet_remove(struct bgmac *bgmac) + { ++ if (bgmac->b53_device) ++ platform_device_unregister(&bgmac_b53_dev); ++ bgmac->b53_device = NULL; ++ + unregister_netdev(bgmac->net_dev); + phy_disconnect(bgmac->net_dev->phydev); + netif_napi_del(&bgmac->napi); +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -388,6 +388,7 @@ + #define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18) + #define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19) + #define BGMAC_FEAT_IDM_MASK BIT(20) ++#define BGMAC_FEAT_SRAB BIT(21) + + struct bgmac_slot_info { + union { +@@ -495,6 +496,9 @@ struct bgmac { + void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask, + u32 set); + int (*phy_connect)(struct bgmac *bgmac); ++ ++ /* platform device for associated switch */ ++ struct platform_device *b53_device; + }; + + struct bgmac *bgmac_alloc(struct device *dev); diff --git a/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch new file mode 100644 index 0000000000..51f939356f --- /dev/null +++ b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch @@ -0,0 +1,69 @@ +From f81700b6bb2eda3756247bce472d8eaf6f466f61 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:49:26 +0200 +Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support + +--- + drivers/net/usb/qmi_wwan.c | 1 + + drivers/usb/serial/option.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1082,12 +1082,18 @@ static const struct usb_device_id produc + USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), + .driver_info = (unsigned long)&qmi_wwan_info, + }, ++ { /* Meiglink SGM828 */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d49, USB_CLASS_VENDOR_SPEC, 0x10, 0x05), ++ .driver_info = (unsigned long)&qmi_wwan_info, ++ }, ++ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */ ++ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* MeigLink SLM750 */ + + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -247,6 +247,11 @@ static void option_instat_callback(struc + #define UBLOX_PRODUCT_R410M 0x90b2 + /* These Yuga products use Qualcomm's vendor ID */ + #define YUGA_PRODUCT_CLM920_NC5 0x9625 ++/* These MeigLink products use Qualcomm's vendor ID */ ++#define MEIGLINK_PRODUCT_SLM750 0xf601 ++ ++#define MEIGLINK_VENDOR_ID 0x2dee ++#define MEIGLINK_PRODUCT_SLM828 0x4d49 + + #define QUECTEL_VENDOR_ID 0x2c7c + /* These Quectel products use Quectel's vendor ID */ +@@ -1147,6 +1152,11 @@ static const struct usb_device_id option + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ + .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, ++ /* MeiG */ ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGLINK_VENDOR_ID, MEIGLINK_PRODUCT_SLM828, USB_CLASS_VENDOR_SPEC, 0x10, 0x01) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGLINK_VENDOR_ID, MEIGLINK_PRODUCT_SLM828, USB_CLASS_VENDOR_SPEC, 0x10, 0x02) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGLINK_VENDOR_ID, MEIGLINK_PRODUCT_SLM828, USB_CLASS_VENDOR_SPEC, 0x10, 0x03) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGLINK_VENDOR_ID, MEIGLINK_PRODUCT_SLM828, USB_CLASS_VENDOR_SPEC, 0x10, 0x04) }, + /* Quectel products using Qualcomm vendor ID */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, + { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), +@@ -1188,6 +1198,11 @@ static const struct usb_device_id option + .driver_info = ZLP }, + { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), + .driver_info = RSVD(4) }, ++ /* Meiglink products using Qualcomm vendor ID */ ++ // Works OK. In case of some issues check macros that are used by Quectel Products ++ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0xff, 0xff), ++ .driver_info = NUMEP2 }, ++ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), + .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, diff --git a/target/linux/generic/hack-6.6/781-usb-net-rndis-support-asr.patch b/target/linux/generic/hack-6.6/781-usb-net-rndis-support-asr.patch new file mode 100644 index 0000000000..9934bb8078 --- /dev/null +++ b/target/linux/generic/hack-6.6/781-usb-net-rndis-support-asr.patch @@ -0,0 +1,56 @@ +--- a/drivers/net/usb/rndis_host.c ++++ b/drivers/net/usb/rndis_host.c +@@ -630,6 +630,16 @@ static const struct driver_info zte_rndi + .tx_fixup = rndis_tx_fixup, + }; + ++static const struct driver_info asr_rndis_info = { ++ .description = "Asr RNDIS device", ++ .flags = FLAG_WWAN | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT | FLAG_NOARP, ++ .bind = rndis_bind, ++ .unbind = rndis_unbind, ++ .status = rndis_status, ++ .rx_fixup = rndis_rx_fixup, ++ .tx_fixup = rndis_tx_fixup, ++}; ++ + /*-------------------------------------------------------------------------*/ + + static const struct usb_device_id products [] = { +@@ -666,6 +676,36 @@ static const struct usb_device_id produc + USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), + .driver_info = (unsigned long) &rndis_info, + }, { ++ /* Quectel EG060V rndis device */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x6004, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { ++ /* Quectel EC200A rndis device */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x6005, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { ++ /* Quectel EC200T rndis device */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x6026, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { ++ /* Simcom A7906E rndis device */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x1e0e, 0x9011, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { ++ /* Meig SLM770A */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d57, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { ++ /* Meig SLM828 */ ++ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d49, ++ USB_CLASS_WIRELESS_CONTROLLER, 1, 3), ++ .driver_info = (unsigned long) &asr_rndis_info, ++}, { + /* Novatel Verizon USB730L */ + USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1), + .driver_info = (unsigned long) &rndis_info, diff --git a/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch new file mode 100644 index 0000000000..bb21bb39d3 --- /dev/null +++ b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch @@ -0,0 +1,63 @@ +From 7cc39a6bedbd85f3ff7e16845f310e4ce8d9833f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 6 Sep 2022 00:31:19 +0100 +Subject: [PATCH] net: sfp: add quirk for ATS SFP-GE-T 1000Base-TX module +To: netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, + Russell King , + Andrew Lunn , + Heiner Kallweit +Cc: David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Josef Schlehofer + +This copper module comes with broken TX_FAULT indicator which must be +ignored for it to work. Implement ignoring TX_FAULT state bit also +during reset/insertion and mute the warning telling the user that the +module indicates TX_FAULT. + +Co-authored-by: Josef Schlehofer +Signed-off-by: Daniel Golle +--- + drivers/net/phy/sfp.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -409,6 +409,9 @@ static const struct sfp_quirk sfp_quirks + SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex, + sfp_fixup_ignore_tx_fault), + ++ // OEM SFP-GE-T is 1000Base-T module ++ SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault), ++ + // Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report + // 2500MBd NRZ in their EEPROM + SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex), +@@ -2344,7 +2347,8 @@ static void sfp_sm_main(struct sfp *sfp, + * or t_start_up, so assume there is a fault. + */ + sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, +- sfp->sm_fault_retries == N_FAULT_INIT); ++ !sfp->tx_fault_ignore && ++ (sfp->sm_fault_retries == N_FAULT_INIT)); + } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) { + init_done: + /* Create mdiobus and start trying for PHY */ +@@ -2578,10 +2582,12 @@ static void sfp_check_state(struct sfp * + mutex_lock(&sfp->st_mutex); + state = sfp_get_state(sfp); + changed = state ^ sfp->state; +- if (sfp->tx_fault_ignore) ++ if (sfp->tx_fault_ignore) { + changed &= SFP_F_PRESENT | SFP_F_LOS; +- else ++ state &= ~SFP_F_TX_FAULT; ++ } else { + changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; ++ } + + for (i = 0; i < GPIO_MAX; i++) + if (changed & BIT(i)) diff --git a/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch new file mode 100644 index 0000000000..b60b428dc8 --- /dev/null +++ b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,190 @@ +From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 30/36] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + #include "gpiolib-of.h" +@@ -1030,3 +1032,100 @@ void of_gpio_dev_init(struct gpio_chip * + else + gc->of_node = gdev->dev.of_node; + } ++ ++#ifdef CONFIG_GPIO_SYSFS ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ struct gpio_desc *desc; ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags & OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) { ++ if (of_flags & OF_GPIO_SINGLE_ENDED) { ++ /* ++ * As gpiod_direction_output_raw() is used, we ++ * need to emulate open drain or open source here. ++ */ ++ if (of_flags & OF_GPIO_OPEN_DRAIN) { ++ flags |= GPIOF_OPEN_DRAIN; ++ flags |= val ? GPIOF_IN : GPIOF_OUT_INIT_LOW; ++ } else { ++ flags |= GPIOF_OPEN_SOURCE; ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_IN; ++ } ++ } else { ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ } ++ } else { ++ flags |= GPIOF_IN; ++ } ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ /* ++ * When emulating open-source or open-drain functionalities by not ++ * actively driving the line (setting mode to input) we still need to ++ * set the IS_OUT flag or otherwise we won't be able to set the line ++ * value anymore. ++ */ ++ if ((flags & GPIOF_IN) && ++ ((flags & GPIOF_OPEN_DRAIN) || (flags & GPIOF_OPEN_SOURCE))) { ++ desc = gpio_to_desc(gpio); ++ set_bit(FLAG_IS_OUT, &desc->flags); ++ } ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); ++ ++#endif +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -125,6 +125,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -715,6 +715,7 @@ static inline struct gpio_desc *acpi_get + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -547,7 +547,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -609,6 +609,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -630,6 +632,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) diff --git a/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch b/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch new file mode 100644 index 0000000000..c581a512cb --- /dev/null +++ b/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch @@ -0,0 +1,187 @@ +From e4d708702e6c98f2111e33201a264d6788564cb2 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Fri, 12 May 2023 11:08:43 +0200 +Subject: [PATCH] ssb_sprom: add generic kernel support for Broadcom Fallback SPROMs + +--- + drivers/bcma/Kconfig | 4 ++++ + drivers/bcma/Makefile | 1 + + drivers/bcma/bcma_private.h | 4 ++++ + drivers/bcma/main.c | 8 ++++++++ + drivers/bcma/sprom.c | 23 ++++++++++++++--------- + drivers/ssb/Kconfig | 5 +++++ + drivers/ssb/Makefile | 1 + + drivers/ssb/main.c | 8 ++++++++ + drivers/ssb/sprom.c | 12 +++++++++++- + drivers/ssb/ssb_private.h | 4 ++++ + 10 files changed, 60 insertions(+), 10 deletions(-) + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -18,6 +18,10 @@ config BCMA_BLOCKIO + bool + default y + ++config BCMA_FALLBACK_SPROM ++ bool ++ default y ++ + config BCMA_HOST_PCI_POSSIBLE + bool + depends on PCI = y +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -11,6 +11,7 @@ bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o + bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o ++bcma-$(CONFIG_BCMA_FALLBACK_SPROM) += fallback-sprom.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o + bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o + obj-$(CONFIG_BCMA) += bcma.o +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -38,6 +38,10 @@ int bcma_bus_resume(struct bcma_bus *bus + void bcma_detect_chip(struct bcma_bus *bus); + int bcma_bus_scan(struct bcma_bus *bus); + ++/* fallback-sprom.c */ ++int __init bcma_fbs_register(void); ++int bcma_get_fallback_sprom(struct bcma_bus *dev, struct ssb_sprom *out); ++ + /* sprom.c */ + int bcma_sprom_get(struct bcma_bus *bus); + +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -668,6 +668,14 @@ static int __init bcma_modinit(void) + { + int err; + ++#ifdef CONFIG_BCMA_FALLBACK_SPROM ++ err = bcma_fbs_register(); ++ if (err) { ++ pr_err("Fallback SPROM initialization failed\n"); ++ err = 0; ++ } ++#endif /* CONFIG_BCMA_FALLBACK_SPROM */ ++ + err = bcma_init_bus_register(); + if (err) + return err; +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -51,21 +51,26 @@ static int bcma_fill_sprom_with_fallback + { + int err; + +- if (!get_fallback_sprom) { ++ if (get_fallback_sprom) ++ err = get_fallback_sprom(bus, out); ++ ++#ifdef CONFIG_BCMA_FALLBACK_SPROM ++ if (!get_fallback_sprom || err) ++ err = bcma_get_fallback_sprom(bus, out); ++#else ++ if (!get_fallback_sprom) + err = -ENOENT; +- goto fail; +- } ++#endif /* CONFIG_BCMA_FALLBACK_SPROM */ + +- err = get_fallback_sprom(bus, out); +- if (err) +- goto fail; ++ if (err) { ++ bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err); ++ return err; ++ } + + bcma_debug(bus, "Using SPROM revision %d provided by platform.\n", + bus->sprom.revision); ++ + return 0; +-fail: +- bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err); +- return err; + } + + /************************************************** +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -25,6 +25,11 @@ if SSB + config SSB_SPROM + bool + ++config SSB_FALLBACK_SPROM ++ bool ++ depends on SSB_PCIHOST ++ default y ++ + # Support for Block-I/O. SELECT this from the driver that needs it. + config SSB_BLOCKIO + bool +--- a/drivers/ssb/Makefile ++++ b/drivers/ssb/Makefile +@@ -2,6 +2,7 @@ + # core + ssb-y += main.o scan.o + ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o ++ssb-$(CONFIG_SSB_FALLBACK_SPROM) += fallback-sprom.o + ssb-$(CONFIG_SSB_SPROM) += sprom.o + + # host support +--- a/drivers/ssb/main.c ++++ b/drivers/ssb/main.c +@@ -1287,6 +1287,14 @@ static int __init ssb_modinit(void) + { + int err; + ++#ifdef CONFIG_SSB_FALLBACK_SPROM ++ err = ssb_fbs_register(); ++ if (err) { ++ pr_err("Fallback SPROM initialization failed\n"); ++ err = 0; ++ } ++#endif /* CONFIG_SSB_FALLBACK_SPROM */ ++ + /* See the comment at the ssb_is_early_boot definition */ + ssb_is_early_boot = 0; + err = bus_register(&ssb_bustype); +--- a/drivers/ssb/sprom.c ++++ b/drivers/ssb/sprom.c +@@ -180,10 +180,20 @@ int ssb_arch_register_fallback_sprom(int + + int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, struct ssb_sprom *out) + { ++ int err; ++ ++ if (get_fallback_sprom) ++ err = get_fallback_sprom(bus, out); ++ ++#ifdef CONFIG_SSB_FALLBACK_SPROM ++ if (!get_fallback_sprom || err) ++ err = ssb_get_fallback_sprom(bus, out); ++#else + if (!get_fallback_sprom) + return -ENOENT; ++#endif /* CONFIG_SSB_FALLBACK_SPROM */ + +- return get_fallback_sprom(bus, out); ++ return err; + } + + /* https://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ +--- a/drivers/ssb/ssb_private.h ++++ b/drivers/ssb/ssb_private.h +@@ -143,6 +143,10 @@ extern int ssb_bus_scan(struct ssb_bus * + extern void ssb_iounmap(struct ssb_bus *ssb); + + ++/* fallback-sprom.c */ ++int __init ssb_fbs_register(void); ++int ssb_get_fallback_sprom(struct ssb_bus *dev, struct ssb_sprom *out); ++ + /* sprom.c */ + extern + ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf, diff --git a/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch new file mode 100644 index 0000000000..ec71f9af4b --- /dev/null +++ b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch @@ -0,0 +1,174 @@ +From 3b6115d6b57a263bdc8c9b1df273bd4a7955eead Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:16:31 +0200 +Subject: debloat: add some debloat patches, strip down procfs and make O_DIRECT support optional, saves ~15K after lzma on MIPS + +Signed-off-by: Felix Fietkau +--- + net/Kconfig | 3 +++ + net/core/Makefile | 3 ++- + net/core/sock.c | 2 ++ + net/ipv4/Kconfig | 1 + + net/netlink/Kconfig | 1 + + net/packet/Kconfig | 1 + + net/unix/Kconfig | 1 + + 7 files changed, 11 insertions(+), 1 deletion(-) + +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -104,6 +104,9 @@ source "net/mptcp/Kconfig" + + endif # if INET + ++config SOCK_DIAG ++ bool ++ + config NETWORK_SECMARK + bool "Security Marking" + help +--- a/net/core/Makefile ++++ b/net/core/Makefile +@@ -11,11 +11,12 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core. + + obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ + neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ +- sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ ++ dev_ioctl.o tso.o sock_reuseport.o \ + fib_notifier.o xdp.o flow_offload.o gro.o + + obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o + ++obj-$(CONFIG_SOCK_DIAG) += sock_diag.o + obj-y += net-sysfs.o + obj-$(CONFIG_PAGE_POOL) += page_pool.o + obj-$(CONFIG_PROC_FS) += net-procfs.o +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -115,6 +115,7 @@ + #include + #include + #include ++#include + + #include + +@@ -146,6 +147,7 @@ + + static DEFINE_MUTEX(proto_list_mutex); + static LIST_HEAD(proto_list); ++DEFINE_COOKIE(sock_cookie); + + static void sock_def_write_space_wfree(struct sock *sk); + static void sock_def_write_space(struct sock *sk); +@@ -585,6 +587,18 @@ discard_and_relse: + } + EXPORT_SYMBOL(__sk_receive_skb); + ++u64 __sock_gen_cookie(struct sock *sk) ++{ ++ while (1) { ++ u64 res = atomic64_read(&sk->sk_cookie); ++ ++ if (res) ++ return res; ++ res = gen_cookie_next(&sock_cookie); ++ atomic64_cmpxchg(&sk->sk_cookie, 0, res); ++ } ++} ++ + INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, + u32)); + INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, +@@ -2188,9 +2202,11 @@ static void __sk_free(struct sock *sk) + if (likely(sk->sk_net_refcnt)) + sock_inuse_add(sock_net(sk), -1); + ++#ifdef CONFIG_SOCK_DIAG + if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk))) + sock_diag_broadcast_destroy(sk); + else ++#endif + sk_destruct(sk); + } + +--- a/net/core/sock_diag.c ++++ b/net/core/sock_diag.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -21,20 +20,6 @@ static int (*inet_rcv_compat)(struct sk_ + static DEFINE_MUTEX(sock_diag_table_mutex); + static struct workqueue_struct *broadcast_wq; + +-DEFINE_COOKIE(sock_cookie); +- +-u64 __sock_gen_cookie(struct sock *sk) +-{ +- while (1) { +- u64 res = atomic64_read(&sk->sk_cookie); +- +- if (res) +- return res; +- res = gen_cookie_next(&sock_cookie); +- atomic64_cmpxchg(&sk->sk_cookie, 0, res); +- } +-} +- + int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie) + { + u64 res; +--- a/net/ipv4/Kconfig ++++ b/net/ipv4/Kconfig +@@ -423,6 +423,7 @@ config INET_TUNNEL + + config INET_DIAG + tristate "INET: socket monitoring interface" ++ select SOCK_DIAG + default y + help + Support for INET (TCP, DCCP, etc) socket monitoring interface used by +--- a/net/netlink/Kconfig ++++ b/net/netlink/Kconfig +@@ -5,6 +5,7 @@ + + config NETLINK_DIAG + tristate "NETLINK: socket monitoring interface" ++ select SOCK_DIAG + default n + help + Support for NETLINK socket monitoring interface used by the ss tool. +--- a/net/packet/Kconfig ++++ b/net/packet/Kconfig +@@ -19,6 +19,7 @@ config PACKET + config PACKET_DIAG + tristate "Packet: sockets monitoring interface" + depends on PACKET ++ select SOCK_DIAG + default n + help + Support for PF_PACKET sockets monitoring interface used by the ss tool. +--- a/net/unix/Kconfig ++++ b/net/unix/Kconfig +@@ -33,6 +33,7 @@ config AF_UNIX_OOB + config UNIX_DIAG + tristate "UNIX: socket monitoring interface" + depends on UNIX ++ select SOCK_DIAG + default n + help + Support for UNIX socket monitoring interface used by the ss tool. +--- a/net/xdp/Kconfig ++++ b/net/xdp/Kconfig +@@ -10,6 +10,7 @@ config XDP_SOCKETS + config XDP_SOCKETS_DIAG + tristate "XDP sockets: monitoring interface" + depends on XDP_SOCKETS ++ select SOCK_DIAG + default n + help + Support for PF_XDP sockets monitoring interface used by the ss tool. diff --git a/target/linux/generic/hack-6.6/902-debloat_proc.patch b/target/linux/generic/hack-6.6/902-debloat_proc.patch new file mode 100644 index 0000000000..a90169efc9 --- /dev/null +++ b/target/linux/generic/hack-6.6/902-debloat_proc.patch @@ -0,0 +1,419 @@ +From 9e3f1d0805b2d919904dd9a4ff0d956314cc3cba Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:20:09 +0200 +Subject: debloat: procfs + +Signed-off-by: Felix Fietkau +--- + fs/locks.c | 2 ++ + fs/proc/Kconfig | 5 +++++ + fs/proc/consoles.c | 3 +++ + fs/proc/proc_tty.c | 11 ++++++++++- + include/net/snmp.h | 18 +++++++++++++++++- + ipc/msg.c | 3 +++ + ipc/sem.c | 2 ++ + ipc/shm.c | 2 ++ + ipc/util.c | 3 +++ + kernel/exec_domain.c | 2 ++ + kernel/irq/proc.c | 9 +++++++++ + kernel/time/timer_list.c | 2 ++ + mm/vmalloc.c | 2 ++ + mm/vmstat.c | 8 +++++--- + net/8021q/vlanproc.c | 6 ++++++ + net/core/net-procfs.c | 18 ++++++++++++------ + net/core/sock.c | 2 ++ + net/ipv4/fib_trie.c | 18 ++++++++++++------ + net/ipv4/proc.c | 3 +++ + net/ipv4/route.c | 3 +++ + 20 files changed, 105 insertions(+), 17 deletions(-) + +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2909,6 +2909,8 @@ static const struct seq_operations locks + + static int __init proc_locks_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + proc_create_seq_private("locks", 0, NULL, &locks_seq_operations, + sizeof(struct locks_iterator), NULL); + return 0; +--- a/fs/proc/Kconfig ++++ b/fs/proc/Kconfig +@@ -101,6 +101,11 @@ config PROC_CHILDREN + Say Y if you are running any user-space software which takes benefit from + this interface. For example, rkt is such a piece of software. + ++config PROC_STRIPPED ++ default n ++ depends on EXPERT ++ bool "Strip non-essential /proc functionality to reduce code size" ++ + config PROC_PID_ARCH_STATUS + def_bool n + depends on PROC_FS +--- a/fs/proc/consoles.c ++++ b/fs/proc/consoles.c +@@ -92,6 +92,9 @@ static const struct seq_operations conso + + static int __init proc_consoles_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + proc_create_seq("consoles", 0, NULL, &consoles_op); + return 0; + } +--- a/fs/proc/proc_tty.c ++++ b/fs/proc/proc_tty.c +@@ -131,7 +131,10 @@ static const struct seq_operations tty_d + void proc_tty_register_driver(struct tty_driver *driver) + { + struct proc_dir_entry *ent; +- ++ ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (!driver->driver_name || driver->proc_entry || + !driver->ops->proc_show) + return; +@@ -148,6 +151,9 @@ void proc_tty_unregister_driver(struct t + { + struct proc_dir_entry *ent; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + ent = driver->proc_entry; + if (!ent) + return; +@@ -162,6 +168,9 @@ void proc_tty_unregister_driver(struct t + */ + void __init proc_tty_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (!proc_mkdir("tty", NULL)) + return; + proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */ +--- a/include/net/snmp.h ++++ b/include/net/snmp.h +@@ -124,6 +124,21 @@ struct linux_tls_mib { + #define DECLARE_SNMP_STAT(type, name) \ + extern __typeof__(type) __percpu *name + ++#ifdef CONFIG_PROC_STRIPPED ++#define __SNMP_STATS_DUMMY(mib) \ ++ do { (void) mib->mibs[0]; } while(0) ++ ++#define __SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_DEC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define __SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) ++#define SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) ++#define SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) ++#define __SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) ++ ++#else ++ + #define __SNMP_INC_STATS(mib, field) \ + __this_cpu_inc(mib->mibs[field]) + +@@ -154,8 +169,9 @@ struct linux_tls_mib { + __this_cpu_add(ptr[basefield##OCTETS], addend); \ + } while (0) + ++#endif + +-#if BITS_PER_LONG==32 ++#if (BITS_PER_LONG==32) && !defined(CONFIG_PROC_STRIPPED) + + #define __SNMP_ADD_STATS64(mib, field, addend) \ + do { \ +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -1370,6 +1370,9 @@ void __init msg_init(void) + { + msg_init_ns(&init_ipc_ns); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + ipc_init_proc_interface("sysvipc/msg", + " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", + IPC_MSG_IDS, sysvipc_msg_proc_show); +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -268,6 +268,8 @@ void sem_exit_ns(struct ipc_namespace *n + void __init sem_init(void) + { + sem_init_ns(&init_ipc_ns); ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; + ipc_init_proc_interface("sysvipc/sem", + " key semid perms nsems uid gid cuid cgid otime ctime\n", + IPC_SEM_IDS, sysvipc_sem_proc_show); +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -154,6 +154,8 @@ pure_initcall(ipc_ns_init); + + void __init shm_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; + ipc_init_proc_interface("sysvipc/shm", + #if BITS_PER_LONG <= 32 + " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n", +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -141,6 +141,9 @@ void __init ipc_init_proc_interface(cons + struct proc_dir_entry *pde; + struct ipc_proc_iface *iface; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + iface = kmalloc(sizeof(*iface), GFP_KERNEL); + if (!iface) + return; +--- a/kernel/exec_domain.c ++++ b/kernel/exec_domain.c +@@ -29,6 +29,8 @@ static int execdomains_proc_show(struct + + static int __init proc_execdomains_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + proc_create_single("execdomains", 0, NULL, execdomains_proc_show); + return 0; + } +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -341,6 +341,9 @@ void register_irq_proc(unsigned int irq, + void __maybe_unused *irqp = (void *)(unsigned long) irq; + char name [MAX_NAMELEN]; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) + return; + +@@ -394,6 +397,9 @@ void unregister_irq_proc(unsigned int ir + { + char name [MAX_NAMELEN]; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + if (!root_irq_dir || !desc->dir) + return; + #ifdef CONFIG_SMP +@@ -432,6 +438,9 @@ void init_irq_proc(void) + unsigned int irq; + struct irq_desc *desc; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", NULL); + if (!root_irq_dir) +--- a/kernel/time/timer_list.c ++++ b/kernel/time/timer_list.c +@@ -350,6 +350,8 @@ static int __init init_timer_list_procfs + { + struct proc_dir_entry *pe; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + pe = proc_create_seq_private("timer_list", 0400, NULL, &timer_list_sops, + sizeof(struct timer_list_iter), NULL); + if (!pe) +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -4205,6 +4205,8 @@ static const struct seq_operations vmall + + static int __init proc_vmalloc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + if (IS_ENABLED(CONFIG_NUMA)) + proc_create_seq_private("vmallocinfo", 0400, NULL, + &vmalloc_op, +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -2109,10 +2109,12 @@ void __init init_mm_internals(void) + start_shepherd_timer(); + #endif + #ifdef CONFIG_PROC_FS +- proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op); +- proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op); ++ proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op); ++ proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op); ++ } + proc_create_seq("vmstat", 0444, NULL, &vmstat_op); +- proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op); + #endif + } + +--- a/net/8021q/vlanproc.c ++++ b/net/8021q/vlanproc.c +@@ -93,6 +93,9 @@ void vlan_proc_cleanup(struct net *net) + { + struct vlan_net *vn = net_generic(net, vlan_net_id); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (vn->proc_vlan_conf) + remove_proc_entry(name_conf, vn->proc_vlan_dir); + +@@ -112,6 +115,9 @@ int __net_init vlan_proc_init(struct net + { + struct vlan_net *vn = net_generic(net, vlan_net_id); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net); + if (!vn->proc_vlan_dir) + goto err; +--- a/net/core/net-procfs.c ++++ b/net/core/net-procfs.c +@@ -319,10 +319,12 @@ static int __net_init dev_proc_net_init( + if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops, + sizeof(struct seq_net_private))) + goto out; +- if (!proc_create_seq("softnet_stat", 0444, net->proc_net, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_seq("softnet_stat", 0444, net->proc_net, + &softnet_seq_ops)) + goto out_dev; +- if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, + sizeof(struct seq_net_private))) + goto out_softnet; + +@@ -332,9 +334,11 @@ static int __net_init dev_proc_net_init( + out: + return rc; + out_ptype: +- remove_proc_entry("ptype", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("ptype", net->proc_net); + out_softnet: +- remove_proc_entry("softnet_stat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("softnet_stat", net->proc_net); + out_dev: + remove_proc_entry("dev", net->proc_net); + goto out; +@@ -344,8 +348,10 @@ static void __net_exit dev_proc_net_exit + { + wext_proc_exit(net); + +- remove_proc_entry("ptype", net->proc_net); +- remove_proc_entry("softnet_stat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ remove_proc_entry("ptype", net->proc_net); ++ remove_proc_entry("softnet_stat", net->proc_net); ++ } + remove_proc_entry("dev", net->proc_net); + } + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -4114,6 +4114,8 @@ static __net_initdata struct pernet_oper + + static int __init proto_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + return register_pernet_subsys(&proto_net_ops); + } + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -3036,11 +3036,13 @@ static const struct seq_operations fib_r + + int __net_init fib_proc_init(struct net *net) + { +- if (!proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops, + sizeof(struct fib_trie_iter))) + goto out1; + +- if (!proc_create_net_single("fib_triestat", 0444, net->proc_net, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net_single("fib_triestat", 0444, net->proc_net, + fib_triestat_seq_show, NULL)) + goto out2; + +@@ -3051,17 +3053,21 @@ int __net_init fib_proc_init(struct net + return 0; + + out3: +- remove_proc_entry("fib_triestat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("fib_triestat", net->proc_net); + out2: +- remove_proc_entry("fib_trie", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("fib_trie", net->proc_net); + out1: + return -ENOMEM; + } + + void __net_exit fib_proc_exit(struct net *net) + { +- remove_proc_entry("fib_trie", net->proc_net); +- remove_proc_entry("fib_triestat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ remove_proc_entry("fib_trie", net->proc_net); ++ remove_proc_entry("fib_triestat", net->proc_net); ++ } + remove_proc_entry("route", net->proc_net); + } + +--- a/net/ipv4/proc.c ++++ b/net/ipv4/proc.c +@@ -553,5 +553,8 @@ static __net_initdata struct pernet_oper + + int __init ip_misc_proc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + return register_pernet_subsys(&ip_proc_ops); + } +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -380,6 +380,9 @@ static struct pernet_operations ip_rt_pr + + static int __init ip_rt_proc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + return register_pernet_subsys(&ip_rt_proc_ops); + } + +--- a/net/ipv4/inet_timewait_sock.c ++++ b/net/ipv4/inet_timewait_sock.c +@@ -269,7 +269,7 @@ void __inet_twsk_schedule(struct inet_ti + */ + + if (!rearm) { +- bool kill = timeo <= 4*HZ; ++ bool __maybe_unused kill = timeo <= 4*HZ; + + __NET_INC_STATS(twsk_net(tw), kill ? LINUX_MIB_TIMEWAITKILLED : + LINUX_MIB_TIMEWAITED); diff --git a/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch new file mode 100644 index 0000000000..105eb3da4b --- /dev/null +++ b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch @@ -0,0 +1,93 @@ +From e3692cb2fcd5ba1244512a0f43b8118f65f1c375 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:20:43 +0200 +Subject: debloat: dmabuf + +Signed-off-by: Felix Fietkau +--- + drivers/base/Kconfig | 2 +- + drivers/dma-buf/Makefile | 10 +++++++--- + drivers/dma-buf/dma-buf.c | 4 +++- + kernel/sched/core.c | 1 + + 4 files changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -198,7 +198,7 @@ config SOC_BUS + source "drivers/base/regmap/Kconfig" + + config DMA_SHARED_BUFFER +- bool ++ tristate + default n + select IRQ_WORK + help +--- a/drivers/dma-buf/heaps/Makefile ++++ b/drivers/dma-buf/heaps/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 +-obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +-obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o +--- a/drivers/dma-buf/Makefile ++++ b/drivers/dma-buf/Makefile +@@ -1,12 +1,14 @@ + # SPDX-License-Identifier: GPL-2.0-only +-obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ ++obj-$(CONFIG_DMA_SHARED_BUFFER) := dma-shared-buffer.o ++ ++dma-buf-objs-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ + dma-fence-unwrap.o dma-resv.o +-obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o +-obj-$(CONFIG_DMABUF_HEAPS) += heaps/ +-obj-$(CONFIG_SYNC_FILE) += sync_file.o +-obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o +-obj-$(CONFIG_UDMABUF) += udmabuf.o +-obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS) += dma-heap.o ++obj-$(CONFIG_DMABUF_HEAPS) += heaps/ ++dma-buf-objs-$(CONFIG_SYNC_FILE) += sync_file.o ++dma-buf-objs-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o ++dma-buf-objs-$(CONFIG_UDMABUF) += udmabuf.o ++dma-buf-objs-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o + + dmabuf_selftests-y := \ + selftest.o \ +@@ -15,4 +17,6 @@ dmabuf_selftests-y := \ + st-dma-fence-unwrap.o \ + st-dma-resv.o + +-obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o ++dma-buf-objs-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o ++ ++dma-shared-buffer-objs := $(dma-buf-objs-y) +--- a/drivers/dma-buf/dma-buf.c ++++ b/drivers/dma-buf/dma-buf.c +@@ -1636,4 +1636,5 @@ static void __exit dma_buf_deinit(void) + kern_unmount(dma_buf_mnt); + dma_buf_uninit_sysfs_statistics(); + } +-__exitcall(dma_buf_deinit); ++module_exit(dma_buf_deinit); ++MODULE_LICENSE("GPL"); +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -4367,6 +4367,7 @@ int wake_up_state(struct task_struct *p, + { + return try_to_wake_up(p, state, 0); + } ++EXPORT_SYMBOL_GPL(wake_up_state); + + /* + * Perform scheduler related setup for a newly forked process p. +--- a/fs/d_path.c ++++ b/fs/d_path.c +@@ -313,6 +313,7 @@ char *dynamic_dname(char *buffer, int bu + buffer += buflen - sz; + return memcpy(buffer, temp, sz); + } ++EXPORT_SYMBOL_GPL(dynamic_dname); + + char *simple_dname(struct dentry *dentry, char *buffer, int buflen) + { diff --git a/target/linux/generic/hack-6.6/910-kobject_uevent.patch b/target/linux/generic/hack-6.6/910-kobject_uevent.patch new file mode 100644 index 0000000000..c4c41ca400 --- /dev/null +++ b/target/linux/generic/hack-6.6/910-kobject_uevent.patch @@ -0,0 +1,32 @@ +From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 16 Jul 2017 16:56:10 +0200 +Subject: lib: add uevent_next_seqnum() + +Signed-off-by: Felix Fietkau +--- + include/linux/kobject.h | 5 +++++ + lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/lib/kobject_uevent.c ++++ b/lib/kobject_uevent.c +@@ -179,6 +179,18 @@ out: + return r; + } + ++u64 uevent_next_seqnum(void) ++{ ++ u64 seq; ++ ++ mutex_lock(&uevent_sock_mutex); ++ seq = ++uevent_seqnum; ++ mutex_unlock(&uevent_sock_mutex); ++ ++ return seq; ++} ++EXPORT_SYMBOL_GPL(uevent_next_seqnum); ++ + /** + * kobject_synth_uevent - send synthetic uevent with arguments + * diff --git a/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch new file mode 100644 index 0000000000..9854585d25 --- /dev/null +++ b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch @@ -0,0 +1,76 @@ +From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 16 Jul 2017 16:56:10 +0200 +Subject: lib: add uevent_next_seqnum() + +Signed-off-by: Felix Fietkau +--- + include/linux/kobject.h | 5 +++++ + lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/include/linux/kobject.h ++++ b/include/linux/kobject.h +@@ -32,6 +32,8 @@ + #define UEVENT_NUM_ENVP 64 /* number of env pointers */ + #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ + ++struct sk_buff; ++ + #ifdef CONFIG_UEVENT_HELPER + /* path to the userspace helper executed on an event */ + extern char uevent_helper[]; +@@ -224,4 +226,7 @@ int kobject_synth_uevent(struct kobject + __printf(2, 3) + int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...); + ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation); ++ + #endif /* _KOBJECT_H_ */ +--- a/lib/kobject_uevent.c ++++ b/lib/kobject_uevent.c +@@ -691,6 +691,43 @@ int add_uevent_var(struct kobj_uevent_en + EXPORT_SYMBOL_GPL(add_uevent_var); + + #if defined(CONFIG_NET) ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation) ++{ ++ struct uevent_sock *ue_sk; ++ int err = 0; ++ ++ /* send netlink message */ ++ mutex_lock(&uevent_sock_mutex); ++ list_for_each_entry(ue_sk, &uevent_sock_list, list) { ++ struct sock *uevent_sock = ue_sk->sk; ++ struct sk_buff *skb2; ++ ++ skb2 = skb_clone(skb, allocation); ++ if (!skb2) ++ break; ++ ++ err = netlink_broadcast(uevent_sock, skb2, pid, group, ++ allocation); ++ if (err) ++ break; ++ } ++ mutex_unlock(&uevent_sock_mutex); ++ ++ kfree_skb(skb); ++ return err; ++} ++#else ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation) ++{ ++ kfree_skb(skb); ++ return 0; ++} ++#endif ++EXPORT_SYMBOL_GPL(broadcast_uevent); ++ ++#if defined(CONFIG_NET) + static int uevent_net_broadcast(struct sock *usk, struct sk_buff *skb, + struct netlink_ext_ack *extack) + { diff --git a/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch new file mode 100644 index 0000000000..cc384bb553 --- /dev/null +++ b/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch @@ -0,0 +1,21 @@ +From e08bcbbaa52fcc41f02743fd2e62a33255ce52da Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:52:28 +0200 +Subject: [PATCH] of/ftd: add device tree cmdline + +--- + drivers/of/fdt.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1183,6 +1183,9 @@ int __init early_init_dt_scan_chosen(cha + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); ++ p = of_get_flat_dt_prop(node, "bootargs-append", &l); ++ if (p != NULL && l > 0) ++ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + + handle_cmdline: + /* diff --git a/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch b/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch new file mode 100644 index 0000000000..04aaab7adf --- /dev/null +++ b/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch @@ -0,0 +1,30 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Jul 2022 06:17:48 +0200 +Subject: [PATCH] Revert "Revert "Revert "driver core: Set fw_devlink=on by + default""" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit ea718c699055c8566eb64432388a04974c43b2ea. + +With of_platform_populate() called for MTD partitions that commit breaks +probing devices which reference MTD in device tree. + +Link: https://lore.kernel.org/all/696cb2da-20b9-b3dd-46d9-de4bf91a1506@gmail.com/T/#u +Signed-off-by: Rafał Miłecki +--- + drivers/base/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -1702,7 +1702,7 @@ static void device_links_purge(struct de + #define FW_DEVLINK_FLAGS_RPM (FW_DEVLINK_FLAGS_ON | \ + DL_FLAG_PM_RUNTIME) + +-static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_ON; ++static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_PERMISSIVE; + static int __init fw_devlink_setup(char *arg) + { + if (!arg) diff --git a/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch new file mode 100644 index 0000000000..7b342e6962 --- /dev/null +++ b/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Thu, 22 Oct 2020 22:00:03 +0200 +Subject: [PATCH] compiler.h: only include asm/rwonce.h for kernel code + +This header file is not in uapi, which makes any user space code that includes +linux/compiler.h to fail with the error 'asm/rwonce.h: No such file or directory' + +Fixes: e506ea451254 ("compiler.h: Split {READ,WRITE}_ONCE definitions out into rwonce.h") +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -203,6 +203,8 @@ void ftrace_likely_update(struct ftrace_ + __v; \ + }) + ++#include ++ + #endif /* __KERNEL__ */ + + /* +@@ -243,6 +245,4 @@ static inline void *offset_to_ptr(const + */ + #define prevent_tail_call_optimization() mb() + +-#include +- + #endif /* __LINUX_COMPILER_H */ diff --git a/target/linux/generic/pending-6.6/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/target/linux/generic/pending-6.6/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch new file mode 100644 index 0000000000..d79d03defb --- /dev/null +++ b/target/linux/generic/pending-6.6/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch @@ -0,0 +1,57 @@ +From: Felix Fietkau +Date: Wed, 18 Apr 2018 10:50:05 +0200 +Subject: [PATCH] MIPS: only process negative stack offsets on stack traces + +Fixes endless back traces in cases where the compiler emits a stack +pointer increase in a branch delay slot (probably for some form of +function return). + +[ 3.475442] BUG: MAX_STACK_TRACE_ENTRIES too low! +[ 3.480070] turning off the locking correctness validator. +[ 3.485521] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.34 #0 +[ 3.491475] Stack : 00000000 00000000 00000000 00000000 80e0fce2 00000034 00000000 00000000 +[ 3.499764] 87c3838c 80696377 8061047c 00000000 00000001 00000001 87c2d850 6534689f +[ 3.508059] 00000000 00000000 80e10000 00000000 00000000 000000cf 0000000f 00000000 +[ 3.516353] 00000000 806a0000 00076891 00000000 00000000 00000000 ffffffff 00000000 +[ 3.524648] 806c0000 00000004 80e10000 806a0000 00000003 80690000 00000000 80700000 +[ 3.532942] ... +[ 3.535362] Call Trace: +[ 3.537818] [<80010a48>] show_stack+0x58/0x100 +[ 3.542207] [<804c2f78>] dump_stack+0xe8/0x170 +[ 3.546613] [<80079f90>] save_trace+0xf0/0x110 +[ 3.551010] [<8007b1ec>] mark_lock+0x33c/0x78c +[ 3.555413] [<8007bf48>] __lock_acquire+0x2ac/0x1a08 +[ 3.560337] [<8007de60>] lock_acquire+0x64/0x8c +[ 3.564846] [<804e1570>] _raw_spin_lock_irqsave+0x54/0x78 +[ 3.570186] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.574770] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.579257] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.583839] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.588329] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.592911] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.597401] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.601983] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.606473] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.611055] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.615545] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.620125] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.624619] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.629197] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.633691] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.638269] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.642763] [<801b618c>] kernfs_notify+0x94/0xac + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -395,6 +395,8 @@ static inline int is_sp_move_ins(union m + + if (ip->i_format.opcode == addiu_op || + ip->i_format.opcode == daddiu_op) { ++ if (ip->i_format.simmediate > 0) ++ return 0; + *frame_size = -ip->i_format.simmediate; + return 1; + } diff --git a/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch new file mode 100644 index 0000000000..c8c0efaecf --- /dev/null +++ b/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch @@ -0,0 +1,21 @@ +From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 9 Jul 2017 00:26:53 +0200 +Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86 + +Signed-off-by: Felix Fietkau +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -605,7 +605,7 @@ endif + # Allows the usage of unstable features in stable compilers. + export RUSTC_BOOTSTRAP := 1 + +-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG ++export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG + export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN CARGO + export HOSTRUSTC KBUILD_HOSTRUSTFLAGS + export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL diff --git a/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch b/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch new file mode 100644 index 0000000000..ebeeae2f8f --- /dev/null +++ b/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch @@ -0,0 +1,32 @@ +From f7982c726e02001afc19052fe48f642dfcbc00b2 Mon Sep 17 00:00:00 2001 +From: Vincent Tremblay +Date: Mon, 26 Dec 2022 21:10:37 -0500 +Subject: [PATCH 1/2] spidev: Add Silicon Labs EM3581 device compatible + +Add compatible string for Silicon Labs EM3581 device. + +Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). + +Signed-off-by: Vincent Tremblay +--- + drivers/spi/spidev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -700,6 +700,7 @@ static const struct spi_device_id spidev + { .name = "m53cpld" }, + { .name = "spi-petra" }, + { .name = "spi-authenta" }, ++ { .name = "em3581" }, + {}, + }; + MODULE_DEVICE_TABLE(spi, spidev_spi_ids); +@@ -726,6 +727,7 @@ static const struct of_device_id spidev_ + { .compatible = "menlo,m53cpld", .data = &spidev_of_check }, + { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, + { .compatible = "micron,spi-authenta", .data = &spidev_of_check }, ++ { .compatible = "silabs,em3581", .data = &spidev_of_check }, + {}, + }; + MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch b/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch new file mode 100644 index 0000000000..db5b5800f4 --- /dev/null +++ b/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch @@ -0,0 +1,32 @@ +From 536581825219e97fa2ae0c4de35605d2f6311416 Mon Sep 17 00:00:00 2001 +From: Vincent Tremblay +Date: Tue, 27 Dec 2022 09:00:58 -0500 +Subject: [PATCH 2/2] spidev: Add Silicon Labs SI3210 device compatible + +Add compatible string for Silicon Labs SI3210 device. + +Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). + +Signed-off-by: Vincent Tremblay +--- + drivers/spi/spidev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -701,6 +701,7 @@ static const struct spi_device_id spidev + { .name = "spi-petra" }, + { .name = "spi-authenta" }, + { .name = "em3581" }, ++ { .name = "si3210" }, + {}, + }; + MODULE_DEVICE_TABLE(spi, spidev_spi_ids); +@@ -728,6 +729,7 @@ static const struct of_device_id spidev_ + { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, + { .compatible = "micron,spi-authenta", .data = &spidev_of_check }, + { .compatible = "silabs,em3581", .data = &spidev_of_check }, ++ { .compatible = "silabs,si3210", .data = &spidev_of_check }, + {}, + }; + MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch b/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch new file mode 100644 index 0000000000..d6b10491f8 --- /dev/null +++ b/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch @@ -0,0 +1,75 @@ +From bd1b9f66d5134e518419f4c4dacf1884c1616983 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 28 Apr 2022 11:13:23 +0200 +Subject: [PATCH] watchdog: max63xx_wdt: Add support for specifying WDI logic + via GPIO +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On some boards is WDI logic of max6370 chip connected via GPIO. +So extend max63xx_wdt driver to allow specifying WDI logic via GPIO. + +Signed-off-by: Pali Rohár +--- + drivers/watchdog/max63xx_wdt.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/drivers/watchdog/max63xx_wdt.c ++++ b/drivers/watchdog/max63xx_wdt.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #define DEFAULT_HEARTBEAT 60 + #define MAX_HEARTBEAT 60 +@@ -53,6 +54,9 @@ struct max63xx_wdt { + void __iomem *base; + spinlock_t lock; + ++ /* GPIOs */ ++ struct gpio_desc *gpio_wdi; ++ + /* WDI and WSET bits write access routines */ + void (*ping)(struct max63xx_wdt *wdt); + void (*set)(struct max63xx_wdt *wdt, u8 set); +@@ -158,6 +162,17 @@ static const struct watchdog_info max63x + .identity = "max63xx Watchdog", + }; + ++static void max63xx_gpio_ping(struct max63xx_wdt *wdt) ++{ ++ spin_lock(&wdt->lock); ++ ++ gpiod_set_value(wdt->gpio_wdi, 1); ++ udelay(1); ++ gpiod_set_value(wdt->gpio_wdi, 0); ++ ++ spin_unlock(&wdt->lock); ++} ++ + static void max63xx_mmap_ping(struct max63xx_wdt *wdt) + { + u8 val; +@@ -225,10 +240,19 @@ static int max63xx_wdt_probe(struct plat + return -EINVAL; + } + ++ wdt->gpio_wdi = devm_gpiod_get(dev, NULL, GPIOD_FLAGS_BIT_DIR_OUT); ++ if (IS_ERR(wdt->gpio_wdi) && PTR_ERR(wdt->gpio_wdi) != -ENOENT) ++ return dev_err_probe(dev, PTR_ERR(wdt->gpio_wdi), ++ "unable to request gpio: %ld\n", ++ PTR_ERR(wdt->gpio_wdi)); ++ + err = max63xx_mmap_init(pdev, wdt); + if (err) + return err; + ++ if (!IS_ERR(wdt->gpio_wdi)) ++ wdt->ping = max63xx_gpio_ping; ++ + platform_set_drvdata(pdev, &wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, wdt); + diff --git a/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch new file mode 100644 index 0000000000..4bf473f9a7 --- /dev/null +++ b/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -0,0 +1,82 @@ +From: Tobias Wolf +Subject: mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET calculation + +An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any +kernel beyond version 4.3 resulting in: + +BUG: Bad page state in process swapper pfn:086ac + +bisect resulted in: + +a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit +commit a1c34a3bf00af2cede839879502e12dc68491ad5 +Author: Laura Abbott +Date: Thu Nov 5 18:48:46 2015 -0800 + + mm: Don't offset memmap for flatmem + + Srinivas Kandagatla reported bad page messages when trying to remove the + bottom 2MB on an ARM based IFC6410 board + + BUG: Bad page state in process swapper pfn:fffa8 + page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0 + flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked) + page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set + bad because of flags: + flags: 0x200041(locked|active|mlocked) + Modules linked in: + CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty +#816 + Hardware name: Qualcomm (Flattened Device Tree) + unwind_backtrace + show_stack + dump_stack + bad_page + free_pages_prepare + free_hot_cold_page + __free_pages + free_highmem_page + mem_init + start_kernel + Disabling lock debugging due to kernel taint + [...] +:040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4 +0a8156f848733dfa21e16c196dfb6c0a76290709 M mm + +This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by +page_to_pfn anymore. + +The following output was generated with two hacked in printk statements: + +printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map - +(pgdat->node_start_pfn - ARCH_PFN_OFFSET)); + if (page_to_pfn(mem_map) != pgdat->node_start_pfn) + mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); +printk("after %p\n", mem_map); + +Output: + +[ 0.000000] before 8861b280 vs. 8861b280 or 8851b280 +[ 0.000000] after 8851b280 + +As seen in the first line mem_map with subtraction of offset does not equal the +mem_map after subtraction of ARCH_PFN_OFFSET. + +After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the +previously calculated offset is zero for the named platform it is able to boot +4.4 and 4.9-rc7 again. + +Signed-off-by: Tobias Wolf +--- + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7897,7 +7897,7 @@ static void __init alloc_node_mem_map(st + if (pgdat == NODE_DATA(0)) { + mem_map = NODE_DATA(0)->node_mem_map; + if (page_to_pfn(mem_map) != pgdat->node_start_pfn) +- mem_map -= offset; ++ mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); + } + #endif + } diff --git a/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch new file mode 100644 index 0000000000..8f40ae3ba2 --- /dev/null +++ b/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -0,0 +1,81 @@ +From: Felix Fietkau +Subject: jffs2: use .rename2 and add RENAME_WHITEOUT support + +It is required for renames on overlayfs + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/dir.c ++++ b/fs/jffs2/dir.c +@@ -614,8 +614,8 @@ static int jffs2_rmdir (struct inode *di + return ret; + } + +-static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, +- struct dentry *dentry, umode_t mode, dev_t rdev) ++static int __jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev, bool whiteout) + { + struct jffs2_inode_info *f, *dir_f; + struct jffs2_sb_info *c; +@@ -754,7 +754,11 @@ static int jffs2_mknod (struct user_name + mutex_unlock(&dir_f->sem); + jffs2_complete_reservation(c); + +- d_instantiate_new(dentry, inode); ++ if (!whiteout) ++ d_instantiate_new(dentry, inode); ++ else ++ unlock_new_inode(inode); ++ + return 0; + + fail: +@@ -762,6 +766,19 @@ static int jffs2_mknod (struct user_name + return ret; + } + ++static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev) ++{ ++ return __jffs2_mknod(mnt_userns, dir_i, dentry, mode, rdev, false); ++} ++ ++static int jffs2_whiteout (struct user_namespace *mnt_userns, struct inode *old_dir, ++ struct dentry *old_dentry) ++{ ++ return __jffs2_mknod(mnt_userns, old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, ++ WHITEOUT_DEV, true); ++} ++ + static int jffs2_rename (struct user_namespace *mnt_userns, + struct inode *old_dir_i, struct dentry *old_dentry, + struct inode *new_dir_i, struct dentry *new_dentry, +@@ -773,7 +790,7 @@ static int jffs2_rename (struct user_nam + uint8_t type; + uint32_t now; + +- if (flags & ~RENAME_NOREPLACE) ++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) + return -EINVAL; + + /* The VFS will check for us and prevent trying to rename a +@@ -839,9 +856,14 @@ static int jffs2_rename (struct user_nam + if (d_is_dir(old_dentry) && !victim_f) + inc_nlink(new_dir_i); + +- /* Unlink the original */ +- ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), +- old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); ++ if (flags & RENAME_WHITEOUT) ++ /* Replace with whiteout */ ++ ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); ++ else ++ /* Unlink the original */ ++ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), ++ old_dentry->d_name.name, ++ old_dentry->d_name.len, NULL, now); + + /* We don't touch inode->i_nlink */ + diff --git a/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch new file mode 100644 index 0000000000..f58fc791d2 --- /dev/null +++ b/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch @@ -0,0 +1,73 @@ +From: Felix Fietkau +Subject: jffs2: add RENAME_EXCHANGE support + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/dir.c ++++ b/fs/jffs2/dir.c +@@ -787,18 +787,31 @@ static int jffs2_rename (struct user_nam + int ret; + struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); + struct jffs2_inode_info *victim_f = NULL; ++ struct inode *fst_inode = d_inode(old_dentry); ++ struct inode *snd_inode = d_inode(new_dentry); + uint8_t type; + uint32_t now; + +- if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) ++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT|RENAME_EXCHANGE)) + return -EINVAL; + ++ if ((flags & RENAME_EXCHANGE) && (old_dir_i != new_dir_i)) { ++ if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) { ++ inc_nlink(new_dir_i); ++ drop_nlink(old_dir_i); ++ } ++ else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) { ++ drop_nlink(new_dir_i); ++ inc_nlink(old_dir_i); ++ } ++ } ++ + /* The VFS will check for us and prevent trying to rename a + * file over a directory and vice versa, but if it's a directory, + * the VFS can't check whether the victim is empty. The filesystem + * needs to do that for itself. + */ +- if (d_really_is_positive(new_dentry)) { ++ if (d_really_is_positive(new_dentry) && !(flags & RENAME_EXCHANGE)) { + victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); + if (d_is_dir(new_dentry)) { + struct jffs2_full_dirent *fd; +@@ -833,7 +846,7 @@ static int jffs2_rename (struct user_nam + if (ret) + return ret; + +- if (victim_f) { ++ if (victim_f && !(flags & RENAME_EXCHANGE)) { + /* There was a victim. Kill it off nicely */ + if (d_is_dir(new_dentry)) + clear_nlink(d_inode(new_dentry)); +@@ -859,6 +872,12 @@ static int jffs2_rename (struct user_nam + if (flags & RENAME_WHITEOUT) + /* Replace with whiteout */ + ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); ++ else if (flags & RENAME_EXCHANGE) ++ /* Replace the original */ ++ ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i), ++ d_inode(new_dentry)->i_ino, type, ++ old_dentry->d_name.name, old_dentry->d_name.len, ++ now); + else + /* Unlink the original */ + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), +@@ -890,7 +909,7 @@ static int jffs2_rename (struct user_nam + return ret; + } + +- if (d_is_dir(old_dentry)) ++ if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE)) + drop_nlink(old_dir_i); + + new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); diff --git a/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch b/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch new file mode 100644 index 0000000000..de847a1f5c --- /dev/null +++ b/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Subject: jffs2: add splice ops + +Add splice_read using generic_file_splice_read. +Add splice_write using iter_file_splice_write + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/file.c ++++ b/fs/jffs2/file.c +@@ -53,6 +53,8 @@ const struct file_operations jffs2_file_ + .open = generic_file_open, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, ++ .splice_read = generic_file_splice_read, ++ .splice_write = iter_file_splice_write, + .unlocked_ioctl=jffs2_ioctl, + .mmap = generic_file_readonly_mmap, + .fsync = jffs2_fsync, diff --git a/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch new file mode 100644 index 0000000000..93a2d146b5 --- /dev/null +++ b/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch @@ -0,0 +1,45 @@ +From: Stephen Hemminger +Subject: bridge: allow receiption on disabled port + +When an ethernet device is enslaved to a bridge, and the bridge STP +detects loss of carrier (or operational state down), then normally +packet receiption is blocked. + +This breaks control applications like WPA which maybe expecting to +receive packets to negotiate to bring link up. The bridge needs to +block forwarding packets from these disabled ports, but there is no +hard requirement to not allow local packet delivery. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Felix Fietkau + +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -222,6 +222,9 @@ static void __br_handle_local_finish(str + /* note: already called with rcu_read_lock */ + static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) + { ++ struct net_bridge_port *p = br_port_get_rcu(skb->dev); ++ ++ if (p->state != BR_STATE_DISABLED) + __br_handle_local_finish(skb); + + /* return 1 to signal the okfn() was called so it's ok to use the skb */ +@@ -390,6 +393,17 @@ forward: + goto defer_stp_filtering; + + switch (p->state) { ++ case BR_STATE_DISABLED: ++ if (ether_addr_equal(p->br->dev->dev_addr, dest)) ++ skb->pkt_type = PACKET_HOST; ++ ++ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, ++ dev_net(skb->dev), NULL, skb, skb->dev, NULL, ++ br_handle_local_finish) == 1) { ++ return RX_HANDLER_PASS; ++ } ++ break; ++ + case BR_STATE_FORWARDING: + case BR_STATE_LEARNING: + defer_stp_filtering: diff --git a/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the diff --git a/target/linux/generic/pending-6.6/190-rtc-rs5c372-support_alarms_up_to_1_week.patch b/target/linux/generic/pending-6.6/190-rtc-rs5c372-support_alarms_up_to_1_week.patch new file mode 100644 index 0000000000..2f5c2228c7 --- /dev/null +++ b/target/linux/generic/pending-6.6/190-rtc-rs5c372-support_alarms_up_to_1_week.patch @@ -0,0 +1,94 @@ +From: Daniel González Cabanelas +Subject: [PATCH 1/2] rtc: rs5c372: support alarms up to 1 week + +The Ricoh R2221x, R2223x, RS5C372, RV5C387A chips can handle 1 week +alarms. + +Read the "wday" alarm register and convert it to a date to support up 1 +week in our driver. + +Signed-off-by: Daniel González Cabanelas +--- + drivers/rtc/rtc-rs5c372.c | 48 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 42 insertions(+), 6 deletions(-) + +--- a/drivers/rtc/rtc-rs5c372.c ++++ b/drivers/rtc/rtc-rs5c372.c +@@ -399,7 +399,9 @@ static int rs5c_read_alarm(struct device + { + struct i2c_client *client = to_i2c_client(dev); + struct rs5c372 *rs5c = i2c_get_clientdata(client); +- int status; ++ int status, wday_offs; ++ struct rtc_time rtc; ++ unsigned long alarm_secs; + + status = rs5c_get_regs(rs5c); + if (status < 0) +@@ -409,6 +411,30 @@ static int rs5c_read_alarm(struct device + t->time.tm_sec = 0; + t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); + t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); ++ t->time.tm_wday = ffs(rs5c->regs[RS5C_REG_ALARM_A_WDAY] & 0x7f) - 1; ++ ++ /* determine the day, month and year based on alarm wday, taking as a ++ * reference the current time from the rtc ++ */ ++ status = rs5c372_rtc_read_time(dev, &rtc); ++ if (status < 0) ++ return status; ++ ++ wday_offs = t->time.tm_wday - rtc.tm_wday; ++ alarm_secs = mktime64(rtc.tm_year + 1900, ++ rtc.tm_mon + 1, ++ rtc.tm_mday + wday_offs, ++ t->time.tm_hour, ++ t->time.tm_min, ++ t->time.tm_sec); ++ ++ if (wday_offs < 0 || (wday_offs == 0 && ++ (t->time.tm_hour < rtc.tm_hour || ++ (t->time.tm_hour == rtc.tm_hour && ++ t->time.tm_min <= rtc.tm_min)))) ++ alarm_secs += 7 * 86400; ++ ++ rtc_time64_to_tm(alarm_secs, &t->time); + + /* ... and status */ + t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE); +@@ -423,12 +449,20 @@ static int rs5c_set_alarm(struct device + struct rs5c372 *rs5c = i2c_get_clientdata(client); + int status, addr, i; + unsigned char buf[3]; ++ struct rtc_time rtc_tm; ++ unsigned long rtc_secs, alarm_secs; + +- /* only handle up to 24 hours in the future, like RTC_ALM_SET */ +- if (t->time.tm_mday != -1 +- || t->time.tm_mon != -1 +- || t->time.tm_year != -1) ++ /* chip only can handle alarms up to one week in the future*/ ++ status = rs5c372_rtc_read_time(dev, &rtc_tm); ++ if (status) ++ return status; ++ rtc_secs = rtc_tm_to_time64(&rtc_tm); ++ alarm_secs = rtc_tm_to_time64(&t->time); ++ if (alarm_secs >= rtc_secs + 7 * 86400) { ++ dev_err(dev, "%s: alarm maximum is one week in the future (%d)\n", ++ __func__, status); + return -EINVAL; ++ } + + /* REVISIT: round up tm_sec */ + +@@ -449,7 +483,9 @@ static int rs5c_set_alarm(struct device + /* set alarm */ + buf[0] = bin2bcd(t->time.tm_min); + buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); +- buf[2] = 0x7f; /* any/all days */ ++ /* each bit is the day of the week, 0x7f means all days */ ++ buf[2] = (t->time.tm_wday >= 0 && t->time.tm_wday < 7) ? ++ BIT(t->time.tm_wday) : 0x7f; + + for (i = 0; i < sizeof(buf); i++) { + addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); diff --git a/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch new file mode 100644 index 0000000000..a9a5cdf8ba --- /dev/null +++ b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch @@ -0,0 +1,71 @@ +From: Daniel González Cabanelas +Subject: [PATCH 2/2] rtc: rs5c372: let the alarm to be used as wakeup source + +Currently there is no use for the interrupts on the rs5c372 RTC and the +wakealarm isn't enabled. There are some devices like NASes which use this +RTC to wake up from the power off state when the INTR pin is activated by +the alarm clock. + +Enable the alarm and let to be used as a wakeup source. + +Tested on a Buffalo LS421DE NAS. + +Signed-off-by: Daniel González Cabanelas +--- + drivers/rtc/rtc-rs5c372.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/rtc/rtc-rs5c372.c ++++ b/drivers/rtc/rtc-rs5c372.c +@@ -833,6 +833,7 @@ static int rs5c372_probe(struct i2c_clie + int err = 0; + int smbus_mode = 0; + struct rs5c372 *rs5c372; ++ bool rs5c372_can_wakeup_device = false; + + dev_dbg(&client->dev, "%s\n", __func__); + +@@ -868,6 +869,12 @@ static int rs5c372_probe(struct i2c_clie + else + rs5c372->type = id->driver_data; + ++#ifdef CONFIG_OF ++ if(of_property_read_bool(client->dev.of_node, ++ "wakeup-source")) ++ rs5c372_can_wakeup_device = true; ++#endif ++ + /* we read registers 0x0f then 0x00-0x0f; skip the first one */ + rs5c372->regs = &rs5c372->buf[1]; + rs5c372->smbus = smbus_mode; +@@ -901,6 +908,8 @@ static int rs5c372_probe(struct i2c_clie + goto exit; + } + ++ rs5c372->has_irq = 1; ++ + /* if the oscillator lost power and no other software (like + * the bootloader) set it up, do it here. + * +@@ -927,6 +936,10 @@ static int rs5c372_probe(struct i2c_clie + ); + + /* REVISIT use client->irq to register alarm irq ... */ ++ if (rs5c372_can_wakeup_device) { ++ device_init_wakeup(&client->dev, true); ++ } ++ + rs5c372->rtc = devm_rtc_device_register(&client->dev, + rs5c372_driver.driver.name, + &rs5c372_rtc_ops, THIS_MODULE); +@@ -940,6 +953,10 @@ static int rs5c372_probe(struct i2c_clie + if (err) + goto exit; + ++ /* the rs5c372 alarm only supports a minute accuracy */ ++ set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rs5c372->rtc->features); ++ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rs5c372->rtc->features); ++ + return 0; + + exit: diff --git a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch new file mode 100644 index 0000000000..78ed262b78 --- /dev/null +++ b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch @@ -0,0 +1,118 @@ +From: Felix Fietkau +Subject: kernel: add a config option for keeping the kallsyms table uncompressed, saving ~9kb kernel size after lzma on ar71xx + +[john@phrozen.org: added to my upstream queue 30.12.2016] +lede-commit: e0e3509b5ce2ccf93d4d67ea907613f5f7ec2eed +Signed-off-by: Felix Fietkau +--- + init/Kconfig | 11 +++++++++++ + kernel/kallsyms.c | 8 ++++++++ + scripts/kallsyms.c | 12 ++++++++++++ + scripts/link-vmlinux.sh | 4 ++++ + 4 files changed, 35 insertions(+) + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1491,6 +1491,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW + the unaligned access emulation. + see arch/parisc/kernel/unaligned.c for reference + ++config KALLSYMS_UNCOMPRESSED ++ bool "Keep kallsyms uncompressed" ++ depends on KALLSYMS ++ help ++ Normally kallsyms contains compressed symbols (using a token table), ++ reducing the uncompressed kernel image size. Keeping the symbol table ++ uncompressed significantly improves the size of this part in compressed ++ kernel images. ++ ++ Say N unless you need compressed kernel images to be small. ++ + config HAVE_PCSPKR_PLATFORM + bool + +--- a/kernel/kallsyms.c ++++ b/kernel/kallsyms.c +@@ -69,6 +69,11 @@ static unsigned int kallsyms_expand_symb + * For every byte on the compressed symbol data, copy the table + * entry for that byte. + */ ++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED ++ memcpy(result, data + 1, len - 1); ++ result += len - 1; ++ len = 0; ++#endif + while (len) { + tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; + data++; +@@ -101,6 +106,9 @@ tail: + */ + static char kallsyms_get_symbol_type(unsigned int off) + { ++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED ++ return kallsyms_names[off + 1]; ++#endif + /* + * Get just the first code, look it up in the token table, + * and return the first char from this token. +--- a/scripts/kallsyms.c ++++ b/scripts/kallsyms.c +@@ -77,6 +77,7 @@ static struct addr_range percpu_range = + static struct sym_entry **table; + static unsigned int table_size, table_cnt; + static int all_symbols; ++static int uncompressed; + static int absolute_percpu; + static int base_relative; + static int lto_clang; +@@ -608,6 +609,9 @@ static void write_src(void) + (unsigned char)(table[i]->seq >> 0)); + printf("\n"); + ++ if (uncompressed) ++ return; ++ + output_label("kallsyms_token_table"); + off = 0; + for (i = 0; i < 256; i++) { +@@ -659,6 +663,9 @@ static unsigned char *find_token(unsigne + { + int i; + ++ if (uncompressed) ++ return NULL; ++ + for (i = 0; i < len - 1; i++) { + if (str[i] == token[0] && str[i+1] == token[1]) + return &str[i]; +@@ -731,6 +738,9 @@ static void optimize_result(void) + { + int i, best; + ++ if (uncompressed) ++ return; ++ + /* using the '\0' symbol last allows compress_symbols to use standard + * fast string functions */ + for (i = 255; i >= 0; i--) { +@@ -892,6 +902,7 @@ int main(int argc, char **argv) + {"absolute-percpu", no_argument, &absolute_percpu, 1}, + {"base-relative", no_argument, &base_relative, 1}, + {"lto-clang", no_argument, <o_clang, 1}, ++ {"uncompressed", no_argument, &uncompressed, 1}, + {}, + }; + +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh +@@ -165,6 +165,10 @@ kallsyms() + kallsymopt="${kallsymopt} --lto-clang" + fi + ++ if is_enabled CONFIG_KALLSYMS_UNCOMPRESSED; then ++ kallsymopt="${kallsymopt} --uncompressed" ++ fi ++ + info KSYMS ${2} + scripts/kallsyms ${kallsymopt} ${1} > ${2} + } diff --git a/target/linux/generic/pending-6.6/205-backtrace_module_info.patch b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch new file mode 100644 index 0000000000..27a1347981 --- /dev/null +++ b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Subject: kernel: when KALLSYMS is disabled, print module address + size for matching backtrace entries + +[john@phrozen.org: felix will add this to his upstream queue] + +lede-commit 53827cdc824556cda910b23ce5030c363b8f1461 +Signed-off-by: Felix Fietkau +--- + lib/vsprintf.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/lib/vsprintf.c ++++ b/lib/vsprintf.c +@@ -985,8 +985,10 @@ char *symbol_string(char *buf, char *end + struct printf_spec spec, const char *fmt) + { + unsigned long value; +-#ifdef CONFIG_KALLSYMS + char sym[KSYM_SYMBOL_LEN]; ++#ifndef CONFIG_KALLSYMS ++ struct module *mod; ++ int len; + #endif + + if (fmt[1] == 'R') +@@ -1007,8 +1009,14 @@ char *symbol_string(char *buf, char *end + + return string_nocheck(buf, end, sym, spec); + #else +- return special_hex_number(buf, end, value, sizeof(void *)); ++ len = snprintf(sym, sizeof(sym), "0x%lx", value); ++ mod = __module_address(value); ++ if (mod) ++ snprintf(sym + len, sizeof(sym) - len, " [%s@%p+0x%x]", ++ mod->name, mod->core_layout.base, ++ mod->core_layout.size); + #endif ++ return string(buf, end, sym, spec); + } + + static const struct printf_spec default_str_spec = { diff --git a/target/linux/generic/pending-6.6/240-remove-unsane-filenames-from-deps_initramfs-list.patch b/target/linux/generic/pending-6.6/240-remove-unsane-filenames-from-deps_initramfs-list.patch new file mode 100644 index 0000000000..9e78284ecf --- /dev/null +++ b/target/linux/generic/pending-6.6/240-remove-unsane-filenames-from-deps_initramfs-list.patch @@ -0,0 +1,30 @@ +From: Gabor Juhos +Subject: usr: sanitize deps_initramfs list + +If any filename in the intramfs dependency +list contains a colon, that causes a kernel +build error like this: + +/devel/openwrt/build_dir/linux-ar71xx_generic/linux-3.6.6/usr/Makefile:58: *** multiple target patterns. Stop. +make[5]: *** [usr] Error 2 + +Fix it by removing such filenames from the +deps_initramfs list. + +Signed-off-by: Gabor Juhos +Signed-off-by: Felix Fietkau +--- + usr/Makefile | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/usr/Makefile ++++ b/usr/Makefile +@@ -56,6 +56,8 @@ hostprogs := gen_init_cpio + # The dependency list is generated by gen_initramfs.sh -l + -include $(obj)/.initramfs_data.cpio.d + ++deps_initramfs := $(foreach v,$(deps_initramfs),$(if $(findstring :,$(v)),,$(v))) ++ + # do not try to update files included in initramfs + $(deps_initramfs): ; + diff --git a/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch b/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch new file mode 100644 index 0000000000..cd31f9d934 --- /dev/null +++ b/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch @@ -0,0 +1,20 @@ +From: Imre Kaloz +Subject: [PATCH] hack: net: wireless: make the wl12xx glue code available with + compat-wireless, too + +Signed-off-by: Imre Kaloz +--- + drivers/net/wireless/ti/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ti/Kconfig ++++ b/drivers/net/wireless/ti/Kconfig +@@ -20,7 +20,7 @@ source "drivers/net/wireless/ti/wlcore/K + + config WILINK_PLATFORM_DATA + bool "TI WiLink platform data" +- depends on WLCORE_SDIO || WL1251_SDIO ++ depends on WLCORE_SDIO || WL1251_SDIO || ARCH_OMAP2PLUS + default y + help + Small platform data bit needed to pass data to the sdio modules. diff --git a/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch new file mode 100644 index 0000000000..997e6142a7 --- /dev/null +++ b/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch @@ -0,0 +1,31 @@ +From c2deb5ef01a0ef09088832744cbace9e239a6ee0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= +Date: Sat, 28 Mar 2020 12:11:50 +0100 +Subject: [PATCH] generic: platform/mikrotik build bits (5.4) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds platform/mikrotik kernel build bits + +Signed-off-by: Thibaut VARÈNE +--- + drivers/platform/Kconfig | 2 ++ + drivers/platform/Makefile | 1 + + 2 files changed, 3 insertions(+) + +--- a/drivers/platform/Kconfig ++++ b/drivers/platform/Kconfig +@@ -16,3 +16,5 @@ source "drivers/platform/olpc/Kconfig" + source "drivers/platform/surface/Kconfig" + + source "drivers/platform/x86/Kconfig" ++ ++source "drivers/platform/mikrotik/Kconfig" +--- a/drivers/platform/Makefile ++++ b/drivers/platform/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_OLPC_EC) += olpc/ + obj-$(CONFIG_GOLDFISH) += goldfish/ + obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ + obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ ++obj-$(CONFIG_MIKROTIK) += mikrotik/ diff --git a/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch b/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch new file mode 100644 index 0000000000..d222ec060e --- /dev/null +++ b/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch @@ -0,0 +1,40 @@ +From: Mark Miller +Subject: mips: expose CONFIG_BOOT_RAW + +This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on +certain Broadcom chipsets running CFE in order to load the kernel. + +Signed-off-by: Mark Miller +Acked-by: Rob Landley +--- +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -1035,9 +1035,6 @@ config FW_ARC + config ARCH_MAY_HAVE_PC_FDC + bool + +-config BOOT_RAW +- bool +- + config CEVT_BCM1480 + bool + +@@ -3093,6 +3090,18 @@ choice + bool "Extend builtin kernel arguments with bootloader arguments" + endchoice + ++config BOOT_RAW ++ bool "Enable the kernel to be executed from the load address" ++ default n ++ help ++ Allow the kernel to be executed from the load address for ++ bootloaders which cannot read the ELF format. This places ++ a jump to start_kernel at the load address. ++ ++ If unsure, say N. ++ ++ ++ + endmenu + + config LOCKDEP_SUPPORT diff --git a/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch b/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch new file mode 100644 index 0000000000..bd56adad3a --- /dev/null +++ b/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch @@ -0,0 +1,71 @@ +From e6e6ef4275978823ec3a84133fc91f4ffbef5c84 Mon Sep 17 00:00:00 2001 +From: Paul Burton +Date: Mon, 22 Feb 2016 18:09:44 +0000 +Subject: [PATCH] MIPS: Add barriers between dcache & icache flushes + +Index-based cache operations may be arbitrarily reordered by out of +order CPUs. Thus code which writes back the dcache & then invalidates +the icache using indexed cache ops must include a barrier between +operating on the 2 caches in order to prevent the scenario in which: + + - icache invalidation occurs. + + - icache fetch occurs, due to speculation. + + - dcache writeback occurs. + +If the above were allowed to happen then the icache would contain stale +data. Forcing the dcache writeback to complete before the icache +invalidation avoids this. + +Signed-off-by: Paul Burton +Cc: James Hogan +--- + arch/mips/mm/c-r4k.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -514,6 +514,7 @@ static inline void local_r4k___flush_cac + + default: + r4k_blast_dcache(); ++ mb(); /* cache instructions may be reordered */ + r4k_blast_icache(); + break; + } +@@ -594,8 +595,10 @@ static inline void local_r4k_flush_cache + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache(); + /* If executable, blast stale lines from icache */ +- if (exec) ++ if (exec) { ++ mb(); /* cache instructions may be reordered */ + r4k_blast_icache(); ++ } + } + + static void r4k_flush_cache_range(struct vm_area_struct *vma, +@@ -696,8 +699,13 @@ static inline void local_r4k_flush_cache + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { + vaddr ? r4k_blast_dcache_page(addr) : + r4k_blast_dcache_user_page(addr); +- if (exec && !cpu_icache_snoops_remote_store) ++ if (exec) ++ mb(); /* cache instructions may be reordered */ ++ ++ if (exec && !cpu_icache_snoops_remote_store) { + r4k_blast_scache_page(addr); ++ mb(); /* cache instructions may be reordered */ ++ } + } + if (exec) { + if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) { +@@ -764,6 +772,7 @@ static inline void __local_r4k_flush_ica + else + blast_dcache_range(start, end); + } ++ mb(); /* cache instructions may be reordered */ + } + + if (type == R4K_INDEX || diff --git a/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch b/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch new file mode 100644 index 0000000000..542fba651f --- /dev/null +++ b/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: mips: use -mno-branch-likely for kernel and userspace + +saves ~11k kernel size after lzma and ~12k squashfs size in the + +lede-commit: 41a039f46450ffae9483d6216422098669da2900 +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -94,7 +94,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin + # machines may also. Since BFD is incredibly buggy with respect to + # crossformat linking we rely on the elf2ecoff tool for format conversion. + # +-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe ++cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely + cflags-y += -msoft-float + LDFLAGS_vmlinux += -G 0 -static -n -nostdlib + KBUILD_AFLAGS_MODULE += -mlong-calls diff --git a/target/linux/generic/pending-6.6/305-mips_module_reloc.patch b/target/linux/generic/pending-6.6/305-mips_module_reloc.patch new file mode 100644 index 0000000000..5de9019677 --- /dev/null +++ b/target/linux/generic/pending-6.6/305-mips_module_reloc.patch @@ -0,0 +1,370 @@ +From: Felix Fietkau +Subject: mips: replace -mlong-calls with -mno-long-calls to make function calls faster in kernel modules to achieve this, try to + +lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 5 + + arch/mips/include/asm/module.h | 5 + + arch/mips/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 284 insertions(+), 5 deletions(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -97,8 +97,18 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin + cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely + cflags-y += -msoft-float + LDFLAGS_vmlinux += -G 0 -static -n -nostdlib ++ifdef CONFIG_64BIT + KBUILD_AFLAGS_MODULE += -mlong-calls + KBUILD_CFLAGS_MODULE += -mlong-calls ++else ++ ifdef CONFIG_DYNAMIC_FTRACE ++ KBUILD_AFLAGS_MODULE += -mlong-calls ++ KBUILD_CFLAGS_MODULE += -mlong-calls ++ else ++ KBUILD_AFLAGS_MODULE += -mno-long-calls ++ KBUILD_CFLAGS_MODULE += -mno-long-calls ++ endif ++endif + + ifeq ($(CONFIG_RELOCATABLE),y) + LDFLAGS_vmlinux += --emit-relocs +--- a/arch/mips/include/asm/module.h ++++ b/arch/mips/include/asm/module.h +@@ -12,6 +12,11 @@ struct mod_arch_specific { + const struct exception_table_entry *dbe_start; + const struct exception_table_entry *dbe_end; + struct mips_hi16 *r_mips_hi16_list; ++ ++ void *phys_plt_tbl; ++ void *virt_plt_tbl; ++ unsigned int phys_plt_offset; ++ unsigned int virt_plt_offset; + }; + + typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ +--- a/arch/mips/kernel/module.c ++++ b/arch/mips/kernel/module.c +@@ -32,23 +32,261 @@ struct mips_hi16 { + static LIST_HEAD(dbe_list); + static DEFINE_SPINLOCK(dbe_lock); + +-#ifdef MODULE_START ++/* ++ * Get the potential max trampolines size required of the init and ++ * non-init sections. Only used if we cannot find enough contiguous ++ * physically mapped memory to put the module into. ++ */ ++static unsigned int ++get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, ++ const char *secstrings, unsigned int symindex, bool is_init) ++{ ++ unsigned long ret = 0; ++ unsigned int i, j; ++ Elf_Sym *syms; ++ ++ /* Everything marked ALLOC (this includes the exported symbols) */ ++ for (i = 1; i < hdr->e_shnum; ++i) { ++ unsigned int info = sechdrs[i].sh_info; ++ ++ if (sechdrs[i].sh_type != SHT_REL ++ && sechdrs[i].sh_type != SHT_RELA) ++ continue; ++ ++ /* Not a valid relocation section? */ ++ if (info >= hdr->e_shnum) ++ continue; ++ ++ /* Don't bother with non-allocated sections */ ++ if (!(sechdrs[info].sh_flags & SHF_ALLOC)) ++ continue; ++ ++ /* If it's called *.init*, and we're not init, we're ++ not interested */ ++ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) ++ != is_init) ++ continue; ++ ++ syms = (Elf_Sym *) sechdrs[symindex].sh_addr; ++ if (sechdrs[i].sh_type == SHT_REL) { ++ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; ++ unsigned int size = sechdrs[i].sh_size / sizeof(*rel); ++ ++ for (j = 0; j < size; ++j) { ++ Elf_Sym *sym; ++ ++ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) ++ continue; ++ ++ sym = syms + ELF_MIPS_R_SYM(rel[j]); ++ if (!is_init && sym->st_shndx != SHN_UNDEF) ++ continue; ++ ++ ret += 4 * sizeof(int); ++ } ++ } else { ++ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; ++ unsigned int size = sechdrs[i].sh_size / sizeof(*rela); ++ ++ for (j = 0; j < size; ++j) { ++ Elf_Sym *sym; ++ ++ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) ++ continue; ++ ++ sym = syms + ELF_MIPS_R_SYM(rela[j]); ++ if (!is_init && sym->st_shndx != SHN_UNDEF) ++ continue; ++ ++ ret += 4 * sizeof(int); ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++#ifndef MODULE_START ++static void *alloc_phys(unsigned long size) ++{ ++ unsigned order; ++ struct page *page; ++ struct page *p; ++ ++ size = PAGE_ALIGN(size); ++ order = get_order(size); ++ ++ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | ++ __GFP_THISNODE, order); ++ if (!page) ++ return NULL; ++ ++ split_page(page, order); ++ ++ /* mark all pages except for the last one */ ++ for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p) ++ set_bit(PG_owner_priv_1, &p->flags); ++ ++ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) ++ __free_page(p); ++ ++ return page_address(page); ++} ++#endif ++ ++static void free_phys(void *ptr) ++{ ++ struct page *page; ++ bool free; ++ ++ page = virt_to_page(ptr); ++ do { ++ free = test_and_clear_bit(PG_owner_priv_1, &page->flags); ++ __free_page(page); ++ page++; ++ } while (free); ++} ++ ++ + void *module_alloc(unsigned long size) + { ++#ifdef MODULE_START + return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END, + GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); ++#else ++ void *ptr; ++ ++ if (size == 0) ++ return NULL; ++ ++ ptr = alloc_phys(size); ++ ++ /* If we failed to allocate physically contiguous memory, ++ * fall back to regular vmalloc. The module loader code will ++ * create jump tables to handle long jumps */ ++ if (!ptr) ++ return vmalloc(size); ++ ++ return ptr; ++#endif + } ++ ++static inline bool is_phys_addr(void *ptr) ++{ ++#ifdef CONFIG_64BIT ++ return (KSEGX((unsigned long)ptr) == CKSEG0); ++#else ++ return (KSEGX(ptr) == KSEG0); + #endif ++} ++ ++/* Free memory returned from module_alloc */ ++void module_memfree(void *module_region) ++{ ++ if (is_phys_addr(module_region)) ++ free_phys(module_region); ++ else ++ vfree(module_region); ++} ++ ++static void *__module_alloc(int size, bool phys) ++{ ++ void *ptr; ++ ++ if (phys) ++ ptr = kmalloc(size, GFP_KERNEL); ++ else ++ ptr = vmalloc(size); ++ return ptr; ++} ++ ++static void __module_free(void *ptr) ++{ ++ if (is_phys_addr(ptr)) ++ kfree(ptr); ++ else ++ vfree(ptr); ++} ++ ++int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, ++ char *secstrings, struct module *mod) ++{ ++ unsigned int symindex = 0; ++ unsigned int core_size, init_size; ++ int i; ++ ++ mod->arch.phys_plt_offset = 0; ++ mod->arch.virt_plt_offset = 0; ++ mod->arch.phys_plt_tbl = NULL; ++ mod->arch.virt_plt_tbl = NULL; ++ ++ if (IS_ENABLED(CONFIG_64BIT)) ++ return 0; ++ ++ for (i = 1; i < hdr->e_shnum; i++) ++ if (sechdrs[i].sh_type == SHT_SYMTAB) ++ symindex = i; ++ ++ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); ++ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); ++ ++ if ((core_size + init_size) == 0) ++ return 0; ++ ++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); ++ if (!mod->arch.phys_plt_tbl) ++ return -ENOMEM; ++ ++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); ++ if (!mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ return -ENOMEM; ++ } ++ ++ return 0; ++} + + static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v) + { + *location = base + v; + } + ++static Elf_Addr add_plt_entry_to(unsigned *plt_offset, ++ void *start, Elf_Addr v) ++{ ++ unsigned *tramp = start + *plt_offset; ++ *plt_offset += 4 * sizeof(int); ++ ++ /* adjust carry for addiu */ ++ if (v & 0x00008000) ++ v += 0x10000; ++ ++ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ ++ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ ++ tramp[2] = 0x03200008; /* jr t9 */ ++ tramp[3] = 0x00000000; /* nop */ ++ ++ return (Elf_Addr) tramp; ++} ++ ++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) ++{ ++ if (is_phys_addr(location)) ++ return add_plt_entry_to(&me->arch.phys_plt_offset, ++ me->arch.phys_plt_tbl, v); ++ else ++ return add_plt_entry_to(&me->arch.virt_plt_offset, ++ me->arch.virt_plt_tbl, v); ++ ++} ++ + static int apply_r_mips_26(struct module *me, u32 *location, u32 base, + Elf_Addr v) + { ++ u32 ofs = base & 0x03ffffff; ++ + if (v % 4) { + pr_err("module %s: dangerous R_MIPS_26 relocation\n", + me->name); +@@ -56,13 +294,17 @@ static int apply_r_mips_26(struct module + } + + if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { +- pr_err("module %s: relocation overflow\n", +- me->name); +- return -ENOEXEC; ++ v = add_plt_entry(me, location, v + (ofs << 2)); ++ if (!v) { ++ pr_err("module %s: relocation overflow\n", ++ me->name); ++ return -ENOEXEC; ++ } ++ ofs = 0; + } + + *location = (*location & ~0x03ffffff) | +- ((base + (v >> 2)) & 0x03ffffff); ++ ((ofs + (v >> 2)) & 0x03ffffff); + + return 0; + } +@@ -442,9 +684,36 @@ int module_finalize(const Elf_Ehdr *hdr, + list_add(&me->arch.dbe_list, &dbe_list); + spin_unlock_irq(&dbe_lock); + } ++ ++ /* Get rid of the fixup trampoline if we're running the module ++ * from physically mapped address space */ ++ if (me->arch.phys_plt_offset == 0) { ++ __module_free(me->arch.phys_plt_tbl); ++ me->arch.phys_plt_tbl = NULL; ++ } ++ if (me->arch.virt_plt_offset == 0) { ++ __module_free(me->arch.virt_plt_tbl); ++ me->arch.virt_plt_tbl = NULL; ++ } ++ + return 0; + } + ++void module_arch_freeing_init(struct module *mod) ++{ ++ if (mod->state == MODULE_STATE_LIVE) ++ return; ++ ++ if (mod->arch.phys_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ } ++ if (mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.virt_plt_tbl); ++ mod->arch.virt_plt_tbl = NULL; ++ } ++} ++ + void module_arch_cleanup(struct module *mod) + { + spin_lock_irq(&dbe_lock); diff --git a/target/linux/generic/pending-6.6/308-mips32r2_tune.patch b/target/linux/generic/pending-6.6/308-mips32r2_tune.patch new file mode 100644 index 0000000000..db410a6bc0 --- /dev/null +++ b/target/linux/generic/pending-6.6/308-mips32r2_tune.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: kernel: add -mtune=34kc to MIPS CFLAGS when building for mips32r2 + +This provides a good tradeoff across at least 24Kc-74Kc, while also +producing smaller code. + +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -172,7 +172,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43 + cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap + cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap + cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap +-cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap ++cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -mtune=34kc -Wa,--trap + cflags-$(CONFIG_CPU_MIPS32_R5) += -march=mips32r5 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap diff --git a/target/linux/generic/pending-6.6/310-arm_module_unresolved_weak_sym.patch b/target/linux/generic/pending-6.6/310-arm_module_unresolved_weak_sym.patch new file mode 100644 index 0000000000..54cc9ba647 --- /dev/null +++ b/target/linux/generic/pending-6.6/310-arm_module_unresolved_weak_sym.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: fix errors in unresolved weak symbols on arm + +lede-commit: 570699d4838a907c3ef9f2819bf19eb72997b32f +Signed-off-by: Felix Fietkau +--- + arch/arm/kernel/module.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm/kernel/module.c ++++ b/arch/arm/kernel/module.c +@@ -146,6 +146,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons + return -ENOEXEC; + } + ++ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) && ++ ELF_ST_BIND(sym->st_info) == STB_WEAK) ++ continue; ++ + loc = dstsec->sh_addr + rel->r_offset; + + switch (ELF32_R_TYPE(rel->r_info)) { diff --git a/target/linux/generic/pending-6.6/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-6.6/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch new file mode 100644 index 0000000000..3f553b28b3 --- /dev/null +++ b/target/linux/generic/pending-6.6/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch @@ -0,0 +1,282 @@ +From: Yousong Zhou +Subject: MIPS: kexec: Accept command line parameters from userspace. + +Signed-off-by: Yousong Zhou +--- + arch/mips/kernel/machine_kexec.c | 153 +++++++++++++++++++++++++++++++----- + arch/mips/kernel/machine_kexec.h | 20 +++++ + arch/mips/kernel/relocate_kernel.S | 21 +++-- + 3 files changed, 167 insertions(+), 27 deletions(-) + create mode 100644 arch/mips/kernel/machine_kexec.h + +--- a/arch/mips/kernel/machine_kexec.c ++++ b/arch/mips/kernel/machine_kexec.c +@@ -9,14 +9,11 @@ + #include + #include + ++#include + #include + #include +- +-extern const unsigned char relocate_new_kernel[]; +-extern const size_t relocate_new_kernel_size; +- +-extern unsigned long kexec_start_address; +-extern unsigned long kexec_indirection_page; ++#include ++#include "machine_kexec.h" + + static unsigned long reboot_code_buffer; + +@@ -30,6 +27,101 @@ void (*_crash_smp_send_stop)(void) = NUL + void (*_machine_kexec_shutdown)(void) = NULL; + void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; + ++static void machine_kexec_print_args(void) ++{ ++ unsigned long argc = (int)kexec_args[0]; ++ int i; ++ ++ pr_info("kexec_args[0] (argc): %lu\n", argc); ++ pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]); ++ pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]); ++ pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]); ++ ++ for (i = 0; i < argc; i++) { ++ pr_info("kexec_argv[%d] = %p, %s\n", ++ i, kexec_argv[i], kexec_argv[i]); ++ } ++} ++ ++static void machine_kexec_init_argv(struct kimage *image) ++{ ++ void __user *buf = NULL; ++ size_t bufsz; ++ size_t size; ++ int i; ++ ++ bufsz = 0; ++ for (i = 0; i < image->nr_segments; i++) { ++ struct kexec_segment *seg; ++ ++ seg = &image->segment[i]; ++ if (seg->bufsz < 6) ++ continue; ++ ++ if (strncmp((char *) seg->buf, "kexec ", 6)) ++ continue; ++ ++ buf = seg->buf; ++ bufsz = seg->bufsz; ++ break; ++ } ++ ++ if (!buf) ++ return; ++ ++ size = KEXEC_COMMAND_LINE_SIZE; ++ size = min(size, bufsz); ++ if (size < bufsz) ++ pr_warn("kexec command line truncated to %zd bytes\n", size); ++ ++ /* Copy to kernel space */ ++ if (copy_from_user(kexec_argv_buf, buf, size)) ++ pr_warn("kexec command line copy to kernel space failed\n"); ++ ++ kexec_argv_buf[size - 1] = 0; ++} ++ ++static void machine_kexec_parse_argv(struct kimage *image) ++{ ++ char *reboot_code_buffer; ++ int reloc_delta; ++ char *ptr; ++ int argc; ++ int i; ++ ++ ptr = kexec_argv_buf; ++ argc = 0; ++ ++ /* ++ * convert command line string to array of parameters ++ * (as bootloader does). ++ */ ++ while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) { ++ if (*ptr == ' ') { ++ *ptr++ = '\0'; ++ continue; ++ } ++ ++ kexec_argv[argc++] = ptr; ++ ptr = strchr(ptr, ' '); ++ } ++ ++ if (!argc) ++ return; ++ ++ kexec_args[0] = argc; ++ kexec_args[1] = (unsigned long)kexec_argv; ++ kexec_args[2] = 0; ++ kexec_args[3] = 0; ++ ++ reboot_code_buffer = page_address(image->control_code_page); ++ reloc_delta = reboot_code_buffer - (char *)kexec_relocate_new_kernel; ++ ++ kexec_args[1] += reloc_delta; ++ for (i = 0; i < argc; i++) ++ kexec_argv[i] += reloc_delta; ++} ++ + static void kexec_image_info(const struct kimage *kimage) + { + unsigned long i; +@@ -99,6 +191,18 @@ machine_kexec_prepare(struct kimage *kim + #endif + + kexec_image_info(kimage); ++ /* ++ * Whenever arguments passed from kexec-tools, Init the arguments as ++ * the original ones to try avoiding booting failure. ++ */ ++ ++ kexec_args[0] = fw_arg0; ++ kexec_args[1] = fw_arg1; ++ kexec_args[2] = fw_arg2; ++ kexec_args[3] = fw_arg3; ++ ++ machine_kexec_init_argv(kimage); ++ machine_kexec_parse_argv(kimage); + + if (_machine_kexec_prepare) + return _machine_kexec_prepare(kimage); +@@ -161,7 +265,7 @@ machine_crash_shutdown(struct pt_regs *r + void kexec_nonboot_cpu_jump(void) + { + local_flush_icache_range((unsigned long)relocated_kexec_smp_wait, +- reboot_code_buffer + relocate_new_kernel_size); ++ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE); + + relocated_kexec_smp_wait(NULL); + } +@@ -199,7 +303,7 @@ void kexec_reboot(void) + * machine_kexec() CPU. + */ + local_flush_icache_range(reboot_code_buffer, +- reboot_code_buffer + relocate_new_kernel_size); ++ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE); + + do_kexec = (void *)reboot_code_buffer; + do_kexec(); +@@ -212,10 +316,12 @@ machine_kexec(struct kimage *image) + unsigned long *ptr; + + reboot_code_buffer = +- (unsigned long)page_address(image->control_code_page); ++ (unsigned long)page_address(image->control_code_page); ++ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer); + + kexec_start_address = + (unsigned long) phys_to_virt(image->start); ++ pr_info("kexec_start_address = %p\n", (void *)kexec_start_address); + + if (image->type == KEXEC_TYPE_DEFAULT) { + kexec_indirection_page = +@@ -223,9 +329,19 @@ machine_kexec(struct kimage *image) + } else { + kexec_indirection_page = (unsigned long)&image->head; + } ++ pr_info("kexec_indirection_page = %p\n", (void *)kexec_indirection_page); + +- memcpy((void*)reboot_code_buffer, relocate_new_kernel, +- relocate_new_kernel_size); ++ pr_info("Where is memcpy: %p\n", memcpy); ++ pr_info("kexec_relocate_new_kernel = %p, kexec_relocate_new_kernel_end = %p\n", ++ (void *)kexec_relocate_new_kernel, &kexec_relocate_new_kernel_end); ++ pr_info("Copy %lu bytes from %p to %p\n", KEXEC_RELOCATE_NEW_KERNEL_SIZE, ++ (void *)kexec_relocate_new_kernel, (void *)reboot_code_buffer); ++ memcpy((void*)reboot_code_buffer, kexec_relocate_new_kernel, ++ KEXEC_RELOCATE_NEW_KERNEL_SIZE); ++ ++ pr_info("Before _print_args().\n"); ++ machine_kexec_print_args(); ++ pr_info("Before eval loop.\n"); + + /* + * The generic kexec code builds a page list with physical +@@ -256,7 +372,7 @@ machine_kexec(struct kimage *image) + #ifdef CONFIG_SMP + /* All secondary cpus now may jump to kexec_wait cycle */ + relocated_kexec_smp_wait = reboot_code_buffer + +- (void *)(kexec_smp_wait - relocate_new_kernel); ++ (void *)(kexec_smp_wait - kexec_relocate_new_kernel); + smp_wmb(); + atomic_set(&kexec_ready_to_reboot, 1); + #endif +--- /dev/null ++++ b/arch/mips/kernel/machine_kexec.h +@@ -0,0 +1,20 @@ ++#ifndef _MACHINE_KEXEC_H ++#define _MACHINE_KEXEC_H ++ ++#ifndef __ASSEMBLY__ ++extern const unsigned char kexec_relocate_new_kernel[]; ++extern unsigned long kexec_relocate_new_kernel_end; ++extern unsigned long kexec_start_address; ++extern unsigned long kexec_indirection_page; ++ ++extern char kexec_argv_buf[]; ++extern char *kexec_argv[]; ++ ++#define KEXEC_RELOCATE_NEW_KERNEL_SIZE ((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel) ++#endif /* !__ASSEMBLY__ */ ++ ++#define KEXEC_COMMAND_LINE_SIZE 256 ++#define KEXEC_ARGV_SIZE (KEXEC_COMMAND_LINE_SIZE / 16) ++#define KEXEC_MAX_ARGC (KEXEC_ARGV_SIZE / sizeof(long)) ++ ++#endif +--- a/arch/mips/kernel/relocate_kernel.S ++++ b/arch/mips/kernel/relocate_kernel.S +@@ -10,10 +10,11 @@ + #include + #include + #include ++#include "machine_kexec.h" + + #include + +-LEAF(relocate_new_kernel) ++LEAF(kexec_relocate_new_kernel) + PTR_L a0, arg0 + PTR_L a1, arg1 + PTR_L a2, arg2 +@@ -98,7 +99,7 @@ done: + #endif + /* jump to kexec_start_address */ + j s1 +- END(relocate_new_kernel) ++ END(kexec_relocate_new_kernel) + + #ifdef CONFIG_SMP + /* +@@ -177,8 +178,15 @@ EXPORT(kexec_indirection_page) + PTR_WD 0 + .size kexec_indirection_page, PTRSIZE + +-relocate_new_kernel_end: ++kexec_argv_buf: ++ EXPORT(kexec_argv_buf) ++ .skip KEXEC_COMMAND_LINE_SIZE ++ .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE ++ ++kexec_argv: ++ EXPORT(kexec_argv) ++ .skip KEXEC_ARGV_SIZE ++ .size kexec_argv, KEXEC_ARGV_SIZE + +-EXPORT(relocate_new_kernel_size) +- PTR_WD relocate_new_kernel_end - relocate_new_kernel +- .size relocate_new_kernel_size, PTRSIZE ++kexec_relocate_new_kernel_end: ++ EXPORT(kexec_relocate_new_kernel_end) diff --git a/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch new file mode 100644 index 0000000000..30158cf399 --- /dev/null +++ b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch @@ -0,0 +1,84 @@ +From bb0c3b0175240bf152fd7c644821a0cf9f77c37c Mon Sep 17 00:00:00 2001 +From: Evgeniy Didin +Date: Fri, 15 Mar 2019 18:53:38 +0300 +Subject: [PATCH] arc add OWRTDTB section + +This change allows OpenWRT to patch resulting kernel binary with +external .dtb. + +That allows us to re-use exactky the same vmlinux on different boards +given its ARC core configurations match (at least cache line sizes etc). + +""patch-dtb" searches for ASCII "OWRTDTB:" strign and copies external +.dtb right after it, keeping the string in place. + +Signed-off-by: Eugeniy Paltsev +Signed-off-by: Alexey Brodkin +Signed-off-by: Evgeniy Didin +--- + arch/arc/kernel/head.S | 10 ++++++++++ + arch/arc/kernel/setup.c | 4 +++- + arch/arc/kernel/vmlinux.lds.S | 13 +++++++++++++ + 3 files changed, 26 insertions(+), 1 deletion(-) + +--- a/arch/arc/kernel/head.S ++++ b/arch/arc/kernel/head.S +@@ -88,6 +88,16 @@ + DSP_EARLY_INIT + .endm + ++ ; Here "patch-dtb" will embed external .dtb ++ ; Note "patch-dtb" searches for ASCII "OWRTDTB:" string ++ ; and pastes .dtb right after it, hense the string precedes ++ ; __image_dtb symbol. ++ .section .owrt, "aw",@progbits ++ .ascii "OWRTDTB:" ++ENTRY(__image_dtb) ++ .fill 0x4000 ++END(__image_dtb) ++ + .section .init.text, "ax",@progbits + + ;---------------------------------------------------------------- +--- a/arch/arc/kernel/setup.c ++++ b/arch/arc/kernel/setup.c +@@ -495,6 +495,8 @@ static inline bool uboot_arg_invalid(uns + /* We always pass 0 as magic from U-boot */ + #define UBOOT_MAGIC_VALUE 0 + ++extern struct boot_param_header __image_dtb; ++ + void __init handle_uboot_args(void) + { + bool use_embedded_dtb = true; +@@ -533,7 +535,7 @@ void __init handle_uboot_args(void) + ignore_uboot_args: + + if (use_embedded_dtb) { +- machine_desc = setup_machine_fdt(__dtb_start); ++ machine_desc = setup_machine_fdt(&__image_dtb); + if (!machine_desc) + panic("Embedded DT invalid\n"); + } +--- a/arch/arc/kernel/vmlinux.lds.S ++++ b/arch/arc/kernel/vmlinux.lds.S +@@ -27,6 +27,19 @@ SECTIONS + + . = CONFIG_LINUX_LINK_BASE; + ++ /* ++ * In OpenWRT we want to patch built binary embedding .dtb of choice. ++ * This is implemented with "patch-dtb" utility which searches for ++ * "OWRTDTB:" string in first 16k of image and if it is found ++ * copies .dtb right after mentioned string. ++ * ++ * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it. ++ */ ++ .owrt : { ++ *(.owrt) ++ . = ALIGN(PAGE_SIZE); ++ } ++ + _int_vec_base_lds = .; + .vector : { + *(.vector) diff --git a/target/linux/generic/pending-6.6/333-arc-enable-unaligned-access-in-kernel-mode.patch b/target/linux/generic/pending-6.6/333-arc-enable-unaligned-access-in-kernel-mode.patch new file mode 100644 index 0000000000..1848a84cc4 --- /dev/null +++ b/target/linux/generic/pending-6.6/333-arc-enable-unaligned-access-in-kernel-mode.patch @@ -0,0 +1,24 @@ +From: Alexey Brodkin +Subject: arc: enable unaligned access in kernel mode + +This enables misaligned access handling even in kernel mode. +Some wireless drivers (ath9k-htc and mt7601u) use misaligned accesses +here and there and to cope with that without fixing stuff in the drivers +we're just gracefully handling it on ARC. + +Signed-off-by: Alexey Brodkin +--- + arch/arc/kernel/unaligned.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arc/kernel/unaligned.c ++++ b/arch/arc/kernel/unaligned.c +@@ -202,7 +202,7 @@ int misaligned_fixup(unsigned long addre + char buf[TASK_COMM_LEN]; + + /* handle user mode only and only if enabled by sysadmin */ +- if (!user_mode(regs) || !unaligned_enabled) ++ if (!unaligned_enabled) + return 1; + + if (no_unaligned_warning) { diff --git a/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch new file mode 100644 index 0000000000..e9b47d185d --- /dev/null +++ b/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch @@ -0,0 +1,25 @@ +From 66770a004afe10df11d3902e16eaa0c2c39436bb Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Fri, 24 May 2019 17:56:19 +0200 +Subject: [PATCH] powerpc: Enable kernel XZ compression option on PPC_85xx + +Enable kernel XZ compression option on PPC_85xx. Tested with +simpleImage on TP-Link TL-WDR4900 (Freescale P1014 processor). + +Suggested-by: Christian Lamparter +Signed-off-by: Pawel Dembicki +--- + arch/powerpc/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -229,7 +229,7 @@ config PPC + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE + select HAVE_KERNEL_LZO if DEFAULT_UIMAGE +- select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x ++ select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x || PPC_85xx + select HAVE_KPROBES + select HAVE_KPROBES_ON_FTRACE + select HAVE_KRETPROBES diff --git a/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch b/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch new file mode 100644 index 0000000000..2675ca4791 --- /dev/null +++ b/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch @@ -0,0 +1,113 @@ +From patchwork Thu Mar 16 19:28:33 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13178238 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 5EF2AC6FD19 + for ; Thu, 16 Mar 2023 19:28:43 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S230076AbjCPT2l (ORCPT ); + Thu, 16 Mar 2023 15:28:41 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56412 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S230039AbjCPT2k (ORCPT + ); Thu, 16 Mar 2023 15:28:40 -0400 +Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com + [IPv6:2a00:1450:4864:20::42f]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7259B7D9F; + Thu, 16 Mar 2023 12:28:38 -0700 (PDT) +Received: by mail-wr1-x42f.google.com with SMTP id y14so2539231wrq.4; + Thu, 16 Mar 2023 12:28:38 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1678994917; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=j8afldfRZftLeVmekmQfoh01jVdumsVP7nkKoPaU3Q0=; + b=FzMRr5ekh/fDiJqTlezNj6nLjzvn5z92FtYeB8MquVSMB8PuvarccnyqAzsXiccf+v + uwRFIomnTWNLGVjzc1xrB2hGiCKD3jBo5n1u8p/yEV6rpolbxVjfM7eTHXyAHXGXz7ZJ + TPeVbWfAlxiSD6+BPtXr/efehcdI64fIoL6G/U1WHNMo01Tzr/Obf3y5tug17N0fGcXg + CH6E5a2HguZUtwrm26LcK9IOV/7xEx5eIE1cOvTLMxPbGWaZwEjjP16HylJr06xRLhaf + RpiYBT3mXwwuOx0jLOhqavY/2kZ9GVbZRWMMwZrZv9xNO13SBwc1VUVgD4k3FntnSk7Z + AaOQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1678994917; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=j8afldfRZftLeVmekmQfoh01jVdumsVP7nkKoPaU3Q0=; + b=OaA5DMgqalrfqO5iOtmmxFPsH90MkN7l4EJpyVnzuiO1Wd6rSCpqPOR7xpxZno8OPP + tdfm4vzn9Ie4AUDbFKDTUlPG+tgkmIruo3K9C0VnY9DD2PRZMEYBbWaJKU1otqKt0NKu + IAAHNvxvQvCESKzbXFLYwWbRKFScOSMGmGBTDfgThz51A18Ff1hJy/BmnuZk7M2TLgHO + wQpy9t7oeB/Hkxl41y46emLc/nESsvwvAG/fx/zPzCe9UiaQLrdZq+BKeOwSBedktzK5 + U/ZTfgzU2UGSI67aGRqqGnI0uXq+MAJMK18qzM0VByxj6W+AXJ6BJr5P0quljeQ8upSg + bEUg== +X-Gm-Message-State: AO0yUKWnqTlccBDnqwCSRdqOBGc2FyfiLy1Tg7EjPENlISpzXuDYwW/R + lJSI06rrfq+Vel/SigfpGJI= +X-Google-Smtp-Source: + AK7set/jYfYl9ttVzIXJO+ZQVfa6cE/yOsP8fx4teiTmGNNWyVlIJRzMAlF3IUGqRAXAmY3hAabIuQ== +X-Received: by 2002:a5d:40ce:0:b0:2cd:ceab:df1a with SMTP id + b14-20020a5d40ce000000b002cdceabdf1amr381006wrq.32.1678994916642; + Thu, 16 Mar 2023 12:28:36 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + l10-20020a5d4bca000000b002cfea3c49d5sm180041wrt.52.2023.03.16.12.28.35 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Thu, 16 Mar 2023 12:28:35 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: f.fainelli@gmail.com, jonas.gorski@gmail.com, + bcm-kernel-feedback-list@broadcom.com, tglx@linutronix.de, + maz@kernel.org, linux-mips@vger.kernel.org, + linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v2] irqchip/bcm-6345-l1: request memory region +Date: Thu, 16 Mar 2023 20:28:33 +0100 +Message-Id: <20230316192833.1603149-1-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230316180701.783785-1-noltari@gmail.com> +References: <20230316180701.783785-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: linux-mips@vger.kernel.org + +Request memory region in order to display it in /proc/iomem. +Also stop printing the MMIO address since it just displays (ptrval). + +Signed-off-by: Álvaro Fernández Rojas +Acked-by: Florian Fainelli +--- + v2: request memory region and stop displaying MMIO address. + + drivers/irqchip/irq-bcm6345-l1.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/irqchip/irq-bcm6345-l1.c ++++ b/drivers/irqchip/irq-bcm6345-l1.c +@@ -253,6 +253,9 @@ static int __init bcm6345_l1_init_one(st + if (!cpu->map_base) + return -ENOMEM; + ++ if (!request_mem_region(res.start, sz, res.name)) ++ pr_err("failed to request intc memory"); ++ + for (i = 0; i < n_words; i++) { + cpu->enable_cache[i] = 0; + __raw_writel(0, cpu->map_base + reg_enable(intc, i)); +@@ -331,8 +334,7 @@ static int __init bcm6345_l1_of_init(str + for_each_cpu(idx, &intc->cpumask) { + struct bcm6345_l1_cpu *cpu = intc->cpus[idx]; + +- pr_info(" CPU%u at MMIO 0x%p (irq = %d)\n", idx, +- cpu->map_base, cpu->parent_irq); ++ pr_info(" CPU%u (irq = %d)\n", idx, cpu->parent_irq); + } + + return 0; diff --git a/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch new file mode 100644 index 0000000000..c619d12ce5 --- /dev/null +++ b/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch @@ -0,0 +1,328 @@ +From 39717277d5c87bdb183cf2f258957b44ba99b4df Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 11:47:35 +0200 +Subject: [PATCH] mtd: mtdsplit support + +--- + drivers/mtd/Kconfig | 19 ++++ + drivers/mtd/Makefile | 2 + + drivers/mtd/mtdpart.c | 169 ++++++++++++++++++++++++++++----- + include/linux/mtd/mtd.h | 25 +++++ + include/linux/mtd/partitions.h | 7 ++ + 5 files changed, 197 insertions(+), 25 deletions(-) + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -12,6 +12,25 @@ menuconfig MTD + + if MTD + ++menu "OpenWrt specific MTD options" ++ ++config MTD_ROOTFS_ROOT_DEV ++ bool "Automatically set 'rootfs' partition to be root filesystem" ++ default y ++ ++config MTD_SPLIT_FIRMWARE ++ bool "Automatically split firmware partition for kernel+rootfs" ++ default y ++ ++config MTD_SPLIT_FIRMWARE_NAME ++ string "Firmware partition name" ++ depends on MTD_SPLIT_FIRMWARE ++ default "firmware" ++ ++source "drivers/mtd/mtdsplit/Kconfig" ++ ++endmenu ++ + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" + depends on m +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -9,6 +9,8 @@ mtd-y := mtdcore.o mtdsuper.o mtdconc + + obj-y += parsers/ + ++obj-$(CONFIG_MTD_SPLIT) += mtdsplit/ ++ + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o + obj-$(CONFIG_MTD_BLOCK) += mtdblock.o +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -15,11 +15,13 @@ + #include + #include + #include ++#include + #include + #include + #include + + #include "mtdcore.h" ++#include "mtdsplit/mtdsplit.h" + + /* + * MTD methods which simply translate the effective address and pass through +@@ -236,6 +238,147 @@ static int mtd_add_partition_attrs(struc + return ret; + } + ++static DEFINE_SPINLOCK(part_parser_lock); ++static LIST_HEAD(part_parsers); ++ ++static struct mtd_part_parser *mtd_part_parser_get(const char *name) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ list_for_each_entry(p, &part_parsers, list) ++ if (!strcmp(p->name, name) && try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++ ++static inline void mtd_part_parser_put(const struct mtd_part_parser *p) ++{ ++ module_put(p->owner); ++} ++ ++static struct mtd_part_parser * ++get_partition_parser_by_type(enum mtd_parser_type type, ++ struct mtd_part_parser *start) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ p = list_prepare_entry(start, &part_parsers, list); ++ if (start) ++ mtd_part_parser_put(start); ++ ++ list_for_each_entry_continue(p, &part_parsers, list) { ++ if (p->type == type && try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++ ++static int parse_mtd_partitions_by_type(struct mtd_info *master, ++ enum mtd_parser_type type, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct mtd_part_parser *prev = NULL; ++ int ret = 0; ++ ++ while (1) { ++ struct mtd_part_parser *parser; ++ ++ parser = get_partition_parser_by_type(type, prev); ++ if (!parser) ++ break; ++ ++ ret = (*parser->parse_fn)(master, pparts, data); ++ ++ if (ret > 0) { ++ mtd_part_parser_put(parser); ++ printk(KERN_NOTICE ++ "%d %s partitions found on MTD device %s\n", ++ ret, parser->name, master->name); ++ break; ++ } ++ ++ prev = parser; ++ } ++ ++ return ret; ++} ++ ++static int ++run_parsers_by_type(struct mtd_info *child, enum mtd_parser_type type) ++{ ++ struct mtd_partition *parts; ++ int nr_parts; ++ int i; ++ ++ nr_parts = parse_mtd_partitions_by_type(child, type, (const struct mtd_partition **)&parts, ++ NULL); ++ if (nr_parts <= 0) ++ return nr_parts; ++ ++ if (WARN_ON(!parts)) ++ return 0; ++ ++ for (i = 0; i < nr_parts; i++) { ++ /* adjust partition offsets */ ++ parts[i].offset += child->part.offset; ++ ++ mtd_add_partition(child->parent, ++ parts[i].name, ++ parts[i].offset, ++ parts[i].size); ++ } ++ ++ kfree(parts); ++ ++ return nr_parts; ++} ++ ++#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#else ++#define SPLIT_FIRMWARE_NAME "unused" ++#endif ++ ++static void split_firmware(struct mtd_info *master, struct mtd_info *part) ++{ ++ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); ++} ++ ++static void mtd_partition_split(struct mtd_info *master, struct mtd_info *part) ++{ ++ static int rootfs_found = 0; ++ ++ if (rootfs_found) ++ return; ++ ++ if (of_find_property(mtd_get_of_node(part), "linux,rootfs", NULL) || ++ !strcmp(part->name, "rootfs")) { ++ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); ++ ++ rootfs_found = 1; ++ } ++ ++ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && ++ !strcmp(part->name, SPLIT_FIRMWARE_NAME) && ++ !of_find_property(mtd_get_of_node(part), "compatible", NULL)) ++ split_firmware(master, part); ++} ++ + int mtd_add_partition(struct mtd_info *parent, const char *name, + long long offset, long long length) + { +@@ -274,6 +417,7 @@ int mtd_add_partition(struct mtd_info *p + if (ret) + goto err_remove_part; + ++ mtd_partition_split(parent, child); + mtd_add_partition_attrs(child); + + return 0; +@@ -422,6 +566,7 @@ int add_mtd_partitions(struct mtd_info * + goto err_del_partitions; + } + ++ mtd_partition_split(master, child); + mtd_add_partition_attrs(child); + + /* Look for subpartitions */ +@@ -438,31 +583,6 @@ err_del_partitions: + return ret; + } + +-static DEFINE_SPINLOCK(part_parser_lock); +-static LIST_HEAD(part_parsers); +- +-static struct mtd_part_parser *mtd_part_parser_get(const char *name) +-{ +- struct mtd_part_parser *p, *ret = NULL; +- +- spin_lock(&part_parser_lock); +- +- list_for_each_entry(p, &part_parsers, list) +- if (!strcmp(p->name, name) && try_module_get(p->owner)) { +- ret = p; +- break; +- } +- +- spin_unlock(&part_parser_lock); +- +- return ret; +-} +- +-static inline void mtd_part_parser_put(const struct mtd_part_parser *p) +-{ +- module_put(p->owner); +-} +- + /* + * Many partition parsers just expected the core to kfree() all their data in + * one chunk. Do that by default. +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -615,6 +615,24 @@ static inline void mtd_align_erase_req(s + req->len += mtd->erasesize - mod; + } + ++static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round up to next erase block */ ++ return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize; ++} ++ ++static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round down to the start of the current erase block */ ++ return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize; ++} ++ + static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) + { + if (mtd->writesize_shift) +@@ -688,6 +706,13 @@ extern struct mtd_info *of_get_mtd_devic + extern struct mtd_info *get_mtd_device_nm(const char *name); + extern void put_mtd_device(struct mtd_info *mtd); + ++static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) ++{ ++ if (!mtd_is_partition(mtd)) ++ return 0; ++ ++ return mtd->part.offset; ++} + + struct mtd_notifier { + void (*add)(struct mtd_info *mtd); +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -75,6 +75,12 @@ struct mtd_part_parser_data { + * Functions dealing with the various ways of partitioning the space + */ + ++enum mtd_parser_type { ++ MTD_PARSER_TYPE_DEVICE = 0, ++ MTD_PARSER_TYPE_ROOTFS, ++ MTD_PARSER_TYPE_FIRMWARE, ++}; ++ + struct mtd_part_parser { + struct list_head list; + struct module *owner; +@@ -83,6 +89,7 @@ struct mtd_part_parser { + int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, + struct mtd_part_parser_data *); + void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); ++ enum mtd_parser_type type; + }; + + /* Container for passing around a set of parsed partitions */ diff --git a/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch new file mode 100644 index 0000000000..42b5a564b1 --- /dev/null +++ b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch @@ -0,0 +1,48 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 31 Oct 2023 15:51:01 +0100 +Subject: [PATCH] mtd: don't register NVMEM devices for partitions with custom + drivers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes issue exposed by upstream commit f4cf4e5db331 ("Revert +"nvmem: add new config option""). + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -519,6 +519,29 @@ static int mtd_nvmem_add(struct mtd_info + struct device_node *node = mtd_get_of_node(mtd); + struct nvmem_config config = {}; + ++ /* ++ * Do NOT register NVMEM device for any partition that is meant to be ++ * handled by a U-Boot env driver. That would result in associating two ++ * different NVMEM devices with the same OF node. ++ * ++ * An example of unwanted behaviour of above (forwardtrace): ++ * of_get_mac_addr_nvmem() ++ * of_nvmem_cell_get() ++ * __nvmem_device_get() ++ * ++ * We can't have __nvmem_device_get() return "mtdX" NVMEM device instead ++ * of U-Boot env NVMEM device. That would result in failing to find ++ * NVMEM cell. ++ * ++ * This issue seems to affect U-Boot env case only and will go away with ++ * switch to NVMEM layouts. ++ */ ++ if (of_device_is_compatible(node, "u-boot,env") || ++ of_device_is_compatible(node, "u-boot,env-redundant-bool") || ++ of_device_is_compatible(node, "u-boot,env-redundant-count") || ++ of_device_is_compatible(node, "brcm,env")) ++ return 0; ++ + config.id = -1; + config.dev = &mtd->dev; + config.name = dev_name(&mtd->dev); diff --git a/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch new file mode 100644 index 0000000000..c7da2f8834 --- /dev/null +++ b/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -0,0 +1,245 @@ +From acacdac272927ae1d96e0bca51eb82899671eaea Mon Sep 17 00:00:00 2001 +From: John Thomson +Date: Fri, 25 Dec 2020 18:50:08 +1000 +Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Do not prevent writing to mtd partitions where a partition boundary sits +on a minor erasesize boundary. +This addresses a FIXME that has been present since the start of the +linux git history: +/* Doesn't start on a boundary of major erase size */ +/* FIXME: Let it be writable if it is on a boundary of + * _minor_ erase size though */ + +Allow a uniform erase region spi-nor device to be configured +to use the non-uniform erase regions code path for an erase with: +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y + +On supporting hardware (SECT_4K: majority of current SPI-NOR device) +provide the facility for an erase to use the least number +of SPI-NOR operations, as well as access to 4K erase without +requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + +Introduce erasesize_minor to the mtd struct, +the smallest erasesize supported by the device + +On existing devices, this is useful where write support is wanted +for data on a 4K partition, such as some u-boot-env partitions, +or RouterBoot soft_config, while still netting the performance +benefits of using 64K sectors + +Performance: +time mtd erase firmware +OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length + +Without this patch +MTD_SPI_NOR_USE_4K_SECTORS=y |n +real 2m 11.66s |0m 50.86s +user 0m 0.00s |0m 0.00s +sys 1m 56.20s |0m 50.80s + +With this patch +MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y |4K_SECTORS=y +real 0m 51.68s |0m 50.85s |2m 12.89s +user 0m 0.00s |0m 0.00s |0m 0.01s +sys 0m 46.94s |0m 50.38s |2m 12.46s + +Signed-off-by: John Thomson +Signed-off-by: Thibaut VARÈNE + +--- + +checkpatch does not like the printk(KERN_WARNING +these should be changed separately beforehand? + +Changes v1 -> v2: +Added mtdcore sysfs for erasesize_minor +Removed finding minor erasesize for variable erase regions device, +as untested and no responses regarding it. +Moved IF_ENABLED for SPINOR variable erase to guard setting +erasesize_minor in spi-nor/core.c +Removed setting erasesize to minor where partition boundaries require +minor erase to be writable +Simplified minor boundary check by relying on minor being a factor of +major + +Changes RFC -> v1: +Fix uninitialized variable smatch warning +Reported-by: kernel test robot +Reported-by: Dan Carpenter +--- + drivers/mtd/mtdcore.c | 10 ++++++++++ + drivers/mtd/mtdpart.c | 35 +++++++++++++++++++++++++---------- + drivers/mtd/spi-nor/Kconfig | 10 ++++++++++ + drivers/mtd/spi-nor/core.c | 11 +++++++++-- + include/linux/mtd/mtd.h | 2 ++ + 5 files changed, 56 insertions(+), 12 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -169,6 +169,15 @@ static ssize_t mtd_erasesize_show(struct + } + MTD_DEVICE_ATTR_RO(erasesize); + ++static ssize_t mtd_erasesize_minor_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct mtd_info *mtd = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize_minor); ++} ++MTD_DEVICE_ATTR_RO(erasesize_minor); ++ + static ssize_t mtd_writesize_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -314,6 +323,7 @@ static struct attribute *mtd_attrs[] = { + &dev_attr_flags.attr, + &dev_attr_size.attr, + &dev_attr_erasesize.attr, ++ &dev_attr_erasesize_minor.attr, + &dev_attr_writesize.attr, + &dev_attr_subpagesize.attr, + &dev_attr_oobsize.attr, +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -41,6 +41,7 @@ static struct mtd_info *allocate_partiti + struct mtd_info *master = mtd_get_master(parent); + int wr_alignment = (parent->flags & MTD_NO_ERASE) ? + master->writesize : master->erasesize; ++ int wr_alignment_minor = 0; + u64 parent_size = mtd_is_partition(parent) ? + parent->part.size : parent->size; + struct mtd_info *child; +@@ -165,6 +166,7 @@ static struct mtd_info *allocate_partiti + } else { + /* Single erase size */ + child->erasesize = master->erasesize; ++ child->erasesize_minor = master->erasesize_minor; + } + + /* +@@ -172,26 +174,39 @@ static struct mtd_info *allocate_partiti + * exposes several regions with different erasesize. Adjust + * wr_alignment accordingly. + */ +- if (!(child->flags & MTD_NO_ERASE)) ++ if (!(child->flags & MTD_NO_ERASE)) { + wr_alignment = child->erasesize; ++ wr_alignment_minor = child->erasesize_minor; ++ } + + tmp = mtd_get_master_ofs(child, 0); + remainder = do_div(tmp, wr_alignment); + if ((child->flags & MTD_WRITEABLE) && remainder) { +- /* Doesn't start on a boundary of major erase size */ +- /* FIXME: Let it be writable if it is on a boundary of +- * _minor_ erase size though */ +- child->flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", +- part->name); ++ if (wr_alignment_minor) { ++ /* rely on minor being a factor of major erasesize */ ++ tmp = remainder; ++ remainder = do_div(tmp, wr_alignment_minor); ++ } ++ if (remainder) { ++ child->flags &= ~MTD_WRITEABLE; ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", ++ part->name); ++ } + } + + tmp = mtd_get_master_ofs(child, 0) + child->part.size; + remainder = do_div(tmp, wr_alignment); + if ((child->flags & MTD_WRITEABLE) && remainder) { +- child->flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", +- part->name); ++ if (wr_alignment_minor) { ++ tmp = remainder; ++ remainder = do_div(tmp, wr_alignment_minor); ++ } ++ ++ if (remainder) { ++ child->flags &= ~MTD_WRITEABLE; ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", ++ part->name); ++ } + } + + child->size = child->part.size; +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR + + if MTD_SPI_NOR + ++config MTD_SPI_NOR_USE_VARIABLE_ERASE ++ bool "Disable uniform_erase to allow use of all hardware supported erasesizes" ++ depends on !MTD_SPI_NOR_USE_4K_SECTORS ++ default n ++ help ++ Allow mixed use of all hardware supported erasesizes, ++ by forcing spi_nor to use the multiple eraseregions code path. ++ For example: A 68K erase will use one 64K erase, and one 4K erase ++ on supporting hardware. ++ + config MTD_SPI_NOR_USE_4K_SECTORS + bool "Use small 4096 B erase sectors" + default y +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1050,6 +1050,8 @@ static u8 spi_nor_convert_3to4_erase(u8 + + static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) + { ++ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE)) ++ return false; + return !!nor->params->erase_map.uniform_erase_type; + } + +@@ -2158,6 +2160,7 @@ static int spi_nor_select_erase(struct s + { + struct spi_nor_erase_map *map = &nor->params->erase_map; + const struct spi_nor_erase_type *erase = NULL; ++ const struct spi_nor_erase_type *erase_minor = NULL; + struct mtd_info *mtd = &nor->mtd; + u32 wanted_size = nor->info->sector_size; + int i; +@@ -2190,8 +2193,9 @@ static int spi_nor_select_erase(struct s + */ + for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { + if (map->erase_type[i].size) { +- erase = &map->erase_type[i]; +- break; ++ if (!erase) ++ erase = &map->erase_type[i]; ++ erase_minor = &map->erase_type[i]; + } + } + +@@ -2199,6 +2203,9 @@ static int spi_nor_select_erase(struct s + return -EINVAL; + + mtd->erasesize = erase->size; ++ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) && ++ erase_minor && erase_minor->size < erase->size) ++ mtd->erasesize_minor = erase_minor->size; + return 0; + } + +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -245,6 +245,8 @@ struct mtd_info { + * information below if they desire + */ + uint32_t erasesize; ++ /* "Minor" (smallest) erase size supported by the whole device */ ++ uint32_t erasesize_minor; + /* Minimal writable flash unit size. In case of NOR flash it is 1 (even + * though individual bits can be cleared), in case of NAND flash it is + * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR diff --git a/target/linux/generic/pending-6.6/420-mtd-redboot_space.patch b/target/linux/generic/pending-6.6/420-mtd-redboot_space.patch new file mode 100644 index 0000000000..5518ea71dd --- /dev/null +++ b/target/linux/generic/pending-6.6/420-mtd-redboot_space.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Subject: add patch for including unpartitioned space in the rootfs partition for redboot devices (if applicable) + +[john@phrozen.org: used by ixp and others] + +lede-commit: 394918851f84e4d00fa16eb900e7700e95091f00 +Signed-off-by: Felix Fietkau +--- + drivers/mtd/redboot.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/mtd/parsers/redboot.c ++++ b/drivers/mtd/parsers/redboot.c +@@ -278,14 +278,21 @@ nogood: + #endif + names += strlen(names) + 1; + +-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED + if (fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { +- i++; +- parts[i].offset = parts[i - 1].size + parts[i - 1].offset; +- parts[i].size = fl->next->img->flash_base - parts[i].offset; +- parts[i].name = nullname; +- } ++ if (!strcmp(parts[i].name, "rootfs")) { ++ parts[i].size = fl->next->img->flash_base; ++ parts[i].size &= ~(master->erasesize - 1); ++ parts[i].size -= parts[i].offset; ++#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED ++ nrparts--; ++ } else { ++ i++; ++ parts[i].offset = parts[i-1].size + parts[i-1].offset; ++ parts[i].size = fl->next->img->flash_base - parts[i].offset; ++ parts[i].name = nullname; + #endif ++ } ++ } + tmp_fl = fl; + fl = fl->next; + kfree(tmp_fl); diff --git a/target/linux/generic/pending-6.6/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.6/430-mtd-add-myloader-partition-parser.patch new file mode 100644 index 0000000000..35e80d6dcc --- /dev/null +++ b/target/linux/generic/pending-6.6/430-mtd-add-myloader-partition-parser.patch @@ -0,0 +1,229 @@ +From: Florian Fainelli +Subject: Add myloader partition table parser + +[john@phozen.org: shoud be upstreamable] + +lede-commit: d8bf22859b51faa09d22c056fe221a45d2f7a3b8 +Signed-off-by: Florian Fainelli +[adjust for kernel 5.4, add myloader.c to patch] +Signed-off-by: Adrian Schmutzler + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -67,6 +67,22 @@ config MTD_CMDLINE_PARTS + + If unsure, say 'N'. + ++config MTD_MYLOADER_PARTS ++ tristate "MyLoader partition parsing" ++ depends on ADM5120 || ATH79 ++ help ++ MyLoader is a bootloader which allows the user to define partitions ++ in flash devices, by putting a table in the second erase block ++ on the device, similar to a partition table. This table gives the ++ offsets and lengths of the user defined partitions. ++ ++ If you need code which can detect and parse these tables, and ++ register MTD 'partitions' corresponding to each image detected, ++ enable this option. ++ ++ You will still need the parsing functions to be called by the driver ++ for your particular device. It won't happen automatically. ++ + config MTD_OF_PARTS + tristate "OpenFirmware (device tree) partitioning parser" + default y +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -4,6 +4,7 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4 + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_BRCM_U_BOOT) += brcm_u-boot.o + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o ++obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o + ofpart-y += ofpart_core.o + ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o +--- /dev/null ++++ b/drivers/mtd/parsers/myloader.c +@@ -0,0 +1,181 @@ ++/* ++ * Parse MyLoader-style flash partition tables and produce a Linux partition ++ * array to match. ++ * ++ * Copyright (C) 2007-2009 Gabor Juhos ++ * ++ * This file was based on drivers/mtd/redboot.c ++ * Author: Red Hat, Inc. - David Woodhouse ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BLOCK_LEN_MIN 0x10000 ++#define PART_NAME_LEN 32 ++ ++struct part_data { ++ struct mylo_partition_table tab; ++ char names[MYLO_MAX_PARTITIONS][PART_NAME_LEN]; ++}; ++ ++static int myloader_parse_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct part_data *buf; ++ struct mylo_partition_table *tab; ++ struct mylo_partition *part; ++ struct mtd_partition *mtd_parts; ++ struct mtd_partition *mtd_part; ++ int num_parts; ++ int ret, i; ++ size_t retlen; ++ char *names; ++ unsigned long offset; ++ unsigned long blocklen; ++ ++ buf = vmalloc(sizeof(*buf)); ++ if (!buf) { ++ return -ENOMEM; ++ goto out; ++ } ++ tab = &buf->tab; ++ ++ blocklen = master->erasesize; ++ if (blocklen < BLOCK_LEN_MIN) ++ blocklen = BLOCK_LEN_MIN; ++ ++ offset = blocklen; ++ ++ /* Find the partition table */ ++ for (i = 0; i < 4; i++, offset += blocklen) { ++ printk(KERN_DEBUG "%s: searching for MyLoader partition table" ++ " at offset 0x%lx\n", master->name, offset); ++ ++ ret = mtd_read(master, offset, sizeof(*buf), &retlen, ++ (void *)buf); ++ if (ret) ++ goto out_free_buf; ++ ++ if (retlen != sizeof(*buf)) { ++ ret = -EIO; ++ goto out_free_buf; ++ } ++ ++ /* Check for Partition Table magic number */ ++ if (tab->magic == le32_to_cpu(MYLO_MAGIC_PARTITIONS)) ++ break; ++ ++ } ++ ++ if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) { ++ printk(KERN_DEBUG "%s: no MyLoader partition table found\n", ++ master->name); ++ ret = 0; ++ goto out_free_buf; ++ } ++ ++ /* The MyLoader and the Partition Table is always present */ ++ num_parts = 2; ++ ++ /* Detect number of used partitions */ ++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { ++ part = &tab->partitions[i]; ++ ++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) ++ continue; ++ ++ num_parts++; ++ } ++ ++ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + ++ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ ++ if (!mtd_parts) { ++ ret = -ENOMEM; ++ goto out_free_buf; ++ } ++ ++ mtd_part = mtd_parts; ++ names = (char *)&mtd_parts[num_parts]; ++ ++ strncpy(names, "myloader", PART_NAME_LEN); ++ mtd_part->name = names; ++ mtd_part->offset = 0; ++ mtd_part->size = offset; ++ mtd_part->mask_flags = MTD_WRITEABLE; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ ++ strncpy(names, "partition_table", PART_NAME_LEN); ++ mtd_part->name = names; ++ mtd_part->offset = offset; ++ mtd_part->size = blocklen; ++ mtd_part->mask_flags = MTD_WRITEABLE; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ ++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { ++ part = &tab->partitions[i]; ++ ++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) ++ continue; ++ ++ if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) ++ strncpy(names, buf->names[i], PART_NAME_LEN); ++ else ++ snprintf(names, PART_NAME_LEN, "partition%d", i); ++ ++ mtd_part->offset = le32_to_cpu(part->addr); ++ mtd_part->size = le32_to_cpu(part->size); ++ mtd_part->name = names; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ } ++ ++ *pparts = mtd_parts; ++ ret = num_parts; ++ ++ out_free_buf: ++ vfree(buf); ++ out: ++ return ret; ++} ++ ++static struct mtd_part_parser myloader_mtd_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = myloader_parse_partitions, ++ .name = "MyLoader", ++}; ++ ++static int __init myloader_mtd_parser_init(void) ++{ ++ register_mtd_parser(&myloader_mtd_parser); ++ ++ return 0; ++} ++ ++static void __exit myloader_mtd_parser_exit(void) ++{ ++ deregister_mtd_parser(&myloader_mtd_parser); ++} ++ ++module_init(myloader_mtd_parser_init); ++module_exit(myloader_mtd_parser_exit); ++ ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/pending-6.6/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/target/linux/generic/pending-6.6/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch new file mode 100644 index 0000000000..bcea45d009 --- /dev/null +++ b/target/linux/generic/pending-6.6/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch @@ -0,0 +1,68 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/mtd/parsers/parser_trx.c ++++ b/drivers/mtd/parsers/parser_trx.c +@@ -25,6 +25,33 @@ struct trx_header { + uint32_t offset[3]; + } __packed; + ++/* ++ * Calculate real end offset (address) for a given amount of data. It checks ++ * all blocks skipping bad ones. ++ */ ++static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes) ++{ ++ size_t real_offset = 0; ++ ++ if (mtd_block_isbad(mtd, real_offset)) ++ pr_warn("Base offset shouldn't be at bad block"); ++ ++ while (bytes >= mtd->erasesize) { ++ bytes -= mtd->erasesize; ++ real_offset += mtd->erasesize; ++ while (mtd_block_isbad(mtd, real_offset)) { ++ real_offset += mtd->erasesize; ++ ++ if (real_offset >= mtd->size) ++ return real_offset - mtd->erasesize; ++ } ++ } ++ ++ real_offset += bytes; ++ ++ return real_offset; ++} ++ + static const char *parser_trx_data_part_name(struct mtd_info *master, + size_t offset) + { +@@ -86,21 +113,21 @@ static int parser_trx_parse(struct mtd_i + if (trx.offset[2]) { + part = &parts[curr_part++]; + part->name = "loader"; +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); + i++; + } + + if (trx.offset[i]) { + part = &parts[curr_part++]; + part->name = "linux"; +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); + i++; + } + + if (trx.offset[i]) { + part = &parts[curr_part++]; +- part->name = parser_trx_data_part_name(mtd, trx.offset[i]); +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); ++ part->name = parser_trx_data_part_name(mtd, part->offset); + i++; + } + diff --git a/target/linux/generic/pending-6.6/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/target/linux/generic/pending-6.6/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch new file mode 100644 index 0000000000..852654d924 --- /dev/null +++ b/target/linux/generic/pending-6.6/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch @@ -0,0 +1,37 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: mtd: bcm47xxpart: detect T_Meter partition + +It can be found on many Netgear devices. It consists of many 0x30 blocks +starting with 4D 54. + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/bcm47xxpart.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/parsers/bcm47xxpart.c ++++ b/drivers/mtd/parsers/bcm47xxpart.c +@@ -35,6 +35,7 @@ + #define NVRAM_HEADER 0x48534C46 /* FLSH */ + #define POT_MAGIC1 0x54544f50 /* POTT */ + #define POT_MAGIC2 0x504f /* OP */ ++#define T_METER_MAGIC 0x4D540000 /* MT */ + #define ML_MAGIC1 0x39685a42 + #define ML_MAGIC2 0x26594131 + #define TRX_MAGIC 0x30524448 +@@ -178,6 +179,15 @@ static int bcm47xxpart_parse(struct mtd_ + MTD_WRITEABLE); + continue; + } ++ ++ /* T_Meter */ ++ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC && ++ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC && ++ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) { ++ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset, ++ MTD_WRITEABLE); ++ continue; ++ } + + /* TRX */ + if (buf[0x000 / 4] == TRX_MAGIC) { diff --git a/target/linux/generic/pending-6.6/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-6.6/435-mtd-add-routerbootpart-parser-config.patch new file mode 100644 index 0000000000..a42dcc868f --- /dev/null +++ b/target/linux/generic/pending-6.6/435-mtd-add-routerbootpart-parser-config.patch @@ -0,0 +1,38 @@ +From 4437e01fb6bca63fccdba5d6c44888b0935885c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= +Date: Tue, 24 Mar 2020 11:45:07 +0100 +Subject: [PATCH] generic: routerboot partition build bits (5.4) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds routerbootpart kernel build bits + +Signed-off-by: Thibaut VARÈNE +--- + drivers/mtd/parsers/Kconfig | 9 +++++++++ + drivers/mtd/parsers/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -236,3 +236,12 @@ config MTD_SERCOMM_PARTS + partition map. This partition table contains real partition + offsets, which may differ from device to device depending on the + number and location of bad blocks on NAND. ++ ++config MTD_ROUTERBOOT_PARTS ++ tristate "RouterBoot flash partition parser" ++ depends on MTD && OF ++ help ++ MikroTik RouterBoot is implemented as a multi segment system on the ++ flash, some of which are fixed and some of which are located at ++ variable offsets. This parser handles both cases via properly ++ formatted DTS. +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -17,3 +17,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa + obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o + obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o ++obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o diff --git a/target/linux/generic/pending-6.6/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch b/target/linux/generic/pending-6.6/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch new file mode 100644 index 0000000000..063d3fa79c --- /dev/null +++ b/target/linux/generic/pending-6.6/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch @@ -0,0 +1,121 @@ +From ffbbe7d66872ff8957dad2136133e28a1fd5d437 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 22:51:05 +0100 +Subject: [PATCH 01/15] dt-bindings: mtd: add basic bindings for UBI + +Add basic bindings for UBI devices and volumes. + +Signed-off-by: Daniel Golle +--- + .../bindings/mtd/partitions/linux,ubi.yaml | 65 +++++++++++++++++++ + .../bindings/mtd/partitions/ubi-volume.yaml | 35 ++++++++++ + 2 files changed, 100 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml +@@ -0,0 +1,65 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/linux,ubi.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Unsorted Block Images ++ ++description: | ++ UBI ("Unsorted Block Images") is a volume management system for raw ++ flash devices which manages multiple logical volumes on a single ++ physical flash device and spreads the I/O load (i.e wear-leveling) ++ across the whole flash chip. ++ ++maintainers: ++ - Daniel Golle ++ ++allOf: ++ - $ref: partition.yaml# ++ ++properties: ++ compatible: ++ const: linux,ubi ++ ++ volumes: ++ type: object ++ description: UBI Volumes ++ ++ patternProperties: ++ "^ubi-volume-.*$": ++ $ref: /schemas/mtd/partitions/ubi-volume.yaml# ++ ++ unevaluatedProperties: false ++ ++required: ++ - compatible ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ reg = <0x0 0x100000>; ++ label = "bootloader"; ++ read-only; ++ }; ++ ++ partition@100000 { ++ reg = <0x100000 0x1ff00000>; ++ label = "ubi"; ++ compatible = "linux,ubi"; ++ ++ volumes { ++ ubi-volume-caldata { ++ volid = <2>; ++ volname = "rf"; ++ }; ++ }; ++ }; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml +@@ -0,0 +1,35 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/ubi-volume.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: UBI volume ++ ++description: | ++ This binding describes a single UBI volume. Volumes can be matches either ++ by their ID or their name, or both. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ volid: ++ $ref: "/schemas/types.yaml#/definitions/uint32" ++ description: ++ Match UBI volume ID ++ ++ volname: ++ $ref: "/schemas/types.yaml#/definitions/string" ++ description: ++ Match UBI volume ID ++ ++anyOf: ++ - required: ++ - volid ++ ++ - required: ++ - volname ++ ++# This is a generic file other binding inherit from and extend ++additionalProperties: true diff --git a/target/linux/generic/pending-6.6/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch b/target/linux/generic/pending-6.6/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch new file mode 100644 index 0000000000..823c8e83b7 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch @@ -0,0 +1,48 @@ +From e4dad3aa5c3ab9c553555dd23c0b85f725f2eb51 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 22:53:01 +0100 +Subject: [PATCH 02/15] dt-bindings: mtd: ubi-volume: allow UBI volumes to + provide NVMEM + +UBI volumes may be used to contain NVMEM bits, typically device MAC +addresses or wireless radio calibration data. + +Signed-off-by: Daniel Golle +--- + .../devicetree/bindings/mtd/partitions/linux,ubi.yaml | 10 ++++++++++ + .../devicetree/bindings/mtd/partitions/ubi-volume.yaml | 5 +++++ + 2 files changed, 15 insertions(+) + +--- a/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml ++++ b/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml +@@ -59,6 +59,16 @@ examples: + ubi-volume-caldata { + volid = <2>; + volname = "rf"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ eeprom@0 { ++ reg = <0x0 0x1000>; ++ }; ++ }; + }; + }; + }; +--- a/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml ++++ b/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml +@@ -24,6 +24,11 @@ properties: + description: + Match UBI volume ID + ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ description: ++ This container may reference an NVMEM layout parser. ++ + anyOf: + - required: + - volid diff --git a/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch new file mode 100644 index 0000000000..eda3b108da --- /dev/null +++ b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch @@ -0,0 +1,225 @@ +From e5cf19bd8204925f3bd2067df9e867313eac388b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 1 May 2023 11:57:51 +0100 +Subject: [PATCH 03/15] mtd: ubi: block: use notifier to create ubiblock from + parameter + +Use UBI_VOLUME_ADDED notification to create ubiblock device specified +on kernel cmdline or module parameter. +This makes thing more simple and has the advantage that ubiblock devices +on volumes which are not present at the time the ubi module is probed +will still be created. + +Suggested-by: Zhihao Cheng +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 154 ++++++++++++++++++++++------------------ + 1 file changed, 85 insertions(+), 69 deletions(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -67,10 +68,10 @@ struct ubiblock_pdu { + }; + + /* Numbers of elements set in the @ubiblock_param array */ +-static int ubiblock_devs __initdata; ++static int ubiblock_devs; + + /* MTD devices specification parameters */ +-static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata; ++static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES]; + + struct ubiblock { + struct ubi_volume_desc *desc; +@@ -504,7 +505,7 @@ int ubiblock_remove(struct ubi_volume_in + } + + /* Found a device, let's lock it so we can check if it's busy */ +- mutex_lock(&dev->dev_mutex); ++ mutex_lock_nested(&dev->dev_mutex, SINGLE_DEPTH_NESTING); + if (dev->refcnt > 0) { + ret = -EBUSY; + goto out_unlock_dev; +@@ -567,6 +568,85 @@ static int ubiblock_resize(struct ubi_vo + return 0; + } + ++static bool ++match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) ++{ ++ int err, len; ++ struct path path; ++ struct kstat stat; ++ ++ if (ubi_num == -1) { ++ /* No ubi num, name must be a vol device path */ ++ err = kern_path(name, LOOKUP_FOLLOW, &path); ++ if (err) ++ return false; ++ ++ err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); ++ path_put(&path); ++ if (err) ++ return false; ++ ++ if (!S_ISCHR(stat.mode)) ++ return false; ++ ++ if (vi->ubi_num != ubi_major2num(MAJOR(stat.rdev))) ++ return false; ++ ++ if (vi->vol_id != MINOR(stat.rdev) - 1) ++ return false; ++ ++ return true; ++ } ++ ++ if (vol_id == -1) { ++ if (vi->ubi_num != ubi_num) ++ return false; ++ ++ len = strnlen(name, UBI_VOL_NAME_MAX + 1); ++ if (len < 1 || vi->name_len != len) ++ return false; ++ ++ if (strcmp(name, vi->name)) ++ return false; ++ ++ return true; ++ } ++ ++ if (vi->ubi_num != ubi_num) ++ return false; ++ ++ if (vi->vol_id != vol_id) ++ return false; ++ ++ return true; ++} ++ ++static void ++ubiblock_create_from_param(struct ubi_volume_info *vi) ++{ ++ int i, ret = 0; ++ struct ubiblock_param *p; ++ ++ /* ++ * Iterate over ubiblock cmdline parameters. If a parameter matches the ++ * newly added volume create the ubiblock device for it. ++ */ ++ for (i = 0; i < ubiblock_devs; i++) { ++ p = &ubiblock_param[i]; ++ ++ if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) ++ continue; ++ ++ ret = ubiblock_create(vi); ++ if (ret) { ++ pr_err( ++ "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", ++ vi->name, p->ubi_num, p->vol_id, ret); ++ } ++ break; ++ } ++} ++ + static int ubiblock_notify(struct notifier_block *nb, + unsigned long notification_type, void *ns_ptr) + { +@@ -574,10 +654,7 @@ static int ubiblock_notify(struct notifi + + switch (notification_type) { + case UBI_VOLUME_ADDED: +- /* +- * We want to enforce explicit block device creation for +- * volumes, so when a volume is added we do nothing. +- */ ++ ubiblock_create_from_param(&nt->vi); + break; + case UBI_VOLUME_REMOVED: + ubiblock_remove(&nt->vi); +@@ -603,56 +680,6 @@ static struct notifier_block ubiblock_no + .notifier_call = ubiblock_notify, + }; + +-static struct ubi_volume_desc * __init +-open_volume_desc(const char *name, int ubi_num, int vol_id) +-{ +- if (ubi_num == -1) +- /* No ubi num, name must be a vol device path */ +- return ubi_open_volume_path(name, UBI_READONLY); +- else if (vol_id == -1) +- /* No vol_id, must be vol_name */ +- return ubi_open_volume_nm(ubi_num, name, UBI_READONLY); +- else +- return ubi_open_volume(ubi_num, vol_id, UBI_READONLY); +-} +- +-static void __init ubiblock_create_from_param(void) +-{ +- int i, ret = 0; +- struct ubiblock_param *p; +- struct ubi_volume_desc *desc; +- struct ubi_volume_info vi; +- +- /* +- * If there is an error creating one of the ubiblocks, continue on to +- * create the following ubiblocks. This helps in a circumstance where +- * the kernel command-line specifies multiple block devices and some +- * may be broken, but we still want the working ones to come up. +- */ +- for (i = 0; i < ubiblock_devs; i++) { +- p = &ubiblock_param[i]; +- +- desc = open_volume_desc(p->name, p->ubi_num, p->vol_id); +- if (IS_ERR(desc)) { +- pr_err( +- "UBI: block: can't open volume on ubi%d_%d, err=%ld\n", +- p->ubi_num, p->vol_id, PTR_ERR(desc)); +- continue; +- } +- +- ubi_get_volume_info(desc, &vi); +- ubi_close_volume(desc); +- +- ret = ubiblock_create(&vi); +- if (ret) { +- pr_err( +- "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", +- vi.name, p->ubi_num, p->vol_id, ret); +- continue; +- } +- } +-} +- + static void ubiblock_remove_all(void) + { + struct ubiblock *next; +@@ -678,18 +705,7 @@ int __init ubiblock_init(void) + if (ubiblock_major < 0) + return ubiblock_major; + +- /* +- * Attach block devices from 'block=' module param. +- * Even if one block device in the param list fails to come up, +- * still allow the module to load and leave any others up. +- */ +- ubiblock_create_from_param(); +- +- /* +- * Block devices are only created upon user requests, so we ignore +- * existing volumes. +- */ +- ret = ubi_register_volume_notifier(&ubiblock_notifier, 1); ++ ret = ubi_register_volume_notifier(&ubiblock_notifier, 0); + if (ret) + goto err_unreg; + return 0; diff --git a/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch b/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch new file mode 100644 index 0000000000..6e10e5ebed --- /dev/null +++ b/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch @@ -0,0 +1,264 @@ +From 471a17d8d1b838092d1a76e48cdce8b5b67ff809 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 27 Nov 2023 01:54:28 +0000 +Subject: [PATCH 04/15] mtd: ubi: attach from device tree + +Introduce device tree compatible 'linux,ubi' and attach compatible MTD +devices using the MTD add notifier. This is needed for a UBI device to +be available early at boot (and not only after late_initcall), so +volumes on them can be used eg. as NVMEM providers for other drivers. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/build.c | 146 ++++++++++++++++++++++++++++------------ + drivers/mtd/ubi/cdev.c | 2 +- + drivers/mtd/ubi/ubi.h | 2 +- + 3 files changed, 106 insertions(+), 44 deletions(-) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include "ubi.h" +@@ -1071,6 +1072,7 @@ out_free: + * ubi_detach_mtd_dev - detach an MTD device. + * @ubi_num: UBI device number to detach from + * @anyway: detach MTD even if device reference count is not zero ++ * @have_lock: called by MTD notifier holding mtd_table_mutex + * + * This function destroys an UBI device number @ubi_num and detaches the + * underlying MTD device. Returns zero in case of success and %-EBUSY if the +@@ -1080,7 +1082,7 @@ out_free: + * Note, the invocations of this function has to be serialized by the + * @ubi_devices_mutex. + */ +-int ubi_detach_mtd_dev(int ubi_num, int anyway) ++int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock) + { + struct ubi_device *ubi; + +@@ -1136,7 +1138,11 @@ int ubi_detach_mtd_dev(int ubi_num, int + vfree(ubi->peb_buf); + vfree(ubi->fm_buf); + ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index); +- put_mtd_device(ubi->mtd); ++ if (have_lock) ++ __put_mtd_device(ubi->mtd); ++ else ++ put_mtd_device(ubi->mtd); ++ + put_device(&ubi->dev); + return 0; + } +@@ -1213,43 +1219,43 @@ static struct mtd_info * __init open_mtd + return mtd; + } + +-static int __init ubi_init(void) ++static void ubi_notify_add(struct mtd_info *mtd) + { +- int err, i, k; ++ struct device_node *np = mtd_get_of_node(mtd); ++ int err; + +- /* Ensure that EC and VID headers have correct size */ +- BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); +- BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); ++ if (!of_device_is_compatible(np, "linux,ubi")) ++ return; + +- if (mtd_devs > UBI_MAX_DEVICES) { +- pr_err("UBI error: too many MTD devices, maximum is %d\n", +- UBI_MAX_DEVICES); +- return -EINVAL; +- } ++ /* ++ * we are already holding &mtd_table_mutex, but still need ++ * to bump refcount ++ */ ++ err = __get_mtd_device(mtd); ++ if (err) ++ return; + +- /* Create base sysfs directory and sysfs files */ +- err = class_register(&ubi_class); ++ /* called while holding mtd_table_mutex */ ++ mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING); ++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false); ++ mutex_unlock(&ubi_devices_mutex); + if (err < 0) +- return err; +- +- err = misc_register(&ubi_ctrl_cdev); +- if (err) { +- pr_err("UBI error: cannot register device\n"); +- goto out; +- } ++ __put_mtd_device(mtd); ++} + +- ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", +- sizeof(struct ubi_wl_entry), +- 0, 0, NULL); +- if (!ubi_wl_entry_slab) { +- err = -ENOMEM; +- goto out_dev_unreg; +- } ++static void ubi_notify_remove(struct mtd_info *mtd) ++{ ++ WARN(1, "mtd%d removed despite UBI still being attached", mtd->index); ++} + +- err = ubi_debugfs_init(); +- if (err) +- goto out_slab; ++static struct mtd_notifier ubi_mtd_notifier = { ++ .add = ubi_notify_add, ++ .remove = ubi_notify_remove, ++}; + ++static int __init ubi_init_attach(void) ++{ ++ int err, i, k; + + /* Attach MTD devices */ + for (i = 0; i < mtd_devs; i++) { +@@ -1297,25 +1303,79 @@ static int __init ubi_init(void) + } + } + ++ return 0; ++ ++out_detach: ++ for (k = 0; k < i; k++) ++ if (ubi_devices[k]) { ++ mutex_lock(&ubi_devices_mutex); ++ ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1, false); ++ mutex_unlock(&ubi_devices_mutex); ++ } ++ return err; ++} ++#ifndef CONFIG_MTD_UBI_MODULE ++late_initcall(ubi_init_attach); ++#endif ++ ++static int __init ubi_init(void) ++{ ++ int err; ++ ++ /* Ensure that EC and VID headers have correct size */ ++ BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); ++ BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); ++ ++ if (mtd_devs > UBI_MAX_DEVICES) { ++ pr_err("UBI error: too many MTD devices, maximum is %d\n", ++ UBI_MAX_DEVICES); ++ return -EINVAL; ++ } ++ ++ /* Create base sysfs directory and sysfs files */ ++ err = class_register(&ubi_class); ++ if (err < 0) ++ return err; ++ ++ err = misc_register(&ubi_ctrl_cdev); ++ if (err) { ++ pr_err("UBI error: cannot register device\n"); ++ goto out; ++ } ++ ++ ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", ++ sizeof(struct ubi_wl_entry), ++ 0, 0, NULL); ++ if (!ubi_wl_entry_slab) { ++ err = -ENOMEM; ++ goto out_dev_unreg; ++ } ++ ++ err = ubi_debugfs_init(); ++ if (err) ++ goto out_slab; ++ + err = ubiblock_init(); + if (err) { + pr_err("UBI error: block: cannot initialize, error %d\n", err); + + /* See comment above re-ubi_is_module(). */ + if (ubi_is_module()) +- goto out_detach; ++ goto out_slab; ++ } ++ ++ register_mtd_user(&ubi_mtd_notifier); ++ ++ if (ubi_is_module()) { ++ err = ubi_init_attach(); ++ if (err) ++ goto out_mtd_notifier; + } + + return 0; + +-out_detach: +- for (k = 0; k < i; k++) +- if (ubi_devices[k]) { +- mutex_lock(&ubi_devices_mutex); +- ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1); +- mutex_unlock(&ubi_devices_mutex); +- } +- ubi_debugfs_exit(); ++out_mtd_notifier: ++ unregister_mtd_user(&ubi_mtd_notifier); + out_slab: + kmem_cache_destroy(ubi_wl_entry_slab); + out_dev_unreg: +@@ -1325,18 +1385,20 @@ out: + pr_err("UBI error: cannot initialize UBI, error %d\n", err); + return err; + } +-late_initcall(ubi_init); ++device_initcall(ubi_init); ++ + + static void __exit ubi_exit(void) + { + int i; + + ubiblock_exit(); ++ unregister_mtd_user(&ubi_mtd_notifier); + + for (i = 0; i < UBI_MAX_DEVICES; i++) + if (ubi_devices[i]) { + mutex_lock(&ubi_devices_mutex); +- ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1); ++ ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1, false); + mutex_unlock(&ubi_devices_mutex); + } + ubi_debugfs_exit(); +--- a/drivers/mtd/ubi/cdev.c ++++ b/drivers/mtd/ubi/cdev.c +@@ -1065,7 +1065,7 @@ static long ctrl_cdev_ioctl(struct file + } + + mutex_lock(&ubi_devices_mutex); +- err = ubi_detach_mtd_dev(ubi_num, 0); ++ err = ubi_detach_mtd_dev(ubi_num, 0, false); + mutex_unlock(&ubi_devices_mutex); + break; + } +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -939,7 +939,7 @@ int ubi_io_write_vid_hdr(struct ubi_devi + int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, + int vid_hdr_offset, int max_beb_per1024, + bool disable_fm); +-int ubi_detach_mtd_dev(int ubi_num, int anyway); ++int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock); + struct ubi_device *ubi_get_device(int ubi_num); + void ubi_put_device(struct ubi_device *ubi); + struct ubi_device *ubi_get_by_major(int major); diff --git a/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch b/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch new file mode 100644 index 0000000000..d5da37b856 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch @@ -0,0 +1,226 @@ +From 2d664266cfdd114cc7a1fa28dd64275e99222455 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 8 Jun 2023 17:18:09 +0100 +Subject: [PATCH 05/15] mtd: ubi: introduce pre-removal notification for UBI + volumes + +Introduce a new notification type UBI_VOLUME_SHUTDOWN to inform users +that a volume is just about to be removed. +This is needed because users (such as the NVMEM subsystem) expect that +at the time their removal function is called, the parenting device is +still available (for removal of sysfs nodes, for example, in case of +NVMEM which otherwise WARNs on volume removal). + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 26 ++++++++++++++++++++++++++ + drivers/mtd/ubi/build.c | 20 +++++++++++++++----- + drivers/mtd/ubi/kapi.c | 2 +- + drivers/mtd/ubi/ubi.h | 2 ++ + drivers/mtd/ubi/vmt.c | 17 +++++++++++++++-- + include/linux/mtd/ubi.h | 2 ++ + 6 files changed, 61 insertions(+), 8 deletions(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -568,6 +568,29 @@ static int ubiblock_resize(struct ubi_vo + return 0; + } + ++static int ubiblock_shutdown(struct ubi_volume_info *vi) ++{ ++ struct ubiblock *dev; ++ struct gendisk *disk; ++ int ret = 0; ++ ++ mutex_lock(&devices_mutex); ++ dev = find_dev_nolock(vi->ubi_num, vi->vol_id); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ disk = dev->gd; ++ ++out_unlock: ++ mutex_unlock(&devices_mutex); ++ ++ if (!ret) ++ blk_mark_disk_dead(disk); ++ ++ return ret; ++}; ++ + static bool + match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) + { +@@ -659,6 +682,9 @@ static int ubiblock_notify(struct notifi + case UBI_VOLUME_REMOVED: + ubiblock_remove(&nt->vi); + break; ++ case UBI_VOLUME_SHUTDOWN: ++ ubiblock_shutdown(&nt->vi); ++ break; + case UBI_VOLUME_RESIZED: + ubiblock_resize(&nt->vi); + break; +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -89,7 +89,7 @@ static struct ubi_device *ubi_devices[UB + /* Serializes UBI devices creations and removals */ + DEFINE_MUTEX(ubi_devices_mutex); + +-/* Protects @ubi_devices and @ubi->ref_count */ ++/* Protects @ubi_devices, @ubi->ref_count and @ubi->is_dead */ + static DEFINE_SPINLOCK(ubi_devices_lock); + + /* "Show" method for files in '//class/ubi/' */ +@@ -258,6 +258,9 @@ struct ubi_device *ubi_get_device(int ub + + spin_lock(&ubi_devices_lock); + ubi = ubi_devices[ubi_num]; ++ if (ubi && ubi->is_dead) ++ ubi = NULL; ++ + if (ubi) { + ubi_assert(ubi->ref_count >= 0); + ubi->ref_count += 1; +@@ -295,7 +298,7 @@ struct ubi_device *ubi_get_by_major(int + spin_lock(&ubi_devices_lock); + for (i = 0; i < UBI_MAX_DEVICES; i++) { + ubi = ubi_devices[i]; +- if (ubi && MAJOR(ubi->cdev.dev) == major) { ++ if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) { + ubi_assert(ubi->ref_count >= 0); + ubi->ref_count += 1; + get_device(&ubi->dev); +@@ -324,7 +327,7 @@ int ubi_major2num(int major) + for (i = 0; i < UBI_MAX_DEVICES; i++) { + struct ubi_device *ubi = ubi_devices[i]; + +- if (ubi && MAJOR(ubi->cdev.dev) == major) { ++ if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) { + ubi_num = ubi->ubi_num; + break; + } +@@ -511,7 +514,7 @@ static void ubi_free_volumes_from(struct + int i; + + for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { +- if (!ubi->volumes[i]) ++ if (!ubi->volumes[i] || ubi->volumes[i]->is_dead) + continue; + ubi_eba_replace_table(ubi->volumes[i], NULL); + ubi_fastmap_destroy_checkmap(ubi->volumes[i]); +@@ -1094,10 +1097,10 @@ int ubi_detach_mtd_dev(int ubi_num, int + return -EINVAL; + + spin_lock(&ubi_devices_lock); +- put_device(&ubi->dev); + ubi->ref_count -= 1; + if (ubi->ref_count) { + if (!anyway) { ++ ubi->ref_count += 1; + spin_unlock(&ubi_devices_lock); + return -EBUSY; + } +@@ -1105,6 +1108,13 @@ int ubi_detach_mtd_dev(int ubi_num, int + ubi_err(ubi, "%s reference count %d, destroy anyway", + ubi->ubi_name, ubi->ref_count); + } ++ ubi->is_dead = true; ++ spin_unlock(&ubi_devices_lock); ++ ++ ubi_notify_all(ubi, UBI_VOLUME_SHUTDOWN, NULL); ++ ++ spin_lock(&ubi_devices_lock); ++ put_device(&ubi->dev); + ubi_devices[ubi_num] = NULL; + spin_unlock(&ubi_devices_lock); + +--- a/drivers/mtd/ubi/kapi.c ++++ b/drivers/mtd/ubi/kapi.c +@@ -152,7 +152,7 @@ struct ubi_volume_desc *ubi_open_volume( + + spin_lock(&ubi->volumes_lock); + vol = ubi->volumes[vol_id]; +- if (!vol) ++ if (!vol || vol->is_dead) + goto out_unlock; + + err = -EBUSY; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -345,6 +345,7 @@ struct ubi_volume { + int writers; + int exclusive; + int metaonly; ++ bool is_dead; + + int reserved_pebs; + int vol_type; +@@ -564,6 +565,7 @@ struct ubi_device { + spinlock_t volumes_lock; + int ref_count; + int image_seq; ++ bool is_dead; + + int rsvd_pebs; + int avail_pebs; +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -59,7 +59,7 @@ static ssize_t vol_attribute_show(struct + struct ubi_device *ubi = vol->ubi; + + spin_lock(&ubi->volumes_lock); +- if (!ubi->volumes[vol->vol_id]) { ++ if (!ubi->volumes[vol->vol_id] || ubi->volumes[vol->vol_id]->is_dead) { + spin_unlock(&ubi->volumes_lock); + return -ENODEV; + } +@@ -189,7 +189,7 @@ int ubi_create_volume(struct ubi_device + + /* Ensure that the name is unique */ + for (i = 0; i < ubi->vtbl_slots; i++) +- if (ubi->volumes[i] && ++ if (ubi->volumes[i] && !ubi->volumes[i]->is_dead && + ubi->volumes[i]->name_len == req->name_len && + !strcmp(ubi->volumes[i]->name, req->name)) { + ubi_err(ubi, "volume \"%s\" exists (ID %d)", +@@ -352,6 +352,19 @@ int ubi_remove_volume(struct ubi_volume_ + err = -EBUSY; + goto out_unlock; + } ++ ++ /* ++ * Mark volume as dead at this point to prevent that anyone ++ * can take a reference to the volume from now on. ++ * This is necessary as we have to release the spinlock before ++ * calling ubi_volume_notify. ++ */ ++ vol->is_dead = true; ++ spin_unlock(&ubi->volumes_lock); ++ ++ ubi_volume_notify(ubi, vol, UBI_VOLUME_SHUTDOWN); ++ ++ spin_lock(&ubi->volumes_lock); + ubi->volumes[vol_id] = NULL; + spin_unlock(&ubi->volumes_lock); + +--- a/include/linux/mtd/ubi.h ++++ b/include/linux/mtd/ubi.h +@@ -192,6 +192,7 @@ struct ubi_device_info { + * or a volume was removed) + * @UBI_VOLUME_RESIZED: a volume has been re-sized + * @UBI_VOLUME_RENAMED: a volume has been re-named ++ * @UBI_VOLUME_SHUTDOWN: a volume is going to removed, shutdown users + * @UBI_VOLUME_UPDATED: data has been written to a volume + * + * These constants define which type of event has happened when a volume +@@ -202,6 +203,7 @@ enum { + UBI_VOLUME_REMOVED, + UBI_VOLUME_RESIZED, + UBI_VOLUME_RENAMED, ++ UBI_VOLUME_SHUTDOWN, + UBI_VOLUME_UPDATED, + }; + diff --git a/target/linux/generic/pending-6.6/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch b/target/linux/generic/pending-6.6/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch new file mode 100644 index 0000000000..1322766965 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch @@ -0,0 +1,65 @@ +From 3a041ee543cdf2e707a1dd72946cd6a583509b28 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 21 Jul 2023 19:26:37 +0100 +Subject: [PATCH 06/15] mtd: ubi: populate ubi volume fwnode + +Look for the 'volumes' subnode of an MTD partition attached to a UBI +device and attach matching child nodes to UBI volumes. +This allows UBI volumes to be referenced in device tree, e.g. for use +as NVMEM providers. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/vmt.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -124,6 +124,31 @@ static void vol_release(struct device *d + kfree(vol); + } + ++static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol) ++{ ++ struct fwnode_handle *fw_vols, *fw_vol; ++ const char *volname; ++ u32 volid; ++ ++ fw_vols = device_get_named_child_node(vol->dev.parent->parent, "volumes"); ++ if (!fw_vols) ++ return NULL; ++ ++ fwnode_for_each_child_node(fw_vols, fw_vol) { ++ if (!fwnode_property_read_string(fw_vol, "volname", &volname) && ++ strncmp(volname, vol->name, vol->name_len)) ++ continue; ++ ++ if (!fwnode_property_read_u32(fw_vol, "volid", &volid) && ++ vol->vol_id != volid) ++ continue; ++ ++ return fw_vol; ++ } ++ ++ return NULL; ++} ++ + /** + * ubi_create_volume - create volume. + * @ubi: UBI device description object +@@ -223,6 +248,7 @@ int ubi_create_volume(struct ubi_device + vol->name_len = req->name_len; + memcpy(vol->name, req->name, vol->name_len); + vol->ubi = ubi; ++ device_set_node(&vol->dev, find_volume_fwnode(vol)); + + /* + * Finish all pending erases because there may be some LEBs belonging +@@ -605,6 +631,7 @@ int ubi_add_volume(struct ubi_device *ub + vol->dev.class = &ubi_class; + vol->dev.groups = volume_dev_groups; + dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id); ++ device_set_node(&vol->dev, find_volume_fwnode(vol)); + err = device_register(&vol->dev); + if (err) { + cdev_del(&vol->cdev); diff --git a/target/linux/generic/pending-6.6/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch b/target/linux/generic/pending-6.6/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch new file mode 100644 index 0000000000..59a1eb9374 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch @@ -0,0 +1,246 @@ +From 7eb6666348f3f2d1f7308c712fa5903cbe189401 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 8 Jun 2023 17:22:04 +0100 +Subject: [PATCH 07/15] mtd: ubi: provide NVMEM layer over UBI volumes + +In an ideal world we would like UBI to be used where ever possible on a +NAND chip. And with UBI support in ARM Trusted Firmware and U-Boot it +is possible to achieve an (almost-)all-UBI flash layout. Hence the need +for a way to also use UBI volumes to store board-level constants, such +as MAC addresses and calibration data of wireless interfaces. + +Add UBI volume NVMEM driver module exposing UBI volumes as NVMEM +providers. Allow UBI devices to have a "volumes" firmware subnode with +volumes which may be compatible with "nvmem-cells". +Access to UBI volumes via the NVMEM interface at this point is +read-only, and it is slow, opening and closing the UBI volume for each +access due to limitations of the NVMEM provider API. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/Kconfig | 12 +++ + drivers/mtd/ubi/Makefile | 1 + + drivers/mtd/ubi/nvmem.c | 188 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+) + create mode 100644 drivers/mtd/ubi/nvmem.c + +--- a/drivers/mtd/ubi/Kconfig ++++ b/drivers/mtd/ubi/Kconfig +@@ -104,4 +104,16 @@ config MTD_UBI_BLOCK + + If in doubt, say "N". + ++config MTD_UBI_NVMEM ++ tristate "UBI virtual NVMEM" ++ default n ++ depends on NVMEM ++ help ++ This option enabled an additional driver exposing UBI volumes as NVMEM ++ providers, intended for platforms where UBI is part of the firmware ++ specification and used to store also e.g. MAC addresses or board- ++ specific Wi-Fi calibration data. ++ ++ If in doubt, say "N". ++ + endif # MTD_UBI +--- a/drivers/mtd/ubi/Makefile ++++ b/drivers/mtd/ubi/Makefile +@@ -7,3 +7,4 @@ ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap + ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o + + obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o ++obj-$(CONFIG_MTD_UBI_NVMEM) += nvmem.o +--- /dev/null ++++ b/drivers/mtd/ubi/nvmem.c +@@ -0,0 +1,191 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2023 Daniel Golle ++ */ ++ ++/* UBI NVMEM provider */ ++#include "ubi.h" ++#include ++#include ++ ++/* List of all NVMEM devices */ ++static LIST_HEAD(nvmem_devices); ++static DEFINE_MUTEX(devices_mutex); ++ ++struct ubi_nvmem { ++ struct nvmem_device *nvmem; ++ int ubi_num; ++ int vol_id; ++ int usable_leb_size; ++ struct list_head list; ++}; ++ ++static int ubi_nvmem_reg_read(void *priv, unsigned int from, ++ void *val, size_t bytes) ++{ ++ uint32_t offs, to_read, bytes_left; ++ struct ubi_nvmem *unv = priv; ++ struct ubi_volume_desc *desc; ++ uint64_t lnum = from; ++ int err = 0; ++ ++ desc = ubi_open_volume(unv->ubi_num, unv->vol_id, UBI_READONLY); ++ if (IS_ERR(desc)) ++ return PTR_ERR(desc); ++ ++ bytes_left = bytes; ++ offs = do_div(lnum, unv->usable_leb_size); ++ while (bytes_left) { ++ to_read = unv->usable_leb_size - offs; ++ ++ if (to_read > bytes_left) ++ to_read = bytes_left; ++ ++ err = ubi_read(desc, lnum, val, offs, to_read); ++ if (err) ++ break; ++ ++ lnum += 1; ++ offs = 0; ++ bytes_left -= to_read; ++ val += to_read; ++ } ++ ubi_close_volume(desc); ++ ++ if (err) ++ return err; ++ ++ return bytes_left == 0 ? 0 : -EIO; ++} ++ ++static int ubi_nvmem_add(struct ubi_volume_info *vi) ++{ ++ struct device_node *np = dev_of_node(vi->dev); ++ struct nvmem_config config = {}; ++ struct ubi_nvmem *unv; ++ int ret; ++ ++ if (!np) ++ return 0; ++ ++ if (!of_get_child_by_name(np, "nvmem-layout")) ++ return 0; ++ ++ if (WARN_ON_ONCE(vi->usable_leb_size <= 0) || ++ WARN_ON_ONCE(vi->size <= 0)) ++ return -EINVAL; ++ ++ unv = kzalloc(sizeof(struct ubi_nvmem), GFP_KERNEL); ++ if (!unv) ++ return -ENOMEM; ++ ++ config.id = NVMEM_DEVID_NONE; ++ config.dev = vi->dev; ++ config.name = dev_name(vi->dev); ++ config.owner = THIS_MODULE; ++ config.priv = unv; ++ config.reg_read = ubi_nvmem_reg_read; ++ config.size = vi->usable_leb_size * vi->size; ++ config.word_size = 1; ++ config.stride = 1; ++ config.read_only = true; ++ config.root_only = true; ++ config.ignore_wp = true; ++ config.of_node = np; ++ ++ unv->ubi_num = vi->ubi_num; ++ unv->vol_id = vi->vol_id; ++ unv->usable_leb_size = vi->usable_leb_size; ++ unv->nvmem = nvmem_register(&config); ++ if (IS_ERR(unv->nvmem)) { ++ ret = dev_err_probe(vi->dev, PTR_ERR(unv->nvmem), ++ "Failed to register NVMEM device\n"); ++ kfree(unv); ++ return ret; ++ } ++ ++ mutex_lock(&devices_mutex); ++ list_add_tail(&unv->list, &nvmem_devices); ++ mutex_unlock(&devices_mutex); ++ ++ return 0; ++} ++ ++static void ubi_nvmem_remove(struct ubi_volume_info *vi) ++{ ++ struct ubi_nvmem *unv_c, *unv = NULL; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry(unv_c, &nvmem_devices, list) ++ if (unv_c->ubi_num == vi->ubi_num && unv_c->vol_id == vi->vol_id) { ++ unv = unv_c; ++ break; ++ } ++ ++ if (!unv) { ++ mutex_unlock(&devices_mutex); ++ return; ++ } ++ ++ list_del(&unv->list); ++ mutex_unlock(&devices_mutex); ++ nvmem_unregister(unv->nvmem); ++ kfree(unv); ++} ++ ++/** ++ * nvmem_notify - UBI notification handler. ++ * @nb: registered notifier block ++ * @l: notification type ++ * @ns_ptr: pointer to the &struct ubi_notification object ++ */ ++static int nvmem_notify(struct notifier_block *nb, unsigned long l, ++ void *ns_ptr) ++{ ++ struct ubi_notification *nt = ns_ptr; ++ ++ switch (l) { ++ case UBI_VOLUME_RESIZED: ++ ubi_nvmem_remove(&nt->vi); ++ fallthrough; ++ case UBI_VOLUME_ADDED: ++ ubi_nvmem_add(&nt->vi); ++ break; ++ case UBI_VOLUME_SHUTDOWN: ++ ubi_nvmem_remove(&nt->vi); ++ break; ++ default: ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block nvmem_notifier = { ++ .notifier_call = nvmem_notify, ++}; ++ ++static int __init ubi_nvmem_init(void) ++{ ++ return ubi_register_volume_notifier(&nvmem_notifier, 0); ++} ++ ++static void __exit ubi_nvmem_exit(void) ++{ ++ struct ubi_nvmem *unv, *tmp; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry_safe(unv, tmp, &nvmem_devices, list) { ++ nvmem_unregister(unv->nvmem); ++ list_del(&unv->list); ++ kfree(unv); ++ } ++ mutex_unlock(&devices_mutex); ++ ++ ubi_unregister_volume_notifier(&nvmem_notifier); ++} ++ ++module_init(ubi_nvmem_init); ++module_exit(ubi_nvmem_exit); ++MODULE_DESCRIPTION("NVMEM layer over UBI volumes"); ++MODULE_AUTHOR("Daniel Golle"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/pending-6.6/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch b/target/linux/generic/pending-6.6/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch new file mode 100644 index 0000000000..d0727faf3d --- /dev/null +++ b/target/linux/generic/pending-6.6/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch @@ -0,0 +1,120 @@ +From 9ffc1d7d73609a89eb264d6066340f8b7b3b0ebe Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 21:19:45 +0100 +Subject: [PATCH 08/15] dt-bindings: block: add basic bindings for block + devices + +Add bindings for block devices which are used to allow referencing +nvmem bits on them. + +Signed-off-by: Daniel Golle +--- + .../bindings/block/block-device.yaml | 22 ++++++++ + .../devicetree/bindings/block/partition.yaml | 50 +++++++++++++++++++ + .../devicetree/bindings/block/partitions.yaml | 20 ++++++++ + 3 files changed, 92 insertions(+) + create mode 100644 Documentation/devicetree/bindings/block/block-device.yaml + create mode 100644 Documentation/devicetree/bindings/block/partition.yaml + create mode 100644 Documentation/devicetree/bindings/block/partitions.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/block-device.yaml +@@ -0,0 +1,22 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/block-device.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: block storage device ++ ++description: | ++ This binding is generic and describes a block-oriented storage device. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ partitions: ++ $ref: /schemas/block/partitions.yaml ++ ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ ++unevaluatedProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/partition.yaml +@@ -0,0 +1,50 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/partition.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Partition on a block device ++ ++description: | ++ This binding describes a partition on a block device. ++ Partitions may be matched by a combination of partition number, name, ++ and UUID. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ $nodename: ++ pattern: '^block-partition-.+$' ++ ++ partnum: ++ description: ++ Matches partition by number if present. ++ ++ partname: ++ "$ref": "/schemas/types.yaml#/definitions/string" ++ description: ++ Matches partition by PARTNAME if present. ++ ++ uuid: ++ "$ref": "/schemas/types.yaml#/definitions/string" ++ description: ++ Matches partition by PARTUUID if present. ++ ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ description: ++ This container may reference an NVMEM layout parser. ++ ++anyOf: ++ - required: ++ - partnum ++ ++ - required: ++ - partname ++ ++ - required: ++ - uuid ++ ++unevaluatedProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/partitions.yaml +@@ -0,0 +1,20 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/partitions.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Partitions on block devices ++ ++description: | ++ This binding is generic and describes the content of the partitions container ++ node. ++ ++maintainers: ++ - Daniel Golle ++ ++patternProperties: ++ "^block-partition-.+$": ++ $ref: partition.yaml ++ ++unevaluatedProperties: false diff --git a/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch new file mode 100644 index 0000000000..8aa5cba678 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch @@ -0,0 +1,77 @@ +From 614f4f6fdda09e30ecf7ef6c8091579db15018cb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 21 Jul 2023 17:51:03 +0100 +Subject: [PATCH 09/15] block: partitions: populate fwnode + +Let block partitions to be represented by a firmware node and hence +allow them to being referenced e.g. for use with blk-nvmem. + +Signed-off-by: Daniel Golle +--- + block/partitions/core.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++ + #include "check.h" + + static int (*check_part[])(struct parsed_partitions *) = { +@@ -298,6 +300,43 @@ static ssize_t whole_disk_show(struct de + } + static DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); + ++static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev) ++{ ++ struct fwnode_handle *fw_parts, *fw_part; ++ struct device *ddev = disk_to_dev(bdev->bd_disk); ++ const char *partname, *uuid; ++ u32 partno; ++ ++ fw_parts = device_get_named_child_node(ddev, "partitions"); ++ if (!fw_parts) ++ fw_parts = device_get_named_child_node(ddev->parent, "partitions"); ++ ++ if (!fw_parts) ++ return NULL; ++ ++ fwnode_for_each_child_node(fw_parts, fw_part) { ++ if (!fwnode_property_read_string(fw_part, "uuid", &uuid) && ++ (!bdev->bd_meta_info || strncmp(uuid, ++ bdev->bd_meta_info->uuid, ++ PARTITION_META_INFO_UUIDLTH))) ++ continue; ++ ++ if (!fwnode_property_read_string(fw_part, "partname", &partname) && ++ (!bdev->bd_meta_info || strncmp(partname, ++ bdev->bd_meta_info->volname, ++ PARTITION_META_INFO_VOLNAMELTH))) ++ continue; ++ ++ if (!fwnode_property_read_u32(fw_part, "partno", &partno) && ++ bdev->bd_partno != partno) ++ continue; ++ ++ return fw_part; ++ } ++ ++ return NULL; ++} ++ + /* + * Must be called either with open_mutex held, before a disk can be opened or + * after all disk users are gone. +@@ -380,6 +419,8 @@ static struct block_device *add_partitio + goto out_put; + } + ++ device_set_node(pdev, find_partition_fwnode(bdev)); ++ + /* delay uevent until 'holders' subdir is created */ + dev_set_uevent_suppress(pdev, 1); + err = device_add(pdev); diff --git a/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch new file mode 100644 index 0000000000..4cbec14f5c --- /dev/null +++ b/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch @@ -0,0 +1,29 @@ +From 65f3ff9672ccd5ee78937047e7a2fc696eee1c8f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:07:16 +0100 +Subject: [PATCH 10/15] block: add new genhd flag GENHD_FL_NVMEM + +Add new flag to destinguish block devices which may act as an NVMEM +provider. + +Signed-off-by: Daniel Golle +--- + include/linux/blkdev.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -87,11 +87,13 @@ struct partition_meta_info { + * ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not + * scan for partitions from add_disk, and users can't add partitions manually. + * ++ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider. + */ + enum { + GENHD_FL_REMOVABLE = 1 << 0, + GENHD_FL_HIDDEN = 1 << 1, + GENHD_FL_NO_PART = 1 << 2, ++ GENHD_FL_NVMEM = 1 << 3, + }; + + enum { diff --git a/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch new file mode 100644 index 0000000000..e18b0c3a5c --- /dev/null +++ b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch @@ -0,0 +1,235 @@ +From b9936aa8a3775c2027f655d91a206d0e6e1c7ec0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 11 Jul 2023 00:17:31 +0100 +Subject: [PATCH 11/15] block: implement NVMEM provider + +On embedded devices using an eMMC it is common that one or more partitions +on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM +data. Allow referencing the partition in device tree for the kernel and +Wi-Fi drivers accessing it via the NVMEM layer. + +Signed-off-by: Daniel Golle +--- + block/Kconfig | 9 +++ + block/Makefile | 1 + + block/blk-nvmem.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 196 insertions(+) + create mode 100644 block/blk-nvmem.c + +--- a/block/Kconfig ++++ b/block/Kconfig +@@ -203,6 +203,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK + by falling back to the kernel crypto API when inline + encryption hardware is not present. + ++config BLK_NVMEM ++ bool "Block device NVMEM provider" ++ depends on OF ++ depends on NVMEM ++ help ++ Allow block devices (or partitions) to act as NVMEM prodivers, ++ typically used with eMMC to store MAC addresses or Wi-Fi ++ calibration data on embedded devices. ++ + source "block/partitions/Kconfig" + + config BLOCK_COMPAT +--- a/block/Makefile ++++ b/block/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned + obj-$(CONFIG_BLK_WBT) += blk-wbt.o + obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o + obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o ++obj-$(CONFIG_BLK_NVMEM) += blk-nvmem.o + obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o + obj-$(CONFIG_BLK_PM) += blk-pm.o + obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += blk-crypto.o blk-crypto-profile.o \ +--- /dev/null ++++ b/block/blk-nvmem.c +@@ -0,0 +1,186 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * block device NVMEM provider ++ * ++ * Copyright (c) 2023 Daniel Golle ++ * ++ * Useful on devices using a partition on an eMMC for MAC addresses or ++ * Wi-Fi calibration EEPROM data. ++ */ ++ ++#include "blk.h" ++#include ++#include ++#include ++#include ++ ++/* List of all NVMEM devices */ ++static LIST_HEAD(nvmem_devices); ++static DEFINE_MUTEX(devices_mutex); ++ ++struct blk_nvmem { ++ struct nvmem_device *nvmem; ++ struct block_device *bdev; ++ struct list_head list; ++}; ++ ++static int blk_nvmem_reg_read(void *priv, unsigned int from, ++ void *val, size_t bytes) ++{ ++ unsigned long offs = from & ~PAGE_MASK, to_read; ++ pgoff_t f_index = from >> PAGE_SHIFT; ++ struct address_space *mapping; ++ struct blk_nvmem *bnv = priv; ++ size_t bytes_left = bytes; ++ struct folio *folio; ++ void *p; ++ int ret; ++ ++ if (!bnv->bdev) ++ return -ENODEV; ++ ++ if (!bnv->bdev->bd_disk) ++ return -EINVAL; ++ ++ if (!bnv->bdev->bd_disk->fops) ++ return -EIO; ++ ++ if (!bnv->bdev->bd_disk->fops->open) ++ return -EIO; ++ ++ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev, FMODE_READ); ++ if (ret) ++ return ret; ++ ++ mapping = bnv->bdev->bd_inode->i_mapping; ++ ++ while (bytes_left) { ++ folio = read_mapping_folio(mapping, f_index++, NULL); ++ if (IS_ERR(folio)) { ++ ret = PTR_ERR(folio); ++ goto err_release_bdev; ++ } ++ to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs); ++ p = folio_address(folio) + offset_in_folio(folio, offs); ++ memcpy(val, p, to_read); ++ offs = 0; ++ bytes_left -= to_read; ++ val += to_read; ++ folio_put(folio); ++ } ++ ++err_release_bdev: ++ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk, FMODE_READ); ++ ++ return ret; ++} ++ ++static int blk_nvmem_register(struct device *dev, struct class_interface *iface) ++{ ++ struct device_node *np = dev_of_node(dev); ++ struct block_device *bdev = dev_to_bdev(dev); ++ struct nvmem_config config = {}; ++ struct blk_nvmem *bnv; ++ ++ /* skip devices which do not have a device tree node */ ++ if (!np) ++ return 0; ++ ++ /* skip devices without an nvmem layout defined */ ++ if (!of_get_child_by_name(np, "nvmem-layout")) ++ return 0; ++ ++ /* ++ * skip devices which don't have GENHD_FL_NVMEM set ++ * ++ * This flag is used for mtdblock and ubiblock devices because ++ * both, MTD and UBI already implement their own NVMEM provider. ++ * To avoid registering multiple NVMEM providers for the same ++ * device node, don't register the block NVMEM provider for them. ++ */ ++ if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM)) ++ return 0; ++ ++ /* ++ * skip block device too large to be represented as NVMEM devices ++ * which are using an 'int' as address ++ */ ++ if (bdev_nr_bytes(bdev) > INT_MAX) ++ return -EFBIG; ++ ++ bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL); ++ if (!bnv) ++ return -ENOMEM; ++ ++ config.id = NVMEM_DEVID_NONE; ++ config.dev = &bdev->bd_device; ++ config.name = dev_name(&bdev->bd_device); ++ config.owner = THIS_MODULE; ++ config.priv = bnv; ++ config.reg_read = blk_nvmem_reg_read; ++ config.size = bdev_nr_bytes(bdev); ++ config.word_size = 1; ++ config.stride = 1; ++ config.read_only = true; ++ config.root_only = true; ++ config.ignore_wp = true; ++ config.of_node = to_of_node(dev->fwnode); ++ ++ bnv->bdev = bdev; ++ bnv->nvmem = nvmem_register(&config); ++ if (IS_ERR(bnv->nvmem)) { ++ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem), ++ "Failed to register NVMEM device\n"); ++ ++ kfree(bnv); ++ return PTR_ERR(bnv->nvmem); ++ } ++ ++ mutex_lock(&devices_mutex); ++ list_add_tail(&bnv->list, &nvmem_devices); ++ mutex_unlock(&devices_mutex); ++ ++ return 0; ++} ++ ++static void blk_nvmem_unregister(struct device *dev, struct class_interface *iface) ++{ ++ struct block_device *bdev = dev_to_bdev(dev); ++ struct blk_nvmem *bnv_c, *bnv = NULL; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry(bnv_c, &nvmem_devices, list) { ++ if (bnv_c->bdev == bdev) { ++ bnv = bnv_c; ++ break; ++ } ++ } ++ ++ if (!bnv) { ++ mutex_unlock(&devices_mutex); ++ return; ++ } ++ ++ list_del(&bnv->list); ++ mutex_unlock(&devices_mutex); ++ nvmem_unregister(bnv->nvmem); ++ kfree(bnv); ++} ++ ++static struct class_interface blk_nvmem_bus_interface __refdata = { ++ .class = &block_class, ++ .add_dev = &blk_nvmem_register, ++ .remove_dev = &blk_nvmem_unregister, ++}; ++ ++static int __init blk_nvmem_init(void) ++{ ++ int ret; ++ ++ ret = class_interface_register(&blk_nvmem_bus_interface); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++device_initcall(blk_nvmem_init); diff --git a/target/linux/generic/pending-6.6/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch b/target/linux/generic/pending-6.6/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch new file mode 100644 index 0000000000..77c9bf91a5 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch @@ -0,0 +1,74 @@ +From 86864bf8f40e84dc881c197ef470a88668329dbf Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 21:21:45 +0100 +Subject: [PATCH 12/15] dt-bindings: mmc: mmc-card: add block device nodes + +Add nodes representing the block devices exposed by an MMC device +including an example involving nvmem-cells. + +Signed-off-by: Daniel Golle +--- + .../devicetree/bindings/mmc/mmc-card.yaml | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml ++++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml +@@ -26,6 +26,18 @@ properties: + Use this to indicate that the mmc-card has a broken hpi + implementation, and that hpi should not be used. + ++ block: ++ $ref: /schemas/block/block-device.yaml# ++ description: ++ Represents the block storage provided by an SD card or the ++ main hardware partition of an eMMC. ++ ++patternProperties: ++ '^boot[0-9]+': ++ $ref: /schemas/block/block-device.yaml# ++ description: ++ Represents a boot hardware partition on an eMMC. ++ + required: + - compatible + - reg +@@ -42,6 +54,39 @@ examples: + compatible = "mmc-card"; + reg = <0>; + broken-hpi; ++ ++ block { ++ partitions { ++ cal_data: block-partition-rf { ++ partnum = <3>; ++ partname = "rf"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ eeprom@0 { ++ reg = <0x0 0x1000>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ boot1 { ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr: macaddr@a { ++ compatible = "mac-base"; ++ reg = <0xa 0x6>; ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ }; + }; + }; + diff --git a/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch new file mode 100644 index 0000000000..fada280437 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch @@ -0,0 +1,23 @@ +From 644942a31719de674e2aa68f83d66bd8ae7e4fb7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:12:21 +0100 +Subject: [PATCH 13/15] mmc: core: set card fwnode_handle + +Set fwnode in case it isn't set yet and of_node is present. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/bus.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/core/bus.c ++++ b/drivers/mmc/core/bus.c +@@ -363,6 +363,8 @@ int mmc_add_card(struct mmc_card *card) + mmc_add_card_debugfs(card); + #endif + card->dev.of_node = mmc_of_find_child_device(card->host, 0); ++ if (card->dev.of_node && !card->dev.fwnode) ++ card->dev.fwnode = &card->dev.of_node->fwnode; + + device_enable_async_suspend(&card->dev); + diff --git a/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch new file mode 100644 index 0000000000..a9e53f1155 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch @@ -0,0 +1,39 @@ +From d9143f86330dd038fc48878558dd287ceee5d3d4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:13:04 +0100 +Subject: [PATCH 14/15] mmc: block: set fwnode of disk devices + +Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of +the mmc-card. This is done in preparation for having the eMMC act as +NVMEM provider. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/block.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2484,6 +2484,8 @@ static struct mmc_blk_data *mmc_blk_allo + int area_type, + unsigned int part_type) + { ++ struct fwnode_handle *fwnode; ++ struct device *ddev; + struct mmc_blk_data *md; + int devidx, ret; + char cap_str[10]; +@@ -2580,6 +2582,13 @@ static struct mmc_blk_data *mmc_blk_allo + + blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled); + ++ ddev = disk_to_dev(md->disk); ++ fwnode = device_get_named_child_node(subname ? md->parent->parent : ++ md->parent, ++ subname ? subname : "block"); ++ if (fwnode) ++ device_set_node(ddev, fwnode); ++ + string_get_size((u64)size, 512, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + pr_info("%s: %s %s %s %s\n", diff --git a/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch new file mode 100644 index 0000000000..d76e7b2fe5 --- /dev/null +++ b/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch @@ -0,0 +1,22 @@ +From 322035ab2b0113d98b6c0ea788d971e0df2952a4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 20 Jul 2023 17:36:44 +0100 +Subject: [PATCH 15/15] mmc: block: set GENHD_FL_NVMEM + +Set flag to consider MMC block devices as NVMEM providers. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/block.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2538,6 +2538,7 @@ static struct mmc_blk_data *mmc_blk_allo + md->disk->major = MMC_BLOCK_MAJOR; + md->disk->minors = perdev_minors; + md->disk->first_minor = devidx * perdev_minors; ++ md->disk->flags = GENHD_FL_NVMEM; + md->disk->fops = &mmc_bdops; + md->disk->private_data = md; + md->parent = parent; diff --git a/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch new file mode 100644 index 0000000000..1b653fb735 --- /dev/null +++ b/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Subject: kernel: disable cfi cmdset 0002 erase suspend + +on some platforms, erase suspend leads to data corruption and lockups when write +ops collide with erase ops. this has been observed on the buffalo wzr-hp-g300nh. +rather than play whack-a-mole with a hard to reproduce issue on a variety of devices, +simply disable erase suspend, as it will usually not produce any useful gain on +the small filesystems used on embedded hardware. + +Signed-off-by: Felix Fietkau +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -908,7 +908,7 @@ static int get_chip(struct map_info *map + return 0; + + case FL_ERASING: +- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || ++ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) || + !(mode == FL_READY || mode == FL_POINT || + (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) + goto sleep; diff --git a/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch new file mode 100644 index 0000000000..f2788c5214 --- /dev/null +++ b/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch @@ -0,0 +1,17 @@ +From: George Kashperko +Subject: Issue map read after Write Buffer Load command to ensure chip is ready to receive data. + +Signed-off-by: George Kashperko +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 1 + + 1 file changed, 1 insertion(+) +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -2052,6 +2052,7 @@ static int __xipram do_write_buffer(stru + + /* Write Buffer Load */ + map_write(map, CMD(0x25), cmd_adr); ++ (void) map_read(map, cmd_adr); + + chip->state = FL_WRITING_TO_BUFFER; + diff --git a/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch new file mode 100644 index 0000000000..1e28077338 --- /dev/null +++ b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch @@ -0,0 +1,18 @@ +From: Felix Fietkau +Subject: Disable software protection bits for Macronix flashes. + +Signed-off-by: Felix Fietkau +--- + drivers/mtd/spi-nor/spi-nor.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -106,6 +106,7 @@ static void macronix_nor_default_init(st + { + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; ++ nor->flags |= SNOR_F_HAS_LOCK; + } + + static const struct spi_nor_fixups macronix_nor_fixups = { diff --git a/target/linux/generic/pending-6.6/476-mtd-spi-nor-add-eon-en25q128.patch b/target/linux/generic/pending-6.6/476-mtd-spi-nor-add-eon-en25q128.patch new file mode 100644 index 0000000000..303e488433 --- /dev/null +++ b/target/linux/generic/pending-6.6/476-mtd-spi-nor-add-eon-en25q128.patch @@ -0,0 +1,19 @@ +From: Piotr Dymacz +Subject: kernel/mtd: add support for EON EN25Q128 + +Signed-off-by: Piotr Dymacz +--- + drivers/mtd/spi-nor/spi-nor.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/eon.c ++++ b/drivers/mtd/spi-nor/eon.c +@@ -17,6 +17,8 @@ static const struct flash_info eon_nor_p + { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128) }, + { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256) ++ NO_SFDP_FLAGS(SECT_4K) }, + { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) }, + { "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32) diff --git a/target/linux/generic/pending-6.6/477-mtd-spi-nor-add-eon-en25qx128a.patch b/target/linux/generic/pending-6.6/477-mtd-spi-nor-add-eon-en25qx128a.patch new file mode 100644 index 0000000000..6740d1d7be --- /dev/null +++ b/target/linux/generic/pending-6.6/477-mtd-spi-nor-add-eon-en25qx128a.patch @@ -0,0 +1,21 @@ +From: Christian Marangi +Subject: kernel/mtd: add support for EON EN25QX128A + +Add support for EON EN25QX128A with no flags as it does +support SFDP parsing. + +Signed-off-by: Christian Marangi +--- + drivers/mtd/spi-nor/spi-nor.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/eon.c ++++ b/drivers/mtd/spi-nor/eon.c +@@ -19,6 +19,7 @@ static const struct flash_info eon_nor_p + NO_SFDP_FLAGS(SECT_4K) }, + { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256) + NO_SFDP_FLAGS(SECT_4K) }, ++ { "en25qx128a", INFO(0x1c7118, 0, 64 * 1024, 256) }, + { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) }, + { "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32) diff --git a/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch new file mode 100644 index 0000000000..d2a9fb3436 --- /dev/null +++ b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -0,0 +1,81 @@ +From patchwork Thu Feb 6 17:19:41 2020 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 1234465 +Date: Thu, 6 Feb 2020 19:19:41 +0200 +From: Daniel Golle +To: linux-mtd@lists.infradead.org +Subject: [PATCH v2] mtd: spi-nor: Add support for xt25f128b chip +Message-ID: <20200206171941.GA2398@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +List-Subscribe: , + +Cc: Eitan Cohen , Piotr Dymacz , + Tudor Ambarus +Sender: "linux-mtd" +Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org + +Add XT25F128B made by XTX Technology (Shenzhen) Limited. +This chip supports dual and quad read and uniform 4K-byte erase. +Verified on Teltonika RUT955 which comes with XT25F128B in recent +versions of the device. + +Signed-off-by: Daniel Golle +Signed-off-by: Felix Fietkau +--- + drivers/mtd/spi-nor/spi-nor.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -17,6 +17,7 @@ spi-nor-objs += sst.o + spi-nor-objs += winbond.o + spi-nor-objs += xilinx.o + spi-nor-objs += xmc.o ++spi-nor-objs += xtx.o + spi-nor-$(CONFIG_DEBUG_FS) += debugfs.o + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o + +--- /dev/null ++++ b/drivers/mtd/spi-nor/xtx.c +@@ -0,0 +1,17 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++ ++#include "core.h" ++ ++static const struct flash_info xtx_parts[] = { ++ /* XTX Technology (Shenzhen) Limited */ ++ { "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256) ++ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | ++ SPI_NOR_QUAD_READ) }, ++}; ++ ++const struct spi_nor_manufacturer spi_nor_xtx = { ++ .name = "xtx", ++ .parts = xtx_parts, ++ .nparts = ARRAY_SIZE(xtx_parts), ++}; +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1636,6 +1636,7 @@ static const struct spi_nor_manufacturer + &spi_nor_winbond, + &spi_nor_xilinx, + &spi_nor_xmc, ++ &spi_nor_xtx, + }; + + static const struct flash_info *spi_nor_match_id(struct spi_nor *nor, +--- a/drivers/mtd/spi-nor/core.h ++++ b/drivers/mtd/spi-nor/core.h +@@ -633,6 +633,7 @@ extern const struct spi_nor_manufacturer + extern const struct spi_nor_manufacturer spi_nor_winbond; + extern const struct spi_nor_manufacturer spi_nor_xilinx; + extern const struct spi_nor_manufacturer spi_nor_xmc; ++extern const struct spi_nor_manufacturer spi_nor_xtx; + + extern const struct attribute_group *spi_nor_sysfs_groups[]; + diff --git a/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch new file mode 100644 index 0000000000..581e06190b --- /dev/null +++ b/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch @@ -0,0 +1,23 @@ +From d68b4aa22e8c625685bfad642dd7337948dc0ad1 Mon Sep 17 00:00:00 2001 +From: Koen Vandeputte +Date: Mon, 6 Jan 2020 13:07:56 +0100 +Subject: [PATCH] mtd: spi-nor: add support for Gigadevice GD25D05 + +Signed-off-by: Koen Vandeputte +--- + drivers/mtd/spi-nor/spi-nor.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/mtd/spi-nor/gigadevice.c ++++ b/drivers/mtd/spi-nor/gigadevice.c +@@ -34,6 +34,10 @@ static const struct spi_nor_fixups gd25q + }; + + static const struct flash_info gigadevice_nor_parts[] = { ++ { "gd25q05", INFO(0xc84010, 0, 64 * 1024, 1) ++ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | ++ SPI_NOR_QUAD_READ) }, + { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32) + FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | diff --git a/target/linux/generic/pending-6.6/482-mtd-spi-nor-add-gd25q512.patch b/target/linux/generic/pending-6.6/482-mtd-spi-nor-add-gd25q512.patch new file mode 100644 index 0000000000..ddd3405ae7 --- /dev/null +++ b/target/linux/generic/pending-6.6/482-mtd-spi-nor-add-gd25q512.patch @@ -0,0 +1,23 @@ +From f8943df3beb0d3f9754bb35320c3a378727175a8 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Thu, 14 Jul 2022 08:38:07 +0200 +Subject: [PATCH] spi-nor/gigadevic: add gd25q512 + +--- + drivers/mtd/spi-nor/gigadevice.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/mtd/spi-nor/gigadevice.c ++++ b/drivers/mtd/spi-nor/gigadevice.c +@@ -71,6 +71,11 @@ static const struct flash_info gigadevic + FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6) + FIXUP_FLAGS(SPI_NOR_4B_OPCODES) + .fixups = &gd25q256_fixups }, ++ { "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024) ++ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ FIXUP_FLAGS(SPI_NOR_4B_OPCODES) ++ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | ++ SPI_NOR_QUAD_READ) }, + }; + + const struct spi_nor_manufacturer spi_nor_gigadevice = { diff --git a/target/linux/generic/pending-6.6/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/target/linux/generic/pending-6.6/484-mtd-spi-nor-add-esmt-f25l16pa.patch new file mode 100644 index 0000000000..d5ebe20309 --- /dev/null +++ b/target/linux/generic/pending-6.6/484-mtd-spi-nor-add-esmt-f25l16pa.patch @@ -0,0 +1,24 @@ +From 87363cc0e522de3294ea6ae10fb468d2a8d6fb2f Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 12:17:21 +0200 +Subject: [PATCH] spi-nor/esmt.c: add esmt f25l16pa + +This fixes support for Dongwon T&I DW02-412H which uses F25L16PA(2S) +flash. + +--- + drivers/mtd/spi-nor/esmt.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/spi-nor/esmt.c ++++ b/drivers/mtd/spi-nor/esmt.c +@@ -10,6 +10,9 @@ + + static const struct flash_info esmt_nor_parts[] = { + /* ESMT */ ++ { "f25l16pa-2s", INFO(0x8c2115, 0, 64 * 1024, 32) ++ FLAGS(SPI_NOR_HAS_LOCK) ++ NO_SFDP_FLAGS(SECT_4K) }, + { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64) + FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) + NO_SFDP_FLAGS(SECT_4K) }, diff --git a/target/linux/generic/pending-6.6/485-mtd-spi-nor-add-xmc-xm25qh128c.patch b/target/linux/generic/pending-6.6/485-mtd-spi-nor-add-xmc-xm25qh128c.patch new file mode 100644 index 0000000000..e8583cc257 --- /dev/null +++ b/target/linux/generic/pending-6.6/485-mtd-spi-nor-add-xmc-xm25qh128c.patch @@ -0,0 +1,25 @@ +From f6b33d850f7f12555df2fa0e3349b33427bf5890 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 12:19:01 +0200 +Subject: [PATCH] spi-nor/xmc.c: add xm25qh128c + +The XMC XM25QH128C is a 16MB SPI NOR chip. The patch is verified on +Ruijie RG-EW3200GX PRO. +Datasheet available at https://www.xmcwh.com/uploads/435/XM25QH128C.pdf + +--- + drivers/mtd/spi-nor/xmc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/spi-nor/xmc.c ++++ b/drivers/mtd/spi-nor/xmc.c +@@ -16,6 +16,9 @@ static const struct flash_info xmc_nor_p + { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, ++ { "XM25QH128C", INFO(0x204018, 0, 64 * 1024, 256) ++ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | ++ SPI_NOR_QUAD_READ) }, + }; + + const struct spi_nor_manufacturer spi_nor_xmc = { diff --git a/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch b/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch new file mode 100644 index 0000000000..b8116db842 --- /dev/null +++ b/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch @@ -0,0 +1,143 @@ +From a43b844cb40bf1b783055fdc81b7f991e21e7e76 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Wed, 13 Apr 2022 11:58:17 +0800 +Subject: [PATCH] mtd: spinand: add support for ESMT F50x1G41LB + +This patch adds support for ESMT F50L1G41LB and F50D1G41LB. +It seems that ESMT likes to use random JEDEC ID from other vendors. +Their 1G chips uses 0xc8 from GigaDevice and 2G/4G chips uses 0x2c from +Micron. For this reason, the ESMT entry is named esmt_c8 with explicit +JEDEC ID in variable name. + +Datasheets: +https://www.esmt.com.tw/upload/pdf/ESMT/datasheets/F50L1G41LB(2M).pdf +https://www.esmt.com.tw/upload/pdf/ESMT/datasheets/F50D1G41LB(2M).pdf + +Signed-off-by: Chuanhong Guo +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/esmt.c | 89 +++++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 92 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/esmt.c + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o ato.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs := core.o ato.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -938,6 +938,7 @@ static const struct nand_ops spinand_ops + + static const struct spinand_manufacturer *spinand_manufacturers[] = { + &ato_spinand_manufacturer, ++ &esmt_c8_spinand_manufacturer, + &gigadevice_spinand_manufacturer, + ¯onix_spinand_manufacturer, + µn_spinand_manufacturer, +--- /dev/null ++++ b/drivers/mtd/nand/spi/esmt.c +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Author: ++ * Chuanhong Guo ++ */ ++ ++#include ++#include ++#include ++ ++/* ESMT uses GigaDevice 0xc8 JECDEC ID on some SPI NANDs */ ++#define SPINAND_MFR_ESMT_C8 0xc8 ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int f50l1g41lb_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = 16 * section + 8; ++ region->length = 8; ++ ++ return 0; ++} ++ ++static int f50l1g41lb_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = 16 * section + 2; ++ region->length = 6; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = { ++ .ecc = f50l1g41lb_ooblayout_ecc, ++ .free = f50l1g41lb_ooblayout_free, ++}; ++ ++static const struct spinand_info esmt_c8_spinand_table[] = { ++ SPINAND_INFO("F50L1G41LB", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(1, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), ++ SPINAND_INFO("F50D1G41LB", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(1, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), ++}; ++ ++static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer esmt_c8_spinand_manufacturer = { ++ .id = SPINAND_MFR_ESMT_C8, ++ .name = "ESMT", ++ .chips = esmt_c8_spinand_table, ++ .nchips = ARRAY_SIZE(esmt_c8_spinand_table), ++ .ops = &esmt_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -261,6 +261,7 @@ struct spinand_manufacturer { + + /* SPI NAND manufacturers */ + extern const struct spinand_manufacturer ato_spinand_manufacturer; ++extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch b/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch new file mode 100644 index 0000000000..81378fba86 --- /dev/null +++ b/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch @@ -0,0 +1,168 @@ +From f32085fc0b87049491b07e198d924d738a1a2834 Mon Sep 17 00:00:00 2001 +From: Daniel Danzberger +Date: Wed, 3 Aug 2022 17:31:03 +0200 +Subject: [PATCH] mtd: spinand: Add support for Etron EM73D044VCx + +Airoha is a new ARM platform based on Cortex-A53 which has recently been +merged into linux-next. + +Due to BootROM limitations on this platform, the Cortex-A53 can't run in +Aarch64 mode and code must be compiled for 32-Bit ARM. + +This support is based mostly on those linux-next commits backported +for kernel 5.15. + +Patches: +1 - platform support = linux-next +2 - clock driver = linux-next +3 - gpio driver = linux-next +4 - linux,usable-memory-range dts support = linux-next +5 - mtd spinand driver +6 - spi driver +7 - pci driver (kconfig only, uses mediatek PCI) = linux-next + +Still missing: +- Ethernet driver +- Sysupgrade support + +A.t.m there exists one subtarget EN7523 with only one evaluation +board. + +The initramfs can be run with the following commands from u-boot: +- +u-boot> setenv bootfile \ + openwrt-airoha-airoha_en7523-evb-initramfs-kernel.bin +u-boot> tftpboot +u-boot> bootm 0x81800000 +- + +Submitted-by: Daniel Danzberger + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o ato.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs := core.o ato.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -939,6 +939,7 @@ static const struct nand_ops spinand_ops + static const struct spinand_manufacturer *spinand_manufacturers[] = { + &ato_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, ++ &etron_spinand_manufacturer, + &gigadevice_spinand_manufacturer, + ¯onix_spinand_manufacturer, + µn_spinand_manufacturer, +--- /dev/null ++++ b/drivers/mtd/nand/spi/etron.c +@@ -0,0 +1,98 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_ETRON 0xd5 ++ ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int etron_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->offset = 72; ++ oobregion->length = 56; ++ ++ return 0; ++} ++ ++static int etron_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->offset = 1; ++ oobregion->length = 71; ++ ++ return 0; ++} ++ ++static int etron_ecc_get_status(struct spinand_device *spinand, u8 status) ++{ ++ switch (status & STATUS_ECC_MASK) { ++ case STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case STATUS_ECC_HAS_BITFLIPS: ++ /* Between 1-7 bitflips were corrected */ ++ return 7; ++ ++ case STATUS_ECC_MASK: ++ /* Maximum bitflips were corrected */ ++ return 8; ++ ++ case STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct mtd_ooblayout_ops etron_ooblayout = { ++ .ecc = etron_ooblayout_ecc, ++ .free = etron_ooblayout_free, ++}; ++ ++static const struct spinand_info etron_spinand_table[] = { ++ SPINAND_INFO("EM73D044VCx", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x1f), ++ // bpc, pagesize, oobsize, pagesperblock, bperlun, maxbadplun, ppl, lpt, #t ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)), ++}; ++ ++static const struct spinand_manufacturer_ops etron_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer etron_spinand_manufacturer = { ++ .id = SPINAND_MFR_ETRON, ++ .name = "Etron", ++ .chips = etron_spinand_table, ++ .nchips = ARRAY_SIZE(etron_spinand_table), ++ .ops = &etron_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -262,6 +262,7 @@ struct spinand_manufacturer { + /* SPI NAND manufacturers */ + extern const struct spinand_manufacturer ato_spinand_manufacturer; + extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; ++extern const struct spinand_manufacturer etron_spinand_manufacturer; + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/generic/pending-6.6/488-mtd-spi-nor-add-xmc-xm25qh64c.patch b/target/linux/generic/pending-6.6/488-mtd-spi-nor-add-xmc-xm25qh64c.patch new file mode 100644 index 0000000000..e1e4f25e11 --- /dev/null +++ b/target/linux/generic/pending-6.6/488-mtd-spi-nor-add-xmc-xm25qh64c.patch @@ -0,0 +1,23 @@ +From: Joe Mullally +Subject: mtd/spi-nor/xmc: add support for XMC XM25QH64C + +The XMC XM25QH64C is a 8MB SPI NOR chip. The patch is verified on TL-WPA8631P v3. +Datasheet available at https://www.xmcwh.com/uploads/442/XM25QH64C.pdf + +Signed-off-by: Joe Mullally +--- + drivers/mtd/spi-nor/xmc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/spi-nor/xmc.c ++++ b/drivers/mtd/spi-nor/xmc.c +@@ -13,6 +13,9 @@ static const struct flash_info xmc_nor_p + { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, ++ { "XM25QH64C", INFO(0x204017, 0, 64 * 1024, 128) ++ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | ++ SPI_NOR_QUAD_READ) }, + { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, diff --git a/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch new file mode 100644 index 0000000000..2eccb9d3bb --- /dev/null +++ b/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -0,0 +1,98 @@ +From: Daniel Golle +Subject: ubi: auto-attach mtd device named "ubi" or "data" on boot + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -1263,6 +1263,74 @@ static struct mtd_notifier ubi_mtd_notif + .remove = ubi_notify_remove, + }; + ++ ++/* ++ * This function tries attaching mtd partitions named either "ubi" or "data" ++ * during boot. ++ */ ++static void __init ubi_auto_attach(void) ++{ ++ int err; ++ struct mtd_info *mtd; ++ loff_t offset = 0; ++ size_t len; ++ char magic[4]; ++ ++ /* try attaching mtd device named "ubi" or "data" */ ++ mtd = open_mtd_device("ubi"); ++ if (IS_ERR(mtd)) ++ mtd = open_mtd_device("data"); ++ ++ if (IS_ERR(mtd)) ++ return; ++ ++ /* get the first not bad block */ ++ if (mtd_can_have_bb(mtd)) ++ while (mtd_block_isbad(mtd, offset)) { ++ offset += mtd->erasesize; ++ ++ if (offset > mtd->size) { ++ pr_err("UBI error: Failed to find a non-bad " ++ "block on mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ } ++ ++ /* check if the read from flash was successful */ ++ err = mtd_read(mtd, offset, 4, &len, (void *) magic); ++ if ((err && !mtd_is_bitflip(err)) || len != 4) { ++ pr_err("UBI error: unable to read from mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ /* check for a valid ubi magic */ ++ if (strncmp(magic, "UBI#", 4)) { ++ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ /* don't auto-add media types where UBI doesn't makes sense */ ++ if (mtd->type != MTD_NANDFLASH && ++ mtd->type != MTD_NORFLASH && ++ mtd->type != MTD_DATAFLASH && ++ mtd->type != MTD_MLCNANDFLASH) ++ goto cleanup; ++ ++ mutex_lock(&ubi_devices_mutex); ++ pr_notice("UBI: auto-attach mtd%d\n", mtd->index); ++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false); ++ mutex_unlock(&ubi_devices_mutex); ++ if (err < 0) { ++ pr_err("UBI error: cannot attach mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ return; ++ ++cleanup: ++ put_mtd_device(mtd); ++} ++ + static int __init ubi_init_attach(void) + { + int err, i, k; +@@ -1313,6 +1381,12 @@ static int __init ubi_init_attach(void) + } + } + ++ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd ++ * parameter was given */ ++ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && ++ !ubi_is_module() && !mtd_devs) ++ ubi_auto_attach(); ++ + return 0; + + out_detach: diff --git a/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch new file mode 100644 index 0000000000..a43da2a572 --- /dev/null +++ b/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -0,0 +1,77 @@ +From: Daniel Golle +Subject: ubi: auto-create ubiblock device for rootfs + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -644,10 +644,47 @@ match_volume_desc(struct ubi_volume_info + return true; + } + ++#define UBIFS_NODE_MAGIC 0x06101831 ++static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc) ++{ ++ int ret; ++ uint32_t magic_of, magic; ++ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4); ++ if (ret) ++ return 0; ++ magic = le32_to_cpu(magic_of); ++ return magic == UBIFS_NODE_MAGIC; ++} ++ ++static void __init ubiblock_create_auto_rootfs(struct ubi_volume_info *vi) ++{ ++ int ret, is_ubifs; ++ struct ubi_volume_desc *desc; ++ ++ if (strcmp(vi->name, "rootfs") && ++ strcmp(vi->name, "fit")) ++ return; ++ ++ desc = ubi_open_volume(vi->ubi_num, vi->vol_id, UBI_READONLY); ++ if (IS_ERR(desc)) ++ return; ++ ++ is_ubifs = ubi_vol_is_ubifs(desc); ++ ubi_close_volume(desc); ++ if (is_ubifs) ++ return; ++ ++ ret = ubiblock_create(vi); ++ if (ret) ++ pr_err("UBI error: block: can't add '%s' volume, err=%d\n", ++ vi->name, ret); ++} ++ + static void + ubiblock_create_from_param(struct ubi_volume_info *vi) + { + int i, ret = 0; ++ bool got_param = false; + struct ubiblock_param *p; + + /* +@@ -660,6 +697,7 @@ ubiblock_create_from_param(struct ubi_vo + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) + continue; + ++ got_param = true; + ret = ubiblock_create(vi); + if (ret) { + pr_err( +@@ -668,6 +706,10 @@ ubiblock_create_from_param(struct ubi_vo + } + break; + } ++ ++ /* auto-attach "rootfs" volume if existing and non-ubifs */ ++ if (!got_param && IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV)) ++ ubiblock_create_auto_rootfs(vi); + } + + static int ubiblock_notify(struct notifier_block *nb, diff --git a/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch new file mode 100644 index 0000000000..f95ec46f14 --- /dev/null +++ b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -0,0 +1,53 @@ +From: Daniel Golle +Subject: try auto-mounting ubi0:rootfs in init/do_mounts.c + +Signed-off-by: Daniel Golle +--- + init/do_mounts.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -446,7 +446,30 @@ retry: + out: + put_page(page); + } +- ++ ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++static int __init mount_ubi_rootfs(void) ++{ ++ int flags = MS_SILENT; ++ int err, tried = 0; ++ ++ while (tried < 2) { ++ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \ ++ root_mount_data); ++ switch (err) { ++ case -EACCES: ++ flags |= MS_RDONLY; ++ tried++; ++ break; ++ default: ++ return err; ++ } ++ } ++ ++ return -EINVAL; ++} ++#endif ++ + #ifdef CONFIG_ROOT_NFS + + #define NFSROOT_TIMEOUT_MIN 5 +@@ -579,6 +602,10 @@ void __init mount_root(void) + return; + } + #endif ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++ if (!mount_ubi_rootfs()) ++ return; ++#endif + if (ROOT_DEV == 0 && root_device_name && root_fs_names) { + if (mount_nodev_root() == 0) + return; diff --git a/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch new file mode 100644 index 0000000000..5357c7e15d --- /dev/null +++ b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -0,0 +1,34 @@ +From: Daniel Golle +Subject: ubi: set ROOT_DEV to ubiblock "rootfs" if unset + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include "ubi-media.h" + #include "ubi.h" +@@ -460,6 +461,15 @@ int ubiblock_create(struct ubi_volume_in + dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", + dev->ubi_num, dev->vol_id, vi->name); + mutex_unlock(&devices_mutex); ++ ++ if (!strcmp(vi->name, "rootfs") && ++ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && ++ ROOT_DEV == 0) { ++ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n", ++ dev->ubi_num, dev->vol_id, vi->name); ++ ROOT_DEV = MKDEV(gd->major, gd->first_minor); ++ } ++ + return 0; + + out_destroy_wq: diff --git a/target/linux/generic/pending-6.6/494-mtd-ubi-add-EOF-marker-support.patch b/target/linux/generic/pending-6.6/494-mtd-ubi-add-EOF-marker-support.patch new file mode 100644 index 0000000000..fc48146221 --- /dev/null +++ b/target/linux/generic/pending-6.6/494-mtd-ubi-add-EOF-marker-support.patch @@ -0,0 +1,60 @@ +From: Gabor Juhos +Subject: mtd: add EOF marker support to the UBI layer + +Signed-off-by: Gabor Juhos +--- + drivers/mtd/ubi/attach.c | 25 ++++++++++++++++++++++--- + drivers/mtd/ubi/ubi.h | 1 + + 2 files changed, 23 insertions(+), 3 deletions(-) + +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -926,6 +926,13 @@ static bool vol_ignored(int vol_id) + #endif + } + ++static bool ec_hdr_has_eof(struct ubi_ec_hdr *ech) ++{ ++ return ech->padding1[0] == 'E' && ++ ech->padding1[1] == 'O' && ++ ech->padding1[2] == 'F'; ++} ++ + /** + * scan_peb - scan and process UBI headers of a PEB. + * @ubi: UBI device description object +@@ -958,9 +965,21 @@ static int scan_peb(struct ubi_device *u + return 0; + } + +- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); +- if (err < 0) +- return err; ++ if (!ai->eof_found) { ++ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); ++ if (err < 0) ++ return err; ++ ++ if (ec_hdr_has_eof(ech)) { ++ pr_notice("UBI: EOF marker found, PEBs from %d will be erased\n", ++ pnum); ++ ai->eof_found = true; ++ } ++ } ++ ++ if (ai->eof_found) ++ err = UBI_IO_FF_BITFLIPS; ++ + switch (err) { + case 0: + break; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -780,6 +780,7 @@ struct ubi_attach_info { + int mean_ec; + uint64_t ec_sum; + int ec_count; ++ bool eof_found; + struct kmem_cache *aeb_slab_cache; + struct ubi_ec_hdr *ech; + struct ubi_vid_io_buf *vidb; diff --git a/target/linux/generic/pending-6.6/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/target/linux/generic/pending-6.6/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch new file mode 100644 index 0000000000..01f3b9ec2d --- /dev/null +++ b/target/linux/generic/pending-6.6/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch @@ -0,0 +1,52 @@ +From 5734c6669fba7ddb5ef491ccff7159d15dba0b59 Mon Sep 17 00:00:00 2001 +From: Bernhard Frauendienst +Date: Wed, 5 Sep 2018 01:32:51 +0200 +Subject: [PATCH 496/497] dt-bindings: add bindings for mtd-concat devices + +Document virtual mtd-concat device bindings. + +Signed-off-by: Bernhard Frauendienst +--- + .../devicetree/bindings/mtd/mtd-concat.txt | 36 +++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/mtd-concat.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/mtd-concat.txt +@@ -0,0 +1,36 @@ ++Virtual MTD concat device ++ ++Requires properties: ++- devices: list of phandles to mtd nodes that should be concatenated ++ ++Example: ++ ++&spi { ++ flash0: flash@0 { ++ ... ++ }; ++ flash1: flash@1 { ++ ... ++ }; ++}; ++ ++flash { ++ compatible = "mtd-concat"; ++ ++ devices = <&flash0 &flash1>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ ++ partition@0 { ++ label = "boot"; ++ reg = <0x0000000 0x0040000>; ++ read-only; ++ }; ++ ++ partition@40000 { ++ label = "firmware"; ++ reg = <0x0040000 0x1fc0000>; ++ }; ++ } ++} diff --git a/target/linux/generic/pending-6.6/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-6.6/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch new file mode 100644 index 0000000000..e0cbc4508b --- /dev/null +++ b/target/linux/generic/pending-6.6/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -0,0 +1,216 @@ +From e53f712d8eac71f54399b61038ccf87d2cee99d7 Mon Sep 17 00:00:00 2001 +From: Bernhard Frauendienst +Date: Sat, 25 Aug 2018 12:35:22 +0200 +Subject: [PATCH 497/497] mtd: mtdconcat: add dt driver for concat devices + +Some mtd drivers like physmap variants have support for concatenating +multiple mtd devices, but there is no generic way to define such a +concat device from within the device tree. + +This is useful for some SoC boards that use multiple flash chips as +memory banks of a single mtd device, with partitions spanning chip +borders. + +This commit adds a driver for creating virtual mtd-concat devices. They +must have a compatible = "mtd-concat" line, and define a list of devices +to concat in the 'devices' property, for example: + +flash { + compatible = "mtd-concat"; + + devices = <&flash0 &flash1>; + + partitions { + ... + }; +}; + +The driver is added to the very end of the mtd Makefile to increase the +likelyhood of all child devices already being loaded at the time of +probing, preventing unnecessary deferred probes. + +Signed-off-by: Bernhard Frauendienst +--- + drivers/mtd/Kconfig | 2 + + drivers/mtd/Makefile | 3 + + drivers/mtd/composite/Kconfig | 12 +++ + drivers/mtd/composite/Makefile | 6 ++ + drivers/mtd/composite/virt_concat.c | 128 ++++++++++++++++++++++++++++ + 5 files changed, 151 insertions(+) + create mode 100644 drivers/mtd/composite/Kconfig + create mode 100644 drivers/mtd/composite/Makefile + create mode 100644 drivers/mtd/composite/virt_concat.c + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -241,4 +241,6 @@ source "drivers/mtd/ubi/Kconfig" + + source "drivers/mtd/hyperbus/Kconfig" + ++source "drivers/mtd/composite/Kconfig" ++ + endif # MTD +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -33,3 +33,6 @@ obj-y += chips/ lpddr/ maps/ devices/ n + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ + obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ ++ ++# Composite drivers must be loaded last ++obj-y += composite/ +--- /dev/null ++++ b/drivers/mtd/composite/Kconfig +@@ -0,0 +1,12 @@ ++menu "Composite MTD device drivers" ++ depends on MTD!=n ++ ++config MTD_VIRT_CONCAT ++ tristate "Virtual concat MTD device" ++ help ++ This driver allows creation of a virtual MTD concat device, which ++ concatenates multiple underlying MTD devices to a single device. ++ This is required by some SoC boards where multiple memory banks are ++ used as one device with partitions spanning across device boundaries. ++ ++endmenu +--- /dev/null ++++ b/drivers/mtd/composite/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# linux/drivers/mtd/composite/Makefile ++# ++ ++obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o +--- /dev/null ++++ b/drivers/mtd/composite/virt_concat.c +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Virtual concat MTD device driver ++ * ++ * Copyright (C) 2018 Bernhard Frauendienst ++ * Author: Bernhard Frauendienst, kernel@nospam.obeliks.de ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * struct of_virt_concat - platform device driver data. ++ * @cmtd the final mtd_concat device ++ * @num_devices the number of devices in @devices ++ * @devices points to an array of devices already loaded ++ */ ++struct of_virt_concat { ++ struct mtd_info *cmtd; ++ int num_devices; ++ struct mtd_info **devices; ++}; ++ ++static int virt_concat_remove(struct platform_device *pdev) ++{ ++ struct of_virt_concat *info; ++ int i; ++ ++ info = platform_get_drvdata(pdev); ++ if (!info) ++ return 0; ++ ++ // unset data for when this is called after a probe error ++ platform_set_drvdata(pdev, NULL); ++ ++ if (info->cmtd) { ++ mtd_device_unregister(info->cmtd); ++ mtd_concat_destroy(info->cmtd); ++ } ++ ++ if (info->devices) { ++ for (i = 0; i < info->num_devices; i++) ++ put_mtd_device(info->devices[i]); ++ } ++ ++ return 0; ++} ++ ++static int virt_concat_probe(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct of_phandle_iterator it; ++ struct of_virt_concat *info; ++ struct mtd_info *mtd; ++ int err = 0, count; ++ ++ count = of_count_phandle_with_args(node, "devices", NULL); ++ if (count <= 0) ++ return -EINVAL; ++ ++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ info->devices = devm_kcalloc(&pdev->dev, count, ++ sizeof(*(info->devices)), GFP_KERNEL); ++ if (!info->devices) { ++ err = -ENOMEM; ++ goto err_remove; ++ } ++ ++ platform_set_drvdata(pdev, info); ++ ++ of_for_each_phandle(&it, err, node, "devices", NULL, 0) { ++ mtd = of_get_mtd_device_by_node(it.node); ++ if (IS_ERR(mtd)) { ++ of_node_put(it.node); ++ err = -EPROBE_DEFER; ++ goto err_remove; ++ } ++ ++ info->devices[info->num_devices++] = mtd; ++ } ++ ++ info->cmtd = mtd_concat_create(info->devices, info->num_devices, ++ dev_name(&pdev->dev)); ++ if (!info->cmtd) { ++ err = -ENXIO; ++ goto err_remove; ++ } ++ ++ info->cmtd->dev.parent = &pdev->dev; ++ mtd_set_of_node(info->cmtd, node); ++ mtd_device_register(info->cmtd, NULL, 0); ++ ++ return 0; ++ ++err_remove: ++ virt_concat_remove(pdev); ++ ++ return err; ++} ++ ++static const struct of_device_id virt_concat_of_match[] = { ++ { .compatible = "mtd-concat", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, virt_concat_of_match); ++ ++static struct platform_driver virt_concat_driver = { ++ .probe = virt_concat_probe, ++ .remove = virt_concat_remove, ++ .driver = { ++ .name = "virt-mtdconcat", ++ .of_match_table = virt_concat_of_match, ++ }, ++}; ++ ++module_platform_driver(virt_concat_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Bernhard Frauendienst "); ++MODULE_DESCRIPTION("Virtual concat MTD device driver"); diff --git a/target/linux/generic/pending-6.6/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch b/target/linux/generic/pending-6.6/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch new file mode 100644 index 0000000000..1a4d5a766f --- /dev/null +++ b/target/linux/generic/pending-6.6/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch @@ -0,0 +1,32 @@ +From 8bf2ce6ea4ee840b70f55a27f80e1cd308051b13 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Mon, 27 Dec 2021 00:38:13 +0100 +Subject: [PATCH 1/2] mtd: spi-nor: locking support for MX25L6405D + +Macronix MX25L6405D supports locking with four block-protection bits. +Currently, the driver only sets three bits. If the bootloader does not +sustain the flash chip in an unlocked state, the flash might be +non-writeable. Add the corresponding flag to enable locking support with +four bits in the status register. + +Tested on Nanostation M2 XM. + +Similar to commit 7ea40b54e83b ("mtd: spi-nor: enable locking support for +MX25L12805D") + +Signed-off-by: David Bauer +Signed-off-by: Nick Hainke +--- + drivers/mtd/spi-nor/macronix.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -48,6 +48,7 @@ static const struct flash_info macronix_ + { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64) + NO_SFDP_FLAGS(SECT_4K) }, + { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128) ++ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP) + NO_SFDP_FLAGS(SECT_4K) }, + { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4) + NO_SFDP_FLAGS(SECT_4K) }, diff --git a/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch new file mode 100644 index 0000000000..99e0fc72bf --- /dev/null +++ b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch @@ -0,0 +1,30 @@ +From 245224608b5368c10407da07557e546743d3c489 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Mon, 27 Dec 2021 09:33:13 +0100 +Subject: [PATCH 2/2] mtd: spi-nor: disable 16-bit-sr for macronix + +Macronix flash chips seem to consist of only one status register. +These chips will not work with the "16-bit Write Status (01h) Command". +Disable SNOR_F_HAS_16BIT_SR for all Macronix chips. + +Tested with MX25L6405D. + +Fixes: 39d1e3340c73 ("mtd: spi-nor: Fix clearing of QE bit on +lock()/unlock()") + +Signed-off-by: David Bauer +Signed-off-by: Nick Hainke +--- + drivers/mtd/spi-nor/macronix.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -107,6 +107,7 @@ static void macronix_nor_default_init(st + { + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; ++ nor->flags &= ~SNOR_F_HAS_16BIT_SR; + nor->flags |= SNOR_F_HAS_LOCK; + } + diff --git a/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch b/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch new file mode 100644 index 0000000000..2053c0fbe2 --- /dev/null +++ b/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch @@ -0,0 +1,52 @@ +From af7b91bcecce0eae24e90acd35d96ecee73e1407 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 12:21:15 +0200 +Subject: [PATCH] fs: add cdrom dependency + +--- + fs/hfs/Kconfig | 1 + + fs/hfsplus/Kconfig | 1 + + fs/isofs/Kconfig | 1 + + fs/udf/Kconfig | 1 + + 4 files changed, 4 insertions(+) + +--- a/fs/hfs/Kconfig ++++ b/fs/hfs/Kconfig +@@ -2,6 +2,7 @@ + config HFS_FS + tristate "Apple Macintosh file system support" + depends on BLOCK ++ select CDROM + select NLS + help + If you say Y here, you will be able to mount Macintosh-formatted +--- a/fs/hfsplus/Kconfig ++++ b/fs/hfsplus/Kconfig +@@ -2,6 +2,7 @@ + config HFSPLUS_FS + tristate "Apple Extended HFS file system support" + depends on BLOCK ++ select CDROM + select NLS + select NLS_UTF8 + help +--- a/fs/isofs/Kconfig ++++ b/fs/isofs/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + config ISO9660_FS + tristate "ISO 9660 CDROM file system support" ++ select CDROM + help + This is the standard file system used on CD-ROMs. It was previously + known as "High Sierra File System" and is called "hsfs" on other +--- a/fs/udf/Kconfig ++++ b/fs/udf/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + config UDF_FS + tristate "UDF file system support" ++ select CDROM + select CRC_ITU_T + select NLS + help diff --git a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch new file mode 100644 index 0000000000..54234caf94 --- /dev/null +++ b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -0,0 +1,733 @@ +From 6173a065cb395d4a9528c4e49810af127db68141 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 16 Nov 2022 12:49:52 +0000 +Subject: [PATCH 1/2] block: add uImage.FIT subimage block driver + +Add a small block driver which exposes filesystem sub-images contained +in U-Boot uImage.FIT images as block devices. + +The uImage.FIT image has to be stored directly on a block device or +partition, MTD device or partition, or UBI volume. + +The driver is intended for systems using the U-Boot bootloader and +uses the root device hint left by the bootloader (or the user) in +the 'chosen' section of the device-tree. + +Example: +/dts-v1/; +/ { + chosen { + rootdisk = <&mmc0_part3>; + }; +}; + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 6 + + drivers/block/Kconfig | 12 + + drivers/block/Makefile | 2 + + drivers/block/fitblk.c | 658 ++++++++++++++++++++++++++++++++++++ + drivers/block/open | 4 + + include/uapi/linux/fitblk.h | 10 + + 6 files changed, 692 insertions(+) + create mode 100644 drivers/block/fitblk.c + create mode 100644 drivers/block/open + create mode 100644 include/uapi/linux/fitblk.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -21052,6 +21052,12 @@ F: Documentation/filesystems/ubifs-authe + F: Documentation/filesystems/ubifs.rst + F: fs/ubifs/ + ++U-BOOT UIMAGE.FIT PARSER ++M: Daniel Golle ++L: linux-block@vger.kernel.org ++S: Maintained ++F: drivers/block/fitblk.c ++ + UBLK USERSPACE BLOCK DRIVER + M: Ming Lei + L: linux-block@vger.kernel.org +--- a/drivers/block/Kconfig ++++ b/drivers/block/Kconfig +@@ -383,6 +383,18 @@ config VIRTIO_BLK + This is the virtual block driver for virtio. It can be used with + QEMU based VMMs (like KVM or Xen). Say Y or M. + ++config UIMAGE_FIT_BLK ++ bool "uImage.FIT block driver" ++ help ++ This driver allows using filesystems contained in uImage.FIT images ++ by mapping them as block devices. ++ ++ It can currently not be built as a module due to libfdt symbols not ++ being exported. ++ ++ Say Y if you want to mount filesystems sub-images of a uImage.FIT ++ stored in a block device partition, mtdblock or ubiblock device. ++ + config BLK_DEV_RBD + tristate "Rados block device (RBD)" + depends on INET && BLOCK +--- a/drivers/block/Makefile ++++ b/drivers/block/Makefile +@@ -39,4 +39,6 @@ obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_b + + obj-$(CONFIG_BLK_DEV_UBLK) += ublk_drv.o + ++obj-$(CONFIG_UIMAGE_FIT_BLK) += fitblk.o ++ + swim_mod-y := swim.o swim_asm.o +--- /dev/null ++++ b/drivers/block/fitblk.c +@@ -0,0 +1,636 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * uImage.FIT virtual block device driver. ++ * ++ * Copyright (C) 2023 Daniel Golle ++ * Copyright (C) 2007 Nick Piggin ++ * Copyright (C) 2007 Novell Inc. ++ * ++ * Initially derived from drivers/block/brd.c which is in parts derived from ++ * drivers/block/rd.c, and drivers/block/loop.c, copyright of their respective ++ * owners. ++ * ++ * uImage.FIT headers extracted from Das U-Boot ++ * (C) Copyright 2008 Semihalf ++ * (C) Copyright 2000-2005 ++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define FIT_DEVICE_PREFIX "fit" ++ ++/* maximum number of pages used for the uImage.FIT index structure */ ++#define FIT_MAX_PAGES 1024 ++ ++/* minimum free sectors to map as read-write "remainder" volume */ ++#define MIN_FREE_SECT 16 ++ ++/* maximum number of mapped loadables */ ++#define MAX_FIT_LOADABLES 16 ++ ++/* constants for uImage.FIT structrure traversal */ ++#define FIT_IMAGES_PATH "/images" ++#define FIT_CONFS_PATH "/configurations" ++ ++/* hash/signature/key node */ ++#define FIT_HASH_NODENAME "hash" ++#define FIT_ALGO_PROP "algo" ++#define FIT_VALUE_PROP "value" ++#define FIT_IGNORE_PROP "uboot-ignore" ++#define FIT_SIG_NODENAME "signature" ++#define FIT_KEY_REQUIRED "required" ++#define FIT_KEY_HINT "key-name-hint" ++ ++/* cipher node */ ++#define FIT_CIPHER_NODENAME "cipher" ++#define FIT_ALGO_PROP "algo" ++ ++/* image node */ ++#define FIT_DATA_PROP "data" ++#define FIT_DATA_POSITION_PROP "data-position" ++#define FIT_DATA_OFFSET_PROP "data-offset" ++#define FIT_DATA_SIZE_PROP "data-size" ++#define FIT_TIMESTAMP_PROP "timestamp" ++#define FIT_DESC_PROP "description" ++#define FIT_ARCH_PROP "arch" ++#define FIT_TYPE_PROP "type" ++#define FIT_OS_PROP "os" ++#define FIT_COMP_PROP "compression" ++#define FIT_ENTRY_PROP "entry" ++#define FIT_LOAD_PROP "load" ++ ++/* configuration node */ ++#define FIT_KERNEL_PROP "kernel" ++#define FIT_FILESYSTEM_PROP "filesystem" ++#define FIT_RAMDISK_PROP "ramdisk" ++#define FIT_FDT_PROP "fdt" ++#define FIT_LOADABLE_PROP "loadables" ++#define FIT_DEFAULT_PROP "default" ++#define FIT_SETUP_PROP "setup" ++#define FIT_FPGA_PROP "fpga" ++#define FIT_FIRMWARE_PROP "firmware" ++#define FIT_STANDALONE_PROP "standalone" ++ ++/* fitblk driver data */ ++static const char *_fitblk_claim_ptr = "I belong to fitblk"; ++static const char *ubootver; ++struct device_node *rootdisk; ++static struct platform_device *pdev; ++static LIST_HEAD(fitblk_devices); ++static DEFINE_MUTEX(devices_mutex); ++refcount_t num_devs; ++ ++struct fitblk { ++ struct platform_device *pdev; ++ struct block_device *lower_bdev; ++ sector_t start_sect; ++ struct gendisk *disk; ++ struct work_struct remove_work; ++ struct list_head list; ++ bool dead; ++}; ++ ++static int fitblk_open(struct block_device *bdev, fmode_t mode) ++{ ++ struct fitblk *fitblk = bdev->bd_disk->private_data; ++ ++ if (fitblk->dead) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++static void fitblk_release(struct gendisk *disk, fmode_t mode) ++{ ++ return; ++} ++ ++static void fitblk_submit_bio(struct bio *orig_bio) ++{ ++ struct bio *bio = orig_bio; ++ struct fitblk *fitblk = bio->bi_bdev->bd_disk->private_data; ++ ++ if (fitblk->dead) ++ return; ++ ++ /* mangle bio and re-submit */ ++ while (bio) { ++ bio->bi_iter.bi_sector += fitblk->start_sect; ++ bio->bi_bdev = fitblk->lower_bdev; ++ bio = bio->bi_next; ++ } ++ submit_bio(orig_bio); ++} ++ ++static void fitblk_remove(struct fitblk *fitblk) ++{ ++ blk_mark_disk_dead(fitblk->disk); ++ mutex_lock(&devices_mutex); ++ fitblk->dead = true; ++ list_del(&fitblk->list); ++ mutex_unlock(&devices_mutex); ++ ++ schedule_work(&fitblk->remove_work); ++} ++ ++static int fitblk_ioctl(struct block_device *bdev, fmode_t mode, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct fitblk *fitblk = bdev->bd_disk->private_data; ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EACCES; ++ ++ if (fitblk->dead) ++ return -ENOENT; ++ ++ switch (cmd) { ++ case FITBLK_RELEASE: ++ fitblk_remove(fitblk); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct block_device_operations fitblk_fops = { ++ .owner = THIS_MODULE, ++ .ioctl = fitblk_ioctl, ++ .open = fitblk_open, ++ .release = fitblk_release, ++ .submit_bio = fitblk_submit_bio, ++}; ++ ++static void fitblk_purge(struct work_struct *work) ++{ ++ struct fitblk *fitblk = container_of(work, struct fitblk, remove_work); ++ ++ //del_gendisk(fitblk->disk); // causes crash, not doing it doesn't matter ++ refcount_dec(&num_devs); ++ platform_device_del(fitblk->pdev); ++ platform_device_put(fitblk->pdev); ++ ++ if (refcount_dec_if_one(&num_devs)) { ++ sysfs_remove_link(&pdev->dev.kobj, "lower_dev"); ++ blkdev_put(fitblk->lower_bdev, FMODE_READ | FMODE_EXCL); ++ } ++ ++ kfree(fitblk); ++} ++ ++static int add_fit_subimage_device(struct block_device *lower_bdev, ++ unsigned int slot, sector_t start_sect, ++ sector_t nr_sect, bool readonly) ++{ ++ struct fitblk *fitblk; ++ struct gendisk *disk; ++ int err; ++ ++ mutex_lock(&devices_mutex); ++ if (!refcount_inc_not_zero(&num_devs)) ++ return -EBADF; ++ ++ fitblk = kzalloc(sizeof(struct fitblk), GFP_KERNEL); ++ if (!fitblk) { ++ err = -ENOMEM; ++ goto out_unlock; ++ } ++ ++ fitblk->lower_bdev = lower_bdev; ++ fitblk->start_sect = start_sect; ++ INIT_WORK(&fitblk->remove_work, fitblk_purge); ++ ++ disk = blk_alloc_disk(NUMA_NO_NODE); ++ if (!disk) { ++ err = -ENOMEM; ++ goto out_free_fitblk; ++ } ++ ++ disk->first_minor = 0; ++ disk->flags = lower_bdev->bd_disk->flags | GENHD_FL_NO_PART; ++ disk->fops = &fitblk_fops; ++ disk->private_data = fitblk; ++ if (readonly) { ++ set_disk_ro(disk, 1); ++ snprintf(disk->disk_name, sizeof(disk->disk_name), FIT_DEVICE_PREFIX "%u", slot); ++ } else { ++ strcpy(disk->disk_name, FIT_DEVICE_PREFIX "rw"); ++ } ++ ++ set_capacity(disk, nr_sect); ++ ++ disk->queue->queue_flags = lower_bdev->bd_disk->queue->queue_flags; ++ memcpy(&disk->queue->limits, &lower_bdev->bd_disk->queue->limits, ++ sizeof(struct queue_limits)); ++ ++ fitblk->disk = disk; ++ fitblk->pdev = platform_device_alloc(disk->disk_name, PLATFORM_DEVID_NONE); ++ if (!fitblk->pdev) { ++ err = -ENOMEM; ++ goto out_cleanup_disk; ++ } ++ ++ fitblk->pdev->dev.parent = &pdev->dev; ++ err = platform_device_add(fitblk->pdev); ++ if (err) ++ goto out_put_pdev; ++ ++ err = device_add_disk(&fitblk->pdev->dev, disk, NULL); ++ if (err) ++ goto out_del_pdev; ++ ++ if (!ROOT_DEV) ++ ROOT_DEV = disk->part0->bd_dev; ++ ++ list_add_tail(&fitblk->list, &fitblk_devices); ++ ++ mutex_unlock(&devices_mutex); ++ ++ return 0; ++ ++out_del_pdev: ++ platform_device_del(fitblk->pdev); ++out_put_pdev: ++ platform_device_put(fitblk->pdev); ++out_cleanup_disk: ++ put_disk(disk); ++out_free_fitblk: ++ kfree(fitblk); ++out_unlock: ++ refcount_dec(&num_devs); ++ mutex_unlock(&devices_mutex); ++ return err; ++} ++ ++static int parse_fit_on_dev(struct device *dev) ++{ ++ struct block_device *bdev; ++ struct address_space *mapping; ++ struct folio *folio; ++ pgoff_t f_index = 0; ++ size_t bytes_left, bytes_to_copy; ++ void *pre_fit, *fit, *fit_c; ++ u64 dsize, dsectors, imgmaxsect = 0; ++ u32 size, image_pos, image_len; ++ const __be32 *image_offset_be, *image_len_be, *image_pos_be; ++ int ret = 0, node, images, config; ++ const char *image_name, *image_type, *image_description, ++ *config_default, *config_description, *config_loadables; ++ u32 image_name_len, image_type_len, image_description_len, ++ bootconf_len, config_default_len, config_description_len, ++ config_loadables_len; ++ sector_t start_sect, nr_sects; ++ struct device_node *np = NULL; ++ const char *bootconf_c; ++ const char *loadable; ++ char *bootconf = NULL, *bootconf_term; ++ bool found; ++ int loadables_rem_len, loadable_len; ++ u16 loadcnt; ++ unsigned int slot = 0; ++ ++ /* Exclusive open the block device to receive holder notifications */ ++ bdev = blkdev_get_by_dev(dev->devt, FMODE_READ | FMODE_EXCL, &_fitblk_claim_ptr); ++ if (!bdev) ++ return -ENODEV; ++ ++ if (IS_ERR(bdev)) ++ return PTR_ERR(bdev); ++ ++ mapping = bdev->bd_inode->i_mapping; ++ ++ /* map first page */ ++ folio = read_mapping_folio(mapping, f_index++, NULL); ++ if (IS_ERR(folio)) { ++ ret = PTR_ERR(folio); ++ goto out_blkdev; ++ } ++ pre_fit = folio_address(folio) + offset_in_folio(folio, 0); ++ ++ /* uImage.FIT is based on flattened device tree structure */ ++ if (fdt_check_header(pre_fit)) { ++ ret = -EINVAL; ++ folio_put(folio); ++ goto out_blkdev; ++ } ++ ++ size = fdt_totalsize(pre_fit); ++ ++ if (size > PAGE_SIZE * FIT_MAX_PAGES) { ++ ret = -EOPNOTSUPP; ++ folio_put(folio); ++ goto out_blkdev; ++ } ++ ++ /* acquire disk size */ ++ dsectors = bdev_nr_sectors(bdev); ++ dsize = dsectors << SECTOR_SHIFT; ++ ++ /* abort if FIT structure is larger than disk or partition size */ ++ if (size >= dsize) { ++ ret = -EFBIG; ++ folio_put(folio); ++ goto out_blkdev; ++ } ++ ++ fit = kmalloc(size, GFP_KERNEL); ++ if (!fit) { ++ ret = -ENOMEM; ++ folio_put(folio); ++ goto out_blkdev; ++ } ++ ++ bytes_left = size; ++ fit_c = fit; ++ while (bytes_left > 0) { ++ bytes_to_copy = min_t(size_t, bytes_left, ++ folio_size(folio) - offset_in_folio(folio, 0)); ++ memcpy(fit_c, pre_fit, bytes_to_copy); ++ fit_c += bytes_to_copy; ++ bytes_left -= bytes_to_copy; ++ if (bytes_left) { ++ folio_put(folio); ++ folio = read_mapping_folio(mapping, f_index++, NULL); ++ if (IS_ERR(folio)) { ++ ret = PTR_ERR(folio); ++ goto out_blkdev; ++ }; ++ pre_fit = folio_address(folio) + offset_in_folio(folio, 0); ++ } ++ } ++ folio_put(folio); ++ ++ /* set boot config node name U-Boot may have added to the device tree */ ++ np = of_find_node_by_path("/chosen"); ++ if (np) { ++ bootconf_c = of_get_property(np, "u-boot,bootconf", &bootconf_len); ++ if (bootconf_c && bootconf_len) ++ bootconf = kmemdup_nul(bootconf_c, bootconf_len, GFP_KERNEL); ++ } ++ ++ if (bootconf) { ++ bootconf_term = strchr(bootconf, '#'); ++ if (bootconf_term) ++ *bootconf_term = '\0'; ++ } ++ ++ /* find configuration path in uImage.FIT */ ++ config = fdt_path_offset(fit, FIT_CONFS_PATH); ++ if (config < 0) { ++ pr_err("FIT: Cannot find %s node: %d\n", ++ FIT_CONFS_PATH, config); ++ ret = -ENOENT; ++ goto out_bootconf; ++ } ++ ++ /* get default configuration node name */ ++ config_default = ++ fdt_getprop(fit, config, FIT_DEFAULT_PROP, &config_default_len); ++ ++ /* make sure we got either default or selected boot config node name */ ++ if (!config_default && !bootconf) { ++ pr_err("FIT: Cannot find default configuration\n"); ++ ret = -ENOENT; ++ goto out_bootconf; ++ } ++ ++ /* find selected boot config node, fallback on default config node */ ++ node = fdt_subnode_offset(fit, config, bootconf ?: config_default); ++ if (node < 0) { ++ pr_err("FIT: Cannot find %s node: %d\n", ++ bootconf ?: config_default, node); ++ ret = -ENOENT; ++ goto out_bootconf; ++ } ++ ++ pr_info("FIT: Detected U-Boot %s\n", ubootver); ++ ++ /* get selected configuration data */ ++ config_description = ++ fdt_getprop(fit, node, FIT_DESC_PROP, &config_description_len); ++ config_loadables = fdt_getprop(fit, node, FIT_LOADABLE_PROP, ++ &config_loadables_len); ++ ++ pr_info("FIT: %s configuration: \"%.*s\"%s%.*s%s\n", ++ bootconf ? "Selected" : "Default", ++ bootconf ? bootconf_len : config_default_len, ++ bootconf ?: config_default, ++ config_description ? " (" : "", ++ config_description ? config_description_len : 0, ++ config_description ?: "", ++ config_description ? ")" : ""); ++ ++ if (!config_loadables || !config_loadables_len) { ++ pr_err("FIT: No loadables configured in \"%s\"\n", ++ bootconf ?: config_default); ++ ret = -ENOENT; ++ goto out_bootconf; ++ } ++ ++ /* get images path in uImage.FIT */ ++ images = fdt_path_offset(fit, FIT_IMAGES_PATH); ++ if (images < 0) { ++ pr_err("FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH, images); ++ ret = -EINVAL; ++ goto out_bootconf; ++ } ++ ++ /* iterate over images in uImage.FIT */ ++ fdt_for_each_subnode(node, fit, images) { ++ image_name = fdt_get_name(fit, node, &image_name_len); ++ image_type = fdt_getprop(fit, node, FIT_TYPE_PROP, &image_type_len); ++ image_offset_be = fdt_getprop(fit, node, FIT_DATA_OFFSET_PROP, NULL); ++ image_pos_be = fdt_getprop(fit, node, FIT_DATA_POSITION_PROP, NULL); ++ image_len_be = fdt_getprop(fit, node, FIT_DATA_SIZE_PROP, NULL); ++ ++ if (!image_name || !image_type || !image_len_be || ++ !image_name_len || !image_type_len) ++ continue; ++ ++ image_len = be32_to_cpu(*image_len_be); ++ if (!image_len) ++ continue; ++ ++ if (image_offset_be) ++ image_pos = be32_to_cpu(*image_offset_be) + size; ++ else if (image_pos_be) ++ image_pos = be32_to_cpu(*image_pos_be); ++ else ++ continue; ++ ++ image_description = fdt_getprop(fit, node, FIT_DESC_PROP, ++ &image_description_len); ++ ++ pr_info("FIT: %16s sub-image 0x%08x..0x%08x \"%.*s\"%s%.*s%s\n", ++ image_type, image_pos, image_pos + image_len - 1, ++ image_name_len, image_name, image_description ? " (" : "", ++ image_description ? image_description_len : 0, ++ image_description ?: "", image_description ? ") " : ""); ++ ++ /* only 'filesystem' images should be mapped as partitions */ ++ if (strncmp(image_type, FIT_FILESYSTEM_PROP, image_type_len)) ++ continue; ++ ++ /* check if sub-image is part of configured loadables */ ++ found = false; ++ loadable = config_loadables; ++ loadables_rem_len = config_loadables_len; ++ for (loadcnt = 0; loadables_rem_len > 1 && ++ loadcnt < MAX_FIT_LOADABLES; ++loadcnt) { ++ loadable_len = ++ strnlen(loadable, loadables_rem_len - 1) + 1; ++ loadables_rem_len -= loadable_len; ++ if (!strncmp(image_name, loadable, loadable_len)) { ++ found = true; ++ break; ++ } ++ loadable += loadable_len; ++ } ++ if (!found) ++ continue; ++ ++ if (image_pos % (1 << PAGE_SHIFT)) { ++ dev_err(dev, "FIT: image %.*s start not aligned to page boundaries, skipping\n", ++ image_name_len, image_name); ++ continue; ++ } ++ ++ if (image_len % (1 << PAGE_SHIFT)) { ++ dev_err(dev, "FIT: sub-image %.*s end not aligned to page boundaries, skipping\n", ++ image_name_len, image_name); ++ continue; ++ } ++ ++ start_sect = image_pos >> SECTOR_SHIFT; ++ nr_sects = image_len >> SECTOR_SHIFT; ++ imgmaxsect = max_t(sector_t, imgmaxsect, start_sect + nr_sects); ++ ++ if (start_sect + nr_sects > dsectors) { ++ dev_err(dev, "FIT: sub-image %.*s disk access beyond EOD\n", ++ image_name_len, image_name); ++ continue; ++ } ++ ++ if (!slot) { ++ ret = sysfs_create_link_nowarn(&pdev->dev.kobj, bdev_kobj(bdev), "lower_dev"); ++ if (ret && ret != -EEXIST) ++ goto out_bootconf; ++ ++ ret = 0; ++ } ++ ++ add_fit_subimage_device(bdev, slot++, start_sect, nr_sects, true); ++ } ++ ++ if (!found || !slot) ++ goto out_bootconf; ++ ++ dev_info(dev, "mapped %u uImage.FIT filesystem sub-image%s as /dev/fit%s%u%s\n", ++ slot, (slot > 1)?"s":"", (slot > 1)?"[0...":"", slot - 1, ++ (slot > 1)?"]":""); ++ ++ /* in case uImage.FIT is stored in a partition, map the remaining space */ ++ if (!bdev->bd_read_only && bdev_is_partition(bdev) && ++ (imgmaxsect + MIN_FREE_SECT) < dsectors) { ++ add_fit_subimage_device(bdev, slot++, imgmaxsect, ++ dsectors - imgmaxsect, false); ++ dev_info(dev, "mapped remaing space as /dev/fitrw\n"); ++ } ++ ++out_bootconf: ++ kfree(bootconf); ++ kfree(fit); ++out_blkdev: ++ if (!found || ret) ++ blkdev_put(bdev, FMODE_READ | FMODE_EXCL); ++ ++ return ret; ++} ++ ++static int fitblk_match_of_node(struct device *dev, const void *np) ++{ ++ int ret; ++ ++ ret = device_match_of_node(dev, np); ++ if (ret) ++ return ret; ++ ++ /* ++ * To match ubiblock and mtdblock devices by their parent ubi ++ * or mtd device, also consider block device parent ++ */ ++ if (!dev->parent) ++ return 0; ++ ++ return device_match_of_node(dev->parent, np); ++} ++ ++static int fitblk_probe(struct platform_device *pdev) ++{ ++ struct device *dev; ++ ++ dev = class_find_device(&block_class, NULL, rootdisk, fitblk_match_of_node); ++ if (!dev) ++ return -EPROBE_DEFER; ++ ++ return parse_fit_on_dev(dev); ++} ++ ++static struct platform_driver fitblk_driver = { ++ .probe = fitblk_probe, ++ .driver = { ++ .name = "fitblk", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init fitblk_init(void) ++{ ++ /* detect U-Boot firmware */ ++ ubootver = of_get_property(of_chosen, "u-boot,version", NULL); ++ if (!ubootver) ++ return 0; ++ ++ /* parse 'rootdisk' property phandle */ ++ rootdisk = of_parse_phandle(of_chosen, "rootdisk", 0); ++ if (!rootdisk) ++ return 0; ++ ++ if (platform_driver_register(&fitblk_driver)) ++ return -ENODEV; ++ ++ refcount_set(&num_devs, 1); ++ pdev = platform_device_register_simple("fitblk", -1, NULL, 0); ++ if (IS_ERR(pdev)) ++ return PTR_ERR(pdev); ++ ++ return 0; ++} ++device_initcall(fitblk_init); +--- /dev/null ++++ b/include/uapi/linux/fitblk.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef _UAPI_LINUX_FITBLK_H ++#define _UAPI_LINUX_FITBLK_H ++ ++/* ++ * IOCTL commands --- we will commandeer 0x46 ('F') ++ */ ++#define FITBLK_RELEASE 0x4600 ++ ++#endif /* _UAPI_LINUX_FITBLK_H */ diff --git a/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch new file mode 100644 index 0000000000..685a5f9da5 --- /dev/null +++ b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch @@ -0,0 +1,25 @@ +From 5ede3f8aed9a1a579bf7304142600d1f3500add9 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 12 Jun 2023 03:58:42 +0100 +Subject: [PATCH 2/2] init: bypass device lookup for /dev/fit* rootfs + +Allow 'rootwait' as /dev/fit* can show up late if the underlaying +device is probed late. + +Signed-off-by: Daniel Golle +--- + init/do_mounts.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -645,7 +645,8 @@ void __init prepare_namespace(void) + + if (saved_root_name[0]) { + root_device_name = saved_root_name; +- if (!strncmp(root_device_name, "mtd", 3) || ++ if (!strncmp(root_device_name, "fit", 3) || ++ !strncmp(root_device_name, "mtd", 3) || + !strncmp(root_device_name, "ubi", 3)) { + mount_block_root(root_device_name, root_mountflags); + goto out; diff --git a/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch new file mode 100644 index 0000000000..27a673399a --- /dev/null +++ b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch @@ -0,0 +1,5180 @@ +From: Alexandros C. Couloumbis +Subject: fs: add jffs2/lzma support (not activated by default yet) + +lede-commit: c2c88d315fa0e881f8b19da07b62859b915b11b2 +Signed-off-by: Alexandros C. Couloumbis +--- + fs/jffs2/Kconfig | 9 + + fs/jffs2/Makefile | 3 + + fs/jffs2/compr.c | 6 + + fs/jffs2/compr.h | 10 +- + fs/jffs2/compr_lzma.c | 128 +++ + fs/jffs2/super.c | 33 +- + include/linux/lzma.h | 62 ++ + include/linux/lzma/LzFind.h | 115 +++ + include/linux/lzma/LzHash.h | 54 + + include/linux/lzma/LzmaDec.h | 231 +++++ + include/linux/lzma/LzmaEnc.h | 80 ++ + include/linux/lzma/Types.h | 226 +++++ + include/uapi/linux/jffs2.h | 1 + + lib/Kconfig | 6 + + lib/Makefile | 12 + + lib/lzma/LzFind.c | 761 ++++++++++++++ + lib/lzma/LzmaDec.c | 999 +++++++++++++++++++ + lib/lzma/LzmaEnc.c | 2271 ++++++++++++++++++++++++++++++++++++++++++ + lib/lzma/Makefile | 7 + + 19 files changed, 5008 insertions(+), 6 deletions(-) + create mode 100644 fs/jffs2/compr_lzma.c + create mode 100644 include/linux/lzma.h + create mode 100644 include/linux/lzma/LzFind.h + create mode 100644 include/linux/lzma/LzHash.h + create mode 100644 include/linux/lzma/LzmaDec.h + create mode 100644 include/linux/lzma/LzmaEnc.h + create mode 100644 include/linux/lzma/Types.h + create mode 100644 lib/lzma/LzFind.c + create mode 100644 lib/lzma/LzmaDec.c + create mode 100644 lib/lzma/LzmaEnc.c + create mode 100644 lib/lzma/Makefile + +--- a/fs/jffs2/Kconfig ++++ b/fs/jffs2/Kconfig +@@ -136,6 +136,15 @@ config JFFS2_LZO + This feature was added in July, 2007. Say 'N' if you need + compatibility with older bootloaders or kernels. + ++config JFFS2_LZMA ++ bool "JFFS2 LZMA compression support" if JFFS2_COMPRESSION_OPTIONS ++ select LZMA_COMPRESS ++ select LZMA_DECOMPRESS ++ depends on JFFS2_FS ++ default n ++ help ++ JFFS2 wrapper to the LZMA C SDK ++ + config JFFS2_RTIME + bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS + depends on JFFS2_FS +--- a/fs/jffs2/Makefile ++++ b/fs/jffs2/Makefile +@@ -19,4 +19,7 @@ jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rub + jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o + jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o + jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o ++jffs2-$(CONFIG_JFFS2_LZMA) += compr_lzma.o + jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o ++ ++CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma +--- a/fs/jffs2/compr.c ++++ b/fs/jffs2/compr.c +@@ -378,6 +378,9 @@ int __init jffs2_compressors_init(void) + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_init(); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_init(); ++#endif + /* Setting default compression mode */ + #ifdef CONFIG_JFFS2_CMODE_NONE + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; +@@ -401,6 +404,9 @@ int __init jffs2_compressors_init(void) + int jffs2_compressors_exit(void) + { + /* Unregistering compressors */ ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_exit(); ++#endif + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_exit(); + #endif +--- a/fs/jffs2/compr.h ++++ b/fs/jffs2/compr.h +@@ -29,9 +29,9 @@ + #define JFFS2_DYNRUBIN_PRIORITY 20 + #define JFFS2_LZARI_PRIORITY 30 + #define JFFS2_RTIME_PRIORITY 50 +-#define JFFS2_ZLIB_PRIORITY 60 +-#define JFFS2_LZO_PRIORITY 80 +- ++#define JFFS2_LZMA_PRIORITY 70 ++#define JFFS2_ZLIB_PRIORITY 80 ++#define JFFS2_LZO_PRIORITY 90 + + #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ + #define JFFS2_DYNRUBIN_DISABLED /* for decompression */ +@@ -101,5 +101,9 @@ void jffs2_zlib_exit(void); + int jffs2_lzo_init(void); + void jffs2_lzo_exit(void); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++int jffs2_lzma_init(void); ++void jffs2_lzma_exit(void); ++#endif + + #endif /* __JFFS2_COMPR_H__ */ +--- /dev/null ++++ b/fs/jffs2/compr_lzma.c +@@ -0,0 +1,128 @@ ++/* ++ * JFFS2 -- Journalling Flash File System, Version 2. ++ * ++ * For licensing information, see the file 'LICENCE' in this directory. ++ * ++ * JFFS2 wrapper to the LZMA C SDK ++ * ++ */ ++ ++#include ++#include "compr.h" ++ ++#ifdef __KERNEL__ ++ static DEFINE_MUTEX(deflate_mutex); ++#endif ++ ++CLzmaEncHandle *p; ++Byte propsEncoded[LZMA_PROPS_SIZE]; ++SizeT propsSize = sizeof(propsEncoded); ++ ++STATIC void lzma_free_workspace(void) ++{ ++ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc); ++} ++ ++STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props) ++{ ++ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) ++ { ++ PRINT_ERROR("Failed to allocate lzma deflate workspace\n"); ++ return -ENOMEM; ++ } ++ ++ if (LzmaEnc_SetProps(p, props) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t *sourcelen, uint32_t *dstlen) ++{ ++ SizeT compress_size = (SizeT)(*dstlen); ++ int ret; ++ ++ #ifdef __KERNEL__ ++ mutex_lock(&deflate_mutex); ++ #endif ++ ++ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen, ++ 0, NULL, &lzma_alloc, &lzma_alloc); ++ ++ #ifdef __KERNEL__ ++ mutex_unlock(&deflate_mutex); ++ #endif ++ ++ if (ret != SZ_OK) ++ return -1; ++ ++ *dstlen = (uint32_t)compress_size; ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t srclen, uint32_t destlen) ++{ ++ int ret; ++ SizeT dl = (SizeT)destlen; ++ SizeT sl = (SizeT)srclen; ++ ELzmaStatus status; ++ ++ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded, ++ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc); ++ ++ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen) ++ return -1; ++ ++ return 0; ++} ++ ++static struct jffs2_compressor jffs2_lzma_comp = { ++ .priority = JFFS2_LZMA_PRIORITY, ++ .name = "lzma", ++ .compr = JFFS2_COMPR_LZMA, ++ .compress = &jffs2_lzma_compress, ++ .decompress = &jffs2_lzma_decompress, ++ .disabled = 0, ++}; ++ ++int INIT jffs2_lzma_init(void) ++{ ++ int ret; ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ ++ props.dictSize = LZMA_BEST_DICT(0x2000); ++ props.level = LZMA_BEST_LEVEL; ++ props.lc = LZMA_BEST_LC; ++ props.lp = LZMA_BEST_LP; ++ props.pb = LZMA_BEST_PB; ++ props.fb = LZMA_BEST_FB; ++ ++ ret = lzma_alloc_workspace(&props); ++ if (ret < 0) ++ return ret; ++ ++ ret = jffs2_register_compressor(&jffs2_lzma_comp); ++ if (ret) ++ lzma_free_workspace(); ++ ++ return ret; ++} ++ ++void jffs2_lzma_exit(void) ++{ ++ jffs2_unregister_compressor(&jffs2_lzma_comp); ++ lzma_free_workspace(); ++} +--- a/fs/jffs2/super.c ++++ b/fs/jffs2/super.c +@@ -374,14 +374,41 @@ static int __init init_jffs2_fs(void) + BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68); + BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32); + +- pr_info("version 2.2." ++ pr_info("version 2.2" + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER + " (NAND)" + #endif + #ifdef CONFIG_JFFS2_SUMMARY +- " (SUMMARY) " ++ " (SUMMARY)" + #endif +- " © 2001-2006 Red Hat, Inc.\n"); ++#ifdef CONFIG_JFFS2_ZLIB ++ " (ZLIB)" ++#endif ++#ifdef CONFIG_JFFS2_LZO ++ " (LZO)" ++#endif ++#ifdef CONFIG_JFFS2_LZMA ++ " (LZMA)" ++#endif ++#ifdef CONFIG_JFFS2_RTIME ++ " (RTIME)" ++#endif ++#ifdef CONFIG_JFFS2_RUBIN ++ " (RUBIN)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_NONE ++ " (CMODE_NONE)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_PRIORITY ++ " (CMODE_PRIORITY)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_SIZE ++ " (CMODE_SIZE)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO ++ " (CMODE_FAVOURLZO)" ++#endif ++ " (c) 2001-2006 Red Hat, Inc.\n"); + + jffs2_inode_cachep = kmem_cache_create("jffs2_i", + sizeof(struct jffs2_inode_info), +--- /dev/null ++++ b/include/linux/lzma.h +@@ -0,0 +1,62 @@ ++#ifndef __LZMA_H__ ++#define __LZMA_H__ ++ ++#ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #define LZMA_MALLOC vmalloc ++ #define LZMA_FREE vfree ++ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg) ++ #define INIT __init ++ #define STATIC static ++#else ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #ifndef PAGE_SIZE ++ extern int page_size; ++ #define PAGE_SIZE page_size ++ #endif ++ #define LZMA_MALLOC malloc ++ #define LZMA_FREE free ++ #define PRINT_ERROR(msg) fprintf(stderr, msg) ++ #define INIT ++ #define STATIC ++#endif ++ ++#include "lzma/LzmaDec.h" ++#include "lzma/LzmaEnc.h" ++ ++#define LZMA_BEST_LEVEL (9) ++#define LZMA_BEST_LC (0) ++#define LZMA_BEST_LP (0) ++#define LZMA_BEST_PB (0) ++#define LZMA_BEST_FB (273) ++ ++#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2) ++ ++static void *p_lzma_malloc(void *p, size_t size) ++{ ++ if (size == 0) ++ return NULL; ++ ++ return LZMA_MALLOC(size); ++} ++ ++static void p_lzma_free(void *p, void *address) ++{ ++ if (address != NULL) ++ LZMA_FREE(address); ++} ++ ++static ISzAlloc lzma_alloc = { .Alloc = p_lzma_malloc, .Free = p_lzma_free }; ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzFind.h +@@ -0,0 +1,115 @@ ++/* LzFind.h -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZ_FIND_H ++#define __LZ_FIND_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef UInt32 CLzRef; ++ ++typedef struct _CMatchFinder ++{ ++ Byte *buffer; ++ UInt32 pos; ++ UInt32 posLimit; ++ UInt32 streamPos; ++ UInt32 lenLimit; ++ ++ UInt32 cyclicBufferPos; ++ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ ++ ++ UInt32 matchMaxLen; ++ CLzRef *hash; ++ CLzRef *son; ++ UInt32 hashMask; ++ UInt32 cutValue; ++ ++ Byte *bufferBase; ++ ISeqInStream *stream; ++ int streamEndWasReached; ++ ++ UInt32 blockSize; ++ UInt32 keepSizeBefore; ++ UInt32 keepSizeAfter; ++ ++ UInt32 numHashBytes; ++ int directInput; ++ size_t directInputRem; ++ int btMode; ++ int bigHash; ++ UInt32 historySize; ++ UInt32 fixedHashSize; ++ UInt32 hashSizeSum; ++ UInt32 numSons; ++ SRes result; ++ UInt32 crc[256]; ++} CMatchFinder; ++ ++#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) ++#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) ++ ++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) ++ ++int MatchFinder_NeedMove(CMatchFinder *p); ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); ++void MatchFinder_MoveBlock(CMatchFinder *p); ++void MatchFinder_ReadIfRequired(CMatchFinder *p); ++ ++void MatchFinder_Construct(CMatchFinder *p); ++ ++/* Conditions: ++ historySize <= 3 GB ++ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB ++*/ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc); ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, ++ UInt32 *distances, UInt32 maxLen); ++ ++/* ++Conditions: ++ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. ++ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function ++*/ ++ ++typedef void (*Mf_Init_Func)(void *object); ++typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); ++typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); ++typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); ++typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); ++typedef void (*Mf_Skip_Func)(void *object, UInt32); ++ ++typedef struct _IMatchFinder ++{ ++ Mf_Init_Func Init; ++ Mf_GetIndexByte_Func GetIndexByte; ++ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; ++ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; ++ Mf_GetMatches_Func GetMatches; ++ Mf_Skip_Func Skip; ++} IMatchFinder; ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); ++ ++void MatchFinder_Init(CMatchFinder *p); ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzHash.h +@@ -0,0 +1,54 @@ ++/* LzHash.h -- HASH functions for LZ algorithms ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZ_HASH_H ++#define __LZ_HASH_H ++ ++#define kHash2Size (1 << 10) ++#define kHash3Size (1 << 16) ++#define kHash4Size (1 << 20) ++ ++#define kFix3HashSize (kHash2Size) ++#define kFix4HashSize (kHash2Size + kHash3Size) ++#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) ++ ++#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); ++ ++#define HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } ++ ++#define HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } ++ ++#define HASH5_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ ++ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ ++ hash4Value &= (kHash4Size - 1); } ++ ++/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ ++#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; ++ ++ ++#define MT_HASH2_CALC \ ++ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); ++ ++#define MT_HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } ++ ++#define MT_HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaDec.h +@@ -0,0 +1,231 @@ ++/* LzmaDec.h -- LZMA Decoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZMA_DEC_H ++#define __LZMA_DEC_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* #define _LZMA_PROB32 */ ++/* _LZMA_PROB32 can increase the speed on some CPUs, ++ but memory usage for CLzmaDec::probs will be doubled in that case */ ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++ ++/* ---------- LZMA Properties ---------- */ ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaProps ++{ ++ unsigned lc, lp, pb; ++ UInt32 dicSize; ++} CLzmaProps; ++ ++/* LzmaProps_Decode - decodes properties ++Returns: ++ SZ_OK ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); ++ ++ ++/* ---------- LZMA Decoder state ---------- */ ++ ++/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. ++ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ ++ ++#define LZMA_REQUIRED_INPUT_MAX 20 ++ ++typedef struct ++{ ++ CLzmaProps prop; ++ CLzmaProb *probs; ++ Byte *dic; ++ const Byte *buf; ++ UInt32 range, code; ++ SizeT dicPos; ++ SizeT dicBufSize; ++ UInt32 processedPos; ++ UInt32 checkDicSize; ++ unsigned state; ++ UInt32 reps[4]; ++ unsigned remainLen; ++ int needFlush; ++ int needInitState; ++ UInt32 numProbs; ++ unsigned tempBufSize; ++ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; ++} CLzmaDec; ++ ++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } ++ ++void LzmaDec_Init(CLzmaDec *p); ++ ++/* There are two types of LZMA streams: ++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. ++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ ++ ++typedef enum ++{ ++ LZMA_FINISH_ANY, /* finish at any point */ ++ LZMA_FINISH_END /* block must be finished at the end */ ++} ELzmaFinishMode; ++ ++/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! ++ ++ You must use LZMA_FINISH_END, when you know that current output buffer ++ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. ++ ++ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, ++ and output value of destLen will be less than output buffer size limit. ++ You can check status result also. ++ ++ You can use multiple checks to test data integrity after full decompression: ++ 1) Check Result and "status" variable. ++ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. ++ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. ++ You must use correct finish mode in that case. */ ++ ++typedef enum ++{ ++ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ ++ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ ++ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ ++ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ ++} ELzmaStatus; ++ ++/* ELzmaStatus is used only as output value for function call */ ++ ++ ++/* ---------- Interfaces ---------- */ ++ ++/* There are 3 levels of interfaces: ++ 1) Dictionary Interface ++ 2) Buffer Interface ++ 3) One Call Interface ++ You can select any of these interfaces, but don't mix functions from different ++ groups for same object. */ ++ ++ ++/* There are two variants to allocate state for Dictionary Interface: ++ 1) LzmaDec_Allocate / LzmaDec_Free ++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs ++ You can use variant 2, if you set dictionary buffer manually. ++ For Buffer Interface you must always use variant 1. ++ ++LzmaDec_Allocate* can return: ++ SZ_OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); ++ ++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); ++ ++/* ---------- Dictionary Interface ---------- */ ++ ++/* You can use it, if you want to eliminate the overhead for data copying from ++ dictionary to some other external buffer. ++ You must work with CLzmaDec variables directly in this interface. ++ ++ STEPS: ++ LzmaDec_Constr() ++ LzmaDec_Allocate() ++ for (each new stream) ++ { ++ LzmaDec_Init() ++ while (it needs more decompression) ++ { ++ LzmaDec_DecodeToDic() ++ use data from CLzmaDec::dic and update CLzmaDec::dicPos ++ } ++ } ++ LzmaDec_Free() ++*/ ++ ++/* LzmaDec_DecodeToDic ++ ++ The decoding to internal dictionary buffer (CLzmaDec::dic). ++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (dicLimit). ++ LZMA_FINISH_ANY - Decode just dicLimit bytes. ++ LZMA_FINISH_END - Stream must be finished after dicLimit. ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_NEEDS_MORE_INPUT ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++*/ ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- Buffer Interface ---------- */ ++ ++/* It's zlib-like interface. ++ See LzmaDec_DecodeToDic description for information about STEPS and return results, ++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need ++ to work with CLzmaDec variables manually. ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++*/ ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaDecode ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). ++*/ ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaEnc.h +@@ -0,0 +1,80 @@ ++/* LzmaEnc.h -- LZMA Encoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZMA_ENC_H ++#define __LZMA_ENC_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaEncProps ++{ ++ int level; /* 0 <= level <= 9 */ ++ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version ++ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version ++ default = (1 << 24) */ ++ int lc; /* 0 <= lc <= 8, default = 3 */ ++ int lp; /* 0 <= lp <= 4, default = 0 */ ++ int pb; /* 0 <= pb <= 4, default = 2 */ ++ int algo; /* 0 - fast, 1 - normal, default = 1 */ ++ int fb; /* 5 <= fb <= 273, default = 32 */ ++ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ ++ int numHashBytes; /* 2, 3 or 4, default = 4 */ ++ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ ++ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ ++ int numThreads; /* 1 or 2, default = 2 */ ++} CLzmaEncProps; ++ ++void LzmaEncProps_Init(CLzmaEncProps *p); ++void LzmaEncProps_Normalize(CLzmaEncProps *p); ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); ++ ++ ++/* ---------- CLzmaEncHandle Interface ---------- */ ++ ++/* LzmaEnc_* functions can return the following exit codes: ++Returns: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater in props ++ SZ_ERROR_WRITE - Write callback error. ++ SZ_ERROR_PROGRESS - some break from progress callback ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++typedef void * CLzmaEncHandle; ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); ++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaEncode ++Return code: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater ++ SZ_ERROR_OUTPUT_EOF - output buffer overflow ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/Types.h +@@ -0,0 +1,226 @@ ++/* Types.h -- Basic types ++2009-11-23 : Igor Pavlov : Public domain */ ++ ++#ifndef __7Z_TYPES_H ++#define __7Z_TYPES_H ++ ++#include ++ ++#ifdef _WIN32 ++#include ++#endif ++ ++#ifndef EXTERN_C_BEGIN ++#ifdef __cplusplus ++#define EXTERN_C_BEGIN extern "C" { ++#define EXTERN_C_END } ++#else ++#define EXTERN_C_BEGIN ++#define EXTERN_C_END ++#endif ++#endif ++ ++EXTERN_C_BEGIN ++ ++#define SZ_OK 0 ++ ++#define SZ_ERROR_DATA 1 ++#define SZ_ERROR_MEM 2 ++#define SZ_ERROR_CRC 3 ++#define SZ_ERROR_UNSUPPORTED 4 ++#define SZ_ERROR_PARAM 5 ++#define SZ_ERROR_INPUT_EOF 6 ++#define SZ_ERROR_OUTPUT_EOF 7 ++#define SZ_ERROR_READ 8 ++#define SZ_ERROR_WRITE 9 ++#define SZ_ERROR_PROGRESS 10 ++#define SZ_ERROR_FAIL 11 ++#define SZ_ERROR_THREAD 12 ++ ++#define SZ_ERROR_ARCHIVE 16 ++#define SZ_ERROR_NO_ARCHIVE 17 ++ ++typedef int SRes; ++ ++#ifdef _WIN32 ++typedef DWORD WRes; ++#else ++typedef int WRes; ++#endif ++ ++#ifndef RINOK ++#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } ++#endif ++ ++typedef unsigned char Byte; ++typedef short Int16; ++typedef unsigned short UInt16; ++ ++#ifdef _LZMA_UINT32_IS_ULONG ++typedef long Int32; ++typedef unsigned long UInt32; ++#else ++typedef int Int32; ++typedef unsigned int UInt32; ++#endif ++ ++#ifdef _SZ_NO_INT_64 ++ ++/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. ++ NOTES: Some code will work incorrectly in that case! */ ++ ++typedef long Int64; ++typedef unsigned long UInt64; ++ ++#else ++ ++#if defined(_MSC_VER) || defined(__BORLANDC__) ++typedef __int64 Int64; ++typedef unsigned __int64 UInt64; ++#else ++typedef long long int Int64; ++typedef unsigned long long int UInt64; ++#endif ++ ++#endif ++ ++#ifdef _LZMA_NO_SYSTEM_SIZE_T ++typedef UInt32 SizeT; ++#else ++typedef size_t SizeT; ++#endif ++ ++typedef int Bool; ++#define True 1 ++#define False 0 ++ ++ ++#ifdef _WIN32 ++#define MY_STD_CALL __stdcall ++#else ++#define MY_STD_CALL ++#endif ++ ++#ifdef _MSC_VER ++ ++#if _MSC_VER >= 1300 ++#define MY_NO_INLINE __declspec(noinline) ++#else ++#define MY_NO_INLINE ++#endif ++ ++#define MY_CDECL __cdecl ++#define MY_FAST_CALL __fastcall ++ ++#else ++ ++#define MY_CDECL ++#define MY_FAST_CALL ++ ++#endif ++ ++ ++/* The following interfaces use first parameter as pointer to structure */ ++ ++typedef struct ++{ ++ SRes (*Read)(void *p, void *buf, size_t *size); ++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. ++ (output(*size) < input(*size)) is allowed */ ++} ISeqInStream; ++ ++/* it can return SZ_ERROR_INPUT_EOF */ ++SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); ++SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); ++SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); ++ ++typedef struct ++{ ++ size_t (*Write)(void *p, const void *buf, size_t size); ++ /* Returns: result - the number of actually written bytes. ++ (result < size) means error */ ++} ISeqOutStream; ++ ++typedef enum ++{ ++ SZ_SEEK_SET = 0, ++ SZ_SEEK_CUR = 1, ++ SZ_SEEK_END = 2 ++} ESzSeek; ++ ++typedef struct ++{ ++ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ ++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); ++} ISeekInStream; ++ ++typedef struct ++{ ++ SRes (*Look)(void *p, void **buf, size_t *size); ++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. ++ (output(*size) > input(*size)) is not allowed ++ (output(*size) < input(*size)) is allowed */ ++ SRes (*Skip)(void *p, size_t offset); ++ /* offset must be <= output(*size) of Look */ ++ ++ SRes (*Read)(void *p, void *buf, size_t *size); ++ /* reads directly (without buffer). It's same as ISeqInStream::Read */ ++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); ++} ILookInStream; ++ ++SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); ++SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); ++ ++/* reads via ILookInStream::Read */ ++SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); ++SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); ++ ++#define LookToRead_BUF_SIZE (1 << 14) ++ ++typedef struct ++{ ++ ILookInStream s; ++ ISeekInStream *realStream; ++ size_t pos; ++ size_t size; ++ Byte buf[LookToRead_BUF_SIZE]; ++} CLookToRead; ++ ++void LookToRead_CreateVTable(CLookToRead *p, int lookahead); ++void LookToRead_Init(CLookToRead *p); ++ ++typedef struct ++{ ++ ISeqInStream s; ++ ILookInStream *realStream; ++} CSecToLook; ++ ++void SecToLook_CreateVTable(CSecToLook *p); ++ ++typedef struct ++{ ++ ISeqInStream s; ++ ILookInStream *realStream; ++} CSecToRead; ++ ++void SecToRead_CreateVTable(CSecToRead *p); ++ ++typedef struct ++{ ++ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); ++ /* Returns: result. (result != SZ_OK) means break. ++ Value (UInt64)(Int64)-1 for size means unknown value. */ ++} ICompressProgress; ++ ++typedef struct ++{ ++ void *(*Alloc)(void *p, size_t size); ++ void (*Free)(void *p, void *address); /* address can be 0 */ ++} ISzAlloc; ++ ++#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) ++#define IAlloc_Free(p, a) (p)->Free((p), a) ++ ++EXTERN_C_END ++ ++#endif +--- a/include/uapi/linux/jffs2.h ++++ b/include/uapi/linux/jffs2.h +@@ -46,6 +46,7 @@ + #define JFFS2_COMPR_DYNRUBIN 0x05 + #define JFFS2_COMPR_ZLIB 0x06 + #define JFFS2_COMPR_LZO 0x07 ++#define JFFS2_COMPR_LZMA 0x08 + /* Compatibility flags. */ + #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ + #define JFFS2_NODE_ACCURATE 0x2000 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -354,6 +354,12 @@ config ZSTD_DECOMPRESS + + source "lib/xz/Kconfig" + ++config LZMA_COMPRESS ++ tristate ++ ++config LZMA_DECOMPRESS ++ tristate ++ + # + # These all provide a common interface (hence the apparent duplication with + # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -140,6 +140,16 @@ CFLAGS_kobject.o += -DDEBUG + CFLAGS_kobject_uevent.o += -DDEBUG + endif + ++ifdef CONFIG_JFFS2_ZLIB ++ CONFIG_ZLIB_INFLATE:=y ++ CONFIG_ZLIB_DEFLATE:=y ++endif ++ ++ifdef CONFIG_JFFS2_LZMA ++ CONFIG_LZMA_DECOMPRESS:=y ++ CONFIG_LZMA_COMPRESS:=y ++endif ++ + obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o + CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any) + +@@ -200,6 +210,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ + obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ + obj-$(CONFIG_XZ_DEC) += xz/ + obj-$(CONFIG_RAID6_PQ) += raid6/ ++obj-$(CONFIG_LZMA_COMPRESS) += lzma/ ++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/ + + lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +--- /dev/null ++++ b/lib/lzma/LzFind.c +@@ -0,0 +1,761 @@ ++/* LzFind.c -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ ++#include ++ ++#include "LzFind.h" ++#include "LzHash.h" ++ ++#define kEmptyHashValue 0 ++#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) ++#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ ++#define kNormalizeMask (~(kNormalizeStepMin - 1)) ++#define kMaxHistorySize ((UInt32)3 << 30) ++ ++#define kStartMaxLen 3 ++ ++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ if (!p->directInput) ++ { ++ alloc->Free(alloc, p->bufferBase); ++ p->bufferBase = 0; ++ } ++} ++ ++/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ ++ ++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) ++{ ++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; ++ if (p->directInput) ++ { ++ p->blockSize = blockSize; ++ return 1; ++ } ++ if (p->bufferBase == 0 || p->blockSize != blockSize) ++ { ++ LzInWindow_Free(p, alloc); ++ p->blockSize = blockSize; ++ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); ++ } ++ return (p->bufferBase != 0); ++} ++ ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } ++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++ ++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++ ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++{ ++ p->posLimit -= subValue; ++ p->pos -= subValue; ++ p->streamPos -= subValue; ++} ++ ++static void MatchFinder_ReadBlock(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached || p->result != SZ_OK) ++ return; ++ if (p->directInput) ++ { ++ UInt32 curSize = 0xFFFFFFFF - p->streamPos; ++ if (curSize > p->directInputRem) ++ curSize = (UInt32)p->directInputRem; ++ p->directInputRem -= curSize; ++ p->streamPos += curSize; ++ if (p->directInputRem == 0) ++ p->streamEndWasReached = 1; ++ return; ++ } ++ for (;;) ++ { ++ Byte *dest = p->buffer + (p->streamPos - p->pos); ++ size_t size = (p->bufferBase + p->blockSize - dest); ++ if (size == 0) ++ return; ++ p->result = p->stream->Read(p->stream, dest, &size); ++ if (p->result != SZ_OK) ++ return; ++ if (size == 0) ++ { ++ p->streamEndWasReached = 1; ++ return; ++ } ++ p->streamPos += (UInt32)size; ++ if (p->streamPos - p->pos > p->keepSizeAfter) ++ return; ++ } ++} ++ ++void MatchFinder_MoveBlock(CMatchFinder *p) ++{ ++ memmove(p->bufferBase, ++ p->buffer - p->keepSizeBefore, ++ (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); ++ p->buffer = p->bufferBase + p->keepSizeBefore; ++} ++ ++int MatchFinder_NeedMove(CMatchFinder *p) ++{ ++ if (p->directInput) ++ return 0; ++ /* if (p->streamEndWasReached) return 0; */ ++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); ++} ++ ++void MatchFinder_ReadIfRequired(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached) ++ return; ++ if (p->keepSizeAfter >= p->streamPos - p->pos) ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) ++{ ++ if (MatchFinder_NeedMove(p)) ++ MatchFinder_MoveBlock(p); ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_SetDefaultSettings(CMatchFinder *p) ++{ ++ p->cutValue = 32; ++ p->btMode = 1; ++ p->numHashBytes = 4; ++ p->bigHash = 0; ++} ++ ++#define kCrcPoly 0xEDB88320 ++ ++void MatchFinder_Construct(CMatchFinder *p) ++{ ++ UInt32 i; ++ p->bufferBase = 0; ++ p->directInput = 0; ++ p->hash = 0; ++ MatchFinder_SetDefaultSettings(p); ++ ++ for (i = 0; i < 256; i++) ++ { ++ UInt32 r = i; ++ int j; ++ for (j = 0; j < 8; j++) ++ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); ++ p->crc[i] = r; ++ } ++} ++ ++static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->hash); ++ p->hash = 0; ++} ++ ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ LzInWindow_Free(p, alloc); ++} ++ ++static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) ++{ ++ size_t sizeInBytes = (size_t)num * sizeof(CLzRef); ++ if (sizeInBytes / sizeof(CLzRef) != num) ++ return 0; ++ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); ++} ++ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc) ++{ ++ UInt32 sizeReserv; ++ if (historySize > kMaxHistorySize) ++ { ++ MatchFinder_Free(p, alloc); ++ return 0; ++ } ++ sizeReserv = historySize >> 1; ++ if (historySize > ((UInt32)2 << 30)) ++ sizeReserv = historySize >> 2; ++ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); ++ ++ p->keepSizeBefore = historySize + keepAddBufferBefore + 1; ++ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; ++ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ ++ if (LzInWindow_Create(p, sizeReserv, alloc)) ++ { ++ UInt32 newCyclicBufferSize = historySize + 1; ++ UInt32 hs; ++ p->matchMaxLen = matchMaxLen; ++ { ++ p->fixedHashSize = 0; ++ if (p->numHashBytes == 2) ++ hs = (1 << 16) - 1; ++ else ++ { ++ hs = historySize - 1; ++ hs |= (hs >> 1); ++ hs |= (hs >> 2); ++ hs |= (hs >> 4); ++ hs |= (hs >> 8); ++ hs >>= 1; ++ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ ++ if (hs > (1 << 24)) ++ { ++ if (p->numHashBytes == 3) ++ hs = (1 << 24) - 1; ++ else ++ hs >>= 1; ++ } ++ } ++ p->hashMask = hs; ++ hs++; ++ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; ++ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; ++ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; ++ hs += p->fixedHashSize; ++ } ++ ++ { ++ UInt32 prevSize = p->hashSizeSum + p->numSons; ++ UInt32 newSize; ++ p->historySize = historySize; ++ p->hashSizeSum = hs; ++ p->cyclicBufferSize = newCyclicBufferSize; ++ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); ++ newSize = p->hashSizeSum + p->numSons; ++ if (p->hash != 0 && prevSize == newSize) ++ return 1; ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ p->hash = AllocRefs(newSize, alloc); ++ if (p->hash != 0) ++ { ++ p->son = p->hash + p->hashSizeSum; ++ return 1; ++ } ++ } ++ } ++ MatchFinder_Free(p, alloc); ++ return 0; ++} ++ ++static void MatchFinder_SetLimits(CMatchFinder *p) ++{ ++ UInt32 limit = kMaxValForNormalize - p->pos; ++ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; ++ if (limit2 < limit) ++ limit = limit2; ++ limit2 = p->streamPos - p->pos; ++ if (limit2 <= p->keepSizeAfter) ++ { ++ if (limit2 > 0) ++ limit2 = 1; ++ } ++ else ++ limit2 -= p->keepSizeAfter; ++ if (limit2 < limit) ++ limit = limit2; ++ { ++ UInt32 lenLimit = p->streamPos - p->pos; ++ if (lenLimit > p->matchMaxLen) ++ lenLimit = p->matchMaxLen; ++ p->lenLimit = lenLimit; ++ } ++ p->posLimit = p->pos + limit; ++} ++ ++void MatchFinder_Init(CMatchFinder *p) ++{ ++ UInt32 i; ++ for (i = 0; i < p->hashSizeSum; i++) ++ p->hash[i] = kEmptyHashValue; ++ p->cyclicBufferPos = 0; ++ p->buffer = p->bufferBase; ++ p->pos = p->streamPos = p->cyclicBufferSize; ++ p->result = SZ_OK; ++ p->streamEndWasReached = 0; ++ MatchFinder_ReadBlock(p); ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) ++{ ++ return (p->pos - p->historySize - 1) & kNormalizeMask; ++} ++ ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++{ ++ UInt32 i; ++ for (i = 0; i < numItems; i++) ++ { ++ UInt32 value = items[i]; ++ if (value <= subValue) ++ value = kEmptyHashValue; ++ else ++ value -= subValue; ++ items[i] = value; ++ } ++} ++ ++static void MatchFinder_Normalize(CMatchFinder *p) ++{ ++ UInt32 subValue = MatchFinder_GetSubValue(p); ++ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); ++ MatchFinder_ReduceOffsets(p, subValue); ++} ++ ++static void MatchFinder_CheckLimits(CMatchFinder *p) ++{ ++ if (p->pos == kMaxValForNormalize) ++ MatchFinder_Normalize(p); ++ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) ++ MatchFinder_CheckAndMoveAndRead(p); ++ if (p->cyclicBufferPos == p->cyclicBufferSize) ++ p->cyclicBufferPos = 0; ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ son[_cyclicBufferPos] = curMatch; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ return distances; ++ { ++ const Byte *pb = cur - delta; ++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; ++ if (pb[maxLen] == cur[maxLen] && *pb == *cur) ++ { ++ UInt32 len = 0; ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ return distances; ++ } ++ } ++ } ++ } ++} ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return distances; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ if (++len != lenLimit && pb[len] == cur[len]) ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return distances; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ { ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++#define MOVE_POS \ ++ ++p->cyclicBufferPos; \ ++ p->buffer++; \ ++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); ++ ++#define MOVE_POS_RET MOVE_POS return offset; ++ ++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } ++ ++#define GET_MATCHES_HEADER2(minLen, ret_op) \ ++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ ++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ ++ cur = p->buffer; ++ ++#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) ++#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) ++ ++#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue ++ ++#define GET_MATCHES_FOOTER(offset, maxLen) \ ++ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ ++ distances + offset, maxLen) - distances); MOVE_POS_RET; ++ ++#define SKIP_FOOTER \ ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; ++ ++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 1) ++} ++ ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 2) ++} ++ ++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, delta2, maxLen, offset; ++ GET_MATCHES_HEADER(3) ++ ++ HASH3_CALC; ++ ++ delta2 = p->pos - p->hash[hash2Value]; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ ++ ++ maxLen = 2; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[0] = maxLen; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances + offset, maxLen) - (distances)); ++ MOVE_POS_RET ++} ++ ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances, 2) - (distances)); ++ MOVE_POS_RET ++} ++ ++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value; ++ SKIP_HEADER(3) ++ HASH3_CALC; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = p->pos; ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) ++{ ++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; ++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; ++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; ++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; ++ if (!p->btMode) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 2) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 3) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; ++ } ++ else ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++ } ++} +--- /dev/null ++++ b/lib/lzma/LzmaDec.c +@@ -0,0 +1,999 @@ ++/* LzmaDec.c -- LZMA Decoder ++2009-09-20 : Igor Pavlov : Public domain */ ++ ++#include "LzmaDec.h" ++ ++#include ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++ ++#define RC_INIT_SIZE 5 ++ ++#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); ++#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); ++#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ ++ { UPDATE_0(p); i = (i + i); A0; } else \ ++ { UPDATE_1(p); i = (i + i) + 1; A1; } ++#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) ++ ++#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } ++#define TREE_DECODE(probs, limit, i) \ ++ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } ++ ++/* #define _LZMA_SIZE_OPT */ ++ ++#ifdef _LZMA_SIZE_OPT ++#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) ++#else ++#define TREE_6_DECODE(probs, i) \ ++ { i = 1; \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ i -= 0x40; } ++#endif ++ ++#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0_CHECK range = bound; ++#define UPDATE_1_CHECK range -= bound; code -= bound; ++#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ ++ { UPDATE_0_CHECK; i = (i + i); A0; } else \ ++ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } ++#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) ++#define TREE_DECODE_CHECK(probs, limit, i) \ ++ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } ++ ++ ++#define kNumPosBitsMax 4 ++#define kNumPosStatesMax (1 << kNumPosBitsMax) ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define LenChoice 0 ++#define LenChoice2 (LenChoice + 1) ++#define LenLow (LenChoice2 + 1) ++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) ++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) ++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) ++ ++ ++#define kNumStates 12 ++#define kNumLitStates 7 ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#define kNumPosSlotBits 6 ++#define kNumLenToPosStates 4 ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++ ++#define kMatchMinLen 2 ++#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define IsMatch 0 ++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) ++#define IsRepG0 (IsRep + kNumStates) ++#define IsRepG1 (IsRepG0 + kNumStates) ++#define IsRepG2 (IsRepG1 + kNumStates) ++#define IsRep0Long (IsRepG2 + kNumStates) ++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) ++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) ++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) ++#define LenCoder (Align + kAlignTableSize) ++#define RepLenCoder (LenCoder + kNumLenProbs) ++#define Literal (RepLenCoder + kNumLenProbs) ++ ++#define LZMA_BASE_SIZE 1846 ++#define LZMA_LIT_SIZE 768 ++ ++#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) ++ ++#if Literal != LZMA_BASE_SIZE ++StopCompilingDueBUG ++#endif ++ ++#define LZMA_DIC_MIN (1 << 12) ++ ++/* First LZMA-symbol is always decoded. ++And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization ++Out: ++ Result: ++ SZ_OK - OK ++ SZ_ERROR_DATA - Error ++ p->remainLen: ++ < kMatchSpecLenStart : normal remain ++ = kMatchSpecLenStart : finished ++ = kMatchSpecLenStart + 1 : Flush marker ++ = kMatchSpecLenStart + 2 : State Init Marker ++*/ ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ CLzmaProb *probs = p->probs; ++ ++ unsigned state = p->state; ++ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; ++ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; ++ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; ++ unsigned lc = p->prop.lc; ++ ++ Byte *dic = p->dic; ++ SizeT dicBufSize = p->dicBufSize; ++ SizeT dicPos = p->dicPos; ++ ++ UInt32 processedPos = p->processedPos; ++ UInt32 checkDicSize = p->checkDicSize; ++ unsigned len = 0; ++ ++ const Byte *buf = p->buf; ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ ++ do ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = processedPos & pbMask; ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ unsigned symbol; ++ UPDATE_0(prob); ++ prob = probs + Literal; ++ if (checkDicSize != 0 || processedPos != 0) ++ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + ++ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ state -= (state < 4) ? state : 3; ++ symbol = 1; ++ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ state -= (state < 10) ? 3 : 6; ++ symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ dic[dicPos++] = (Byte)symbol; ++ processedPos++; ++ continue; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRep + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ state += kNumStates; ++ prob = probs + LenCoder; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ if (checkDicSize == 0 && processedPos == 0) ++ return SZ_ERROR_DATA; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ processedPos++; ++ state = state < kNumLitStates ? 9 : 11; ++ continue; ++ } ++ UPDATE_1(prob); ++ } ++ else ++ { ++ UInt32 distance; ++ UPDATE_1(prob); ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep1; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep2; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ distance = rep3; ++ rep3 = rep2; ++ } ++ rep2 = rep1; ++ } ++ rep1 = rep0; ++ rep0 = distance; ++ } ++ state = state < kNumLitStates ? 8 : 11; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = (1 << kLenNumLowBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenChoice2; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = (1 << kLenNumMidBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = (1 << kLenNumHighBits); ++ } ++ } ++ TREE_DECODE(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state >= kNumStates) ++ { ++ UInt32 distance; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); ++ TREE_6_DECODE(prob, distance); ++ if (distance >= kStartPosModelIndex) ++ { ++ unsigned posSlot = (unsigned)distance; ++ int numDirectBits = (int)(((distance >> 1) - 1)); ++ distance = (2 | (distance & 1)); ++ if (posSlot < kEndPosModelIndex) ++ { ++ distance <<= numDirectBits; ++ prob = probs + SpecPos + distance - posSlot - 1; ++ { ++ UInt32 mask = 1; ++ unsigned i = 1; ++ do ++ { ++ GET_BIT2(prob + i, i, ; , distance |= mask); ++ mask <<= 1; ++ } ++ while (--numDirectBits != 0); ++ } ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE ++ range >>= 1; ++ ++ { ++ UInt32 t; ++ code -= range; ++ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ ++ distance = (distance << 1) + (t + 1); ++ code += range & t; ++ } ++ /* ++ distance <<= 1; ++ if (code >= range) ++ { ++ code -= range; ++ distance |= 1; ++ } ++ */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ distance <<= kNumAlignBits; ++ { ++ unsigned i = 1; ++ GET_BIT2(prob + i, i, ; , distance |= 1); ++ GET_BIT2(prob + i, i, ; , distance |= 2); ++ GET_BIT2(prob + i, i, ; , distance |= 4); ++ GET_BIT2(prob + i, i, ; , distance |= 8); ++ } ++ if (distance == (UInt32)0xFFFFFFFF) ++ { ++ len += kMatchSpecLenStart; ++ state -= kNumStates; ++ break; ++ } ++ } ++ } ++ rep3 = rep2; ++ rep2 = rep1; ++ rep1 = rep0; ++ rep0 = distance + 1; ++ if (checkDicSize == 0) ++ { ++ if (distance >= processedPos) ++ return SZ_ERROR_DATA; ++ } ++ else if (distance >= checkDicSize) ++ return SZ_ERROR_DATA; ++ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; ++ } ++ ++ len += kMatchMinLen; ++ ++ if (limit == dicPos) ++ return SZ_ERROR_DATA; ++ { ++ SizeT rem = limit - dicPos; ++ unsigned curLen = ((rem < len) ? (unsigned)rem : len); ++ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); ++ ++ processedPos += curLen; ++ ++ len -= curLen; ++ if (pos + curLen <= dicBufSize) ++ { ++ Byte *dest = dic + dicPos; ++ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; ++ const Byte *lim = dest + curLen; ++ dicPos += curLen; ++ do ++ *(dest) = (Byte)*(dest + src); ++ while (++dest != lim); ++ } ++ else ++ { ++ do ++ { ++ dic[dicPos++] = dic[pos]; ++ if (++pos == dicBufSize) ++ pos = 0; ++ } ++ while (--curLen != 0); ++ } ++ } ++ } ++ } ++ while (dicPos < limit && buf < bufLimit); ++ NORMALIZE; ++ p->buf = buf; ++ p->range = range; ++ p->code = code; ++ p->remainLen = len; ++ p->dicPos = dicPos; ++ p->processedPos = processedPos; ++ p->reps[0] = rep0; ++ p->reps[1] = rep1; ++ p->reps[2] = rep2; ++ p->reps[3] = rep3; ++ p->state = state; ++ ++ return SZ_OK; ++} ++ ++static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) ++{ ++ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) ++ { ++ Byte *dic = p->dic; ++ SizeT dicPos = p->dicPos; ++ SizeT dicBufSize = p->dicBufSize; ++ unsigned len = p->remainLen; ++ UInt32 rep0 = p->reps[0]; ++ if (limit - dicPos < len) ++ len = (unsigned)(limit - dicPos); ++ ++ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) ++ p->checkDicSize = p->prop.dicSize; ++ ++ p->processedPos += len; ++ p->remainLen -= len; ++ while (len-- != 0) ++ { ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ } ++ p->dicPos = dicPos; ++ } ++} ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ do ++ { ++ SizeT limit2 = limit; ++ if (p->checkDicSize == 0) ++ { ++ UInt32 rem = p->prop.dicSize - p->processedPos; ++ if (limit - p->dicPos > rem) ++ limit2 = p->dicPos + rem; ++ } ++ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); ++ if (p->processedPos >= p->prop.dicSize) ++ p->checkDicSize = p->prop.dicSize; ++ LzmaDec_WriteRem(p, limit); ++ } ++ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); ++ ++ if (p->remainLen > kMatchSpecLenStart) ++ { ++ p->remainLen = kMatchSpecLenStart; ++ } ++ return 0; ++} ++ ++typedef enum ++{ ++ DUMMY_ERROR, /* unexpected end of input stream */ ++ DUMMY_LIT, ++ DUMMY_MATCH, ++ DUMMY_REP ++} ELzmaDummy; ++ ++static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) ++{ ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ const Byte *bufLimit = buf + inSize; ++ CLzmaProb *probs = p->probs; ++ unsigned state = p->state; ++ ELzmaDummy res; ++ ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK ++ ++ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ ++ ++ prob = probs + Literal; ++ if (p->checkDicSize != 0 || p->processedPos != 0) ++ prob += (LZMA_LIT_SIZE * ++ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + ++ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ unsigned symbol = 1; ++ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ++ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ unsigned symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ res = DUMMY_LIT; ++ } ++ else ++ { ++ unsigned len; ++ UPDATE_1_CHECK; ++ ++ prob = probs + IsRep + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ state = 0; ++ prob = probs + LenCoder; ++ res = DUMMY_MATCH; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ res = DUMMY_REP; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ NORMALIZE_CHECK; ++ return DUMMY_REP; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ } ++ state = kNumStates; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = 1 << kLenNumLowBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenChoice2; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = 1 << kLenNumMidBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = 1 << kLenNumHighBits; ++ } ++ } ++ TREE_DECODE_CHECK(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state < 4) ++ { ++ unsigned posSlot; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ++ kNumPosSlotBits); ++ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); ++ if (posSlot >= kStartPosModelIndex) ++ { ++ int numDirectBits = ((posSlot >> 1) - 1); ++ ++ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ ++ ++ if (posSlot < kEndPosModelIndex) ++ { ++ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE_CHECK ++ range >>= 1; ++ code -= range & (((code - range) >> 31) - 1); ++ /* if (code >= range) code -= range; */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ numDirectBits = kNumAlignBits; ++ } ++ { ++ unsigned i = 1; ++ do ++ { ++ GET_BIT_CHECK(prob + i, i); ++ } ++ while (--numDirectBits != 0); ++ } ++ } ++ } ++ } ++ } ++ NORMALIZE_CHECK; ++ return res; ++} ++ ++ ++static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) ++{ ++ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); ++ p->range = 0xFFFFFFFF; ++ p->needFlush = 0; ++} ++ ++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++{ ++ p->needFlush = 1; ++ p->remainLen = 0; ++ p->tempBufSize = 0; ++ ++ if (initDic) ++ { ++ p->processedPos = 0; ++ p->checkDicSize = 0; ++ p->needInitState = 1; ++ } ++ if (initState) ++ p->needInitState = 1; ++} ++ ++void LzmaDec_Init(CLzmaDec *p) ++{ ++ p->dicPos = 0; ++ LzmaDec_InitDicAndState(p, True, True); ++} ++ ++static void LzmaDec_InitStateReal(CLzmaDec *p) ++{ ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); ++ UInt32 i; ++ CLzmaProb *probs = p->probs; ++ for (i = 0; i < numProbs; i++) ++ probs[i] = kBitModelTotal >> 1; ++ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; ++ p->state = 0; ++ p->needInitState = 0; ++} ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++ ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT inSize = *srcLen; ++ (*srcLen) = 0; ++ LzmaDec_WriteRem(p, dicLimit); ++ ++ *status = LZMA_STATUS_NOT_SPECIFIED; ++ ++ while (p->remainLen != kMatchSpecLenStart) ++ { ++ int checkEndMarkNow; ++ ++ if (p->needFlush != 0) ++ { ++ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) ++ p->tempBuf[p->tempBufSize++] = *src++; ++ if (p->tempBufSize < RC_INIT_SIZE) ++ { ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (p->tempBuf[0] != 0) ++ return SZ_ERROR_DATA; ++ ++ LzmaDec_InitRc(p, p->tempBuf); ++ p->tempBufSize = 0; ++ } ++ ++ checkEndMarkNow = 0; ++ if (p->dicPos >= dicLimit) ++ { ++ if (p->remainLen == 0 && p->code == 0) ++ { ++ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; ++ return SZ_OK; ++ } ++ if (finishMode == LZMA_FINISH_ANY) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_OK; ++ } ++ if (p->remainLen != 0) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ checkEndMarkNow = 1; ++ } ++ ++ if (p->needInitState) ++ LzmaDec_InitStateReal(p); ++ ++ if (p->tempBufSize == 0) ++ { ++ SizeT processed; ++ const Byte *bufLimit; ++ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, src, inSize); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ memcpy(p->tempBuf, src, inSize); ++ p->tempBufSize = (unsigned)inSize; ++ (*srcLen) += inSize; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ bufLimit = src; ++ } ++ else ++ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; ++ p->buf = src; ++ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) ++ return SZ_ERROR_DATA; ++ processed = (SizeT)(p->buf - src); ++ (*srcLen) += processed; ++ src += processed; ++ inSize -= processed; ++ } ++ else ++ { ++ unsigned rem = p->tempBufSize, lookAhead = 0; ++ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) ++ p->tempBuf[rem++] = src[lookAhead++]; ++ p->tempBufSize = rem; ++ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ (*srcLen) += lookAhead; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ } ++ p->buf = p->tempBuf; ++ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) ++ return SZ_ERROR_DATA; ++ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); ++ (*srcLen) += lookAhead; ++ src += lookAhead; ++ inSize -= lookAhead; ++ p->tempBufSize = 0; ++ } ++ } ++ if (p->code == 0) ++ *status = LZMA_STATUS_FINISHED_WITH_MARK; ++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; ++} ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT outSize = *destLen; ++ SizeT inSize = *srcLen; ++ *srcLen = *destLen = 0; ++ for (;;) ++ { ++ SizeT inSizeCur = inSize, outSizeCur, dicPos; ++ ELzmaFinishMode curFinishMode; ++ SRes res; ++ if (p->dicPos == p->dicBufSize) ++ p->dicPos = 0; ++ dicPos = p->dicPos; ++ if (outSize > p->dicBufSize - dicPos) ++ { ++ outSizeCur = p->dicBufSize; ++ curFinishMode = LZMA_FINISH_ANY; ++ } ++ else ++ { ++ outSizeCur = dicPos + outSize; ++ curFinishMode = finishMode; ++ } ++ ++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); ++ src += inSizeCur; ++ inSize -= inSizeCur; ++ *srcLen += inSizeCur; ++ outSizeCur = p->dicPos - dicPos; ++ memcpy(dest, p->dic + dicPos, outSizeCur); ++ dest += outSizeCur; ++ outSize -= outSizeCur; ++ *destLen += outSizeCur; ++ if (res != 0) ++ return res; ++ if (outSizeCur == 0 || outSize == 0) ++ return SZ_OK; ++ } ++} ++ ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->probs); ++ p->probs = 0; ++} ++ ++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->dic); ++ p->dic = 0; ++} ++ ++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ LzmaDec_FreeProbs(p, alloc); ++ LzmaDec_FreeDict(p, alloc); ++} ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++{ ++ UInt32 dicSize; ++ Byte d; ++ ++ if (size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_UNSUPPORTED; ++ else ++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); ++ ++ if (dicSize < LZMA_DIC_MIN) ++ dicSize = LZMA_DIC_MIN; ++ p->dicSize = dicSize; ++ ++ d = data[0]; ++ if (d >= (9 * 5 * 5)) ++ return SZ_ERROR_UNSUPPORTED; ++ ++ p->lc = d % 9; ++ d /= 9; ++ p->pb = d / 5; ++ p->lp = d % 5; ++ ++ return SZ_OK; ++} ++ ++static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) ++{ ++ UInt32 numProbs = LzmaProps_GetNumProbs(propNew); ++ if (p->probs == 0 || numProbs != p->numProbs) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); ++ p->numProbs = numProbs; ++ if (p->probs == 0) ++ return SZ_ERROR_MEM; ++ } ++ return SZ_OK; ++} ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ SizeT dicBufSize; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ dicBufSize = propNew.dicSize; ++ if (p->dic == 0 || dicBufSize != p->dicBufSize) ++ { ++ LzmaDec_FreeDict(p, alloc); ++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); ++ if (p->dic == 0) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ } ++ p->dicBufSize = dicBufSize; ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc) ++{ ++ CLzmaDec p; ++ SRes res; ++ SizeT inSize = *srcLen; ++ SizeT outSize = *destLen; ++ *srcLen = *destLen = 0; ++ if (inSize < RC_INIT_SIZE) ++ return SZ_ERROR_INPUT_EOF; ++ ++ LzmaDec_Construct(&p); ++ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); ++ if (res != 0) ++ return res; ++ p.dic = dest; ++ p.dicBufSize = outSize; ++ ++ LzmaDec_Init(&p); ++ ++ *srcLen = inSize; ++ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); ++ ++ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) ++ res = SZ_ERROR_INPUT_EOF; ++ ++ (*destLen) = p.dicPos; ++ LzmaDec_FreeProbs(&p, alloc); ++ return res; ++} +--- /dev/null ++++ b/lib/lzma/LzmaEnc.c +@@ -0,0 +1,2271 @@ ++/* LzmaEnc.c -- LZMA Encoder ++2009-11-24 : Igor Pavlov : Public domain */ ++ ++#include ++ ++/* #define SHOW_STAT */ ++/* #define SHOW_STAT2 */ ++ ++#if defined(SHOW_STAT) || defined(SHOW_STAT2) ++#include ++#endif ++ ++#include "LzmaEnc.h" ++ ++/* disable MT */ ++#define _7ZIP_ST ++ ++#include "LzFind.h" ++#ifndef _7ZIP_ST ++#include "LzFindMt.h" ++#endif ++ ++#ifdef SHOW_STAT ++static int ttt = 0; ++#endif ++ ++#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) ++ ++#define kBlockSize (9 << 10) ++#define kUnpackBlockSize (1 << 18) ++#define kMatchArraySize (1 << 21) ++#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) ++ ++#define kNumMaxDirectBits (31) ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++#define kProbInitValue (kBitModelTotal >> 1) ++ ++#define kNumMoveReducingBits 4 ++#define kNumBitPriceShiftBits 4 ++#define kBitPrice (1 << kNumBitPriceShiftBits) ++ ++void LzmaEncProps_Init(CLzmaEncProps *p) ++{ ++ p->level = 5; ++ p->dictSize = p->mc = 0; ++ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; ++ p->writeEndMark = 0; ++} ++ ++void LzmaEncProps_Normalize(CLzmaEncProps *p) ++{ ++ int level = p->level; ++ if (level < 0) level = 5; ++ p->level = level; ++ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); ++ if (p->lc < 0) p->lc = 3; ++ if (p->lp < 0) p->lp = 0; ++ if (p->pb < 0) p->pb = 2; ++ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); ++ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); ++ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); ++ if (p->numHashBytes < 0) p->numHashBytes = 4; ++ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); ++ if (p->numThreads < 0) ++ p->numThreads = ++ #ifndef _7ZIP_ST ++ ((p->btMode && p->algo) ? 2 : 1); ++ #else ++ 1; ++ #endif ++} ++ ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++{ ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ return props.dictSize; ++} ++ ++/* #define LZMA_LOG_BSR */ ++/* Define it for Intel's CPU */ ++ ++ ++#ifdef LZMA_LOG_BSR ++ ++#define kDicLogSizeMaxCompress 30 ++ ++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } ++ ++UInt32 GetPosSlot1(UInt32 pos) ++{ ++ UInt32 res; ++ BSR2_RET(pos, res); ++ return res; ++} ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } ++ ++#else ++ ++#define kNumLogBits (9 + (int)sizeof(size_t) / 2) ++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) ++ ++void LzmaEnc_FastPosInit(Byte *g_FastPos) ++{ ++ int c = 2, slotFast; ++ g_FastPos[0] = 0; ++ g_FastPos[1] = 1; ++ ++ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) ++ { ++ UInt32 k = (1 << ((slotFast >> 1) - 1)); ++ UInt32 j; ++ for (j = 0; j < k; j++, c++) ++ g_FastPos[c] = (Byte)slotFast; ++ } ++} ++ ++#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ ++ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ ++ res = p->g_FastPos[pos >> i] + (i * 2); } ++/* ++#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ ++ p->g_FastPos[pos >> 6] + 12 : \ ++ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } ++*/ ++ ++#define GetPosSlot1(pos) p->g_FastPos[pos] ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } ++ ++#endif ++ ++ ++#define LZMA_NUM_REPS 4 ++ ++typedef unsigned CState; ++ ++typedef struct ++{ ++ UInt32 price; ++ ++ CState state; ++ int prev1IsChar; ++ int prev2; ++ ++ UInt32 posPrev2; ++ UInt32 backPrev2; ++ ++ UInt32 posPrev; ++ UInt32 backPrev; ++ UInt32 backs[LZMA_NUM_REPS]; ++} COptimal; ++ ++#define kNumOpts (1 << 12) ++ ++#define kNumLenToPosStates 4 ++#define kNumPosSlotBits 6 ++#define kDicLogSizeMin 0 ++#define kDicLogSizeMax 32 ++#define kDistTableSizeMax (kDicLogSizeMax * 2) ++ ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++#define kAlignMask (kAlignTableSize - 1) ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) ++ ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++#define LZMA_PB_MAX 4 ++#define LZMA_LC_MAX 8 ++#define LZMA_LP_MAX 4 ++ ++#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) ++ ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define LZMA_MATCH_LEN_MIN 2 ++#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) ++ ++#define kNumStates 12 ++ ++typedef struct ++{ ++ CLzmaProb choice; ++ CLzmaProb choice2; ++ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; ++ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; ++ CLzmaProb high[kLenNumHighSymbols]; ++} CLenEnc; ++ ++typedef struct ++{ ++ CLenEnc p; ++ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; ++ UInt32 tableSize; ++ UInt32 counters[LZMA_NUM_PB_STATES_MAX]; ++} CLenPriceEnc; ++ ++typedef struct ++{ ++ UInt32 range; ++ Byte cache; ++ UInt64 low; ++ UInt64 cacheSize; ++ Byte *buf; ++ Byte *bufLim; ++ Byte *bufBase; ++ ISeqOutStream *outStream; ++ UInt64 processed; ++ SRes res; ++} CRangeEnc; ++ ++typedef struct ++{ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++} CSaveState; ++ ++typedef struct ++{ ++ IMatchFinder matchFinder; ++ void *matchFinderObj; ++ ++ #ifndef _7ZIP_ST ++ Bool mtMode; ++ CMatchFinderMt matchFinderMt; ++ #endif ++ ++ CMatchFinder matchFinderBase; ++ ++ #ifndef _7ZIP_ST ++ Byte pad[128]; ++ #endif ++ ++ UInt32 optimumEndIndex; ++ UInt32 optimumCurrentIndex; ++ ++ UInt32 longestMatchLength; ++ UInt32 numPairs; ++ UInt32 numAvail; ++ COptimal opt[kNumOpts]; ++ ++ #ifndef LZMA_LOG_BSR ++ Byte g_FastPos[1 << kNumLogBits]; ++ #endif ++ ++ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; ++ UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; ++ UInt32 numFastBytes; ++ UInt32 additionalOffset; ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++ ++ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; ++ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; ++ UInt32 alignPrices[kAlignTableSize]; ++ UInt32 alignPriceCount; ++ ++ UInt32 distTableSize; ++ ++ unsigned lc, lp, pb; ++ unsigned lpMask, pbMask; ++ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ unsigned lclp; ++ ++ Bool fastMode; ++ ++ CRangeEnc rc; ++ ++ Bool writeEndMark; ++ UInt64 nowPos64; ++ UInt32 matchPriceCount; ++ Bool finished; ++ Bool multiThread; ++ ++ SRes result; ++ UInt32 dictSize; ++ UInt32 matchFinderCycles; ++ ++ int needInit; ++ ++ CSaveState saveState; ++} CLzmaEnc; ++ ++void LzmaEnc_SaveState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CSaveState *dest = &p->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); ++} ++ ++void LzmaEnc_RestoreState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *dest = (CLzmaEnc *)pp; ++ const CSaveState *p = &dest->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); ++} ++ ++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ ++ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || ++ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) ++ return SZ_ERROR_PARAM; ++ p->dictSize = props.dictSize; ++ p->matchFinderCycles = props.mc; ++ { ++ unsigned fb = props.fb; ++ if (fb < 5) ++ fb = 5; ++ if (fb > LZMA_MATCH_LEN_MAX) ++ fb = LZMA_MATCH_LEN_MAX; ++ p->numFastBytes = fb; ++ } ++ p->lc = props.lc; ++ p->lp = props.lp; ++ p->pb = props.pb; ++ p->fastMode = (props.algo == 0); ++ p->matchFinderBase.btMode = props.btMode; ++ { ++ UInt32 numHashBytes = 4; ++ if (props.btMode) ++ { ++ if (props.numHashBytes < 2) ++ numHashBytes = 2; ++ else if (props.numHashBytes < 4) ++ numHashBytes = props.numHashBytes; ++ } ++ p->matchFinderBase.numHashBytes = numHashBytes; ++ } ++ ++ p->matchFinderBase.cutValue = props.mc; ++ ++ p->writeEndMark = props.writeEndMark; ++ ++ #ifndef _7ZIP_ST ++ /* ++ if (newMultiThread != _multiThread) ++ { ++ ReleaseMatchFinder(); ++ _multiThread = newMultiThread; ++ } ++ */ ++ p->multiThread = (props.numThreads > 1); ++ #endif ++ ++ return SZ_OK; ++} ++ ++static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; ++static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; ++static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; ++static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; ++ ++#define IsCharState(s) ((s) < 7) ++ ++#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) ++ ++#define kInfinityPrice (1 << 30) ++ ++static void RangeEnc_Construct(CRangeEnc *p) ++{ ++ p->outStream = 0; ++ p->bufBase = 0; ++} ++ ++#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) ++ ++#define RC_BUF_SIZE (1 << 16) ++static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ if (p->bufBase == 0) ++ { ++ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); ++ if (p->bufBase == 0) ++ return 0; ++ p->bufLim = p->bufBase + RC_BUF_SIZE; ++ } ++ return 1; ++} ++ ++static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->bufBase); ++ p->bufBase = 0; ++} ++ ++static void RangeEnc_Init(CRangeEnc *p) ++{ ++ /* Stream.Init(); */ ++ p->low = 0; ++ p->range = 0xFFFFFFFF; ++ p->cacheSize = 1; ++ p->cache = 0; ++ ++ p->buf = p->bufBase; ++ ++ p->processed = 0; ++ p->res = SZ_OK; ++} ++ ++static void RangeEnc_FlushStream(CRangeEnc *p) ++{ ++ size_t num; ++ if (p->res != SZ_OK) ++ return; ++ num = p->buf - p->bufBase; ++ if (num != p->outStream->Write(p->outStream, p->bufBase, num)) ++ p->res = SZ_ERROR_WRITE; ++ p->processed += num; ++ p->buf = p->bufBase; ++} ++ ++static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) ++{ ++ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) ++ { ++ Byte temp = p->cache; ++ do ++ { ++ Byte *buf = p->buf; ++ *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); ++ p->buf = buf; ++ if (buf == p->bufLim) ++ RangeEnc_FlushStream(p); ++ temp = 0xFF; ++ } ++ while (--p->cacheSize != 0); ++ p->cache = (Byte)((UInt32)p->low >> 24); ++ } ++ p->cacheSize++; ++ p->low = (UInt32)p->low << 8; ++} ++ ++static void RangeEnc_FlushData(CRangeEnc *p) ++{ ++ int i; ++ for (i = 0; i < 5; i++) ++ RangeEnc_ShiftLow(p); ++} ++ ++static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) ++{ ++ do ++ { ++ p->range >>= 1; ++ p->low += p->range & (0 - ((value >> --numBits) & 1)); ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++ } ++ while (numBits != 0); ++} ++ ++static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) ++{ ++ UInt32 ttt = *prob; ++ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; ++ if (symbol == 0) ++ { ++ p->range = newBound; ++ ttt += (kBitModelTotal - ttt) >> kNumMoveBits; ++ } ++ else ++ { ++ p->low += newBound; ++ p->range -= newBound; ++ ttt -= ttt >> kNumMoveBits; ++ } ++ *prob = (CLzmaProb)ttt; ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++} ++ ++static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) ++{ ++ symbol |= 0x100; ++ do ++ { ++ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++} ++ ++static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) ++{ ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++} ++ ++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++{ ++ UInt32 i; ++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) ++ { ++ const int kCyclesBits = kNumBitPriceShiftBits; ++ UInt32 w = i; ++ UInt32 bitCount = 0; ++ int j; ++ for (j = 0; j < kCyclesBits; j++) ++ { ++ w = w * w; ++ bitCount <<= 1; ++ while (w >= ((UInt32)1 << 16)) ++ { ++ w >>= 1; ++ bitCount++; ++ } ++ } ++ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); ++ } ++} ++ ++ ++#define GET_PRICE(prob, symbol) \ ++ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICEa(prob, symbol) \ ++ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= 0x100; ++ do ++ { ++ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++ return price; ++} ++ ++static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++ return price; ++} ++ ++ ++static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0;) ++ { ++ UInt32 bit; ++ i--; ++ bit = (symbol >> i) & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ } ++} ++ ++static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = 0; i < numBitLevels; i++) ++ { ++ UInt32 bit = symbol & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ symbol >>= 1; ++ } ++} ++ ++static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= (1 << numBitLevels); ++ while (symbol != 1) ++ { ++ price += GET_PRICEa(probs[symbol >> 1], symbol & 1); ++ symbol >>= 1; ++ } ++ return price; ++} ++ ++static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0; i--) ++ { ++ UInt32 bit = symbol & 1; ++ symbol >>= 1; ++ price += GET_PRICEa(probs[m], bit); ++ m = (m << 1) | bit; ++ } ++ return price; ++} ++ ++ ++static void LenEnc_Init(CLenEnc *p) ++{ ++ unsigned i; ++ p->choice = p->choice2 = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) ++ p->low[i] = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) ++ p->mid[i] = kProbInitValue; ++ for (i = 0; i < kLenNumHighSymbols; i++) ++ p->high[i] = kProbInitValue; ++} ++ ++static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) ++{ ++ if (symbol < kLenNumLowSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 0); ++ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 1); ++ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 0); ++ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 1); ++ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); ++ } ++ } ++} ++ ++static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) ++{ ++ UInt32 a0 = GET_PRICE_0a(p->choice); ++ UInt32 a1 = GET_PRICE_1a(p->choice); ++ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); ++ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); ++ UInt32 i = 0; ++ for (i = 0; i < kLenNumLowSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); ++ } ++ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); ++ } ++ for (; i < numSymbols; i++) ++ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); ++} ++ ++static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) ++{ ++ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); ++ p->counters[posState] = p->tableSize; ++} ++ ++static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) ++{ ++ UInt32 posState; ++ for (posState = 0; posState < numPosStates; posState++) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) ++{ ++ LenEnc_Encode(&p->p, rc, symbol, posState); ++ if (updatePrice) ++ if (--p->counters[posState] == 0) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++ ++ ++ ++static void MovePos(CLzmaEnc *p, UInt32 num) ++{ ++ #ifdef SHOW_STAT ++ ttt += num; ++ printf("\n MovePos %d", num); ++ #endif ++ if (num != 0) ++ { ++ p->additionalOffset += num; ++ p->matchFinder.Skip(p->matchFinderObj, num); ++ } ++} ++ ++static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) ++{ ++ UInt32 lenRes = 0, numPairs; ++ p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); ++ #ifdef SHOW_STAT ++ printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ++ ttt++; ++ { ++ UInt32 i; ++ for (i = 0; i < numPairs; i += 2) ++ printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); ++ } ++ #endif ++ if (numPairs > 0) ++ { ++ lenRes = p->matches[numPairs - 2]; ++ if (lenRes == p->numFastBytes) ++ { ++ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ UInt32 distance = p->matches[numPairs - 1] + 1; ++ UInt32 numAvail = p->numAvail; ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ { ++ const Byte *pby2 = pby - distance; ++ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); ++ } ++ } ++ } ++ p->additionalOffset++; ++ *numDistancePairsRes = numPairs; ++ return lenRes; ++} ++ ++ ++#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; ++#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; ++#define IsShortRep(p) ((p)->backPrev == 0) ++ ++static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) ++{ ++ return ++ GET_PRICE_0(p->isRepG0[state]) + ++ GET_PRICE_0(p->isRep0Long[state][posState]); ++} ++ ++static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) ++{ ++ UInt32 price; ++ if (repIndex == 0) ++ { ++ price = GET_PRICE_0(p->isRepG0[state]); ++ price += GET_PRICE_1(p->isRep0Long[state][posState]); ++ } ++ else ++ { ++ price = GET_PRICE_1(p->isRepG0[state]); ++ if (repIndex == 1) ++ price += GET_PRICE_0(p->isRepG1[state]); ++ else ++ { ++ price += GET_PRICE_1(p->isRepG1[state]); ++ price += GET_PRICE(p->isRepG2[state], repIndex - 2); ++ } ++ } ++ return price; ++} ++ ++static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) ++{ ++ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + ++ GetPureRepPrice(p, repIndex, state, posState); ++} ++ ++static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) ++{ ++ UInt32 posMem = p->opt[cur].posPrev; ++ UInt32 backMem = p->opt[cur].backPrev; ++ p->optimumEndIndex = cur; ++ do ++ { ++ if (p->opt[cur].prev1IsChar) ++ { ++ MakeAsChar(&p->opt[posMem]) ++ p->opt[posMem].posPrev = posMem - 1; ++ if (p->opt[cur].prev2) ++ { ++ p->opt[posMem - 1].prev1IsChar = False; ++ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; ++ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; ++ } ++ } ++ { ++ UInt32 posPrev = posMem; ++ UInt32 backCur = backMem; ++ ++ backMem = p->opt[posPrev].backPrev; ++ posMem = p->opt[posPrev].posPrev; ++ ++ p->opt[posPrev].backPrev = backCur; ++ p->opt[posPrev].posPrev = cur; ++ cur = posPrev; ++ } ++ } ++ while (cur != 0); ++ *backRes = p->opt[0].backPrev; ++ p->optimumCurrentIndex = p->opt[0].posPrev; ++ return p->optimumCurrentIndex; ++} ++ ++#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) ++ ++static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) ++{ ++ UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; ++ UInt32 matchPrice, repMatchPrice, normalMatchPrice; ++ UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; ++ UInt32 *matches; ++ const Byte *data; ++ Byte curByte, matchByte; ++ if (p->optimumEndIndex != p->optimumCurrentIndex) ++ { ++ const COptimal *opt = &p->opt[p->optimumCurrentIndex]; ++ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; ++ *backRes = opt->backPrev; ++ p->optimumCurrentIndex = opt->posPrev; ++ return lenRes; ++ } ++ p->optimumCurrentIndex = p->optimumEndIndex = 0; ++ ++ if (p->additionalOffset == 0) ++ mainLen = ReadMatchDistances(p, &numPairs); ++ else ++ { ++ mainLen = p->longestMatchLength; ++ numPairs = p->numPairs; ++ } ++ ++ numAvail = p->numAvail; ++ if (numAvail < 2) ++ { ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ repMaxIndex = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 lenTest; ++ const Byte *data2; ++ reps[i] = p->reps[i]; ++ data2 = data - (reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ { ++ repLens[i] = 0; ++ continue; ++ } ++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); ++ repLens[i] = lenTest; ++ if (lenTest > repLens[repMaxIndex]) ++ repMaxIndex = i; ++ } ++ if (repLens[repMaxIndex] >= p->numFastBytes) ++ { ++ UInt32 lenRes; ++ *backRes = repMaxIndex; ++ lenRes = repLens[repMaxIndex]; ++ MovePos(p, lenRes - 1); ++ return lenRes; ++ } ++ ++ matches = p->matches; ++ if (mainLen >= p->numFastBytes) ++ { ++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 1); ++ return mainLen; ++ } ++ curByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) ++ { ++ *backRes = (UInt32)-1; ++ return 1; ++ } ++ ++ p->opt[0].state = (CState)p->state; ++ ++ posState = (position & p->pbMask); ++ ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + ++ (!IsCharState(p->state) ? ++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); ++ } ++ ++ MakeAsChar(&p->opt[1]); ++ ++ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); ++ ++ if (matchByte == curByte) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); ++ if (shortRepPrice < p->opt[1].price) ++ { ++ p->opt[1].price = shortRepPrice; ++ MakeAsShortRep(&p->opt[1]); ++ } ++ } ++ lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); ++ ++ if (lenEnd < 2) ++ { ++ *backRes = p->opt[1].backPrev; ++ return 1; ++ } ++ ++ p->opt[1].posPrev = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ p->opt[0].backs[i] = reps[i]; ++ ++ len = lenEnd; ++ do ++ p->opt[len--].price = kInfinityPrice; ++ while (len >= 2); ++ ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 repLen = repLens[i]; ++ UInt32 price; ++ if (repLen < 2) ++ continue; ++ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; ++ COptimal *opt = &p->opt[repLen]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = i; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--repLen >= 2); ++ } ++ ++ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); ++ ++ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); ++ if (len <= mainLen) ++ { ++ UInt32 offs = 0; ++ while (len > matches[offs]) ++ offs += 2; ++ for (; ; len++) ++ { ++ COptimal *opt; ++ UInt32 distance = matches[offs + 1]; ++ ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(len); ++ if (distance < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][distance]; ++ else ++ { ++ UInt32 slot; ++ GetPosSlot2(distance, slot); ++ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; ++ } ++ opt = &p->opt[len]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = distance + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ if (len == matches[offs]) ++ { ++ offs += 2; ++ if (offs == numPairs) ++ break; ++ } ++ } ++ } ++ ++ cur = 0; ++ ++ #ifdef SHOW_STAT2 ++ if (position >= 0) ++ { ++ unsigned i; ++ printf("\n pos = %4X", position); ++ for (i = cur; i <= lenEnd; i++) ++ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); ++ } ++ #endif ++ ++ for (;;) ++ { ++ UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; ++ UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; ++ Bool nextIsChar; ++ Byte curByte, matchByte; ++ const Byte *data; ++ COptimal *curOpt; ++ COptimal *nextOpt; ++ ++ cur++; ++ if (cur == lenEnd) ++ return Backward(p, backRes, cur); ++ ++ newLen = ReadMatchDistances(p, &numPairs); ++ if (newLen >= p->numFastBytes) ++ { ++ p->numPairs = numPairs; ++ p->longestMatchLength = newLen; ++ return Backward(p, backRes, cur); ++ } ++ position++; ++ curOpt = &p->opt[cur]; ++ posPrev = curOpt->posPrev; ++ if (curOpt->prev1IsChar) ++ { ++ posPrev--; ++ if (curOpt->prev2) ++ { ++ state = p->opt[curOpt->posPrev2].state; ++ if (curOpt->backPrev2 < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ state = kLiteralNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ if (posPrev == cur - 1) ++ { ++ if (IsShortRep(curOpt)) ++ state = kShortRepNextStates[state]; ++ else ++ state = kLiteralNextStates[state]; ++ } ++ else ++ { ++ UInt32 pos; ++ const COptimal *prevOpt; ++ if (curOpt->prev1IsChar && curOpt->prev2) ++ { ++ posPrev = curOpt->posPrev2; ++ pos = curOpt->backPrev2; ++ state = kRepNextStates[state]; ++ } ++ else ++ { ++ pos = curOpt->backPrev; ++ if (pos < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ prevOpt = &p->opt[posPrev]; ++ if (pos < LZMA_NUM_REPS) ++ { ++ UInt32 i; ++ reps[0] = prevOpt->backs[pos]; ++ for (i = 1; i <= pos; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ for (; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i]; ++ } ++ else ++ { ++ UInt32 i; ++ reps[0] = (pos - LZMA_NUM_REPS); ++ for (i = 1; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ } ++ } ++ curOpt->state = (CState)state; ++ ++ curOpt->backs[0] = reps[0]; ++ curOpt->backs[1] = reps[1]; ++ curOpt->backs[2] = reps[2]; ++ curOpt->backs[3] = reps[3]; ++ ++ curPrice = curOpt->price; ++ nextIsChar = False; ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ curByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ posState = (position & p->pbMask); ++ ++ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ curAnd1Price += ++ (!IsCharState(state) ? ++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); ++ } ++ ++ nextOpt = &p->opt[cur + 1]; ++ ++ if (curAnd1Price < nextOpt->price) ++ { ++ nextOpt->price = curAnd1Price; ++ nextOpt->posPrev = cur; ++ MakeAsChar(nextOpt); ++ nextIsChar = True; ++ } ++ ++ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); ++ ++ if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); ++ if (shortRepPrice <= nextOpt->price) ++ { ++ nextOpt->price = shortRepPrice; ++ nextOpt->posPrev = cur; ++ MakeAsShortRep(nextOpt); ++ nextIsChar = True; ++ } ++ } ++ numAvailFull = p->numAvail; ++ { ++ UInt32 temp = kNumOpts - 1 - cur; ++ if (temp < numAvailFull) ++ numAvailFull = temp; ++ } ++ ++ if (numAvailFull < 2) ++ continue; ++ numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); ++ ++ if (!nextIsChar && matchByte != curByte) /* speed optimization */ ++ { ++ /* try Literal + rep0 */ ++ UInt32 temp; ++ UInt32 lenTest2; ++ const Byte *data2 = data - (reps[0] + 1); ++ UInt32 limit = p->numFastBytes + 1; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ ++ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); ++ lenTest2 = temp - 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kLiteralNextStates[state]; ++ UInt32 posStateNext = (position + 1) & p->pbMask; ++ UInt32 nextRepMatchPrice = curAnd1Price + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = False; ++ } ++ } ++ } ++ } ++ ++ startLen = 2; /* speed optimization */ ++ { ++ UInt32 repIndex; ++ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) ++ { ++ UInt32 lenTest; ++ UInt32 lenTestTemp; ++ UInt32 price; ++ const Byte *data2 = data - (reps[repIndex] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); ++ while (lenEnd < cur + lenTest) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ lenTestTemp = lenTest; ++ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; ++ COptimal *opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = repIndex; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--lenTest >= 2); ++ lenTest = lenTestTemp; ++ ++ if (repIndex == 0) ++ startLen = lenTest + 1; ++ ++ /* if (_maxMode) */ ++ { ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kRepNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = ++ price + p->repLenEnc.prices[posState][lenTest - 2] + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (position + lenTest + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = repIndex; ++ } ++ } ++ } ++ } ++ } ++ } ++ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ ++ if (newLen > numAvail) ++ { ++ newLen = numAvail; ++ for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); ++ matches[numPairs] = newLen; ++ numPairs += 2; ++ } ++ if (newLen >= startLen) ++ { ++ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); ++ UInt32 offs, curBack, posSlot; ++ UInt32 lenTest; ++ while (lenEnd < cur + newLen) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ ++ offs = 0; ++ while (startLen > matches[offs]) ++ offs += 2; ++ curBack = matches[offs + 1]; ++ GetPosSlot2(curBack, posSlot); ++ for (lenTest = /*2*/ startLen; ; lenTest++) ++ { ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(lenTest); ++ COptimal *opt; ++ if (curBack < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; ++ else ++ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; ++ ++ opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = curBack + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ ++ if (/*_maxMode && */lenTest == matches[offs]) ++ { ++ /* Try Match + Literal + Rep0 */ ++ const Byte *data2 = data - (curBack + 1); ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kMatchNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = curAndLenPrice + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (posStateNext + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = curBack + LZMA_NUM_REPS; ++ } ++ } ++ } ++ offs += 2; ++ if (offs == numPairs) ++ break; ++ curBack = matches[offs + 1]; ++ if (curBack >= kNumFullDistances) ++ GetPosSlot2(curBack, posSlot); ++ } ++ } ++ } ++ } ++} ++ ++#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) ++ ++static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) ++{ ++ UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; ++ const Byte *data; ++ const UInt32 *matches; ++ ++ if (p->additionalOffset == 0) ++ mainLen = ReadMatchDistances(p, &numPairs); ++ else ++ { ++ mainLen = p->longestMatchLength; ++ numPairs = p->numPairs; ++ } ++ ++ numAvail = p->numAvail; ++ *backRes = (UInt32)-1; ++ if (numAvail < 2) ++ return 1; ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ ++ repLen = repIndex = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 len; ++ const Byte *data2 = data - (p->reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ for (len = 2; len < numAvail && data[len] == data2[len]; len++); ++ if (len >= p->numFastBytes) ++ { ++ *backRes = i; ++ MovePos(p, len - 1); ++ return len; ++ } ++ if (len > repLen) ++ { ++ repIndex = i; ++ repLen = len; ++ } ++ } ++ ++ matches = p->matches; ++ if (mainLen >= p->numFastBytes) ++ { ++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 1); ++ return mainLen; ++ } ++ ++ mainDist = 0; /* for GCC */ ++ if (mainLen >= 2) ++ { ++ mainDist = matches[numPairs - 1]; ++ while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) ++ { ++ if (!ChangePair(matches[numPairs - 3], mainDist)) ++ break; ++ numPairs -= 2; ++ mainLen = matches[numPairs - 2]; ++ mainDist = matches[numPairs - 1]; ++ } ++ if (mainLen == 2 && mainDist >= 0x80) ++ mainLen = 1; ++ } ++ ++ if (repLen >= 2 && ( ++ (repLen + 1 >= mainLen) || ++ (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || ++ (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) ++ { ++ *backRes = repIndex; ++ MovePos(p, repLen - 1); ++ return repLen; ++ } ++ ++ if (mainLen < 2 || numAvail <= 2) ++ return 1; ++ ++ p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); ++ if (p->longestMatchLength >= 2) ++ { ++ UInt32 newDistance = matches[p->numPairs - 1]; ++ if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || ++ (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || ++ (p->longestMatchLength > mainLen + 1) || ++ (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) ++ return 1; ++ } ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 len, limit; ++ const Byte *data2 = data - (p->reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ limit = mainLen - 1; ++ for (len = 2; len < limit && data[len] == data2[len]; len++); ++ if (len >= limit) ++ return 1; ++ } ++ *backRes = mainDist + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 2); ++ return mainLen; ++} ++ ++static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) ++{ ++ UInt32 len; ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ len = LZMA_MATCH_LEN_MIN; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); ++ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); ++} ++ ++static SRes CheckErrors(CLzmaEnc *p) ++{ ++ if (p->result != SZ_OK) ++ return p->result; ++ if (p->rc.res != SZ_OK) ++ p->result = SZ_ERROR_WRITE; ++ if (p->matchFinderBase.result != SZ_OK) ++ p->result = SZ_ERROR_READ; ++ if (p->result != SZ_OK) ++ p->finished = True; ++ return p->result; ++} ++ ++static SRes Flush(CLzmaEnc *p, UInt32 nowPos) ++{ ++ /* ReleaseMFStream(); */ ++ p->finished = True; ++ if (p->writeEndMark) ++ WriteEndMarker(p, nowPos & p->pbMask); ++ RangeEnc_FlushData(&p->rc); ++ RangeEnc_FlushStream(&p->rc); ++ return CheckErrors(p); ++} ++ ++static void FillAlignPrices(CLzmaEnc *p) ++{ ++ UInt32 i; ++ for (i = 0; i < kAlignTableSize; i++) ++ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); ++ p->alignPriceCount = 0; ++} ++ ++static void FillDistancesPrices(CLzmaEnc *p) ++{ ++ UInt32 tempPrices[kNumFullDistances]; ++ UInt32 i, lenToPosState; ++ for (i = kStartPosModelIndex; i < kNumFullDistances; i++) ++ { ++ UInt32 posSlot = GetPosSlot1(i); ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); ++ } ++ ++ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) ++ { ++ UInt32 posSlot; ++ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; ++ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; ++ for (posSlot = 0; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); ++ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); ++ ++ { ++ UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; ++ UInt32 i; ++ for (i = 0; i < kStartPosModelIndex; i++) ++ distancesPrices[i] = posSlotPrices[i]; ++ for (; i < kNumFullDistances; i++) ++ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; ++ } ++ } ++ p->matchPriceCount = 0; ++} ++ ++void LzmaEnc_Construct(CLzmaEnc *p) ++{ ++ RangeEnc_Construct(&p->rc); ++ MatchFinder_Construct(&p->matchFinderBase); ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Construct(&p->matchFinderMt); ++ p->matchFinderMt.MatchFinder = &p->matchFinderBase; ++ #endif ++ ++ { ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ LzmaEnc_SetProps(p, &props); ++ } ++ ++ #ifndef LZMA_LOG_BSR ++ LzmaEnc_FastPosInit(p->g_FastPos); ++ #endif ++ ++ LzmaEnc_InitPriceTables(p->ProbPrices); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) ++{ ++ void *p; ++ p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); ++ if (p != 0) ++ LzmaEnc_Construct((CLzmaEnc *)p); ++ return p; ++} ++ ++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->litProbs); ++ alloc->Free(alloc, p->saveState.litProbs); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); ++ #endif ++ MatchFinder_Free(&p->matchFinderBase, allocBig); ++ LzmaEnc_FreeLits(p, alloc); ++ RangeEnc_Free(&p->rc, alloc); ++} ++ ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); ++ alloc->Free(alloc, p); ++} ++ ++static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) ++{ ++ UInt32 nowPos32, startPos32; ++ if (p->needInit) ++ { ++ p->matchFinder.Init(p->matchFinderObj); ++ p->needInit = 0; ++ } ++ ++ if (p->finished) ++ return p->result; ++ RINOK(CheckErrors(p)); ++ ++ nowPos32 = (UInt32)p->nowPos64; ++ startPos32 = nowPos32; ++ ++ if (p->nowPos64 == 0) ++ { ++ UInt32 numPairs; ++ Byte curByte; ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ return Flush(p, nowPos32); ++ ReadMatchDistances(p, &numPairs); ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); ++ p->state = kLiteralNextStates[p->state]; ++ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); ++ LitEnc_Encode(&p->rc, p->litProbs, curByte); ++ p->additionalOffset--; ++ nowPos32++; ++ } ++ ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) ++ for (;;) ++ { ++ UInt32 pos, len, posState; ++ ++ if (p->fastMode) ++ len = GetOptimumFast(p, &pos); ++ else ++ len = GetOptimum(p, nowPos32, &pos); ++ ++ #ifdef SHOW_STAT2 ++ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); ++ #endif ++ ++ posState = nowPos32 & p->pbMask; ++ if (len == 1 && pos == (UInt32)-1) ++ { ++ Byte curByte; ++ CLzmaProb *probs; ++ const Byte *data; ++ ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++ curByte = *data; ++ probs = LIT_PROBS(nowPos32, *(data - 1)); ++ if (IsCharState(p->state)) ++ LitEnc_Encode(&p->rc, probs, curByte); ++ else ++ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); ++ p->state = kLiteralNextStates[p->state]; ++ } ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ if (pos < LZMA_NUM_REPS) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); ++ if (pos == 0) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); ++ } ++ else ++ { ++ UInt32 distance = p->reps[pos]; ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); ++ if (pos == 1) ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); ++ if (pos == 3) ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ } ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = distance; ++ } ++ if (len == 1) ++ p->state = kShortRepNextStates[p->state]; ++ else ++ { ++ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ p->state = kRepNextStates[p->state]; ++ } ++ } ++ else ++ { ++ UInt32 posSlot; ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ pos -= LZMA_NUM_REPS; ++ GetPosSlot(pos, posSlot); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); ++ ++ if (posSlot >= kStartPosModelIndex) ++ { ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ UInt32 posReduced = pos - base; ++ ++ if (posSlot < kEndPosModelIndex) ++ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); ++ else ++ { ++ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); ++ p->alignPriceCount++; ++ } ++ } ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = pos; ++ p->matchPriceCount++; ++ } ++ } ++ p->additionalOffset -= len; ++ nowPos32 += len; ++ if (p->additionalOffset == 0) ++ { ++ UInt32 processed; ++ if (!p->fastMode) ++ { ++ if (p->matchPriceCount >= (1 << 7)) ++ FillDistancesPrices(p); ++ if (p->alignPriceCount >= kAlignTableSize) ++ FillAlignPrices(p); ++ } ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ break; ++ processed = nowPos32 - startPos32; ++ if (useLimits) ++ { ++ if (processed + kNumOpts + 300 >= maxUnpackSize || ++ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) ++ break; ++ } ++ else if (processed >= (1 << 15)) ++ { ++ p->nowPos64 += nowPos32 - startPos32; ++ return CheckErrors(p); ++ } ++ } ++ } ++ p->nowPos64 += nowPos32 - startPos32; ++ return Flush(p, nowPos32); ++} ++ ++#define kBigHashDicLimit ((UInt32)1 << 24) ++ ++static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 beforeSize = kNumOpts; ++ Bool btMode; ++ if (!RangeEnc_Alloc(&p->rc, alloc)) ++ return SZ_ERROR_MEM; ++ btMode = (p->matchFinderBase.btMode != 0); ++ #ifndef _7ZIP_ST ++ p->mtMode = (p->multiThread && !p->fastMode && btMode); ++ #endif ++ ++ { ++ unsigned lclp = p->lc + p->lp; ++ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ if (p->litProbs == 0 || p->saveState.litProbs == 0) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ p->lclp = lclp; ++ } ++ } ++ ++ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); ++ ++ if (beforeSize + p->dictSize < keepWindowSize) ++ beforeSize = keepWindowSize - p->dictSize; ++ ++ #ifndef _7ZIP_ST ++ if (p->mtMode) ++ { ++ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); ++ p->matchFinderObj = &p->matchFinderMt; ++ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); ++ } ++ else ++ #endif ++ { ++ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) ++ return SZ_ERROR_MEM; ++ p->matchFinderObj = &p->matchFinderBase; ++ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); ++ } ++ return SZ_OK; ++} ++ ++void LzmaEnc_Init(CLzmaEnc *p) ++{ ++ UInt32 i; ++ p->state = 0; ++ for (i = 0 ; i < LZMA_NUM_REPS; i++) ++ p->reps[i] = 0; ++ ++ RangeEnc_Init(&p->rc); ++ ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ UInt32 j; ++ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) ++ { ++ p->isMatch[i][j] = kProbInitValue; ++ p->isRep0Long[i][j] = kProbInitValue; ++ } ++ p->isRep[i] = kProbInitValue; ++ p->isRepG0[i] = kProbInitValue; ++ p->isRepG1[i] = kProbInitValue; ++ p->isRepG2[i] = kProbInitValue; ++ } ++ ++ { ++ UInt32 num = 0x300 << (p->lp + p->lc); ++ for (i = 0; i < num; i++) ++ p->litProbs[i] = kProbInitValue; ++ } ++ ++ { ++ for (i = 0; i < kNumLenToPosStates; i++) ++ { ++ CLzmaProb *probs = p->posSlotEncoder[i]; ++ UInt32 j; ++ for (j = 0; j < (1 << kNumPosSlotBits); j++) ++ probs[j] = kProbInitValue; ++ } ++ } ++ { ++ for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) ++ p->posEncoders[i] = kProbInitValue; ++ } ++ ++ LenEnc_Init(&p->lenEnc.p); ++ LenEnc_Init(&p->repLenEnc.p); ++ ++ for (i = 0; i < (1 << kNumAlignBits); i++) ++ p->posAlignEncoder[i] = kProbInitValue; ++ ++ p->optimumEndIndex = 0; ++ p->optimumCurrentIndex = 0; ++ p->additionalOffset = 0; ++ ++ p->pbMask = (1 << p->pb) - 1; ++ p->lpMask = (1 << p->lp) - 1; ++} ++ ++void LzmaEnc_InitPrices(CLzmaEnc *p) ++{ ++ if (!p->fastMode) ++ { ++ FillDistancesPrices(p); ++ FillAlignPrices(p); ++ } ++ ++ p->lenEnc.tableSize = ++ p->repLenEnc.tableSize = ++ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; ++ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); ++ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); ++} ++ ++static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 i; ++ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) ++ if (p->dictSize <= ((UInt32)1 << i)) ++ break; ++ p->distTableSize = i * 2; ++ ++ p->finished = False; ++ p->result = SZ_OK; ++ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ p->nowPos64 = 0; ++ return SZ_OK; ++} ++ ++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->matchFinderBase.stream = inStream; ++ p->needInit = 1; ++ p->rc.outStream = outStream; ++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); ++} ++ ++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ++ ISeqInStream *inStream, UInt32 keepWindowSize, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->matchFinderBase.stream = inStream; ++ p->needInit = 1; ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) ++{ ++ p->matchFinderBase.directInput = 1; ++ p->matchFinderBase.bufferBase = (Byte *)src; ++ p->matchFinderBase.directInputRem = srcLen; ++} ++ ++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ p->needInit = 1; ++ ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++void LzmaEnc_Finish(CLzmaEncHandle pp) ++{ ++ #ifndef _7ZIP_ST ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ if (p->mtMode) ++ MatchFinderMt_ReleaseStream(&p->matchFinderMt); ++ #else ++ pp = pp; ++ #endif ++} ++ ++typedef struct ++{ ++ ISeqOutStream funcTable; ++ Byte *data; ++ SizeT rem; ++ Bool overflow; ++} CSeqOutStreamBuf; ++ ++static size_t MyWrite(void *pp, const void *data, size_t size) ++{ ++ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; ++ if (p->rem < size) ++ { ++ size = p->rem; ++ p->overflow = True; ++ } ++ memcpy(p->data, data, size); ++ p->rem -= size; ++ p->data += size; ++ return size; ++} ++ ++ ++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++} ++ ++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++} ++ ++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, ++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ UInt64 nowPos64; ++ SRes res; ++ CSeqOutStreamBuf outStream; ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = False; ++ p->finished = False; ++ p->result = SZ_OK; ++ ++ if (reInit) ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ nowPos64 = p->nowPos64; ++ RangeEnc_Init(&p->rc); ++ p->rc.outStream = &outStream.funcTable; ++ ++ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); ++ ++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64); ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ ++ return res; ++} ++ ++static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) ++{ ++ SRes res = SZ_OK; ++ ++ #ifndef _7ZIP_ST ++ Byte allocaDummy[0x300]; ++ int i = 0; ++ for (i = 0; i < 16; i++) ++ allocaDummy[i] = (Byte)i; ++ #endif ++ ++ for (;;) ++ { ++ res = LzmaEnc_CodeOneBlock(p, False, 0, 0); ++ if (res != SZ_OK || p->finished != 0) ++ break; ++ if (progress != 0) ++ { ++ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); ++ if (res != SZ_OK) ++ { ++ res = SZ_ERROR_PROGRESS; ++ break; ++ } ++ } ++ } ++ LzmaEnc_Finish(p); ++ return res; ++} ++ ++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); ++ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); ++} ++ ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ int i; ++ UInt32 dictSize = p->dictSize; ++ if (*size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_PARAM; ++ *size = LZMA_PROPS_SIZE; ++ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); ++ ++ for (i = 11; i <= 30; i++) ++ { ++ if (dictSize <= ((UInt32)2 << i)) ++ { ++ dictSize = (2 << i); ++ break; ++ } ++ if (dictSize <= ((UInt32)3 << i)) ++ { ++ dictSize = (3 << i); ++ break; ++ } ++ } ++ ++ for (i = 0; i < 4; i++) ++ props[1 + i] = (Byte)(dictSize >> (8 * i)); ++ return SZ_OK; ++} ++ ++SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ SRes res; ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ ++ CSeqOutStreamBuf outStream; ++ ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = writeEndMark; ++ ++ p->rc.outStream = &outStream.funcTable; ++ res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); ++ if (res == SZ_OK) ++ res = LzmaEnc_Encode2(p, progress); ++ ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ return res; ++} ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); ++ SRes res; ++ if (p == 0) ++ return SZ_ERROR_MEM; ++ ++ res = LzmaEnc_SetProps(p, props); ++ if (res == SZ_OK) ++ { ++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); ++ if (res == SZ_OK) ++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, ++ writeEndMark, progress, alloc, allocBig); ++ } ++ ++ LzmaEnc_Destroy(p, alloc, allocBig); ++ return res; ++} +--- /dev/null ++++ b/lib/lzma/Makefile +@@ -0,0 +1,7 @@ ++lzma_compress-objs := LzFind.o LzmaEnc.o ++lzma_decompress-objs := LzmaDec.o ++ ++obj-$(CONFIG_LZMA_COMPRESS) += lzma_compress.o ++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma_decompress.o ++ ++EXTRA_CFLAGS += -Iinclude/linux -Iinclude/linux/lzma -include types.h diff --git a/target/linux/generic/pending-6.6/532-jffs2_eofdetect.patch b/target/linux/generic/pending-6.6/532-jffs2_eofdetect.patch new file mode 100644 index 0000000000..744fbd0e21 --- /dev/null +++ b/target/linux/generic/pending-6.6/532-jffs2_eofdetect.patch @@ -0,0 +1,65 @@ +From: Felix Fietkau +Subject: fs: jffs2: EOF marker + +Signed-off-by: Felix Fietkau +--- + fs/jffs2/build.c | 10 ++++++++++ + fs/jffs2/scan.c | 21 +++++++++++++++++++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +--- a/fs/jffs2/build.c ++++ b/fs/jffs2/build.c +@@ -117,6 +117,16 @@ static int jffs2_build_filesystem(struct + dbg_fsbuild("scanned flash completely\n"); + jffs2_dbg_dump_block_lists_nolock(c); + ++ if (c->flags & (1 << 7)) { ++ printk("%s(): unlocking the mtd device... ", __func__); ++ mtd_unlock(c->mtd, 0, c->mtd->size); ++ printk("done.\n"); ++ ++ printk("%s(): erasing all blocks after the end marker... ", __func__); ++ jffs2_erase_pending_blocks(c, -1); ++ printk("done.\n"); ++ } ++ + dbg_fsbuild("pass 1 starting\n"); + c->flags |= JFFS2_SB_FLAG_BUILDING; + /* Now scan the directory tree, increasing nlink according to every dirent found. */ +--- a/fs/jffs2/scan.c ++++ b/fs/jffs2/scan.c +@@ -148,8 +148,14 @@ int jffs2_scan_medium(struct jffs2_sb_in + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + +- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), +- buf_size, s); ++ if (c->flags & (1 << 7)) { ++ if (mtd_block_isbad(c->mtd, jeb->offset)) ++ ret = BLK_STATE_BADBLOCK; ++ else ++ ret = BLK_STATE_ALLFF; ++ } else ++ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), ++ buf_size, s); + + if (ret < 0) + goto out; +@@ -567,6 +573,17 @@ full_scan: + return err; + } + ++ if ((buf[0] == 0xde) && ++ (buf[1] == 0xad) && ++ (buf[2] == 0xc0) && ++ (buf[3] == 0xde)) { ++ /* end of filesystem. erase everything after this point */ ++ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset); ++ c->flags |= (1 << 7); ++ ++ return BLK_STATE_ALLFF; ++ } ++ + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ + ofs = 0; + max_ofs = EMPTY_SCAN_SIZE(c->sector_size); diff --git a/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch new file mode 100644 index 0000000000..d7548c1419 --- /dev/null +++ b/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch @@ -0,0 +1,90 @@ +From: Felix Fietkau +Subject: netfilter: add support for flushing conntrack via /proc + +lede-commit 8193bbe59a74d34d6a26d4a8cb857b1952905314 +Signed-off-by: Felix Fietkau +--- + net/netfilter/nf_conntrack_standalone.c | 59 ++++++++++++++++++++++++++++++++- + 1 file changed, 58 insertions(+), 1 deletion(-) + +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #ifdef CONFIG_SYSCTL + #include +@@ -465,6 +466,58 @@ static int ct_cpu_seq_show(struct seq_fi + return 0; + } + ++struct kill_request { ++ u16 family; ++ union nf_inet_addr addr; ++}; ++ ++static int kill_matching(struct nf_conn *i, void *data) ++{ ++ struct kill_request *kr = data; ++ struct nf_conntrack_tuple *t1 = &i->tuplehash[IP_CT_DIR_ORIGINAL].tuple; ++ struct nf_conntrack_tuple *t2 = &i->tuplehash[IP_CT_DIR_REPLY].tuple; ++ ++ if (!kr->family) ++ return 1; ++ ++ if (t1->src.l3num != kr->family) ++ return 0; ++ ++ return (nf_inet_addr_cmp(&kr->addr, &t1->src.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t1->dst.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t2->src.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t2->dst.u3)); ++} ++ ++static int ct_file_write(struct file *file, char *buf, size_t count) ++{ ++ struct seq_file *seq = file->private_data; ++ struct nf_ct_iter_data iter_data; ++ struct kill_request kr = { }; ++ ++ if (count == 0) ++ return 0; ++ ++ if (count >= INET6_ADDRSTRLEN) ++ count = INET6_ADDRSTRLEN - 1; ++ ++ if (strnchr(buf, count, ':')) { ++ kr.family = AF_INET6; ++ if (!in6_pton(buf, count, (void *)&kr.addr, '\n', NULL)) ++ return -EINVAL; ++ } else if (strnchr(buf, count, '.')) { ++ kr.family = AF_INET; ++ if (!in4_pton(buf, count, (void *)&kr.addr, '\n', NULL)) ++ return -EINVAL; ++ } ++ ++ iter_data.net = seq_file_net(seq); ++ iter_data.data = &kr; ++ nf_ct_iterate_cleanup_net(kill_matching, &iter_data); ++ ++ return 0; ++} ++ + static const struct seq_operations ct_cpu_seq_ops = { + .start = ct_cpu_seq_start, + .next = ct_cpu_seq_next, +@@ -478,8 +531,9 @@ static int nf_conntrack_standalone_init_ + kuid_t root_uid; + kgid_t root_gid; + +- pde = proc_create_net("nf_conntrack", 0440, net->proc_net, &ct_seq_ops, +- sizeof(struct ct_iter_state)); ++ pde = proc_create_net_data_write("nf_conntrack", 0440, net->proc_net, ++ &ct_seq_ops, &ct_file_write, ++ sizeof(struct ct_iter_state), NULL); + if (!pde) + goto out_nf_conntrack; + diff --git a/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch new file mode 100644 index 0000000000..7e34ef3713 --- /dev/null +++ b/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch @@ -0,0 +1,110 @@ +From: Felix Fietkau +Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 + +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + + net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h ++++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h +@@ -89,6 +89,7 @@ struct ipt_ip { + #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ + #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ + #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ ++#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ + + /* Values for "inv" field in struct ipt_ip. */ + #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -50,6 +50,9 @@ ip_packet_match(const struct iphdr *ip, + { + unsigned long ret; + ++ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) ++ return true; ++ + if (NF_INVF(ipinfo, IPT_INV_SRCIP, + (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || + NF_INVF(ipinfo, IPT_INV_DSTIP, +@@ -80,6 +83,29 @@ ip_packet_match(const struct iphdr *ip, + return true; + } + ++static void ++ip_checkdefault(struct ipt_ip *ip) ++{ ++ static const char iface_mask[IFNAMSIZ] = {}; ++ ++ if (ip->invflags || ip->flags & IPT_F_FRAG) ++ return; ++ ++ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) ++ return; ++ ++ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) ++ return; ++ ++ if (ip->smsk.s_addr || ip->dmsk.s_addr) ++ return; ++ ++ if (ip->proto) ++ return; ++ ++ ip->flags |= IPT_F_NO_DEF_MATCH; ++} ++ + static bool + ip_checkentry(const struct ipt_ip *ip) + { +@@ -525,6 +551,8 @@ find_check_entry(struct ipt_entry *e, st + struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; + ++ ip_checkdefault(&e->ip); ++ + if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) + return -ENOMEM; + +@@ -819,6 +847,7 @@ copy_entries_to_user(unsigned int total_ + const struct xt_table_info *private = table->private; + int ret = 0; + const void *loc_cpu_entry; ++ u8 flags; + + counters = alloc_counters(table); + if (IS_ERR(counters)) +@@ -846,6 +875,14 @@ copy_entries_to_user(unsigned int total_ + goto free_counters; + } + ++ flags = e->ip.flags & IPT_F_MASK; ++ if (copy_to_user(userptr + off ++ + offsetof(struct ipt_entry, ip.flags), ++ &flags, sizeof(flags)) != 0) { ++ ret = -EFAULT; ++ goto free_counters; ++ } ++ + for (i = sizeof(struct ipt_entry); + i < e->target_offset; + i += m->u.match_size) { +@@ -1223,12 +1260,15 @@ compat_copy_entry_to_user(struct ipt_ent + compat_uint_t origsize; + const struct xt_entry_match *ematch; + int ret = 0; ++ u8 flags = e->ip.flags & IPT_F_MASK; + + origsize = *size; + ce = *dstptr; + if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || + copy_to_user(&ce->counters, &counters[i], +- sizeof(counters[i])) != 0) ++ sizeof(counters[i])) != 0 || ++ copy_to_user(&ce->ip.flags, &flags, ++ sizeof(flags)) != 0) + return -EFAULT; + + *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch new file mode 100644 index 0000000000..dd557fd3ea --- /dev/null +++ b/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch @@ -0,0 +1,106 @@ +From: Felix Fietkau +Subject: netfilter: match bypass default table + +Signed-off-by: Felix Fietkau +--- + net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- + 1 file changed, 58 insertions(+), 21 deletions(-) + +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -246,6 +246,33 @@ struct ipt_entry *ipt_next_entry(const s + return (void *)entry + entry->next_offset; + } + ++static bool ++ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) ++{ ++ struct xt_entry_target *t; ++ struct xt_standard_target *st; ++ ++ if (e->target_offset != sizeof(struct ipt_entry)) ++ return false; ++ ++ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) ++ return false; ++ ++ t = ipt_get_target(e); ++ if (t->u.kernel.target->target) ++ return false; ++ ++ st = (struct xt_standard_target *) t; ++ if (st->verdict == XT_RETURN) ++ return false; ++ ++ if (st->verdict >= 0) ++ return false; ++ ++ *verdict = (unsigned)(-st->verdict) - 1; ++ return true; ++} ++ + /* Returns one of the generic firewall policies, like NF_ACCEPT. */ + unsigned int + ipt_do_table(void *priv, +@@ -267,27 +294,28 @@ ipt_do_table(void *priv, + unsigned int addend; + + /* Initialization */ ++ WARN_ON(!(table->valid_hooks & (1 << hook))); ++ local_bh_disable(); ++ private = READ_ONCE(table->private); /* Address dependency. */ ++ cpu = smp_processor_id(); ++ table_base = private->entries; ++ ++ e = get_entry(table_base, private->hook_entry[hook]); ++ if (ipt_handle_default_rule(e, &verdict)) { ++ struct xt_counters *counter; ++ ++ counter = xt_get_this_cpu_counter(&e->counters); ++ ADD_COUNTER(*counter, skb->len, 1); ++ local_bh_enable(); ++ return verdict; ++ } ++ + stackidx = 0; + ip = ip_hdr(skb); + indev = state->in ? state->in->name : nulldevname; + outdev = state->out ? state->out->name : nulldevname; +- /* We handle fragments by dealing with the first fragment as +- * if it was a normal packet. All other fragments are treated +- * normally, except that they will NEVER match rules that ask +- * things we don't know, ie. tcp syn flag or ports). If the +- * rule is also a fragment-specific rule, non-fragments won't +- * match it. */ +- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; +- acpar.thoff = ip_hdrlen(skb); +- acpar.hotdrop = false; +- acpar.state = state; + +- WARN_ON(!(table->valid_hooks & (1 << hook))); +- local_bh_disable(); + addend = xt_write_recseq_begin(); +- private = READ_ONCE(table->private); /* Address dependency. */ +- cpu = smp_processor_id(); +- table_base = private->entries; + jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; + + /* Switch to alternate jumpstack if we're being invoked via TEE. +@@ -300,7 +328,16 @@ ipt_do_table(void *priv, + if (static_key_false(&xt_tee_enabled)) + jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); + +- e = get_entry(table_base, private->hook_entry[hook]); ++ /* We handle fragments by dealing with the first fragment as ++ * if it was a normal packet. All other fragments are treated ++ * normally, except that they will NEVER match rules that ask ++ * things we don't know, ie. tcp syn flag or ports). If the ++ * rule is also a fragment-specific rule, non-fragments won't ++ * match it. */ ++ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; ++ acpar.thoff = ip_hdrlen(skb); ++ acpar.hotdrop = false; ++ acpar.state = state; + + do { + const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch new file mode 100644 index 0000000000..79da6778b6 --- /dev/null +++ b/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: netfilter: reduce match memory access + +Signed-off-by: Felix Fietkau +--- + net/ipv4/netfilter/ip_tables.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -53,9 +53,9 @@ ip_packet_match(const struct iphdr *ip, + if (ipinfo->flags & IPT_F_NO_DEF_MATCH) + return true; + +- if (NF_INVF(ipinfo, IPT_INV_SRCIP, ++ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && + (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || +- NF_INVF(ipinfo, IPT_INV_DSTIP, ++ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && + (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) + return false; + diff --git a/target/linux/generic/pending-6.6/620-net_sched-codel-do-not-defer-queue-length-update.patch b/target/linux/generic/pending-6.6/620-net_sched-codel-do-not-defer-queue-length-update.patch new file mode 100644 index 0000000000..4b4825ae3b --- /dev/null +++ b/target/linux/generic/pending-6.6/620-net_sched-codel-do-not-defer-queue-length-update.patch @@ -0,0 +1,86 @@ +From: Konstantin Khlebnikov +Date: Mon, 21 Aug 2017 11:14:14 +0300 +Subject: [PATCH] net_sched/codel: do not defer queue length update + +When codel wants to drop last packet in ->dequeue() it cannot call +qdisc_tree_reduce_backlog() right away - it will notify parent qdisc +about zero qlen and HTB/HFSC will deactivate class. The same class will +be deactivated second time by caller of ->dequeue(). Currently codel and +fq_codel defer update. This triggers warning in HFSC when it's qlen != 0 +but there is no active classes. + +This patch update parent queue length immediately: just temporary increase +qlen around qdisc_tree_reduce_backlog() to prevent first class deactivation +if we have skb to return. + +This might open another problem in HFSC - now operation peek could fail and +deactivate parent class. + +Signed-off-by: Konstantin Khlebnikov +Link: https://bugzilla.kernel.org/show_bug.cgi?id=109581 +--- + +--- a/net/sched/sch_codel.c ++++ b/net/sched/sch_codel.c +@@ -95,11 +95,17 @@ static struct sk_buff *codel_qdisc_deque + &q->stats, qdisc_pkt_len, codel_get_enqueue_time, + drop_func, dequeue_func); + +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. + */ +- if (q->stats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len); ++ if (q->stats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->stats.drop_count, ++ q->stats.drop_len); ++ if (skb) ++ sch->q.qlen--; + q->stats.drop_count = 0; + q->stats.drop_len = 0; + } +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -304,6 +304,21 @@ begin: + &flow->cvars, &q->cstats, qdisc_pkt_len, + codel_get_enqueue_time, drop_func, dequeue_func); + ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. ++ */ ++ if (q->cstats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, ++ q->cstats.drop_len); ++ if (skb) ++ sch->q.qlen--; ++ q->cstats.drop_count = 0; ++ q->cstats.drop_len = 0; ++ } ++ + if (!skb) { + /* force a pass through old_flows to prevent starvation */ + if ((head == &q->new_flows) && !list_empty(&q->old_flows)) +@@ -314,15 +329,6 @@ begin: + } + qdisc_bstats_update(sch, skb); + flow->deficit -= qdisc_pkt_len(skb); +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. +- */ +- if (q->cstats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, +- q->cstats.drop_len); +- q->cstats.drop_count = 0; +- q->cstats.drop_len = 0; +- } + return skb; + } + diff --git a/target/linux/generic/pending-6.6/630-packet_socket_type.patch b/target/linux/generic/pending-6.6/630-packet_socket_type.patch new file mode 100644 index 0000000000..c40c709635 --- /dev/null +++ b/target/linux/generic/pending-6.6/630-packet_socket_type.patch @@ -0,0 +1,138 @@ +From: Felix Fietkau +Subject: net: add an optimization for dealing with raw sockets + +lede-commit: 4898039703d7315f0f3431c860123338ec3be0f6 +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/if_packet.h | 3 +++ + net/packet/af_packet.c | 34 +++++++++++++++++++++++++++------- + net/packet/internal.h | 1 + + 3 files changed, 31 insertions(+), 7 deletions(-) + +--- a/include/uapi/linux/if_packet.h ++++ b/include/uapi/linux/if_packet.h +@@ -33,6 +33,8 @@ struct sockaddr_ll { + #define PACKET_KERNEL 7 /* To kernel space */ + /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */ + #define PACKET_FASTROUTE 6 /* Fastrouted frame */ ++#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */ ++ + + /* Packet socket options */ + +@@ -59,6 +61,7 @@ struct sockaddr_ll { + #define PACKET_ROLLOVER_STATS 21 + #define PACKET_FANOUT_DATA 22 + #define PACKET_IGNORE_OUTGOING 23 ++#define PACKET_RECV_TYPE 24 + + #define PACKET_FANOUT_HASH 0 + #define PACKET_FANOUT_LB 1 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1866,6 +1866,7 @@ static int packet_rcv_spkt(struct sk_buf + { + struct sock *sk; + struct sockaddr_pkt *spkt; ++ struct packet_sock *po; + + /* + * When we registered the protocol we saved the socket in the data +@@ -1873,6 +1874,7 @@ static int packet_rcv_spkt(struct sk_buf + */ + + sk = pt->af_packet_priv; ++ po = pkt_sk(sk); + + /* + * Yank back the headers [hope the device set this +@@ -1885,7 +1887,7 @@ static int packet_rcv_spkt(struct sk_buf + * so that this procedure is noop. + */ + +- if (skb->pkt_type == PACKET_LOOPBACK) ++ if (!(po->pkt_type & (1 << skb->pkt_type))) + goto out; + + if (!net_eq(dev_net(dev), sock_net(sk))) +@@ -2131,12 +2133,12 @@ static int packet_rcv(struct sk_buff *sk + unsigned int snaplen, res; + bool is_drop_n_account = false; + +- if (skb->pkt_type == PACKET_LOOPBACK) +- goto drop; +- + sk = pt->af_packet_priv; + po = pkt_sk(sk); + ++ if (!(po->pkt_type & (1 << skb->pkt_type))) ++ goto drop; ++ + if (!net_eq(dev_net(dev), sock_net(sk))) + goto drop; + +@@ -2263,12 +2265,12 @@ static int tpacket_rcv(struct sk_buff *s + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); + +- if (skb->pkt_type == PACKET_LOOPBACK) +- goto drop; +- + sk = pt->af_packet_priv; + po = pkt_sk(sk); + ++ if (!(po->pkt_type & (1 << skb->pkt_type))) ++ goto drop; ++ + if (!net_eq(dev_net(dev), sock_net(sk))) + goto drop; + +@@ -3378,6 +3380,7 @@ static int packet_create(struct net *net + mutex_init(&po->pg_vec_lock); + po->rollover = NULL; + po->prot_hook.func = packet_rcv; ++ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK); + + if (sock->type == SOCK_PACKET) + po->prot_hook.func = packet_rcv_spkt; +@@ -4013,6 +4016,16 @@ packet_setsockopt(struct socket *sock, i + WRITE_ONCE(po->xmit, val ? packet_direct_xmit : dev_queue_xmit); + return 0; + } ++ case PACKET_RECV_TYPE: ++ { ++ unsigned int val; ++ if (optlen != sizeof(val)) ++ return -EINVAL; ++ if (copy_from_sockptr(&val, optval, sizeof(val))) ++ return -EFAULT; ++ po->pkt_type = val & ~BIT(PACKET_LOOPBACK); ++ return 0; ++ } + default: + return -ENOPROTOOPT; + } +@@ -4069,6 +4082,13 @@ static int packet_getsockopt(struct sock + case PACKET_VNET_HDR: + val = po->has_vnet_hdr; + break; ++ case PACKET_RECV_TYPE: ++ if (len > sizeof(unsigned int)) ++ len = sizeof(unsigned int); ++ val = po->pkt_type; ++ ++ data = &val; ++ break; + case PACKET_VERSION: + val = po->tp_version; + break; +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -136,6 +136,7 @@ struct packet_sock { + int (*xmit)(struct sk_buff *skb); + struct packet_type prot_hook ____cacheline_aligned_in_smp; + atomic_t tp_drops ____cacheline_aligned_in_smp; ++ unsigned int pkt_type; + }; + + static inline struct packet_sock *pkt_sk(struct sock *sk) diff --git a/target/linux/generic/pending-6.6/655-increase_skb_pad.patch b/target/linux/generic/pending-6.6/655-increase_skb_pad.patch new file mode 100644 index 0000000000..0c47bc9d2c --- /dev/null +++ b/target/linux/generic/pending-6.6/655-increase_skb_pad.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Subject: kernel: add a few patches for avoiding unnecessary skb reallocations - significantly improves ethernet<->wireless performance + +lede-commit: 6f89cffc9add6939d44a6b54cf9a5e77849aa7fd +Signed-off-by: Felix Fietkau +--- + include/linux/skbuff.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -3006,7 +3006,7 @@ static inline int pskb_network_may_pull( + * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) + */ + #ifndef NET_SKB_PAD +-#define NET_SKB_PAD max(32, L1_CACHE_BYTES) ++#define NET_SKB_PAD max(64, L1_CACHE_BYTES) + #endif + + int ___pskb_trim(struct sk_buff *skb, unsigned int len); diff --git a/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch new file mode 100644 index 0000000000..b799c6fc9c --- /dev/null +++ b/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -0,0 +1,511 @@ +From: Steven Barth +Subject: Add support for MAP-E FMRs (mesh mode) + +MAP-E FMRs (draft-ietf-softwire-map-10) are rules for IPv4-communication +between MAP CEs (mesh mode) without the need to forward such data to a +border relay. This is similar to how 6rd works but for IPv4 over IPv6. + +Signed-off-by: Steven Barth +--- + include/net/ip6_tunnel.h | 13 ++ + include/uapi/linux/if_tunnel.h | 13 ++ + net/ipv6/ip6_tunnel.c | 276 +++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 291 insertions(+), 11 deletions(-) + +--- a/include/net/ip6_tunnel.h ++++ b/include/net/ip6_tunnel.h +@@ -18,6 +18,18 @@ + /* determine capability on a per-packet basis */ + #define IP6_TNL_F_CAP_PER_PACKET 0x40000 + ++/* IPv6 tunnel FMR */ ++struct __ip6_tnl_fmr { ++ struct __ip6_tnl_fmr *next; /* next fmr in list */ ++ struct in6_addr ip6_prefix; ++ struct in_addr ip4_prefix; ++ ++ __u8 ip6_prefix_len; ++ __u8 ip4_prefix_len; ++ __u8 ea_len; ++ __u8 offset; ++}; ++ + struct __ip6_tnl_parm { + char name[IFNAMSIZ]; /* name of tunnel device */ + int link; /* ifindex of underlying L2 interface */ +@@ -29,6 +41,7 @@ struct __ip6_tnl_parm { + __u32 flags; /* tunnel flags */ + struct in6_addr laddr; /* local tunnel end-point address */ + struct in6_addr raddr; /* remote tunnel end-point address */ ++ struct __ip6_tnl_fmr *fmrs; /* FMRs */ + + __be16 i_flags; + __be16 o_flags; +--- a/include/uapi/linux/if_tunnel.h ++++ b/include/uapi/linux/if_tunnel.h +@@ -77,10 +77,23 @@ enum { + IFLA_IPTUN_ENCAP_DPORT, + IFLA_IPTUN_COLLECT_METADATA, + IFLA_IPTUN_FWMARK, ++ IFLA_IPTUN_FMRS, + __IFLA_IPTUN_MAX, + }; + #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + ++enum { ++ IFLA_IPTUN_FMR_UNSPEC, ++ IFLA_IPTUN_FMR_IP6_PREFIX, ++ IFLA_IPTUN_FMR_IP4_PREFIX, ++ IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ++ IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ++ IFLA_IPTUN_FMR_EA_LEN, ++ IFLA_IPTUN_FMR_OFFSET, ++ __IFLA_IPTUN_FMR_MAX, ++}; ++#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1) ++ + enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -11,6 +11,9 @@ + * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c + * + * RFC 2473 ++ * ++ * Changes: ++ * Steven Barth : MAP-E FMR support + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -67,9 +70,9 @@ static bool log_ecn_error = true; + module_param(log_ecn_error, bool, 0644); + MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); + +-static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) ++static u32 HASH(const struct in6_addr *addr) + { +- u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); ++ u32 hash = ipv6_addr_hash(addr); + + return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); + } +@@ -114,17 +117,33 @@ static struct ip6_tnl * + ip6_tnl_lookup(struct net *net, int link, + const struct in6_addr *remote, const struct in6_addr *local) + { +- unsigned int hash = HASH(remote, local); ++ unsigned int hash = HASH(local); + struct ip6_tnl *t, *cand = NULL; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct in6_addr any; + + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || +- !ipv6_addr_equal(remote, &t->parms.raddr) || + !(t->dev->flags & IFF_UP)) + continue; + ++ if (!ipv6_addr_equal(remote, &t->parms.raddr)) { ++ struct __ip6_tnl_fmr *fmr; ++ bool found = false; ++ ++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { ++ if (!ipv6_prefix_equal(remote, &fmr->ip6_prefix, ++ fmr->ip6_prefix_len)) ++ continue; ++ ++ found = true; ++ break; ++ } ++ ++ if (!found) ++ continue; ++ } ++ + if (link == t->parms.link) + return t; + else +@@ -132,7 +151,7 @@ ip6_tnl_lookup(struct net *net, int link + } + + memset(&any, 0, sizeof(any)); +- hash = HASH(&any, local); ++ hash = HASH(local); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || + !ipv6_addr_any(&t->parms.raddr) || +@@ -145,7 +164,7 @@ ip6_tnl_lookup(struct net *net, int link + cand = t; + } + +- hash = HASH(remote, &any); ++ hash = HASH(&any); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(remote, &t->parms.raddr) || + !ipv6_addr_any(&t->parms.laddr) || +@@ -194,7 +213,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, + + if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { + prio = 1; +- h = HASH(remote, local); ++ h = HASH(local); + } + return &ip6n->tnls[prio][h]; + } +@@ -376,6 +395,12 @@ ip6_tnl_dev_uninit(struct net_device *de + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + ++ while (t->parms.fmrs) { ++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; ++ kfree(t->parms.fmrs); ++ t->parms.fmrs = next; ++ } ++ + if (dev == ip6n->fb_tnl_dev) + RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); + else +@@ -788,6 +813,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, + } + EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); + ++/** ++ * ip4ip6_fmr_calc - calculate target / source IPv6-address based on FMR ++ * @dest: destination IPv6 address buffer ++ * @skb: received socket buffer ++ * @fmr: MAP FMR ++ * @xmit: Calculate for xmit or rcv ++ **/ ++static void ip4ip6_fmr_calc(struct in6_addr *dest, ++ const struct iphdr *iph, const uint8_t *end, ++ const struct __ip6_tnl_fmr *fmr, bool xmit) ++{ ++ int psidlen = fmr->ea_len - (32 - fmr->ip4_prefix_len); ++ u8 *portp = NULL; ++ bool use_dest_addr; ++ const struct iphdr *dsth = iph; ++ ++ if ((u8*)dsth >= end) ++ return; ++ ++ /* find significant IP header */ ++ if (iph->protocol == IPPROTO_ICMP) { ++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); ++ if (ih && ((u8*)&ih[1]) <= end && ( ++ ih->type == ICMP_DEST_UNREACH || ++ ih->type == ICMP_SOURCE_QUENCH || ++ ih->type == ICMP_TIME_EXCEEDED || ++ ih->type == ICMP_PARAMETERPROB || ++ ih->type == ICMP_REDIRECT)) ++ dsth = (const struct iphdr*)&ih[1]; ++ } ++ ++ /* in xmit-path use dest port by default and source port only if ++ this is an ICMP reply to something else; vice versa in rcv-path */ ++ use_dest_addr = (xmit && dsth == iph) || (!xmit && dsth != iph); ++ ++ /* get dst port */ ++ if (((u8*)&dsth[1]) <= end && ( ++ dsth->protocol == IPPROTO_UDP || ++ dsth->protocol == IPPROTO_TCP || ++ dsth->protocol == IPPROTO_SCTP || ++ dsth->protocol == IPPROTO_DCCP)) { ++ /* for UDP, TCP, SCTP and DCCP source and dest port ++ follow IPv4 header directly */ ++ portp = ((u8*)dsth) + dsth->ihl * 4; ++ ++ if (use_dest_addr) ++ portp += sizeof(u16); ++ } else if (iph->protocol == IPPROTO_ICMP) { ++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); ++ ++ /* use icmp identifier as port */ ++ if (((u8*)&ih) <= end && ( ++ (use_dest_addr && ( ++ ih->type == ICMP_ECHOREPLY || ++ ih->type == ICMP_TIMESTAMPREPLY || ++ ih->type == ICMP_INFO_REPLY || ++ ih->type == ICMP_ADDRESSREPLY)) || ++ (!use_dest_addr && ( ++ ih->type == ICMP_ECHO || ++ ih->type == ICMP_TIMESTAMP || ++ ih->type == ICMP_INFO_REQUEST || ++ ih->type == ICMP_ADDRESS) ++ ))) ++ portp = (u8*)&ih->un.echo.id; ++ } ++ ++ if ((portp && &portp[2] <= end) || psidlen == 0) { ++ int frombyte = fmr->ip6_prefix_len / 8; ++ int fromrem = fmr->ip6_prefix_len % 8; ++ int bytes = sizeof(struct in6_addr) - frombyte; ++ const u32 *addr = (use_dest_addr) ? &iph->daddr : &iph->saddr; ++ u64 eabits = ((u64)ntohl(*addr)) << (32 + fmr->ip4_prefix_len); ++ u64 t = 0; ++ ++ /* extract PSID from port and add it to eabits */ ++ u16 psidbits = 0; ++ if (psidlen > 0) { ++ psidbits = ((u16)portp[0]) << 8 | ((u16)portp[1]); ++ psidbits >>= 16 - psidlen - fmr->offset; ++ psidbits = (u16)(psidbits << (16 - psidlen)); ++ eabits |= ((u64)psidbits) << (48 - (fmr->ea_len - psidlen)); ++ } ++ ++ /* rewrite destination address */ ++ *dest = fmr->ip6_prefix; ++ memcpy(&dest->s6_addr[10], addr, sizeof(*addr)); ++ dest->s6_addr16[7] = htons(psidbits >> (16 - psidlen)); ++ ++ if (bytes > sizeof(u64)) ++ bytes = sizeof(u64); ++ ++ /* insert eabits */ ++ memcpy(&t, &dest->s6_addr[frombyte], bytes); ++ t = be64_to_cpu(t) & ~(((((u64)1) << fmr->ea_len) - 1) ++ << (64 - fmr->ea_len - fromrem)); ++ t = cpu_to_be64(t | (eabits >> fromrem)); ++ memcpy(&dest->s6_addr[frombyte], &t, bytes); ++ } ++} ++ ++ + static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, +@@ -855,6 +981,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl + + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + ++ if (tpi->proto == htons(ETH_P_IP) && tunnel->parms.fmrs && ++ !ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) { ++ /* Packet didn't come from BR, so lookup FMR */ ++ struct __ip6_tnl_fmr *fmr; ++ struct in6_addr expected = tunnel->parms.raddr; ++ for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next) ++ if (ipv6_prefix_equal(&ipv6h->saddr, ++ &fmr->ip6_prefix, fmr->ip6_prefix_len)) ++ break; ++ ++ /* Check that IPv6 matches IPv4 source to prevent spoofing */ ++ if (fmr) ++ ip4ip6_fmr_calc(&expected, ip_hdr(skb), ++ skb_tail_pointer(skb), fmr, false); ++ ++ if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) { ++ rcu_read_unlock(); ++ goto drop; ++ } ++ } ++ + __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); + + err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); +@@ -1002,6 +1149,7 @@ static void init_tel_txopt(struct ipv6_t + opt->ops.opt_nflen = 8; + } + ++ + /** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device +@@ -1293,6 +1441,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str + u8 protocol) + { + struct ip6_tnl *t = netdev_priv(dev); ++ struct __ip6_tnl_fmr *fmr; + struct ipv6hdr *ipv6h; + const struct iphdr *iph; + int encap_limit = -1; +@@ -1392,6 +1541,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str + fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield); + ++ /* try to find matching FMR */ ++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { ++ unsigned mshift = 32 - fmr->ip4_prefix_len; ++ if (ntohl(fmr->ip4_prefix.s_addr) >> mshift == ++ ntohl(ip_hdr(skb)->daddr) >> mshift) ++ break; ++ } ++ ++ /* change dstaddr according to FMR */ ++ if (fmr) ++ ip4ip6_fmr_calc(&fl6.daddr, ip_hdr(skb), skb_tail_pointer(skb), fmr, true); ++ + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + +@@ -1545,6 +1706,14 @@ ip6_tnl_change(struct ip6_tnl *t, const + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.fwmark = p->fwmark; ++ ++ while (t->parms.fmrs) { ++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; ++ kfree(t->parms.fmrs); ++ t->parms.fmrs = next; ++ } ++ t->parms.fmrs = p->fmrs; ++ + dst_cache_reset(&t->dst_cache); + ip6_tnl_link_config(t); + } +@@ -1579,6 +1748,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ + p->flowinfo = u->flowinfo; + p->link = u->link; + p->proto = u->proto; ++ p->fmrs = NULL; + memcpy(p->name, u->name, sizeof(u->name)); + } + +@@ -1965,6 +2135,15 @@ static int ip6_tnl_validate(struct nlatt + return 0; + } + ++static const struct nla_policy ip6_tnl_fmr_policy[IFLA_IPTUN_FMR_MAX + 1] = { ++ [IFLA_IPTUN_FMR_IP6_PREFIX] = { .len = sizeof(struct in6_addr) }, ++ [IFLA_IPTUN_FMR_IP4_PREFIX] = { .len = sizeof(struct in_addr) }, ++ [IFLA_IPTUN_FMR_IP6_PREFIX_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_IP4_PREFIX_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_EA_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_OFFSET] = { .type = NLA_U8 } ++}; ++ + static void ip6_tnl_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) + { +@@ -2002,6 +2181,46 @@ static void ip6_tnl_netlink_parms(struct + + if (data[IFLA_IPTUN_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); ++ ++ if (data[IFLA_IPTUN_FMRS]) { ++ unsigned rem; ++ struct nlattr *fmr; ++ nla_for_each_nested(fmr, data[IFLA_IPTUN_FMRS], rem) { ++ struct nlattr *fmrd[IFLA_IPTUN_FMR_MAX + 1], *c; ++ struct __ip6_tnl_fmr *nfmr; ++ ++ nla_parse_nested(fmrd, IFLA_IPTUN_FMR_MAX, ++ fmr, ip6_tnl_fmr_policy, NULL); ++ ++ if (!(nfmr = kzalloc(sizeof(*nfmr), GFP_KERNEL))) ++ continue; ++ ++ nfmr->offset = 6; ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX])) ++ nla_memcpy(&nfmr->ip6_prefix, fmrd[IFLA_IPTUN_FMR_IP6_PREFIX], ++ sizeof(nfmr->ip6_prefix)); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX])) ++ nla_memcpy(&nfmr->ip4_prefix, fmrd[IFLA_IPTUN_FMR_IP4_PREFIX], ++ sizeof(nfmr->ip4_prefix)); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX_LEN])) ++ nfmr->ip6_prefix_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX_LEN])) ++ nfmr->ip4_prefix_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_EA_LEN])) ++ nfmr->ea_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_OFFSET])) ++ nfmr->offset = nla_get_u8(c); ++ ++ nfmr->next = parms->fmrs; ++ parms->fmrs = nfmr; ++ } ++ } + } + + static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, +@@ -2085,6 +2304,12 @@ static void ip6_tnl_dellink(struct net_d + + static size_t ip6_tnl_get_size(const struct net_device *dev) + { ++ const struct ip6_tnl *t = netdev_priv(dev); ++ struct __ip6_tnl_fmr *c; ++ int fmrs = 0; ++ for (c = t->parms.fmrs; c; c = c->next) ++ ++fmrs; ++ + return + /* IFLA_IPTUN_LINK */ + nla_total_size(4) + +@@ -2114,6 +2339,24 @@ static size_t ip6_tnl_get_size(const str + nla_total_size(0) + + /* IFLA_IPTUN_FWMARK */ + nla_total_size(4) + ++ /* IFLA_IPTUN_FMRS */ ++ nla_total_size(0) + ++ ( ++ /* nest */ ++ nla_total_size(0) + ++ /* IFLA_IPTUN_FMR_IP6_PREFIX */ ++ nla_total_size(sizeof(struct in6_addr)) + ++ /* IFLA_IPTUN_FMR_IP4_PREFIX */ ++ nla_total_size(sizeof(struct in_addr)) + ++ /* IFLA_IPTUN_FMR_EA_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_IP6_PREFIX_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_IP4_PREFIX_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_OFFSET */ ++ nla_total_size(1) ++ ) * fmrs + + 0; + } + +@@ -2121,6 +2364,9 @@ static int ip6_tnl_fill_info(struct sk_b + { + struct ip6_tnl *tunnel = netdev_priv(dev); + struct __ip6_tnl_parm *parm = &tunnel->parms; ++ struct __ip6_tnl_fmr *c; ++ int fmrcnt = 0; ++ struct nlattr *fmrs; + + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || + nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || +@@ -2130,9 +2376,27 @@ static int ip6_tnl_fill_info(struct sk_b + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || +- nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark)) ++ nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark) || ++ !(fmrs = nla_nest_start(skb, IFLA_IPTUN_FMRS))) + goto nla_put_failure; + ++ for (c = parm->fmrs; c; c = c->next) { ++ struct nlattr *fmr = nla_nest_start(skb, ++fmrcnt); ++ if (!fmr || ++ nla_put(skb, IFLA_IPTUN_FMR_IP6_PREFIX, ++ sizeof(c->ip6_prefix), &c->ip6_prefix) || ++ nla_put(skb, IFLA_IPTUN_FMR_IP4_PREFIX, ++ sizeof(c->ip4_prefix), &c->ip4_prefix) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, c->ip6_prefix_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, c->ip4_prefix_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_EA_LEN, c->ea_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_OFFSET, c->offset)) ++ goto nla_put_failure; ++ ++ nla_nest_end(skb, fmr); ++ } ++ nla_nest_end(skb, fmrs); ++ + if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || +@@ -2172,6 +2436,7 @@ static const struct nla_policy ip6_tnl_p + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, ++ [IFLA_IPTUN_FMRS] = { .type = NLA_NESTED }, + }; + + static struct rtnl_link_ops ip6_link_ops __read_mostly = { diff --git a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch new file mode 100644 index 0000000000..72e8de2f1d --- /dev/null +++ b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -0,0 +1,263 @@ +From: Jonas Gorski +Subject: ipv6: allow rejecting with "source address failed policy" + +RFC6204 L-14 requires rejecting traffic from invalid addresses with +ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/ +egress policy) on the LAN side, so add an appropriate rule for that. + +Signed-off-by: Jonas Gorski +--- + include/net/netns/ipv6.h | 1 + + include/uapi/linux/fib_rules.h | 4 +++ + include/uapi/linux/rtnetlink.h | 1 + + net/ipv4/fib_semantics.c | 4 +++ + net/ipv4/fib_trie.c | 1 + + net/ipv4/ipmr.c | 1 + + net/ipv6/fib6_rules.c | 4 +++ + net/ipv6/ip6mr.c | 2 ++ + net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++- + 9 files changed, 75 insertions(+), 1 deletion(-) + +--- a/include/net/netns/ipv6.h ++++ b/include/net/netns/ipv6.h +@@ -85,6 +85,7 @@ struct netns_ipv6 { + unsigned int fib6_routes_require_src; + #endif + struct rt6_info *ip6_prohibit_entry; ++ struct rt6_info *ip6_policy_failed_entry; + struct rt6_info *ip6_blk_hole_entry; + struct fib6_table *fib6_local_tbl; + struct fib_rules_ops *fib6_rules_ops; +--- a/include/uapi/linux/fib_rules.h ++++ b/include/uapi/linux/fib_rules.h +@@ -82,6 +82,10 @@ enum { + FR_ACT_BLACKHOLE, /* Drop without notification */ + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT, /* Drop with EACCES */ ++ FR_ACT_RES9, ++ FR_ACT_RES10, ++ FR_ACT_RES11, ++ FR_ACT_POLICY_FAILED, /* Drop with EACCES */ + __FR_ACT_MAX, + }; + +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -265,6 +265,7 @@ enum { + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ ++ RTN_POLICY_FAILED, /* Failed ingress/egress policy */ + __RTN_MAX + }; + +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -145,6 +145,10 @@ const struct fib_prop fib_props[RTN_MAX + .error = -EINVAL, + .scope = RT_SCOPE_NOWHERE, + }, ++ [RTN_POLICY_FAILED] = { ++ .error = -EACCES, ++ .scope = RT_SCOPE_UNIVERSE, ++ }, + }; + + static void rt_fibinfo_free(struct rtable __rcu **rtp) +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -2783,6 +2783,7 @@ static const char *const rtn_type_names[ + [RTN_THROW] = "THROW", + [RTN_NAT] = "NAT", + [RTN_XRESOLVE] = "XRESOLVE", ++ [RTN_POLICY_FAILED] = "POLICY_FAILED", + }; + + static inline const char *rtn_type(char *buf, size_t len, unsigned int t) +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -180,6 +180,7 @@ static int ipmr_rule_action(struct fib_r + case FR_ACT_UNREACHABLE: + return -ENETUNREACH; + case FR_ACT_PROHIBIT: ++ case FR_ACT_POLICY_FAILED: + return -EACCES; + case FR_ACT_BLACKHOLE: + default: +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -221,6 +221,10 @@ static int __fib6_rule_action(struct fib + err = -EACCES; + rt = net->ipv6.ip6_prohibit_entry; + goto discard_pkt; ++ case FR_ACT_POLICY_FAILED: ++ err = -EACCES; ++ rt = net->ipv6.ip6_policy_failed_entry; ++ goto discard_pkt; + } + + tb_id = fib_rule_get_table(rule, arg); +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -170,6 +170,8 @@ static int ip6mr_rule_action(struct fib_ + return -ENETUNREACH; + case FR_ACT_PROHIBIT: + return -EACCES; ++ case FR_ACT_POLICY_FAILED: ++ return -EACCES; + case FR_ACT_BLACKHOLE: + default: + return -EINVAL; +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -97,6 +97,8 @@ static int ip6_pkt_discard(struct sk_bu + static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); + static int ip6_pkt_prohibit(struct sk_buff *skb); + static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); ++static int ip6_pkt_policy_failed(struct sk_buff *skb); ++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb); + static void ip6_link_failure(struct sk_buff *skb); + static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu, +@@ -317,6 +319,18 @@ static const struct rt6_info ip6_prohibi + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), + }; + ++static const struct rt6_info ip6_policy_failed_entry_template = { ++ .dst = { ++ .__refcnt = ATOMIC_INIT(1), ++ .__use = 1, ++ .obsolete = DST_OBSOLETE_FORCE_CHK, ++ .error = -EACCES, ++ .input = ip6_pkt_policy_failed, ++ .output = ip6_pkt_policy_failed_out, ++ }, ++ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), ++}; ++ + static const struct rt6_info ip6_blk_hole_entry_template = { + .dst = { + .__refcnt = ATOMIC_INIT(1), +@@ -1039,6 +1053,7 @@ static const int fib6_prop[RTN_MAX + 1] + [RTN_BLACKHOLE] = -EINVAL, + [RTN_UNREACHABLE] = -EHOSTUNREACH, + [RTN_PROHIBIT] = -EACCES, ++ [RTN_POLICY_FAILED] = -EACCES, + [RTN_THROW] = -EAGAIN, + [RTN_NAT] = -EINVAL, + [RTN_XRESOLVE] = -EINVAL, +@@ -1074,6 +1089,10 @@ static void ip6_rt_init_dst_reject(struc + rt->dst.output = ip6_pkt_prohibit_out; + rt->dst.input = ip6_pkt_prohibit; + break; ++ case RTN_POLICY_FAILED: ++ rt->dst.output = ip6_pkt_policy_failed_out; ++ rt->dst.input = ip6_pkt_policy_failed; ++ break; + case RTN_THROW: + case RTN_UNREACHABLE: + default: +@@ -4540,6 +4559,17 @@ static int ip6_pkt_prohibit_out(struct n + return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); + } + ++static int ip6_pkt_policy_failed(struct sk_buff *skb) ++{ ++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES); ++} ++ ++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb) ++{ ++ skb->dev = skb_dst(skb)->dev; ++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES); ++} ++ + /* + * Allocate a dst for local (unicast / anycast) address. + */ +@@ -5033,7 +5063,8 @@ static int rtm_to_fib6_config(struct sk_ + if (rtm->rtm_type == RTN_UNREACHABLE || + rtm->rtm_type == RTN_BLACKHOLE || + rtm->rtm_type == RTN_PROHIBIT || +- rtm->rtm_type == RTN_THROW) ++ rtm->rtm_type == RTN_THROW || ++ rtm->rtm_type == RTN_POLICY_FAILED) + cfg->fc_flags |= RTF_REJECT; + + if (rtm->rtm_type == RTN_LOCAL) +@@ -6287,6 +6318,8 @@ static int ip6_route_dev_notify(struct n + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + net->ipv6.ip6_prohibit_entry->dst.dev = dev; + net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); ++ net->ipv6.ip6_policy_failed_entry->dst.dev = dev; ++ net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev); + net->ipv6.ip6_blk_hole_entry->dst.dev = dev; + net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); + #endif +@@ -6298,6 +6331,7 @@ static int ip6_route_dev_notify(struct n + in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); ++ in6_dev_put_clear(&net->ipv6.ip6_policy_failed_entry->rt6i_idev); + in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); + #endif + } +@@ -6489,6 +6523,8 @@ static int __net_init ip6_route_net_init + + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + net->ipv6.fib6_has_custom_rules = false; ++ ++ + net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, + sizeof(*net->ipv6.ip6_prohibit_entry), + GFP_KERNEL); +@@ -6499,11 +6535,21 @@ static int __net_init ip6_route_net_init + ip6_template_metrics, true); + INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); + ++ net->ipv6.ip6_policy_failed_entry = ++ kmemdup(&ip6_policy_failed_entry_template, ++ sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL); ++ if (!net->ipv6.ip6_policy_failed_entry) ++ goto out_ip6_prohibit_entry; ++ net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; ++ dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, ++ ip6_template_metrics, true); ++ INIT_LIST_HEAD(&net->ipv6.ip6_policy_failed_entry->rt6i_uncached); ++ + net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, + sizeof(*net->ipv6.ip6_blk_hole_entry), + GFP_KERNEL); + if (!net->ipv6.ip6_blk_hole_entry) +- goto out_ip6_prohibit_entry; ++ goto out_ip6_policy_failed_entry; + net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, + ip6_template_metrics, true); +@@ -6530,6 +6576,8 @@ out: + return ret; + + #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++out_ip6_policy_failed_entry: ++ kfree(net->ipv6.ip6_policy_failed_entry); + out_ip6_prohibit_entry: + kfree(net->ipv6.ip6_prohibit_entry); + out_ip6_null_entry: +@@ -6549,6 +6597,7 @@ static void __net_exit ip6_route_net_exi + kfree(net->ipv6.ip6_null_entry); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + kfree(net->ipv6.ip6_prohibit_entry); ++ kfree(net->ipv6.ip6_policy_failed_entry); + kfree(net->ipv6.ip6_blk_hole_entry); + #endif + dst_entries_destroy(&net->ipv6.ip6_dst_ops); +@@ -6632,6 +6681,9 @@ void __init ip6_route_init_special_entri + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); ++ init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev; ++ init_net.ipv6.ip6_policy_failed_entry->rt6i_idev = ++ in6_dev_get(init_net.loopback_dev); + #endif + } + diff --git a/target/linux/generic/pending-6.6/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/target/linux/generic/pending-6.6/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch new file mode 100644 index 0000000000..94416a5d70 --- /dev/null +++ b/target/linux/generic/pending-6.6/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch @@ -0,0 +1,50 @@ +From: Jonas Gorski +Subject: net: provide defines for _POLICY_FAILED until all code is updated + +Upstream introduced ICMPV6_POLICY_FAIL for code 5 of destination +unreachable, conflicting with our name. + +Add appropriate defines to allow our code to build with the new +name until we have updated our local patches for older kernels +and userspace packages. + +Signed-off-by: Jonas Gorski +--- + include/uapi/linux/fib_rules.h | 2 ++ + include/uapi/linux/icmpv6.h | 2 ++ + include/uapi/linux/rtnetlink.h | 2 ++ + 3 files changed, 6 insertions(+) + +--- a/include/uapi/linux/fib_rules.h ++++ b/include/uapi/linux/fib_rules.h +@@ -89,6 +89,8 @@ enum { + __FR_ACT_MAX, + }; + ++#define FR_ACT_FAILED_POLICY FR_ACT_POLICY_FAILED ++ + #define FR_ACT_MAX (__FR_ACT_MAX - 1) + + #endif +--- a/include/uapi/linux/icmpv6.h ++++ b/include/uapi/linux/icmpv6.h +@@ -126,6 +126,8 @@ struct icmp6hdr { + #define ICMPV6_POLICY_FAIL 5 + #define ICMPV6_REJECT_ROUTE 6 + ++#define ICMPV6_FAILED_POLICY ICMPV6_POLICY_FAIL ++ + /* + * Codes for Time Exceeded + */ +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -269,6 +269,8 @@ enum { + __RTN_MAX + }; + ++#define RTN_FAILED_POLICY RTN_POLICY_FAILED ++ + #define RTN_MAX (__RTN_MAX - 1) + + diff --git a/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch new file mode 100644 index 0000000000..11850c0418 --- /dev/null +++ b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -0,0 +1,151 @@ +From: Felix Fietkau +Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses + +Signed-off-by: Felix Fietkau +--- + include/linux/netdevice.h | 2 ++ + include/linux/skbuff.h | 3 ++- + net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ + net/ethernet/eth.c | 18 +++++++++++++++++- + 4 files changed, 69 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2157,6 +2157,8 @@ struct net_device { + struct netdev_hw_addr_list mc; + struct netdev_hw_addr_list dev_addrs; + ++ unsigned char local_addr_mask[MAX_ADDR_LEN]; ++ + #ifdef CONFIG_SYSFS + struct kset *queues_kset; + #endif +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -972,6 +972,7 @@ struct sk_buff { + #ifdef CONFIG_IPV6_NDISC_NODETYPE + __u8 ndisc_nodetype:2; + #endif ++ __u8 gro_skip:1; + + __u8 ipvs_property:1; + __u8 inner_protocol_type:1; +--- a/net/core/gro.c ++++ b/net/core/gro.c +@@ -491,6 +491,9 @@ static enum gro_result dev_gro_receive(s + int same_flow; + int grow; + ++ if (skb->gro_skip) ++ goto normal; ++ + if (netif_elide_gro(skb->dev)) + goto normal; + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -7625,6 +7625,48 @@ static void __netdev_adjacent_dev_unlink + &upper_dev->adj_list.lower); + } + ++static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr, ++ struct net_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < dev->addr_len; i++) ++ mask[i] |= addr[i] ^ dev->dev_addr[i]; ++} ++ ++static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev, ++ struct net_device *lower) ++{ ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ netdev_for_each_upper_dev_rcu(dev, cur, iter) { ++ __netdev_addr_mask(mask, cur->dev_addr, lower); ++ __netdev_upper_mask(mask, cur, lower); ++ } ++} ++ ++static void __netdev_update_addr_mask(struct net_device *dev) ++{ ++ unsigned char mask[MAX_ADDR_LEN]; ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ memset(mask, 0, sizeof(mask)); ++ __netdev_upper_mask(mask, dev, dev); ++ memcpy(dev->local_addr_mask, mask, dev->addr_len); ++ ++ netdev_for_each_lower_dev(dev, cur, iter) ++ __netdev_update_addr_mask(cur); ++} ++ ++static void netdev_update_addr_mask(struct net_device *dev) ++{ ++ rcu_read_lock(); ++ __netdev_update_addr_mask(dev); ++ rcu_read_unlock(); ++} ++ + static int __netdev_upper_dev_link(struct net_device *dev, + struct net_device *upper_dev, bool master, + void *upper_priv, void *upper_info, +@@ -7676,6 +7718,7 @@ static int __netdev_upper_dev_link(struc + if (ret) + return ret; + ++ netdev_update_addr_mask(dev); + ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + ret = notifier_to_errno(ret); +@@ -7772,6 +7815,7 @@ static void __netdev_upper_dev_unlink(st + + __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); + ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + +@@ -8824,6 +8868,7 @@ int dev_set_mac_address(struct net_devic + if (err) + return err; + dev->addr_assign_type = NET_ADDR_SET; ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); + return 0; +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -143,6 +143,18 @@ u32 eth_get_headlen(const struct net_dev + } + EXPORT_SYMBOL(eth_get_headlen); + ++static inline bool ++eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) ++{ ++ const u16 *a1 = addr1; ++ const u16 *a2 = addr2; ++ const u16 *m = mask; ++ ++ return (((a1[0] ^ a2[0]) & ~m[0]) | ++ ((a1[1] ^ a2[1]) & ~m[1]) | ++ ((a1[2] ^ a2[2]) & ~m[2])); ++} ++ + /** + * eth_type_trans - determine the packet's protocol ID. + * @skb: received socket data +@@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk + } else { + skb->pkt_type = PACKET_OTHERHOST; + } ++ ++ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, ++ dev->local_addr_mask)) ++ skb->gro_skip = 1; + } + + /* diff --git a/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch new file mode 100644 index 0000000000..03ee537fb8 --- /dev/null +++ b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch @@ -0,0 +1,75 @@ +From 8585756342caa6d27008d1ad0c18023e4211a40a Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 12:22:48 +0200 +Subject: [PATCH] of/of_net: write back netdev MAC-address to device-tree + +The label-mac logic relies on the mac-address property of a netdev +devices of-node. However, the mac address can also be stored as a +different property or read from e.g. an mtd device. + +Create this node when reading a mac-address from OF if it does not +already exist and copy the mac-address used for the device to this +property. This way, the MAC address can be accessed using procfs. + +--- + net/core/of_net.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/net/core/of_net.c ++++ b/net/core/of_net.c +@@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct + return 0; + } + ++static int of_add_mac_address(struct device_node *np, u8* addr) ++{ ++ struct property *prop; ++ ++ prop = kzalloc(sizeof(*prop), GFP_KERNEL); ++ if (!prop) ++ return -ENOMEM; ++ ++ prop->name = "mac-address"; ++ prop->length = ETH_ALEN; ++ prop->value = kmemdup(addr, ETH_ALEN, GFP_KERNEL); ++ if (!prop->value || of_update_property(np, prop)) ++ goto free; ++ ++ return 0; ++free: ++ kfree(prop->value); ++ kfree(prop); ++ return -ENOMEM; ++} ++ + /** + * of_get_mac_address() + * @np: Caller's Device Node +@@ -130,17 +151,23 @@ int of_get_mac_address(struct device_nod + + ret = of_get_mac_addr(np, "mac-address", addr); + if (!ret) +- return 0; ++ goto found; + + ret = of_get_mac_addr(np, "local-mac-address", addr); + if (!ret) +- return 0; ++ goto found; + + ret = of_get_mac_addr(np, "address", addr); + if (!ret) +- return 0; ++ goto found; + +- return of_get_mac_addr_nvmem(np, addr); ++ ret = of_get_mac_addr_nvmem(np, addr); ++ if (ret) ++ return ret; ++ ++found: ++ ret = of_add_mac_address(np, addr); ++ return ret; + } + EXPORT_SYMBOL(of_get_mac_address); + diff --git a/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch new file mode 100644 index 0000000000..b335748705 --- /dev/null +++ b/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -0,0 +1,110 @@ +From: Pablo Neira Ayuso +Date: Thu, 25 Jan 2018 12:58:55 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from + nf_flow_table + +Move the code that deals with device events to the core. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -659,6 +659,23 @@ static struct pernet_operations nf_flow_ + .exit_batch = nf_flow_table_pernet_exit, + }; + ++static int nf_flow_table_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++ nf_flow_table_cleanup(dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = nf_flow_table_netdev_event, ++}; ++ + static int __init nf_flow_table_module_init(void) + { + int ret; +@@ -671,8 +688,14 @@ static int __init nf_flow_table_module_i + if (ret) + goto out_offload; + ++ ret = register_netdevice_notifier(&flow_offload_netdev_notifier); ++ if (ret) ++ goto out_offload_init; ++ + return 0; + ++out_offload_init: ++ nf_flow_table_offload_exit(); + out_offload: + unregister_pernet_subsys(&nf_flow_table_net_ops); + return ret; +@@ -680,6 +703,7 @@ out_offload: + + static void __exit nf_flow_table_module_exit(void) + { ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); + nf_flow_table_offload_exit(); + unregister_pernet_subsys(&nf_flow_table_net_ops); + } +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -479,47 +479,14 @@ static struct nft_expr_type nft_flow_off + .owner = THIS_MODULE, + }; + +-static int flow_offload_netdev_event(struct notifier_block *this, +- unsigned long event, void *ptr) +-{ +- struct net_device *dev = netdev_notifier_info_to_dev(ptr); +- +- if (event != NETDEV_DOWN) +- return NOTIFY_DONE; +- +- nf_flow_table_cleanup(dev); +- +- return NOTIFY_DONE; +-} +- +-static struct notifier_block flow_offload_netdev_notifier = { +- .notifier_call = flow_offload_netdev_event, +-}; +- + static int __init nft_flow_offload_module_init(void) + { +- int err; +- +- err = register_netdevice_notifier(&flow_offload_netdev_notifier); +- if (err) +- goto err; +- +- err = nft_register_expr(&nft_flow_offload_type); +- if (err < 0) +- goto register_expr; +- +- return 0; +- +-register_expr: +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); +-err: +- return err; ++ return nft_register_expr(&nft_flow_offload_type); + } + + static void __exit nft_flow_offload_module_exit(void) + { + nft_unregister_expr(&nft_flow_offload_type); +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); + } + + module_init(nft_flow_offload_module_init); diff --git a/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch new file mode 100644 index 0000000000..757c0b2449 --- /dev/null +++ b/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Thu, 31 Aug 2023 21:48:38 +0200 +Subject: [PATCH] netfilter: nf_tables: ignore -EOPNOTSUPP on flowtable device + offload setup + +On many embedded devices, it is common to configure flowtable offloading for +a mix of different devices, some of which have hardware offload support and +some of which don't. +The current code limits the ability of user space to properly set up such a +configuration by only allowing adding devices with hardware offload support to +a offload-enabled flowtable. +Given that offload-enabled flowtables also imply fallback to pure software +offloading, this limitation makes little sense. +Fix it by not bailing out when the offload setup returns -EOPNOTSUPP + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7911,7 +7911,7 @@ static int nft_register_flowtable_net_ho + err = flowtable->data.type->setup(&flowtable->data, + hook->ops.dev, + FLOW_BLOCK_BIND); +- if (err < 0) ++ if (err < 0 && err != -EOPNOTSUPP) + goto err_unregister_net_hooks; + + err = nf_register_net_hook(net, &hook->ops); diff --git a/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch new file mode 100644 index 0000000000..842fef3a9c --- /dev/null +++ b/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -0,0 +1,21 @@ +From: Felix Fietkau +Date: Mon, 21 Mar 2022 20:39:59 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: enable threaded NAPI + +This can improve performance under load by ensuring that NAPI processing is +not pinned on CPU 0. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4941,6 +4941,8 @@ static int mtk_probe(struct platform_dev + * for NAPI to work + */ + init_dummy_netdev(ð->dummy_dev); ++ eth->dummy_dev.threaded = 1; ++ strcpy(eth->dummy_dev.name, "mtk_eth"); + netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx); + netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx); + diff --git a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch new file mode 100644 index 0000000000..e4937a1df1 --- /dev/null +++ b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -0,0 +1,38 @@ +From: Gabor Juhos +Subject: generic: add detach callback to struct phy_driver + +lede-commit: fe61fc2d7d0b3fb348b502f68f98243b3ddf5867 + +Signed-off-by: Gabor Juhos +--- + drivers/net/phy/phy_device.c | 3 +++ + include/linux/phy.h | 6 ++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1850,6 +1850,9 @@ void phy_detach(struct phy_device *phyde + struct module *ndev_owner = NULL; + struct mii_bus *bus; + ++ if (phydev->drv && phydev->drv->detach) ++ phydev->drv->detach(phydev); ++ + if (phydev->sysfs_links) { + if (dev) + sysfs_remove_link(&dev->dev.kobj, "phydev"); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -900,6 +900,12 @@ struct phy_driver { + /** @handle_interrupt: Override default interrupt handling */ + irqreturn_t (*handle_interrupt)(struct phy_device *phydev); + ++ /* ++ * Called before an ethernet device is detached ++ * from the PHY. ++ */ ++ void (*detach)(struct phy_device *phydev); ++ + /** @remove: Clears up any memory if needed */ + void (*remove)(struct phy_device *phydev); + diff --git a/target/linux/generic/pending-6.6/704-netfilter-nf_tables-fix-bidirectional-offload-regres.patch b/target/linux/generic/pending-6.6/704-netfilter-nf_tables-fix-bidirectional-offload-regres.patch new file mode 100644 index 0000000000..d1d6fa3fe1 --- /dev/null +++ b/target/linux/generic/pending-6.6/704-netfilter-nf_tables-fix-bidirectional-offload-regres.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Wed, 14 Feb 2024 15:24:41 +0100 +Subject: [PATCH] netfilter: nf_tables: fix bidirectional offload regression + +Commit 8f84780b84d6 ("netfilter: flowtable: allow unidirectional rules") +made unidirectional flow offload possible, while completely ignoring (and +breaking) bidirectional flow offload for nftables. +Add the missing flag that was left out as an exercise for the reader :) + +Cc: Vlad Buslov +Fixes: 8f84780b84d6 ("netfilter: flowtable: allow unidirectional rules") +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -361,6 +361,7 @@ static void nft_flow_offload_eval(const + ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; + } + ++ __set_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags); + ret = flow_offload_add(flowtable, flow); + if (ret < 0) + goto err_flow_add; diff --git a/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch b/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch new file mode 100644 index 0000000000..d444b2027c --- /dev/null +++ b/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch @@ -0,0 +1,28 @@ +From: Felix Fietkau +Date: Fri, 6 May 2022 21:38:42 +0200 +Subject: [PATCH] net: dsa: tag_mtk: add padding for tx packets + +Padding for transmitted packets needs to account for the special tag. +With not enough padding, garbage bytes are inserted by the switch at the +end of small packets. + +Fixes: 5cd8985a1909 ("net-next: dsa: add Mediatek tag RX/TX handler") +Signed-off-by: Felix Fietkau +--- + +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -27,6 +27,13 @@ static struct sk_buff *mtk_tag_xmit(stru + + skb_set_queue_mapping(skb, dp->index); + ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise their padding might be ++ * corrupted. With tags enabled, we need to make sure that packets are ++ * at least 68 bytes (including FCS and tag). ++ */ ++ eth_skb_pad(skb); ++ + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is + * being combined. Only in this way we can allow the switch can parse diff --git a/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch new file mode 100644 index 0000000000..989aca8f35 --- /dev/null +++ b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -0,0 +1,174 @@ +From: Felix Fietkau +Date: Fri, 27 Aug 2021 12:22:32 +0200 +Subject: [PATCH] bridge: add knob for filtering rx/tx BPDU packets on a port + +Some devices (e.g. wireless APs) can't have devices behind them be part of +a bridge topology with redundant links, due to address limitations. +Additionally, broadcast traffic on these devices is somewhat expensive, due to +the low data rate and wakeups of clients in powersave mode. +This knob can be used to ensure that BPDU packets are never sent or forwarded +to/from these devices + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -59,6 +59,7 @@ struct br_ip_list { + #define BR_MRP_LOST_IN_CONT BIT(19) + #define BR_TX_FWD_OFFLOAD BIT(20) + #define BR_PORT_LOCKED BIT(21) ++#define BR_BPDU_FILTER BIT(22) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -199,6 +199,7 @@ out: + void br_flood(struct net_bridge *br, struct sk_buff *skb, + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) + { ++ const unsigned char *dest = eth_hdr(skb)->h_dest; + struct net_bridge_port *prev = NULL; + struct net_bridge_port *p; + +@@ -214,6 +215,10 @@ void br_flood(struct net_bridge *br, str + case BR_PKT_MULTICAST: + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; ++ if ((p->flags & BR_BPDU_FILTER) && ++ unlikely(is_link_local_ether_addr(dest) && ++ dest[5] == 0)) ++ continue; + break; + case BR_PKT_BROADCAST: + if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -344,6 +344,8 @@ static rx_handler_result_t br_handle_fra + fwd_mask |= p->group_fwd_mask; + switch (dest[5]) { + case 0x00: /* Bridge Group Address */ ++ if (p->flags & BR_BPDU_FILTER) ++ goto drop; + /* If STP is turned off, + then must forward to keep loop detection */ + if (p->br->stp_enabled == BR_NO_STP || +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -240,6 +240,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA + BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); + BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); + BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ++BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -292,6 +293,7 @@ static const struct brport_attribute *br + &brport_attr_group_fwd_mask, + &brport_attr_neigh_suppress, + &brport_attr_isolated, ++ &brport_attr_bpdu_filter, + &brport_attr_backup_port, + NULL + }; +--- a/net/bridge/br_stp_bpdu.c ++++ b/net/bridge/br_stp_bpdu.c +@@ -80,7 +80,8 @@ void br_send_config_bpdu(struct net_brid + { + unsigned char buf[35]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -127,7 +128,8 @@ void br_send_tcn_bpdu(struct net_bridge_ + { + unsigned char buf[4]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -172,6 +174,9 @@ void br_stp_rcv(const struct stp_proto * + if (!(br->dev->flags & IFF_UP)) + goto out; + ++ if (p->flags & BR_BPDU_FILTER) ++ goto out; ++ + if (p->state == BR_STATE_DISABLED) + goto out; + +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -561,6 +561,7 @@ enum { + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, + IFLA_BRPORT_LOCKED, ++ IFLA_BRPORT_BPDU_FILTER, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -188,6 +188,7 @@ static inline size_t br_port_info_size(v + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ + + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ + + nla_total_size(1) /* IFLA_BRPORT_LOCKED */ ++ + nla_total_size(1) /* IFLA_BRPORT_BPDU_FILTER */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ +@@ -274,7 +275,8 @@ static int br_port_fill_attrs(struct sk_ + nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN, + !!(p->flags & BR_MRP_LOST_IN_CONT)) || + nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) || +- nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED))) ++ nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) || ++ nla_put_u8(skb, IFLA_BRPORT_BPDU_FILTER, !!(p->flags & BR_BPDU_FILTER))) + return -EMSGSIZE; + + timerval = br_timer_value(&p->message_age_timer); +@@ -878,6 +880,7 @@ static const struct nla_policy br_port_p + [IFLA_BRPORT_LOCKED] = { .type = NLA_U8 }, + [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, + [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 }, ++ [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, + }; + + /* Change the state of the port and notify spanning tree */ +@@ -943,6 +946,7 @@ static int br_setport(struct net_bridge_ + br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS); + br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); + br_set_port_flag(p, tb, IFLA_BRPORT_LOCKED, BR_PORT_LOCKED); ++ br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); + + changed_mask = old_flags ^ p->flags; + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -57,7 +57,7 @@ + #include "dev.h" + + #define RTNL_MAX_TYPE 50 +-#define RTNL_SLAVE_MAX_TYPE 40 ++#define RTNL_SLAVE_MAX_TYPE 41 + + struct rtnl_link { + rtnl_doit_func doit; +@@ -4840,7 +4840,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu + brport_nla_put_flag(skb, flags, mask, + IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || + brport_nla_put_flag(skb, flags, mask, +- IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD)) { ++ IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD) || ++ brport_nla_put_flag(skb, flags, mask, ++ IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER)) { + nla_nest_cancel(skb, protinfo); + goto nla_put_failure; + } diff --git a/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch new file mode 100644 index 0000000000..629b141572 --- /dev/null +++ b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch @@ -0,0 +1,86 @@ +From 3b4329230db8750bea7a56ef07f07cbbf5fc6c5a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 4 Jul 2023 22:50:12 +0200 +Subject: [PATCH 19/20] net: dsa: qca8k: implement lag_fdb_add/del ops + +Implement lag_fdb_add/del ops to correctly support using LAG interface. +Qca8k switch supports declaring fdb entry for link aggregation by simply +setting the DES_PORT bits to all the LAG member. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 2 ++ + drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 6 ++++ + 3 files changed, 56 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -2015,6 +2015,8 @@ static const struct dsa_switch_ops qca8k + .port_fdb_add = qca8k_port_fdb_add, + .port_fdb_del = qca8k_port_fdb_del, + .port_fdb_dump = qca8k_port_fdb_dump, ++ .lag_fdb_add = qca8k_lag_fdb_add, ++ .lag_fdb_del = qca8k_lag_fdb_del, + .port_mdb_add = qca8k_port_mdb_add, + .port_mdb_del = qca8k_port_mdb_del, + .port_mirror_add = qca8k_port_mirror_add, +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit + return qca8k_lag_refresh_portmap(ds, port, lag, true); + } + ++int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ struct dsa_port *dp; ++ u16 port_mask = 0; ++ ++ /* Set the vid to the port vlan id if no vid is set */ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ dsa_lag_foreach_port(dp, ds->dst, &lag) ++ port_mask |= BIT(dp->index); ++ ++ return qca8k_port_fdb_insert(priv, addr, port_mask, vid); ++} ++ ++int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ struct dsa_port *dp; ++ u16 port_mask = 0; ++ ++ /* Set the vid to the port vlan id if no vid is set */ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ dsa_lag_foreach_port(dp, ds->dst, &lag) ++ port_mask |= BIT(dp->index); ++ ++ return qca8k_fdb_del(priv, addr, port_mask, vid); ++} ++ + int qca8k_read_switch_id(struct qca8k_priv *priv) + { + u32 val; +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc + struct netlink_ext_ack *extack); + int qca8k_port_lag_leave(struct dsa_switch *ds, int port, + struct dsa_lag lag); ++int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db); ++int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db); + + #endif /* __QCA8K_H */ diff --git a/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch b/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch new file mode 100644 index 0000000000..24243468a8 --- /dev/null +++ b/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch @@ -0,0 +1,37 @@ +From b954d61d9ecfa64450fc178586719dc2a95b92a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 20 Jun 2023 21:48:24 +0200 +Subject: [PATCH 3/4] net: dsa: qca8k: enable flooding to both CPU port + +To permit a multi-CPU setup, flood all unknown frames to all CPU ports. +Each CPU port should have correct LOOKUP MEMBER configuration to +prevent receiving duplicate packets from user ports. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1904,15 +1904,12 @@ qca8k_setup(struct dsa_switch *ds) + } + } + +- /* Forward all unknown frames to CPU port for Linux processing +- * Notice that in multi-cpu config only one port should be set +- * for igmp, unknown, multicast and broadcast packet +- */ ++ /* Forward all unknown frames to CPU port for Linux processing */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(cpu_port))); ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, dsa_cpu_ports(ds))); + if (ret) + return ret; + diff --git a/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch b/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch new file mode 100644 index 0000000000..8a58e0f76e --- /dev/null +++ b/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch @@ -0,0 +1,158 @@ +From b2d6ebf2f92f8695c83fa6979f4ab579c588df76 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 20 Jun 2023 07:57:38 +0200 +Subject: [PATCH 4/4] net: dsa: qca8k: add support for port_change_master + +Add support for port_change_master to permit assigning an alternative +CPU port if the switch have both CPU port connected or create a LAG on +both CPU port and assign the LAG as DSA master. + +On port change master request, we check if the master is a LAG. +With LAG we compose the cpu_port_mask with the CPU port in the LAG, if +master is a simple dsa_port, we derive the index. + +Finally we apply the new cpu_port_mask to the LOOKUP MEMBER to permit +the port to receive packet by the new CPU port setup for the port and we +refresh the CPU ports LOOKUP MEMBER configuration to reflect the new +user port state. + +port_lag_join/leave is updated to refresh the user ports if we detect +that the LAG is a DSA master and we have user port using it as a master. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 116 ++++++++++++++++++++++++++++++- + 1 file changed, 114 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1741,6 +1741,117 @@ qca8k_get_tag_protocol(struct dsa_switch + return DSA_TAG_PROTO_QCA; + } + ++static int qca8k_port_change_master(struct dsa_switch *ds, int port, ++ struct net_device *master, ++ struct netlink_ext_ack *extack) ++{ ++ struct dsa_switch_tree *dst = ds->dst; ++ struct qca8k_priv *priv = ds->priv; ++ u8 cpu_port_mask = 0; ++ struct dsa_port *dp; ++ u32 val; ++ int ret; ++ ++ /* With LAG of CPU port, compose the mask for port LOOKUP MEMBER */ ++ if (netif_is_lag_master(master)) { ++ struct dsa_lag *lag; ++ int id; ++ ++ id = dsa_lag_id(dst, master); ++ lag = dsa_lag_by_id(dst, id); ++ ++ dsa_lag_foreach_port(dp, dst, lag) ++ if (dsa_port_is_cpu(dp)) ++ cpu_port_mask |= BIT(dp->index); ++ } else { ++ dp = master->dsa_ptr; ++ cpu_port_mask |= BIT(dp->index); ++ } ++ ++ /* Connect port to new cpu port */ ++ ret = regmap_read(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), &val); ++ if (ret) ++ return ret; ++ ++ /* Reset connected CPU port in port LOOKUP MEMBER */ ++ val &= ~dsa_cpu_ports(ds); ++ /* Assign the new CPU port in port LOOKUP MEMBER */ ++ val |= cpu_port_mask; ++ ++ ret = regmap_update_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ val); ++ if (ret) ++ return ret; ++ ++ /* Refresh CPU port LOOKUP MEMBER with new port */ ++ dsa_tree_for_each_cpu_port(dp, ds->dst) { ++ u32 reg = QCA8K_PORT_LOOKUP_CTRL(dp->index); ++ ++ /* If CPU port in mask assign port, else remove port */ ++ if (BIT(dp->index) & cpu_port_mask) ++ ret = regmap_set_bits(priv->regmap, reg, BIT(port)); ++ else ++ ret = regmap_clear_bits(priv->regmap, reg, BIT(port)); ++ ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int qca8k_port_lag_refresh_user_ports(struct dsa_switch *ds, ++ struct dsa_lag lag) ++{ ++ struct net_device *lag_dev = lag.dev; ++ struct dsa_port *dp; ++ int ret; ++ ++ /* Ignore if LAG is not a DSA master */ ++ if (!netif_is_lag_master(lag_dev)) ++ return 0; ++ ++ dsa_switch_for_each_user_port(dp, ds) { ++ /* Skip if assigned master is not the LAG */ ++ if (dsa_port_to_master(dp) != lag_dev) ++ continue; ++ ++ ret = qca8k_port_change_master(ds, dp->index, ++ lag_dev, NULL); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int qca8xxx_port_lag_join(struct dsa_switch *ds, int port, ++ struct dsa_lag lag, ++ struct netdev_lag_upper_info *info, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ ret = qca8k_port_lag_join(ds, port, lag, info, extack); ++ if (ret) ++ return ret; ++ ++ return qca8k_port_lag_refresh_user_ports(ds, lag); ++} ++ ++static int qca8xxx_port_lag_leave(struct dsa_switch *ds, int port, ++ struct dsa_lag lag) ++{ ++ int ret; ++ ++ ret = qca8k_port_lag_leave(ds, port, lag); ++ if (ret) ++ return ret; ++ ++ return qca8k_port_lag_refresh_user_ports(ds, lag); ++} ++ + static void + qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, + bool operational) +@@ -2027,8 +2138,9 @@ static const struct dsa_switch_ops qca8k + .phylink_mac_link_down = qca8k_phylink_mac_link_down, + .phylink_mac_link_up = qca8k_phylink_mac_link_up, + .get_phy_flags = qca8k_get_phy_flags, +- .port_lag_join = qca8k_port_lag_join, +- .port_lag_leave = qca8k_port_lag_leave, ++ .port_lag_join = qca8xxx_port_lag_join, ++ .port_lag_leave = qca8xxx_port_lag_leave, ++ .port_change_master = qca8k_port_change_master, + .master_state_change = qca8k_master_change, + .connect_tag_protocol = qca8k_connect_tag_protocol, + }; diff --git a/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..23816fe366 --- /dev/null +++ b/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch @@ -0,0 +1,57 @@ +From 0f6599167c126ce32c85d4f8a1f3d1775a268572 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 6 Oct 2023 12:44:00 +0200 +Subject: [PATCH] net: dsa: qca8k: enable assisted learning on CPU port + +Enable assisted learning on CPU port. + +It has been verified that there is a problem in packet roaming +from one BSS to another in the same security settings from one +physical R7800 to another physical R7800 where they are in the +same L2 broadcast domain backhauled/linked together via one +of the ethernet ports. +DHCP will fail to complete and traffic cannot flow for around 300 +seconds. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -2013,6 +2013,12 @@ qca8k_setup(struct dsa_switch *ds) + dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); + return ret; + } ++ ++ /* Disable learning by default on all ports */ ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(dp->index), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; + } + + /* Forward all unknown frames to CPU port for Linux processing */ +@@ -2042,11 +2048,6 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_LEARN); +- if (ret) +- return ret; +- + /* For port based vlans to work we need to set the + * default egress vid + */ +@@ -2098,6 +2099,9 @@ qca8k_setup(struct dsa_switch *ds) + /* Set max number of LAGs supported */ + ds->num_lag_ids = QCA8K_NUM_LAGS; + ++ /* HW learn on CPU port is limited and require manual setting */ ++ ds->assisted_learning_on_cpu_port = true; ++ + return 0; + } + diff --git a/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch b/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch new file mode 100644 index 0000000000..55f116ec5f --- /dev/null +++ b/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch @@ -0,0 +1,25 @@ +From 3b5a603bf66236b956287909556fd7ad4904450c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:38:01 +0100 +Subject: [PATCH 3/3] arm64: dts: qcom: ipq8074: add clock-frequency to MDIO + node + +Add clock-frequency to MDIO node to set the MDC rate to 6.25Mhz instead +of using the default value of 390KHz from MDIO default divider. + +Signed-off-by: Christian Marangi +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -263,6 +263,8 @@ + clocks = <&gcc GCC_MDIO_AHB_CLK>; + clock-names = "gcc_mdio_ahb_clk"; + ++ clock-frequency = <6250000>; ++ + status = "disabled"; + }; + diff --git a/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch b/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch new file mode 100644 index 0000000000..ed13b004e4 --- /dev/null +++ b/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch @@ -0,0 +1,106 @@ +From ace6abaa0f9203083fe4c0a6a74da2d96410b625 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 12:49:33 +0200 +Subject: [PATCH 01/10] net: phy: realtek: rtl8221: allow to configure SERDES + mode + +The rtl8221 supports multiple SERDES modes: +- SGMII +- 2500base-x +- HiSGMII + +Further it supports rate adaption on SERDES links to allow +slow ethernet speeds (10/100/1000mbit) to work on 2500base-x/HiSGMII +links without reducing the SERDES speed. + +When operating without rate adapters the SERDES link will follow the +ethernet speed. + +Signed-off-by: Alexander Couzens +--- + drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -53,6 +53,15 @@ + RTL8201F_ISR_LINK) + #define RTL8201F_IER 0x13 + ++#define RTL8221B_MMD_SERDES_CTRL MDIO_MMD_VEND1 ++#define RTL8221B_MMD_PHY_CTRL MDIO_MMD_VEND2 ++#define RTL8221B_SERDES_OPTION 0x697a ++#define RTL8221B_SERDES_OPTION_MODE_MASK GENMASK(5, 0) ++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII 0 ++#define RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII 1 ++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 ++#define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + +@@ -851,6 +860,48 @@ static irqreturn_t rtl9000a_handle_inter + return IRQ_HANDLED; + } + ++static int rtl8221b_config_init(struct phy_device *phydev) ++{ ++ u16 option_mode; ++ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_2500BASEX: ++ if (!phydev->is_c45) { ++ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX; ++ break; ++ } ++ fallthrough; ++ case PHY_INTERFACE_MODE_SGMII: ++ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII; ++ break; ++ default: ++ return 0; ++ } ++ ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, ++ 0x75f3, 0); ++ ++ phy_modify_mmd_changed(phydev, RTL8221B_MMD_SERDES_CTRL, ++ RTL8221B_SERDES_OPTION, ++ RTL8221B_SERDES_OPTION_MODE_MASK, option_mode); ++ switch (option_mode) { ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; ++ } ++ ++ return 0; ++} ++ + static struct phy_driver realtek_drvs[] = { + { + PHY_ID_MATCH_EXACT(0x00008201), +@@ -1003,6 +1054,7 @@ static struct phy_driver realtek_drvs[] + PHY_ID_MATCH_EXACT(0x001cc849), + .name = "RTL8221B-VB-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, ++ .config_init = rtl8221b_config_init, + .config_aneg = rtl822x_config_aneg, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, +@@ -1014,6 +1066,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8221B-VM-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl8221b_config_init, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, diff --git a/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch b/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch new file mode 100644 index 0000000000..abe31e66af --- /dev/null +++ b/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch @@ -0,0 +1,61 @@ +From 312753d0aadba0f58841ae513b80fdbabc887523 Mon Sep 17 00:00:00 2001 +From: Chukun Pan +Date: Wed, 8 Feb 2023 16:32:18 +0800 +Subject: [PATCH] net: phy: realtek: support switching between SGMII and + 2500BASE-X for RTL822x series + +After commit ace6aba ("net: phy: realtek: rtl8221: allow to configure +SERDES mode"), the rtl8221 phy can work in SGMII and 2500base-x modes +respectively. So add interface automatic switching for rtl8221 phy to +match various wire speeds. + +Signed-off-by: Chukun Pan +--- + drivers/net/phy/realtek.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -686,6 +686,25 @@ static int rtl822x_config_aneg(struct ph + return __genphy_config_aneg(phydev, ret); + } + ++static void rtl822x_update_interface(struct phy_device *phydev) ++{ ++ /* Automatically switch SERDES interface between ++ * SGMII and 2500-BaseX according to speed. ++ */ ++ switch (phydev->speed) { ++ case SPEED_2500: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ case SPEED_1000: ++ case SPEED_100: ++ case SPEED_10: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ default: ++ break; ++ } ++} ++ + static int rtl822x_read_status(struct phy_device *phydev) + { + int ret; +@@ -704,11 +723,14 @@ static int rtl822x_read_status(struct ph + phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); + } + +- ret = genphy_read_status(phydev); ++ ret = rtlgen_read_status(phydev); + if (ret < 0) + return ret; + +- return rtlgen_get_speed(phydev); ++ if (phydev->is_c45 && phydev->link) ++ rtl822x_update_interface(phydev); ++ ++ return 0; + } + + static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) diff --git a/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch new file mode 100644 index 0000000000..a18d1ad717 --- /dev/null +++ b/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch @@ -0,0 +1,28 @@ +From 3fb8841513c4ec3a2e5d366df86230c45f239a57 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 13:08:22 +0200 +Subject: [PATCH 03/10] net: mt7531: ensure all MACs are powered down before + reset + +The datasheet [1] explicit describes it as requirement for a reset. + +[1] MT7531 Reference Manual for Development Board rev 1.0, page 735 + +Signed-off-by: Alexander Couzens +--- + drivers/net/dsa/mt7530.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2252,6 +2252,10 @@ mt7530_setup(struct dsa_switch *ds) + return -ENODEV; + } + ++ /* all MACs must be forced link-down before sw reset */ ++ for (i = 0; i < MT7530_NUM_PORTS; i++) ++ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); ++ + /* Reset the switch through internal reset */ + mt7530_write(priv, MT7530_SYS_CTRL, + SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | diff --git a/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch b/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch new file mode 100644 index 0000000000..8e0e4b1fdd --- /dev/null +++ b/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch @@ -0,0 +1,65 @@ +From 85cd45580f5e3b26068cccb7d6173f200e754dc0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 2 Apr 2023 23:56:16 +0100 +Subject: [PATCH 1/2] net: phy: realtek: use genphy_soft_reset for 2.5G PHYs + +Some vendor bootloaders do weird things with those PHYs which result in +link modes being reported wrongly. Start from a clean sheet by resetting +the PHY. + +Reported-by: Yevhen Kolomeiko +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -1040,6 +1040,7 @@ static struct phy_driver realtek_drvs[] + .write_page = rtl821x_write_page, + .read_mmd = rtl822x_read_mmd, + .write_mmd = rtl822x_write_mmd, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc840), + .name = "RTL8226B_RTL8221B 2.5Gbps PHY", +@@ -1052,6 +1053,7 @@ static struct phy_driver realtek_drvs[] + .write_page = rtl821x_write_page, + .read_mmd = rtl822x_read_mmd, + .write_mmd = rtl822x_write_mmd, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc838), + .name = "RTL8226-CG 2.5Gbps PHY", +@@ -1062,6 +1064,7 @@ static struct phy_driver realtek_drvs[] + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc848), + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", +@@ -1072,6 +1075,7 @@ static struct phy_driver realtek_drvs[] + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc849), + .name = "RTL8221B-VB-CG 2.5Gbps PHY", +@@ -1083,6 +1087,7 @@ static struct phy_driver realtek_drvs[] + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc84a), + .name = "RTL8221B-VM-CG 2.5Gbps PHY", +@@ -1094,6 +1099,7 @@ static struct phy_driver realtek_drvs[] + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, ++ .soft_reset = genphy_soft_reset, + }, { + PHY_ID_MATCH_EXACT(0x001cc961), + .name = "RTL8366RB Gigabit Ethernet", diff --git a/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch new file mode 100644 index 0000000000..babaa47aed --- /dev/null +++ b/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -0,0 +1,43 @@ +From 2b1b8c4c215af7988136401c902338d091d408a1 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 01:21:57 +0300 +Subject: [PATCH 2/2] net: phy: realtek: disable SGMII in-band AN for 2.5G PHYs + +MAC drivers don't use SGMII in-band autonegotiation unless told to do so +in device tree using 'managed = "in-band-status"'. When using MDIO to +access a PHY, in-band-status is unneeded as we have link-status via +MDIO. Switch off SGMII in-band autonegotiation using magic values. + +Reported-by: Chen Minqiang +Reported-by: Chukun Pan +Reported-by: Yevhen Kolomeiko +Tested-by: Yevhen Kolomeiko +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -885,6 +885,7 @@ static irqreturn_t rtl9000a_handle_inter + static int rtl8221b_config_init(struct phy_device *phydev) + { + u16 option_mode; ++ int val; + + switch (phydev->interface) { + case PHY_INTERFACE_MODE_2500BASEX: +@@ -921,6 +922,13 @@ static int rtl8221b_config_init(struct p + break; + } + ++ /* Disable SGMII AN */ ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7588, 0x2); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7589, 0x71d0); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, 0x3); ++ phy_read_mmd_poll_timeout(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, ++ val, !(val & BIT(0)), 500, 100000, false); ++ + return 0; + } + diff --git a/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch b/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch new file mode 100644 index 0000000000..6e338d9474 --- /dev/null +++ b/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch @@ -0,0 +1,35 @@ +From 4dd2cc9b91ecb25f278a2c55e07e6455e9000e6b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:21:14 +0100 +Subject: [PATCH] net: phy: realtek: make sure paged read is protected by mutex + +As we cannot rely on phy_read_paged function before the PHY is +identified, the paged read in rtlgen_supports_2_5gbps needs to be open +coded as it is being called by the match_phy_device function, ie. before +.read_page and .write_page have been populated. + +Make sure it is also protected by the MDIO bus mutex and use +rtl821x_write_page instead of 3 individually locked MDIO bus operations. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -737,9 +737,11 @@ static bool rtlgen_supports_2_5gbps(stru + { + int val; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); +- val = phy_read(phydev, 0x13); +- phy_write(phydev, RTL821x_PAGE_SELECT, 0); ++ mutex_lock(&phydev->mdio.bus->mdio_lock); ++ rtl821x_write_page(phydev, 0xa61); ++ val = __phy_read(phydev, 0x13); ++ rtl821x_write_page(phydev, 0); ++ mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return val >= 0 && val & RTL_SUPPORTS_2500FULL; + } diff --git a/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch b/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch new file mode 100644 index 0000000000..cafaefd3bf --- /dev/null +++ b/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch @@ -0,0 +1,60 @@ +From 92c8b9d558160d94b981dd8a2b9c47657627ffdc Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:23:08 +0100 +Subject: [PATCH 2/3] net: phy: realtek: use inline functions for 10GbE + advertisement + +Use existing generic inline functions to encode local advertisement +of 10GbE link modes as well as to decode link-partner advertisement. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 22 +++++----------------- + 1 file changed, 5 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -68,10 +68,6 @@ + #define RTL_SUPPORTS_5000FULL BIT(14) + #define RTL_SUPPORTS_2500FULL BIT(13) + #define RTL_SUPPORTS_10000FULL BIT(0) +-#define RTL_ADV_2500FULL BIT(7) +-#define RTL_LPADV_10000FULL BIT(11) +-#define RTL_LPADV_5000FULL BIT(6) +-#define RTL_LPADV_2500FULL BIT(5) + + #define RTL9000A_GINMR 0x14 + #define RTL9000A_GINMR_LINK_STATUS BIT(4) +@@ -671,14 +667,11 @@ static int rtl822x_config_aneg(struct ph + int ret = 0; + + if (phydev->autoneg == AUTONEG_ENABLE) { +- u16 adv2500 = 0; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->advertising)) +- adv2500 = RTL_ADV_2500FULL; +- + ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, +- RTL_ADV_2500FULL, adv2500); ++ MDIO_AN_10GBT_CTRL_ADV10G | ++ MDIO_AN_10GBT_CTRL_ADV5G | ++ MDIO_AN_10GBT_CTRL_ADV2_5G, ++ linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising)); + if (ret < 0) + return ret; + } +@@ -715,12 +708,7 @@ static int rtl822x_read_status(struct ph + if (lpadv < 0) + return lpadv; + +- linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, +- phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); + } + + ret = rtlgen_read_status(phydev); diff --git a/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch b/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch new file mode 100644 index 0000000000..8be1af6e50 --- /dev/null +++ b/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch @@ -0,0 +1,28 @@ +From 929bb4d3cfbc7878326c0771a01a636d49c54b40 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:25:39 +0100 +Subject: [PATCH 3/3] net: phy: realtek: check validity of 10GbE link-partner + advertisement + +Only use link-partner advertisement bits for 10GbE modes if they are +actually valid. Check LOCALOK and REMOTEOK bits and clear 10GbE modes +unless both of them are set. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -708,6 +708,10 @@ static int rtl822x_read_status(struct ph + if (lpadv < 0) + return lpadv; + ++ if (!(lpadv & MDIO_AN_10GBT_STAT_REMOK) || ++ !(lpadv & MDIO_AN_10GBT_STAT_LOCOK)) ++ lpadv = 0; ++ + mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); + } + diff --git a/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch b/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch new file mode 100644 index 0000000000..92e7a8742a --- /dev/null +++ b/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch @@ -0,0 +1,84 @@ +From 9155098547fb1172d4fa536f3f6bc9d42f59d08c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 03:26:01 +0100 +Subject: [PATCH] net: phy: realtek: setup ALDPS on RTL822x + +Setup Link Down Power Saving Mode according the DTS property +just like for RTL821x 1GE PHYs. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -62,6 +62,10 @@ + #define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 + #define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 + ++#define RTL8221B_PHYCR1 0xa430 ++#define RTL8221B_PHYCR1_ALDPS_EN BIT(2) ++#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12) ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + +@@ -750,6 +754,25 @@ static int rtl8226_match_phy_device(stru + rtlgen_supports_2_5gbps(phydev); + } + ++static int rtl822x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ int val; ++ ++ val = phy_read_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, RTL8221B_PHYCR1); ++ if (val < 0) ++ return val; ++ ++ if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) ++ val |= RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN; ++ else ++ val &= ~(RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN); ++ ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, RTL8221B_PHYCR1, val); ++ ++ return 0; ++} ++ + static int rtlgen_resume(struct phy_device *phydev) + { + int ret = genphy_resume(phydev); +@@ -1061,6 +1084,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8226-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1072,6 +1096,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1084,6 +1109,7 @@ static struct phy_driver realtek_drvs[] + .get_features = rtl822x_get_features, + .config_init = rtl8221b_config_init, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1096,6 +1122,7 @@ static struct phy_driver realtek_drvs[] + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .config_init = rtl8221b_config_init, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, diff --git a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch new file mode 100644 index 0000000000..f5987109f6 --- /dev/null +++ b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -0,0 +1,63 @@ +From 0de82310d2b32e78ff79d42c08b1122a6ede3778 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 30 Apr 2023 00:15:41 +0100 +Subject: [PATCH] net: phy: realtek: detect early version of RTL8221B + +Early versions (?) of the RTL8221B PHY cannot be identified in a regular +Clause-45 bus scan as the PHY doesn't report the implemented MMDs +correctly but returns 0 instead. +Implement custom identify function using the PKGID instead of iterating +over the implemented MMDs. + +Signed-off-by: Daniel Golle + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -754,6 +754,38 @@ static int rtl8226_match_phy_device(stru + rtlgen_supports_2_5gbps(phydev); + } + ++static int rtl8221b_vb_cg_match_phy_device(struct phy_device *phydev) ++{ ++ int val; ++ u32 id; ++ ++ if (phydev->mdio.bus->probe_capabilities >= MDIOBUS_C45) { ++ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID1); ++ if (val < 0) ++ return 0; ++ ++ id = val << 16; ++ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID2); ++ if (val < 0) ++ return 0; ++ ++ id |= val; ++ } else { ++ val = phy_read(phydev, MII_PHYSID1); ++ if (val < 0) ++ return 0; ++ ++ id = val << 16; ++ val = phy_read(phydev, MII_PHYSID2); ++ if (val < 0) ++ return 0; ++ ++ id |= val; ++ } ++ ++ return (id == 0x001cc849); ++} ++ + static int rtl822x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -1104,7 +1136,7 @@ static struct phy_driver realtek_drvs[] + .write_page = rtl821x_write_page, + .soft_reset = genphy_soft_reset, + }, { +- PHY_ID_MATCH_EXACT(0x001cc849), ++ .match_phy_device = rtl8221b_vb_cg_match_phy_device, + .name = "RTL8221B-VB-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_init = rtl8221b_config_init, diff --git a/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch b/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch new file mode 100644 index 0000000000..a7a4bafbb6 --- /dev/null +++ b/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch @@ -0,0 +1,59 @@ +From 686c603f67ae87bf21a61b5e4b1564443f41c3ee Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 20 Oct 2022 03:34:43 +0200 +Subject: [PATCH] net: permit ieee80211_ptr even with no CFG82111 support + +Introduce a new flag CONFIG_CFG80211_HEADERS to compile in ieee80211_ptr +even if CFG80211 support is not compiled in. This is needed for the +backports project and for any downstream wireless driver that loads in +the kernel dynamically. + +Signed-off-by: Christian Marangi +--- + include/linux/netdevice.h | 2 +- + net/batman-adv/hard-interface.c | 2 +- + net/wireless/Kconfig | 4 ++++ + 3 files changed, 6 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2192,7 +2192,7 @@ struct net_device { + #if IS_ENABLED(CONFIG_AX25) + void *ax25_ptr; + #endif +-#if IS_ENABLED(CONFIG_CFG80211) ++#if IS_ENABLED(CONFIG_CFG80211_HEADERS) + struct wireless_dev *ieee80211_ptr; + #endif + #if IS_ENABLED(CONFIG_IEEE802154) || IS_ENABLED(CONFIG_6LOWPAN) +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -308,7 +308,7 @@ static bool batadv_is_cfg80211_netdev(st + if (!net_device) + return false; + +-#if IS_ENABLED(CONFIG_CFG80211) ++#if IS_ENABLED(CONFIG_CFG80211_HEADERS) + /* cfg80211 drivers have to set ieee80211_ptr */ + if (net_device->ieee80211_ptr) + return true; +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -26,6 +26,7 @@ config CFG80211 + # using a different algorithm, though right now they shouldn't + # (this is here rather than below to allow it to be a module) + select CRYPTO_SHA256 if CFG80211_USE_KERNEL_REGDB_KEYS ++ select CFG80211_HEADERS + help + cfg80211 is the Linux wireless LAN (802.11) configuration API. + Enable this if you have a wireless device. +@@ -36,6 +37,9 @@ config CFG80211 + + When built as a module it will be called cfg80211. + ++config CFG80211_HEADERS ++ bool "cfg80211 - headers support" ++ + if CFG80211 + + config NL80211_TESTMODE diff --git a/target/linux/generic/pending-6.6/732-00-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch b/target/linux/generic/pending-6.6/732-00-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch new file mode 100644 index 0000000000..decf647bce --- /dev/null +++ b/target/linux/generic/pending-6.6/732-00-net-ethernet-mtk_eth_soc-compile-out-netsys-v2-code-.patch @@ -0,0 +1,44 @@ +From: Felix Fietkau +Date: Thu, 27 Oct 2022 23:39:52 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: compile out netsys v2 code + on mt7621 + +Avoid some branches in the hot path on low-end devices with limited CPU power, +and reduce code size + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1326,6 +1326,22 @@ struct mtk_mac { + /* the struct describing the SoC. these are declared in the soc_xyz.c files */ + extern const struct of_device_id of_mtk_match[]; + ++#ifdef CONFIG_SOC_MT7621 ++static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) ++{ ++ return true; ++} ++ ++static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) ++{ ++ return false; ++} ++ ++static inline bool mtk_is_netsys_v3_or_greater(struct mtk_eth *eth) ++{ ++ return false; ++} ++#else + static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) + { + return eth->soc->version == 1; +@@ -1340,6 +1356,7 @@ static inline bool mtk_is_netsys_v3_or_g + { + return eth->soc->version > 2; + } ++#endif + + static inline struct mtk_foe_entry * + mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) diff --git a/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch new file mode 100644 index 0000000000..a1cc109050 --- /dev/null +++ b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch @@ -0,0 +1,94 @@ +From: Felix Fietkau +Date: Thu, 3 Nov 2022 12:38:49 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with sending + small fragments + +When lots of frames are sent with a number of very small fragments, an +internal FIFO can overflow, causing the DMA engine to lock up lock up and +transmit attempts time out. + +Fix this on MT7986 by increasing the reserved FIFO space. +Fix this on older chips by detecting the presence of small fragments and use +skb_gso_segment + skb_linearize to deal with them. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1562,12 +1562,28 @@ static void mtk_wake_queue(struct mtk_et + } + } + ++static bool mtk_skb_has_small_frag(struct sk_buff *skb) ++{ ++ int min_size = 16; ++ int i; ++ ++ if (skb_headlen(skb) < min_size) ++ return true; ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) ++ if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size) ++ return true; ++ ++ return false; ++} ++ + static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + struct mtk_tx_ring *ring = ð->tx_ring; + struct net_device_stats *stats = &dev->stats; ++ struct sk_buff *segs, *next; + bool gso = false; + int tx_num; + +@@ -1589,6 +1605,18 @@ static netdev_tx_t mtk_start_xmit(struct + return NETDEV_TX_BUSY; + } + ++ if (mtk_is_netsys_v1(eth) && ++ skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) { ++ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO); ++ if (IS_ERR(segs)) ++ goto drop; ++ ++ if (segs) { ++ consume_skb(skb); ++ skb = segs; ++ } ++ } ++ + /* TSO: fill MSS info in tcp checksum field */ + if (skb_is_gso(skb)) { + if (skb_cow_head(skb, 0)) { +@@ -1604,8 +1632,14 @@ static netdev_tx_t mtk_start_xmit(struct + } + } + +- if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) +- goto drop; ++ skb_list_walk_safe(skb, skb, next) { ++ if ((mtk_is_netsys_v1(eth) && ++ mtk_skb_has_small_frag(skb) && skb_linearize(skb)) || ++ mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) { ++ stats->tx_dropped++; ++ dev_kfree_skb_any(skb); ++ } ++ } + + if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) + netif_tx_stop_all_queues(dev); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -268,7 +268,7 @@ + #define MTK_CHK_DDONE_EN BIT(28) + #define MTK_DMAD_WR_WDONE BIT(26) + #define MTK_WCOMP_EN BIT(24) +-#define MTK_RESV_BUF (0x40 << 16) ++#define MTK_RESV_BUF (0x80 << 16) + #define MTK_MUTLI_CNT (0x4 << 12) + #define MTK_LEAKY_BUCKET_EN BIT(11) + diff --git a/target/linux/generic/pending-6.6/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch b/target/linux/generic/pending-6.6/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch new file mode 100644 index 0000000000..11a81dd0bf --- /dev/null +++ b/target/linux/generic/pending-6.6/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch @@ -0,0 +1,21 @@ +From: Felix Fietkau +Date: Fri, 28 Oct 2022 12:54:48 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO + +Significantly improves performance by avoiding unnecessary segmentation + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -47,8 +47,7 @@ + #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ + NETIF_F_RXCSUM | \ + NETIF_F_HW_VLAN_CTAG_TX | \ +- NETIF_F_SG | NETIF_F_TSO | \ +- NETIF_F_TSO6 | \ ++ NETIF_F_SG | NETIF_F_ALL_TSO | \ + NETIF_F_IPV6_CSUM |\ + NETIF_F_HW_TC) + #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) diff --git a/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch b/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch new file mode 100644 index 0000000000..0a49c75b00 --- /dev/null +++ b/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch @@ -0,0 +1,42 @@ +From: Felix Fietkau +Date: Wed, 29 Mar 2023 16:02:54 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix remaining throughput + regression + +Based on further tests, it seems that the QDMA shaper is not able to +perform shaping close to the MAC link rate without throughput loss. +This cannot be compensated by increasing the shaping rate, so it seems +to be an internal limit. + +Fix the remaining throughput regression by detecting that condition and +limiting shaping to ports with lower link speed. + +This patch intentionally ignores link speed gain from TRGMII, because +even on such links, shaping to 1000 Mbit/s incurs some throughput +degradation. + +Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") +Reported-by: Frank Wunderlich +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -767,6 +767,7 @@ static void mtk_mac_link_up(struct phyli + MAC_MCR_FORCE_RX_FC); + + /* Configure speed */ ++ mac->speed = speed; + switch (speed) { + case SPEED_2500: + case SPEED_1000: +@@ -3348,6 +3349,9 @@ found: + if (dp->index >= MTK_QDMA_NUM_QUEUES) + return NOTIFY_DONE; + ++ if (mac->speed > 0 && mac->speed <= s.base.speed) ++ s.base.speed = 0; ++ + mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); + + return NOTIFY_DONE; diff --git a/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch b/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch new file mode 100644 index 0000000000..61042c1ad0 --- /dev/null +++ b/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch @@ -0,0 +1,33 @@ +From: Felix Fietkau +Date: Tue, 27 Dec 2022 15:02:51 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: ppe: fix L2 offloading with DSA + untagging offload enabled + +Check for skb metadata in order to detect the case where the DSA header is not +present. + +Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include "mtk_eth_soc.h" + #include "mtk_ppe.h" +@@ -829,7 +830,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe + skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) + goto out; + +- tag += 4; ++ if (!skb_metadata_dst(skb)) ++ tag += 4; ++ + if (get_unaligned_be16(tag) != ETH_P_8021Q) + break; + diff --git a/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch new file mode 100644 index 0000000000..afe561ab31 --- /dev/null +++ b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -0,0 +1,935 @@ +From 91bda2f441f9e37273922028ffc48ce8e91bf5bd Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:51:14 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add paths and SerDes modes for + MT7988 + +MT7988 comes with a built-in 2.5G PHY as well as SerDes lanes to +connect external PHYs or transceivers in USXGMII, 10GBase-R, 5GBase-R, +2500Base-X, 1000Base-X and Cisco SGMII interface modes. + +Implement support for configuring for the new paths to SerDes interfaces +and the internal 2.5G PHY. + +Add USXGMII PCS driver for 10GBase-R, 5GBase-R and USXGMII mode, and +setup the new PHYA on MT7988 to access the also still existing old +LynxI PCS for 1000Base-X, 2500Base-X and Cisco SGMII PCS interface +modes. + +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 291 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++- + 3 files changed, 469 insertions(+), 51 deletions(-) + +--- 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"; + } +@@ -127,6 +137,27 @@ static int set_mux_u3_gmac2_to_qphy(stru + return 0; + } + ++static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path) ++{ ++ int ret; ++ ++ if (path == MTK_ETH_PATH_GMAC2_2P5GPHY) { ++ ret = regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0, SYSCFG0_SGMII_GMAC2_V2); ++ if (ret) ++ return ret; ++ ++ /* Setup mux to 2p5g PHY */ ++ ret = regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, MUX_G2_USXGMII_SEL); ++ if (ret) ++ return ret; ++ ++ dev_dbg(eth->dev, "path %s in %s updated\n", ++ mtk_eth_path_name(path), __func__); ++ } ++ ++ return 0; ++} ++ + static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; +@@ -165,7 +196,48 @@ 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; ++ ++ /* 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 (mac_id == MTK_GMAC2_ID) ++ regmap_set_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, ++ MUX_G2_USXGMII_SEL); ++ } ++ ++ 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; +@@ -182,6 +254,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; + } +@@ -210,13 +285,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, + }, + }; + +@@ -249,12 +336,39 @@ 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); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -258,12 +260,8 @@ static const char * const mtk_clks_sourc + "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", +@@ -475,6 +473,30 @@ static void mtk_setup_bridge_switch(stru + MTK_GSW_CFG); + } + ++static bool mtk_check_gmac23_idle(struct mtk_mac *mac) ++{ ++ u32 mac_fsm, gdm_fsm; ++ ++ mac_fsm = mtk_r32(mac->hw, MTK_MAC_FSM(mac->id)); ++ ++ switch (mac->id) { ++ case MTK_GMAC2_ID: ++ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM2_FSM); ++ break; ++ case MTK_GMAC3_ID: ++ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM3_FSM); ++ break; ++ default: ++ return true; ++ }; ++ ++ if ((mac_fsm & 0xFFFF0000) == 0x01010000 && ++ (gdm_fsm & 0xFFFF0000) == 0x00000000) ++ return true; ++ ++ return false; ++} ++ + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +@@ -483,6 +505,21 @@ static struct phylink_pcs *mtk_mac_selec + struct mtk_eth *eth = mac->hw; + unsigned int sid; + ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ return mac->sgmii_pcs; ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ return mac->usxgmii_pcs; ++ default: ++ return NULL; ++ } ++ } ++ + if (interface == PHY_INTERFACE_MODE_SGMII || + phy_interface_mode_is_8023z(interface)) { + sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +@@ -544,7 +581,22 @@ static void mtk_mac_config(struct phylin + goto init_err; + } + break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ 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; +@@ -599,8 +651,6 @@ static void mtk_mac_config(struct phylin + val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id); + val |= SYSCFG0_GE_MODE(ge_mode, mac->id); + regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); +- +- mac->interface = state->interface; + } + + /* SGMII */ +@@ -617,21 +667,40 @@ static void mtk_mac_config(struct phylin + + /* Save the syscfg0 value for mac_finish */ + mac->syscfg0 = val; +- } else if (phylink_autoneg_inband(mode)) { ++ } else if (state->interface != PHY_INTERFACE_MODE_USXGMII && ++ state->interface != PHY_INTERFACE_MODE_10GBASER && ++ state->interface != PHY_INTERFACE_MODE_5GBASER && ++ phylink_autoneg_inband(mode)) { + dev_err(eth->dev, +- "In-band mode not supported in non SGMII mode!\n"); ++ "In-band mode not supported in non-SerDes modes!\n"); + return; + } + + /* Setup gmac */ +- if (mtk_is_netsys_v3_or_greater(eth) && +- 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)); ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ if (mtk_interface_mode_is_xgmii(state->interface)) { ++ 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)); ++ ++ if (mac->id == MTK_GMAC1_ID) ++ mtk_setup_bridge_switch(eth); ++ } else { ++ mtk_w32(eth, 0, MTK_GDMA_EG_CTRL(mac->id)); + +- mtk_setup_bridge_switch(eth); ++ /* FIXME: In current hardware design, we have to reset FE ++ * when swtiching XGDM to GDM. Therefore, here trigger an SER ++ * to let GDM go back to the initial state. ++ */ ++ if ((mtk_interface_mode_is_xgmii(mac->interface) || ++ mac->interface == PHY_INTERFACE_MODE_NA) && ++ !mtk_check_gmac23_idle(mac) && ++ !test_bit(MTK_RESETTING, ð->state)) ++ schedule_work(ð->pending_work); ++ } + } + ++ mac->interface = state->interface; ++ + return; + + err_phy: +@@ -644,6 +713,18 @@ init_err: + mac->id, phy_modes(state->interface), err); + } + ++static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ ++ if (mac->pextp && mac->interface != interface) ++ phy_reset(mac->pextp); ++ ++ return 0; ++} ++ + static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) + { +@@ -652,6 +733,10 @@ static int mtk_mac_finish(struct phylink + struct mtk_eth *eth = mac->hw; + u32 mcr_cur, mcr_new; + ++ /* Setup PMA/PMD */ ++ if (mac->pextp) ++ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); ++ + /* Enable SGMII */ + if (interface == PHY_INTERFACE_MODE_SGMII || + phy_interface_mode_is_8023z(interface)) +@@ -677,10 +762,13 @@ static void mtk_mac_link_down(struct phy + { + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); +- u32 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)); ++ if (!mtk_interface_mode_is_xgmii(interface)) { ++ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); ++ } else if (mac->id != MTK_GMAC1_ID) { ++ mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id)); ++ } + } + + static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, +@@ -752,13 +840,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)); +@@ -792,9 +878,63 @@ 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, force_link = 0; ++ ++ if (mac->id == MTK_GMAC1_ID) ++ return; ++ ++ /* Eliminate the interference(before link-up) caused by PHY noise */ ++ mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->id)); ++ mdelay(20); ++ mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR, MTK_XMAC_CNT_CTRL(mac->id)); ++ ++ if (mac->interface == PHY_INTERFACE_MODE_INTERNAL || mac->id == MTK_GMAC3_ID) ++ force_link = MTK_XGMAC_FORCE_LINK(mac->id); ++ ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), force_link, MTK_XGMAC_STS(mac->id)); ++ ++ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id)); ++ mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC | XMAC_MCR_TRX_DISABLE); ++ /* 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; ++ ++ 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); ++ ++ /* Repeat pextp setup to tune link */ ++ if (mac->pextp) ++ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); ++} ++ + static const struct phylink_mac_ops mtk_phylink_ops = { + .mac_select_pcs = mtk_mac_select_pcs, + .mac_config = mtk_mac_config, ++ .mac_prepare = mtk_mac_prepare, + .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, + .mac_link_up = mtk_mac_link_up, +@@ -3373,6 +3513,9 @@ static int mtk_open(struct net_device *d + struct mtk_eth *eth = mac->hw; + int i, err; + ++ if (mac->pextp) ++ phy_power_on(mac->pextp); ++ + err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); + if (err) { + netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, +@@ -3501,6 +3644,9 @@ static int mtk_stop(struct net_device *d + for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) + mtk_ppe_stop(eth->ppe[i]); + ++ if (mac->pextp) ++ phy_power_off(mac->pextp); ++ + return 0; + } + +@@ -4498,6 +4644,7 @@ static const struct net_device_ops mtk_n + static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + { + const __be32 *_id = of_get_property(np, "reg", NULL); ++ struct device_node *pcs_np; + phy_interface_t phy_mode; + struct phylink *phylink; + struct mtk_mac *mac; +@@ -4533,16 +4680,41 @@ static int mtk_add_mac(struct mtk_eth *e + mac->id = id; + mac->hw = eth; + mac->of_node = np; ++ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 0); ++ if (pcs_np) { ++ mac->sgmii_pcs = mtk_pcs_lynxi_get(eth->dev, pcs_np); ++ if (IS_ERR(mac->sgmii_pcs)) { ++ if (PTR_ERR(mac->sgmii_pcs) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; + +- err = of_get_ethdev_address(mac->of_node, eth->netdev[id]); +- if (err == -EPROBE_DEFER) +- return err; ++ dev_err(eth->dev, "cannot select SGMII PCS, error %ld\n", ++ PTR_ERR(mac->sgmii_pcs)); ++ return PTR_ERR(mac->sgmii_pcs); ++ } ++ } + +- if (err) { +- /* If the mac address is invalid, use random mac address */ +- eth_hw_addr_random(eth->netdev[id]); +- dev_err(eth->dev, "generated random MAC address %pM\n", +- eth->netdev[id]->dev_addr); ++ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 1); ++ if (pcs_np) { ++ mac->usxgmii_pcs = mtk_usxgmii_pcs_get(eth->dev, pcs_np); ++ if (IS_ERR(mac->usxgmii_pcs)) { ++ if (PTR_ERR(mac->usxgmii_pcs) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ dev_err(eth->dev, "cannot select USXGMII PCS, error %ld\n", ++ PTR_ERR(mac->usxgmii_pcs)); ++ return PTR_ERR(mac->usxgmii_pcs); ++ } ++ } ++ ++ if (mtk_is_netsys_v3_or_greater(eth) && (mac->sgmii_pcs || mac->usxgmii_pcs)) { ++ mac->pextp = devm_of_phy_get(eth->dev, mac->of_node, NULL); ++ if (IS_ERR(mac->pextp)) { ++ if (PTR_ERR(mac->pextp) != -EPROBE_DEFER) ++ dev_err(eth->dev, "cannot get PHY, error %ld\n", ++ PTR_ERR(mac->pextp)); ++ ++ return PTR_ERR(mac->pextp); ++ } + } + + memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); +@@ -4616,8 +4788,21 @@ static int mtk_add_mac(struct mtk_eth *e + phy_interface_zero(mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + mac->phylink_config.supported_interfaces); ++ } else if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) { ++ 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_10GBASER, ++ 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) && ++ 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); +@@ -4662,6 +4847,26 @@ free_netdev: + return err; + } + ++static int mtk_mac_assign_address(struct mtk_eth *eth, int i, bool test_defer_only) ++{ ++ int err = of_get_ethdev_address(eth->mac[i]->of_node, eth->netdev[i]); ++ ++ if (err == -EPROBE_DEFER) ++ return err; ++ ++ if (test_defer_only) ++ return 0; ++ ++ if (err) { ++ /* If the mac address is invalid, use random mac address */ ++ eth_hw_addr_random(eth->netdev[i]); ++ dev_err(eth->dev, "generated random MAC address %pM\n", ++ eth->netdev[i]); ++ } ++ ++ return 0; ++} ++ + void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) + { + struct net_device *dev, *tmp; +@@ -4805,7 +5010,8 @@ static int mtk_probe(struct platform_dev + regmap_write(cci, 0, 3); + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII) && ++ !mtk_is_netsys_v3_or_greater(eth)) { + err = mtk_sgmii_init(eth); + + if (err) +@@ -4916,6 +5122,24 @@ static int mtk_probe(struct platform_dev + } + } + ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->netdev[i]) ++ continue; ++ ++ err = mtk_mac_assign_address(eth, i, true); ++ if (err) ++ goto err_deinit_hw; ++ } ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->netdev[i]) ++ continue; ++ ++ err = mtk_mac_assign_address(eth, i, false); ++ if (err) ++ goto err_deinit_hw; ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { + err = devm_request_irq(eth->dev, eth->irq[0], + mtk_handle_irq, 0, +@@ -5018,6 +5242,11 @@ static int mtk_remove(struct platform_de + mtk_stop(eth->netdev[i]); + mac = netdev_priv(eth->netdev[i]); + phylink_disconnect_phy(mac->phylink); ++ if (mac->sgmii_pcs) ++ mtk_pcs_lynxi_put(mac->sgmii_pcs); ++ ++ if (mac->usxgmii_pcs) ++ mtk_usxgmii_pcs_put(mac->usxgmii_pcs); + } + + mtk_wed_exit(); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -502,6 +503,21 @@ + #define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED) + #define INTF_MODE_RGMII_10_100 0 + ++/* XFI Mac control registers */ ++#define MTK_XMAC_BASE(x) (0x12000 + (((x) - 1) * 0x1000)) ++#define MTK_XMAC_MCR(x) (MTK_XMAC_BASE(x)) ++#define XMAC_MCR_TRX_DISABLE 0xf ++#define XMAC_MCR_FORCE_TX_FC BIT(5) ++#define XMAC_MCR_FORCE_RX_FC BIT(4) ++ ++/* XFI Mac logic reset registers */ ++#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + 0x10) ++#define XMAC_LOGIC_RST BIT(0) ++ ++/* XFI Mac count global control */ ++#define MTK_XMAC_CNT_CTRL(x) (MTK_XMAC_BASE(x) + 0x100) ++#define XMAC_GLB_CNTCLR BIT(0) ++ + /* GPIO port control registers for GMAC 2*/ + #define GPIO_OD33_CTRL8 0x4c0 + #define GPIO_BIAS_CTRL 0xed0 +@@ -527,6 +543,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 */ +@@ -565,6 +582,11 @@ + #define GEPHY_MAC_SEL BIT(1) + + /* 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 +@@ -589,6 +611,8 @@ + #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) + #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) + ++/* Debug Purpose Register */ ++#define MTK_PSE_FQFC_CFG 0x100 + #define MTK_FE_CDM1_FSM 0x220 + #define MTK_FE_CDM2_FSM 0x224 + #define MTK_FE_CDM3_FSM 0x238 +@@ -597,6 +621,11 @@ + #define MTK_FE_CDM6_FSM 0x328 + #define MTK_FE_GDM1_FSM 0x228 + #define MTK_FE_GDM2_FSM 0x22C ++#define MTK_FE_GDM3_FSM 0x23C ++#define MTK_FE_PSE_FREE 0x240 ++#define MTK_FE_DROP_FQ 0x244 ++#define MTK_FE_DROP_FC 0x248 ++#define MTK_FE_DROP_PPE 0x24C + + #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) + +@@ -721,12 +750,8 @@ enum mtk_clks_map { + 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, +@@ -797,19 +822,9 @@ enum mtk_clks_map { + 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) | \ +@@ -943,6 +958,8 @@ enum mkt_eth_capabilities { + MTK_RGMII_BIT = 0, + MTK_TRGMII_BIT, + MTK_SGMII_BIT, ++ MTK_USXGMII_BIT, ++ MTK_2P5GPHY_BIT, + MTK_ESW_BIT, + MTK_GEPHY_BIT, + MTK_MUX_BIT, +@@ -963,8 +980,11 @@ 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, ++ MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT, + + /* PATH BITS */ + MTK_ETH_PATH_GMAC1_RGMII_BIT, +@@ -972,14 +992,21 @@ 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, ++ 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_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) +@@ -1002,10 +1029,16 @@ 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 \ + 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) +@@ -1013,8 +1046,13 @@ 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) ++#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) +@@ -1022,7 +1060,12 @@ 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) ++#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 */ +@@ -1041,10 +1084,20 @@ 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) + ++#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) ++ + #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) + + #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ +@@ -1076,8 +1129,12 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_RSTCTRL_PPE1 | MTK_SRAM) + +-#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) ++#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ ++ MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ ++ MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \ ++ MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ ++ MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \ ++ MTK_QDMA | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1314,6 +1371,9 @@ struct mtk_mac { + struct device_node *of_node; + struct phylink *phylink; + struct phylink_config phylink_config; ++ struct phylink_pcs *sgmii_pcs; ++ struct phylink_pcs *usxgmii_pcs; ++ struct phy *pextp; + struct mtk_eth *hw; + struct mtk_hw_stats *hw_stats; + __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; +@@ -1437,6 +1497,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_INTERNAL: ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_5GBASER: ++ return true; ++ default: ++ return false; ++ } ++} ++ + /* read the hardware status register */ + void mtk_stats_update_mac(struct mtk_mac *mac); + +@@ -1445,8 +1518,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne + u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int 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, diff --git a/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch b/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch new file mode 100644 index 0000000000..b598d15866 --- /dev/null +++ b/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch @@ -0,0 +1,46 @@ +From dee3f591103910c8d8b2a6d57879ccd2a4be4b10 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Daniel Golle +Date: Wed, 24 Jan 2024 03:19:49 +0000 +Subject: [PATCH net] net: ethernet: mtk_eth_soc: set coherent mask to get PPE + working +To: Felix Fietkau , + Sean Wang , + Mark Lee , + Lorenzo Bianconi , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Matthias Brugger , + AngeloGioacchino Del Regno , + Daniel Golle , + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org + +Set DMA coherent mask to 32-bit which makes PPE offloading engine start +working on BPi-R4 which got 4 GiB of RAM. + +Fixes: 2d75891ebc09 ("net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988") +Suggested-by: Elad Yifee +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4963,7 +4963,10 @@ static int mtk_probe(struct platform_dev + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { +- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); ++ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); ++ if (!err) ++ err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ + if (err) { + dev_err(&pdev->dev, "Wrong DMA config\n"); + return -EINVAL; diff --git a/target/linux/generic/pending-6.6/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch b/target/linux/generic/pending-6.6/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch new file mode 100644 index 0000000000..1f1c40b1d9 --- /dev/null +++ b/target/linux/generic/pending-6.6/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch @@ -0,0 +1,136 @@ +From patchwork Thu Feb 1 21:52:20 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13541842 +Date: Thu, 1 Feb 2024 21:52:20 +0000 +From: Daniel Golle +To: Bc-bocun Chen , + Steven Liu , + John Crispin , + Chunfeng Yun , + Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Daniel Golle , + Qingfang Deng , + SkyLake Huang , + Matthias Brugger , + AngeloGioacchino Del Regno , + Philipp Zabel , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Subject: [PATCH 1/2] dt-bindings: phy: mediatek,xfi-tphy: add new bindings +Message-ID: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +List-Id: Linux Phy Mailing list + +Add bindings for the MediaTek XFI T-PHY Ethernet SerDes PHY found in the +MediaTek MT7988 SoC which can operate at various interfaces modes: + +via USXGMII PCS: + * USXGMII + * 10GBase-R + * 5GBase-R + +via LynxI SGMII PCS: + * 2500Base-X + * 1000Base-X + * Cisco SGMII (MAC side) + +Signed-off-by: Daniel Golle +--- + .../bindings/phy/mediatek,xfi-tphy.yaml | 80 +++++++++++++++++++ + 1 file changed, 80 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml +@@ -0,0 +1,80 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/mediatek,xfi-tphy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek XFI T-PHY ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek XFI SerDes T-PHY provides the physical SerDes lanes ++ used by the (10G/5G) USXGMII PCS and (1G/2.5G) LynxI PCS found in ++ MediaTek's 10G-capabale SoCs. ++ ++properties: ++ $nodename: ++ pattern: "^phy@[0-9a-f]+$" ++ ++ compatible: ++ const: mediatek,mt7988-xfi-tphy ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: XFI PHY clock ++ - description: XFI register clock ++ ++ clock-names: ++ items: ++ - const: xfipll ++ - const: topxtal ++ ++ resets: ++ items: ++ - description: PEXTP reset ++ ++ mediatek,usxgmii-performance-errata: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ One instance of the T-PHY on MT7988 suffers from a performance ++ problem in 10GBase-R mode which needs a work-around in the driver. ++ The work-around is enabled using this flag. ++ ++ "#phy-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ phy@11f20000 { ++ compatible = "mediatek,mt7988-xfi-tphy"; ++ reg = <0 0x11f20000 0 0x10000>; ++ clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, ++ <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>; ++ clock-names = "xfipll", "topxtal"; ++ resets = <&watchdog 14>; ++ mediatek,usxgmii-performance-errata; ++ #phy-cells = <0>; ++ }; ++ }; ++ ++... diff --git a/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch b/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch new file mode 100644 index 0000000000..d7424020a7 --- /dev/null +++ b/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch @@ -0,0 +1,497 @@ +From patchwork Thu Feb 1 21:53:06 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13541843 +Date: Thu, 1 Feb 2024 21:53:06 +0000 +From: Daniel Golle +To: Bc-bocun Chen , + Chunfeng Yun , + Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Daniel Golle , + Qingfang Deng , + SkyLake Huang , + Matthias Brugger , + AngeloGioacchino Del Regno , + Philipp Zabel , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Subject: [PATCH 2/2] phy: add driver for MediaTek XFI T-PHY +Message-ID: + +References: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +List-Id: Linux Phy Mailing list + +Add driver for MediaTek's XFI T-PHY, 10 Gigabit/s Ethernet SerDes PHY +which can be found in the MT7988 SoC. + +The PHY can operates only in PHY_MODE_ETHERNET, the submode is one of +PHY_INTERFACE_MODE_* corresponding to the supported modes: + + * USXGMII \ + * 10GBase-R }- USXGMII PCS - XGDM \ + * 5GBase-R / \ + }- Ethernet MAC + * 2500Base-X \ / + * 1000Base-X }- LynxI PCS - GDM / + * Cisco SGMII (MAC side) / + +In order to work-around a performance issue present on the first of +two XFI T-PHYs present in MT7988, special tuning is applied which can be +selected by adding the 'mediatek,usxgmii-performance-errata' property to +the device tree node. + +There is no documentation for most registers used for the +analog/tuning part, however, most of the registers have been partially +reverse-engineered from MediaTek's SDK implementation (an opaque +sequence of 32-bit register writes) and descriptions for all relevant +digital registers and bits such as resets and muxes have been supplied +by MediaTek. + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 1 + + drivers/phy/mediatek/Kconfig | 12 + + drivers/phy/mediatek/Makefile | 1 + + drivers/phy/mediatek/phy-mtk-xfi-tphy.c | 392 ++++++++++++++++++++++++ + 4 files changed, 406 insertions(+) + create mode 100644 drivers/phy/mediatek/phy-mtk-xfi-tphy.c + +--- a/drivers/phy/mediatek/Kconfig ++++ b/drivers/phy/mediatek/Kconfig +@@ -13,6 +13,18 @@ config PHY_MTK_PCIE + callback for PCIe GEN3 port, it supports software efuse + initialization. + ++config PHY_MTK_XFI_TPHY ++ tristate "MediaTek XFI T-PHY Driver" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ depends on OF && OF_ADDRESS ++ depends on HAS_IOMEM ++ select GENERIC_PHY ++ help ++ Say 'Y' here to add support for MediaTek XFI T-PHY driver. ++ The driver provides access to the Ethernet SerDes T-PHY supporting ++ 1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes ++ via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet. ++ + config PHY_MTK_TPHY + tristate "MediaTek T-PHY Driver" + depends on ARCH_MEDIATEK || COMPILE_TEST +--- a/drivers/phy/mediatek/Makefile ++++ b/drivers/phy/mediatek/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-p + obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o + obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o + obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o ++obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o + + phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o + phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o +--- /dev/null ++++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c +@@ -0,0 +1,392 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* MediaTek 10GE SerDes PHY driver ++ * ++ * Copyright (c) 2024 Daniel Golle ++ * Bc-bocun Chen ++ * based on mtk_usxgmii.c found in MediaTek's SDK released under GPL-2.0 ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Henry Yen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_XFI_TPHY_NUM_CLOCKS 2 ++ ++#define REG_DIG_GLB_70 0x0070 ++#define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x)) ++#define XTP_PCS_MODE_MASK GENMASK(17, 16) ++#define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x)) ++#define XTP_PCS_RST_B BIT(15) ++#define XTP_FRC_PCS_RST_B BIT(14) ++#define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12) ++#define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x)) ++#define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10) ++#define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x)) ++#define XTP_FRC_PCS_PWD_ASYNC BIT(8) ++#define XTP_PCS_UPDT BIT(4) ++#define XTP_PCS_IN_FR_RG BIT(0) ++ ++#define REG_DIG_GLB_F4 0x00f4 ++#define XFI_DPHY_PCS_SEL BIT(0) ++#define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1) ++#define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0) ++#define XFI_DPHY_AD_SGDT_FRC_EN BIT(5) ++ ++#define REG_DIG_LN_TRX_40 0x3040 ++#define XTP_LN_FRC_TX_DATA_EN BIT(29) ++#define XTP_LN_TX_DATA_EN BIT(28) ++ ++#define REG_DIG_LN_TRX_B0 0x30b0 ++#define XTP_LN_FRC_TX_MACCK_EN BIT(5) ++#define XTP_LN_TX_MACCK_EN BIT(4) ++ ++#define REG_ANA_GLB_D0 0x90d0 ++#define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1) ++#define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x)) ++#define XTP_GLB_USXGMII_EN BIT(0) ++ ++struct mtk_xfi_tphy { ++ void __iomem *base; ++ struct device *dev; ++ struct reset_control *reset; ++ struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS]; ++ bool da_war; ++}; ++ ++static void mtk_xfi_tphy_write(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 value) ++{ ++ iowrite32(value, xfi_tphy->base + reg); ++} ++ ++static void mtk_xfi_tphy_rmw(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 clr, u32 set) ++{ ++ u32 val; ++ ++ val = ioread32(xfi_tphy->base + reg); ++ val &= ~clr; ++ val |= set; ++ iowrite32(val, xfi_tphy->base + reg); ++} ++ ++static void mtk_xfi_tphy_set(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 set) ++{ ++ mtk_xfi_tphy_rmw(xfi_tphy, reg, 0, set); ++} ++ ++static void mtk_xfi_tphy_clear(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 clr) ++{ ++ mtk_xfi_tphy_rmw(xfi_tphy, reg, clr, 0); ++} ++ ++static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy, ++ phy_interface_t interface) ++{ ++ bool is_2p5g = (interface == PHY_INTERFACE_MODE_2500BASEX); ++ bool is_1g = (interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_SGMII); ++ bool is_10g = (interface == PHY_INTERFACE_MODE_10GBASER || ++ interface == PHY_INTERFACE_MODE_USXGMII); ++ bool is_5g = (interface == PHY_INTERFACE_MODE_5GBASER); ++ bool is_xgmii = (is_10g || is_5g); ++ ++ dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface)); ++ ++ /* Setup PLL setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x9024, 0x100000, is_10g ? 0x0 : 0x100000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2020, 0x202000, is_5g ? 0x202000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2030, 0x500, is_1g ? 0x0 : 0x500); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2034, 0xa00, is_1g ? 0x0 : 0xa00); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2040, 0x340000, is_1g ? 0x200000 : ++ 0x140000); ++ ++ /* Setup RXFE BW setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50f0, 0xc10, is_1g ? 0x410 : ++ is_5g ? 0x800 : 0x400); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000); ++ ++ /* Setup RX CDR setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x506c, 0x30000, is_5g ? 0x0 : 0x30000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5074, 0x180000, is_5g ? 0x180000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5078, 0xf000400, is_5g ? 0x8000000 : ++ 0x7000400); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x507c, 0x5000500, is_5g ? 0x4000400 : ++ 0x1000100); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5080, 0x1410, is_1g ? 0x400 : ++ is_5g ? 0x1010 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5084, 0x30300, is_1g ? 0x30300 : ++ is_5g ? 0x30100 : ++ 0x100); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5088, 0x60200, is_1g ? 0x20200 : ++ is_5g ? 0x40000 : ++ 0x20000); ++ ++ /* Setting RXFE adaptation range setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50ec, 0xa00, is_1g ? 0x200 : 0x800); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50a8, 0xee0000, is_5g ? 0x800000 : ++ 0x6e0000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x6004, 0x190000, is_5g ? 0x0 : 0x190000); ++ if (is_10g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x01423342); ++ else if (is_5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00a132a1); ++ else if (is_2p5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x009c329c); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00fa32fa); ++ ++ /* Force SGDT_OUT off and select PCS */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_F4, ++ XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL, ++ XFI_DPHY_AD_SGDT_FRC_EN | ++ (is_xgmii ? XFI_DPHY_PCS_SEL_USXGMII : ++ XFI_DPHY_PCS_SEL_SGMII)); ++ ++ ++ /* Force GLB_CKDET_OUT */ ++ mtk_xfi_tphy_set(xfi_tphy, 0x0030, 0xc00); ++ ++ /* Force AEQ on */ ++ mtk_xfi_tphy_write(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_RX_EQ_IN_PROGRESS(2) | ++ XTP_PCS_PWD_SYNC(2) | ++ XTP_PCS_PWD_ASYNC(2)); ++ ++ usleep_range(1, 5); ++ ++ /* Setup TX DA default value */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x30b0, 0x30, 0x20); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3028, 0x00008a01); ++ mtk_xfi_tphy_write(xfi_tphy, 0x302c, 0x0000a884); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3024, 0x00083002); ++ ++ /* Setup RG default value */ ++ if (is_xgmii) { ++ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00022220); ++ mtk_xfi_tphy_write(xfi_tphy, 0x5064, 0x0f020a01); ++ mtk_xfi_tphy_write(xfi_tphy, 0x50b4, 0x06100600); ++ if (interface == PHY_INTERFACE_MODE_USXGMII) ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x47684100); ++ } else { ++ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00011110); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000); ++ } ++ ++ if (is_1g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x3064, 0x0000c000); ++ ++ /* Setup RX EQ initial value */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x3050, 0xa8000000, ++ (interface != PHY_INTERFACE_MODE_10GBASER) ? ++ 0xa8000000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x3054, 0xaa, ++ (interface != PHY_INTERFACE_MODE_10GBASER) ? ++ 0xaa : 0x0); ++ ++ if (is_xgmii) ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x00000f00); ++ else if (is_2p5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x22000f00); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x20200f00); ++ ++ if (interface == PHY_INTERFACE_MODE_10GBASER && xfi_tphy->da_war) ++ mtk_xfi_tphy_rmw(xfi_tphy, 0xa008, 0x10000, 0x10000); ++ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0xa060, 0x50000, is_xgmii ? 0x40000 : ++ 0x50000); ++ ++ /* Setup PHYA speed */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_ANA_GLB_D0, ++ XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN, ++ is_10g ? XTP_GLB_USXGMII_SEL(0) : ++ is_5g ? XTP_GLB_USXGMII_SEL(1) : ++ is_2p5g ? XTP_GLB_USXGMII_SEL(2) : ++ XTP_GLB_USXGMII_SEL(3)); ++ mtk_xfi_tphy_set(xfi_tphy, REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN); ++ ++ /* Release reset */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_RST_B | XTP_FRC_PCS_RST_B); ++ usleep_range(150, 500); ++ ++ /* Switch to P0 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_PWD_SYNC_MASK | ++ XTP_PCS_PWD_ASYNC_MASK, ++ XTP_FRC_PCS_PWD_ASYNC | ++ XTP_PCS_UPDT | XTP_PCS_IN_FR_RG); ++ usleep_range(1, 5); ++ ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT); ++ usleep_range(15, 50); ++ ++ if (is_xgmii) { ++ /* Switch to Gen3 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_MODE_MASK | XTP_PCS_UPDT, ++ XTP_PCS_MODE(2) | XTP_PCS_UPDT); ++ } else { ++ /* Switch to Gen2 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_MODE_MASK | XTP_PCS_UPDT, ++ XTP_PCS_MODE(1) | XTP_PCS_UPDT); ++ } ++ usleep_range(1, 5); ++ ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT); ++ ++ usleep_range(100, 500); ++ ++ /* Enable MAC CK */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN); ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN); ++ ++ /* Enable TX data */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_40, ++ XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN); ++ usleep_range(400, 1000); ++} ++ ++static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int ++ submode) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ if (mode != PHY_MODE_ETHERNET) ++ return -EINVAL; ++ ++ switch (submode) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ mtk_xfi_tphy_setup(xfi_tphy, submode); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int mtk_xfi_tphy_reset(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ reset_control_assert(xfi_tphy->reset); ++ usleep_range(100, 500); ++ reset_control_deassert(xfi_tphy->reset); ++ usleep_range(1, 10); ++ ++ return 0; ++} ++ ++static int mtk_xfi_tphy_power_on(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); ++} ++ ++static int mtk_xfi_tphy_power_off(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); ++ ++ return 0; ++} ++ ++static const struct phy_ops mtk_xfi_tphy_ops = { ++ .power_on = mtk_xfi_tphy_power_on, ++ .power_off = mtk_xfi_tphy_power_off, ++ .set_mode = mtk_xfi_tphy_set_mode, ++ .reset = mtk_xfi_tphy_reset, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_xfi_tphy_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct phy_provider *phy_provider; ++ struct mtk_xfi_tphy *xfi_tphy; ++ struct phy *phy; ++ ++ if (!np) ++ return -ENODEV; ++ ++ xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL); ++ if (!xfi_tphy) ++ return -ENOMEM; ++ ++ xfi_tphy->base = devm_of_iomap(&pdev->dev, np, 0, NULL); ++ if (!xfi_tphy->base) ++ return -EIO; ++ ++ xfi_tphy->dev = &pdev->dev; ++ ++ xfi_tphy->clocks[0].id = "topxtal"; ++ xfi_tphy->clocks[0].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[0].id); ++ if (IS_ERR(xfi_tphy->clocks[0].clk)) ++ return PTR_ERR(xfi_tphy->clocks[0].clk); ++ ++ xfi_tphy->clocks[1].id = "xfipll"; ++ xfi_tphy->clocks[1].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[1].id); ++ if (IS_ERR(xfi_tphy->clocks[1].clk)) ++ return PTR_ERR(xfi_tphy->clocks[1].clk); ++ ++ xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(xfi_tphy->reset)) ++ return PTR_ERR(xfi_tphy->reset); ++ ++ xfi_tphy->da_war = of_property_read_bool(np, ++ "mediatek,usxgmii-performance-errata"); ++ ++ phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops); ++ if (IS_ERR(phy)) ++ return PTR_ERR(phy); ++ ++ phy_set_drvdata(phy, xfi_tphy); ++ ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, ++ of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id mtk_xfi_tphy_match[] = { ++ { .compatible = "mediatek,mt7988-xfi-tphy", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match); ++ ++static struct platform_driver mtk_xfi_tphy_driver = { ++ .probe = mtk_xfi_tphy_probe, ++ .driver = { ++ .name = "mtk-xfi-tphy", ++ .of_match_table = mtk_xfi_tphy_match, ++ }, ++}; ++module_platform_driver(mtk_xfi_tphy_driver); ++ ++MODULE_DESCRIPTION("MediaTek XFI T-PHY driver"); ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_AUTHOR("Bc-bocun Chen "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch new file mode 100644 index 0000000000..adb95e9587 --- /dev/null +++ b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch @@ -0,0 +1,371 @@ +From 4b1a2716299c0e96a698044aebf3f80513509ae7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:18 +0000 +Subject: [PATCH 3/5] net: pcs: pcs-mtk-lynxi: add platform driver for MT7988 + +Introduce a proper platform MFD driver for the LynxI (H)SGMII PCS which +is going to initially be used for the MT7988 SoC. + +Signed-off-by: Daniel Golle +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 227 ++++++++++++++++++++++++++++-- + include/linux/pcs/pcs-mtk-lynxi.h | 11 ++ + 2 files changed, 227 insertions(+), 11 deletions(-) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + // Copyright (c) 2018-2019 MediaTek Inc. +-/* A library for MediaTek SGMII circuit ++/* A library and platform driver for the MediaTek LynxI SGMII circuit + * + * Author: Sean Wang + * Author: Alexander Couzens +@@ -8,11 +8,17 @@ + * + */ + ++#include + #include ++#include ++#include + #include ++#include + #include + #include ++#include + #include ++#include + + /* SGMII subsystem config registers */ + /* BMCR (low 16) BMSR (high 16) */ +@@ -65,6 +71,8 @@ + #define SGMII_PN_SWAP_MASK GENMASK(1, 0) + #define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) + ++#define MTK_NETSYS_V3_AMA_RGC3 0x128 ++ + /* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated + * data + * @regmap: The register map pointing at the range used to setup +@@ -74,15 +82,29 @@ + * @interface: Currently configured interface mode + * @pcs: Phylink PCS structure + * @flags: Flags indicating hardware properties ++ * @rstc: Reset controller ++ * @sgmii_sel: SGMII Register Clock ++ * @sgmii_rx: SGMII RX Clock ++ * @sgmii_tx: SGMII TX Clock ++ * @node: List node + */ + struct mtk_pcs_lynxi { + struct regmap *regmap; ++ struct device *dev; + u32 ana_rgc3; + phy_interface_t interface; + struct phylink_pcs pcs; + u32 flags; ++ struct reset_control *rstc; ++ struct clk *sgmii_sel; ++ struct clk *sgmii_rx; ++ struct clk *sgmii_tx; ++ struct list_head node; + }; + ++static LIST_HEAD(mtk_pcs_lynxi_instances); ++static DEFINE_MUTEX(instance_mutex); ++ + static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) + { + return container_of(pcs, struct mtk_pcs_lynxi, pcs); +@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru + FIELD_GET(SGMII_LPA, adv)); + } + ++static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) ++{ ++ if (!mpcs->rstc) ++ return; ++ ++ reset_control_assert(mpcs->rstc); ++ udelay(100); ++ reset_control_deassert(mpcs->rstc); ++ mdelay(1); ++} ++ + static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, +@@ -148,6 +181,7 @@ static int mtk_pcs_lynxi_config(struct p + SGMII_PHYA_PWD); + + /* Reset SGMII PCS state */ ++ mtk_sgmii_reset(mpcs); + regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, + SGMII_SW_RESET); + +@@ -234,10 +268,29 @@ static void mtk_pcs_lynxi_link_up(struct + } + } + ++static int mtk_pcs_lynxi_enable(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_prepare_enable(mpcs->sgmii_rx); ++ clk_prepare_enable(mpcs->sgmii_tx); ++ } ++ ++ return 0; ++} ++ + static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_disable_unprepare(mpcs->sgmii_tx); ++ clk_disable_unprepare(mpcs->sgmii_rx); ++ } ++ + mpcs->interface = PHY_INTERFACE_MODE_NA; + } + +@@ -247,11 +300,12 @@ static const struct phylink_pcs_ops mtk_ + .pcs_an_restart = mtk_pcs_lynxi_restart_an, + .pcs_link_up = mtk_pcs_lynxi_link_up, + .pcs_disable = mtk_pcs_lynxi_disable, ++ .pcs_enable = mtk_pcs_lynxi_enable, + }; + +-struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, +- struct regmap *regmap, u32 ana_rgc3, +- u32 flags) ++static struct phylink_pcs *mtk_pcs_lynxi_init(struct device *dev, struct regmap *regmap, ++ u32 ana_rgc3, u32 flags, ++ struct mtk_pcs_lynxi *prealloc) + { + struct mtk_pcs_lynxi *mpcs; + u32 id, ver; +@@ -259,29 +313,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create + + ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + if (id != SGMII_LYNXI_DEV_ID) { + dev_err(dev, "unknown PCS device id %08x\n", id); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + ver = FIELD_GET(SGMII_DEV_VERSION, ver); + if (ver != 0x1) { + dev_err(dev, "unknown PCS device version %04x\n", ver); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, + ver); + +- mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); +- if (!mpcs) +- return NULL; ++ if (prealloc) { ++ mpcs = prealloc; ++ } else { ++ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return ERR_PTR(-ENOMEM); ++ }; + + mpcs->ana_rgc3 = ana_rgc3; + mpcs->regmap = regmap; +@@ -292,6 +350,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create + mpcs->interface = PHY_INTERFACE_MODE_NA; + + return &mpcs->pcs; ++}; ++ ++struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, ++ struct regmap *regmap, u32 ana_rgc3, ++ u32 flags) ++{ ++ return mtk_pcs_lynxi_init(dev, regmap, ana_rgc3, flags, NULL); + } + EXPORT_SYMBOL(mtk_pcs_lynxi_create); + +@@ -304,4 +369,144 @@ void mtk_pcs_lynxi_destroy(struct phylin + } + EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); + ++static int mtk_pcs_lynxi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct mtk_pcs_lynxi *mpcs; ++ struct phylink_pcs *pcs; ++ struct regmap *regmap; ++ u32 flags = 0; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->dev = dev; ++ regmap = syscon_node_to_regmap(np->parent); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ if (of_property_read_bool(np->parent, "mediatek,pnswap")) ++ flags |= MTK_SGMII_FLAG_PN_SWAP; ++ ++ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL); ++ if (IS_ERR(mpcs->rstc)) ++ return PTR_ERR(mpcs->rstc); ++ ++ reset_control_deassert(mpcs->rstc); ++ mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel"); ++ if (IS_ERR(mpcs->sgmii_sel)) ++ return PTR_ERR(mpcs->sgmii_sel); ++ ++ mpcs->sgmii_rx = devm_clk_get(dev, "sgmii_rx"); ++ if (IS_ERR(mpcs->sgmii_rx)) ++ return PTR_ERR(mpcs->sgmii_rx); ++ ++ mpcs->sgmii_tx = devm_clk_get(dev, "sgmii_tx"); ++ if (IS_ERR(mpcs->sgmii_tx)) ++ return PTR_ERR(mpcs->sgmii_tx); ++ ++ pcs = mtk_pcs_lynxi_init(dev, regmap, (uintptr_t)of_device_get_match_data(dev), ++ flags, mpcs); ++ if (IS_ERR(pcs)) ++ return PTR_ERR(pcs); ++ ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ mutex_lock(&instance_mutex); ++ list_add_tail(&mpcs->node, &mtk_pcs_lynxi_instances); ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static int mtk_pcs_lynxi_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_pcs_lynxi *cur, *tmp; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry_safe(cur, tmp, &mtk_pcs_lynxi_instances, node) ++ if (cur->dev == dev) { ++ list_del(&cur->node); ++ kfree(cur); ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_pcs_lynxi_of_match[] = { ++ { .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_pcs_lynxi_of_match); ++ ++struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np) ++{ ++ struct platform_device *pdev; ++ struct mtk_pcs_lynxi *mpcs; ++ ++ if (!np) ++ return NULL; ++ ++ if (!of_device_is_available(np)) ++ return ERR_PTR(-ENODEV); ++ ++ if (!of_match_node(mtk_pcs_lynxi_of_match, np)) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev || !platform_get_drvdata(pdev)) { ++ if (pdev) ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ mpcs = platform_get_drvdata(pdev); ++ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER); ++ ++ return &mpcs->pcs; ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_get); ++ ++void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *cur, *mpcs = NULL; ++ ++ if (!pcs) ++ return; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry(cur, &mtk_pcs_lynxi_instances, node) ++ if (pcs == &cur->pcs) { ++ mpcs = cur; ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ if (WARN_ON(!mpcs)) ++ return; ++ ++ put_device(mpcs->dev); ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_put); ++ ++static struct platform_driver mtk_pcs_lynxi_driver = { ++ .driver = { ++ .name = "mtk-pcs-lynxi", ++ .suppress_bind_attrs = true, ++ .of_match_table = mtk_pcs_lynxi_of_match, ++ }, ++ .probe = mtk_pcs_lynxi_probe, ++ .remove = mtk_pcs_lynxi_remove, ++}; ++module_platform_driver(mtk_pcs_lynxi_driver); ++ ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_DESCRIPTION("MediaTek LynxI HSGMII PCS"); + MODULE_LICENSE("GPL"); +--- a/include/linux/pcs/pcs-mtk-lynxi.h ++++ b/include/linux/pcs/pcs-mtk-lynxi.h +@@ -10,4 +10,15 @@ struct phylink_pcs *mtk_pcs_lynxi_create + struct regmap *regmap, + u32 ana_rgc3, u32 flags); + void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); ++ ++#if IS_ENABLED(CONFIG_PCS_MTK_LYNXI) ++struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np); ++void mtk_pcs_lynxi_put(struct phylink_pcs *pcs); ++#else ++static inline struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np) ++{ ++ return NULL; ++} ++static inline void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) { } ++#endif /* IS_ENABLED(CONFIG_PCS_MTK_LYNXI) */ + #endif diff --git a/target/linux/generic/pending-6.6/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch b/target/linux/generic/pending-6.6/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch new file mode 100644 index 0000000000..215bd2ca2e --- /dev/null +++ b/target/linux/generic/pending-6.6/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch @@ -0,0 +1,81 @@ +From 7d88d79c0f65b27a92754d7547f7af098b3de67b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:31 +0000 +Subject: [PATCH 4/5] dt-bindings: net: pcs: add bindings for MediaTek USXGMII + PCS + +MediaTek's USXGMII can be found in the MT7988 SoC. We need to access +it in order to configure and monitor the Ethernet SerDes link in +USXGMII, 10GBase-R and 5GBase-R mode. By including a wrapped +legacy 1000Base-X/2500Base-X/Cisco SGMII LynxI PCS as well, those +interface modes are also available. + +Signed-off-by: Daniel Golle +--- + .../bindings/net/pcs/mediatek,usxgmii.yaml | 60 +++++++++++++++++++ + 1 file changed, 60 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml +@@ -0,0 +1,60 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/pcs/mediatek,usxgmii.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek USXGMII PCS ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek USXGMII PCS provides physical link control and status ++ for USXGMII, 10GBase-R and 5GBase-R links on the SerDes interfaces ++ provided by the PEXTP PHY. ++ In order to also support legacy 2500Base-X, 1000Base-X and Cisco ++ SGMII an existing mediatek,*-sgmiisys LynxI PCS is wrapped to ++ provide those interfaces modes on the same SerDes interfaces shared ++ with the USXGMII PCS. ++ ++properties: ++ $nodename: ++ pattern: "^pcs@[0-9a-f]+$" ++ ++ compatible: ++ const: mediatek,mt7988-usxgmiisys ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: USXGMII top-level clock ++ ++ resets: ++ items: ++ - description: XFI reset ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #define MT7988_TOPRGU_XFI0_GRST 12 ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ usxgmiisys0: pcs@10080000 { ++ compatible = "mediatek,mt7988-usxgmiisys"; ++ reg = <0 0x10080000 0 0x1000>; ++ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>; ++ resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>; ++ }; ++ }; diff --git a/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch new file mode 100644 index 0000000000..5bd2850fec --- /dev/null +++ b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -0,0 +1,547 @@ +From dde0e95fff92e9f5009f3bea75278e0e34a48822 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:47 +0000 +Subject: [PATCH 5/5] net: pcs: add driver for MediaTek USXGMII PCS + +Add driver for USXGMII PCS found in the MediaTek MT7988 SoC and supporting +USXGMII, 10GBase-R and 5GBase-R interface modes. + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 2 + + drivers/net/pcs/Kconfig | 11 + + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs-mtk-usxgmii.c | 456 ++++++++++++++++++++++++++++ + include/linux/pcs/pcs-mtk-usxgmii.h | 27 ++ + 5 files changed, 497 insertions(+) + create mode 100644 drivers/net/pcs/pcs-mtk-usxgmii.c + create mode 100644 include/linux/pcs/pcs-mtk-usxgmii.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -12934,7 +12934,9 @@ M: Daniel Golle + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/pcs/pcs-mtk-lynxi.c ++F: drivers/net/pcs/pcs-mtk-usxgmii.c + F: include/linux/pcs/pcs-mtk-lynxi.h ++F: include/linux/pcs/pcs-mtk-usxgmii.h + + MEDIATEK I2C CONTROLLER DRIVER + M: Qii Wang +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -18,6 +18,17 @@ config PCS_LYNX + This module provides helpers to phylink for managing the Lynx PCS + which is part of the Layerscape and QorIQ Ethernet SERDES. + ++config PCS_MTK_USXGMII ++ tristate "MediaTek USXGMII PCS" ++ select PCS_MTK_LYNXI ++ select PHY_MTK_PEXTP ++ select PHYLINK ++ help ++ This module provides a driver for MediaTek's USXGMII PCS supporting ++ 10GBase-R, 5GBase-R and USXGMII interface modes. ++ 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same ++ differential pairs via an embedded LynxI PHY. ++ + config PCS_RZN1_MIIC + tristate "Renesas RZ/N1 MII converter" + depends on OF && (ARCH_RZN1 || COMPILE_TEST) +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o + obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o + obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o ++obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o +--- /dev/null ++++ b/drivers/net/pcs/pcs-mtk-usxgmii.c +@@ -0,0 +1,456 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2023 MediaTek Inc. ++ * Author: Henry Yen ++ * Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* USXGMII subsystem config registers */ ++/* Register to control speed */ ++#define RG_PHY_TOP_SPEED_CTRL1 0x80c ++#define USXGMII_RATE_UPDATE_MODE BIT(31) ++#define USXGMII_MAC_CK_GATED BIT(29) ++#define USXGMII_IF_FORCE_EN BIT(28) ++#define USXGMII_RATE_ADAPT_MODE GENMASK(10, 8) ++#define USXGMII_RATE_ADAPT_MODE_X1 0 ++#define USXGMII_RATE_ADAPT_MODE_X2 1 ++#define USXGMII_RATE_ADAPT_MODE_X4 2 ++#define USXGMII_RATE_ADAPT_MODE_X10 3 ++#define USXGMII_RATE_ADAPT_MODE_X100 4 ++#define USXGMII_RATE_ADAPT_MODE_X5 5 ++#define USXGMII_RATE_ADAPT_MODE_X50 6 ++#define USXGMII_XFI_RX_MODE GENMASK(6, 4) ++#define USXGMII_XFI_TX_MODE GENMASK(2, 0) ++#define USXGMII_XFI_MODE_10G 0 ++#define USXGMII_XFI_MODE_5G 1 ++#define USXGMII_XFI_MODE_2P5G 3 ++ ++/* Register to control PCS AN */ ++#define RG_PCS_AN_CTRL0 0x810 ++#define USXGMII_AN_RESTART BIT(31) ++#define USXGMII_AN_SYNC_CNT GENMASK(30, 11) ++#define USXGMII_AN_ENABLE BIT(0) ++ ++#define RG_PCS_AN_CTRL2 0x818 ++#define USXGMII_LINK_TIMER_IDLE_DETECT GENMASK(29, 20) ++#define USXGMII_LINK_TIMER_COMP_ACK_DETECT GENMASK(19, 10) ++#define USXGMII_LINK_TIMER_AN_RESTART GENMASK(9, 0) ++ ++/* Register to read PCS AN status */ ++#define RG_PCS_AN_STS0 0x81c ++#define USXGMII_LPA GENMASK(15, 0) ++#define USXGMII_LPA_LATCH BIT(31) ++ ++/* Register to read PCS link status */ ++#define RG_PCS_RX_STATUS0 0x904 ++#define RG_PCS_RX_STATUS_UPDATE BIT(16) ++#define RG_PCS_RX_LINK_STATUS BIT(2) ++ ++/* struct mtk_usxgmii_pcs - This structure holds each usxgmii PCS ++ * @pcs: Phylink PCS structure ++ * @dev: Pointer to device structure ++ * @base: IO memory to access PCS hardware ++ * @clk: Pointer to USXGMII clk ++ * @reset: Pointer to USXGMII reset control ++ * @interface: Currently selected interface mode ++ * @neg_mode: Currently used phylink neg_mode ++ * @node: List node ++ */ ++struct mtk_usxgmii_pcs { ++ struct phylink_pcs pcs; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++ struct reset_control *reset; ++ phy_interface_t interface; ++ unsigned int neg_mode; ++ struct list_head node; ++}; ++ ++static LIST_HEAD(mtk_usxgmii_pcs_instances); ++static DEFINE_MUTEX(instance_mutex); ++ ++static u32 mtk_r32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg) ++{ ++ return ioread32(mpcs->base + reg); ++} ++ ++static void mtk_m32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = ioread32(mpcs->base + reg); ++ val &= ~mask; ++ val |= set; ++ iowrite32(val, mpcs->base + reg); ++} ++ ++static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mtk_usxgmii_pcs, pcs); ++} ++ ++static void mtk_usxgmii_reset(struct mtk_usxgmii_pcs *mpcs) ++{ ++ reset_control_assert(mpcs->reset); ++ udelay(100); ++ reset_control_deassert(mpcs->reset); ++ ++ mdelay(10); ++} ++ ++static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0; ++ bool mode_changed = false; ++ ++ if (interface == PHY_INTERFACE_MODE_USXGMII) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) | USXGMII_AN_ENABLE; ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ } else if (interface == PHY_INTERFACE_MODE_10GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else if (interface == PHY_INTERFACE_MODE_5GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_5G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_5G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else { ++ return -EINVAL; ++ } ++ ++ adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1); ++ ++ if (mpcs->interface != interface) { ++ mpcs->interface = interface; ++ mode_changed = true; ++ } ++ ++ mtk_usxgmii_reset(mpcs); ++ ++ /* Setup USXGMII AN ctrl */ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, ++ USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE, ++ an_ctrl); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL2, ++ USXGMII_LINK_TIMER_IDLE_DETECT | ++ USXGMII_LINK_TIMER_COMP_ACK_DETECT | ++ USXGMII_LINK_TIMER_AN_RESTART, ++ link_timer); ++ ++ mpcs->neg_mode = neg_mode; ++ ++ /* Gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED); ++ ++ /* Enable interface force mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN); ++ ++ /* Setup USXGMII adapt mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE, ++ adapt_mode); ++ ++ /* Setup USXGMII speed */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE, ++ xfi_mode); ++ ++ usleep_range(1, 10); ++ ++ /* Un-gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_MAC_CK_GATED, 0); ++ ++ usleep_range(1, 10); ++ ++ /* Disable interface force mode for the AN mode */ ++ if (an_ctrl & USXGMII_AN_ENABLE) ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_IF_FORCE_EN, 0); ++ ++ return mode_changed; ++} ++ ++static void mtk_usxgmii_pcs_get_fixed_speed(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u32 val = mtk_r32(mpcs, RG_PHY_TOP_SPEED_CTRL1); ++ int speed; ++ ++ /* Calculate speed from interface speed and rate adapt mode */ ++ switch (FIELD_GET(USXGMII_XFI_RX_MODE, val)) { ++ case USXGMII_XFI_MODE_10G: ++ speed = 10000; ++ break; ++ case USXGMII_XFI_MODE_5G: ++ speed = 5000; ++ break; ++ case USXGMII_XFI_MODE_2P5G: ++ speed = 2500; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ switch (FIELD_GET(USXGMII_RATE_ADAPT_MODE, val)) { ++ case USXGMII_RATE_ADAPT_MODE_X100: ++ speed /= 100; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X50: ++ speed /= 50; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X10: ++ speed /= 10; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X5: ++ speed /= 5; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X4: ++ speed /= 4; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X2: ++ speed /= 2; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X1: ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ state->speed = speed; ++ state->duplex = DUPLEX_FULL; ++} ++ ++static void mtk_usxgmii_pcs_get_an_state(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u16 lpa; ++ ++ /* Refresh LPA by toggling LPA_LATCH */ ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, USXGMII_LPA_LATCH); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, 0); ++ ndelay(1020); ++ lpa = FIELD_GET(USXGMII_LPA, mtk_r32(mpcs, RG_PCS_AN_STS0)); ++ ++ phylink_decode_usxgmii_word(state, lpa); ++} ++ ++static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ /* Refresh USXGMII link status by toggling RG_PCS_AN_STATUS_UPDATE */ ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, ++ RG_PCS_RX_STATUS_UPDATE); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, 0); ++ ndelay(1020); ++ ++ /* Read USXGMII link status */ ++ state->link = FIELD_GET(RG_PCS_RX_LINK_STATUS, ++ mtk_r32(mpcs, RG_PCS_RX_STATUS0)); ++ ++ /* Continuously repeat re-configuration sequence until link comes up */ ++ if (!state->link) { ++ mtk_usxgmii_pcs_config(pcs, mpcs->neg_mode, ++ state->interface, NULL, false); ++ return; ++ } ++ ++ if (FIELD_GET(USXGMII_AN_ENABLE, mtk_r32(mpcs, RG_PCS_AN_CTRL0))) ++ mtk_usxgmii_pcs_get_an_state(mpcs, state); ++ else ++ mtk_usxgmii_pcs_get_fixed_speed(mpcs, state); ++} ++ ++static void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, USXGMII_AN_RESTART, USXGMII_AN_RESTART); ++} ++ ++static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ int speed, int duplex) ++{ ++ /* Reconfiguring USXGMII to ensure the quality of the RX signal ++ * after the line side link up. ++ */ ++ mtk_usxgmii_pcs_config(pcs, neg_mode, interface, NULL, false); ++} ++ ++static void mtk_usxgmii_pcs_disable(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++} ++ ++static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = { ++ .pcs_config = mtk_usxgmii_pcs_config, ++ .pcs_get_state = mtk_usxgmii_pcs_get_state, ++ .pcs_an_restart = mtk_usxgmii_pcs_restart_an, ++ .pcs_link_up = mtk_usxgmii_pcs_link_up, ++ .pcs_disable = mtk_usxgmii_pcs_disable, ++}; ++ ++static int mtk_usxgmii_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_usxgmii_pcs *mpcs; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mpcs->base)) ++ return PTR_ERR(mpcs->base); ++ ++ mpcs->dev = dev; ++ mpcs->pcs.ops = &mtk_usxgmii_pcs_ops; ++ mpcs->pcs.poll = true; ++ mpcs->pcs.neg_mode = true; ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++ ++ mpcs->clk = devm_clk_get_enabled(mpcs->dev, NULL); ++ if (IS_ERR(mpcs->clk)) ++ return PTR_ERR(mpcs->clk); ++ ++ mpcs->reset = devm_reset_control_get_shared(dev, NULL); ++ if (IS_ERR(mpcs->reset)) ++ return PTR_ERR(mpcs->reset); ++ ++ reset_control_deassert(mpcs->reset); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ mutex_lock(&instance_mutex); ++ list_add_tail(&mpcs->node, &mtk_usxgmii_pcs_instances); ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static int mtk_usxgmii_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_usxgmii_pcs *cur, *tmp; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry_safe(cur, tmp, &mtk_usxgmii_pcs_instances, node) ++ if (cur->dev == dev) { ++ list_del(&cur->node); ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_usxgmii_of_mtable[] = { ++ { .compatible = "mediatek,mt7988-usxgmiisys" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_usxgmii_of_mtable); ++ ++struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np) ++{ ++ struct platform_device *pdev; ++ struct mtk_usxgmii_pcs *mpcs; ++ ++ if (!np) ++ return NULL; ++ ++ if (!of_device_is_available(np)) ++ return ERR_PTR(-ENODEV); ++ ++ if (!of_match_node(mtk_usxgmii_of_mtable, np)) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev || !platform_get_drvdata(pdev)) { ++ if (pdev) ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ mpcs = platform_get_drvdata(pdev); ++ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER); ++ ++ return &mpcs->pcs; ++} ++EXPORT_SYMBOL(mtk_usxgmii_pcs_get); ++ ++void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *cur, *mpcs = NULL; ++ ++ if (!pcs) ++ return; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry(cur, &mtk_usxgmii_pcs_instances, node) ++ if (pcs == &cur->pcs) { ++ mpcs = cur; ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ if (WARN_ON(!mpcs)) ++ return; ++ ++ put_device(mpcs->dev); ++} ++EXPORT_SYMBOL(mtk_usxgmii_pcs_put); ++ ++static struct platform_driver mtk_usxgmii_driver = { ++ .driver = { ++ .name = "mtk_usxgmii", ++ .suppress_bind_attrs = true, ++ .of_match_table = mtk_usxgmii_of_mtable, ++ }, ++ .probe = mtk_usxgmii_probe, ++ .remove = mtk_usxgmii_remove, ++}; ++module_platform_driver(mtk_usxgmii_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MediaTek USXGMII PCS driver"); ++MODULE_AUTHOR("Daniel Golle "); +--- /dev/null ++++ b/include/linux/pcs/pcs-mtk-usxgmii.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __LINUX_PCS_MTK_USXGMII_H ++#define __LINUX_PCS_MTK_USXGMII_H ++ ++#include ++ ++/** ++ * mtk_usxgmii_select_pcs() - Get MediaTek PCS instance ++ * @np: Pointer to device node indentifying a MediaTek USXGMII PCS ++ * @mode: Ethernet PHY interface mode ++ * ++ * Return PCS identified by a device node and the PHY interface mode in use ++ * ++ * Return: Pointer to phylink PCS instance of NULL ++ */ ++#if IS_ENABLED(CONFIG_PCS_MTK_USXGMII) ++struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np); ++void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs); ++#else ++static inline struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np) ++{ ++ return NULL; ++} ++static inline void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs) { } ++#endif /* IS_ENABLED(CONFIG_PCS_MTK_USXGMII) */ ++ ++#endif /* __LINUX_PCS_MTK_USXGMII_H */ diff --git a/target/linux/generic/pending-6.6/740-net-phy-motorcomm-Add-missing-include.patch b/target/linux/generic/pending-6.6/740-net-phy-motorcomm-Add-missing-include.patch new file mode 100644 index 0000000000..2a1f908cfb --- /dev/null +++ b/target/linux/generic/pending-6.6/740-net-phy-motorcomm-Add-missing-include.patch @@ -0,0 +1,22 @@ +From 6f291aa7da199c6486cc229b055dcbcd5cee7a21 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 21 May 2023 22:24:56 +0200 +Subject: [PATCH] net: phy: motorcomm: Add missing include + +Directly include linux/bitfield.h which provides FIELD_PREP. + +Signed-off-by: Hauke Mehrtens +--- + drivers/net/phy/motorcomm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -6,6 +6,7 @@ + * Author: Frank + */ + ++#include + #include + #include + #include diff --git a/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch new file mode 100644 index 0000000000..51cd98c883 --- /dev/null +++ b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -0,0 +1,63 @@ +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -981,6 +981,51 @@ static int rtl8221b_config_init(struct p + return 0; + } + ++static int rtl8221b_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read_mmd(phydev, RTL8221B_MMD_PHY_CTRL, 0xa4d4); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl8221b_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl8221b_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ err = phy_write_mmd(phydev, RTL8221B_MMD_PHY_CTRL, 0xa4d2, 0x7ff); ++ } else { ++ err = phy_write_mmd(phydev, RTL8221B_MMD_PHY_CTRL, 0xa4d2, 0x0); ++ if (err) ++ return err; ++ ++ err = rtl8221b_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = rtl8221b_ack_interrupt(phydev); ++ if (err) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ + static struct phy_driver realtek_drvs[] = { + { + PHY_ID_MATCH_EXACT(0x00008201), +@@ -1141,6 +1186,8 @@ static struct phy_driver realtek_drvs[] + .get_features = rtl822x_get_features, + .config_init = rtl8221b_config_init, + .config_aneg = rtl822x_config_aneg, ++ .config_intr = rtl8221b_config_intr, ++ .handle_interrupt = rtl8221b_handle_interrupt, + .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, diff --git a/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch b/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch new file mode 100644 index 0000000000..1dfa1366eb --- /dev/null +++ b/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch @@ -0,0 +1,1115 @@ +From patchwork Tue Feb 6 19:47:51 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Eric Woudstra +X-Patchwork-Id: 13547762 +X-Patchwork-Delegate: kuba@kernel.org +From: Eric Woudstra +To: "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Andrew Lunn , + Heiner Kallweit , + Russell King , + Matthias Brugger , + AngeloGioacchino Del Regno , + "Frank Wunderlich" , + Daniel Golle , + Lucien Jheng , + Zhi-Jun You +Cc: netdev@vger.kernel.org, + devicetree@vger.kernel.org, + Eric Woudstra +Subject: [PATCH net-next 2/2] net: phy: air_en8811h: Add the Airoha EN8811H + PHY driver +Date: Tue, 6 Feb 2024 20:47:51 +0100 +Message-ID: <20240206194751.1901802-3-ericwouds@gmail.com> +X-Mailer: git-send-email 2.42.1 +In-Reply-To: <20240206194751.1901802-1-ericwouds@gmail.com> +References: <20240206194751.1901802-1-ericwouds@gmail.com> +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-Patchwork-Delegate: kuba@kernel.org + +* Source originated from airoha's en8811h v1.2.1 driver + * Moved air_en8811h.h to air_en8811h.c + * Removed air_pbus_reg_write() as it writes to another device on mdio-bus + * Load firmware from /lib/firmware/airoha/ instead of /lib/firmware/ + * Added .get_rate_matching() + * Use generic phy_read/write() and phy_read/write_mmd() + * Edited .get_features() to use generic C45 functions + * Edited .config_aneg() and .read_status() to use a mix of generic C22/C45 + * Use led handling functions from mediatek-ge-soc.c + * Simplified led handling by storing led rules + * Cleanup macro definitions + * Cleanup code to pass checkpatch.pl + * General code cleanup + +Changes from original RFC patch: + + * Use the correct order in Kconfig and Makefile + * Change some register naming to correspond with datasheet + * Use phy_driver .read_page() and .write_page() + * Use module_phy_driver() + * Use get_unaligned_le16() instead of macro + * In .config_aneg() and .read_status() use genphy_xxx() C22 + * Use another vendor register to read real speed + * Load firmware only once and store firmware version + * Apply 2.5G LPA work-around (firmware before 24011202) + * Read 2.5G LPA from vendor register (firmware 24011202 and later) + +Changes to be committed: + modified: drivers/net/phy/Kconfig + modified: drivers/net/phy/Makefile + new file: drivers/net/phy/air_en8811h.c + +Signed-off-by: Eric Woudstra +--- + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/air_en8811h.c | 1006 +++++++++++++++++++++++++++++++++ + 3 files changed, 1012 insertions(+) + create mode 100644 drivers/net/phy/air_en8811h.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -69,6 +69,11 @@ config SFP + + comment "MII PHY device drivers" + ++config AIR_EN8811H_PHY ++ tristate "Airoha EN8811H 2.5 Gigabit PHY" ++ help ++ Currently supports the Airoha EN8811H PHY. ++ + config AMD_PHY + tristate "AMD and Altima PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -32,6 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o ++obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o +--- /dev/null ++++ b/drivers/net/phy/air_en8811h.c +@@ -0,0 +1,1006 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Airoha Ethernet PHYs ++ * ++ * Currently supporting the EN8811H. ++ * ++ * Limitations of the EN8811H: ++ * - Only full duplex supported ++ * - Forced speed (AN off) is not supported by hardware (100Mbps) ++ * ++ * Source originated from airoha's en8811h.c and en8811h.h v1.2.1 ++ * ++ * Copyright (C) 2023 Airoha Technology Corp. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#define EN8811H_PHY_ID 0x03a2a411 ++ ++#define EN8811H_MD32_DM "airoha/EthMD32.dm.bin" ++#define EN8811H_MD32_DSP "airoha/EthMD32.DSP.bin" ++ ++#define AIR_FW_ADDR_DM 0x00000000 ++#define AIR_FW_ADDR_DSP 0x00100000 ++ ++/* u32 (DWORD) component macros */ ++#define LOWORD(d) ((u16)(u32)(d)) ++#define HIWORD(d) ((u16)(((u32)(d)) >> 16)) ++ ++/* MII Registers */ ++#define AIR_AUX_CTRL_STATUS 0x1d ++#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2) ++#define AIR_AUX_CTRL_STATUS_SPEED_100 0x4 ++#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 ++#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc ++ ++#define AIR_EXT_PAGE_ACCESS 0x1f ++#define AIR_PHY_PAGE_STANDARD 0x0000 ++#define AIR_PHY_PAGE_EXTENDED_4 0x0004 ++ ++/* MII Registers Page 4*/ ++#define AIR_PBUS_MODE 0x10 ++#define AIR_PBUS_MODE_ADDR_FIXED 0x0000 ++#define AIR_PBUS_MODE_ADDR_INCR BIT(15) ++#define AIR_PBUS_WR_ADDR_HIGH 0x11 ++#define AIR_PBUS_WR_ADDR_LOW 0x12 ++#define AIR_PBUS_WR_DATA_HIGH 0x13 ++#define AIR_PBUS_WR_DATA_LOW 0x14 ++#define AIR_PBUS_RD_ADDR_HIGH 0x15 ++#define AIR_PBUS_RD_ADDR_LOW 0x16 ++#define AIR_PBUS_RD_DATA_HIGH 0x17 ++#define AIR_PBUS_RD_DATA_LOW 0x18 ++ ++/* Registers on MDIO_MMD_VEND1 */ ++#define EN8811H_PHY_FW_STATUS 0x8009 ++#define EN8811H_PHY_READY 0x02 ++ ++#define AIR_PHY_HOST_CMD_1 0x800c ++#define AIR_PHY_HOST_CMD_1_MODE1 0x0 ++#define AIR_PHY_HOST_CMD_2 0x800d ++#define AIR_PHY_HOST_CMD_2_MODE1 0x0 ++#define AIR_PHY_HOST_CMD_3 0x800e ++#define AIR_PHY_HOST_CMD_3_MODE1 0x1101 ++#define AIR_PHY_HOST_CMD_3_DOCMD 0x1100 ++#define AIR_PHY_HOST_CMD_4 0x800f ++#define AIR_PHY_HOST_CMD_4_MODE1 0x0002 ++#define AIR_PHY_HOST_CMD_4_INTCLR 0x00e4 ++ ++/* Registers on MDIO_MMD_VEND2 */ ++#define AIR_PHY_LED_BCR 0x021 ++#define AIR_PHY_LED_BCR_MODE_MASK GENMASK(1, 0) ++#define AIR_PHY_LED_BCR_TIME_TEST BIT(2) ++#define AIR_PHY_LED_BCR_CLK_EN BIT(3) ++#define AIR_PHY_LED_BCR_EXT_CTRL BIT(15) ++ ++#define AIR_PHY_LED_DUR_ON 0x022 ++ ++#define AIR_PHY_LED_DUR_BLINK 0x023 ++ ++#define AIR_PHY_LED_ON(i) (0x024 + ((i) * 2)) ++#define AIR_PHY_LED_ON_MASK (GENMASK(6, 0) | BIT(8)) ++#define AIR_PHY_LED_ON_LINK1000 BIT(0) ++#define AIR_PHY_LED_ON_LINK100 BIT(1) ++#define AIR_PHY_LED_ON_LINK10 BIT(2) ++#define AIR_PHY_LED_ON_LINKDOWN BIT(3) ++#define AIR_PHY_LED_ON_FDX BIT(4) /* Full duplex */ ++#define AIR_PHY_LED_ON_HDX BIT(5) /* Half duplex */ ++#define AIR_PHY_LED_ON_FORCE_ON BIT(6) ++#define AIR_PHY_LED_ON_LINK2500 BIT(8) ++#define AIR_PHY_LED_ON_POLARITY BIT(14) ++#define AIR_PHY_LED_ON_ENABLE BIT(15) ++ ++#define AIR_PHY_LED_BLINK(i) (0x025 + ((i) * 2)) ++#define AIR_PHY_LED_BLINK_1000TX BIT(0) ++#define AIR_PHY_LED_BLINK_1000RX BIT(1) ++#define AIR_PHY_LED_BLINK_100TX BIT(2) ++#define AIR_PHY_LED_BLINK_100RX BIT(3) ++#define AIR_PHY_LED_BLINK_10TX BIT(4) ++#define AIR_PHY_LED_BLINK_10RX BIT(5) ++#define AIR_PHY_LED_BLINK_COLLISION BIT(6) ++#define AIR_PHY_LED_BLINK_RX_CRC_ERR BIT(7) ++#define AIR_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) ++#define AIR_PHY_LED_BLINK_FORCE_BLINK BIT(9) ++#define AIR_PHY_LED_BLINK_2500TX BIT(10) ++#define AIR_PHY_LED_BLINK_2500RX BIT(11) ++ ++/* Registers on BUCKPBUS */ ++#define EN8811H_2P5G_LPA 0x3b30 ++#define EN8811H_2P5G_LPA_2P5G BIT(0) ++ ++#define EN8811H_FW_VERSION 0x3b3c ++ ++#define EN8811H_POLARITY 0xca0f8 ++#define EN8811H_POLARITY_TX_NORMAL BIT(0) ++#define EN8811H_POLARITY_RX_REVERSE BIT(1) ++ ++#define EN8811H_GPIO_OUTPUT 0xcf8b8 ++#define EN8811H_GPIO_OUTPUT_345 (BIT(3) | BIT(4) | BIT(5)) ++ ++#define EN8811H_FW_CTRL_1 0x0f0018 ++#define EN8811H_FW_CTRL_1_START 0x0 ++#define EN8811H_FW_CTRL_1_FINISH 0x1 ++#define EN8811H_FW_CTRL_2 0x800000 ++#define EN8811H_FW_CTRL_2_LOADING BIT(11) ++ ++#define EN8811H_LED_COUNT 3 ++ ++/* GPIO5 <-> BASE_T_LED0 ++ * GPIO4 <-> BASE_T_LED1 ++ * GPIO3 <-> BASE_T_LED2 ++ * ++ * Default setup suitable for 2 leds connected: ++ * 100M link up triggers led0, only led0 blinking on traffic ++ * 1000M link up triggers led1, only led1 blinking on traffic ++ * 2500M link up triggers led0 and led1, both blinking on traffic ++ * Also suitable for 1 led connected: ++ * any link up triggers led2 ++ */ ++#define AIR_DEFAULT_TRIGGER_LED0 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_100) | \ ++ BIT(TRIGGER_NETDEV_RX) | \ ++ BIT(TRIGGER_NETDEV_TX)) ++#define AIR_DEFAULT_TRIGGER_LED1 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_1000) | \ ++ BIT(TRIGGER_NETDEV_RX) | \ ++ BIT(TRIGGER_NETDEV_TX)) ++#define AIR_DEFAULT_TRIGGER_LED2 BIT(TRIGGER_NETDEV_LINK) ++ ++struct led { ++ unsigned long rules; ++ unsigned long state; ++}; ++ ++struct en8811h_priv { ++ u32 firmware_version; ++ struct led led[EN8811H_LED_COUNT]; ++}; ++ ++enum { ++ AIR_PHY_LED_STATE_FORCE_ON, ++ AIR_PHY_LED_STATE_FORCE_BLINK, ++}; ++ ++enum { ++ AIR_PHY_LED_DUR_BLINK_32M, ++ AIR_PHY_LED_DUR_BLINK_64M, ++ AIR_PHY_LED_DUR_BLINK_128M, ++ AIR_PHY_LED_DUR_BLINK_256M, ++ AIR_PHY_LED_DUR_BLINK_512M, ++ AIR_PHY_LED_DUR_BLINK_1024M, ++}; ++ ++enum { ++ AIR_LED_DISABLE, ++ AIR_LED_ENABLE, ++}; ++ ++enum { ++ AIR_ACTIVE_LOW, ++ AIR_ACTIVE_HIGH, ++}; ++ ++enum { ++ AIR_LED_MODE_DISABLE, ++ AIR_LED_MODE_USER_DEFINE, ++}; ++ ++#define AIR_PHY_LED_DUR_UNIT 1024 ++#define AIR_PHY_LED_DUR (AIR_PHY_LED_DUR_UNIT << AIR_PHY_LED_DUR_BLINK_64M) ++ ++static const unsigned long en8811h_led_trig = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | ++ BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_LINK_2500) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)); ++ ++static int air_phy_read_page(struct phy_device *phydev) ++{ ++ return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); ++} ++ ++static int air_phy_write_page(struct phy_device *phydev, int page) ++{ ++ return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page); ++} ++ ++static int __air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_HIGH, HIWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_LOW, LOWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_HIGH, HIWORD(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_LOW, LOWORD(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_buckpbus_reg_write(phydev, pbus_address, pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++; ++} ++ ++static int __air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int pbus_data_low, pbus_data_high; ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_RD_ADDR_HIGH, HIWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_RD_ADDR_LOW, LOWORD(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ pbus_data_high = __phy_read(phydev, AIR_PBUS_RD_DATA_HIGH); ++ if (pbus_data_high < 0) ++ return ret; ++ ++ pbus_data_low = __phy_read(phydev, AIR_PBUS_RD_DATA_LOW); ++ if (pbus_data_low < 0) ++ return ret; ++ ++ *pbus_data = (u16)pbus_data_low | ((u32)(u16)pbus_data_high << 16); ++ return 0; ++} ++ ++static int air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int __air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ unsigned int offset; ++ int ret; ++ u16 val; ++ ++ ret = __phy_write(phydev, AIR_PBUS_MODE, AIR_PBUS_MODE_ADDR_INCR); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_HIGH, HIWORD(address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_PBUS_WR_ADDR_LOW, LOWORD(address)); ++ if (ret < 0) ++ return ret; ++ ++ for (offset = 0; offset < fw->size; offset += 4) { ++ val = get_unaligned_le16(&fw->data[offset + 2]); ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_HIGH, val); ++ if (ret < 0) ++ return ret; ++ ++ val = get_unaligned_le16(&fw->data[offset]); ++ ret = __phy_write(phydev, AIR_PBUS_WR_DATA_LOW, val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ int ret, saved_page; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ ret = __air_write_buf(phydev, address, fw); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ address, ret); ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int en8811h_load_firmware(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw1, *fw2; ++ u32 pbus_value; ++ int ret; ++ ++ ret = request_firmware_direct(&fw1, EN8811H_MD32_DM, dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = request_firmware_direct(&fw2, EN8811H_MD32_DSP, dev); ++ if (ret < 0) ++ goto en8811h_load_firmware_rel1; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_CTRL_2, &pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ pbus_value |= EN8811H_FW_CTRL_2_LOADING; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_2, pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DM, fw1); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, fw2); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_CTRL_2, &pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ pbus_value &= ~EN8811H_FW_CTRL_2_LOADING; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_2, pbus_value); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = 0; ++ ++en8811h_load_firmware_out: ++ release_firmware(fw2); ++ ++en8811h_load_firmware_rel1: ++ release_firmware(fw1); ++ ++ if (ret < 0) ++ phydev_err(phydev, "Load firmware failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int en8811h_restart_host(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ return ret; ++ ++ return air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++} ++ ++static int air_hw_led_on_set(struct phy_device *phydev, u8 index, bool on) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (on) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, ++ on ? AIR_PHY_LED_ON_FORCE_ON : 0); ++ ++ return 0; ++} ++ ++static int air_hw_led_blink_set(struct phy_device *phydev, u8 index, ++ bool blinking) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (blinking) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_BLINK(index), ++ blinking ? ++ AIR_PHY_LED_BLINK_FORCE_BLINK : 0); ++ else ++ return 0; ++} ++ ++static int air_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool blinking = false; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { ++ blinking = true; ++ *delay_on = 50; ++ *delay_off = 50; ++ } ++ ++ err = air_hw_led_blink_set(phydev, index, blinking); ++ if (err) ++ return err; ++ ++ /* led-blink set, so switch led-on off */ ++ err = air_hw_led_on_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ /* hw-control is off*/ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_brightness_set(struct phy_device *phydev, u8 index, ++ enum led_brightness value) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* led-on set, so switch led-blink off */ ++ err = air_hw_led_blink_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ err = air_hw_led_on_set(phydev, index, (value != LED_OFF)); ++ if (err) ++ return err; ++ ++ /* hw-control is off */ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ *rules = priv->led[index].rules; ++ ++ return 0; ++}; ++ ++static int air_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u16 on = 0, blink = 0; ++ int ret; ++ ++ priv->led[index].rules = rules; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK10; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_10RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_10TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK100; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_100RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_100TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK1000; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_1000RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_1000TX; ++ } ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK))) { ++ on |= AIR_PHY_LED_ON_LINK2500; ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ blink |= AIR_PHY_LED_BLINK_2500RX; ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ blink |= AIR_PHY_LED_BLINK_2500TX; ++ } ++ ++ if (on == 0) { ++ if (rules & BIT(TRIGGER_NETDEV_RX)) { ++ blink |= AIR_PHY_LED_BLINK_10RX | ++ AIR_PHY_LED_BLINK_100RX | ++ AIR_PHY_LED_BLINK_1000RX | ++ AIR_PHY_LED_BLINK_2500RX; ++ } ++ if (rules & BIT(TRIGGER_NETDEV_TX)) { ++ blink |= AIR_PHY_LED_BLINK_10TX | ++ AIR_PHY_LED_BLINK_100TX | ++ AIR_PHY_LED_BLINK_1000TX | ++ AIR_PHY_LED_BLINK_2500TX; ++ } ++ } ++ ++ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) ++ on |= AIR_PHY_LED_ON_FDX; ++ ++ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) ++ on |= AIR_PHY_LED_ON_HDX; ++ ++ if (blink || on) { ++ /* switch hw-control on, so led-on and led-blink are off */ ++ clear_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state); ++ clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state); ++ } else { ++ priv->led[index].rules = 0; ++ } ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, on); ++ ++ if (ret < 0) ++ return ret; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BLINK(index), ++ blink); ++}; ++ ++static int air_led_init(struct phy_device *phydev, u8 index, u8 state, u8 pol) ++{ ++ int cl45_data; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ cl45_data = phy_read_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index)); ++ if (cl45_data < 0) ++ return cl45_data; ++ ++ if (state == AIR_LED_ENABLE) ++ cl45_data |= AIR_PHY_LED_ON_ENABLE; ++ else ++ cl45_data &= ~AIR_PHY_LED_ON_ENABLE; ++ ++ if (pol == AIR_ACTIVE_HIGH) ++ cl45_data |= AIR_PHY_LED_ON_POLARITY; ++ else ++ cl45_data &= ~AIR_PHY_LED_ON_POLARITY; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ cl45_data); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int air_leds_init(struct phy_device *phydev, int num, int dur, int mode) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int cl45_data = dur; ++ int ret, i; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK, ++ cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ cl45_data >>= 1; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_ON, ++ cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ cl45_data = phy_read_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR); ++ if (cl45_data < 0) ++ return cl45_data; ++ ++ switch (mode) { ++ case AIR_LED_MODE_DISABLE: ++ cl45_data &= ~AIR_PHY_LED_BCR_EXT_CTRL; ++ cl45_data &= ~AIR_PHY_LED_BCR_MODE_MASK; ++ break; ++ case AIR_LED_MODE_USER_DEFINE: ++ cl45_data |= AIR_PHY_LED_BCR_EXT_CTRL; ++ cl45_data |= AIR_PHY_LED_BCR_CLK_EN; ++ break; ++ default: ++ phydev_err(phydev, "LED mode %d is not supported\n", mode); ++ return -EINVAL; ++ } ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR, cl45_data); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < num; ++i) { ++ ret = air_led_init(phydev, i, AIR_LED_ENABLE, AIR_ACTIVE_HIGH); ++ if (ret < 0) { ++ phydev_err(phydev, "LED%d init failed: %d\n", i, ret); ++ return ret; ++ } ++ air_led_hw_control_set(phydev, i, priv->led[i].rules); ++ } ++ ++ return 0; ++} ++ ++static int en8811h_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* All combinations of the supported triggers are allowed */ ++ if (rules & ~en8811h_led_trig) ++ return -EOPNOTSUPP; ++ ++ return 0; ++}; ++ ++static int en8811h_probe(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv; ++ ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct en8811h_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->led[0].rules = AIR_DEFAULT_TRIGGER_LED0; ++ priv->led[1].rules = AIR_DEFAULT_TRIGGER_LED1; ++ priv->led[2].rules = AIR_DEFAULT_TRIGGER_LED2; ++ ++ phydev->priv = priv; ++ ++ /* MDIO_DEVS1/2 empty, so set mmds_present bits here */ ++ phydev->c45_ids.mmds_present |= MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; ++ ++ return 0; ++} ++ ++static int en8811h_config_init(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ int ret, pollret, reg_value; ++ u32 pbus_value; ++ ++ if (!priv->firmware_version) ++ ret = en8811h_load_firmware(phydev); ++ else ++ ret = en8811h_restart_host(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Because of mdio-lock, may have to wait for multiple loads */ ++ pollret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ EN8811H_PHY_FW_STATUS, reg_value, ++ reg_value == EN8811H_PHY_READY, ++ 20000, 7500000, true); ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, &pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ if (pollret || !pbus_value) { ++ phydev_err(phydev, "Firmware not ready: 0x%x\n", reg_value); ++ return -ENODEV; ++ } ++ ++ if (!priv->firmware_version) { ++ phydev_info(phydev, "MD32 firmware version: %08x\n", pbus_value); ++ priv->firmware_version = pbus_value; ++ } ++ ++ /* Select mode 1, the only mode supported */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_1, ++ AIR_PHY_HOST_CMD_1_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_2, ++ AIR_PHY_HOST_CMD_2_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_3, ++ AIR_PHY_HOST_CMD_3_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_4, ++ AIR_PHY_HOST_CMD_4_MODE1); ++ if (ret < 0) ++ return ret; ++ ++ /* Serdes polarity */ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_POLARITY, &pbus_value); ++ if (ret < 0) ++ return ret; ++ if (device_property_read_bool(dev, "airoha,pnswap-rx")) ++ pbus_value |= EN8811H_POLARITY_RX_REVERSE; ++ else ++ pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; ++ if (device_property_read_bool(dev, "airoha,pnswap-tx")) ++ pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; ++ else ++ pbus_value |= EN8811H_POLARITY_TX_NORMAL; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_POLARITY, pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, ++ AIR_LED_MODE_USER_DEFINE); ++ if (ret < 0) { ++ phydev_err(phydev, "Failed to initialize leds: %d\n", ret); ++ return ret; ++ } ++ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_GPIO_OUTPUT, &pbus_value); ++ if (ret < 0) ++ return ret; ++ pbus_value |= EN8811H_GPIO_OUTPUT_345; ++ ret = air_buckpbus_reg_write(phydev, EN8811H_GPIO_OUTPUT, pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int en8811h_get_features(struct phy_device *phydev) ++{ ++ linkmode_set_bit_array(phy_basic_ports_array, ++ ARRAY_SIZE(phy_basic_ports_array), ++ phydev->supported); ++ ++ return genphy_c45_pma_read_abilities(phydev); ++} ++ ++static int en8811h_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ return RATE_MATCH_PAUSE; ++} ++ ++static int en8811h_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ int err, val; ++ ++ val = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ val |= MDIO_AN_10GBT_CTRL_ADV2_5G; ++ err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, val); ++ if (err < 0) ++ return err; ++ if (err > 0) ++ changed = true; ++ ++ return __genphy_config_aneg(phydev, changed); ++} ++ ++static int en8811h_read_status(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u32 pbus_value; ++ int ret, val; ++ ++ ret = genphy_update_link(phydev); ++ if (ret) ++ return ret; ++ ++ phydev->master_slave_get = MASTER_SLAVE_CFG_UNSUPPORTED; ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_read_lpa(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Get link partner 2.5GBASE-T ability from vendor register */ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, &pbus_value); ++ if (ret < 0) ++ return ret; ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ pbus_value & EN8811H_2P5G_LPA_2P5G); ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ if (!phydev->link) ++ return 0; ++ ++ /* Get real speed from vendor register */ ++ val = phy_read(phydev, AIR_AUX_CTRL_STATUS); ++ if (val < 0) ++ return val; ++ switch (val & AIR_AUX_CTRL_STATUS_SPEED_MASK) { ++ case AIR_AUX_CTRL_STATUS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ } ++ ++ /* BUG in PHY firmware: MDIO_AN_10GBT_STAT_LP2_5G does not get set. ++ * Firmware before version 24011202 has no vendor register 2P5G_LPA. ++ * Assume link partner advertised it if connected at 2500Mbps. ++ */ ++ if (priv->firmware_version < 0x24011202) { ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ phydev->speed == SPEED_2500); ++ } ++ ++ /* Only supports full duplex */ ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static int en8811h_clear_intr(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_3, ++ AIR_PHY_HOST_CMD_3_DOCMD); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_HOST_CMD_4, ++ AIR_PHY_HOST_CMD_4_INTCLR); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static irqreturn_t en8811h_handle_interrupt(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = en8811h_clear_intr(phydev); ++ if (ret < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct phy_driver en8811h_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID), ++ .name = "Airoha EN8811H", ++ .probe = en8811h_probe, ++ .get_features = en8811h_get_features, ++ .config_init = en8811h_config_init, ++ .get_rate_matching = en8811h_get_rate_matching, ++ .config_aneg = en8811h_config_aneg, ++ .read_status = en8811h_read_status, ++ .config_intr = en8811h_clear_intr, ++ .handle_interrupt = en8811h_handle_interrupt, ++ .led_hw_is_supported = en8811h_led_hw_is_supported, ++ .read_page = air_phy_read_page, ++ .write_page = air_phy_write_page, ++ .led_blink_set = air_led_blink_set, ++ .led_brightness_set = air_led_brightness_set, ++ .led_hw_control_set = air_led_hw_control_set, ++ .led_hw_control_get = air_led_hw_control_get, ++} }; ++ ++module_phy_driver(en8811h_driver); ++ ++static struct mdio_device_id __maybe_unused en8811h_tbl[] = { ++ { PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(mdio, en8811h_tbl); ++MODULE_FIRMWARE(EN8811H_MD32_DM); ++MODULE_FIRMWARE(EN8811H_MD32_DSP); ++ ++MODULE_DESCRIPTION("Airoha EN8811H PHY drivers"); ++MODULE_AUTHOR("Airoha"); ++MODULE_AUTHOR("Eric Woudstra "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch new file mode 100644 index 0000000000..42c8519c90 --- /dev/null +++ b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -0,0 +1,227 @@ +From: Felix Fietkau +Date: Thu, 16 Feb 2023 18:39:04 +0100 +Subject: [PATCH] net/core: add optional threading for backlog processing + +When dealing with few flows or an imbalance on CPU utilization, static RPS +CPU assignment can be too inflexible. Add support for enabling threaded NAPI +for backlog processing in order to allow the scheduler to better balance +processing. This helps better spread the load across idle CPUs. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -543,6 +543,7 @@ static inline bool napi_complete(struct + } + + int dev_set_threaded(struct net_device *dev, bool threaded); ++int backlog_set_threaded(bool threaded); + + /** + * napi_disable - prevent NAPI from scheduling +@@ -3152,6 +3153,7 @@ struct softnet_data { + unsigned int processed; + unsigned int time_squeeze; + unsigned int received_rps; ++ unsigned int process_queue_empty; + #ifdef CONFIG_RPS + struct softnet_data *rps_ipi_list; + #endif +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4625,7 +4625,7 @@ static int napi_schedule_rps(struct soft + struct softnet_data *mysd = this_cpu_ptr(&softnet_data); + + #ifdef CONFIG_RPS +- if (sd != mysd) { ++ if (sd != mysd && !test_bit(NAPI_STATE_THREADED, &sd->backlog.state)) { + sd->rps_ipi_next = mysd->rps_ipi_list; + mysd->rps_ipi_list = sd; + +@@ -5806,6 +5806,8 @@ static DEFINE_PER_CPU(struct work_struct + /* Network device is going away, flush any packets still pending */ + static void flush_backlog(struct work_struct *work) + { ++ unsigned int process_queue_empty; ++ bool threaded, flush_processq; + struct sk_buff *skb, *tmp; + struct softnet_data *sd; + +@@ -5820,8 +5822,17 @@ static void flush_backlog(struct work_st + input_queue_head_incr(sd); + } + } ++ ++ threaded = test_bit(NAPI_STATE_THREADED, &sd->backlog.state); ++ flush_processq = threaded && ++ !skb_queue_empty_lockless(&sd->process_queue); ++ if (flush_processq) ++ process_queue_empty = sd->process_queue_empty; + rps_unlock_irq_enable(sd); + ++ if (threaded) ++ goto out; ++ + skb_queue_walk_safe(&sd->process_queue, skb, tmp) { + if (skb->dev->reg_state == NETREG_UNREGISTERING) { + __skb_unlink(skb, &sd->process_queue); +@@ -5829,7 +5840,16 @@ static void flush_backlog(struct work_st + input_queue_head_incr(sd); + } + } ++ ++out: + local_bh_enable(); ++ ++ while (flush_processq) { ++ msleep(1); ++ rps_lock_irq_disable(sd); ++ flush_processq = process_queue_empty == sd->process_queue_empty; ++ rps_unlock_irq_enable(sd); ++ } + } + + static bool flush_required(int cpu) +@@ -5961,6 +5981,7 @@ static int process_backlog(struct napi_s + } + + rps_lock_irq_disable(sd); ++ sd->process_queue_empty++; + if (skb_queue_empty(&sd->input_pkt_queue)) { + /* + * Inline a custom version of __napi_complete(). +@@ -5970,7 +5991,8 @@ static int process_backlog(struct napi_s + * We can use a plain write instead of clear_bit(), + * and we dont need an smp_mb() memory barrier. + */ +- napi->state = 0; ++ napi->state &= ~(NAPIF_STATE_SCHED | ++ NAPIF_STATE_SCHED_THREADED); + again = false; + } else { + skb_queue_splice_tail_init(&sd->input_pkt_queue, +@@ -6386,6 +6408,55 @@ int dev_set_threaded(struct net_device * + } + EXPORT_SYMBOL(dev_set_threaded); + ++int backlog_set_threaded(bool threaded) ++{ ++ static bool backlog_threaded; ++ int err = 0; ++ int i; ++ ++ if (backlog_threaded == threaded) ++ return 0; ++ ++ for_each_possible_cpu(i) { ++ struct softnet_data *sd = &per_cpu(softnet_data, i); ++ struct napi_struct *n = &sd->backlog; ++ ++ if (n->thread) ++ continue; ++ n->thread = kthread_run(napi_threaded_poll, n, "napi/backlog-%d", i); ++ if (IS_ERR(n->thread)) { ++ err = PTR_ERR(n->thread); ++ pr_err("kthread_run failed with err %d\n", err); ++ n->thread = NULL; ++ threaded = false; ++ break; ++ } ++ ++ } ++ ++ backlog_threaded = threaded; ++ ++ /* Make sure kthread is created before THREADED bit ++ * is set. ++ */ ++ smp_mb__before_atomic(); ++ ++ for_each_possible_cpu(i) { ++ struct softnet_data *sd = &per_cpu(softnet_data, i); ++ struct napi_struct *n = &sd->backlog; ++ unsigned long flags; ++ ++ rps_lock_irqsave(sd, &flags); ++ if (threaded) ++ n->state |= NAPIF_STATE_THREADED; ++ else ++ n->state &= ~NAPIF_STATE_THREADED; ++ rps_unlock_irq_restore(sd, &flags); ++ } ++ ++ return err; ++} ++ + void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, + int (*poll)(struct napi_struct *, int), int weight) + { +@@ -11168,6 +11239,9 @@ static int dev_cpu_dead(unsigned int old + raise_softirq_irqoff(NET_TX_SOFTIRQ); + local_irq_enable(); + ++ if (test_bit(NAPI_STATE_THREADED, &oldsd->backlog.state)) ++ return 0; ++ + #ifdef CONFIG_RPS + remsd = oldsd->rps_ipi_list; + oldsd->rps_ipi_list = NULL; +@@ -11480,6 +11554,7 @@ static int __init net_dev_init(void) + INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); + spin_lock_init(&sd->defer_lock); + ++ INIT_LIST_HEAD(&sd->backlog.poll_list); + init_gro_hash(&sd->backlog); + sd->backlog.poll = process_backlog; + sd->backlog.weight = weight_p; +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -29,6 +29,7 @@ static int int_3600 = 3600; + static int min_sndbuf = SOCK_MIN_SNDBUF; + static int min_rcvbuf = SOCK_MIN_RCVBUF; + static int max_skb_frags = MAX_SKB_FRAGS; ++static int backlog_threaded; + + static int net_msg_warn; /* Unused, but still a sysctl */ + +@@ -112,6 +113,23 @@ static int rps_sock_flow_sysctl(struct c + } + #endif /* CONFIG_RPS */ + ++static int backlog_threaded_sysctl(struct ctl_table *table, int write, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ static DEFINE_MUTEX(backlog_threaded_mutex); ++ int ret; ++ ++ mutex_lock(&backlog_threaded_mutex); ++ ++ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); ++ if (write && !ret) ++ ret = backlog_set_threaded(backlog_threaded); ++ ++ mutex_unlock(&backlog_threaded_mutex); ++ ++ return ret; ++} ++ + #ifdef CONFIG_NET_FLOW_LIMIT + static DEFINE_MUTEX(flow_limit_update_mutex); + +@@ -473,6 +491,15 @@ static struct ctl_table net_core_table[] + .proc_handler = rps_sock_flow_sysctl + }, + #endif ++ { ++ .procname = "backlog_threaded", ++ .data = &backlog_threaded, ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = backlog_threaded_sysctl, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_ONE ++ }, + #ifdef CONFIG_NET_FLOW_LIMIT + { + .procname = "flow_limit_cpu_bitmap", diff --git a/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..9556c90b57 --- /dev/null +++ b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -0,0 +1,27 @@ +From: Tobias Waldekranz +Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port +Date: Sat, 16 Jan 2021 02:25:15 +0100 +Archived-At: + +While the hardware is capable of performing learning on the CPU port, +it requires alot of additions to the bridge's forwarding path in order +to handle multi-destination traffic correctly. + +Until that is in place, opt for the next best thing and let DSA sync +the relevant addresses down to the hardware FDB. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -7025,6 +7025,7 @@ static int mv88e6xxx_register_switch(str + ds->ops = &mv88e6xxx_switch_ops; + ds->ageing_time_min = chip->info->age_time_coeff; + ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; ++ ds->assisted_learning_on_cpu_port = true; + + /* Some chips support up to 32, but that requires enabling the + * 5-bit port mode, which we do not support. 640k^W16 ought to diff --git a/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch b/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch new file mode 100644 index 0000000000..23859816fa --- /dev/null +++ b/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch @@ -0,0 +1,174 @@ +From patchwork Sun Mar 19 22:08:05 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13180645 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id A7A46C6FD1F + for ; Sun, 19 Mar 2023 22:08:15 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S230223AbjCSWIN (ORCPT ); + Sun, 19 Mar 2023 18:08:13 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32878 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S229565AbjCSWIM (ORCPT + ); Sun, 19 Mar 2023 18:08:12 -0400 +Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com + [IPv6:2a00:1450:4864:20::42e]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 605D3E062; + Sun, 19 Mar 2023 15:08:10 -0700 (PDT) +Received: by mail-wr1-x42e.google.com with SMTP id h17so8695188wrt.8; + Sun, 19 Mar 2023 15:08:10 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679263689; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=GmPK75Q9ZD3h3IYflWYuDwS99V2e532KgDlnNucAoJg=; + b=PSdrywW48P4Lq8z9wOSPXFB/ZdO/JfuyiGlw3Gz1Iriy+Smo/cBnJ0Ve9zKkX3AKTO + Tr7/g8xhSQX8sU5WAOEPC13uVjKpO4VZsamXHTmMKL4mmfII3K/piAsQcMQkkNpgouab + Ci9yr+7ASSmqEUHIbYTM6sl6a47rPwqk3b3DcTIE2CwJsPPNXnpQ/aSVbJAcEdhcZICc + X4rAmjrYjcsl8coFIGHHPlrMH9ShekQWxB84vEb6bO1nXOORNPizOHuY1vJ3wa3WgXsx + YwlvutMFVIUXfgL2ZwCmQAKWJPiAaFk+CCk3oxSeOYoAzkjcbMyapz9VnooStfvR2aV3 + k+2g== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679263689; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=GmPK75Q9ZD3h3IYflWYuDwS99V2e532KgDlnNucAoJg=; + b=NGjqrGERyaxRwINtevHaY97h9X9W+1UY62YYwotqwv5+cfvB8myjBbD3WH2WzaqMes + o9MMER9RE8/arW3jIVlBv4ORDUuEZ7AeGgy5UbFyQZIPHlp+hJ/sxFrGvYUwamg4Qrr9 + ojargh8ORsEiMeqaf+5AkmEagNhrrV3ax0pUuWDzbJ3vXGoHjfCetHz5xyNL46dvXBfb + l/OZqjv9IYob552uUoUmCy/TbEQDqvmjkFrROFK9gtBNxgxUJkwbyiWIOVsf6RR8OarP + f7bbvSJYkvTvzx2u/g0Up7NW5ZyihMGBmDs377M3yW6AnSxW6jlfl30QmMU1aEigYXvy + v3mA== +X-Gm-Message-State: AO0yUKUm1PYmYa4xlHuVD23mZcZm83a+xbhcbs0Xryi3yF/+UnjM4Cho + GAfqSh5MZ/rlOAm3Vnpn//9hOG5Lc8vLYg== +X-Google-Smtp-Source: + AK7set+5pTahGGgk1hF/mHGkGBhsMf0//oQjZd4QFHx+HaeSgP5f6q7g0bRUcTX8kRtgHH0T7l1/hQ== +X-Received: by 2002:a5d:474f:0:b0:2d6:2ae8:70d with SMTP id + o15-20020a5d474f000000b002d62ae8070dmr2382593wrs.39.1679263688549; + Sun, 19 Mar 2023 15:08:08 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + d6-20020a5d6dc6000000b002c53f6c7599sm7354727wrz.29.2023.03.19.15.08.07 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Sun, 19 Mar 2023 15:08:07 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, + olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, + kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v2] net: dsa: b53: add support for BCM63xx RGMIIs +Date: Sun, 19 Mar 2023 23:08:05 +0100 +Message-Id: <20230319220805.124024-1-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230319183330.761251-1-noltari@gmail.com> +References: <20230319183330.761251-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +BCM63xx RGMII ports require additional configuration in order to work. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Andrew Lunn +--- + v2: add changes suggested by Andrew: + - Use a switch statement. + - Use dev_dbg() instead of dev_info(). + + drivers/net/dsa/b53/b53_common.c | 46 ++++++++++++++++++++++++++++++++ + drivers/net/dsa/b53/b53_priv.h | 1 + + 2 files changed, 47 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1209,6 +1209,46 @@ static void b53_force_port_config(struct + b53_write8(dev, B53_CTRL_PAGE, off, reg); + } + ++static void b53_adjust_63xx_rgmii(struct dsa_switch *ds, int port, ++ phy_interface_t interface) ++{ ++ struct b53_device *dev = ds->priv; ++ u8 rgmii_ctrl = 0, off; ++ ++ if (port == dev->imp_port) ++ off = B53_RGMII_CTRL_IMP; ++ else ++ off = B53_RGMII_CTRL_P(port); ++ ++ b53_read8(dev, B53_CTRL_PAGE, off, &rgmii_ctrl); ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ rgmii_ctrl |= (RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ rgmii_ctrl &= ~(RGMII_CTRL_DLL_TXC); ++ rgmii_ctrl |= RGMII_CTRL_DLL_RXC; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC); ++ rgmii_ctrl |= RGMII_CTRL_DLL_TXC; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ default: ++ rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); ++ break; ++ } ++ ++ if (port != dev->imp_port) ++ rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; ++ ++ b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); ++ ++ dev_dbg(ds->dev, "Configured port %d for %s\n", port, ++ phy_modes(interface)); ++} ++ + static void b53_adjust_link(struct dsa_switch *ds, int port, + struct phy_device *phydev) + { +@@ -1235,6 +1275,9 @@ static void b53_adjust_link(struct dsa_s + tx_pause, rx_pause); + b53_force_link(dev, port, phydev->link); + ++ if (is63xx(dev) && port >= B53_63XX_RGMII0) ++ b53_adjust_63xx_rgmii(ds, port, phydev->interface); ++ + if (is531x5(dev) && phy_interface_is_rgmii(phydev)) { + if (port == dev->imp_port) + off = B53_RGMII_CTRL_IMP; +@@ -1402,6 +1445,9 @@ void b53_phylink_mac_link_up(struct dsa_ + { + struct b53_device *dev = ds->priv; + ++ if (is63xx(dev) && port >= B53_63XX_RGMII0) ++ b53_adjust_63xx_rgmii(ds, port, interface); ++ + if (mode == MLO_AN_PHY) + return; + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -211,6 +211,7 @@ static inline int is58xx(struct b53_devi + dev->chip_id == BCM7278_DEVICE_ID; + } + ++#define B53_63XX_RGMII0 4 + #define B53_CPU_PORT_25 5 + #define B53_CPU_PORT 8 + diff --git a/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch b/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch new file mode 100644 index 0000000000..8ab701ef56 --- /dev/null +++ b/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch @@ -0,0 +1,108 @@ +From patchwork Tue Mar 21 17:33:57 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13183003 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 823A1C761AF + for ; Tue, 21 Mar 2023 17:35:06 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S230490AbjCURfE (ORCPT ); + Tue, 21 Mar 2023 13:35:04 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47440 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S230357AbjCURex (ORCPT + ); Tue, 21 Mar 2023 13:34:53 -0400 +Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com + [IPv6:2a00:1450:4864:20::430]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C9A45559D8; + Tue, 21 Mar 2023 10:34:26 -0700 (PDT) +Received: by mail-wr1-x430.google.com with SMTP id m2so14547588wrh.6; + Tue, 21 Mar 2023 10:34:26 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679420063; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=cUvnluVaZPzfEQB9fMRuYo+4/361t/7po7nyUBBJfxc=; + b=F0pa8JmQZ1FeXVtdpCygur8UmLrgKwxCcjaMn312u5zNvsXsEPeCAIDqP2tvNNTwv/ + UYjaNaoZ77HSvv/gSqeG808AXGyNs1PvLuHZYuUTJRNuLaMixKtkNFi4ypheCdk0WCiE + IWz0DIm6ojmdwMqafDUKQ6Qwkv5R0vo8Wh5vpjimEmCelOyMvfuLZNqubsiGqpnCguBp + uWlmKh95/VubCGgiGG2xK1IXQayL14ENuWseDds7nVpVK50NycrFgJbL17Bd6qJKYkbo + m70IC+9jM0hjwKXpyi6ipCBNcW+1E6JIwILVC04Xi+BTpOGhbUAQ59Yn2hyq7tQM7dzs + 4PLg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679420063; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=cUvnluVaZPzfEQB9fMRuYo+4/361t/7po7nyUBBJfxc=; + b=SCX78yTuGjdnE5nuL0p7+kxGnOzsCExsigLdaV+x/JswmwxSpZvxn223i1yM95klj9 + Rk0RnXqATLF1wZA7L1YmbeZ66zxUwW/osnCjJHPeEF8AGgjK/qawtLl/HJQHN67NaRNQ + bDsRn2nWQ2GRTRFpvD+iGRy4uyQCDu9HFxLbn43fBsBmRnXWGPQP5cEb90tL83/Onp4D + Lx/XcyZOh9QRfJNhj+G1BAeRCLRA/sdA0W3Ecu5SCFs+LtS6uvLVGWDKEDfnZhYY8Xqf + Mx9evWzdW2OorEN2FI6+xTglvnEBcVhHIJ7XEGAhCG6ocgMZeck++774S8RWumWl8xpy + /K9Q== +X-Gm-Message-State: AO0yUKUORAlGfbkNwnYmQnTWcGPqW6sp4g9WfgQmRZGCV+9tCB0OebSP + ICq6v4YPmUPNRl/WNnVCbps= +X-Google-Smtp-Source: + AK7set8pFDl8fHRwGPhAguqxIfqnQ4PY+b57IHEsybIaQ/HPNwdJ1cs1+IPBGHe3TL14dTS4aVNpHA== +X-Received: by 2002:a5d:6991:0:b0:2ce:aab5:f96b with SMTP id + g17-20020a5d6991000000b002ceaab5f96bmr2965175wru.67.1679420062764; + Tue, 21 Mar 2023 10:34:22 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.21 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 21 Mar 2023 10:34:21 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, + olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, + kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v2 2/4] net: dsa: b53: mmap: add more 63xx SoCs +Date: Tue, 21 Mar 2023 18:33:57 +0100 +Message-Id: <20230321173359.251778-3-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> +References: <20230320155024.164523-1-noltari@gmail.com> + <20230321173359.251778-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +BCM6318, BCM6362 and BCM63268 are SoCs with a B53 MMAP switch. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +--- + v2: no changes. + + drivers/net/dsa/b53/b53_mmap.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -345,8 +345,11 @@ static void b53_mmap_shutdown(struct pla + + static const struct of_device_id b53_mmap_of_table[] = { + { .compatible = "brcm,bcm3384-switch" }, ++ { .compatible = "brcm,bcm6318-switch" }, + { .compatible = "brcm,bcm6328-switch" }, ++ { .compatible = "brcm,bcm6362-switch" }, + { .compatible = "brcm,bcm6368-switch" }, ++ { .compatible = "brcm,bcm63268-switch" }, + { .compatible = "brcm,bcm63xx-switch" }, + { /* sentinel */ }, + }; diff --git a/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch b/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch new file mode 100644 index 0000000000..de237374af --- /dev/null +++ b/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch @@ -0,0 +1,195 @@ +From patchwork Tue Mar 21 17:33:58 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13183004 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id B2B12C74A5B + for ; Tue, 21 Mar 2023 17:35:12 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S230297AbjCURfK (ORCPT ); + Tue, 21 Mar 2023 13:35:10 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47438 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S230374AbjCURex (ORCPT + ); Tue, 21 Mar 2023 13:34:53 -0400 +Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com + [IPv6:2a00:1450:4864:20::432]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C906B5550A; + Tue, 21 Mar 2023 10:34:26 -0700 (PDT) +Received: by mail-wr1-x432.google.com with SMTP id y14so14546846wrq.4; + Tue, 21 Mar 2023 10:34:26 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679420064; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=vnvnwWc5Tmg09HBQo/m9RbRM6yM8KLx8r1VA+Abfg3k=; + b=eFv+mwe94Y2YZMiJP5gydXVrGlbIAR5HCrY0rdcoGoMPzQUHLFckZeYCgEKudI55I7 + gMLZYCtLwvDXvKeHM2AUigsq2YuJSeF5QwICPrhTnMwUGBg4yyyltrc3+J0lSd6/4kQv + h0yM1Oo4v0d8CuqjBU6bXienIk34AFVJfsPq+vWQTjAbUL7ht4WHZ2Ez2MFoTvZpkIJA + 5iWMyVoMbugZl6eqNRjvDHFmtBtrZIv8AFs10r2Ca6+Yxm+aq0v33DRkbSVVqgFPNEzy + q5QOXOeLBPL6BvyovOpmVSWGoHf1zFV7lrzcqi+uc+FuYxQ9dyN3ND73DrrhWSkLaSg9 + r8yA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679420064; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=vnvnwWc5Tmg09HBQo/m9RbRM6yM8KLx8r1VA+Abfg3k=; + b=jIRB8pIlrLA/ovhnEoePs/6SX8fn6l7l4fY2CxX2pLrTbP1JI8AAetPavvrNVQTr2M + Vm0iLbKyL/VpTq9+bSN1SMjaoi4lAMj0pgafoHrwABMVZpFauYvtCfSYTstZ2pw4Dr1j + wYQGj3BUSpFIYHtSIDMkb5449WA3T3TONhaQLRFAUCBD6gAFyEky5fY+DIHrGaj352B6 + 9ST/tkqHgPpuFlmromr42KQWoTFU+Pj0Uhyp7ru4BsnF7tTshWroZZIHUJmSACudEadr + fBPiuurX9jgp9zNqj8Oy0HjiVUnULFCapj8yICGp5s44uDAK/XFqFXpOuJ8ptS6uPazU + xUwg== +X-Gm-Message-State: AO0yUKX2w6QZfaGDHtlZAlY/U8F8VuJa3HwlgXbxgGChgdgvIoFThawv + oDyFAhWbVfe4DxwXTwxgJ/I= +X-Google-Smtp-Source: + AK7set+sH60XiJYup7bqrZTzFJVNe1YGcX/UTfjWV9xfGwNyodc34cHvKpqNagw5J+vEpv6CKvNHaA== +X-Received: by 2002:adf:f344:0:b0:2cd:de25:1c76 with SMTP id + e4-20020adff344000000b002cdde251c76mr12989754wrp.17.1679420064464; + Tue, 21 Mar 2023 10:34:24 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.22 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 21 Mar 2023 10:34:23 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, + olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, + kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v2 3/4] net: dsa: b53: mmap: allow passing a chip ID +Date: Tue, 21 Mar 2023 18:33:58 +0100 +Message-Id: <20230321173359.251778-4-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> +References: <20230320155024.164523-1-noltari@gmail.com> + <20230321173359.251778-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +BCM6318 and BCM63268 SoCs require a special handling for their RGMIIs, so we +should be able to identify them as a special BCM63xx switch. + +Signed-off-by: Álvaro Fernández Rojas +--- + v2: + - Add missing chip to b53_switch_chips[]. + - Fix device_get_match_data() casting warning. + - Add BCM63268_DEVICE_ID to BCM6318 too. + - Add BCM6318 in commit description. + + drivers/net/dsa/b53/b53_common.c | 13 +++++++++++++ + drivers/net/dsa/b53/b53_mmap.c | 32 +++++++++++++++++++++++--------- + drivers/net/dsa/b53/b53_priv.h | 9 ++++++++- + 3 files changed, 44 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2466,6 +2466,19 @@ static const struct b53_chip_data b53_sw + .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, + }, + { ++ .chip_id = BCM63268_DEVICE_ID, ++ .dev_name = "BCM63268", ++ .vlans = 4096, ++ .enabled_ports = 0, /* pdata must provide them */ ++ .arl_bins = 4, ++ .arl_buckets = 1024, ++ .imp_port = 8, ++ .vta_regs = B53_VTA_REGS_63XX, ++ .duplex_reg = B53_DUPLEX_STAT_63XX, ++ .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, ++ .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, ++ }, ++ { + .chip_id = BCM53010_DEVICE_ID, + .dev_name = "BCM53010", + .vlans = 4096, +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -262,7 +262,7 @@ static int b53_mmap_probe_of(struct plat + return -ENOMEM; + + pdata->regs = mem; +- pdata->chip_id = BCM63XX_DEVICE_ID; ++ pdata->chip_id = (u32)(unsigned long)device_get_match_data(dev); + pdata->big_endian = of_property_read_bool(np, "big-endian"); + + of_ports = of_get_child_by_name(np, "ports"); +@@ -344,14 +344,28 @@ static void b53_mmap_shutdown(struct pla + } + + static const struct of_device_id b53_mmap_of_table[] = { +- { .compatible = "brcm,bcm3384-switch" }, +- { .compatible = "brcm,bcm6318-switch" }, +- { .compatible = "brcm,bcm6328-switch" }, +- { .compatible = "brcm,bcm6362-switch" }, +- { .compatible = "brcm,bcm6368-switch" }, +- { .compatible = "brcm,bcm63268-switch" }, +- { .compatible = "brcm,bcm63xx-switch" }, +- { /* sentinel */ }, ++ { ++ .compatible = "brcm,bcm3384-switch", ++ .data = (void *)BCM63XX_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm6318-switch", ++ .data = (void *)BCM63268_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm6328-switch", ++ .data = (void *)BCM63XX_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm6362-switch", ++ .data = (void *)BCM63XX_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm6368-switch", ++ .data = (void *)BCM63XX_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm63268-switch", ++ .data = (void *)BCM63268_DEVICE_ID, ++ }, { ++ .compatible = "brcm,bcm63xx-switch", ++ .data = (void *)BCM63XX_DEVICE_ID, ++ }, { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, b53_mmap_of_table); + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -70,6 +70,7 @@ enum { + BCM53125_DEVICE_ID = 0x53125, + BCM53128_DEVICE_ID = 0x53128, + BCM63XX_DEVICE_ID = 0x6300, ++ BCM63268_DEVICE_ID = 0x63268, + BCM53010_DEVICE_ID = 0x53010, + BCM53011_DEVICE_ID = 0x53011, + BCM53012_DEVICE_ID = 0x53012, +@@ -191,7 +192,13 @@ static inline int is531x5(struct b53_dev + + static inline int is63xx(struct b53_device *dev) + { +- return dev->chip_id == BCM63XX_DEVICE_ID; ++ return dev->chip_id == BCM63XX_DEVICE_ID || ++ dev->chip_id == BCM63268_DEVICE_ID; ++} ++ ++static inline int is63268(struct b53_device *dev) ++{ ++ return dev->chip_id == BCM63268_DEVICE_ID; + } + + static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch b/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch new file mode 100644 index 0000000000..d90d757fb2 --- /dev/null +++ b/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch @@ -0,0 +1,123 @@ +From patchwork Tue Mar 21 17:33:59 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13183005 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 31BE4C761A6 + for ; Tue, 21 Mar 2023 17:35:16 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S229674AbjCURfN (ORCPT ); + Tue, 21 Mar 2023 13:35:13 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47684 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S230327AbjCURfB (ORCPT + ); Tue, 21 Mar 2023 13:35:01 -0400 +Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com + [IPv6:2a00:1450:4864:20::436]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1D855507D; + Tue, 21 Mar 2023 10:34:27 -0700 (PDT) +Received: by mail-wr1-x436.google.com with SMTP id i9so14537769wrp.3; + Tue, 21 Mar 2023 10:34:27 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679420066; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=asmFs22xWYwR1Ql9m/IrNv+MPUNDn8hSjmwDRYvO7mE=; + b=Cqj2C6aG5vEOlhh9N3ybvDA0CV38nhQODnfdnr7utNddd323iDagoJty1Wmi3MAzj1 + 5ORmYT5fQvUnild7C4RhcCNTBn+MoYZ+wDZwZYelu6BKHkW11YFK949ax5B50by+ASR2 + z+rGI3wR5fVXd4VDgmcsT6zF5x69wKyhbhqIfrhG9BVFTctfaBgDS/l+bX1C56kSqv82 + bQkKSSAehSLGpFoCU3q62OGoZVi3jDe6HDb5M1Dp2mgHhqsW19otZpJ57DjtZ1CmtPai + o7T/ew6WoIYSl6whBmV36jeNaDJ3TItOBrKc4nMJBDWaCg4DNzUSe0ei5Xz7Oik5lb3p + y9ew== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679420066; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=asmFs22xWYwR1Ql9m/IrNv+MPUNDn8hSjmwDRYvO7mE=; + b=UdI2iQNBYwRf40ivf3ROR132t95BU/p3RUzXdZLCyz6c6JWtECQ5byyGeEwoX10n5u + HlepoNTJxMFLYrAHGvNLDPpWPuLXMa645S1mCVZ7NyWp8W96XzSynNZPeXHuJdb464QU + A7UTRSW3mlvKe9OR3EcB2CfBZv0yHWR0ldbnxcxGUFw8z78PNqpOVnITtjBdfpGesJ9c + VJw+fiM6hCcahor4nk9LLcAryPm8xmhDLxBKaLILO8wyTUiHY8G9hsXnFCtcpetnF5wS + pW13beAE+odb7ZZaXZUYpWGYhCe/hLzNjbo8YpgzHwadZthxPrT5YvNIYwyrvoViLM0n + KDRQ== +X-Gm-Message-State: AO0yUKW+9H/kqcAUyWeZhZJhiJjsBcYn1THmZaSDrPrk/pNuGXJXGtJd + NgsGZW8iSqLEv81yK+U5Os8= +X-Google-Smtp-Source: + AK7set/lzQZwCSxVaOe5dZ+7TR3xaQty/vg5xvZDpRW8TwTiPQblIbw5kJJTPLp67RySehrPIlCqSg== +X-Received: by 2002:a5d:65c9:0:b0:2ce:ac31:54ff with SMTP id + e9-20020a5d65c9000000b002ceac3154ffmr2776515wrw.2.1679420066191; + Tue, 21 Mar 2023 10:34:26 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.24 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 21 Mar 2023 10:34:25 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, + olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, + kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , + Simon Horman +Subject: [PATCH v2 4/4] net: dsa: b53: add BCM63268 RGMII configuration +Date: Tue, 21 Mar 2023 18:33:59 +0100 +Message-Id: <20230321173359.251778-5-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> +References: <20230320155024.164523-1-noltari@gmail.com> + <20230321173359.251778-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +BCM63268 requires special RGMII configuration to work. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Reviewed-by: Simon Horman +--- + v2: no changes. + + drivers/net/dsa/b53/b53_common.c | 6 +++++- + drivers/net/dsa/b53/b53_regs.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1240,8 +1240,12 @@ static void b53_adjust_63xx_rgmii(struct + break; + } + +- if (port != dev->imp_port) ++ if (port != dev->imp_port) { ++ if (is63268(dev)) ++ rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; ++ + rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; ++ } + + b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); + +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -138,6 +138,7 @@ + + #define B53_RGMII_CTRL_IMP 0x60 + #define RGMII_CTRL_ENABLE_GMII BIT(7) ++#define RGMII_CTRL_MII_OVERRIDE BIT(6) + #define RGMII_CTRL_TIMING_SEL BIT(2) + #define RGMII_CTRL_DLL_RXC BIT(1) + #define RGMII_CTRL_DLL_TXC BIT(0) diff --git a/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch b/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch new file mode 100644 index 0000000000..f0ae2defce --- /dev/null +++ b/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch @@ -0,0 +1,189 @@ +From patchwork Fri Mar 24 08:41:38 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13186549 +X-Patchwork-Delegate: kuba@kernel.org +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id EF744C76195 + for ; Fri, 24 Mar 2023 08:42:01 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S231807AbjCXImA (ORCPT ); + Fri, 24 Mar 2023 04:42:00 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32956 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S231272AbjCXIly (ORCPT + ); Fri, 24 Mar 2023 04:41:54 -0400 +Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com + [IPv6:2a00:1450:4864:20::535]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 113A517CF3; + Fri, 24 Mar 2023 01:41:46 -0700 (PDT) +Received: by mail-ed1-x535.google.com with SMTP id ek18so4877175edb.6; + Fri, 24 Mar 2023 01:41:45 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679647304; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=OfUWRaFIQIQw/lRivER+LHryfdLliXzvabGrcmkQVEU=; + b=JMrl6Eay1FS0JZqgPHsbcVzuNAbFELc0SLNGyzYtOVQXcI+YwKDM9Ls7I9PsQVEPoZ + CthomCTYoz5G9DU7uBuia207rnjOhssZJRu0syrCoU+O/ZiQyGLJDvq61z5oZJxC2S40 + kzRsUsC6MRjn64DKPWmxhsSTMKLzn2+P233LKNFbHtfi3NWF5Qu/85sUkxMurnfUgja0 + qQhl25qYY7ZIvmlFHYefaI5UkITQFuiybrqJW9tztCdHf/gS+f33YkkvQ8njmMQa1DW0 + ppedfOUotX+6kmHZGX1yea2V5ezEGGvRourZtYMoecTiD0E5d1J1bKhktKslVLIDm0ig + oc2g== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679647304; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=OfUWRaFIQIQw/lRivER+LHryfdLliXzvabGrcmkQVEU=; + b=b3Gmga5ZDbnmQfnw1GCz+eU2JwgsVzfciZuSmfYAiVxpW4c6cur3MHbpzDPhi99wzA + ZYAM7ryLv88rXl/tQB5g2Nte5rvMfxUeHXsT/JpsRcSSocFRbRrk0QJyiA/Xj86NiD5N + C1sKz50Im190FmrvPcBh6OHQbv/3MQyE+1fQx+9q3jW5rQiAWQaYk4Ng8GlWA7gtG3jB + fHO6Fuoenn32pgkveJbQLYL/2t2f53wGf3QLQ3IeKW7jdfIHNThwrwqBMxdHoIDaTBT9 + UWMeJuiYtylIibo/3zbORbWOgIERlWxZRf3BCOFpnzUn4eBzio4LgjtNxZ77ITRxsmbk + 3+Hg== +X-Gm-Message-State: AAQBX9dfyBfbR7Sdd5wqxMiAv3Yhk47pK1XzD87MZyAF3AxyoFyKcMaF + EbwJLyRvTGQEFdVWCGw1eMU= +X-Google-Smtp-Source: + AKy350bpDVLq7k1FxG2Mek/VIobZL4KhufiKx8qfmpxpcWmLI3bLg8wfQKEAKJRNJBleo/7CZuCL5g== +X-Received: by 2002:aa7:c711:0:b0:4a2:588f:b3c5 with SMTP id + i17-20020aa7c711000000b004a2588fb3c5mr2261236edq.21.1679647304260; + Fri, 24 Mar 2023 01:41:44 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + z21-20020a50cd15000000b004acbda55f6bsm10323728edi.27.2023.03.24.01.41.43 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Fri, 24 Mar 2023 01:41:43 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: paul.geurts@prodrive-technologies.com, f.fainelli@gmail.com, + jonas.gorski@gmail.com, andrew@lunn.ch, olteanv@gmail.com, + davem@davemloft.net, edumazet@google.com, kuba@kernel.org, + pabeni@redhat.com, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v2 2/2] net: dsa: b53: mdio: add support for BCM53134 +Date: Fri, 24 Mar 2023 09:41:38 +0100 +Message-Id: <20230324084138.664285-3-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230324084138.664285-1-noltari@gmail.com> +References: <20230323121804.2249605-1-noltari@gmail.com> + <20230324084138.664285-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-Patchwork-Delegate: kuba@kernel.org + +From: Paul Geurts + +Add support for the BCM53134 Ethernet switch in the existing b53 dsa driver. +BCM53134 is very similar to the BCM58XX series. + +Signed-off-by: Paul Geurts +Signed-off-by: Álvaro Fernández Rojas +--- + v2: add BCM53134 to is531x5() and remove special RGMII config + + drivers/net/dsa/b53/b53_common.c | 15 +++++++++++++++ + drivers/net/dsa/b53/b53_mdio.c | 5 ++++- + drivers/net/dsa/b53/b53_priv.h | 7 +++++-- + 3 files changed, 24 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2613,6 +2613,20 @@ static const struct b53_chip_data b53_sw + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + }, ++ { ++ .chip_id = BCM53134_DEVICE_ID, ++ .dev_name = "BCM53134", ++ .vlans = 4096, ++ .enabled_ports = 0x12f, ++ .imp_port = 8, ++ .cpu_port = B53_CPU_PORT, ++ .vta_regs = B53_VTA_REGS, ++ .arl_bins = 4, ++ .arl_buckets = 1024, ++ .duplex_reg = B53_DUPLEX_STAT_GE, ++ .jumbo_pm_reg = B53_JUMBO_PORT_MASK, ++ .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ }, + }; + + static int b53_switch_init(struct b53_device *dev) +@@ -2790,6 +2804,7 @@ int b53_switch_detect(struct b53_device + case BCM53012_DEVICE_ID: + case BCM53018_DEVICE_ID: + case BCM53019_DEVICE_ID: ++ case BCM53134_DEVICE_ID: + dev->chip_id = id32; + break; + default: +--- a/drivers/net/dsa/b53/b53_mdio.c ++++ b/drivers/net/dsa/b53/b53_mdio.c +@@ -286,6 +286,7 @@ static const struct b53_io_ops b53_mdio_ + #define B53_BRCM_OUI_2 0x03625c00 + #define B53_BRCM_OUI_3 0x00406000 + #define B53_BRCM_OUI_4 0x01410c00 ++#define B53_BRCM_OUI_5 0xae025000 + + static int b53_mdio_probe(struct mdio_device *mdiodev) + { +@@ -313,7 +314,8 @@ static int b53_mdio_probe(struct mdio_de + if ((phy_id & 0xfffffc00) != B53_BRCM_OUI_1 && + (phy_id & 0xfffffc00) != B53_BRCM_OUI_2 && + (phy_id & 0xfffffc00) != B53_BRCM_OUI_3 && +- (phy_id & 0xfffffc00) != B53_BRCM_OUI_4) { ++ (phy_id & 0xfffffc00) != B53_BRCM_OUI_4 && ++ (phy_id & 0xfffffc00) != B53_BRCM_OUI_5) { + dev_err(&mdiodev->dev, "Unsupported device: 0x%08x\n", phy_id); + return -ENODEV; + } +@@ -375,6 +377,7 @@ static const struct of_device_id b53_of_ + { .compatible = "brcm,bcm53115" }, + { .compatible = "brcm,bcm53125" }, + { .compatible = "brcm,bcm53128" }, ++ { .compatible = "brcm,bcm53134" }, + { .compatible = "brcm,bcm5365" }, + { .compatible = "brcm,bcm5389" }, + { .compatible = "brcm,bcm5395" }, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -80,6 +80,7 @@ enum { + BCM583XX_DEVICE_ID = 0x58300, + BCM7445_DEVICE_ID = 0x7445, + BCM7278_DEVICE_ID = 0x7278, ++ BCM53134_DEVICE_ID = 0x5075, + }; + + struct b53_pcs { +@@ -187,7 +188,8 @@ static inline int is531x5(struct b53_dev + { + return dev->chip_id == BCM53115_DEVICE_ID || + dev->chip_id == BCM53125_DEVICE_ID || +- dev->chip_id == BCM53128_DEVICE_ID; ++ dev->chip_id == BCM53128_DEVICE_ID || ++ dev->chip_id == BCM53134_DEVICE_ID; + } + + static inline int is63xx(struct b53_device *dev) +@@ -215,7 +217,8 @@ static inline int is58xx(struct b53_devi + return dev->chip_id == BCM58XX_DEVICE_ID || + dev->chip_id == BCM583XX_DEVICE_ID || + dev->chip_id == BCM7445_DEVICE_ID || +- dev->chip_id == BCM7278_DEVICE_ID; ++ dev->chip_id == BCM7278_DEVICE_ID || ++ dev->chip_id == BCM53134_DEVICE_ID; + } + + #define B53_63XX_RGMII0 4 diff --git a/target/linux/generic/pending-6.6/778-net-l2tp-drop-flow-hash-on-forward.patch b/target/linux/generic/pending-6.6/778-net-l2tp-drop-flow-hash-on-forward.patch new file mode 100644 index 0000000000..a2c0edcbbf --- /dev/null +++ b/target/linux/generic/pending-6.6/778-net-l2tp-drop-flow-hash-on-forward.patch @@ -0,0 +1,31 @@ +From 4a44a52f16ccd3d03e0cb5fb437a5eb31a5f9f05 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 26 Feb 2024 21:39:34 +0100 +Subject: [PATCH] net l2tp: drop flow hash on forward + +Drop the flow-hash of the skb when forwarding to the L2TP netdev. + +This avoids the L2TP qdisc from using the flow-hash from the outer +packet, which is identical for every flow within the tunnel. + +This does not affect every platform but is specific for the ethernet +driver. It depends on the platform including L4 information in the +flow-hash. + +Signed-off-by: David Bauer +--- + net/l2tp/l2tp_eth.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/l2tp/l2tp_eth.c ++++ b/net/l2tp/l2tp_eth.c +@@ -136,6 +136,9 @@ static void l2tp_eth_dev_recv(struct l2t + /* checksums verified by L2TP */ + skb->ip_summed = CHECKSUM_NONE; + ++ /* drop outer flow-hash */ ++ skb_clear_hash(skb); ++ + skb_dst_drop(skb); + nf_reset_ct(skb); + diff --git a/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch b/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch new file mode 100644 index 0000000000..6c1f596759 --- /dev/null +++ b/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch @@ -0,0 +1,30 @@ +From 3f1a227cb071f65f6ecc4db9f399649869735a7c Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sat, 17 Feb 2024 22:34:59 +0100 +Subject: [PATCH] net vxlan: don't learn non-unicast L2 destinations + +This patch avoids learning non-unicast targets in the vxlan FDB. +They are non-unicast and thus should be sent to the broadcast-IPv6 +instead of a unicast address. + +Link: https://lore.kernel.org/netdev/15ee0cc7-9252-466b-8ce7-5225d605dde8@david-bauer.net/ +Link: https://github.com/freifunk-gluon/gluon/issues/3191 + +Signed-off-by: David Bauer +--- + drivers/net/vxlan.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -1493,6 +1493,10 @@ static bool vxlan_snoop(struct net_devic + struct vxlan_fdb *f; + u32 ifindex = 0; + ++ /* Don't learn broadcast packets */ ++ if (is_multicast_ether_addr(src_mac) || is_zero_ether_addr(src_mac)) ++ return false; ++ + #if IS_ENABLED(CONFIG_IPV6) + if (src_ip->sa.sa_family == AF_INET6 && + (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)) diff --git a/target/linux/generic/pending-6.6/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/target/linux/generic/pending-6.6/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch new file mode 100644 index 0000000000..39ba71606e --- /dev/null +++ b/target/linux/generic/pending-6.6/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch @@ -0,0 +1,61 @@ +From patchwork Thu Aug 5 22:23:30 2021 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 12422209 +Date: Thu, 5 Aug 2021 23:23:30 +0100 +From: Daniel Golle +To: linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org +Cc: "David S. Miller" , Andrew Lunn , + Michael Walle +Subject: [PATCH] ARM: kirkwood: add missing for ETH_ALEN +Message-ID: +MIME-Version: 1.0 +Content-Disposition: inline +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.34 +Precedence: list +List-Id: +List-Archive: +Sender: "linux-arm-kernel" + +After commit 83216e3988cd1 ("of: net: pass the dst buffer to +of_get_mac_address()") build fails for kirkwood as ETH_ALEN is not +defined. + +arch/arm/mach-mvebu/kirkwood.c: In function 'kirkwood_dt_eth_fixup': +arch/arm/mach-mvebu/kirkwood.c:87:13: error: 'ETH_ALEN' undeclared (first use in this function); did you mean 'ESTALE'? + u8 tmpmac[ETH_ALEN]; + ^~~~~~~~ + ESTALE +arch/arm/mach-mvebu/kirkwood.c:87:13: note: each undeclared identifier is reported only once for each function it appears in +arch/arm/mach-mvebu/kirkwood.c:87:6: warning: unused variable 'tmpmac' [-Wunused-variable] + u8 tmpmac[ETH_ALEN]; + ^~~~~~ +make[5]: *** [scripts/Makefile.build:262: arch/arm/mach-mvebu/kirkwood.o] Error 1 +make[5]: *** Waiting for unfinished jobs.... + +Add missing #include to fix this. + +Cc: David S. Miller +Cc: Andrew Lunn +Cc: Michael Walle +Reported-by: https://buildbot.openwrt.org/master/images/#/builders/56/builds/220/steps/44/logs/stdio +Fixes: 83216e3988cd1 ("of: net: pass the dst buffer to of_get_mac_address()") +Signed-off-by: Daniel Golle +--- + arch/arm/mach-mvebu/kirkwood.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/mach-mvebu/kirkwood.c ++++ b/arch/arm/mach-mvebu/kirkwood.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/target/linux/generic/pending-6.6/790-bus-mhi-core-add-SBL-state-callback.patch b/target/linux/generic/pending-6.6/790-bus-mhi-core-add-SBL-state-callback.patch new file mode 100644 index 0000000000..f239355594 --- /dev/null +++ b/target/linux/generic/pending-6.6/790-bus-mhi-core-add-SBL-state-callback.patch @@ -0,0 +1,48 @@ +From 5f7c5e1c0d7a79be144e5efc1f24728ddd7fc25c Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 5 Nov 2022 20:02:56 +0100 +Subject: [PATCH 1/2] bus: mhi: core: add SBL state callback + +Add support for SBL state callback in MHI core. + +It is required for ath11k MHI devices in order to be able to set QRTR +instance ID in the SBL state so that QRTR instance ID-s dont conflict in +case of multiple PCI/MHI cards or AHB + PCI/MHI card. +Setting QRTR instance ID is only possible in SBL state and there is +currently no way to ensure that we are in that state, so provide a +callback that the controller can trigger off. + +Signed-off-by: Robert Marko +--- + drivers/bus/mhi/host/main.c | 1 + + include/linux/mhi.h | 2 ++ + 2 files changed, 3 insertions(+) + +--- a/drivers/bus/mhi/host/main.c ++++ b/drivers/bus/mhi/host/main.c +@@ -905,6 +905,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_ + switch (event) { + case MHI_EE_SBL: + st = DEV_ST_TRANSITION_SBL; ++ mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_EE_SBL_MODE); + break; + case MHI_EE_WFW: + case MHI_EE_AMSS: +--- a/include/linux/mhi.h ++++ b/include/linux/mhi.h +@@ -34,6 +34,7 @@ struct mhi_buf_info; + * @MHI_CB_SYS_ERROR: MHI device entered error state (may recover) + * @MHI_CB_FATAL_ERROR: MHI device entered fatal error state + * @MHI_CB_BW_REQ: Received a bandwidth switch request from device ++ * @MHI_CB_EE_SBL_MODE: MHI device entered SBL mode + */ + enum mhi_callback { + MHI_CB_IDLE, +@@ -45,6 +46,7 @@ enum mhi_callback { + MHI_CB_SYS_ERROR, + MHI_CB_FATAL_ERROR, + MHI_CB_BW_REQ, ++ MHI_CB_EE_SBL_MODE, + }; + + /** diff --git a/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch b/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch new file mode 100644 index 0000000000..d333f3f489 --- /dev/null +++ b/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch @@ -0,0 +1,43 @@ +From 1d81e51d6d79d9098013b2e8cdd677bae998c5d8 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 28 Apr 2023 02:22:59 +0200 +Subject: [PATCH 1/2] mt7530: register OF node for internal MDIO bus + +The MT753x switches provide a switch-internal MDIO bus for the embedded +PHYs. + +Register a OF sub-node on the switch OF-node for this internal MDIO bus. +This allows to configure the embedded PHYs using device-tree. + +Signed-off-by: David Bauer +--- + drivers/net/dsa/mt7530.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2142,10 +2142,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr + { + struct dsa_switch *ds = priv->ds; + struct device *dev = priv->dev; ++ struct device_node *np, *mnp; + struct mii_bus *bus; + static int idx; + int ret; + ++ np = priv->dev->of_node; ++ + bus = devm_mdiobus_alloc(dev); + if (!bus) + return -ENOMEM; +@@ -2162,7 +2165,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr + if (priv->irq) + mt7530_setup_mdio_irq(priv); + +- ret = devm_mdiobus_register(dev, bus); ++ mnp = of_get_child_by_name(np, "mdio"); ++ ret = devm_of_mdiobus_register(dev, bus, mnp); ++ of_node_put(mnp); + if (ret) { + dev_err(dev, "failed to register MDIO bus: %d\n", ret); + if (priv->irq) diff --git a/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch b/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch new file mode 100644 index 0000000000..47e3b140c8 --- /dev/null +++ b/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch @@ -0,0 +1,45 @@ +From a444877c10a665cd8a869e6d37facdb89fd95f79 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Daniel Golle +Date: Wed, 24 Jan 2024 04:17:11 +0000 +Subject: [PATCH net] net: dsa: mt7530: fix 10M/100M speed on MT7988 switch +To: Arınç ÜNAL , + Daniel Golle , + DENG Qingfang , + Sean Wang , + Andrew Lunn , + Florian Fainelli , + Vladimir Oltean , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Matthias Brugger , + AngeloGioacchino Del Regno , + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org + +Setup PMCR port register for actual speed and duplex on internally +connected PHYs of the MT7988 built-in switch. This fixes links with +speeds other than 1000M. + +Fixes: ("110c18bfed414 net: dsa: mt7530: introduce driver for MT7988 built-in switch") +Signed-off-by: Daniel Golle +--- + drivers/net/dsa/mt7530.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2849,8 +2849,7 @@ 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_INTERNAL || +- interface == PHY_INTERFACE_MODE_TRGMII || ++ if (interface == PHY_INTERFACE_MODE_TRGMII || + (phy_interface_mode_is_8023z(interface))) { + speed = SPEED_1000; + duplex = DUPLEX_FULL; diff --git a/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch new file mode 100644 index 0000000000..478a2cb27d --- /dev/null +++ b/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch @@ -0,0 +1,73 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] bcma: get SoC device struct & copy its DMA params to the + subdevices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For bus devices to be fully usable it's required to set their DMA +parameters. + +For years it has been missing and remained unnoticed because of +mips_dma_alloc_coherent() silently handling the empty coherent_dma_mask. +Kernel 4.19 came with a lot of DMA changes and caused a regression on +the bcm47xx. Starting with the commit f8c55dc6e828 ("MIPS: use generic +dma noncoherent ops for simple noncoherent platforms") DMA coherent +allocations just fail. Example: +[ 1.114914] bgmac_bcma bcma0:2: Allocation of TX ring 0x200 failed +[ 1.121215] bgmac_bcma bcma0:2: Unable to alloc memory for DMA +[ 1.127626] bgmac_bcma: probe of bcma0:2 failed with error -12 +[ 1.133838] bgmac_bcma: Broadcom 47xx GBit MAC driver loaded + +This change fixes above regression in addition to the MIPS bcm47xx +commit 321c46b91550 ("MIPS: BCM47XX: Setup struct device for the SoC"). + +It also fixes another *old* GPIO regression caused by a parent pointing +to the NULL: +[ 0.157054] missing gpiochip .dev parent pointer +[ 0.157287] bcma: bus0: Error registering GPIO driver: -22 +introduced by the commit 74f4e0cc6108 ("bcma: switch GPIO portions to +use GPIOLIB_IRQCHIP"). + +Fixes: f8c55dc6e828 ("MIPS: use generic dma noncoherent ops for simple noncoherent platforms") +Fixes: 74f4e0cc6108 ("bcma: switch GPIO portions to use GPIOLIB_IRQCHIP") +Cc: linux-mips@linux-mips.org +Cc: Christoph Hellwig +Cc: Linus Walleij +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/bcma/host_soc.c ++++ b/drivers/bcma/host_soc.c +@@ -191,6 +191,8 @@ int __init bcma_host_soc_init(struct bcm + struct bcma_bus *bus = &soc->bus; + int err; + ++ bus->dev = soc->dev; ++ + /* Scan bus and initialize it */ + err = bcma_bus_early_register(bus); + if (err) +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -236,13 +236,17 @@ EXPORT_SYMBOL(bcma_core_irq); + + void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) + { +- device_initialize(&core->dev); ++ struct device *dev = &core->dev; ++ ++ device_initialize(dev); + core->dev.release = bcma_release_core_dev; + core->dev.bus = &bcma_bus_type; +- dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); ++ dev_set_name(dev, "bcma%d:%d", bus->num, core->core_index); + core->dev.parent = bus->dev; +- if (bus->dev) ++ if (bus->dev) { + bcma_of_fill_device(bus->dev, core); ++ dma_coerce_mask_and_coherent(dev, bus->dev->coherent_dma_mask); ++ } + + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: diff --git a/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch new file mode 100644 index 0000000000..a13d405e64 --- /dev/null +++ b/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch @@ -0,0 +1,222 @@ +From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001 +From: Mauri Sandberg +Date: Thu, 25 Mar 2021 11:48:05 +0200 +Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade + +Adds support for building cascades of GPIO lines. That is, it allows +setups when there is one upstream line and multiple cascaded lines, out +of which one can be chosen at a time. The status of the upstream line +can be conveyed to the selected cascaded line or, vice versa, the status +of the cascaded line can be conveyed to the upstream line. + +A multiplexer is being used to select, which cascaded GPIO line is being +used at any given time. + +At the moment only input direction is supported. In future it should be +possible to add support for output direction, too. + +Signed-off-by: Mauri Sandberg +Reviewed-by: Linus Walleij +Reviewed-by: Andy Shevchenko +--- +v7 -> v8: + - rearrange members in struct gpio_cascade + - cosmetic changes in file header and in one function declaration + - added Reviewed-by tags by Linus and Andy +v6 -> v7: + - In Kconfig add info about module name + - adhere to new convention that allows lines longer than 80 chars + - use dev_probe_err with upstream gpio line too + - refactor for cleaner exit of probe function. +v5 -> v6: + - In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER + - refactor code preferring one-liners + - clean up prints, removing them from success-path. + - don't explicitly set gpio_chip.of_node as it's done in the GPIO library + - use devm_gpiochip_add_data instead of gpiochip_add +v4 -> v5: + - renamed gpio-mux-input -> gpio-cascade. refactored code accordingly + here and there and changed to use new bindings and compatible string + - ambigious and vague 'pin' was rename to 'upstream_line' + - dropped Tested-by and Reviewed-by due to changes in bindings + - dropped Reported-by suggested by an automatic bot as it was not really + appropriate to begin with + - functionally it's the same as v4 +v3 -> v4: + - Changed author email + - Included Tested-by and Reviewed-by from Drew +v2 -> v3: + - use managed device resources + - update Kconfig description +v1 -> v2: + - removed .owner from platform_driver as per test bot's instruction + - added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE + - added gpio_mux_input_get_direction as it's recommended for all chips + - removed because this is input only chip: gpio_mux_input_set_value + - removed because they are not needed for input/output only chips: + gpio_mux_input_direction_input + gpio_mux_input_direction_output + - fixed typo in an error message + - added info message about successful registration + - removed can_sleep flag as this does not sleep while getting GPIO value + like I2C or SPI do + - Updated description in Kconfig +--- + drivers/gpio/Kconfig | 15 +++++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 133 insertions(+) + create mode 100644 drivers/gpio/gpio-cascade.c + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1711,4 +1711,19 @@ config GPIO_SIM + + endmenu + ++comment "Other GPIO expanders" ++ ++config GPIO_CASCADE ++ tristate "General GPIO cascade" ++ select MULTIPLEXER ++ help ++ Say yes here to enable support for generic GPIO cascade. ++ ++ This allows building one-to-many cascades of GPIO lines using ++ different types of multiplexers readily available. At the ++ moment only input lines are supported. ++ ++ To build the driver as a module choose 'm' and the resulting module ++ will be called 'gpio-cascade'. ++ + endif +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o ++obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o + obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o + obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o +--- /dev/null ++++ b/drivers/gpio/gpio-cascade.c +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * A generic GPIO cascade driver ++ * ++ * Copyright (C) 2021 Mauri Sandberg ++ * ++ * This allows building cascades of GPIO lines in a manner illustrated ++ * below: ++ * ++ * /|---- Cascaded GPIO line 0 ++ * Upstream | |---- Cascaded GPIO line 1 ++ * GPIO line ----+ | . ++ * | | . ++ * \|---- Cascaded GPIO line n ++ * ++ * A multiplexer is being used to select, which cascaded line is being ++ * addressed at any given time. ++ * ++ * At the moment only input mode is supported due to lack of means for ++ * testing output functionality. At least theoretically output should be ++ * possible with open drain constructions. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct gpio_cascade { ++ struct gpio_chip gpio_chip; ++ struct device *parent; ++ struct mux_control *mux_control; ++ struct gpio_desc *upstream_line; ++}; ++ ++static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc) ++{ ++ return container_of(gc, struct gpio_cascade, gpio_chip); ++} ++ ++static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ return GPIO_LINE_DIRECTION_IN; ++} ++ ++static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct gpio_cascade *cas = chip_to_cascade(gc); ++ int ret; ++ ++ ret = mux_control_select(cas->mux_control, offset); ++ if (ret) ++ return ret; ++ ++ ret = gpiod_get_value(cas->upstream_line); ++ mux_control_deselect(cas->mux_control); ++ return ret; ++} ++ ++static int gpio_cascade_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct gpio_cascade *cas; ++ struct mux_control *mc; ++ struct gpio_desc *upstream; ++ struct gpio_chip *gc; ++ ++ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL); ++ if (!cas) ++ return -ENOMEM; ++ ++ mc = devm_mux_control_get(dev, NULL); ++ if (IS_ERR(mc)) ++ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n"); ++ ++ cas->mux_control = mc; ++ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN); ++ if (IS_ERR(upstream)) ++ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n"); ++ ++ cas->upstream_line = upstream; ++ cas->parent = dev; ++ ++ gc = &cas->gpio_chip; ++ gc->get = gpio_cascade_get_value; ++ gc->get_direction = gpio_cascade_get_direction; ++ gc->base = -1; ++ gc->ngpio = mux_control_states(mc); ++ gc->label = dev_name(cas->parent); ++ gc->parent = cas->parent; ++ gc->owner = THIS_MODULE; ++ ++ platform_set_drvdata(pdev, cas); ++ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL); ++} ++ ++static const struct of_device_id gpio_cascade_id[] = { ++ { .compatible = "gpio-cascade" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, gpio_cascade_id); ++ ++static struct platform_driver gpio_cascade_driver = { ++ .driver = { ++ .name = "gpio-cascade", ++ .of_match_table = gpio_cascade_id, ++ }, ++ .probe = gpio_cascade_probe, ++}; ++module_platform_driver(gpio_cascade_driver); ++ ++MODULE_AUTHOR("Mauri Sandberg "); ++MODULE_DESCRIPTION("Generic GPIO cascade"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch new file mode 100644 index 0000000000..2b3e4bbf71 --- /dev/null +++ b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch @@ -0,0 +1,108 @@ +From fd59b838dd90452f61a17dc9e5ff175205003068 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 15 Sep 2022 18:49:43 +0200 +Subject: [PATCH] OPP: Provide old opp to config_clks on _set_opp + +With the target opp, also pass the old opp to config_clks function. +This can be useful when a driver needs to take decision on what fequency +to set based on what is the current frequency without using a +clk_get_freq call. +Update the only user of custom config_clks (tegra30 devfreq driver) to +this new implementation. + +Signed-off-by: Christian Marangi +--- + drivers/devfreq/tegra30-devfreq.c | 5 +++-- + drivers/opp/core.c | 11 ++++++----- + include/linux/pm_opp.h | 11 ++++++----- + 3 files changed, 15 insertions(+), 12 deletions(-) + +--- a/drivers/devfreq/tegra30-devfreq.c ++++ b/drivers/devfreq/tegra30-devfreq.c +@@ -823,8 +823,9 @@ static int devm_tegra_devfreq_init_hw(st + + static int tegra_devfreq_config_clks_nop(struct device *dev, + struct opp_table *opp_table, +- struct dev_pm_opp *opp, void *data, +- bool scaling_down) ++ struct dev_pm_opp *old_opp, ++ struct dev_pm_opp *opp, ++ void *data, bool scaling_down) + { + /* We want to skip clk configuration via dev_pm_opp_set_opp() */ + return 0; +--- a/drivers/opp/core.c ++++ b/drivers/opp/core.c +@@ -816,7 +816,8 @@ static int _set_opp_voltage(struct devic + + static int + _opp_config_clk_single(struct device *dev, struct opp_table *opp_table, +- struct dev_pm_opp *opp, void *data, bool scaling_down) ++ struct dev_pm_opp *old_opp, struct dev_pm_opp *opp, ++ void *data, bool scaling_down) + { + unsigned long *target = data; + unsigned long freq; +@@ -848,8 +849,8 @@ _opp_config_clk_single(struct device *de + * the order in which they are present in the array while scaling up. + */ + int dev_pm_opp_config_clks_simple(struct device *dev, +- struct opp_table *opp_table, struct dev_pm_opp *opp, void *data, +- bool scaling_down) ++ struct opp_table *opp_table, struct dev_pm_opp *old_opp, ++ struct dev_pm_opp *opp, void *data, bool scaling_down) + { + int ret, i; + +@@ -1121,7 +1122,7 @@ static int _set_opp(struct device *dev, + } + + if (opp_table->config_clks) { +- ret = opp_table->config_clks(dev, opp_table, opp, clk_data, scaling_down); ++ ret = opp_table->config_clks(dev, opp_table, old_opp, opp, clk_data, scaling_down); + if (ret) + return ret; + } +@@ -1196,7 +1197,7 @@ int dev_pm_opp_set_rate(struct device *d + * equivalent to a clk_set_rate() + */ + if (!_get_opp_count(opp_table)) { +- ret = opp_table->config_clks(dev, opp_table, NULL, ++ ret = opp_table->config_clks(dev, opp_table, NULL, NULL, + &target_freq, false); + goto put_opp_table; + } +--- a/include/linux/pm_opp.h ++++ b/include/linux/pm_opp.h +@@ -61,7 +61,8 @@ typedef int (*config_regulators_t)(struc + struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp, + struct regulator **regulators, unsigned int count); + +-typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table, ++typedef int (*config_clks_t)(struct device *dev, ++ struct opp_table *opp_table, struct dev_pm_opp *old_opp, + struct dev_pm_opp *opp, void *data, bool scaling_down); + + /** +@@ -160,8 +161,8 @@ int dev_pm_opp_set_config(struct device + int devm_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config); + void dev_pm_opp_clear_config(int token); + int dev_pm_opp_config_clks_simple(struct device *dev, +- struct opp_table *opp_table, struct dev_pm_opp *opp, void *data, +- bool scaling_down); ++ struct opp_table *opp_table, struct dev_pm_opp *old_opp, ++ struct dev_pm_opp *opp, void *data, bool scaling_down); + + struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp); + int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate); +@@ -346,8 +347,8 @@ static inline int devm_pm_opp_set_config + static inline void dev_pm_opp_clear_config(int token) {} + + static inline int dev_pm_opp_config_clks_simple(struct device *dev, +- struct opp_table *opp_table, struct dev_pm_opp *opp, void *data, +- bool scaling_down) ++ struct opp_table *opp_table, struct dev_pm_opp *old_opp, ++ struct dev_pm_opp *opp, void *data, bool scaling_down) + { + return -EOPNOTSUPP; + } diff --git a/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch new file mode 100644 index 0000000000..d07447bcba --- /dev/null +++ b/target/linux/generic/pending-6.6/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -0,0 +1,47 @@ +From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Thu, 13 Oct 2022 00:51:33 +0900 +Subject: [PATCH] nvmem: u-boot-env: align endianness of crc32 values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes crc32 error on Big-Endianness system by conversion of +calculated crc32 value. + +Little-Endianness system: + + obtained crc32: Little +calculated crc32: Little + +Big-Endianness system: + + obtained crc32: Little +calculated crc32: Big + +log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness): + +[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88) +[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22 + +Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables") + +Signed-off-by: INAGAKI Hiroshi +Acked-by: Rafał Miłecki +Tested-by: Christian Lamparter +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; ++ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); + if (calc != crc32) { + dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); + err = -EINVAL; diff --git a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch new file mode 100644 index 0000000000..9bb94a28b5 --- /dev/null +++ b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -0,0 +1,124 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 13 Jul 2023 18:29:19 +0200 +Subject: [PATCH] nvmem: core: support "mac-base" fixed layout cells + +Fixed layout binding allows specifying "mac-base" NVMEM cells. It's used +for base MAC address (that can be used for calculating relative +addresses). It can be stored in a raw binary format or as an ASCII +string. +--- + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + menuconfig NVMEM + bool "NVMEM Support" ++ select GENERIC_NET_UTILS + imply NVMEM_LAYOUTS + help + Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -7,9 +7,12 @@ + */ + + #include ++#include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -780,6 +783,62 @@ static int nvmem_validate_keepouts(struc + return 0; + } + ++static int nvmem_mac_base_raw_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ if (WARN_ON(bytes != ETH_ALEN)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(buf, index); ++ ++ return 0; ++} ++ ++static int nvmem_mac_base_ascii_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (WARN_ON(bytes != 3 * ETH_ALEN - 1)) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ ++static int nvmem_mac_base_hex_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN], *hexstr; ++ int i; ++ ++ if (WARN_ON(bytes != 2 * ETH_ALEN)) ++ return -EINVAL; ++ ++ hexstr = (u8 *)buf; ++ for (i = 0; i < ETH_ALEN; i++) { ++ if (!isxdigit(hexstr[i * 2]) || !isxdigit(hexstr[i * 2 + 1])) ++ return -EINVAL; ++ ++ mac[i] = (hex_to_bin(hexstr[i * 2]) << 4) | hex_to_bin(hexstr[i * 2 + 1]); ++ } ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ + static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) + { + struct device *dev = &nvmem->dev; +@@ -814,6 +873,25 @@ static int nvmem_add_cells_from_dt(struc + if (nvmem->fixup_dt_cell_info) + nvmem->fixup_dt_cell_info(nvmem, &info); + ++ if (of_device_is_compatible(np, "fixed-layout")) { ++ if (of_device_is_compatible(child, "mac-base")) { ++ if (info.bytes == ETH_ALEN) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_raw_read; ++ } else if (info.bytes == 2 * ETH_ALEN) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_hex_read; ++ } else if (info.bytes == 3 * ETH_ALEN - 1) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_ascii_read; ++ } ++ ++ } ++ } ++ + ret = nvmem_add_one_cell(nvmem, &info); + kfree(info.name); + if (ret) { diff --git a/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch new file mode 100644 index 0000000000..ba06196f7c --- /dev/null +++ b/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch @@ -0,0 +1,62 @@ +From: Gabor Juhos +Subject: debloat: add kernel config option to disabling common PCI quirks + +Signed-off-by: Gabor Juhos +--- + drivers/pci/Kconfig | 6 ++++++ + drivers/pci/quirks.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + ++config PCI_DISABLE_COMMON_QUIRKS ++ bool "PCI disable common quirks" ++ depends on PCI ++ help ++ If you don't know what to do here, say N. ++ ++ + config PCI_ATS + bool + +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -207,6 +207,7 @@ static void quirk_mmio_always_on(struct + DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + /* + * The Mellanox Tavor device gives false positive parity errors. Disable + * parity error reporting. +@@ -3393,6 +3394,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); + ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ + /* + * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. + * To work around this, query the size it should be configured to by the +@@ -3418,6 +3421,8 @@ static void quirk_intel_ntb(struct pci_d + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + /* + * Some BIOS implementations leave the Intel GPU interrupts enabled, even + * though no one is handling them (e.g., if the i915 driver is never +@@ -3456,6 +3461,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); + ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ + /* + * PCI devices which are on Intel chips can skip the 10ms delay + * before entering D3 mode. diff --git a/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch new file mode 100644 index 0000000000..98ea4c06d9 --- /dev/null +++ b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch @@ -0,0 +1,115 @@ +From: Felix Fietkau +Subject: debloat: disable common USB quirks + +Signed-off-by: Felix Fietkau +--- + drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++ + drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++- + include/linux/usb/hcd.h | 7 +++++++ + 3 files changed, 40 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -128,6 +128,8 @@ struct amd_chipset_type { + u8 rev; + }; + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + static struct amd_chipset_info { + struct pci_dev *nb_dev; + struct pci_dev *smbus_dev; +@@ -633,6 +635,10 @@ bool usb_amd_pt_check_port(struct device + } + EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); + ++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ ++#if IS_ENABLED(CONFIG_USB_UHCI_HCD) ++ + /* + * Make sure the controller is completely inactive, unable to + * generate interrupts or do DMA. +@@ -712,8 +718,17 @@ reset_needed: + uhci_reset_hc(pdev, base); + return 1; + } ++#else ++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) ++{ ++ return 0; ++} ++ ++#endif + EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) + { + u16 cmd; +@@ -1285,3 +1300,4 @@ static void quirk_usb_early_handoff(stru + } + DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); ++#endif +--- a/drivers/usb/host/pci-quirks.h ++++ b/drivers/usb/host/pci-quirks.h +@@ -5,6 +5,9 @@ + #ifdef CONFIG_USB_PCI + void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); + int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); ++#endif /* CONFIG_USB_PCI */ ++ ++#if defined(CONFIG_USB_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS) + int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); + bool usb_amd_hang_symptom_quirk(void); + bool usb_amd_prefetch_quirk(void); +@@ -19,6 +22,18 @@ void sb800_prefetch(struct device *dev, + bool usb_amd_pt_check_port(struct device *device, int port); + #else + struct pci_dev; ++static inline int usb_amd_quirk_pll_check(void) ++{ ++ return 0; ++} ++static inline bool usb_amd_hang_symptom_quirk(void) ++{ ++ return false; ++} ++static inline bool usb_amd_prefetch_quirk(void) ++{ ++ return false; ++} + static inline void usb_amd_quirk_pll_disable(void) {} + static inline void usb_amd_quirk_pll_enable(void) {} + static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} +@@ -29,6 +44,11 @@ static inline bool usb_amd_pt_check_port + { + return false; + } ++static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} ++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) ++{ ++ return false; ++} + #endif /* CONFIG_USB_PCI */ + + #endif /* __LINUX_USB_PCI_QUIRKS_H */ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -483,7 +483,14 @@ extern int usb_hcd_pci_probe(struct pci_ + extern void usb_hcd_pci_remove(struct pci_dev *dev); + extern void usb_hcd_pci_shutdown(struct pci_dev *dev); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); ++#else ++static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev) ++{ ++ return 0; ++} ++#endif + + #ifdef CONFIG_PM + extern const struct dev_pm_ops usb_hcd_pci_pm_ops; diff --git a/target/linux/generic/pending-6.6/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-6.6/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch new file mode 100644 index 0000000000..33eb34c913 --- /dev/null +++ b/target/linux/generic/pending-6.6/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch @@ -0,0 +1,26 @@ +From d9c8bc8c1408f3e8529db6e4e04017b4c579c342 Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Sun, 18 Feb 2018 17:08:04 +0100 +Subject: [PATCH] w1: gpio: fix problem with platfom data in w1-gpio + +In devices, where fdt is used, is impossible to apply platform data +without proper fdt node. + +This patch allow to use platform data in devices with fdt. + +Signed-off-by: Pawel Dembicki +--- + drivers/w1/masters/w1-gpio.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/w1/masters/w1-gpio.c ++++ b/drivers/w1/masters/w1-gpio.c +@@ -76,7 +76,7 @@ static int w1_gpio_probe(struct platform + enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN; + int err; + +- if (of_have_populated_dt()) { ++ if (of_have_populated_dt() && !dev_get_platdata(&pdev->dev)) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; diff --git a/target/linux/generic/pending-6.6/834-ledtrig-libata.patch b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch new file mode 100644 index 0000000000..050c3515f6 --- /dev/null +++ b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch @@ -0,0 +1,149 @@ +From: Daniel Golle +Subject: libata: add ledtrig support + +This adds a LED trigger for each ATA port indicating disk activity. + +As this is needed only on specific platforms (NAS SoCs and such), +these platforms should define ARCH_WANTS_LIBATA_LEDS if there +are boards with LED(s) intended to indicate ATA disk activity and +need the OS to take care of that. +In that way, if not selected, LED trigger support not will be +included in libata-core and both, codepaths and structures remain +untouched. + +Signed-off-by: Daniel Golle +--- + drivers/ata/Kconfig | 16 ++++++++++++++++ + drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++ + include/linux/libata.h | 9 +++++++++ + 3 files changed, 66 insertions(+) + +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -67,6 +67,22 @@ config ATA_FORCE + + If unsure, say Y. + ++config ARCH_WANT_LIBATA_LEDS ++ bool ++ ++config ATA_LEDS ++ bool "support ATA port LED triggers" ++ depends on ARCH_WANT_LIBATA_LEDS ++ select NEW_LEDS ++ select LEDS_CLASS ++ select LEDS_TRIGGERS ++ default y ++ help ++ This option adds a LED trigger for each registered ATA port. ++ It is used to drive disk activity leds connected via GPIO. ++ ++ If unsure, say N. ++ + config ATA_ACPI + bool "ATA ACPI Support" + depends on ACPI +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -663,6 +663,19 @@ u64 ata_tf_read_block(const struct ata_t + return block; + } + ++#ifdef CONFIG_ATA_LEDS ++#define LIBATA_BLINK_DELAY 20 /* ms */ ++static inline void ata_led_act(struct ata_port *ap) ++{ ++ unsigned long led_delay = LIBATA_BLINK_DELAY; ++ ++ if (unlikely(!ap->ledtrig)) ++ return; ++ ++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); ++} ++#endif ++ + /** + * ata_build_rw_tf - Build ATA taskfile for given read/write request + * @qc: Metadata associated with the taskfile to build +@@ -4716,6 +4729,9 @@ void __ata_qc_complete(struct ata_queued + link->active_tag = ATA_TAG_POISON; + ap->nr_active_links--; + } ++#ifdef CONFIG_ATA_LEDS ++ ata_led_act(ap); ++#endif + + /* clear exclusive status */ + if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL && +@@ -5438,6 +5454,9 @@ struct ata_port *ata_port_alloc(struct a + ap->stats.unhandled_irq = 1; + ap->stats.idle_irq = 1; + #endif ++#ifdef CONFIG_ATA_LEDS ++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); ++#endif + ata_sff_port_init(ap); + + return ap; +@@ -5473,6 +5492,12 @@ static void ata_host_release(struct kref + + kfree(ap->pmp_link); + kfree(ap->slave_link); ++#ifdef CONFIG_ATA_LEDS ++ if (ap->ledtrig) { ++ led_trigger_unregister(ap->ledtrig); ++ kfree(ap->ledtrig); ++ }; ++#endif + kfree(ap); + host->ports[i] = NULL; + } +@@ -5875,7 +5900,23 @@ int ata_host_register(struct ata_host *h + host->ports[i]->print_id = atomic_inc_return(&ata_print_id); + host->ports[i]->local_port_no = i + 1; + } ++#ifdef CONFIG_ATA_LEDS ++ for (i = 0; i < host->n_ports; i++) { ++ if (unlikely(!host->ports[i]->ledtrig)) ++ continue; + ++ snprintf(host->ports[i]->ledtrig_name, ++ sizeof(host->ports[i]->ledtrig_name), "ata%u", ++ host->ports[i]->print_id); ++ ++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; ++ ++ if (led_trigger_register(host->ports[i]->ledtrig)) { ++ kfree(host->ports[i]->ledtrig); ++ host->ports[i]->ledtrig = NULL; ++ } ++ } ++#endif + /* Create associated sysfs transport objects */ + for (i = 0; i < host->n_ports; i++) { + rc = ata_tport_add(host->dev,host->ports[i]); +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -23,6 +23,9 @@ + #include + #include + #include ++#ifdef CONFIG_ATA_LEDS ++#include ++#endif + + /* + * Define if arch has non-standard setup. This is a _PCI_ standard +@@ -864,6 +867,12 @@ struct ata_port { + #ifdef CONFIG_ATA_ACPI + struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ + #endif ++ ++#ifdef CONFIG_ATA_LEDS ++ struct led_trigger *ledtrig; ++ char ledtrig_name[8]; ++#endif ++ + /* owned by EH */ + u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; + }; diff --git a/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch new file mode 100644 index 0000000000..5ca8933d6f --- /dev/null +++ b/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch @@ -0,0 +1,26 @@ +From d6988cf1d16faac56899918bb2b1be8d85155e3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 20 Feb 2021 18:36:38 +0100 +Subject: [PATCH] hwrng: bcm2835: set quality to 1000 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows devices without a high precission timer to reduce boot from >100s +to <30s. + +Signed-off-by: Álvaro Fernández Rojas +--- + drivers/char/hw_random/bcm2835-rng.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/char/hw_random/bcm2835-rng.c ++++ b/drivers/char/hw_random/bcm2835-rng.c +@@ -170,6 +170,7 @@ static int bcm2835_rng_probe(struct plat + priv->rng.init = bcm2835_rng_init; + priv->rng.read = bcm2835_rng_read; + priv->rng.cleanup = bcm2835_rng_cleanup; ++ priv->rng.quality = 1000; + + if (dev_of_node(dev)) { + rng_id = of_match_node(bcm2835_rng_of_match, dev->of_node); diff --git a/target/linux/generic/pending-6.6/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-6.6/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch new file mode 100644 index 0000000000..fc61ee202a --- /dev/null +++ b/target/linux/generic/pending-6.6/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch @@ -0,0 +1,102 @@ +From 663b9f99bb35dbc0c7b685f71ee3668a60d31320 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 02:02:00 +0100 +Subject: [PATCH] PCI: aardvark: Make main irq_chip structure a static driver + structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Marc Zyngier says [1] that we should use struct irq_chip as a global +static struct in the driver. Even though the structure currently +contains a dynamic member (parent_device), Marc says [2] that he plans +to kill it and make the structure completely static. + +We have already converted others irq_chip structures in this driver in +this way, but we omitted this one because the .name member is +dynamically created from device's name, and the name is displayed in +sysfs, so changing it would break sysfs ABI. + +The rationale for changing the name (to "advk-INT") in spite of sysfs +ABI, and thus allowing to convert to a static structure, is that after +the other changes we made in this series, the IRQ chip is basically +something different: it no logner generates ERR and PME interrupts (they +are generated by emulated bridge's rp_irq_chip). + +[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/ +[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/ + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 25 +++++++------------------ + 1 file changed, 7 insertions(+), 18 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -277,7 +277,6 @@ struct advk_pcie { + u8 wins_count; + struct irq_domain *rp_irq_domain; + struct irq_domain *irq_domain; +- struct irq_chip irq_chip; + raw_spinlock_t irq_lock; + struct irq_domain *msi_domain; + struct irq_domain *msi_inner_domain; +@@ -1426,14 +1425,19 @@ static void advk_pcie_irq_unmask(struct + raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); + } + ++static struct irq_chip advk_irq_chip = { ++ .name = "advk-INT", ++ .irq_mask = advk_pcie_irq_mask, ++ .irq_unmask = advk_pcie_irq_unmask, ++}; ++ + static int advk_pcie_irq_map(struct irq_domain *h, + unsigned int virq, irq_hw_number_t hwirq) + { + struct advk_pcie *pcie = h->host_data; + + irq_set_status_flags(virq, IRQ_LEVEL); +- irq_set_chip_and_handler(virq, &pcie->irq_chip, +- handle_level_irq); ++ irq_set_chip_and_handler(virq, &advk_irq_chip, handle_level_irq); + irq_set_chip_data(virq, pcie); + + return 0; +@@ -1492,7 +1496,6 @@ static int advk_pcie_init_irq_domain(str + struct device *dev = &pcie->pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *pcie_intc_node; +- struct irq_chip *irq_chip; + int ret = 0; + + raw_spin_lock_init(&pcie->irq_lock); +@@ -1503,28 +1506,14 @@ static int advk_pcie_init_irq_domain(str + return -ENODEV; + } + +- irq_chip = &pcie->irq_chip; +- +- irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq", +- dev_name(dev)); +- if (!irq_chip->name) { +- ret = -ENOMEM; +- goto out_put_node; +- } +- +- irq_chip->irq_mask = advk_pcie_irq_mask; +- irq_chip->irq_unmask = advk_pcie_irq_unmask; +- + pcie->irq_domain = + irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, + &advk_pcie_irq_domain_ops, pcie); + if (!pcie->irq_domain) { + dev_err(dev, "Failed to get a INTx IRQ domain\n"); + ret = -ENOMEM; +- goto out_put_node; + } + +-out_put_node: + of_node_put(pcie_intc_node); + return ret; + } diff --git a/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch b/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch new file mode 100644 index 0000000000..cc6f1e0d9d --- /dev/null +++ b/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch @@ -0,0 +1,114 @@ +From patchwork Wed Mar 22 17:15:12 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13184389 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 73F2DC6FD1C + for ; Wed, 22 Mar 2023 17:15:59 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S231363AbjCVRP5 (ORCPT ); + Wed, 22 Mar 2023 13:15:57 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58824 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S231408AbjCVRPy (ORCPT + ); Wed, 22 Mar 2023 13:15:54 -0400 +Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com + [IPv6:2a00:1450:4864:20::32d]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70E4C64B28; + Wed, 22 Mar 2023 10:15:24 -0700 (PDT) +Received: by mail-wm1-x32d.google.com with SMTP id n19so1740892wms.0; + Wed, 22 Mar 2023 10:15:24 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679505322; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=dEknM98Izmc8d/crPsoJ+ejZxfl78958Ei6SPYhYDHs=; + b=LTOQ75W3s5nYo+nEfiJAKqytSopONB4jCtU3zRygzPMasugVOrYFMsUR+WrpsAjuRT + v4HgWpJxEsIWeRXrUN9W21mFXhGgJLJXSxRnrio0CsZZBNMdkebbNOphgKXIWAdm+2iM + PzqAdGm5t38wT2mmm6V/9hCy90+12raHM82tNFdhhiezfg2cukVOKP3j/TeOVCwas0gQ + iFc+CuZB6y73zYXvMUMUpTsqI5vev4xJsSMHIQJVmUxJAwqhOBhN9JCRo7Ao+wayjn2d + Fxo6AV3A8v68nVfoQ0K0I+eWXG48nMCX45iWh/lVvVTOFcR99kn4va7NY1oVnPsh+WQz + WcLA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679505322; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=dEknM98Izmc8d/crPsoJ+ejZxfl78958Ei6SPYhYDHs=; + b=wv2NSR1B5RnsdoEE7mgJSHAfSs1JHZbQ1HPMldyaGWAk1dcucqh/uDzM3Flz+ADRi1 + 19NoaB2Ur7QaWZejbuplnIOK/nte3PnmqJ9ZNw8HejmuS4eU8mB1V1aJUSKSPGsfUi4a + LYe3HSw87l0jrAC7ptdKvdUtzBoIkX0CeFvfguTQQkDhUTyAFIG144hY6uPXY9Mga96b + gnNe2dLCzHQLbEJpaDaavT7FEEcLDxaq7jNcR2xqEEZaIwfcew+Q05t4xL/3i8GAj9Ru + 6ivQjIbBKfYQF88o7KnOW9o1wjrGsk+Nd4Iy0OLZix3JQasCJGrKV7ib5awI9J39upYV + fa4A== +X-Gm-Message-State: AO0yUKWw75I1M5Vjrd4vXq4GTruQu0H84pycgyi2CT3bczTYRJpWmEWg + +bHDhvp1n5IWW85GI9vKWpbclB13a/S0RQ== +X-Google-Smtp-Source: + AK7set9T/2oJsVetUb2L4mPEWu8YqDrnK8EzHK5bJf1ABIa1Et8f7BFJ7AA3j14ITZuf8cH0HqlRtg== +X-Received: by 2002:a05:600c:2304:b0:3ed:2949:985b with SMTP id + 4-20020a05600c230400b003ed2949985bmr206833wmo.23.1679505322457; + Wed, 22 Mar 2023 10:15:22 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.21 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Wed, 22 Mar 2023 10:15:22 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, + f.fainelli@gmail.com, jonas.gorski@gmail.com, + william.zhang@broadcom.com, linux-clk@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , + Rob Herring +Subject: [PATCH v4 1/4] dt-bindings: clk: add BCM63268 timer clock definitions +Date: Wed, 22 Mar 2023 18:15:12 +0100 +Message-Id: <20230322171515.120353-2-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> +References: <20230322171515.120353-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: linux-clk@vger.kernel.org + +Add missing timer clock definitions for BCM63268. + +Signed-off-by: Álvaro Fernández Rojas +Acked-by: Rob Herring +--- + v4: no changes + v3: no changes + v2: change commit title, as suggested by Stephen Boyd + + include/dt-bindings/clock/bcm63268-clock.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/include/dt-bindings/clock/bcm63268-clock.h ++++ b/include/dt-bindings/clock/bcm63268-clock.h +@@ -27,4 +27,17 @@ + #define BCM63268_CLK_TBUS 27 + #define BCM63268_CLK_ROBOSW250 31 + ++#define BCM63268_TCLK_EPHY1 0 ++#define BCM63268_TCLK_EPHY2 1 ++#define BCM63268_TCLK_EPHY3 2 ++#define BCM63268_TCLK_GPHY1 3 ++#define BCM63268_TCLK_DSL 4 ++#define BCM63268_TCLK_WAKEON_EPHY 6 ++#define BCM63268_TCLK_WAKEON_DSL 7 ++#define BCM63268_TCLK_FAP1 11 ++#define BCM63268_TCLK_FAP2 15 ++#define BCM63268_TCLK_UTO_50 16 ++#define BCM63268_TCLK_UTO_EXTIN 17 ++#define BCM63268_TCLK_USB_REF 18 ++ + #endif /* __DT_BINDINGS_CLOCK_BCM63268_H */ diff --git a/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch b/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch new file mode 100644 index 0000000000..5f1be105ac --- /dev/null +++ b/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch @@ -0,0 +1,107 @@ +From patchwork Wed Mar 22 17:15:13 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13184390 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id D0B1AC6FD1C + for ; Wed, 22 Mar 2023 17:16:08 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S231472AbjCVRQI (ORCPT ); + Wed, 22 Mar 2023 13:16:08 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58934 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S231435AbjCVRP5 (ORCPT + ); Wed, 22 Mar 2023 13:15:57 -0400 +Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com + [IPv6:2a00:1450:4864:20::329]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9655064863; + Wed, 22 Mar 2023 10:15:25 -0700 (PDT) +Received: by mail-wm1-x329.google.com with SMTP id + v4-20020a05600c470400b003ee4f06428fso2424553wmo.4; + Wed, 22 Mar 2023 10:15:25 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679505324; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=C7ykhArT1dO7P8wtmI92eo4c7KtPZI9w182/5+cB3T0=; + b=WRZRU2SM9n1LfUj4SgTPfQczADC2pfvoIrOsNpBLTym2eOfmkTetb/WbGSla5kw2Wb + SH5MIC2fFeScJg6T5FFAUOOLmRVW9xvl8Q3T3NKb3z/9wvPHO767nrdIbffRWMJFs7gW + wT/kuTpn8GYdfY0sZ/dMTkq41DVusEkxfX6GxtG85O98ZP8xMHQog8aPs9fRfUvI5ZKB + eGYcRz/Wn1cHhjey9jtWzQEEmZ/BT3b0HQTF9Tl88oofhiEgbyjFXr91+vRsLbsJpGXH + /1FjjaLG5DnonKubV9rmbuCU8KzwH331gi2KuRjvLD2V+OMewqSa5i+GvgVv8x2zC8y+ + /mLQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679505324; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=C7ykhArT1dO7P8wtmI92eo4c7KtPZI9w182/5+cB3T0=; + b=bhd0fNh0jDOMlGSC4F+p5igV8AUlGEPj2cXUwgdgqRfSSuUy9z+Li8cT0MbY/aWH5Z + qInRVA+R1cWV3ubrDyKag6oEc0LDU234bnMFcP9b7MRlrM8Dpit9TFSyqJU4sDUWNDs5 + KOe2k/SNIdat6munC9VOuEBDO0eB/UDMN+repKwXNdHChp/Toq9qMvW4Uy8uHxosbQlD + 8P88GbKFjynb1E8I8croGjfub7+y8PPsWB0xNUcafIv6xs3MnVOP1Mk4KwBCbqS509la + mfjsriXtIybO8XFqtn100ungjvbFWdogEplLdSPVdgAqdfF5J8gHxAoApoeYejYkL5/R + kOhQ== +X-Gm-Message-State: AO0yUKWdzr3dMmjKhD8tF+ec4Dfdq9VGZ/WCU4d85npKQvxSwhNPZZ1J + 5WYRIqivh0suFC1OqEidwenpiJYvXedYjw== +X-Google-Smtp-Source: + AK7set87ew2/mKWeShXTTW/YBbBJNR2zeGFV0CfuqLXhiJEU6tqFuyKcW+vFEoKHIbNUS8wRy1SzLA== +X-Received: by 2002:a05:600c:290:b0:3ee:6d88:774a with SMTP id + 16-20020a05600c029000b003ee6d88774amr160734wmk.14.1679505323514; + Wed, 22 Mar 2023 10:15:23 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.22 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Wed, 22 Mar 2023 10:15:23 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, + f.fainelli@gmail.com, jonas.gorski@gmail.com, + william.zhang@broadcom.com, linux-clk@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , + Rob Herring +Subject: [PATCH v4 2/4] dt-bindings: reset: add BCM63268 timer reset + definitions +Date: Wed, 22 Mar 2023 18:15:13 +0100 +Message-Id: <20230322171515.120353-3-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> +References: <20230322171515.120353-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: linux-clk@vger.kernel.org + +Add missing timer reset definitions for BCM63268. + +Signed-off-by: Álvaro Fernández Rojas +Acked-by: Rob Herring +--- + v4: no changes + v3: no changes + v2: change commit title, as suggested by Stephen Boyd + + include/dt-bindings/reset/bcm63268-reset.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/include/dt-bindings/reset/bcm63268-reset.h ++++ b/include/dt-bindings/reset/bcm63268-reset.h +@@ -23,4 +23,8 @@ + #define BCM63268_RST_PCIE_HARD 17 + #define BCM63268_RST_GPHY 18 + ++#define BCM63268_TRST_SW 29 ++#define BCM63268_TRST_HW 30 ++#define BCM63268_TRST_POR 31 ++ + #endif /* __DT_BINDINGS_RESET_BCM63268_H */ diff --git a/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch b/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch new file mode 100644 index 0000000000..7e500cd1b5 --- /dev/null +++ b/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch @@ -0,0 +1,345 @@ +From patchwork Wed Mar 22 17:15:15 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 13184392 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 199D9C76196 + for ; Wed, 22 Mar 2023 17:16:11 +0000 (UTC) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S231512AbjCVRQJ (ORCPT ); + Wed, 22 Mar 2023 13:16:09 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58942 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S231442AbjCVRP5 (ORCPT + ); Wed, 22 Mar 2023 13:15:57 -0400 +Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com + [IPv6:2a00:1450:4864:20::32c]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DDB36487D; + Wed, 22 Mar 2023 10:15:27 -0700 (PDT) +Received: by mail-wm1-x32c.google.com with SMTP id + i5-20020a05600c354500b003edd24054e0so6717370wmq.4; + Wed, 22 Mar 2023 10:15:27 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; t=1679505325; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:from:to:cc:subject:date + :message-id:reply-to; + bh=rkv/eZYA1ncHp5FnV2ZWc3hgYnAx28S86QA9vmcXFCY=; + b=Y1mva2Bt3sUbKxLgEUS331CJbGxUc4z8kTQW8qiHWGhYlFKtm+d5z4sT40E5BeZAnU + zmTbCI7jbroe9NYBxGUmSli6LNVDPjND80ChbhWTqbqMQTmeQFWut9KmeBWK6Oze2lC/ + XMSOorUzowjcU2xtHNrzoq2KH2pstW573lsB8WnzFVfhMaRkE9DfRr6WNyA7zC8DyxM5 + ezxlCQtCmgPfCqlyksbIDKrgrRf3GiUR0yUd6xRU+MssyvH1FkYGDCerPctDto6lGHBz + 8Y15jT3l6OnQMT6dkekgpPF5/XrSUY93u9g0B4U8+0dhNj+K7vmDen+jqdess+tpLnq/ + gFrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; t=1679505325; + h=content-transfer-encoding:mime-version:references:in-reply-to + :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc + :subject:date:message-id:reply-to; + bh=rkv/eZYA1ncHp5FnV2ZWc3hgYnAx28S86QA9vmcXFCY=; + b=Ym4+u8bbTQGNkewUBrLf+89vE0EFJBQp2f1crwUxZFboKTROF9ltZonY1CGepo7b0B + fkx3TbWQy5X65g3ScuieqtClCI8WanPeNBJ48+JipJYO3ODVNBxnVaTuW/0FOIcahfqe + sG5GvggHhzRz+Yeybsbnupmzxnw8Ez0BpMl3p7zcjHL7BGZDdOOX2Zbw3zfyYa5sg2nX + UXYJT36zy2h39gxUsy9QkhQ76CG3w6omniohZpYidpojpiDjbOy0nKFky4kUe+YyA1fF + 4IBhjAm6mH+uh6wHSG1qj+NAXHs0xDDJps16PbJwAgL7Qt9K5WW+R/UAYPmHFgaRIHOw + /seA== +X-Gm-Message-State: AO0yUKXRtoYO8Nfus6Ca8lhM39P1Xn6TGkhatEfoISd1YNOkTJJN2hW+ + xRphLgxlzNfCLcVPlpGK9dk= +X-Google-Smtp-Source: + AK7set9VnMEykugk8ZYnkXuqK41bX1dzlvKsAXHEjr8i2NZBld0buKhQLcGYEcwxnBgVTtC7eRGfXw== +X-Received: by 2002:a1c:7c0b:0:b0:3e2:1dac:b071 with SMTP id + x11-20020a1c7c0b000000b003e21dacb071mr178053wmc.13.1679505325582; + Wed, 22 Mar 2023 10:15:25 -0700 (PDT) +Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. + [79.146.124.255]) + by smtp.gmail.com with ESMTPSA id + v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.24 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Wed, 22 Mar 2023 10:15:25 -0700 (PDT) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, + krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, + f.fainelli@gmail.com, jonas.gorski@gmail.com, + william.zhang@broadcom.com, linux-clk@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH v4 4/4] clk: bcm: Add BCM63268 timer clock and reset driver +Date: Wed, 22 Mar 2023 18:15:15 +0100 +Message-Id: <20230322171515.120353-5-noltari@gmail.com> +X-Mailer: git-send-email 2.30.2 +In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> +References: <20230322171515.120353-1-noltari@gmail.com> +MIME-Version: 1.0 +Precedence: bulk +List-ID: +X-Mailing-List: linux-clk@vger.kernel.org + +Add driver for BCM63268 timer clock and reset controller. + +Signed-off-by: Álvaro Fernández Rojas +--- + v4: add changes suggested by Stephen Boyd: + - Usage of of_device_get_match_data() isn't needed. + - Use devm_clk_hw_register_gate(). + - Drop clk_hw_unregister_gate(). + v3: add missing include to fix build warning + v2: add changes suggested by Stephen Boyd + + drivers/clk/bcm/Kconfig | 9 ++ + drivers/clk/bcm/Makefile | 1 + + drivers/clk/bcm/clk-bcm63268-timer.c | 215 +++++++++++++++++++++++++++ + 3 files changed, 225 insertions(+) + create mode 100644 drivers/clk/bcm/clk-bcm63268-timer.c + +--- a/drivers/clk/bcm/Kconfig ++++ b/drivers/clk/bcm/Kconfig +@@ -37,6 +37,15 @@ config CLK_BCM_63XX_GATE + Enable common clock framework support for Broadcom BCM63xx DSL SoCs + based on the MIPS architecture + ++config CLK_BCM63268_TIMER ++ bool "Broadcom BCM63268 timer clock and reset support" ++ depends on BMIPS_GENERIC || COMPILE_TEST ++ default BMIPS_GENERIC ++ select RESET_CONTROLLER ++ help ++ Enable timer clock and reset support for Broadcom BCM63268 DSL SoCs ++ based on the MIPS architecture. ++ + config CLK_BCM_KONA + bool "Broadcom Kona CCU clock support" + depends on ARCH_BCM_MOBILE || COMPILE_TEST +--- a/drivers/clk/bcm/Makefile ++++ b/drivers/clk/bcm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o + obj-$(CONFIG_CLK_BCM_63XX_GATE) += clk-bcm63xx-gate.o ++obj-$(CONFIG_CLK_BCM63268_TIMER) += clk-bcm63268-timer.o + obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o + obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o + obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o +--- /dev/null ++++ b/drivers/clk/bcm/clk-bcm63268-timer.c +@@ -0,0 +1,215 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * BCM63268 Timer Clock and Reset Controller Driver ++ * ++ * Copyright (C) 2023 Álvaro Fernández Rojas ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define BCM63268_TIMER_RESET_SLEEP_MIN_US 10000 ++#define BCM63268_TIMER_RESET_SLEEP_MAX_US 20000 ++ ++struct bcm63268_tclkrst_hw { ++ void __iomem *regs; ++ spinlock_t lock; ++ ++ struct reset_controller_dev rcdev; ++ struct clk_hw_onecell_data data; ++}; ++ ++struct bcm63268_tclk_table_entry { ++ const char * const name; ++ u8 bit; ++}; ++ ++static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = { ++ { ++ .name = "ephy1", ++ .bit = BCM63268_TCLK_EPHY1, ++ }, { ++ .name = "ephy2", ++ .bit = BCM63268_TCLK_EPHY2, ++ }, { ++ .name = "ephy3", ++ .bit = BCM63268_TCLK_EPHY3, ++ }, { ++ .name = "gphy1", ++ .bit = BCM63268_TCLK_GPHY1, ++ }, { ++ .name = "dsl", ++ .bit = BCM63268_TCLK_DSL, ++ }, { ++ .name = "wakeon_ephy", ++ .bit = BCM63268_TCLK_WAKEON_EPHY, ++ }, { ++ .name = "wakeon_dsl", ++ .bit = BCM63268_TCLK_WAKEON_DSL, ++ }, { ++ .name = "fap1_pll", ++ .bit = BCM63268_TCLK_FAP1, ++ }, { ++ .name = "fap2_pll", ++ .bit = BCM63268_TCLK_FAP2, ++ }, { ++ .name = "uto_50", ++ .bit = BCM63268_TCLK_UTO_50, ++ }, { ++ .name = "uto_extin", ++ .bit = BCM63268_TCLK_UTO_EXTIN, ++ }, { ++ .name = "usb_ref", ++ .bit = BCM63268_TCLK_USB_REF, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static inline struct bcm63268_tclkrst_hw * ++to_bcm63268_timer_reset(struct reset_controller_dev *rcdev) ++{ ++ return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev); ++} ++ ++static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev, ++ unsigned long id, bool assert) ++{ ++ struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); ++ unsigned long flags; ++ uint32_t val; ++ ++ spin_lock_irqsave(&reset->lock, flags); ++ val = __raw_readl(reset->regs); ++ if (assert) ++ val &= ~BIT(id); ++ else ++ val |= BIT(id); ++ __raw_writel(val, reset->regs); ++ spin_unlock_irqrestore(&reset->lock, flags); ++ ++ return 0; ++} ++ ++static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return bcm63268_timer_reset_update(rcdev, id, true); ++} ++ ++static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return bcm63268_timer_reset_update(rcdev, id, false); ++} ++ ++static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ bcm63268_timer_reset_update(rcdev, id, true); ++ usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, ++ BCM63268_TIMER_RESET_SLEEP_MAX_US); ++ ++ bcm63268_timer_reset_update(rcdev, id, false); ++ /* ++ * Ensure component is taken out reset state by sleeping also after ++ * deasserting the reset. Otherwise, the component may not be ready ++ * for operation. ++ */ ++ usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, ++ BCM63268_TIMER_RESET_SLEEP_MAX_US); ++ ++ return 0; ++} ++ ++static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); ++ ++ return !(__raw_readl(reset->regs) & BIT(id)); ++} ++ ++static struct reset_control_ops bcm63268_timer_reset_ops = { ++ .assert = bcm63268_timer_reset_assert, ++ .deassert = bcm63268_timer_reset_deassert, ++ .reset = bcm63268_timer_reset_reset, ++ .status = bcm63268_timer_reset_status, ++}; ++ ++static int bcm63268_tclk_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ const struct bcm63268_tclk_table_entry *entry; ++ struct bcm63268_tclkrst_hw *hw; ++ struct clk_hw *clk; ++ u8 maxbit = 0; ++ int i, ret; ++ ++ for (entry = bcm63268_timer_clocks; entry->name; entry++) ++ maxbit = max(maxbit, entry->bit); ++ maxbit++; ++ ++ hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit), ++ GFP_KERNEL); ++ if (!hw) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, hw); ++ ++ spin_lock_init(&hw->lock); ++ ++ hw->data.num = maxbit; ++ for (i = 0; i < maxbit; i++) ++ hw->data.hws[i] = ERR_PTR(-ENODEV); ++ ++ hw->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(hw->regs)) ++ return PTR_ERR(hw->regs); ++ ++ for (entry = bcm63268_timer_clocks; entry->name; entry++) { ++ clk = devm_clk_hw_register_gate(dev, entry->name, NULL, 0, ++ hw->regs, entry->bit, ++ CLK_GATE_BIG_ENDIAN, ++ &hw->lock); ++ if (IS_ERR(clk)) ++ return PTR_ERR(clk); ++ ++ hw->data.hws[entry->bit] = clk; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, ++ &hw->data); ++ if (ret) ++ return ret; ++ ++ hw->rcdev.of_node = dev->of_node; ++ hw->rcdev.ops = &bcm63268_timer_reset_ops; ++ ++ ret = devm_reset_controller_register(dev, &hw->rcdev); ++ if (ret) ++ dev_err(dev, "Failed to register reset controller\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm63268_tclk_dt_ids[] = { ++ { .compatible = "brcm,bcm63268-timer-clocks" }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver bcm63268_tclk = { ++ .probe = bcm63268_tclk_probe, ++ .driver = { ++ .name = "bcm63268-timer-clock", ++ .of_match_table = bcm63268_tclk_dt_ids, ++ }, ++}; ++builtin_platform_driver(bcm63268_tclk); diff --git a/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch b/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch new file mode 100644 index 0000000000..c5db5d9491 --- /dev/null +++ b/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch @@ -0,0 +1,61 @@ +From 629c701fc39f1ada9416e0766a86729e83bde86c Mon Sep 17 00:00:00 2001 +Message-ID: <629c701fc39f1ada9416e0766a86729e83bde86c.1694465766.git.daniel@makrotopia.org> +From: Daniel Golle +Date: Mon, 11 Sep 2023 21:27:44 +0100 +Subject: [PATCH] serial: 8250_mtk: track busclk state to avoid bus error +To: Greg Kroah-Hartman , + Jiri Slaby , + Matthias Brugger , + AngeloGioacchino Del Regno , + Daniel Golle , + John Ogness , + Chen-Yu Tsai , + Changqi Hu , + linux-kernel@vger.kernel.org, + linux-serial@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org + +Commit e32a83c70cf9 ("serial: 8250-mtk: modify mtk uart power and +clock management") introduced polling a debug register to make sure +the UART is idle before disabling the bus clock. However, at least on +some MediaTek SoCs access to that very debug register requires the bus +clock being enabled. Hence calling the suspend function while already +in suspended state results in that register access triggering a bus +error. In order to avoid that, track the state of the bus clock and +only poll the debug register if not already in suspended state. + +Fixes: e32a83c70cf9 ("serial: 8250-mtk: modify mtk uart power and clock management") +Signed-off-by: Daniel Golle +--- + drivers/tty/serial/8250/8250_mtk.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/tty/serial/8250/8250_mtk.c ++++ b/drivers/tty/serial/8250/8250_mtk.c +@@ -32,7 +32,7 @@ + #define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */ + #define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */ + #define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */ +-#define MTK_UART_DEBUG0 0x18 ++#define MTK_UART_DEBUG0 0x18 + #define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */ + #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ + #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ +@@ -418,13 +418,12 @@ static int __maybe_unused mtk8250_runtim + struct mtk8250_data *data = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(data->line); + +- /* wait until UART in idle status */ +- while +- (serial_in(up, MTK_UART_DEBUG0)); +- + if (data->clk_count == 0U) { + dev_dbg(dev, "%s clock count is 0\n", __func__); + } else { ++ /* wait until UART in idle status */ ++ while ++ (serial_in(up, MTK_UART_DEBUG0)); + clk_disable_unprepare(data->bus_clk); + data->clk_count--; + } diff --git a/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch b/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch new file mode 100644 index 0000000000..e25389363f --- /dev/null +++ b/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch @@ -0,0 +1,43 @@ +From d0562705bcd4cb9849156f095b2af0ec1bb53b56 Mon Sep 17 00:00:00 2001 +From: Lech Perczak +Date: Fri, 17 Nov 2023 21:33:04 +0100 +Subject: [PATCH] ARM: dts: nxp: imx7d-pico: add cpu-supply nodes + +The PICO-IMX7D SoM has the usual power supply configuration using +output sw1a of PF3000 PMIC, which was defined in downstream derivative +of linux-imx (see link) in the sources for "Android Things" devkit. +It is required to support CPU frequency scaling. + +Map the respective "cpu-supply" nodes of each core to sw1a of the PMIC. + +Enabling them causes cpufreq-dt, and imx-thermal drivers to probe +successfully, and CPU frequency scaling to function. + +Link: https://android.googlesource.com/platform/hardware/bsp/kernel/nxp/imx-v4.1/+/o-iot-preview-5/arch/arm/boot/dts/imx7d-pico.dtsi#849 + +Cc: Fabio Estevam +Cc: Shawn Guo +Cc: Sascha Hauer + +Signed-off-by: Lech Perczak +--- + arch/arm/boot/dts/imx7d-pico.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/imx7d-pico.dtsi ++++ b/arch/arm/boot/dts/imx7d-pico.dtsi +@@ -108,6 +108,14 @@ + assigned-clock-rates = <0>, <32768>; + }; + ++&cpu0 { ++ cpu-supply = <&sw1a_reg>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&sw1a_reg>; ++}; ++ + &ecspi3 { + cs-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; diff --git a/target/linux/generic/pending-6.6/920-mangle_bootargs.patch b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch new file mode 100644 index 0000000000..4552b4cd66 --- /dev/null +++ b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch @@ -0,0 +1,71 @@ +From: Imre Kaloz +Subject: init: add CONFIG_MANGLE_BOOTARGS and disable it by default + +Enabling this option renames the bootloader supplied root= +and rootfstype= variables, which might have to be know but +would break the automatisms OpenWrt uses. + +Signed-off-by: Imre Kaloz +--- + init/Kconfig | 9 +++++++++ + init/main.c | 24 ++++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1836,6 +1836,15 @@ config EMBEDDED + an embedded system so certain expert options are available + for configuration. + ++config MANGLE_BOOTARGS ++ bool "Rename offending bootargs" ++ depends on EXPERT ++ help ++ Sometimes the bootloader passed bogus root= and rootfstype= ++ parameters to the kernel, and while you want to ignore them, ++ you need to know the values f.e. to support dual firmware ++ layouts on the flash. ++ + config HAVE_PERF_EVENTS + bool + help +--- a/init/main.c ++++ b/init/main.c +@@ -611,6 +611,29 @@ static inline void setup_nr_cpu_ids(void + static inline void smp_prepare_cpus(unsigned int maxcpus) { } + #endif + ++#ifdef CONFIG_MANGLE_BOOTARGS ++static void __init mangle_bootargs(char *command_line) ++{ ++ char *rootdev; ++ char *rootfs; ++ ++ rootdev = strstr(command_line, "root=/dev/mtdblock"); ++ ++ if (rootdev) ++ strncpy(rootdev, "mangled_rootblock=", 18); ++ ++ rootfs = strstr(command_line, "rootfstype"); ++ ++ if (rootfs) ++ strncpy(rootfs, "mangled_fs", 10); ++ ++} ++#else ++static void __init mangle_bootargs(char *command_line) ++{ ++} ++#endif ++ + /* + * We need to store the untouched command line for future reference. + * We also need to store the touched command line since the parameter +@@ -958,6 +981,7 @@ asmlinkage __visible void __init __no_sa + pr_notice("%s", linux_banner); + early_security_init(); + setup_arch(&command_line); ++ mangle_bootargs(command_line); + setup_boot_config(); + setup_command_line(command_line); + setup_nr_cpu_ids(); diff --git a/target/linux/generic/pending-6.6/980-tools-thermal-tmon-Fix-compilation-warning-for-wrong.patch b/target/linux/generic/pending-6.6/980-tools-thermal-tmon-Fix-compilation-warning-for-wrong.patch new file mode 100644 index 0000000000..6a0a19987f --- /dev/null +++ b/target/linux/generic/pending-6.6/980-tools-thermal-tmon-Fix-compilation-warning-for-wrong.patch @@ -0,0 +1,51 @@ +From a7a94ca21ac0f347f683d33c72b4aab57ce5eec3 Mon Sep 17 00:00:00 2001 +From: Florian Eckert +Date: Mon, 20 Nov 2023 11:13:20 +0100 +Subject: [PATCH] tools/thermal/tmon: Fix compilation warning for wrong format + +The following warnings are shown during compilation: + +tui.c: In function 'show_cooling_device': + tui.c:216:40: warning: format '%d' expects argument of type 'int', but +argument 7 has type 'long unsigned int' [-Wformat=] + 216 | "%02d %12.12s%6d %6d", + | ~~^ + | | + | int + | %6ld + ...... + 219 | ptdata.cdi[j].cur_state, + | ~~~~~~~~~~~~~~~~~~~~~~~ + | | + | long unsigned int + tui.c:216:44: warning: format '%d' expects argument of type 'int', but +argument 8 has type 'long unsigned int' [-Wformat=] + 216 | "%02d %12.12s%6d %6d", + | ~~^ + | | + | int + | %6ld + ...... + 220 | ptdata.cdi[j].max_state); + | ~~~~~~~~~~~~~~~~~~~~~~~ + | | + | long unsigned int + +To fix this, the correct string format must be used for printing. + +Signed-off-by: Florian Eckert +--- + tools/thermal/tmon/tui.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/thermal/tmon/tui.c ++++ b/tools/thermal/tmon/tui.c +@@ -213,7 +213,7 @@ void show_cooling_device(void) + * cooling device instances. skip unused idr. + */ + mvwprintw(cooling_device_window, j + 2, 1, +- "%02d %12.12s%6d %6d", ++ "%02d %12.12s%6lu %6lu", + ptdata.cdi[j].instance, + ptdata.cdi[j].type, + ptdata.cdi[j].cur_state, From 8c3892b1d79aa0901154e31644b9e6f0446023f4 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 01:47:10 +0800 Subject: [PATCH 041/108] generic: 6.6: drop backport patches Drop all backport patches that are now included in kernel 6.6. Signed-off-by: Weijie Gao --- ...i-gen-LRU-rename-lru_gen_struct-to-l.patch | 352 --- ...i-gen-LRU-remove-eviction-fairness-s.patch | 192 -- ...i-gen-LRU-remove-aging-fairness-safe.patch | 294 -- ...lti-gen-LRU-shuffle-should_run_aging.patch | 166 -- ...i-gen-LRU-per-node-lru_gen_folio-lis.patch | 876 ------ ...i-gen-LRU-clarify-scan_control-flags.patch | 202 -- ...i-gen-LRU-simplify-arch_has_hw_pte_y.patch | 38 - ...m-multi-gen-LRU-avoid-futile-retries.patch | 92 - ...3-10-UPSTREAM-mm-add-vma_has_recency.patch | 191 -- ...STREAM-mm-support-POSIX_FADV_NOREUSE.patch | 129 - ...i-gen-LRU-section-for-working-set-pr.patch | 67 - ...i-gen-LRU-section-for-rmap-PT-walk-f.patch | 57 - ...ti-gen-LRU-section-for-Bloom-filters.patch | 243 -- ...-multi-gen-LRU-section-for-memcg-LRU.patch | 427 --- ...i-gen-LRU-improve-lru_gen_exit_memcg.patch | 40 - ...multi-gen-LRU-improve-walk_pmd_range.patch | 135 - ...i-gen-LRU-simplify-lru_gen_look_arou.patch | 148 - ...i-gen-LRU-remove-wait_event_killable.patch | 273 -- ...0-v6.3-bitfield-add-FIELD_PREP_CONST.patch | 58 - ...-some-linker-warnings-in-recent-link.patch | 63 - ...y-a-bit-code-find-partition-matching.patch | 65 - ...find-OF-node-for-every-MTD-partition.patch | 84 - ...T_DEV-for-partitions-marked-as-rootf.patch | 47 - ...TP-Link-SafeLoader-partitions-table-.patch | 229 -- ...onix-use-scratch-buffer-for-DMA-oper.patch | 35 - ....3-mtd-ubi-wire-up-parent-MTD-device.patch | 33 - ...-mtd-ubi-block-wire-up-device-parent.patch | 49 - ...-mtd_otp_nvmem_add-to-handle-EPROBE_.patch | 47 - ...611-v6.3-net-add-helper-eth_addr_add.patch | 41 - ...uirk-for-Fiberstone-GPON-ONU-34-20BI.patch | 32 - ...edicated-C45-API-to-MDIO-bus-drivers.patch | 326 --- ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 - ...eplace-of_gpio.h-with-what-indeed-is.patch | 32 - ...upport-qca8081-genphy_c45_pma_read_a.patch | 70 - ...3x-merge-qca8081-slave-seed-function.patch | 73 - ...nable-qca8081-slave-seed-conditional.patch | 76 - ...-at803x-support-qca8081-1G-chip-type.patch | 48 - ...emove-qca8081-1G-fast-retrain-and-sl.patch | 98 - ...dd-qca8081-fifo-reset-on-the-link-ch.patch | 55 - ...cs-add-driver-for-MediaTek-SGMII-PCS.patch | 394 --- ....2-net-fman-memac-Add-serdes-support.patch | 103 - ...2-net-fman-memac-Use-lynx-pcs-driver.patch | 384 --- ...-03-v6.2-net-dpaa-Convert-to-phylink.patch | 2451 ----------------- ...ide-phylink_validate_mask_caps-helpe.patch | 93 - ...valid-state-argument-to-phylink_vali.patch | 39 - ...add-phylink_get_link_timer_ns-helper.patch | 48 - ...cit-phylink_generic_validate-referen.patch | 250 -- ..._bus_find_fwnode-take-a-const-fwnode.patch | 48 - ...-t-print-an_enabled-in-pcs_get_state.patch | 31 - ...e-Autoneg-bit-rather-than-an_enabled.patch | 32 - ...ort-validated-pause-and-autoneg-in-f.patch | 64 - ...2-v6.4-net-phylink-remove-an_enabled.patch | 177 -- ...et-phylink-constify-fwnode-arguments.patch | 88 - ...-fwnode_get_phy_node-fwnode-argument.patch | 38 - ...ylink-fix-ksettings_set-ethtool-call.patch | 44 - ...-support-for-setting-signalling-rate.patch | 149 - ...hy-add-helpers-for-comparing-phy-IDs.patch | 147 - ...ire-supported_interfaces-to-be-fille.patch | 71 - ...ve-duplicated-linkmode-pause-resolut.patch | 64 - ...function-to-resolve-clause-73-negoti.patch | 76 - ...ide-phylink_pcs_config-and-phylink_p.patch | 100 - ...ually-fix-ksettings_set-ethtool-call.patch | 55 - ...net-phylink-add-PCS-negotiation-mode.patch | 324 --- ...ert-phylink_mii_c22_pcs_config-to-ne.patch | 45 - ...-neg_mode-into-phylink_mii_c22_pcs_c.patch | 187 -- ...xi-update-PCS-driver-to-use-neg_mode.patch | 101 - ...e-Autoneg-bit-rather-than-an_enabled.patch | 55 - ...s-fix-incorrect-number-of-interfaces.patch | 30 - ..._eth_soc-enable-flow-offloading-supp.patch | 26 - ...et-mtk_wed-introduce-wed-mcu-support.patch | 591 ---- ...net-mtk_wed-introduce-wed-wo-support.patch | 737 ----- ..._wed-rename-tx_wdma-array-in-rx_wdma.patch | 79 - ...mtk_wed-add-configure-wed-wo-support.patch | 1521 ---------- ...ethernet-mtk_wed-add-rx-mib-counters.patch | 149 - ..._eth_soc-remove-cpu_relax-in-mtk_pen.patch | 36 - ..._wed-add-wcid-overwritten-support-fo.patch | 80 - ..._wed-return-status-value-in-mtk_wdma.patch | 85 - ..._wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch | 52 - ...ethernet-mtk_wed-update-mtk_wed_stop.patch | 98 - ...mtk_wed-add-mtk_wed_rx_reset-routine.patch | 309 --- ..._wed-add-reset-to-tx_ring_setup-call.patch | 103 - ..._wed-fix-sleep-while-atomic-in-mtk_w.patch | 103 - ..._wed-get-rid-of-queue-lock-for-rx-qu.patch | 52 - ..._wed-get-rid-of-queue-lock-for-tx-qu.patch | 75 - ..._eth_soc-introduce-mtk_hw_reset-util.patch | 70 - ..._eth_soc-introduce-mtk_hw_warm_reset.patch | 107 - ..._eth_soc-align-reset-procedure-to-ve.patch | 262 -- ..._eth_soc-add-dma-checks-to-mtk_hw_re.patch | 249 -- ..._wed-add-reset-reset_complete-callba.patch | 124 - ..._wed-add-reset-to-rx_ring_setup-call.patch | 106 - ..._eth_soc-account-for-vlan-in-rx-head.patch | 22 - ..._eth_soc-increase-tx-ring-side-for-Q.patch | 143 - ..._eth_soc-avoid-port_mg-assignment-on.patch | 52 - ..._eth_soc-implement-multi-queue-suppo.patch | 654 ----- ...t-dsa-tag_mtk-assign-per-port-queues.patch | 20 - ...iatek-ppe-assign-per-port-queues-for.patch | 93 - ...ort-for-DSA-rx-offloading-via-metada.patch | 72 - ..._eth_soc-fix-VLAN-rx-hardware-accele.patch | 192 -- ..._eth_soc-disable-hardware-DSA-untagg.patch | 42 - ..._eth_soc-enable-special-tag-when-any.patch | 54 - ..._eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch | 129 - ..._wed-No-need-to-clear-memory-after-a.patch | 26 - ..._wed-fix-some-possible-NULL-pointer-.patch | 61 - ..._wed-fix-possible-deadlock-if-mtk_we.patch | 58 - ..._eth_soc-fix-tx-throughput-regressio.patch | 31 - ...-mtk_eth_soc-add-definitions-for-PCS.patch | 55 - ...eliminate-unnecessary-error-handling.patch | 74 - ...soc-add-pcs_get_state-implementation.patch | 46 - ...convert-mtk_sgmii-to-use-regmap_upda.patch | 130 - ...add-out-of-band-forcing-of-speed-and.patch | 52 - ...07-net-mtk_eth_soc-move-PHY-power-up.patch | 48 - ...h_soc-move-interface-speed-selection.patch | 48 - ...th_soc-add-advertisement-programming.patch | 52 - ...move-and-correct-link-timer-programm.patch | 63 - ...add-support-for-in-band-802.3z-negot.patch | 132 - ...ii-ensure-the-SGMII-PHY-is-powered-d.patch | 119 - ...iatek-sgmii-fix-duplex-configuration.patch | 52 - ...enable-PCS-polling-to-allow-SFP-work.patch | 33 - ...ethernet-mtk_eth_soc-reset-PCS-state.patch | 48 - ..._eth_soc-only-write-values-if-needed.patch | 103 - ...t-mtk_eth_soc-add-support-for-MT7981.patch | 206 -- ..._eth_soc-set-MDIO-bus-clock-frequenc.patch | 76 - ..._eth_soc-switch-to-external-PCS-driv.patch | 512 ---- ...k_eth_soc-use-WO-firmware-for-MT7981.patch | 46 - ..._eth_soc-fix-NULL-pointer-dereferenc.patch | 28 - ..._eth_soc-ppe-add-support-for-flow-ac.patch | 403 --- ...iatek-fix-ppe-flow-accounting-for-v1.patch | 58 - ..._eth_soc-drop-generic-vlan-rx-offloa.patch | 201 -- ..._eth_soc-always-mtk_get_ib1_pkt_type.patch | 31 - ..._ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch | 78 - ..._eth_soc-remove-incorrect-PLL-config.patch | 141 - ..._eth_soc-remove-mac_pcs_get_state-an.patch | 81 - ..._eth_soc-add-version-in-mtk_soc_data.patch | 550 ---- ...t-mtk_eth_soc-increase-MAX_DEVS-to-3.patch | 29 - ..._eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch | 186 -- ..._eth_soc-add-NETSYS_V3-version-suppo.patch | 307 --- ..._eth_soc-convert-caps-in-mtk_soc_dat.patch | 193 -- ..._eth_soc-convert-clock-bitmap-to-u64.patch | 132 - ..._eth_soc-add-basic-support-for-MT798.patch | 477 ---- ..._eth_soc-enable-page_pool-support-fo.patch | 27 - ..._eth_soc-enable-nft-hw-flowtable_off.patch | 135 - ..._eth_soc-support-per-flow-accounting.patch | 78 - ..._eth_soc-fix-NULL-pointer-on-hw-rese.patch | 52 - ..._eth_soc-fix-register-definitions-fo.patch | 44 - ...tk_eth_soc-add-reset-bits-for-MT7988.patch | 188 -- ..._eth_soc-add-support-for-in-SoC-SRAM.patch | 254 -- ..._eth_soc-support-36-bit-DMA-addressi.patch | 166 -- ...k_eth_soc-fix-uninitialized-variable.patch | 44 - ..._eth_soc-fix-pse_port-configuration-.patch | 33 - ..._eth_soc-add-code-for-offloading-flo.patch | 271 -- ...iatek-mtk_ppe-prefer-newly-added-l2-.patch | 37 - ..._wed-add-some-more-info-in-wed_txinf.patch | 45 - ..._wed-minor-change-in-wed_-tx-rx-info.patch | 47 - ...ntroduce-single-mii-read-write-lo-hi.patch | 150 - ...prove-mdio-master-read-write-by-usin.patch | 73 - ...d-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch | 63 - ...a8k-convert-to-regmap-read-write-API.patch | 261 -- ...-enable-use_single_write-for-qca8xxx.patch | 78 - ...ke-learning-configurable-and-keep-of.patch | 146 - ...mit-user-ports-access-to-the-first-C.patch | 53 - ...ve-qca8xxx-hol-fixup-to-separate-fun.patch | 111 - ...e-dsa_for_each-macro-instead-of-for-.patch | 158 -- ...x-regmap-bulk-read-write-methods-on-.patch | 61 - ...t-dsa-mt7530-use-external-PCS-driver.patch | 514 ---- ...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 | 54 - ...t7530-introduce-separate-MDIO-driver.patch | 691 ----- ...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 | 1724 ------------ ...fix-yt8521-duplicated-argument-to-or.patch | 49 - ...net-phy-add-Motorcomm-YT8531S-phy-id.patch | 140 - ...fix-the-spelling-problem-of-Sentinel.patch | 26 - ...nge-the-phy-id-of-yt8521-and-yt8531s.patch | 29 - ...-for-Motorcomm-yt8521-yt8531-gigabit.patch | 107 - ...support-for-Motorcomm-yt8521-gigabit.patch | 343 --- ...upport-for-Motorcomm-yt8531s-gigabit.patch | 100 - ...or-Motorcomm-yt8531-gigabit-ethernet.patch | 302 -- ...motorcomm-uninitialized-variables-in.patch | 34 - ...m-Add-pad-drive-strength-cfg-support.patch | 170 -- ...k-add-pcs_enable-pcs_disable-methods.patch | 173 -- ...t-pcs-lynxi-implement-pcs_disable-op.patch | 44 - ...ive-renaming-when-an-interface-is-up.patch | 136 - ...-need-to-blacklist-any-r8152-devices.patch | 158 -- ...-control-transfer-of-rtl8152_get_ver.patch | 46 - ...-Add-__GFP_NOWARN-to-big-allocations.patch | 55 - ...52-adjust-generic_ocp_write-function.patch | 70 - .../795-v6.6-09-r8152-set-bp-in-bulk.patch | 129 - ...eth-r8152-try-to-use-a-normal-budget.patch | 39 - ...re-register-access-if-register-acces.patch | 398 --- ...he-loop-when-the-budget-is-exhausted.patch | 83 - ..._ether-add-u-blox-0x1313-composition.patch | 47 - ...it_default_state_get-to-the-global-h.patch | 39 - ...a8k-move-qca8k_port_to_phy-to-header.patch | 67 - ...net-dsa-qca8k-add-LEDs-basic-support.patch | 435 --- ...dsa-qca8k-add-LEDs-blink_set-support.patch | 74 - ...bs-for-when-CLASS_LED-NEW_LEDS-are-d.patch | 59 - ...5-net-phy-Add-a-binding-for-PHY-LEDs.patch | 191 -- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 97 - ...ell-Add-software-control-of-the-LEDs.patch | 112 - ...ce-Call-into-the-PHY-driver-to-set-L.patch | 73 - ...-phy-marvell-Implement-led_blink_set.patch | 104 - ...Fix-inconsistent-indenting-in-led_bl.patch | 38 - ...dev-Drop-NETDEV_LED_MODE_LINKUP-from.patch | 87 - ...dev-Rename-add-namespace-to-netdev-t.patch | 149 - ...-netdev-Convert-device-attr-to-macro.patch | 82 - ...etdev-Use-mutex-instead-of-spinlocks.patch | 106 - ...01-leds-add-APIs-for-LEDs-hw-control.patch | 74 - ...get-attached-device-for-LED-hw-contr.patch | 37 - ...ds-leds-class-Document-new-Hardware-.patch | 113 - ...dev-refactor-code-setting-device-nam.patch | 69 - ...dev-introduce-check-for-possible-hw-.patch | 54 - ...dev-add-basic-check-for-hw-control-s.patch | 42 - ...dev-reject-interval-store-for-hw_con.patch | 28 - ...etdev-add-support-for-LED-hw-control.patch | 107 - ...er-netdev-validate-configured-netdev.patch | 58 - ...dev-init-mode-if-hw-control-already-.patch | 53 - ...dev-expose-netdev-trigger-modes-in-l.patch | 54 - ...t-dsa-qca8k-implement-hw_control-ops.patch | 200 -- ...dsa-qca8k-add-op-to-get-ports-netdev.patch | 70 - ...dev-add-additional-specific-link-spe.patch | 242 -- ...dev-add-additional-specific-link-dup.patch | 138 - ...dev-expose-hw_control-status-via-sys.patch | 45 - ...d-support-for-additional-modes-for-n.patch | 64 - ...x-pass-directly-chip-structure-to-mv.patch | 64 - ...x-use-mv88e6xxx_phy_is_internal-in-m.patch | 31 - ...x-add-field-to-specify-internal-phys.patch | 69 - ...x-fix-88E6393X-family-internal-phys-.patch | 52 - ...x-pass-mv88e6xxx_chip-structure-to-p.patch | 110 - ...xx-enable-support-for-88E6361-switch.patch | 153 - ...e-STM32MP15_BSEC_NUM_LOWER-in-config.patch | 82 - ...-warning-when-upper-OTPs-are-updated.patch | 34 - ...nvmem-stm32-add-nvmem-type-attribute.patch | 26 - ...m-stm32-fix-spelling-typo-in-comment.patch | 27 - ...x-spelling-mistake-controlls-control.patch | 27 - ...boot-env-add-Broadcom-format-support.patch | 67 - ...mem-core-remove-spurious-white-space.patch | 26 - ...e-add-an-index-parameter-to-the-cell.patch | 180 -- ...struct-nvmem_cell_info-to-nvmem-prov.patch | 78 - ...the-removal-of-the-cells-in-nvmem_ad.patch | 65 - ...05-nvmem-core-add-nvmem_add_one_cell.patch | 122 - ...vmem_add_one_cell-in-nvmem_add_cells.patch | 93 - ...32-add-OP-TEE-support-for-STM32MP13x.patch | 562 ---- ...ect-bsec-pta-presence-for-STM32MP15x.patch | 85 - ...eprm-fix-kernel-doc-bad-line-warning.patch | 32 - ...mi-sdam-register-at-device-init-time.patch | 43 - ...011-nvmem-stm32-fix-OPTEE-dependency.patch | 46 - ...ount-to-list.h-as-list_count_nodes-f.patch | 75 - ...001-nvmem-xilinx-zynqmp-make-modular.patch | 35 - ...2-nvmem-core-introduce-NVMEM-layouts.patch | 387 --- ...ndle-the-absence-of-expected-layouts.patch | 61 - ...-core-request-layout-modules-loading.patch | 52 - ...em-core-add-per-cell-post-processing.patch | 86 - ...ow-to-modify-a-cell-before-adding-it.patch | 59 - ...replace-global-post-processing-with-.patch | 81 - ...m-cell-drop-global-cell_post_process.patch | 68 - ...de-own-priv-pointer-in-post-process-.patch | 76 - ...ayouts-sl28vpd-Add-new-layout-driver.patch | 215 -- ...youts-onie-tlv-Add-new-layout-driver.patch | 306 -- ...m-mark-OF-related-data-as-maybe-unus.patch | 32 - ...Support-postprocessing-for-GPU-speed.patch | 120 - ...p-Use-devm_platform_ioremap_resource.patch | 39 - ...tp-Use-devm_platform_ioremap_resourc.patch | 39 - ...p-Use-devm_platform_get_and_ioremap_.patch | 32 - ...rt-specifying-both-cell-raw-data-pos.patch | 115 - ...nv-post-process-ethaddr-env-variable.patch | 81 - ...cro-to-register-nvmem-layout-drivers.patch | 42 - ...28vpd-Use-module_nvmem_layout_driver.patch | 39 - ...ie-tlv-Use-module_nvmem_layout_drive.patch | 39 - ...uts-onie-tlv-Drop-wrong-module-alias.patch | 24 - ...28vpd-set-varaiable-sl28vpd_layout-s.patch | 31 - ...-bcm47xx-support-init-from-IO-memory.patch | 100 - ...set-varaiable-imx_ocotp_layout-stora.patch | 31 - ...Reverse-MAC-addresses-on-all-i.MX-de.patch | 71 - ...vram-add-.read_post_process-for-MACs.patch | 81 - ...tp-Add-clks-and-reg_read-to-rockchip.patch | 166 -- ...tp-Generalize-rockchip_otp_wait_stat.patch | 62 - ...tp-Use-devm_reset_control_array_get_.patch | 31 - ...hip-otp-Improve-probe-error-handling.patch | 71 - ...-rockchip-otp-Add-support-for-RK3588.patch | 129 - ...-Switch-xilinx.com-emails-to-amd.com.patch | 26 - ...-0010-nvmem-imx-support-i.MX93-OCOTP.patch | 230 -- ...e-add-support-for-fixed-cells-layout.patch | 96 - ...Convert-to-devm_platform_ioremap_res.patch | 36 - ...-Use-devm_platform_get_and_ioremap_r.patch | 30 - ...p-Convert-to-devm_platform_ioremap_r.patch | 34 - ...fuse-Convert-to-devm_platform_iorema.patch | 36 - ...fuse-Use-devm_platform_get_and_iorem.patch | 31 - ...m-Use-devm_platform_get_and_ioremap_.patch | 30 - ....6-0007-nvmem-qfprom-do-some-cleanup.patch | 59 - ...se-devm_platform_get_and_ioremap_res.patch | 29 - ...nvmem-add-new-NXP-QorIQ-eFuse-driver.patch | 133 - ...-nvmem-Kconfig-Fix-typo-drive-driver.patch | 37 - ...m-Add-Qualcomm-secure-QFPROM-support.patch | 152 - ...-Replace-zero-length-array-with-DECL.patch | 30 - ...e-all-cells-before-adding-the-nvmem-.patch | 40 - ...n-NULL-when-no-nvmem-layout-is-found.patch | 35 - ...-Do-not-open-code-existing-functions.patch | 29 - ...tify-when-a-new-layout-is-registered.patch | 44 - ...ia-Use-sysfs_emit-instead-of-sprintf.patch | 29 - ...ect-fixed-layouts-to-grab-a-layout-d.patch | 45 - ..._nvram-store-a-copy-of-NVRAM-content.patch | 261 -- ...fix-circular-LEDS_CLASS-dependencies.patch | 65 - ...net-phy-Fix-reading-LED-reg-property.patch | 43 - ...emove-LEDs-to-ensure-correct-orderin.patch | 67 - ...dev-Remove-NULL-check-before-dev_-pu.patch | 44 - ...dev-uninitialized-variable-in-netdev.patch | 31 - ...netdev-Fix-requesting-offload-device.patch | 57 - ...ce-Call-into-the-PHY-driver-to-set-L.patch | 149 - ...Add-support-for-offloading-LED-blink.patch | 344 --- ...-Disable-offload-on-deactivation-of-.patch | 31 - ...-of_parse_phandle_with_optional_args.patch | 58 - ...ke-.-cells-optional-for-simple-props.patch | 34 - ...operty-add-nvmem-cell-cells-property.patch | 30 - ...vice-Ignore-modalias-of-reused-nodes.patch | 37 - ...-ignore-error-code-in-of_device_ueve.patch | 29 - ...002-of-Update-of_device_get_modalias.patch | 103 - ...v6.4-0003-of-Rename-of_modalias_node.patch | 173 -- ...0004-of-Move-of_modalias-to-module.c.patch | 160 -- ...uest-module-helper-logic-to-module.c.patch | 131 - ...qcom-document-qcom-msm-id-and-qcom-b.patch | 207 -- ...-move-SMEM-item-struct-and-defines-t.patch | 171 -- ...com-smem-Switch-to-EXPORT_SYMBOL_GPL.patch | 55 - ...-smem-introduce-qcom_smem_get_soc_id.patch | 70 - ...com-nvmem-use-SoC-ID-s-from-bindings.patch | 51 - ...-nvmem-use-helper-to-get-SMEM-SoC-ID.patch | 109 - ...dev-fix-RTNL-handling-to-prevent-pot.patch | 170 -- ....4-net-phy-hide-the-PHYLIB_LEDS-knob.patch | 43 - ...-spinand-winbond-fix-flash-detection.patch | 40 - ...6.2-mtd-spinand-winbond-add-W25N02KV.patch | 106 - ...d-spinand-winbond-Fix-ecc_get_status.patch | 49 - 339 files changed, 44789 deletions(-) delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch delete mode 100644 target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch delete mode 100644 target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch delete mode 100644 target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch delete mode 100644 target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch delete mode 100644 target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch delete mode 100644 target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch delete mode 100644 target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch delete mode 100644 target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch delete mode 100644 target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch delete mode 100644 target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch delete mode 100644 target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch delete mode 100644 target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch delete mode 100644 target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch delete mode 100644 target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch delete mode 100644 target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch delete mode 100644 target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch delete mode 100644 target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch delete mode 100644 target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch delete mode 100644 target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch delete mode 100644 target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch delete mode 100644 target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch delete mode 100644 target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch delete mode 100644 target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch delete mode 100644 target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch delete mode 100644 target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch delete mode 100644 target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch delete mode 100644 target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch delete mode 100644 target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch delete mode 100644 target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch delete mode 100644 target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch delete mode 100644 target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch delete mode 100644 target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch delete mode 100644 target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch delete mode 100644 target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch delete mode 100644 target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch delete mode 100644 target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch delete mode 100644 target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch delete mode 100644 target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch delete mode 100644 target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch delete mode 100644 target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch delete mode 100644 target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch delete mode 100644 target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch delete mode 100644 target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch delete mode 100644 target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch delete mode 100644 target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch delete mode 100644 target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch delete mode 100644 target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch delete mode 100644 target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch delete mode 100644 target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch delete mode 100644 target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch delete mode 100644 target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch delete mode 100644 target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch delete mode 100644 target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch delete mode 100644 target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch delete mode 100644 target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch delete mode 100644 target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch delete mode 100644 target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch delete mode 100644 target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch delete mode 100644 target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch delete mode 100644 target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch delete mode 100644 target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch delete mode 100644 target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch delete mode 100644 target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch delete mode 100644 target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch delete mode 100644 target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch delete mode 100644 target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch delete mode 100644 target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch delete mode 100644 target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch delete mode 100644 target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch delete mode 100644 target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch delete mode 100644 target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch delete mode 100644 target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch delete mode 100644 target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch delete mode 100644 target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch delete mode 100644 target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch delete mode 100644 target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch delete mode 100644 target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch delete mode 100644 target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch delete mode 100644 target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch delete mode 100644 target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch delete mode 100644 target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch delete mode 100644 target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch delete mode 100644 target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch delete mode 100644 target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch delete mode 100644 target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch delete mode 100644 target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch delete mode 100644 target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch delete mode 100644 target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch delete mode 100644 target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch delete mode 100644 target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch delete mode 100644 target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch delete mode 100644 target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch delete mode 100644 target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch delete mode 100644 target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch delete mode 100644 target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch delete mode 100644 target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch delete mode 100644 target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch delete mode 100644 target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch delete mode 100644 target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch delete mode 100644 target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch delete mode 100644 target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch delete mode 100644 target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch delete mode 100644 target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch delete mode 100644 target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch delete mode 100644 target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch delete mode 100644 target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch delete mode 100644 target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch delete mode 100644 target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch delete mode 100644 target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch delete mode 100644 target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch delete mode 100644 target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch delete mode 100644 target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch delete mode 100644 target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch delete mode 100644 target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch delete mode 100644 target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch delete mode 100644 target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch delete mode 100644 target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch delete mode 100644 target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch delete mode 100644 target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch delete mode 100644 target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch delete mode 100644 target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch delete mode 100644 target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch delete mode 100644 target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch delete mode 100644 target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch delete mode 100644 target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch delete mode 100644 target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch delete mode 100644 target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch delete mode 100644 target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch delete mode 100644 target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch delete mode 100644 target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch delete mode 100644 target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch delete mode 100644 target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch delete mode 100644 target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch delete mode 100644 target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch delete mode 100644 target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch delete mode 100644 target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch delete mode 100644 target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch delete mode 100644 target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch delete mode 100644 target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch delete mode 100644 target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch delete mode 100644 target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch delete mode 100644 target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch delete mode 100644 target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch delete mode 100644 target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch delete mode 100644 target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch delete mode 100644 target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch delete mode 100644 target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch delete mode 100644 target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch delete mode 100644 target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch delete mode 100644 target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch delete mode 100644 target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch delete mode 100644 target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch delete mode 100644 target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch delete mode 100644 target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch delete mode 100644 target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch delete mode 100644 target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch delete mode 100644 target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch delete mode 100644 target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch diff --git a/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch b/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch deleted file mode 100644 index fe32acc985..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch +++ /dev/null @@ -1,352 +0,0 @@ -From 8c20e2eb5f2a0175b774134685e4d7bd93e85ff8 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:18:59 -0700 -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. - -Overview -======== - -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 reclaim is currently out of scope. - -Its memory bloat is a pointer to each lruvec and negligible to each -pglist_data. 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 in contrast to the current linear complexity. - -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. - -The commit message in patch 6 details the workflow: -https://lore.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com/ - -The following is a simple test to quickly verify its effectiveness. - - Test design: - 1. Create multiple memcgs. - 2. Each memcg contains a job (fio). - 3. All jobs access the same amount of memory randomly. - 4. The system does not experience global memory pressure. - 5. Periodically write to the root memory.reclaim. - - Desired outcome: - 1. All memcgs have similar pgsteal counts, i.e., stddev(pgsteal) - over mean(pgsteal) is close to 0%. - 2. The total pgsteal is close to the total requested through - memory.reclaim, i.e., sum(pgsteal) over sum(requested) is close - to 100%. - - Actual outcome [1]: - MGLRU off MGLRU on - stddev(pgsteal) / mean(pgsteal) 75% 20% - sum(pgsteal) / sum(requested) 425% 95% - - #################################################################### - MEMCGS=128 - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - mkdir /sys/fs/cgroup/memcg$memcg - done - - start() { - echo $BASHPID > /sys/fs/cgroup/memcg$memcg/cgroup.procs - - fio -name=memcg$memcg --numjobs=1 --ioengine=mmap \ - --filename=/dev/zero --size=1920M --rw=randrw \ - --rate=64m,64m --random_distribution=random \ - --fadvise_hint=0 --time_based --runtime=10h \ - --group_reporting --minimal - } - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - start & - done - - sleep 600 - - for ((i = 0; i < 600; i++)); do - echo 256m >/sys/fs/cgroup/memory.reclaim - sleep 6 - done - - for ((memcg = 0; memcg < $MEMCGS; memcg++)); do - grep "pgsteal " /sys/fs/cgroup/memcg$memcg/memory.stat - done - #################################################################### - -[1]: This was obtained from running the above script (touches less - than 256GB memory) on an EPYC 7B13 with 512GB DRAM for over an - hour. - -This patch (of 8): - -The new name lru_gen_folio will be more distinct from the coming -lru_gen_memcg. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-1-yuzhao@google.com -Link: https://lkml.kernel.org/r/20221222041905.2431096-2-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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 +++--- - mm/vmscan.c | 34 +++++++++++++++++----------------- - mm/workingset.c | 4 ++-- - 4 files changed, 24 insertions(+), 24 deletions(-) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(s - int zone = folio_zonenum(folio); - int delta = folio_nr_pages(folio); - enum lru_list lru = type * LRU_INACTIVE_FILE; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - 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 - int gen = folio_lru_gen(folio); - int type = folio_is_file_lru(folio); - int zone = folio_zonenum(folio); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_FOLIO(gen != -1, folio); - ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -404,7 +404,7 @@ enum { - * The number of pages in each generation is eventually consistent and therefore - * can be transiently negative when reset_batch_size() is pending. - */ --struct lru_gen_struct { -+struct lru_gen_folio { - /* the aging increments the youngest generation number */ - unsigned long max_seq; - /* the eviction increments the oldest generation numbers */ -@@ -461,7 +461,7 @@ struct lru_gen_mm_state { - struct lru_gen_mm_walk { - /* the lruvec under reclaim */ - struct lruvec *lruvec; -- /* unstable max_seq from lru_gen_struct */ -+ /* unstable max_seq from lru_gen_folio */ - unsigned long max_seq; - /* the next address within an mm to scan */ - unsigned long next_addr; -@@ -524,7 +524,7 @@ struct lruvec { - unsigned long flags; - #ifdef CONFIG_LRU_GEN - /* evictable pages divided into generations */ -- struct lru_gen_struct lrugen; -+ struct lru_gen_folio lrugen; - /* to concurrently iterate lru_gen_mm_list */ - struct lru_gen_mm_state mm_state; - #endif ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lr - - static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) - { -- /* see the comment on lru_gen_struct */ -+ /* see the comment on lru_gen_folio */ - return get_nr_gens(lruvec, LRU_GEN_FILE) >= MIN_NR_GENS && - get_nr_gens(lruvec, LRU_GEN_FILE) <= get_nr_gens(lruvec, LRU_GEN_ANON) && - get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; -@@ -3596,7 +3596,7 @@ struct ctrl_pos { - static void read_ctrl_pos(struct lruvec *lruvec, int type, int tier, int gain, - struct ctrl_pos *pos) - { -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - 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 - static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) - { - int hist, tier; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - 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 - static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclaiming) - { - int type = folio_is_file_lru(folio); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - 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 - static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) - { - int gen, type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - walk->batched = 0; - -@@ -4250,7 +4250,7 @@ static bool inc_min_seq(struct lruvec *l - { - int zone; - int remaining = MAX_LRU_BATCH; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); - - if (type == LRU_GEN_ANON && !can_swap) -@@ -4286,7 +4286,7 @@ static bool try_to_inc_min_seq(struct lr - { - int gen, type, zone; - bool success = false; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - DEFINE_MIN_SEQ(lruvec); - - VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); -@@ -4307,7 +4307,7 @@ next: - ; - } - -- /* see the comment on lru_gen_struct */ -+ /* see the comment on lru_gen_folio */ - 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]); -@@ -4329,7 +4329,7 @@ static void inc_max_seq(struct lruvec *l - { - int prev, next; - int type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - restart: - spin_lock_irq(&lruvec->lru_lock); -@@ -4389,7 +4389,7 @@ static bool try_to_inc_max_seq(struct lr - bool success; - struct lru_gen_mm_walk *walk; - struct mm_struct *mm = NULL; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); - -@@ -4454,7 +4454,7 @@ static bool should_run_aging(struct lruv - unsigned long old = 0; - unsigned long young = 0; - unsigned long total = 0; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - 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 - int delta = folio_nr_pages(folio); - int refs = folio_lru_refs(folio); - int tier = lru_tier_from_refs(refs); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio); - -@@ -4848,7 +4848,7 @@ static int scan_folios(struct lruvec *lr - int scanned = 0; - int isolated = 0; - int remaining = MAX_LRU_BATCH; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - VM_WARN_ON_ONCE(!list_empty(list)); -@@ -5249,7 +5249,7 @@ done: - - static bool __maybe_unused state_is_valid(struct lruvec *lruvec) - { -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - if (lrugen->enabled) { - enum lru_list lru; -@@ -5531,7 +5531,7 @@ static void lru_gen_seq_show_full(struct - int i; - int type, tier; - int hist = lru_hist_from_seq(seq); -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - for (tier = 0; tier < MAX_NR_TIERS; tier++) { - seq_printf(m, " %10d", tier); -@@ -5581,7 +5581,7 @@ static int lru_gen_seq_show(struct seq_f - unsigned long seq; - bool full = !debugfs_real_fops(m->file)->write; - struct lruvec *lruvec = v; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - int nid = lruvec_pgdat(lruvec)->node_id; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); -@@ -5835,7 +5835,7 @@ void lru_gen_init_lruvec(struct lruvec * - { - int i; - int gen, type, zone; -- struct lru_gen_struct *lrugen = &lruvec->lrugen; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - - lrugen->max_seq = MIN_NR_GENS + 1; - lrugen->enabled = lru_gen_enabled(); ---- a/mm/workingset.c -+++ b/mm/workingset.c -@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct fol - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; -- struct lru_gen_struct *lrugen; -+ struct lru_gen_folio *lrugen; - 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 - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; -- struct lru_gen_struct *lrugen; -+ struct lru_gen_folio *lrugen; - struct mem_cgroup *memcg; - struct pglist_data *pgdat; - int type = folio_is_file_lru(folio); diff --git a/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch b/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch deleted file mode 100644 index e5ad78b61d..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch +++ /dev/null @@ -1,192 +0,0 @@ -From 14f9a7a15f3d1af351f30e0438fd747b7ac253b0 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:01 -0700 -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 -reclaims the rest; then it increments lrugen->min_seq. - -The current eviction fairness safeguard for global reclaim has a -dilemma: when there are multiple eligible memcgs, should it continue -or stop upon meeting the reclaim goal? If it continues, it overshoots -and increases direct reclaim latency; if it stops, it loses fairness -between memcgs it has taken memory away from and those it has yet to. - -With memcg LRU, the eviction, while ensuring eventual fairness, will -stop upon meeting its goal. Therefore the current eviction fairness -safeguard for global reclaim will not be needed. - -Note that memcg LRU only applies to global reclaim. For memcg reclaim, -the eviction will continue, even if it is overshooting. This becomes -unconditional due to code simplification. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-4-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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 | 81 +++++++++++++++-------------------------------------- - 1 file changed, 23 insertions(+), 58 deletions(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_c - return sc->target_mem_cgroup; - } - -+static bool global_reclaim(struct scan_control *sc) -+{ -+ return !sc->target_mem_cgroup || mem_cgroup_is_root(sc->target_mem_cgroup); -+} -+ - /** - * 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 - return false; - } - -+static bool global_reclaim(struct scan_control *sc) -+{ -+ return true; -+} -+ - static bool writeback_throttling_sane(struct scan_control *sc) - { - return true; -@@ -5005,8 +5015,7 @@ static int isolate_folios(struct lruvec - return scanned; - } - --static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness, -- bool *need_swapping) -+static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness) - { - int type; - int scanned; -@@ -5095,9 +5104,6 @@ retry: - goto retry; - } - -- if (need_swapping && type == LRU_GEN_ANON) -- *need_swapping = true; -- - return scanned; - } - -@@ -5136,67 +5142,26 @@ done: - return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; - } - --static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq, -- struct scan_control *sc, bool need_swapping) -+static unsigned long get_nr_to_reclaim(struct scan_control *sc) - { -- int i; -- DEFINE_MAX_SEQ(lruvec); -- -- if (!current_is_kswapd()) { -- /* age each memcg at most once to ensure fairness */ -- if (max_seq - seq > 1) -- return true; -- -- /* over-swapping can increase allocation latency */ -- if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping) -- return true; -- -- /* give this thread a chance to exit and free its memory */ -- if (fatal_signal_pending(current)) { -- sc->nr_reclaimed += MIN_LRU_BATCH; -- return true; -- } -- -- if (cgroup_reclaim(sc)) -- return false; -- } else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim) -- return false; -- -- /* keep scanning at low priorities to ensure fairness */ -- if (sc->priority > DEF_PRIORITY - 2) -- return false; -- -- /* -- * A minimum amount of work was done under global memory pressure. For -- * kswapd, it may be overshooting. For direct reclaim, the allocation -- * may succeed if all suitable zones are somewhat safe. In either case, -- * it's better to stop now, and restart later if necessary. -- */ -- for (i = 0; i <= sc->reclaim_idx; i++) { -- unsigned long wmark; -- struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i; -- -- if (!managed_zone(zone)) -- continue; -- -- wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone); -- if (wmark > zone_page_state(zone, NR_FREE_PAGES)) -- return false; -- } -+ /* don't abort memcg reclaim to ensure fairness */ -+ if (!global_reclaim(sc)) -+ return -1; - -- sc->nr_reclaimed += MIN_LRU_BATCH; -+ /* discount the previous progress for kswapd */ -+ if (current_is_kswapd()) -+ return sc->nr_to_reclaim + sc->last_reclaimed; - -- return true; -+ return max(sc->nr_to_reclaim, compact_gap(sc->order)); - } - - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { - struct blk_plug plug; - bool need_aging = false; -- bool need_swapping = false; - unsigned long scanned = 0; - unsigned long reclaimed = sc->nr_reclaimed; -- DEFINE_MAX_SEQ(lruvec); -+ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - lru_add_drain(); - -@@ -5220,7 +5185,7 @@ static void lru_gen_shrink_lruvec(struct - if (!nr_to_scan) - goto done; - -- delta = evict_folios(lruvec, sc, swappiness, &need_swapping); -+ delta = evict_folios(lruvec, sc, swappiness); - if (!delta) - goto done; - -@@ -5228,7 +5193,7 @@ static void lru_gen_shrink_lruvec(struct - if (scanned >= nr_to_scan) - break; - -- if (should_abort_scan(lruvec, max_seq, sc, need_swapping)) -+ if (sc->nr_reclaimed >= nr_to_reclaim) - break; - - cond_resched(); -@@ -5678,7 +5643,7 @@ static int run_eviction(struct lruvec *l - if (sc->nr_reclaimed >= nr_to_reclaim) - return 0; - -- if (!evict_folios(lruvec, sc, swappiness, NULL)) -+ if (!evict_folios(lruvec, sc, swappiness)) - return 0; - - cond_resched(); diff --git a/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch b/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch deleted file mode 100644 index cb349abcdb..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch +++ /dev/null @@ -1,294 +0,0 @@ -From f3c93d2e37a3c56593d7ccf4f4bcf1b58426fdd8 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:02 -0700 -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 -lrugen->max_seq. - -The current aging fairness safeguard for kswapd uses two passes to -ensure the fairness to multiple eligible memcgs. On the first pass, -which is shared with the eviction, it checks whether all eligible -memcgs are low on cold folios. If so, it requires a second pass, on -which it ages all those memcgs at the same time. - -With memcg LRU, the aging, while ensuring eventual fairness, will run -when necessary. Therefore the current aging fairness safeguard for -kswapd will not be needed. - -Note that memcg LRU only applies to global reclaim. For memcg reclaim, -the aging can be unfair to different memcgs, i.e., their -lrugen->max_seq can be incremented at different paces. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-5-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -136,7 +136,6 @@ struct scan_control { - - #ifdef CONFIG_LRU_GEN - /* help kswapd make better choices among multiple memcgs */ -- unsigned int memcgs_need_aging:1; - unsigned long last_reclaimed; - #endif - -@@ -4457,7 +4456,7 @@ done: - return true; - } - --static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, -+static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, - struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) - { - int gen, type, zone; -@@ -4466,6 +4465,13 @@ static bool should_run_aging(struct lruv - unsigned long total = 0; - struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); -+ -+ /* whether this lruvec is completely out of cold folios */ -+ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -+ *nr_to_scan = 0; -+ return true; -+ } - - for (type = !can_swap; type < ANON_AND_FILE; type++) { - unsigned long seq; -@@ -4494,8 +4500,6 @@ static bool should_run_aging(struct lruv - * stalls when the number of generations reaches MIN_NR_GENS. Hence, the - * ideal number of generations is MIN_NR_GENS+1. - */ -- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) -- return true; - if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) - return false; - -@@ -4514,40 +4518,54 @@ static bool should_run_aging(struct lruv - return false; - } - --static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned long min_ttl) -+static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { -- bool need_aging; -- unsigned long nr_to_scan; -- int swappiness = get_swappiness(lruvec, sc); -+ int gen, type, zone; -+ unsigned long total = 0; -+ bool can_swap = get_swappiness(lruvec, sc); -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - -- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); -+ for (type = !can_swap; type < ANON_AND_FILE; type++) { -+ unsigned long seq; - -- mem_cgroup_calculate_protection(NULL, memcg); -+ for (seq = min_seq[type]; seq <= max_seq; seq++) { -+ gen = lru_gen_from_seq(seq); - -- if (mem_cgroup_below_min(memcg)) -- return false; -+ for (zone = 0; zone < MAX_NR_ZONES; zone++) -+ total += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -+ } -+ } - -- need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); -+ /* whether the size is big enough to be helpful */ -+ return mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -+} - -- if (min_ttl) { -- int gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); -- unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); -+static bool lruvec_is_reclaimable(struct lruvec *lruvec, struct scan_control *sc, -+ unsigned long min_ttl) -+{ -+ int gen; -+ unsigned long birth; -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); - -- if (time_is_after_jiffies(birth + min_ttl)) -- return false; -+ VM_WARN_ON_ONCE(sc->memcg_low_reclaim); - -- /* the size is likely too small to be helpful */ -- if (!nr_to_scan && sc->priority != DEF_PRIORITY) -- return false; -- } -+ /* see the comment on lru_gen_folio */ -+ gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); -+ birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); - -- if (need_aging) -- try_to_inc_max_seq(lruvec, max_seq, sc, swappiness, false); -+ if (time_is_after_jiffies(birth + min_ttl)) -+ return false; - -- return true; -+ if (!lruvec_is_sizable(lruvec, sc)) -+ return false; -+ -+ mem_cgroup_calculate_protection(NULL, memcg); -+ -+ return !mem_cgroup_below_min(memcg); - } - - /* to protect the working set of the last N jiffies */ -@@ -4556,46 +4574,32 @@ static unsigned long lru_gen_min_ttl __r - static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) - { - struct mem_cgroup *memcg; -- bool success = false; - unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); - - VM_WARN_ON_ONCE(!current_is_kswapd()); - - sc->last_reclaimed = sc->nr_reclaimed; - -- /* -- * To reduce the chance of going into the aging path, which can be -- * costly, optimistically skip it if the flag below was cleared in the -- * eviction path. This improves the overall performance when multiple -- * memcgs are available. -- */ -- if (!sc->memcgs_need_aging) { -- sc->memcgs_need_aging = true; -+ /* check the order to exclude compaction-induced reclaim */ -+ if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) - return; -- } -- -- set_mm_walk(pgdat); - - memcg = mem_cgroup_iter(NULL, NULL, NULL); - do { - struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); - -- if (age_lruvec(lruvec, sc, min_ttl)) -- success = true; -+ if (lruvec_is_reclaimable(lruvec, sc, min_ttl)) { -+ mem_cgroup_iter_break(NULL, memcg); -+ return; -+ } - - cond_resched(); - } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); - -- clear_mm_walk(); -- -- /* check the order to exclude compaction-induced reclaim */ -- if (success || !min_ttl || sc->order) -- return; -- - /* - * The main goal is to OOM kill if every generation from all memcgs is - * younger than min_ttl. However, another possibility is all memcgs are -- * either below min or empty. -+ * either too small or below min. - */ - if (mutex_trylock(&oom_lock)) { - struct oom_control oc = { -@@ -5113,33 +5117,27 @@ retry: - * reclaim. - */ - static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, -- bool can_swap, bool *need_aging) -+ bool can_swap) - { - unsigned long nr_to_scan; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); -- DEFINE_MIN_SEQ(lruvec); - - if (mem_cgroup_below_min(memcg) || - (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) - return 0; - -- *need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); -- if (!*need_aging) -+ if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) - return nr_to_scan; - - /* skip the aging path at the default priority */ - if (sc->priority == DEF_PRIORITY) -- goto done; -+ return nr_to_scan; - -- /* leave the work to lru_gen_age_node() */ -- if (current_is_kswapd()) -- return 0; -+ try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); - -- if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false)) -- return nr_to_scan; --done: -- return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; -+ /* skip this lruvec as it's low on cold folios */ -+ return 0; - } - - static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5158,9 +5156,7 @@ static unsigned long get_nr_to_reclaim(s - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { - struct blk_plug plug; -- bool need_aging = false; - unsigned long scanned = 0; -- unsigned long reclaimed = sc->nr_reclaimed; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - lru_add_drain(); -@@ -5181,13 +5177,13 @@ static void lru_gen_shrink_lruvec(struct - else - swappiness = 0; - -- nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness, &need_aging); -+ nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); - if (!nr_to_scan) -- goto done; -+ break; - - delta = evict_folios(lruvec, sc, swappiness); - if (!delta) -- goto done; -+ break; - - scanned += delta; - if (scanned >= nr_to_scan) -@@ -5199,10 +5195,6 @@ static void lru_gen_shrink_lruvec(struct - cond_resched(); - } - -- /* see the comment in lru_gen_age_node() */ -- if (sc->nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging) -- sc->memcgs_need_aging = false; --done: - clear_mm_walk(); - - blk_finish_plug(&plug); diff --git a/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch b/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch deleted file mode 100644 index 42caab7c37..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch +++ /dev/null @@ -1,166 +0,0 @@ -From eca3858631e0cbad2ca6e40f788892749428e4cb Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:03 -0700 -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 -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4456,68 +4456,6 @@ done: - return true; - } - --static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, -- struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) --{ -- int gen, type, zone; -- unsigned long old = 0; -- unsigned long young = 0; -- unsigned long total = 0; -- struct lru_gen_folio *lrugen = &lruvec->lrugen; -- struct mem_cgroup *memcg = lruvec_memcg(lruvec); -- DEFINE_MIN_SEQ(lruvec); -- -- /* whether this lruvec is completely out of cold folios */ -- if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -- *nr_to_scan = 0; -- return true; -- } -- -- for (type = !can_swap; type < ANON_AND_FILE; type++) { -- unsigned long seq; -- -- for (seq = min_seq[type]; seq <= max_seq; seq++) { -- unsigned long size = 0; -- -- gen = lru_gen_from_seq(seq); -- -- for (zone = 0; zone < MAX_NR_ZONES; zone++) -- size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -- -- total += size; -- if (seq == max_seq) -- young += size; -- else if (seq + MIN_NR_GENS == max_seq) -- old += size; -- } -- } -- -- /* try to scrape all its memory if this memcg was deleted */ -- *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -- -- /* -- * The aging tries to be lazy to reduce the overhead, while the eviction -- * stalls when the number of generations reaches MIN_NR_GENS. Hence, the -- * ideal number of generations is MIN_NR_GENS+1. -- */ -- if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) -- return false; -- -- /* -- * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) -- * of the total number of pages for each generation. A reasonable range -- * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The -- * aging cares about the upper bound of hot pages, while the eviction -- * cares about the lower bound of cold pages. -- */ -- if (young * MIN_NR_GENS > total) -- return true; -- if (old * (MIN_NR_GENS + 2) < total) -- return true; -- -- return false; --} -- - static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { - int gen, type, zone; -@@ -5111,6 +5049,68 @@ retry: - return scanned; - } - -+static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, -+ struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) -+{ -+ int gen, type, zone; -+ unsigned long old = 0; -+ unsigned long young = 0; -+ unsigned long total = 0; -+ struct lru_gen_folio *lrugen = &lruvec->lrugen; -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ DEFINE_MIN_SEQ(lruvec); -+ -+ /* whether this lruvec is completely out of cold folios */ -+ if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) { -+ *nr_to_scan = 0; -+ return true; -+ } -+ -+ for (type = !can_swap; type < ANON_AND_FILE; type++) { -+ unsigned long seq; -+ -+ for (seq = min_seq[type]; seq <= max_seq; seq++) { -+ unsigned long size = 0; -+ -+ gen = lru_gen_from_seq(seq); -+ -+ for (zone = 0; zone < MAX_NR_ZONES; zone++) -+ size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); -+ -+ total += size; -+ if (seq == max_seq) -+ young += size; -+ else if (seq + MIN_NR_GENS == max_seq) -+ old += size; -+ } -+ } -+ -+ /* try to scrape all its memory if this memcg was deleted */ -+ *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; -+ -+ /* -+ * The aging tries to be lazy to reduce the overhead, while the eviction -+ * stalls when the number of generations reaches MIN_NR_GENS. Hence, the -+ * ideal number of generations is MIN_NR_GENS+1. -+ */ -+ if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) -+ return false; -+ -+ /* -+ * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) -+ * of the total number of pages for each generation. A reasonable range -+ * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The -+ * aging cares about the upper bound of hot pages, while the eviction -+ * cares about the lower bound of cold pages. -+ */ -+ if (young * MIN_NR_GENS > total) -+ return true; -+ if (old * (MIN_NR_GENS + 2) < total) -+ return true; -+ -+ return false; -+} -+ - /* - * For future optimizations: - * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg diff --git a/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch b/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch deleted file mode 100644 index 99ec42fe48..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch +++ /dev/null @@ -1,876 +0,0 @@ -From 8ee8571e47aa75221e5fbd4c9c7802fc4244c346 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:04 -0700 -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 -multiple bins to improve scalability. For each bin, an RCU hlist_nulls -is virtually divided into three segments: the head, the tail and the -default. - -An onlining memcg is added to the tail of a random bin in the old -generation. The eviction starts at the head of a random bin in the old -generation. The per-node memcg generation counter, whose reminder (mod -2) indexes the old generation, is incremented when all its bins become -empty. - -There are four operations: -1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in - its current generation (old or young) and updates its "seg" to - "head"; -2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in - its current generation (old or young) and updates its "seg" to - "tail"; -3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in - the old generation, updates its "gen" to "old" and resets its "seg" - to "default"; -4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin - in the young generation, updates its "gen" to "young" and resets - its "seg" to "default". - -The events that trigger the above operations are: -1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; -2. The first attempt to reclaim an memcg below low, which triggers - MEMCG_LRU_TAIL; -3. The first attempt to reclaim an memcg below reclaimable size - threshold, which triggers MEMCG_LRU_TAIL; -4. The second attempt to reclaim an memcg below reclaimable size - threshold, which triggers MEMCG_LRU_YOUNG; -5. Attempting to reclaim an memcg below min, which triggers - MEMCG_LRU_YOUNG; -6. Finishing the aging on the eviction path, which triggers - MEMCG_LRU_YOUNG; -7. Offlining an memcg, which triggers MEMCG_LRU_OLD. - -Note that memcg LRU only applies to global reclaim, and the -round-robin incrementing of their max_seq counters ensures the -eventual fairness to all eligible memcgs. For memcg reclaim, it still -relies on mem_cgroup_iter(). - -Link: https://lkml.kernel.org/r/20221222041905.2431096-7-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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/page_alloc.c | 1 + - mm/vmscan.c | 374 +++++++++++++++++++++++++++++++++---- - 6 files changed, 500 insertions(+), 35 deletions(-) - ---- a/include/linux/memcontrol.h -+++ b/include/linux/memcontrol.h -@@ -795,6 +795,11 @@ static inline void obj_cgroup_put(struct - percpu_ref_put(&objcg->refcnt); - } - -+static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) -+{ -+ return !memcg || css_tryget(&memcg->css); -+} -+ - static inline void mem_cgroup_put(struct mem_cgroup *memcg) - { - if (memcg) -@@ -1295,6 +1300,11 @@ static inline void obj_cgroup_put(struct - { - } - -+static inline bool mem_cgroup_tryget(struct mem_cgroup *memcg) -+{ -+ return true; -+} -+ - static inline void mem_cgroup_put(struct mem_cgroup *memcg) - { - } ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -122,6 +122,18 @@ 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; -@@ -302,6 +314,11 @@ 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; ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -7,6 +7,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -367,6 +368,15 @@ 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 { -@@ -426,6 +436,14 @@ struct lru_gen_folio { - atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; - /* whether the multi-gen LRU is enabled */ - bool enabled; -+#ifdef CONFIG_MEMCG -+ /* the memcg generation this lru_gen_folio belongs to */ -+ u8 gen; -+ /* the list segment this lru_gen_folio belongs to */ -+ u8 seg; -+ /* per-node lru_gen_folio list for global reclaim */ -+ struct hlist_nulls_node list; -+#endif - }; - - enum { -@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec * - void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); - - #ifdef CONFIG_MEMCG -+ -+/* -+ * For each node, memcgs are divided into two generations: the old and the -+ * young. For each generation, memcgs are randomly sharded into multiple bins -+ * to improve scalability. For each bin, the hlist_nulls is virtually divided -+ * into three segments: the head, the tail and the default. -+ * -+ * An onlining memcg is added to the tail of a random bin in the old generation. -+ * The eviction starts at the head of a random bin in the old generation. The -+ * per-node memcg generation counter, whose reminder (mod MEMCG_NR_GENS) indexes -+ * the old generation, is incremented when all its bins become empty. -+ * -+ * There are four operations: -+ * 1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in its -+ * current generation (old or young) and updates its "seg" to "head"; -+ * 2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in its -+ * current generation (old or young) and updates its "seg" to "tail"; -+ * 3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in the old -+ * generation, updates its "gen" to "old" and resets its "seg" to "default"; -+ * 4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin in the -+ * young generation, updates its "gen" to "young" and resets its "seg" to -+ * "default". -+ * -+ * The events that trigger the above operations are: -+ * 1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD; -+ * 2. The first attempt to reclaim an memcg below low, which triggers -+ * MEMCG_LRU_TAIL; -+ * 3. The first attempt to reclaim an memcg below reclaimable size threshold, -+ * which triggers MEMCG_LRU_TAIL; -+ * 4. The second attempt to reclaim an memcg below reclaimable size threshold, -+ * which triggers MEMCG_LRU_YOUNG; -+ * 5. Attempting to reclaim an memcg below min, which triggers MEMCG_LRU_YOUNG; -+ * 6. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG; -+ * 7. Offlining an memcg, which triggers MEMCG_LRU_OLD. -+ * -+ * Note that memcg LRU only applies to global reclaim, and the round-robin -+ * incrementing of their max_seq counters ensures the eventual fairness to all -+ * eligible memcgs. For memcg reclaim, it still relies on mem_cgroup_iter(). -+ */ -+#define MEMCG_NR_GENS 2 -+#define MEMCG_NR_BINS 8 -+ -+struct lru_gen_memcg { -+ /* the per-node memcg generation counter */ -+ unsigned long seq; -+ /* each memcg has one lru_gen_folio per node */ -+ unsigned long nr_memcgs[MEMCG_NR_GENS]; -+ /* per-node lru_gen_folio list for global reclaim */ -+ struct hlist_nulls_head fifo[MEMCG_NR_GENS][MEMCG_NR_BINS]; -+ /* protects the above */ -+ spinlock_t lock; -+}; -+ -+void lru_gen_init_pgdat(struct pglist_data *pgdat); -+ - void lru_gen_init_memcg(struct mem_cgroup *memcg); - void lru_gen_exit_memcg(struct mem_cgroup *memcg); --#endif -+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); -+ -+#else /* !CONFIG_MEMCG */ -+ -+#define MEMCG_NR_GENS 1 -+ -+struct lru_gen_memcg { -+}; -+ -+static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+} -+ -+#endif /* CONFIG_MEMCG */ - - #else /* !CONFIG_LRU_GEN */ - -+static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+} -+ - static inline void lru_gen_init_lruvec(struct lruvec *lruvec) - { - } -@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(s - } - - #ifdef CONFIG_MEMCG -+ - static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) - { - } -@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(st - static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) - { - } --#endif -+ -+static inline void lru_gen_online_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_offline_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_release_memcg(struct mem_cgroup *memcg) -+{ -+} -+ -+static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+{ -+} -+ -+#endif /* CONFIG_MEMCG */ - - #endif /* CONFIG_LRU_GEN */ - -@@ -1219,6 +1330,8 @@ typedef struct pglist_data { - #ifdef CONFIG_LRU_GEN - /* kswap mm walk data */ - struct lru_gen_mm_walk mm_walk; -+ /* lru_gen_folio list */ -+ struct lru_gen_memcg memcg_lru; - #endif - - CACHELINE_PADDING(_pad2_); ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struc - struct mem_cgroup_per_node *mz; - 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); -+ -+ return; -+ } -+ - mctz = soft_limit_tree.rb_tree_per_node[nid]; - if (!mctz) - return; -@@ -3524,6 +3534,9 @@ unsigned long mem_cgroup_soft_limit_recl - struct mem_cgroup_tree_per_node *mctz; - unsigned long excess; - -+ if (lru_gen_enabled()) -+ return 0; -+ - if (order > 0) - return 0; - -@@ -5387,6 +5400,7 @@ static int mem_cgroup_css_online(struct - if (unlikely(mem_cgroup_is_root(memcg))) - queue_delayed_work(system_unbound_wq, &stats_flush_dwork, - 2UL*HZ); -+ lru_gen_online_memcg(memcg); - return 0; - offline_kmem: - memcg_offline_kmem(memcg); -@@ -5418,6 +5432,7 @@ static void mem_cgroup_css_offline(struc - memcg_offline_kmem(memcg); - reparent_shrinker_deferred(memcg); - wb_memcg_offline(memcg); -+ lru_gen_offline_memcg(memcg); - - drain_all_stock(memcg); - -@@ -5429,6 +5444,7 @@ static void mem_cgroup_css_released(stru - struct mem_cgroup *memcg = mem_cgroup_from_css(css); - - invalidate_reclaim_iterators(memcg); -+ lru_gen_release_memcg(memcg); - } - - static void mem_cgroup_css_free(struct cgroup_subsys_state *css) ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -7943,6 +7943,7 @@ static void __init free_area_init_node(i - pgdat_set_deferred_range(pgdat); - - free_area_init_core(pgdat); -+ lru_gen_init_pgdat(pgdat); - } - - static void __init free_area_init_memoryless_node(int nid) ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -54,6 +54,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -134,11 +136,6 @@ struct scan_control { - /* Always discard instead of demoting to lower tier memory */ - unsigned int no_demotion:1; - --#ifdef CONFIG_LRU_GEN -- /* help kswapd make better choices among multiple memcgs */ -- unsigned long last_reclaimed; --#endif -- - /* Allocation order */ - s8 order; - -@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_ca - for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ - for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) - -+#define get_memcg_gen(seq) ((seq) % MEMCG_NR_GENS) -+#define get_memcg_bin(bin) ((bin) % MEMCG_NR_BINS) -+ - static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) - { - struct pglist_data *pgdat = NODE_DATA(nid); -@@ -4442,8 +4442,7 @@ done: - if (sc->priority <= DEF_PRIORITY - 2) - wait_event_killable(lruvec->mm_state.wait, - max_seq < READ_ONCE(lrugen->max_seq)); -- -- return max_seq < READ_ONCE(lrugen->max_seq); -+ return false; - } - - VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); -@@ -4516,8 +4515,6 @@ static void lru_gen_age_node(struct pgli - - VM_WARN_ON_ONCE(!current_is_kswapd()); - -- sc->last_reclaimed = sc->nr_reclaimed; -- - /* check the order to exclude compaction-induced reclaim */ - if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) - return; -@@ -5116,8 +5113,7 @@ static bool should_run_aging(struct lruv - * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg - * reclaim. - */ --static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, -- bool can_swap) -+static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool can_swap) - { - unsigned long nr_to_scan; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); -@@ -5134,10 +5130,8 @@ static unsigned long get_nr_to_scan(stru - if (sc->priority == DEF_PRIORITY) - return nr_to_scan; - -- try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false); -- - /* skip this lruvec as it's low on cold folios */ -- return 0; -+ return try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false) ? -1 : 0; - } - - static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5146,29 +5140,18 @@ static unsigned long get_nr_to_reclaim(s - if (!global_reclaim(sc)) - return -1; - -- /* discount the previous progress for kswapd */ -- if (current_is_kswapd()) -- return sc->nr_to_reclaim + sc->last_reclaimed; -- - return max(sc->nr_to_reclaim, compact_gap(sc->order)); - } - --static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) - { -- struct blk_plug plug; -+ long nr_to_scan; - unsigned long scanned = 0; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - -- lru_add_drain(); -- -- blk_start_plug(&plug); -- -- set_mm_walk(lruvec_pgdat(lruvec)); -- - while (true) { - int delta; - int swappiness; -- unsigned long nr_to_scan; - - if (sc->may_swap) - swappiness = get_swappiness(lruvec, sc); -@@ -5178,7 +5161,7 @@ static void lru_gen_shrink_lruvec(struct - swappiness = 0; - - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); -- if (!nr_to_scan) -+ if (nr_to_scan <= 0) - break; - - delta = evict_folios(lruvec, sc, swappiness); -@@ -5195,10 +5178,251 @@ static void lru_gen_shrink_lruvec(struct - cond_resched(); - } - -+ /* whether try_to_inc_max_seq() was successful */ -+ return nr_to_scan < 0; -+} -+ -+static int shrink_one(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ bool success; -+ unsigned long scanned = sc->nr_scanned; -+ unsigned long reclaimed = sc->nr_reclaimed; -+ int seg = lru_gen_memcg_seg(lruvec); -+ struct mem_cgroup *memcg = lruvec_memcg(lruvec); -+ struct pglist_data *pgdat = lruvec_pgdat(lruvec); -+ -+ /* see the comment on MEMCG_NR_GENS */ -+ if (!lruvec_is_sizable(lruvec, sc)) -+ return seg != MEMCG_LRU_TAIL ? MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG; -+ -+ mem_cgroup_calculate_protection(NULL, memcg); -+ -+ if (mem_cgroup_below_min(memcg)) -+ return MEMCG_LRU_YOUNG; -+ -+ if (mem_cgroup_below_low(memcg)) { -+ /* see the comment on MEMCG_NR_GENS */ -+ if (seg != MEMCG_LRU_TAIL) -+ return MEMCG_LRU_TAIL; -+ -+ memcg_memory_event(memcg, MEMCG_LOW); -+ } -+ -+ success = try_to_shrink_lruvec(lruvec, sc); -+ -+ shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); -+ -+ 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; -+ -+ return success ? MEMCG_LRU_YOUNG : 0; -+} -+ -+#ifdef CONFIG_MEMCG -+ -+static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ int gen; -+ int bin; -+ int first_bin; -+ struct lruvec *lruvec; -+ struct lru_gen_folio *lrugen; -+ const struct hlist_nulls_node *pos; -+ int op = 0; -+ struct mem_cgroup *memcg = NULL; -+ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); -+ -+ bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); -+restart: -+ gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); -+ -+ rcu_read_lock(); -+ -+ hlist_nulls_for_each_entry_rcu(lrugen, pos, &pgdat->memcg_lru.fifo[gen][bin], list) { -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+ -+ lruvec = container_of(lrugen, struct lruvec, lrugen); -+ memcg = lruvec_memcg(lruvec); -+ -+ if (!mem_cgroup_tryget(memcg)) { -+ op = 0; -+ memcg = NULL; -+ continue; -+ } -+ -+ rcu_read_unlock(); -+ -+ op = shrink_one(lruvec, sc); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ goto success; -+ -+ rcu_read_lock(); -+ } -+ -+ rcu_read_unlock(); -+ -+ /* restart if raced with lru_gen_rotate_memcg() */ -+ if (gen != get_nulls_value(pos)) -+ goto restart; -+ -+ /* try the rest of the bins of the current generation */ -+ bin = get_memcg_bin(bin + 1); -+ if (bin != first_bin) -+ goto restart; -+success: -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+} -+ -+static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ struct blk_plug plug; -+ -+ VM_WARN_ON_ONCE(global_reclaim(sc)); -+ -+ lru_add_drain(); -+ -+ blk_start_plug(&plug); -+ -+ set_mm_walk(lruvec_pgdat(lruvec)); -+ -+ if (try_to_shrink_lruvec(lruvec, sc)) -+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); -+ -+ clear_mm_walk(); -+ -+ blk_finish_plug(&plug); -+} -+ -+#else /* !CONFIG_MEMCG */ -+ -+static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ BUILD_BUG(); -+} -+ -+static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -+{ -+ BUILD_BUG(); -+} -+ -+#endif -+ -+static void set_initial_priority(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ int priority; -+ unsigned long reclaimable; -+ struct lruvec *lruvec = mem_cgroup_lruvec(NULL, pgdat); -+ -+ if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH) -+ return; -+ /* -+ * Determine the initial priority based on ((total / MEMCG_NR_GENS) >> -+ * priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, where the -+ * estimated reclaimed_to_scanned_ratio = inactive / total. -+ */ -+ reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE); -+ if (get_swappiness(lruvec, sc)) -+ reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON); -+ -+ reclaimable /= MEMCG_NR_GENS; -+ -+ /* round down reclaimable and round up sc->nr_to_reclaim */ -+ priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1); -+ -+ sc->priority = clamp(priority, 0, DEF_PRIORITY); -+} -+ -+static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+ struct blk_plug plug; -+ unsigned long reclaimed = sc->nr_reclaimed; -+ -+ VM_WARN_ON_ONCE(!global_reclaim(sc)); -+ -+ lru_add_drain(); -+ -+ blk_start_plug(&plug); -+ -+ set_mm_walk(pgdat); -+ -+ set_initial_priority(pgdat, sc); -+ -+ if (current_is_kswapd()) -+ sc->nr_reclaimed = 0; -+ -+ if (mem_cgroup_disabled()) -+ shrink_one(&pgdat->__lruvec, sc); -+ else -+ shrink_many(pgdat, sc); -+ -+ if (current_is_kswapd()) -+ sc->nr_reclaimed += reclaimed; -+ - clear_mm_walk(); - - blk_finish_plug(&plug); -+ -+ /* kswapd should never fail */ -+ 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 -@@ -5656,11 +5880,11 @@ static int run_cmd(char cmd, int memcg_i - - if (!mem_cgroup_disabled()) { - rcu_read_lock(); -+ - memcg = mem_cgroup_from_id(memcg_id); --#ifdef CONFIG_MEMCG -- if (memcg && !css_tryget(&memcg->css)) -+ if (!mem_cgroup_tryget(memcg)) - memcg = NULL; --#endif -+ - rcu_read_unlock(); - - if (!memcg) -@@ -5808,6 +6032,19 @@ void lru_gen_init_lruvec(struct lruvec * - } - - #ifdef CONFIG_MEMCG -+ -+void lru_gen_init_pgdat(struct pglist_data *pgdat) -+{ -+ int i, j; -+ -+ spin_lock_init(&pgdat->memcg_lru.lock); -+ -+ for (i = 0; i < MEMCG_NR_GENS; i++) { -+ for (j = 0; j < MEMCG_NR_BINS; j++) -+ INIT_HLIST_NULLS_HEAD(&pgdat->memcg_lru.fifo[i][j], i); -+ } -+} -+ - void lru_gen_init_memcg(struct mem_cgroup *memcg) - { - INIT_LIST_HEAD(&memcg->mm_list.fifo); -@@ -5831,7 +6068,69 @@ void lru_gen_exit_memcg(struct mem_cgrou - } - } - } --#endif -+ -+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) - { -@@ -5858,6 +6157,10 @@ static void lru_gen_shrink_lruvec(struct - { - } - -+static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) -+{ -+} -+ - #endif /* CONFIG_LRU_GEN */ - - static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -@@ -5871,7 +6174,7 @@ static void shrink_lruvec(struct lruvec - bool proportional_reclaim; - struct blk_plug plug; - -- if (lru_gen_enabled()) { -+ if (lru_gen_enabled() && !global_reclaim(sc)) { - lru_gen_shrink_lruvec(lruvec, sc); - return; - } -@@ -6114,6 +6417,11 @@ static void shrink_node(pg_data_t *pgdat - struct lruvec *target_lruvec; - bool reclaimable = false; - -+ if (lru_gen_enabled() && global_reclaim(sc)) { -+ lru_gen_shrink_node(pgdat, sc); -+ return; -+ } -+ - target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat); - - again: diff --git a/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch b/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch deleted file mode 100644 index d60ddb9dcc..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 11b14ee8cbbbebd8204609076a9327a1171cd253 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:05 -0700 -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 - supported as usual. -2. sc->proactive, which indicates reclaim by memory.reclaim, may not - opportunistically skip the aging path, since it is considered less - latency sensitive. -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_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. - -The rest are handled by the existing code. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-8-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct pglist_data *pgdat = lruvec_pgdat(lruvec); - -+ if (!sc->may_swap) -+ return 0; -+ - if (!can_demote(pgdat->node_id, sc) && - mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) - return 0; -@@ -4223,7 +4226,7 @@ static void walk_mm(struct lruvec *lruve - } while (err == -EAGAIN); - } - --static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) -+static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat, bool force_alloc) - { - struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; - -@@ -4231,7 +4234,7 @@ static struct lru_gen_mm_walk *set_mm_wa - VM_WARN_ON_ONCE(walk); - - walk = &pgdat->mm_walk; -- } else if (!pgdat && !walk) { -+ } else if (!walk && force_alloc) { - VM_WARN_ON_ONCE(current_is_kswapd()); - - walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); -@@ -4419,7 +4422,7 @@ static bool try_to_inc_max_seq(struct lr - goto done; - } - -- walk = set_mm_walk(NULL); -+ walk = set_mm_walk(NULL, true); - if (!walk) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; -@@ -4488,8 +4491,6 @@ static bool lruvec_is_reclaimable(struct - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MIN_SEQ(lruvec); - -- VM_WARN_ON_ONCE(sc->memcg_low_reclaim); -- - /* see the comment on lru_gen_folio */ - gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); - birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); -@@ -4753,12 +4754,8 @@ static bool isolate_folio(struct lruvec - { - bool success; - -- /* unmapping inhibited */ -- if (!sc->may_unmap && folio_mapped(folio)) -- return false; -- - /* swapping inhibited */ -- if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && -+ if (!(sc->gfp_mask & __GFP_IO) && - (folio_test_dirty(folio) || - (folio_test_anon(folio) && !folio_test_swapcache(folio)))) - return false; -@@ -4857,9 +4854,8 @@ static int scan_folios(struct lruvec *lr - __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 folios due to reclaim_idx. Check the -+ * remaining to prevent livelock if it's not making progress. - */ - return isolated || !remaining ? scanned : 0; - } -@@ -5119,8 +5115,7 @@ static long get_nr_to_scan(struct lruvec - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - -- if (mem_cgroup_below_min(memcg) || -- (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) -+ if (mem_cgroup_below_min(memcg)) - return 0; - - if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) -@@ -5148,17 +5143,14 @@ static bool try_to_shrink_lruvec(struct - long nr_to_scan; - unsigned long scanned = 0; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); -+ int swappiness = get_swappiness(lruvec, sc); -+ -+ /* clean file folios are more likely to exist */ -+ if (swappiness && !(sc->gfp_mask & __GFP_IO)) -+ swappiness = 1; - - while (true) { - int delta; -- int swappiness; -- -- if (sc->may_swap) -- swappiness = get_swappiness(lruvec, sc); -- else if (!cgroup_reclaim(sc) && get_swappiness(lruvec, sc)) -- swappiness = 1; -- else -- swappiness = 0; - - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); - if (nr_to_scan <= 0) -@@ -5289,12 +5281,13 @@ static void lru_gen_shrink_lruvec(struct - struct blk_plug plug; - - VM_WARN_ON_ONCE(global_reclaim(sc)); -+ VM_WARN_ON_ONCE(!sc->may_writepage || !sc->may_unmap); - - lru_add_drain(); - - blk_start_plug(&plug); - -- set_mm_walk(lruvec_pgdat(lruvec)); -+ set_mm_walk(NULL, sc->proactive); - - if (try_to_shrink_lruvec(lruvec, sc)) - lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); -@@ -5350,11 +5343,19 @@ static void lru_gen_shrink_node(struct p - - VM_WARN_ON_ONCE(!global_reclaim(sc)); - -+ /* -+ * 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. -+ */ -+ if (!sc->may_writepage || !sc->may_unmap) -+ goto done; -+ - lru_add_drain(); - - blk_start_plug(&plug); - -- set_mm_walk(pgdat); -+ set_mm_walk(pgdat, sc->proactive); - - set_initial_priority(pgdat, sc); - -@@ -5372,7 +5373,7 @@ static void lru_gen_shrink_node(struct p - clear_mm_walk(); - - blk_finish_plug(&plug); -- -+done: - /* kswapd should never fail */ - pgdat->kswapd_failures = 0; - } -@@ -5944,7 +5945,7 @@ static ssize_t lru_gen_seq_write(struct - set_task_reclaim_state(current, &sc.reclaim_state); - flags = memalloc_noreclaim_save(); - blk_start_plug(&plug); -- if (!set_mm_walk(NULL)) { -+ if (!set_mm_walk(NULL, true)) { - err = -ENOMEM; - goto done; - } diff --git a/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch b/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch deleted file mode 100644 index 3cbc84f8b8..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 25887d48dff860751a06caa4188bfaf6bfb6e4b2 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Wed, 21 Dec 2022 21:19:06 -0700 -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. - -Link: https://lkml.kernel.org/r/20221222041905.2431096-9-yuzhao@google.com -Signed-off-by: Yu Zhao -Cc: Johannes Weiner -Cc: Jonathan Corbet -Cc: Michael Larabel -Cc: Michal Hocko -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4417,7 +4417,7 @@ static bool try_to_inc_max_seq(struct lr - * handful of PTEs. Spreading the work out over a period of time usually - * is less efficient, but it avoids bursty page faults. - */ -- if (!force_scan && !(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { -+ if (!arch_has_hw_pte_young() || !get_cap(LRU_GEN_MM_WALK)) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; - } diff --git a/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch b/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch deleted file mode 100644 index c1ad1c538e..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 620b0ee94455e48d124414cd06d8a53f69fb6453 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Mon, 13 Feb 2023 00:53:22 -0700 -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. -Each generation is also sharded into multiple bins to improve scalability. -A reclaimer starts with a random bin (in the old generation) and, if it -fails, it will retry, i.e., to try the rest of the bins. - -If a reclaimer fails with the last memcg, it should move this memcg to the -young generation first, which causes the generations to alternate, and -then retry. Otherwise, the retries will be futile because all other bins -are empty. - -Link: https://lkml.kernel.org/r/20230213075322.1416966-1-yuzhao@google.com -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -5218,18 +5218,20 @@ static int shrink_one(struct lruvec *lru - - static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) - { -+ int op; - int gen; - int bin; - int first_bin; - struct lruvec *lruvec; - struct lru_gen_folio *lrugen; -+ struct mem_cgroup *memcg; - const struct hlist_nulls_node *pos; -- int op = 0; -- struct mem_cgroup *memcg = NULL; - unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - - 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(); -@@ -5253,14 +5255,22 @@ restart: - - op = shrink_one(lruvec, sc); - -- if (sc->nr_reclaimed >= nr_to_reclaim) -- goto success; -- - rcu_read_lock(); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ break; - } - - rcu_read_unlock(); - -+ if (op) -+ lru_gen_rotate_memcg(lruvec, op); -+ -+ mem_cgroup_put(memcg); -+ -+ if (sc->nr_reclaimed >= nr_to_reclaim) -+ return; -+ - /* restart if raced with lru_gen_rotate_memcg() */ - if (gen != get_nulls_value(pos)) - goto restart; -@@ -5269,11 +5279,6 @@ restart: - bin = get_memcg_bin(bin + 1); - if (bin != first_bin) - goto restart; --success: -- if (op) -- lru_gen_rotate_memcg(lruvec, op); -- -- mem_cgroup_put(memcg); - } - - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) diff --git a/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch b/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch deleted file mode 100644 index 67fe4f96ec..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 70d216c71ff5c5b17dd1da6294f97b91fb6aba7a Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Fri, 30 Dec 2022 14:52:51 -0700 -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. - -This function returns false for VMAs marked by VM_SEQ_READ or -VM_RAND_READ. While the former flag indicates linear access, i.e., a -special case of spatial locality, both flags indicate a lack of temporal -locality, i.e., the reuse of an area within a relatively small duration. - -"Recency" is chosen over "locality" to avoid confusion between temporal -and spatial localities. - -Before this patch, the active/inactive LRU only ignored the accessed bit -from VMAs marked by VM_SEQ_READ. After this patch, the active/inactive -LRU and MGLRU share the same logic: they both ignore the accessed bit if -vma_has_recency() returns false. - -For the active/inactive LRU, the following fio test showed a [6, 8]% -increase in IOPS when randomly accessing mapped files under memory -pressure. - - kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) - kb=$((kb - 8*1024*1024)) - - modprobe brd rd_nr=1 rd_size=$kb - dd if=/dev/zero of=/dev/ram0 bs=1M - - mkfs.ext4 /dev/ram0 - mount /dev/ram0 /mnt/ - swapoff -a - - fio --name=test --directory=/mnt/ --ioengine=mmap --numjobs=8 \ - --size=8G --rw=randrw --time_based --runtime=10m \ - --group_reporting - -The discussion that led to this patch is here [1]. Additional test -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 | 8 ++++++++ - mm/memory.c | 7 +++---- - mm/rmap.c | 42 +++++++++++++++++---------------------- - mm/vmscan.c | 5 ++++- - 4 files changed, 33 insertions(+), 29 deletions(-) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -600,4 +600,12 @@ pte_install_uffd_wp_if_needed(struct vm_ - #endif - } - -+static inline bool vma_has_recency(struct vm_area_struct *vma) -+{ -+ if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) -+ return false; -+ -+ return true; -+} -+ - #endif ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1445,8 +1445,7 @@ again: - force_flush = 1; - set_page_dirty(page); - } -- if (pte_young(ptent) && -- likely(!(vma->vm_flags & VM_SEQ_READ))) -+ if (pte_young(ptent) && likely(vma_has_recency(vma))) - mark_page_accessed(page); - } - rss[mm_counter(page)]--; -@@ -5219,8 +5218,8 @@ static inline void mm_account_fault(stru - #ifdef CONFIG_LRU_GEN - static void lru_gen_enter_fault(struct vm_area_struct *vma) - { -- /* the LRU algorithm doesn't apply to sequential or random reads */ -- current->in_lru_fault = !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)); -+ /* the LRU algorithm only applies to accesses with recency */ -+ current->in_lru_fault = vma_has_recency(vma); - } - - static void lru_gen_exit_fault(void) ---- a/mm/rmap.c -+++ b/mm/rmap.c -@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct - } - - if (pvmw.pte) { -- if (lru_gen_enabled() && pte_young(*pvmw.pte) && -- !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))) { -+ if (lru_gen_enabled() && pte_young(*pvmw.pte)) { - lru_gen_look_around(&pvmw); - referenced++; - } - - if (ptep_clear_flush_young_notify(vma, address, -- pvmw.pte)) { -- /* -- * Don't treat a reference through -- * a sequentially read mapping as such. -- * If the 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 folio. -- */ -- if (likely(!(vma->vm_flags & VM_SEQ_READ))) -- referenced++; -- } -+ pvmw.pte)) -+ referenced++; - } 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 - 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 -+ * 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 folio in zap_pte_range(). -+ */ -+ if (!vma_has_recency(vma)) -+ return true; -+ -+ /* -+ * If we are reclaiming on behalf of a cgroup, skip counting on behalf -+ * of references from different cgroups. -+ */ -+ if (memcg && !mm_match_cgroup(vma->vm_mm, memcg)) - return true; - - return false; -@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio - .arg = (void *)&pra, - .anon_lock = folio_lock_anon_vma_read, - .try_lock = true, -+ .invalid_vma = invalid_folio_referenced_vma, - }; - - *vm_flags = 0; -@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio - return 1; - } - -- /* -- * If we are reclaiming on behalf of a cgroup, skip -- * counting on behalf of references from different -- * cgroups -- */ -- if (memcg) { -- rwc.invalid_vma = invalid_folio_referenced_vma; -- } -- - rmap_walk(folio, &rwc); - *vm_flags = pra.vm_flags; - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3778,7 +3778,10 @@ static int should_skip_vma(unsigned long - if (is_vm_hugetlb_page(vma)) - return true; - -- if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_SEQ_READ | VM_RAND_READ)) -+ if (!vma_has_recency(vma)) -+ return true; -+ -+ if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) - return true; - - if (vma == get_gate_vma(vma->vm_mm)) diff --git a/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch b/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch deleted file mode 100644 index f9c39be920..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 9ca4e437a24dfc4ec6c362f319eb9850b9eca497 Mon Sep 17 00:00:00 2001 -From: Yu Zhao -Date: Fri, 30 Dec 2022 14:52:52 -0700 -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. - -The advantages of POSIX_FADV_NOREUSE are: -1. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not alter the - default readahead behavior. -2. Unlike MADV_SEQUENTIAL and MADV_RANDOM, it does not split VMAs and - therefore does not take mmap_lock. -3. Unlike MADV_COLD, setting it has a negligible cost, regardless of - how many pages it affects. - -Its limitations are: -1. Like POSIX_FADV_RANDOM and POSIX_FADV_SEQUENTIAL, it currently does - not support range. IOW, its scope is the entire file. -2. It currently does not ignore access through file descriptors. - Specifically, for the active/inactive LRU, given a file page shared - 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 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]. -This time the goal is to fill a niche: a few desktop applications, e.g., -large file transferring and video encoding/decoding, want fast file -streaming with mmap() rather than direct IO. Among those applications, an -SVT-AV1 regression was reported when running with MGLRU [2]. The -following test can reproduce that regression. - - kb=$(awk '/MemTotal/ { print $2 }' /proc/meminfo) - kb=$((kb - 8*1024*1024)) - - modprobe brd rd_nr=1 rd_size=$kb - dd if=/dev/zero of=/dev/ram0 bs=1M - - mkfs.ext4 /dev/ram0 - mount /dev/ram0 /mnt/ - swapoff -a - - fallocate -l 8G /mnt/swapfile - mkswap /mnt/swapfile - swapon /mnt/swapfile - - wget http://ultravideo.cs.tut.fi/video/Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z - 7z e -o/mnt/ Bosphorus_3840x2160_120fps_420_8bit_YUV_Y4M.7z - SvtAv1EncApp --preset 12 -w 3840 -h 2160 \ - -i /mnt/Bosphorus_3840x2160.y4m - -For MGLRU, the following change showed a [9-11]% increase in FPS, -which makes it on par with the active/inactive LRU. - - patch Source/App/EncApp/EbAppMain.c < #include - 35d35 - < #include /* _O_BINARY */ - 117a118 - > posix_fadvise(config->mmap.fd, 0, 0, POSIX_FADV_NOREUSE); - EOF - -[1] https://lore.kernel.org/r/1308923350-7932-1-git-send-email-andrea@betterlinux.com/ -[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(-) - ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb - /* File supports DIRECT IO */ - #define FMODE_CAN_ODIRECT ((__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) - ---- a/include/linux/mm_inline.h -+++ b/include/linux/mm_inline.h -@@ -605,6 +605,9 @@ static inline bool vma_has_recency(struc - if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) - return false; - -+ if (vma->vm_file && (vma->vm_file->f_mode & FMODE_NOREUSE)) -+ return false; -+ - return true; - } - ---- a/mm/fadvise.c -+++ b/mm/fadvise.c -@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, l - case POSIX_FADV_NORMAL: - file->f_ra.ra_pages = bdi->ra_pages; - spin_lock(&file->f_lock); -- file->f_mode &= ~FMODE_RANDOM; -+ file->f_mode &= ~(FMODE_RANDOM | FMODE_NOREUSE); - spin_unlock(&file->f_lock); - break; - case POSIX_FADV_RANDOM: -@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, l - force_page_cache_readahead(mapping, file, start_index, nrpages); - break; - case POSIX_FADV_NOREUSE: -+ spin_lock(&file->f_lock); -+ file->f_mode |= FMODE_NOREUSE; -+ spin_unlock(&file->f_lock); - break; - case POSIX_FADV_DONTNEED: - __filemap_fdatawrite_range(mapping, offset, endbyte, diff --git a/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch b/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch deleted file mode 100644 index bac2e3e344..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch +++ /dev/null @@ -1,67 +0,0 @@ -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(+) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -141,6 +141,21 @@ loop has detected outlying refaults from - 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: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4461,6 +4461,10 @@ done: - return true; - } - -+/****************************************************************************** -+ * working set protection -+ ******************************************************************************/ -+ - static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) - { - int gen, type, zone; diff --git a/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch b/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch deleted file mode 100644 index c28a1c5d5b..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch +++ /dev/null @@ -1,57 +0,0 @@ -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(+) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -156,6 +156,20 @@ This time-based approach has the followi - 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: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4555,6 +4555,10 @@ static void lru_gen_age_node(struct pgli - } - } - -+/****************************************************************************** -+ * 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 diff --git a/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch b/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch deleted file mode 100644 index a7dfb5ffe7..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch +++ /dev/null @@ -1,243 +0,0 @@ -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(-) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -170,6 +170,22 @@ promotes hot pages. If the scan was done - 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: ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3209,6 +3209,98 @@ static bool __maybe_unused seq_is_valid( - } - - /****************************************************************************** -+ * 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 - } - #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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch b/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch deleted file mode 100644 index 101a0a3757..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch +++ /dev/null @@ -1,427 +0,0 @@ -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(-) - ---- a/Documentation/mm/multigen_lru.rst -+++ b/Documentation/mm/multigen_lru.rst -@@ -186,9 +186,40 @@ is false positive, the cost is an additi - 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 ---- 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; -@@ -314,11 +302,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; ---- 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_cgrou - 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 - { - } - --static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) -+static inline void lru_gen_soft_reclaim(struct lruvec *lruvec) - { - } - ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -478,12 +478,8 @@ static void mem_cgroup_update_tree(struc - 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; - } - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4692,6 +4692,148 @@ void lru_gen_look_around(struct page_vma - } - - /****************************************************************************** -+ * 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 - ******************************************************************************/ - -@@ -5398,53 +5540,6 @@ done: - 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 - ******************************************************************************/ -@@ -6090,67 +6185,6 @@ void lru_gen_exit_memcg(struct mem_cgrou - } - } - --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) diff --git a/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch b/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch deleted file mode 100644 index 1ee766f861..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch +++ /dev/null @@ -1,40 +0,0 @@ -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(+) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -6172,12 +6172,17 @@ void lru_gen_exit_memcg(struct mem_cgrou - 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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch b/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch deleted file mode 100644 index 2273977dc9..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch +++ /dev/null @@ -1,135 +0,0 @@ -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -3980,8 +3980,8 @@ restart: - } - - #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 - 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 - 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 @@ next: - 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, u - 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 @@ restart: - 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 @@ restart: - 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; diff --git a/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch b/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch deleted file mode 100644 index 856199574a..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch +++ /dev/null @@ -1,148 +0,0 @@ -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(-) - ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -4573,13 +4573,12 @@ static void lru_gen_age_node(struct pgli - 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); -@@ -4596,25 +4595,28 @@ void lru_gen_look_around(struct page_vma - /* 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; - -@@ -4639,56 +4641,27 @@ void lru_gen_look_around(struct page_vma - !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(); - } - - /****************************************************************************** diff --git a/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch b/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch deleted file mode 100644 index 1b0459cdb9..0000000000 --- a/target/linux/generic/backport-6.6/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch +++ /dev/null @@ -1,273 +0,0 @@ -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(-) - ---- 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 { ---- 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 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); - -@@ -3567,9 +3548,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; -@@ -4172,10 +4153,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; -@@ -4208,8 +4185,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; -+ - /* folio_update_gen() requires stable folio_memcg() */ - if (!mem_cgroup_trylock_pages(memcg)) - break; -@@ -4444,25 +4427,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; - } - - /****************************************************************************** -@@ -6117,7 +6087,6 @@ void lru_gen_init_lruvec(struct 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 -@@ -6150,7 +6119,6 @@ void lru_gen_exit_memcg(struct mem_cgrou - 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))); - diff --git a/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch b/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch deleted file mode 100644 index 2e6d881fe9..0000000000 --- a/target/linux/generic/backport-6.6/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch +++ /dev/null @@ -1,58 +0,0 @@ -From e2192de59e457aef8d1f055a452131f0b3e5d097 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 18 Jan 2023 14:26:53 +0100 -Subject: [PATCH] bitfield: add FIELD_PREP_CONST() - -Neither FIELD_PREP() nor *_encode_bits() can be used -in constant contexts (such as initializers), but we -don't want to define shift constants for all masks -just for use in initializers, and having checks that -the values fit is also useful. - -Therefore, add FIELD_PREP_CONST() which is a smaller -version of FIELD_PREP() that can only take constant -arguments and has less friendly (but not less strict) -error checks, and expands to a constant value. - -Signed-off-by: Johannes Berg -Link: https://lore.kernel.org/r/20230118142652.53f20593504b.Iaeea0aee77a6493d70e573b4aa55c91c00e01e4b@changeid -Signed-off-by: Johannes Berg ---- - include/linux/bitfield.h | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - ---- a/include/linux/bitfield.h -+++ b/include/linux/bitfield.h -@@ -115,6 +115,32 @@ - ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ - }) - -+#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) -+ -+/** -+ * FIELD_PREP_CONST() - prepare a constant bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_val: value to put in the field -+ * -+ * FIELD_PREP_CONST() masks and shifts up the value. The result should -+ * be combined with other fields of the bitfield using logical OR. -+ * -+ * Unlike FIELD_PREP() this is a constant expression and can therefore -+ * be used in initializers. Error checking is less comfortable for this -+ * version, and non-constant masks cannot be used. -+ */ -+#define FIELD_PREP_CONST(_mask, _val) \ -+ ( \ -+ /* mask must be non-zero */ \ -+ BUILD_BUG_ON_ZERO((_mask) == 0) + \ -+ /* check if value fits */ \ -+ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ -+ /* check if mask is contiguous */ \ -+ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \ -+ /* and create the value */ \ -+ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \ -+ ) -+ - /** - * FIELD_GET() - extract a bitfield element - * @_mask: shifted mask defining the field's length and position diff --git a/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch b/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch deleted file mode 100644 index d8d0cf9555..0000000000 --- a/target/linux/generic/backport-6.6/300-v6.2-powerpc-suppress-some-linker-warnings-in-recent-link.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 579aee9fc594af94c242068c011b0233563d4bbf Mon Sep 17 00:00:00 2001 -From: Stephen Rothwell -Date: Mon, 10 Oct 2022 16:57:21 +1100 -Subject: [PATCH] powerpc: suppress some linker warnings in recent linker - versions - -This is a follow on from commit - - 0d362be5b142 ("Makefile: link with -z noexecstack --no-warn-rwx-segments") - -for arch/powerpc/boot to address wanrings like: - - ld: warning: opal-calls.o: missing .note.GNU-stack section implies executable stack - ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker - ld: warning: arch/powerpc/boot/zImage.epapr has a LOAD segment with RWX permissions - -This fixes issue https://github.com/linuxppc/issues/issues/417 - -Signed-off-by: Stephen Rothwell -Signed-off-by: Michael Ellerman -Link: https://lore.kernel.org/r/20221010165721.106267e6@canb.auug.org.au ---- - arch/powerpc/boot/wrapper | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -215,6 +215,11 @@ ld_version() - }' - } - -+ld_is_lld() -+{ -+ ${CROSS}ld -V 2>&1 | grep -q LLD -+} -+ - # Do not include PT_INTERP segment when linking pie. Non-pie linking - # just ignores this option. - LD_VERSION=$(${CROSS}ld --version | ld_version) -@@ -223,6 +228,14 @@ if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VE - nodl="--no-dynamic-linker" - fi - -+# suppress some warnings in recent ld versions -+nowarn="-z noexecstack" -+if ! ld_is_lld; then -+ if [ "$LD_VERSION" -ge "$(echo 2.39 | ld_version)" ]; then -+ nowarn="$nowarn --no-warn-rwx-segments" -+ fi -+fi -+ - platformo=$object/"$platform".o - lds=$object/zImage.lds - ext=strip -@@ -504,7 +517,7 @@ if [ "$platform" != "miboot" ]; then - text_start="-Ttext $link_address" - fi - #link everything -- ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $rodynamic $notext -o "$ofile" $map \ -+ ${CROSS}ld -m $format -T $lds $text_start $pie $nodl $nowarn $rodynamic $notext -o "$ofile" $map \ - $platformo $tmp $object/wrapper.a - rm $tmp - fi diff --git a/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch b/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch deleted file mode 100644 index eb6be5ed00..0000000000 --- a/target/linux/generic/backport-6.6/406-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 63db0cb35e1cb3b3c134906d1062f65513fdda2d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Oct 2022 10:37:09 +0200 -Subject: [PATCH] mtd: core: simplify (a bit) code find partition-matching - dynamic OF node -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -1. Don't hardcode "partition-" string twice -2. Use simpler logic & use ->name to avoid of_property_read_string() -3. Use mtd_get_of_node() helper - -Cc: Christian Marangi -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-1-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 16 +++++++--------- - 1 file changed, 7 insertions(+), 9 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -551,18 +551,16 @@ static void mtd_check_of_node(struct mtd - struct device_node *partitions, *parent_dn, *mtd_dn = NULL; - const char *pname, *prefix = "partition-"; - int plen, mtd_name_len, offset, prefix_len; -- struct mtd_info *parent; - bool found = false; - - /* Check if MTD already has a device node */ -- if (dev_of_node(&mtd->dev)) -+ if (mtd_get_of_node(mtd)) - return; - - /* Check if a partitions node exist */ - if (!mtd_is_partition(mtd)) - return; -- parent = mtd->parent; -- parent_dn = of_node_get(dev_of_node(&parent->dev)); -+ parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); - if (!parent_dn) - return; - -@@ -575,15 +573,15 @@ static void mtd_check_of_node(struct mtd - - /* Search if a partition is defined with the same name */ - for_each_child_of_node(partitions, mtd_dn) { -- offset = 0; -- - /* Skip partition with no/wrong prefix */ -- if (!of_node_name_prefix(mtd_dn, "partition-")) -+ if (!of_node_name_prefix(mtd_dn, prefix)) - continue; - - /* Label have priority. Check that first */ -- if (of_property_read_string(mtd_dn, "label", &pname)) { -- of_property_read_string(mtd_dn, "name", &pname); -+ if (!of_property_read_string(mtd_dn, "label", &pname)) { -+ offset = 0; -+ } else { -+ pname = mtd_dn->name; - offset = prefix_len; - } - diff --git a/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch b/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch deleted file mode 100644 index f8d3a370d4..0000000000 --- a/target/linux/generic/backport-6.6/406-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch +++ /dev/null @@ -1,84 +0,0 @@ -From ddb8cefb7af288950447ca6eeeafb09977dab56f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Oct 2022 10:37:10 +0200 -Subject: [PATCH] mtd: core: try to find OF node for every MTD partition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -So far this feature was limited to the top-level "nvmem-cells" node. -There are multiple parsers creating partitions and subpartitions -dynamically. Extend that code to handle them too. - -This allows finding partition-* node for every MTD (sub)partition. - -Random example: - -partitions { - compatible = "brcm,bcm947xx-cfe-partitions"; - - partition-firmware { - compatible = "brcm,trx"; - - partition-loader { - }; - }; -}; - -Cc: Christian Marangi -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221004083710.27704-2-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -551,20 +551,22 @@ static void mtd_check_of_node(struct mtd - struct device_node *partitions, *parent_dn, *mtd_dn = NULL; - const char *pname, *prefix = "partition-"; - int plen, mtd_name_len, offset, prefix_len; -- bool found = false; - - /* Check if MTD already has a device node */ - if (mtd_get_of_node(mtd)) - return; - -- /* Check if a partitions node exist */ - if (!mtd_is_partition(mtd)) - return; -+ - parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); - if (!parent_dn) - return; - -- partitions = of_get_child_by_name(parent_dn, "partitions"); -+ if (mtd_is_partition(mtd->parent)) -+ partitions = of_node_get(parent_dn); -+ else -+ partitions = of_get_child_by_name(parent_dn, "partitions"); - if (!partitions) - goto exit_parent; - -@@ -588,19 +590,11 @@ static void mtd_check_of_node(struct mtd - plen = strlen(pname) - offset; - if (plen == mtd_name_len && - !strncmp(mtd->name, pname + offset, plen)) { -- found = true; -+ mtd_set_of_node(mtd, mtd_dn); - break; - } - } - -- if (!found) -- goto exit_partitions; -- -- /* Set of_node only for nvmem */ -- if (of_device_is_compatible(mtd_dn, "nvmem-cells")) -- mtd_set_of_node(mtd, mtd_dn); -- --exit_partitions: - of_node_put(partitions); - exit_parent: - of_node_put(parent_dn); diff --git a/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch b/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch deleted file mode 100644 index 5a5e11c8f7..0000000000 --- a/target/linux/generic/backport-6.6/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 26422ac78e9d8767bd4aabfbae616b15edbf6a1b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sat, 22 Oct 2022 23:13:18 +0200 -Subject: [PATCH] mtd: core: set ROOT_DEV for partitions marked as rootfs in DT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds support for "linux,rootfs" binding that is used to mark flash -partition containing rootfs. It's useful for devices using device tree -that don't have bootloader passing root info in cmdline. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221022211318.32009-2-zajec5@gmail.com ---- - drivers/mtd/mtdcore.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -737,6 +738,17 @@ int add_mtd_device(struct mtd_info *mtd) - not->add(mtd); - - mutex_unlock(&mtd_table_mutex); -+ -+ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) { -+ if (IS_BUILTIN(CONFIG_MTD)) { -+ pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); -+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); -+ } else { -+ pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", -+ mtd->index, mtd->name); -+ } -+ } -+ - /* We _know_ we aren't being removed, because - our caller is still holding us here. So none - of this try_ nonsense, and no bitching about it diff --git a/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch b/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch deleted file mode 100644 index e570564a0b..0000000000 --- a/target/linux/generic/backport-6.6/421-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch +++ /dev/null @@ -1,229 +0,0 @@ -From aec4d5f5ffd0f0092bd9dc21ea90e0bc237d4b74 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sat, 15 Oct 2022 11:29:50 +0200 -Subject: [PATCH] mtd: parsers: add TP-Link SafeLoader partitions table parser -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This parser deals with most TP-Link home routers. It reads info about -partitions and registers them in the MTD subsystem. - -Example from TP-Link Archer C5 V2: - -spi-nor spi0.0: s25fl128s1 (16384 Kbytes) -15 tplink-safeloader partitions found on MTD device spi0.0 -Creating 15 MTD partitions on "spi0.0": -0x000000000000-0x000000040000 : "fs-uboot" -0x000000040000-0x000000440000 : "os-image" -0x000000440000-0x000000e40000 : "rootfs" -0x000000e40000-0x000000e40200 : "default-mac" -0x000000e40200-0x000000e40400 : "pin" -0x000000e40400-0x000000e40600 : "product-info" -0x000000e50000-0x000000e60000 : "partition-table" -0x000000e60000-0x000000e60200 : "soft-version" -0x000000e61000-0x000000e70000 : "support-list" -0x000000e70000-0x000000e80000 : "profile" -0x000000e80000-0x000000e90000 : "default-config" -0x000000e90000-0x000000ee0000 : "user-config" -0x000000ee0000-0x000000fe0000 : "log" -0x000000fe0000-0x000000ff0000 : "radio_bk" -0x000000ff0000-0x000001000000 : "radio" - -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221015092950.27467-2-zajec5@gmail.com ---- - drivers/mtd/parsers/Kconfig | 15 +++ - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/tplink_safeloader.c | 150 ++++++++++++++++++++++++ - 3 files changed, 166 insertions(+) - create mode 100644 drivers/mtd/parsers/tplink_safeloader.c - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -123,6 +123,21 @@ config MTD_AFS_PARTS - for your particular device. It won't happen automatically. The - 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. - -+config MTD_PARSER_TPLINK_SAFELOADER -+ tristate "TP-Link Safeloader partitions parser" -+ depends on MTD && (ARCH_BCM_5301X || ATH79 || SOC_MT7620 || SOC_MT7621 || COMPILE_TEST) -+ help -+ TP-Link home routers use flash partitions to store various data. Info -+ about flash space layout is stored in a partitions table using a -+ custom ASCII-based format. -+ -+ That format was first found in devices with SafeLoader bootloader and -+ was named after it. Later it was adapted to CFE and U-Boot -+ bootloaders. -+ -+ This driver reads partitions table, parses it and creates MTD -+ partitions. -+ - config MTD_PARSER_TRX - tristate "Parser for TRX format partitions" - depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST) ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += - ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o -+obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o - obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o - obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o ---- /dev/null -+++ b/drivers/mtd/parsers/tplink_safeloader.c -@@ -0,0 +1,150 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright © 2022 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TPLINK_SAFELOADER_DATA_OFFSET 4 -+#define TPLINK_SAFELOADER_MAX_PARTS 32 -+ -+struct safeloader_cmn_header { -+ __be32 size; -+ uint32_t unused; -+} __packed; -+ -+static void *mtd_parser_tplink_safeloader_read_table(struct mtd_info *mtd) -+{ -+ struct safeloader_cmn_header hdr; -+ struct device_node *np; -+ size_t bytes_read; -+ size_t offset; -+ size_t size; -+ char *buf; -+ int err; -+ -+ np = mtd_get_of_node(mtd); -+ if (mtd_is_partition(mtd)) -+ of_node_get(np); -+ else -+ np = of_get_child_by_name(np, "partitions"); -+ -+ if (of_property_read_u32(np, "partitions-table-offset", (u32 *)&offset)) { -+ pr_err("Failed to get partitions table offset\n"); -+ goto err_put; -+ } -+ -+ err = mtd_read(mtd, offset, sizeof(hdr), &bytes_read, (uint8_t *)&hdr); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset); -+ goto err_put; -+ } -+ -+ size = be32_to_cpu(hdr.size); -+ -+ buf = kmalloc(size + 1, GFP_KERNEL); -+ if (!buf) -+ goto err_put; -+ -+ err = mtd_read(mtd, offset + sizeof(hdr), size, &bytes_read, buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("Failed to read from %s at 0x%zx\n", mtd->name, offset + sizeof(hdr)); -+ goto err_kfree; -+ } -+ -+ buf[size] = '\0'; -+ -+ of_node_put(np); -+ -+ return buf; -+ -+err_kfree: -+ kfree(buf); -+err_put: -+ of_node_put(np); -+ return NULL; -+} -+ -+static int mtd_parser_tplink_safeloader_parse(struct mtd_info *mtd, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ struct mtd_partition *parts; -+ char name[65]; -+ size_t offset; -+ size_t bytes; -+ char *buf; -+ int idx; -+ int err; -+ -+ parts = kcalloc(TPLINK_SAFELOADER_MAX_PARTS, sizeof(*parts), GFP_KERNEL); -+ if (!parts) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ buf = mtd_parser_tplink_safeloader_read_table(mtd); -+ if (!buf) { -+ err = -ENOENT; -+ goto err_out; -+ } -+ -+ for (idx = 0, offset = TPLINK_SAFELOADER_DATA_OFFSET; -+ idx < TPLINK_SAFELOADER_MAX_PARTS && -+ sscanf(buf + offset, "partition %64s base 0x%llx size 0x%llx%zn\n", -+ name, &parts[idx].offset, &parts[idx].size, &bytes) == 3; -+ idx++, offset += bytes + 1) { -+ parts[idx].name = kstrdup(name, GFP_KERNEL); -+ if (!parts[idx].name) { -+ err = -ENOMEM; -+ goto err_free; -+ } -+ } -+ -+ if (idx == TPLINK_SAFELOADER_MAX_PARTS) -+ pr_warn("Reached maximum number of partitions!\n"); -+ -+ kfree(buf); -+ -+ *pparts = parts; -+ -+ return idx; -+ -+err_free: -+ for (idx -= 1; idx >= 0; idx--) -+ kfree(parts[idx].name); -+err_out: -+ return err; -+}; -+ -+static void mtd_parser_tplink_safeloader_cleanup(const struct mtd_partition *pparts, -+ int nr_parts) -+{ -+ int i; -+ -+ for (i = 0; i < nr_parts; i++) -+ kfree(pparts[i].name); -+ -+ kfree(pparts); -+} -+ -+static const struct of_device_id mtd_parser_tplink_safeloader_of_match_table[] = { -+ { .compatible = "tplink,safeloader-partitions" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mtd_parser_tplink_safeloader_of_match_table); -+ -+static struct mtd_part_parser mtd_parser_tplink_safeloader = { -+ .parse_fn = mtd_parser_tplink_safeloader_parse, -+ .cleanup = mtd_parser_tplink_safeloader_cleanup, -+ .name = "tplink-safeloader", -+ .of_match_table = mtd_parser_tplink_safeloader_of_match_table, -+}; -+module_mtd_part_parser(mtd_parser_tplink_safeloader); -+ -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch b/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch deleted file mode 100644 index 7dbc271725..0000000000 --- a/target/linux/generic/backport-6.6/423-v6.3-mtd-spinand-macronix-use-scratch-buffer-for-DMA-oper.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ebed787a0becb9354f0a23620a5130cccd6c730c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 19 Jan 2023 03:45:43 +0000 -Subject: [PATCH] mtd: spinand: macronix: use scratch buffer for DMA operation - -The mx35lf1ge4ab_get_eccsr() function uses an SPI DMA operation to -read the eccsr, hence the buffer should not be on stack. Since commit -380583227c0c7f ("spi: spi-mem: Add extra sanity checks on the op param") -the kernel emmits a warning and blocks such operations. - -Use the scratch buffer to get eccsr instead of trying to directly read -into a stack-allocated variable. - -Signed-off-by: Daniel Golle -Reviewed-by: Dhruva Gole -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/Y8i85zM0u4XdM46z@makrotopia.org ---- - drivers/mtd/nand/spi/macronix.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/nand/spi/macronix.c -+++ b/drivers/mtd/nand/spi/macronix.c -@@ -83,9 +83,10 @@ static int mx35lf1ge4ab_ecc_get_status(s - * in order to avoid forcing the wear-leveling layer to move - * data around if it's not necessary. - */ -- if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) -+ if (mx35lf1ge4ab_get_eccsr(spinand, spinand->scratchbuf)) - return nanddev_get_ecc_conf(nand)->strength; - -+ eccsr = *spinand->scratchbuf; - if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || - !eccsr)) - return nanddev_get_ecc_conf(nand)->strength; diff --git a/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch b/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch deleted file mode 100644 index 657404196d..0000000000 --- a/target/linux/generic/backport-6.6/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 1ecf9e390452e73a362ea7fbde8f3f0db83de856 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 22 Dec 2022 19:33:04 +0000 -Subject: [PATCH] mtd: ubi: wire-up parent MTD device - -Wire up the device parent pointer of UBI devices to their lower MTD -device, typically an MTD partition or whole-chip device. - -The most noticeable change is that in sysfs, previously ubi devices -would be could in /sys/devices/virtual/ubi while after this change they -would be correctly attached to their parent MTD device, e.g. - -/sys/devices/platform/1100d000.spi/spi_master/spi1/spi1.0/mtd/mtd2/ubi0. - -Locating UBI devices using /sys/class/ubi/ of course still works as -well. - -Signed-off-by: Daniel Golle -Signed-off-by: Richard Weinberger ---- - drivers/mtd/ubi/build.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/mtd/ubi/build.c -+++ b/drivers/mtd/ubi/build.c -@@ -929,6 +929,7 @@ int ubi_attach_mtd_dev(struct mtd_info * - ubi->dev.release = dev_release; - ubi->dev.class = &ubi_class; - ubi->dev.groups = ubi_dev_groups; -+ ubi->dev.parent = &mtd->dev; - - ubi->mtd = mtd; - ubi->ubi_num = ubi_num; diff --git a/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch b/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch deleted file mode 100644 index 48bf986118..0000000000 --- a/target/linux/generic/backport-6.6/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 05b8773ca33253ea562be145cf3145b05ef19f86 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 22 Dec 2022 19:33:31 +0000 -Subject: [PATCH] mtd: ubi: block: wire-up device parent - -ubiblock devices were previously only identifyable by their name, but -not connected to their parent UBI volume device e.g. in sysfs. -Properly parent ubiblock device as descendant of a UBI volume device -to reflect device model hierachy. - -Signed-off-by: Daniel Golle -Signed-off-by: Richard Weinberger ---- - drivers/mtd/ubi/block.c | 2 +- - drivers/mtd/ubi/kapi.c | 1 + - include/linux/mtd/ubi.h | 1 + - 3 files changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/ubi/block.c -+++ b/drivers/mtd/ubi/block.c -@@ -452,7 +452,7 @@ int ubiblock_create(struct ubi_volume_in - list_add_tail(&dev->list, &ubiblock_devices); - - /* Must be the last step: anyone can call file ops from now on */ -- ret = add_disk(dev->gd); -+ ret = device_add_disk(vi->dev, dev->gd, NULL); - if (ret) - goto out_destroy_wq; - ---- a/drivers/mtd/ubi/kapi.c -+++ b/drivers/mtd/ubi/kapi.c -@@ -79,6 +79,7 @@ void ubi_do_get_volume_info(struct ubi_d - vi->name_len = vol->name_len; - vi->name = vol->name; - vi->cdev = vol->cdev.dev; -+ vi->dev = &vol->dev; - } - - /** ---- a/include/linux/mtd/ubi.h -+++ b/include/linux/mtd/ubi.h -@@ -110,6 +110,7 @@ struct ubi_volume_info { - int name_len; - const char *name; - dev_t cdev; -+ struct device *dev; - }; - - /** diff --git a/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch b/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch deleted file mode 100644 index 9ddda420ac..0000000000 --- a/target/linux/generic/backport-6.6/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 281f7a6c1a33fffcde32001bacbb4f672140fbf9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Wed, 8 Mar 2023 09:20:21 +0100 -Subject: [PATCH] mtd: core: prepare mtd_otp_nvmem_add() to handle - -EPROBE_DEFER - -NVMEM soon will get the ability for nvmem layouts and these might -not be ready when nvmem_register() is called and thus it might -return -EPROBE_DEFER. Don't print the error message in this case. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20230308082021.870459-4-michael@walle.cc ---- - drivers/mtd/mtdcore.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -953,8 +953,8 @@ static int mtd_otp_nvmem_add(struct mtd_ - nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, - mtd_nvmem_user_otp_reg_read); - if (IS_ERR(nvmem)) { -- dev_err(dev, "Failed to register OTP NVMEM device\n"); -- return PTR_ERR(nvmem); -+ err = PTR_ERR(nvmem); -+ goto err; - } - mtd->otp_user_nvmem = nvmem; - } -@@ -971,7 +971,6 @@ static int mtd_otp_nvmem_add(struct mtd_ - nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, - mtd_nvmem_fact_otp_reg_read); - if (IS_ERR(nvmem)) { -- dev_err(dev, "Failed to register OTP NVMEM device\n"); - err = PTR_ERR(nvmem); - goto err; - } -@@ -983,7 +982,7 @@ static int mtd_otp_nvmem_add(struct mtd_ - - err: - nvmem_unregister(mtd->otp_user_nvmem); -- return err; -+ return dev_err_probe(dev, err, "Failed to register OTP NVMEM device\n"); - } - - /** diff --git a/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch b/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch deleted file mode 100644 index 28b7b4383e..0000000000 --- a/target/linux/generic/backport-6.6/611-v6.3-net-add-helper-eth_addr_add.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 7390609b0121a1b982c5ecdfcd72dc328e5784ee Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:42 +0000 -Subject: [PATCH] net: add helper eth_addr_add() - -Add a helper to add an offset to a ethernet address. This comes in handy -if you have a base ethernet address for multiple interfaces. - -Signed-off-by: Michael Walle -Reviewed-by: Andrew Lunn -Acked-by: Jakub Kicinski -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/etherdevice.h | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/include/linux/etherdevice.h -+++ b/include/linux/etherdevice.h -@@ -508,6 +508,20 @@ static inline void eth_addr_inc(u8 *addr - } - - /** -+ * eth_addr_add() - Add (or subtract) an offset to/from the given MAC address. -+ * -+ * @offset: Offset to add. -+ * @addr: Pointer to a six-byte array containing Ethernet address to increment. -+ */ -+static inline void eth_addr_add(u8 *addr, long offset) -+{ -+ u64 u = ether_addr_to_u64(addr); -+ -+ u += offset; -+ u64_to_ether_addr(u, addr); -+} -+ -+/** - * is_etherdev_addr - Tell if given Ethernet address belongs to the device. - * @dev: Pointer to a device structure - * @addr: Pointer to a six-byte array containing the Ethernet address diff --git a/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch b/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch deleted file mode 100644 index 56e14c5c0a..0000000000 --- a/target/linux/generic/backport-6.6/701-net-next-net-sfp-add-quirk-for-Fiberstone-GPON-ONU-34-20BI.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d387e34fec407f881fdf165b5d7ec128ebff362f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 19 Sep 2023 14:47:20 +0200 -Subject: [PATCH] net: sfp: add quirk for Fiberstone GPON-ONU-34-20BI - -Fiberstone GPON-ONU-34-20B can operate at 2500base-X, but report 1.2GBd -NRZ in their EEPROM. - -The module also require the ignore tx fault fixup similar to Huawei MA5671A -as it gets disabled on error messages with serial redirection enabled. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20230919124720.8210-1-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/sfp.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -393,6 +393,11 @@ static const struct sfp_quirk sfp_quirks - SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, - sfp_fixup_long_startup), - -+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd -+ // NRZ in their EEPROM -+ SFP_QUIRK("FS", "GPON-ONU-34-20BI", sfp_quirk_2500basex, -+ sfp_fixup_ignore_tx_fault), -+ - SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp), - - // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports diff --git a/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch deleted file mode 100644 index ff186742ba..0000000000 --- a/target/linux/generic/backport-6.6/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch +++ /dev/null @@ -1,326 +0,0 @@ -From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 9 Jan 2023 16:30:41 +0100 -Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers - -Currently C22 and C45 transactions are mixed over a combined API calls -which make use of a special bit in the reg address to indicate if a -C45 transaction should be performed. This makes it impossible to know -if the bus driver actually supports C45. Additionally, many C22 only -drivers don't return -EOPNOTSUPP when asked to perform a C45 -transaction, they mistaking perform a C22 transaction. - -This is the first step to cleanly separate C22 from C45. To maintain -backwards compatibility until all drivers which are capable of -performing C45 are converted to this new API, the helper functions -will fall back to the older API if the new API is not -supported. Eventually this fallback will be removed. - -Signed-off-by: Andrew Lunn -Signed-off-by: Michael Walle -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ - include/linux/mdio.h | 39 ++++---- - include/linux/phy.h | 5 + - 3 files changed, 214 insertions(+), 19 deletions(-) - ---- a/drivers/net/phy/mdio_bus.c -+++ b/drivers/net/phy/mdio_bus.c -@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ - EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); - - /** -+ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to read -+ * -+ * Read a MDIO bus register. Caller must hold the mdio bus lock. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) -+{ -+ int retval; -+ -+ lockdep_assert_held_once(&bus->mdio_lock); -+ -+ if (bus->read_c45) -+ retval = bus->read_c45(bus, addr, devad, regnum); -+ else -+ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); -+ -+ trace_mdio_access(bus, 1, addr, regnum, retval, retval); -+ mdiobus_stats_acct(&bus->stats[addr], true, retval); -+ -+ return retval; -+} -+EXPORT_SYMBOL(__mdiobus_c45_read); -+ -+/** -+ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * Write a MDIO bus register. Caller must hold the mdio bus lock. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val) -+{ -+ int err; -+ -+ lockdep_assert_held_once(&bus->mdio_lock); -+ -+ if (bus->write_c45) -+ err = bus->write_c45(bus, addr, devad, regnum, val); -+ else -+ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), -+ val); -+ -+ trace_mdio_access(bus, 0, addr, regnum, val, err); -+ mdiobus_stats_acct(&bus->stats[addr], false, err); -+ -+ return err; -+} -+EXPORT_SYMBOL(__mdiobus_c45_write); -+ -+/** -+ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to modify -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * Read, modify, and if any change, write the register value back to the -+ * device. Any error returns a negative number. -+ * -+ * NOTE: MUST NOT be called from interrupt context. -+ */ -+static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, -+ int devad, u32 regnum, u16 mask, -+ u16 set) -+{ -+ int new, ret; -+ -+ ret = __mdiobus_c45_read(bus, addr, devad, regnum); -+ if (ret < 0) -+ return ret; -+ -+ new = (ret & ~mask) | set; -+ if (new == ret) -+ return 0; -+ -+ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); -+ -+ return ret < 0 ? ret : 1; -+} -+ -+/** - * mdiobus_read_nested - Nested version of the mdiobus_read function - * @bus: the mii_bus struct - * @addr: the phy address -@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in - EXPORT_SYMBOL(mdiobus_read); - - /** -+ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to read -+ * -+ * NOTE: MUST NOT be called from interrupt context, -+ * because the bus read/write functions may wait for an interrupt -+ * to conclude the operation. -+ */ -+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) -+{ -+ int retval; -+ -+ mutex_lock(&bus->mdio_lock); -+ retval = __mdiobus_c45_read(bus, addr, devad, regnum); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return retval; -+} -+EXPORT_SYMBOL(mdiobus_c45_read); -+ -+/** - * mdiobus_write_nested - Nested version of the mdiobus_write function - * @bus: the mii_bus struct - * @addr: the phy address -@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i - EXPORT_SYMBOL(mdiobus_write); - - /** -+ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * NOTE: MUST NOT be called from interrupt context, -+ * because the bus read/write functions may wait for an interrupt -+ * to conclude the operation. -+ */ -+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL(mdiobus_c45_write); -+ -+/** - * mdiobus_modify - Convenience function for modifying a given mdio device - * register - * @bus: the mii_bus struct -@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, - EXPORT_SYMBOL_GPL(mdiobus_modify); - - /** -+ * mdiobus_c45_modify - Convenience function for modifying a given mdio device -+ * register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 mask, u16 set) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, -+ mask, set); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err < 0 ? err : 0; -+} -+EXPORT_SYMBOL_GPL(mdiobus_c45_modify); -+ -+/** - * mdiobus_modify_changed - Convenience function for modifying a given mdio - * device register and returning if it changed - * @bus: the mii_bus struct -@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu - EXPORT_SYMBOL_GPL(mdiobus_modify_changed); - - /** -+ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio -+ * device register and returning if it changed -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @devad: device address to read -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, -+ u32 regnum, u16 mask, u16 set) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); -+ -+/** - * mdio_bus_match - determine if given MDIO driver supports the given - * MDIO device - * @dev: target MDIO device ---- a/include/linux/mdio.h -+++ b/include/linux/mdio.h -@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, - u16 set); - int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, - u16 mask, u16 set); -+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); -+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); -+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val); -+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 val); -+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, -+ u16 mask, u16 set); -+ -+int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, -+ u32 regnum, u16 mask, u16 set); - - static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) - { -@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 - return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); - } - --static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, -- u16 regnum) --{ -- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); --} -- --static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, -- u16 regnum, u16 val) --{ -- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), -- val); --} -- --static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, -- u16 regnum) -+static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, -+ u32 regnum, u16 mask, u16 set) - { -- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); -+ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, -+ mask, set); - } - --static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, -- u16 regnum, u16 val) -+static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, -+ int devad, u32 regnum, u16 mask, -+ u16 set) - { -- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); -+ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, -+ regnum, mask, set); - } - - int mdiobus_register_device(struct mdio_device *mdiodev); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -364,6 +364,11 @@ struct mii_bus { - int (*read)(struct mii_bus *bus, int addr, int regnum); - /** @write: Perform a write transfer on the bus */ - int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); -+ /** @read_c45: Perform a C45 read transfer on the bus */ -+ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); -+ /** @write_c45: Perform a C45 write transfer on the bus */ -+ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, -+ int regnum, u16 val); - /** @reset: Perform a reset of the bus */ - int (*reset)(struct mii_bus *bus); - diff --git a/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch deleted file mode 100644 index 80210e6da1..0000000000 --- a/target/linux/generic/backport-6.6/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 11 Aug 2023 13:10:07 +0200 -Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode - -The PSGMII interface is similar to QSGMII. The main difference -is that the PSGMII interface combines five SGMII lines into a -single link while in QSGMII only four lines are combined. - -Similarly to the QSGMII, this interface mode might also needs -special handling within the MAC driver. - -It is commonly used by Qualcomm with their QCA807x PHY series and -modern WiSoC-s. - -Add definitions for the PHY layer to allow to express this type -of connection between the MAC and PHY. - -Signed-off-by: Gabor Juhos -Signed-off-by: Robert Marko -Signed-off-by: David S. Miller ---- - Documentation/networking/phy.rst | 4 ++++ - drivers/net/phy/phy-core.c | 2 ++ - drivers/net/phy/phylink.c | 3 +++ - include/linux/phy.h | 4 ++++ - 4 files changed, 13 insertions(+) - ---- a/Documentation/networking/phy.rst -+++ b/Documentation/networking/phy.rst -@@ -323,6 +323,10 @@ Some of the interface modes are describe - contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this - interface mode has different autonegotiation and only supports full duplex. - -+``PHY_INTERFACE_MODE_PSGMII`` -+ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 -+ SGMII lines into a single link compared to 4 on QSGMII. -+ - Pause frames / flow control - =========================== - ---- a/drivers/net/phy/phy-core.c -+++ b/drivers/net/phy/phy-core.c -@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - return 4; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return 5; - case PHY_INTERFACE_MODE_MAX: - WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); - return 0; ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy - - switch (pl->link_config.interface) { - case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_RGMII: ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr - * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface - * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface - * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax -+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII - * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII - * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII - * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX -@@ -140,6 +141,7 @@ typedef enum { - PHY_INTERFACE_MODE_XGMII, - PHY_INTERFACE_MODE_XLGMII, - PHY_INTERFACE_MODE_MOCA, -+ PHY_INTERFACE_MODE_PSGMII, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TRGMII, - PHY_INTERFACE_MODE_100BASEX, -@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ - return "xlgmii"; - case PHY_INTERFACE_MODE_MOCA: - return "moca"; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return "psgmii"; - case PHY_INTERFACE_MODE_QSGMII: - return "qsgmii"; - case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch deleted file mode 100644 index 7cacb71b18..0000000000 --- a/target/linux/generic/backport-6.6/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Thu, 16 Mar 2023 14:08:26 +0200 -Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used - -of_gpio.h in this driver is solely used as a proxy to other headers. -This is incorrect usage of the of_gpio.h. Replace it .h with what -indeed is used in the code. - -Signed-off-by: Andy Shevchenko -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -13,12 +13,11 @@ - #include - #include - #include --#include - #include --#include - #include - #include - #include -+#include - #include - #include - #include diff --git a/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch deleted file mode 100644 index dab4928960..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:19 +0800 -Subject: [PATCH 1/6] net: phy: at803x: support qca8081 - genphy_c45_pma_read_abilities - -qca8081 PHY supports to use genphy_c45_pma_read_abilities for -getting the PHY features supported except for the autoneg ability - -but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it -manually after calling genphy_c45_pma_read_abilities. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- - 1 file changed, 18 insertions(+), 10 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph - if (err) - return err; - -- if (phydev->drv->phy_id == QCA8081_PHY_ID) { -- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); -- if (err < 0) -- return err; -- -- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, -- err & MDIO_PMA_NG_EXTABLE_2_5GBT); -- } -- - if (phydev->drv->phy_id != ATH8031_PHY_ID) - return 0; - -@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status - return 0; - } - -+static int qca808x_get_features(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = genphy_c45_pma_read_abilities(phydev); -+ if (ret) -+ return ret; -+ -+ /* The autoneg ability is not existed in bit3 of MMD7.1, -+ * but it is supported by qca808x PHY, so we add it here -+ * manually. -+ */ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); -+ -+ return 0; -+} -+ - static struct phy_driver at803x_driver[] = { - { - /* Qualcomm Atheros AR8035 */ -@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] - .set_tunable = at803x_set_tunable, - .set_wol = at803x_set_wol, - .get_wol = at803x_get_wol, -- .get_features = at803x_get_features, -+ .get_features = qca808x_get_features, - .config_aneg = at803x_config_aneg, - .suspend = genphy_suspend, - .resume = genphy_resume, diff --git a/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch deleted file mode 100644 index 28874068ce..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch +++ /dev/null @@ -1,73 +0,0 @@ -From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:20 +0800 -Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function - -merge the seed enablement and seed value configuration into -one function, since the random seed value is needed to be -configured when the seed is enabled. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 29 +++++++++-------------------- - 1 file changed, 9 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf - return 0; - } - --static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) --{ -- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); -- -- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -- QCA808X_MASTER_SLAVE_SEED_CFG, -- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); --} -- - static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) - { -- u16 seed_enable = 0; -+ u16 seed_value; - -- if (enable) -- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; -+ if (!enable) -+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -+ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); - -+ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, -- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); -+ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, -+ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | -+ QCA808X_MASTER_SLAVE_SEED_ENABLE); - } - - static int qca808x_config_init(struct phy_device *phydev) -@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_random_seed_set(phydev); -- if (ret) -- return ret; -- -- /* Enable seed */ -+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ - ret = qca808x_phy_ms_seed_enable(phydev, true); - if (ret) - return ret; -@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph - if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { - qca808x_phy_ms_seed_enable(phydev, false); - } else { -- qca808x_phy_ms_random_seed_set(phydev); - qca808x_phy_ms_seed_enable(phydev, true); - } - } diff --git a/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch deleted file mode 100644 index b91d2cab30..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:21 +0800 -Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally - -qca8081 is the single port PHY, the slave prefer mode is used -by default. - -if the phy master perfer mode is configured, the slave seed -configuration should not be enabled, since the slave seed -enablement is for making PHY linked as slave mode easily. - -disable slave seed if the master mode is preferred. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- - 1 file changed, 20 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st - QCA808X_MASTER_SLAVE_SEED_ENABLE); - } - -+static bool qca808x_is_prefer_master(struct phy_device *phydev) -+{ -+ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || -+ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); -+} -+ - static int qca808x_config_init(struct phy_device *phydev) - { - int ret; -@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_seed_enable(phydev, true); -- if (ret) -+ ret = genphy_read_master_slave(phydev); -+ if (ret < 0) - return ret; - -+ if (!qca808x_is_prefer_master(phydev)) { -+ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (ret) -+ return ret; -+ } -+ - /* Configure adc threshold as 100mv for the link 10M */ - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, - QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); -@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph - phydev->interface = PHY_INTERFACE_MODE_SGMII; - } else { - /* generate seed as a lower random value to make PHY linked as SLAVE easily, -- * except for master/slave configuration fault detected. -+ * except for master/slave configuration fault detected or the master mode -+ * preferred. -+ * - * the reason for not putting this code into the function link_change_notify is - * the corner case where the link partner is also the qca8081 PHY and the seed - * value is configured as the same value, the link can't be up and no link change - * occurs. - */ -- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { -+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -+ qca808x_is_prefer_master(phydev)) { - qca808x_phy_ms_seed_enable(phydev, false); - } else { - qca808x_phy_ms_seed_enable(phydev, true); diff --git a/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch deleted file mode 100644 index b8db89d853..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch +++ /dev/null @@ -1,48 +0,0 @@ -From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:22 +0800 -Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type - -The qca8081 1G chip version does not support 2.5 capability, which -is distinguished from qca8081 2.5G chip according to the bit0 of -register mmd7.0x901d, the 1G version chip also has the same PHY ID -as the normal qca8081 2.5G chip. - -Signed-off-by: Luo Jie -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -272,6 +272,10 @@ - #define QCA808X_CDT_STATUS_STAT_OPEN 2 - #define QCA808X_CDT_STATUS_STAT_SHORT 3 - -+/* QCA808X 1G chip type */ -+#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d -+#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); -@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p - */ - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); - -+ /* As for the qca8081 1G version chip, the 2500baseT ability is also -+ * existed in the bit0 of MMD1.21, we need to remove it manually if -+ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. -+ */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); -+ if (ret < 0) -+ return ret; -+ -+ if (QCA808X_PHY_CHIP_TYPE_1G & ret) -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch deleted file mode 100644 index b54a86e5f5..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch +++ /dev/null @@ -1,98 +0,0 @@ -From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:23 +0800 -Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and - slave seed config - -The fast retrain and slave seed configs are only applicable when the 2.5G -ability is supported. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- - 1 file changed, 32 insertions(+), 18 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str - (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); - } - -+static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) -+{ -+ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); -+} -+ - static int qca808x_config_init(struct phy_device *phydev) - { - int ret; -@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph - if (ret) - return ret; - -- /* Config the fast retrain for the link 2500M */ -- ret = qca808x_phy_fast_retrain_config(phydev); -- if (ret) -- return ret; -- -- ret = genphy_read_master_slave(phydev); -- if (ret < 0) -- return ret; -- -- if (!qca808x_is_prefer_master(phydev)) { -- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ -- ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { -+ /* Config the fast retrain for the link 2500M */ -+ ret = qca808x_phy_fast_retrain_config(phydev); - if (ret) - return ret; -+ -+ ret = genphy_read_master_slave(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (!qca808x_is_prefer_master(phydev)) { -+ /* Enable seed and configure lower ramdom seed to make phy -+ * linked as slave mode. -+ */ -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ if (ret) -+ return ret; -+ } - } - - /* Configure adc threshold as 100mv for the link 10M */ -@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph - * value is configured as the same value, the link can't be up and no link change - * occurs. - */ -- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -- qca808x_is_prefer_master(phydev)) { -- qca808x_phy_ms_seed_enable(phydev, false); -- } else { -- qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { -+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || -+ qca808x_is_prefer_master(phydev)) { -+ qca808x_phy_ms_seed_enable(phydev, false); -+ } else { -+ qca808x_phy_ms_seed_enable(phydev, true); -+ } - } - } - -@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy - if (ret < 0) - return ret; - -- return qca808x_phy_ms_seed_enable(phydev, true); -+ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) -+ ret = qca808x_phy_ms_seed_enable(phydev, true); -+ -+ return ret; - } - - static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch deleted file mode 100644 index e382cf7876..0000000000 --- a/target/linux/generic/backport-6.6/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 16 Jul 2023 16:49:24 +0800 -Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link - changed - -The qca8081 sgmii fifo needs to be reset on link down and -released on the link up in case of any abnormal issue -such as the packet blocked on the PHY. - -Signed-off-by: Luo Jie -Reviewed-by: Andrew Lunn -Reviewed-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -276,6 +276,9 @@ - #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d - #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) - -+#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 -+#define QCA8081_PHY_FIFO_RSTN BIT(11) -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); -@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p - return 0; - } - -+static void qca808x_link_change_notify(struct phy_device *phydev) -+{ -+ /* Assert interface sgmii fifo on link down, deassert it on link up, -+ * the interface device address is always phy address added by 1. -+ */ -+ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, -+ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, -+ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); -+} -+ - static struct phy_driver at803x_driver[] = { - { - /* Qualcomm Atheros AR8035 */ -@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] - .soft_reset = qca808x_soft_reset, - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, -+ .link_change_notify = qca808x_link_change_notify, - }, }; - - module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch deleted file mode 100644 index d56a142451..0000000000 --- a/target/linux/generic/backport-6.6/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 4765a9722e09765866e131ec31f7b9cf4c1f4854 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:50 +0000 -Subject: [PATCH] net: pcs: add driver for MediaTek SGMII PCS - -The SGMII core found in several MediaTek SoCs is identical to what can -also be found in MediaTek's MT7531 Ethernet switch IC. -As this has not always been clear, both drivers developed different -implementations to deal with the PCS. -Recently Alexander Couzens pointed out this fact which lead to the -development of this shared driver. - -Add a dedicated driver, mostly by copying the code now found in the -Ethernet driver. The now redundant code will be removed by a follow-up -commit. - -Suggested-by: Alexander Couzens -Suggested-by: Russell King (Oracle) -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich -Reviewed-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - MAINTAINERS | 8 + - drivers/net/pcs/Kconfig | 7 + - drivers/net/pcs/Makefile | 1 + - drivers/net/pcs/pcs-mtk-lynxi.c | 305 ++++++++++++++++++++++++++++++ - include/linux/pcs/pcs-mtk-lynxi.h | 13 ++ - 5 files changed, 334 insertions(+) - create mode 100644 drivers/net/pcs/pcs-mtk-lynxi.c - create mode 100644 include/linux/pcs/pcs-mtk-lynxi.h - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/ethernet/mediatek/ - -+MEDIATEK ETHERNET PCS DRIVER -+M: Alexander Couzens -+M: Daniel Golle -+L: netdev@vger.kernel.org -+S: Maintained -+F: drivers/net/pcs/pcs-mtk-lynxi.c -+F: include/linux/pcs/pcs-mtk-lynxi.h -+ - MEDIATEK I2C CONTROLLER DRIVER - M: Qii Wang - L: linux-i2c@vger.kernel.org ---- a/drivers/net/pcs/Kconfig -+++ b/drivers/net/pcs/Kconfig -@@ -32,4 +32,11 @@ config PCS_ALTERA_TSE - This module provides helper functions for the Altera Triple Speed - Ethernet SGMII PCS, that can be found on the Intel Socfpga family. - -+config PCS_MTK_LYNXI -+ tristate -+ select REGMAP -+ help -+ This module provides helpers to phylink for managing the LynxI PCS -+ which is part of MediaTek's SoC and Ethernet switch ICs. -+ - endmenu ---- a/drivers/net/pcs/Makefile -+++ b/drivers/net/pcs/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o - obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o - obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o - obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o -+obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o ---- /dev/null -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -0,0 +1,305 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018-2019 MediaTek Inc. -+/* A library for MediaTek SGMII circuit -+ * -+ * Author: Sean Wang -+ * Author: Alexander Couzens -+ * Author: Daniel Golle -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* SGMII subsystem config registers */ -+/* BMCR (low 16) BMSR (high 16) */ -+#define SGMSYS_PCS_CONTROL_1 0x0 -+#define SGMII_BMCR GENMASK(15, 0) -+#define SGMII_BMSR GENMASK(31, 16) -+ -+#define SGMSYS_PCS_DEVICE_ID 0x4 -+#define SGMII_LYNXI_DEV_ID 0x4d544950 -+ -+#define SGMSYS_PCS_ADVERTISE 0x8 -+#define SGMII_ADVERTISE GENMASK(15, 0) -+#define SGMII_LPA GENMASK(31, 16) -+ -+#define SGMSYS_PCS_SCRATCH 0x14 -+#define SGMII_DEV_VERSION GENMASK(31, 16) -+ -+/* Register to programmable link timer, the unit in 2 * 8ns */ -+#define SGMSYS_PCS_LINK_TIMER 0x18 -+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) -+#define SGMII_LINK_TIMER_VAL(ns) FIELD_PREP(SGMII_LINK_TIMER_MASK, \ -+ ((ns) / 2 / 8)) -+ -+/* Register to control remote fault */ -+#define SGMSYS_SGMII_MODE 0x20 -+#define SGMII_IF_MODE_SGMII BIT(0) -+#define SGMII_SPEED_DUPLEX_AN BIT(1) -+#define SGMII_SPEED_MASK GENMASK(3, 2) -+#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) -+#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) -+#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) -+#define SGMII_DUPLEX_HALF BIT(4) -+#define SGMII_REMOTE_FAULT_DIS BIT(8) -+ -+/* Register to reset SGMII design */ -+#define SGMSYS_RESERVED_0 0x34 -+#define SGMII_SW_RESET BIT(0) -+ -+/* Register to set SGMII speed, ANA RG_ Control Signals III */ -+#define SGMII_PHY_SPEED_MASK GENMASK(3, 2) -+#define SGMII_PHY_SPEED_1_25G FIELD_PREP(SGMII_PHY_SPEED_MASK, 0) -+#define SGMII_PHY_SPEED_3_125G FIELD_PREP(SGMII_PHY_SPEED_MASK, 1) -+ -+/* Register to power up QPHY */ -+#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 -+#define SGMII_PHYA_PWD BIT(4) -+ -+/* Register to QPHY wrapper control */ -+#define SGMSYS_QPHY_WRAP_CTRL 0xec -+#define SGMII_PN_SWAP_MASK GENMASK(1, 0) -+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) -+ -+/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated -+ * data -+ * @regmap: The register map pointing at the range used to setup -+ * SGMII modes -+ * @dev: Pointer to device owning the PCS -+ * @ana_rgc3: The offset of register ANA_RGC3 relative to regmap -+ * @interface: Currently configured interface mode -+ * @pcs: Phylink PCS structure -+ * @flags: Flags indicating hardware properties -+ */ -+struct mtk_pcs_lynxi { -+ struct regmap *regmap; -+ u32 ana_rgc3; -+ phy_interface_t interface; -+ struct phylink_pcs pcs; -+ u32 flags; -+}; -+ -+static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mtk_pcs_lynxi, pcs); -+} -+ -+static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ unsigned int bm, adv; -+ -+ /* Read the BMSR and LPA */ -+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -+ -+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -+ FIELD_GET(SGMII_LPA, adv)); -+} -+ -+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ bool mode_changed = false, changed, use_an; -+ unsigned int rgc3, sgm_mode, bmcr; -+ int advertise, link_timer; -+ -+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -+ advertising); -+ if (advertise < 0) -+ return advertise; -+ -+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -+ * we assume that fixes it's speed at bitrate = line rate (in -+ * other words, 1000Mbps or 2500Mbps). -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII) { -+ sgm_mode = SGMII_IF_MODE_SGMII; -+ if (phylink_autoneg_inband(mode)) { -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS | -+ SGMII_SPEED_DUPLEX_AN; -+ use_an = true; -+ } else { -+ use_an = false; -+ } -+ } else if (phylink_autoneg_inband(mode)) { -+ /* 1000base-X or 2500base-X autoneg */ -+ sgm_mode = SGMII_REMOTE_FAULT_DIS; -+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising); -+ } else { -+ /* 1000base-X or 2500base-X without autoneg */ -+ sgm_mode = 0; -+ use_an = false; -+ } -+ -+ if (use_an) -+ bmcr = BMCR_ANENABLE; -+ else -+ bmcr = 0; -+ -+ if (mpcs->interface != interface) { -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ -+ /* PHYA power down */ -+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD); -+ -+ /* Reset SGMII PCS state */ -+ regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, -+ SGMII_SW_RESET); -+ -+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -+ SGMII_PN_SWAP_MASK, -+ SGMII_PN_SWAP_TX_RX); -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = SGMII_PHY_SPEED_3_125G; -+ else -+ rgc3 = SGMII_PHY_SPEED_1_25G; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ SGMII_PHY_SPEED_MASK, rgc3); -+ -+ /* Setup the link timer */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, -+ SGMII_LINK_TIMER_VAL(link_timer)); -+ -+ mpcs->interface = interface; -+ mode_changed = true; -+ } -+ -+ /* Update the advertisement, noting whether it has changed */ -+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -+ SGMII_ADVERTISE, advertise, &changed); -+ -+ /* Update the sgmsys mode register */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -+ SGMII_IF_MODE_SGMII, sgm_mode); -+ -+ /* Update the BMCR */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ BMCR_ANENABLE, bmcr); -+ -+ /* Release PHYA power down state -+ * Only removing bit SGMII_PHYA_PWD isn't enough. -+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -+ * prevents SGMII from working. The SGMII still shows link but no traffic -+ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -+ * taken from a good working state of the SGMII interface. -+ * Unknown how much the QPHY needs but it is racy without a sleep. -+ * Tested on mt7622 & mt7986. -+ */ -+ usleep_range(50, 100); -+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); -+ -+ return changed || mode_changed; -+} -+ -+static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ -+ regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); -+} -+ -+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, int speed, -+ int duplex) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ unsigned int sgm_mode; -+ -+ if (!phylink_autoneg_inband(mode)) { -+ /* Force the speed and duplex setting */ -+ if (speed == SPEED_10) -+ sgm_mode = SGMII_SPEED_10; -+ else if (speed == SPEED_100) -+ sgm_mode = SGMII_SPEED_100; -+ else -+ sgm_mode = SGMII_SPEED_1000; -+ -+ if (duplex != DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_HALF; -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, -+ sgm_mode); -+ } -+} -+ -+static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { -+ .pcs_get_state = mtk_pcs_lynxi_get_state, -+ .pcs_config = mtk_pcs_lynxi_config, -+ .pcs_an_restart = mtk_pcs_lynxi_restart_an, -+ .pcs_link_up = mtk_pcs_lynxi_link_up, -+}; -+ -+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, -+ struct regmap *regmap, u32 ana_rgc3, -+ u32 flags) -+{ -+ struct mtk_pcs_lynxi *mpcs; -+ u32 id, ver; -+ int ret; -+ -+ ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); -+ if (ret < 0) -+ return NULL; -+ -+ if (id != SGMII_LYNXI_DEV_ID) { -+ dev_err(dev, "unknown PCS device id %08x\n", id); -+ return NULL; -+ } -+ -+ ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); -+ if (ret < 0) -+ return NULL; -+ -+ ver = FIELD_GET(SGMII_DEV_VERSION, ver); -+ if (ver != 0x1) { -+ dev_err(dev, "unknown PCS device version %04x\n", ver); -+ return NULL; -+ } -+ -+ dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, -+ ver); -+ -+ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); -+ if (!mpcs) -+ return NULL; -+ -+ mpcs->ana_rgc3 = ana_rgc3; -+ mpcs->regmap = regmap; -+ mpcs->flags = flags; -+ mpcs->pcs.ops = &mtk_pcs_lynxi_ops; -+ mpcs->pcs.poll = true; -+ mpcs->interface = PHY_INTERFACE_MODE_NA; -+ -+ return &mpcs->pcs; -+} -+EXPORT_SYMBOL(mtk_pcs_lynxi_create); -+ -+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs) -+{ -+ if (!pcs) -+ return; -+ -+ kfree(pcs_to_mtk_pcs_lynxi(pcs)); -+} -+EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); -+ -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/pcs/pcs-mtk-lynxi.h -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __LINUX_PCS_MTK_LYNXI_H -+#define __LINUX_PCS_MTK_LYNXI_H -+ -+#include -+#include -+ -+#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, -+ struct regmap *regmap, -+ u32 ana_rgc3, u32 flags); -+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); -+#endif diff --git a/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch b/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch deleted file mode 100644 index 2886123f2d..0000000000 --- a/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-Add-serdes-support.patch +++ /dev/null @@ -1,103 +0,0 @@ -From affa013f494486079c3c5ad2d00cebc41a3d7445 Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:36 -0400 -Subject: [PATCH 01/21] net: fman: memac: Add serdes support - -This adds support for using a serdes which has to be configured. This is -primarly in preparation for phylink conversion, which will then change the -serdes mode dynamically. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - .../net/ethernet/freescale/fman/fman_memac.c | 49 ++++++++++++++++++- - 1 file changed, 47 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - /* PCS registers */ -@@ -324,6 +325,7 @@ struct fman_mac { - void *fm; - struct fman_rev_info fm_rev_info; - bool basex_if; -+ struct phy *serdes; - struct phy_device *pcsphy; - bool allmulti_enabled; - }; -@@ -1203,17 +1205,56 @@ int memac_initialization(struct mac_devi - } - } - -+ memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); -+ err = PTR_ERR(memac->serdes); -+ if (err == -ENODEV || err == -ENOSYS) { -+ dev_dbg(mac_dev->dev, "could not get (optional) serdes\n"); -+ memac->serdes = NULL; -+ } else if (IS_ERR(memac->serdes)) { -+ dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); -+ goto _return_fm_mac_free; -+ } else { -+ err = phy_init(memac->serdes); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not initialize serdes\n"); -+ goto _return_fm_mac_free; -+ } -+ -+ err = phy_power_on(memac->serdes); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not power on serdes\n"); -+ goto _return_phy_exit; -+ } -+ -+ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -+ memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || -+ memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || -+ memac->phy_if == PHY_INTERFACE_MODE_QSGMII || -+ memac->phy_if == PHY_INTERFACE_MODE_XGMII) { -+ err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -+ memac->phy_if); -+ if (err) { -+ dev_err_probe(mac_dev->dev, err, -+ "could not set serdes mode to %s\n", -+ phy_modes(memac->phy_if)); -+ goto _return_phy_power_off; -+ } -+ } -+ } -+ - if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { - struct phy_device *phy; - - err = of_phy_register_fixed_link(mac_node); - if (err) -- goto _return_fm_mac_free; -+ goto _return_phy_power_off; - - fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); - if (!fixed_link) { - err = -ENOMEM; -- goto _return_fm_mac_free; -+ goto _return_phy_power_off; - } - - mac_dev->phy_node = of_node_get(mac_node); -@@ -1242,6 +1283,10 @@ int memac_initialization(struct mac_devi - - goto _return; - -+_return_phy_power_off: -+ phy_power_off(memac->serdes); -+_return_phy_exit: -+ phy_exit(memac->serdes); - _return_fixed_link_free: - kfree(fixed_link); - _return_fm_mac_free: diff --git a/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch b/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch deleted file mode 100644 index 873debc080..0000000000 --- a/target/linux/generic/backport-6.6/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch +++ /dev/null @@ -1,384 +0,0 @@ -From fe60e7154d3a35af975c5e6570d6ec31aab9a731 Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:37 -0400 -Subject: [PATCH 02/21] net: fman: memac: Use lynx pcs driver - -Although not stated in the datasheet, as far as I can tell PCS for mEMACs -is a "Lynx." By reusing the existing driver, we can remove the PCS -management code from the memac driver. This requires calling some PCS -functions manually which phylink would usually do for us, but we will let -it do that soon. - -One problem is that we don't actually have a PCS for QSGMII. We pretend -that each mEMAC's MDIO bus has four QSGMII PCSs, but this is not the case. -Only the "base" mEMAC's MDIO bus has the four QSGMII PCSs. This is not an -issue yet, because we never get the PCS state. However, it will be once the -conversion to phylink is complete, since the links will appear to never -come up. To get around this, we allow specifying multiple PCSs in pcsphy. -This breaks backwards compatibility with old device trees, but only for -QSGMII. IMO this is the only reasonable way to figure out what the actual -QSGMII PCS is. - -Additionally, we now also support a separate XFI PCS. This can allow the -SerDes driver to set different addresses for the SGMII and XFI PCSs so they -can be accessed at the same time. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/freescale/fman/Kconfig | 3 + - .../net/ethernet/freescale/fman/fman_memac.c | 258 +++++++----------- - 2 files changed, 105 insertions(+), 156 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/Kconfig -+++ b/drivers/net/ethernet/freescale/fman/Kconfig -@@ -4,6 +4,9 @@ config FSL_FMAN - depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST - select GENERIC_ALLOCATOR - select PHYLIB -+ select PHYLINK -+ select PCS -+ select PCS_LYNX - select CRC32 - default n - help ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -11,43 +11,12 @@ - - #include - #include -+#include - #include - #include - #include - #include - --/* PCS registers */ --#define MDIO_SGMII_CR 0x00 --#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 --#define MDIO_SGMII_LINK_TMR_L 0x12 --#define MDIO_SGMII_LINK_TMR_H 0x13 --#define MDIO_SGMII_IF_MODE 0x14 -- --/* SGMII Control defines */ --#define SGMII_CR_AN_EN 0x1000 --#define SGMII_CR_RESTART_AN 0x0200 --#define SGMII_CR_FD 0x0100 --#define SGMII_CR_SPEED_SEL1_1G 0x0040 --#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ -- SGMII_CR_SPEED_SEL1_1G) -- --/* SGMII Device Ability for SGMII defines */ --#define MDIO_SGMII_DEV_ABIL_SGMII_MODE 0x4001 --#define MDIO_SGMII_DEV_ABIL_BASEX_MODE 0x01A0 -- --/* Link timer define */ --#define LINK_TMR_L 0xa120 --#define LINK_TMR_H 0x0007 --#define LINK_TMR_L_BASEX 0xaf08 --#define LINK_TMR_H_BASEX 0x002f -- --/* SGMII IF Mode defines */ --#define IF_MODE_USE_SGMII_AN 0x0002 --#define IF_MODE_SGMII_EN 0x0001 --#define IF_MODE_SGMII_SPEED_100M 0x0004 --#define IF_MODE_SGMII_SPEED_1G 0x0008 --#define IF_MODE_SGMII_DUPLEX_HALF 0x0010 -- - /* Num of additional exact match MAC adr regs */ - #define MEMAC_NUM_OF_PADDRS 7 - -@@ -326,7 +295,9 @@ struct fman_mac { - struct fman_rev_info fm_rev_info; - bool basex_if; - struct phy *serdes; -- struct phy_device *pcsphy; -+ struct phylink_pcs *sgmii_pcs; -+ struct phylink_pcs *qsgmii_pcs; -+ struct phylink_pcs *xfi_pcs; - bool allmulti_enabled; - }; - -@@ -487,91 +458,22 @@ static u32 get_mac_addr_hash_code(u64 et - return xor_val; - } - --static void setup_sgmii_internal_phy(struct fman_mac *memac, -- struct fixed_phy_status *fixed_link) --{ -- u16 tmp_reg16; -- -- if (WARN_ON(!memac->pcsphy)) -- return; -- -- /* SGMII mode */ -- tmp_reg16 = IF_MODE_SGMII_EN; -- if (!fixed_link) -- /* AN enable */ -- tmp_reg16 |= IF_MODE_USE_SGMII_AN; -- else { -- switch (fixed_link->speed) { -- case 10: -- /* For 10M: IF_MODE[SPEED_10M] = 0 */ -- break; -- case 100: -- tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; -- break; -- case 1000: -- default: -- tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; -- break; -- } -- if (!fixed_link->duplex) -- tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF; -- } -- phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16); -- -- /* Device ability according to SGMII specification */ -- tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE; -- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); -- -- /* Adjust link timer for SGMII - -- * According to Cisco SGMII specification the timer should be 1.6 ms. -- * The link_timer register is configured in units of the clock. -- * - When running as 1G SGMII, Serdes clock is 125 MHz, so -- * unit = 1 / (125*10^6 Hz) = 8 ns. -- * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40 -- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so -- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. -- * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120. -- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, -- * we always set up here a value of 2.5 SGMII. -- */ -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H); -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L); -- -- if (!fixed_link) -- /* Restart AN */ -- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; -+static void setup_sgmii_internal(struct fman_mac *memac, -+ struct phylink_pcs *pcs, -+ struct fixed_phy_status *fixed_link) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); -+ phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : -+ PHY_INTERFACE_MODE_SGMII; -+ unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; -+ -+ linkmode_set_pause(advertising, true, true); -+ pcs->ops->pcs_config(pcs, mode, iface, advertising, true); -+ if (fixed_link) -+ pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, -+ fixed_link->duplex); - else -- /* AN disabled */ -- tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN; -- phy_write(memac->pcsphy, 0x0, tmp_reg16); --} -- --static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac) --{ -- u16 tmp_reg16; -- -- /* AN Device capability */ -- tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE; -- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); -- -- /* Adjust link timer for SGMII - -- * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. -- * The link_timer register is configured in units of the clock. -- * - When running as 1G SGMII, Serdes clock is 125 MHz, so -- * unit = 1 / (125*10^6 Hz) = 8 ns. -- * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 -- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so -- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. -- * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. -- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, -- * we always set up here a value of 2.5 SGMII. -- */ -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX); -- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX); -- -- /* Restart AN */ -- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; -- phy_write(memac->pcsphy, 0x0, tmp_reg16); -+ pcs->ops->pcs_an_restart(pcs); - } - - static int check_init_parameters(struct fman_mac *memac) -@@ -983,7 +885,6 @@ static int memac_set_exception(struct fm - static int memac_init(struct fman_mac *memac) - { - struct memac_cfg *memac_drv_param; -- u8 i; - enet_addr_t eth_addr; - bool slow_10g_if = false; - struct fixed_phy_status *fixed_link = NULL; -@@ -1036,32 +937,10 @@ static int memac_init(struct fman_mac *m - iowrite32be(reg32, &memac->regs->command_config); - } - -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) { -- /* Configure internal SGMII PHY */ -- if (memac->basex_if) -- setup_sgmii_internal_phy_base_x(memac); -- else -- setup_sgmii_internal_phy(memac, fixed_link); -- } else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { -- /* Configure 4 internal SGMII PHYs */ -- for (i = 0; i < 4; i++) { -- u8 qsmgii_phy_addr, phy_addr; -- /* QSGMII PHY address occupies 3 upper bits of 5-bit -- * phy_address; the lower 2 bits are used to extend -- * register address space and access each one of 4 -- * ports inside QSGMII. -- */ -- phy_addr = memac->pcsphy->mdio.addr; -- qsmgii_phy_addr = (u8)((phy_addr << 2) | i); -- memac->pcsphy->mdio.addr = qsmgii_phy_addr; -- if (memac->basex_if) -- setup_sgmii_internal_phy_base_x(memac); -- else -- setup_sgmii_internal_phy(memac, fixed_link); -- -- memac->pcsphy->mdio.addr = phy_addr; -- } -- } -+ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) -+ setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); -+ else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) -+ setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); - - /* Max Frame Length */ - err = fman_set_mac_max_frame(memac->fm, memac->mac_id, -@@ -1097,12 +976,25 @@ static int memac_init(struct fman_mac *m - return 0; - } - -+static void pcs_put(struct phylink_pcs *pcs) -+{ -+ struct mdio_device *mdiodev; -+ -+ if (IS_ERR_OR_NULL(pcs)) -+ return; -+ -+ mdiodev = lynx_get_mdio_device(pcs); -+ lynx_pcs_destroy(pcs); -+ mdio_device_free(mdiodev); -+} -+ - static int memac_free(struct fman_mac *memac) - { - free_init_resources(memac); - -- if (memac->pcsphy) -- put_device(&memac->pcsphy->mdio.dev); -+ pcs_put(memac->sgmii_pcs); -+ pcs_put(memac->qsgmii_pcs); -+ pcs_put(memac->xfi_pcs); - - kfree(memac->memac_drv_param); - kfree(memac); -@@ -1153,12 +1045,31 @@ static struct fman_mac *memac_config(str - return memac; - } - -+static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, -+ int index) -+{ -+ struct device_node *node; -+ struct mdio_device *mdiodev = NULL; -+ struct phylink_pcs *pcs; -+ -+ node = of_parse_phandle(mac_node, "pcsphy-handle", index); -+ if (node && of_device_is_available(node)) -+ mdiodev = of_mdio_find_device(node); -+ of_node_put(node); -+ -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ pcs = lynx_pcs_create(mdiodev); -+ return pcs; -+} -+ - int memac_initialization(struct mac_device *mac_dev, - struct device_node *mac_node, - struct fman_mac_params *params) - { - int err; -- struct device_node *phy_node; -+ struct phylink_pcs *pcs; - struct fixed_phy_status *fixed_link; - struct fman_mac *memac; - -@@ -1188,23 +1099,58 @@ int memac_initialization(struct mac_devi - memac = mac_dev->fman_mac; - memac->memac_drv_param->max_frame_length = fman_get_max_frm(); - memac->memac_drv_param->reset_on_init = true; -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -- memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { -- phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); -- if (!phy_node) { -- pr_err("PCS PHY node is not available\n"); -- err = -EINVAL; -+ -+ err = of_property_match_string(mac_node, "pcs-handle-names", "xfi"); -+ if (err >= 0) { -+ memac->xfi_pcs = memac_pcs_create(mac_node, err); -+ if (IS_ERR(memac->xfi_pcs)) { -+ err = PTR_ERR(memac->xfi_pcs); -+ dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n"); - goto _return_fm_mac_free; - } -+ } else if (err != -EINVAL && err != -ENODATA) { -+ goto _return_fm_mac_free; -+ } - -- memac->pcsphy = of_phy_find_device(phy_node); -- if (!memac->pcsphy) { -- pr_err("of_phy_find_device (PCS PHY) failed\n"); -- err = -EINVAL; -+ err = of_property_match_string(mac_node, "pcs-handle-names", "qsgmii"); -+ if (err >= 0) { -+ memac->qsgmii_pcs = memac_pcs_create(mac_node, err); -+ if (IS_ERR(memac->qsgmii_pcs)) { -+ err = PTR_ERR(memac->qsgmii_pcs); -+ dev_err_probe(mac_dev->dev, err, -+ "missing qsgmii pcs\n"); - goto _return_fm_mac_free; - } -+ } else if (err != -EINVAL && err != -ENODATA) { -+ goto _return_fm_mac_free; -+ } -+ -+ /* For compatibility, if pcs-handle-names is missing, we assume this -+ * phy is the first one in pcsphy-handle -+ */ -+ err = of_property_match_string(mac_node, "pcs-handle-names", "sgmii"); -+ if (err == -EINVAL || err == -ENODATA) -+ pcs = memac_pcs_create(mac_node, 0); -+ else if (err < 0) -+ goto _return_fm_mac_free; -+ else -+ pcs = memac_pcs_create(mac_node, err); -+ -+ if (!pcs) { -+ dev_err(mac_dev->dev, "missing pcs\n"); -+ err = -ENOENT; -+ goto _return_fm_mac_free; - } - -+ /* If err is set here, it means that pcs-handle-names was missing above -+ * (and therefore that xfi_pcs cannot be set). If we are defaulting to -+ * XGMII, assume this is for XFI. Otherwise, assume it is for SGMII. -+ */ -+ if (err && mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ memac->xfi_pcs = pcs; -+ else -+ memac->sgmii_pcs = pcs; -+ - memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); - err = PTR_ERR(memac->serdes); - if (err == -ENODEV || err == -ENOSYS) { diff --git a/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch b/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch deleted file mode 100644 index 63b651bb2d..0000000000 --- a/target/linux/generic/backport-6.6/715-03-v6.2-net-dpaa-Convert-to-phylink.patch +++ /dev/null @@ -1,2451 +0,0 @@ -From 38e50fc3d43882a43115b4f1ca3eb88255163c5b Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Mon, 17 Oct 2022 16:22:38 -0400 -Subject: [PATCH 03/21] net: dpaa: Convert to phylink - -This converts DPAA to phylink. All macs are converted. This should work -with no device tree modifications (including those made in this series), -except for QSGMII (as noted previously). - -The mEMAC configuration is one of the tricker areas. I have tried to -capture all the restrictions across the various models. Most of the time, -we assume that if the serdes supports a mode or the phy-interface-mode -specifies it, then we support it. The only place we can't do this is -(RG)MII, since there's no serdes. In that case, we rely on a (new) -devicetree property. There are also several cases where half-duplex is -broken. Unfortunately, only a single compatible is used for the MAC, so we -have to use the board compatible instead. - -The 10GEC conversion is very straightforward, since it only supports XAUI. -There is generally nothing to configure. - -The dTSEC conversion is broadly similar to mEMAC, but is simpler because we -don't support configuring the SerDes (though this can be easily added) and -we don't have multiple PCSs. From what I can tell, there's nothing -different in the driver or documentation between SGMII and 1000BASE-X -except for the advertising. Similarly, I couldn't find anything about -2500BASE-X. In both cases, I treat them like SGMII. These modes aren't used -by any in-tree boards. Similarly, despite being mentioned in the driver, I -couldn't find any documented SoCs which supported QSGMII. I have left it -unimplemented for now. - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/freescale/dpaa/Kconfig | 4 +- - .../net/ethernet/freescale/dpaa/dpaa_eth.c | 89 +-- - .../ethernet/freescale/dpaa/dpaa_ethtool.c | 90 +-- - drivers/net/ethernet/freescale/fman/Kconfig | 1 - - .../net/ethernet/freescale/fman/fman_dtsec.c | 458 +++++++-------- - .../net/ethernet/freescale/fman/fman_mac.h | 10 - - .../net/ethernet/freescale/fman/fman_memac.c | 547 +++++++++--------- - .../net/ethernet/freescale/fman/fman_tgec.c | 131 ++--- - drivers/net/ethernet/freescale/fman/mac.c | 168 +----- - drivers/net/ethernet/freescale/fman/mac.h | 23 +- - 10 files changed, 612 insertions(+), 909 deletions(-) - ---- a/drivers/net/ethernet/freescale/dpaa/Kconfig -+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig -@@ -2,8 +2,8 @@ - menuconfig FSL_DPAA_ETH - tristate "DPAA Ethernet" - depends on FSL_DPAA && FSL_FMAN -- select PHYLIB -- select FIXED_PHY -+ select PHYLINK -+ select PCS_LYNX - help - Data Path Acceleration Architecture Ethernet driver, - supporting the Freescale QorIQ chips. ---- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c -+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c -@@ -264,8 +264,19 @@ static int dpaa_netdev_init(struct net_d - net_dev->needed_headroom = priv->tx_headroom; - net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); - -- mac_dev->net_dev = net_dev; -+ /* The rest of the config is filled in by the mac device already */ -+ mac_dev->phylink_config.dev = &net_dev->dev; -+ mac_dev->phylink_config.type = PHYLINK_NETDEV; - mac_dev->update_speed = dpaa_eth_cgr_set_speed; -+ mac_dev->phylink = phylink_create(&mac_dev->phylink_config, -+ dev_fwnode(mac_dev->dev), -+ mac_dev->phy_if, -+ mac_dev->phylink_ops); -+ if (IS_ERR(mac_dev->phylink)) { -+ err = PTR_ERR(mac_dev->phylink); -+ dev_err_probe(dev, err, "Could not create phylink\n"); -+ return err; -+ } - - /* start without the RUNNING flag, phylib controls it later */ - netif_carrier_off(net_dev); -@@ -273,6 +284,7 @@ static int dpaa_netdev_init(struct net_d - err = register_netdev(net_dev); - if (err < 0) { - dev_err(dev, "register_netdev() = %d\n", err); -+ phylink_destroy(mac_dev->phylink); - return err; - } - -@@ -295,8 +307,7 @@ static int dpaa_stop(struct net_device * - */ - msleep(200); - -- if (mac_dev->phy_dev) -- phy_stop(mac_dev->phy_dev); -+ phylink_stop(mac_dev->phylink); - mac_dev->disable(mac_dev->fman_mac); - - for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { -@@ -305,8 +316,7 @@ static int dpaa_stop(struct net_device * - err = error; - } - -- if (net_dev->phydev) -- phy_disconnect(net_dev->phydev); -+ phylink_disconnect_phy(mac_dev->phylink); - net_dev->phydev = NULL; - - msleep(200); -@@ -834,10 +844,10 @@ static int dpaa_eth_cgr_init(struct dpaa - - /* Set different thresholds based on the configured MAC speed. - * This may turn suboptimal if the MAC is reconfigured at another -- * speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link -+ * speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up - * callback. - */ -- if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) -+ if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD) - cs_th = DPAA_CS_THRESHOLD_10G; - else - cs_th = DPAA_CS_THRESHOLD_1G; -@@ -866,7 +876,7 @@ out_error: - - static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed) - { -- struct net_device *net_dev = mac_dev->net_dev; -+ struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev); - struct dpaa_priv *priv = netdev_priv(net_dev); - struct qm_mcc_initcgr opts = { }; - u32 cs_th; -@@ -2905,58 +2915,6 @@ static void dpaa_eth_napi_disable(struct - } - } - --static void dpaa_adjust_link(struct net_device *net_dev) --{ -- struct mac_device *mac_dev; -- struct dpaa_priv *priv; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- mac_dev->adjust_link(mac_dev); --} -- --/* The Aquantia PHYs are capable of performing rate adaptation */ --#define PHY_VEND_AQUANTIA 0x03a1b400 --#define PHY_VEND_AQUANTIA2 0x31c31c00 -- --static int dpaa_phy_init(struct net_device *net_dev) --{ -- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; -- struct mac_device *mac_dev; -- struct phy_device *phy_dev; -- struct dpaa_priv *priv; -- u32 phy_vendor; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, -- &dpaa_adjust_link, 0, -- mac_dev->phy_if); -- if (!phy_dev) { -- netif_err(priv, ifup, net_dev, "init_phy() failed\n"); -- return -ENODEV; -- } -- -- phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10); -- /* Unless the PHY is capable of rate adaptation */ -- if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII || -- (phy_vendor != PHY_VEND_AQUANTIA && -- phy_vendor != PHY_VEND_AQUANTIA2)) { -- /* remove any features not supported by the controller */ -- ethtool_convert_legacy_u32_to_link_mode(mask, -- mac_dev->if_support); -- linkmode_and(phy_dev->supported, phy_dev->supported, mask); -- } -- -- phy_support_asym_pause(phy_dev); -- -- mac_dev->phy_dev = phy_dev; -- net_dev->phydev = phy_dev; -- -- return 0; --} -- - static int dpaa_open(struct net_device *net_dev) - { - struct mac_device *mac_dev; -@@ -2967,7 +2925,8 @@ static int dpaa_open(struct net_device * - mac_dev = priv->mac_dev; - dpaa_eth_napi_enable(priv); - -- err = dpaa_phy_init(net_dev); -+ err = phylink_of_phy_connect(mac_dev->phylink, -+ mac_dev->dev->of_node, 0); - if (err) - goto phy_init_failed; - -@@ -2982,7 +2941,7 @@ static int dpaa_open(struct net_device * - netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err); - goto mac_start_failed; - } -- phy_start(priv->mac_dev->phy_dev); -+ phylink_start(mac_dev->phylink); - - netif_tx_start_all_queues(net_dev); - -@@ -2991,6 +2950,7 @@ static int dpaa_open(struct net_device * - mac_start_failed: - for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) - fman_port_disable(mac_dev->port[i]); -+ phylink_disconnect_phy(mac_dev->phylink); - - phy_init_failed: - dpaa_eth_napi_disable(priv); -@@ -3146,10 +3106,12 @@ static int dpaa_ts_ioctl(struct net_devi - static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) - { - int ret = -EINVAL; -+ struct dpaa_priv *priv = netdev_priv(net_dev); - - if (cmd == SIOCGMIIREG) { - if (net_dev->phydev) -- return phy_mii_ioctl(net_dev->phydev, rq, cmd); -+ return phylink_mii_ioctl(priv->mac_dev->phylink, rq, -+ cmd); - } - - if (cmd == SIOCSHWTSTAMP) -@@ -3552,6 +3514,7 @@ static int dpaa_remove(struct platform_d - - dev_set_drvdata(dev, NULL); - unregister_netdev(net_dev); -+ phylink_destroy(priv->mac_dev->phylink); - - err = dpaa_fq_free(dev, &priv->dpaa_fq_list); - ---- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c -+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c -@@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTR - static int dpaa_get_link_ksettings(struct net_device *net_dev, - struct ethtool_link_ksettings *cmd) - { -- if (!net_dev->phydev) -- return 0; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- phy_ethtool_ksettings_get(net_dev->phydev, cmd); -- -- return 0; -+ return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd); - } - - static int dpaa_set_link_ksettings(struct net_device *net_dev, - const struct ethtool_link_ksettings *cmd) - { -- int err; -- -- if (!net_dev->phydev) -- return -ENODEV; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- err = phy_ethtool_ksettings_set(net_dev->phydev, cmd); -- if (err < 0) -- netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err); -- -- return err; -+ return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd); - } - - static void dpaa_get_drvinfo(struct net_device *net_dev, -@@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net - - static int dpaa_nway_reset(struct net_device *net_dev) - { -- int err; -- -- if (!net_dev->phydev) -- return -ENODEV; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- err = 0; -- if (net_dev->phydev->autoneg) { -- err = phy_start_aneg(net_dev->phydev); -- if (err < 0) -- netdev_err(net_dev, "phy_start_aneg() = %d\n", -- err); -- } -- -- return err; -+ return phylink_ethtool_nway_reset(mac_dev->phylink); - } - - static void dpaa_get_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *epause) - { -- struct mac_device *mac_dev; -- struct dpaa_priv *priv; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- if (!net_dev->phydev) -- return; -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- epause->autoneg = mac_dev->autoneg_pause; -- epause->rx_pause = mac_dev->rx_pause_active; -- epause->tx_pause = mac_dev->tx_pause_active; -+ phylink_ethtool_get_pauseparam(mac_dev->phylink, epause); - } - - static int dpaa_set_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *epause) - { -- struct mac_device *mac_dev; -- struct phy_device *phydev; -- bool rx_pause, tx_pause; -- struct dpaa_priv *priv; -- int err; -- -- priv = netdev_priv(net_dev); -- mac_dev = priv->mac_dev; -- -- phydev = net_dev->phydev; -- if (!phydev) { -- netdev_err(net_dev, "phy device not initialized\n"); -- return -ENODEV; -- } -- -- if (!phy_validate_pause(phydev, epause)) -- return -EINVAL; -- -- /* The MAC should know how to handle PAUSE frame autonegotiation before -- * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE -- * settings. -- */ -- mac_dev->autoneg_pause = !!epause->autoneg; -- mac_dev->rx_pause_req = !!epause->rx_pause; -- mac_dev->tx_pause_req = !!epause->tx_pause; -- -- /* Determine the sym/asym advertised PAUSE capabilities from the desired -- * rx/tx pause settings. -- */ -- -- phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause); -- -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- netdev_err(net_dev, "set_mac_active_pause() = %d\n", err); -+ struct dpaa_priv *priv = netdev_priv(net_dev); -+ struct mac_device *mac_dev = priv->mac_dev; - -- return err; -+ return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause); - } - - static int dpaa_get_sset_count(struct net_device *net_dev, int type) ---- a/drivers/net/ethernet/freescale/fman/Kconfig -+++ b/drivers/net/ethernet/freescale/fman/Kconfig -@@ -3,7 +3,6 @@ config FSL_FMAN - tristate "FMan support" - depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST - select GENERIC_ALLOCATOR -- select PHYLIB - select PHYLINK - select PCS - select PCS_LYNX ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - /* TBI register addresses */ - #define MII_TBICON 0x11 -@@ -29,9 +30,6 @@ - #define TBICON_CLK_SELECT 0x0020 /* Clock select */ - #define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ - --#define TBIANA_SGMII 0x4001 --#define TBIANA_1000X 0x01a0 -- - /* Interrupt Mask Register (IMASK) */ - #define DTSEC_IMASK_BREN 0x80000000 - #define DTSEC_IMASK_RXCEN 0x40000000 -@@ -92,9 +90,10 @@ - - #define DTSEC_ECNTRL_GMIIM 0x00000040 - #define DTSEC_ECNTRL_TBIM 0x00000020 --#define DTSEC_ECNTRL_SGMIIM 0x00000002 - #define DTSEC_ECNTRL_RPM 0x00000010 - #define DTSEC_ECNTRL_R100M 0x00000008 -+#define DTSEC_ECNTRL_RMM 0x00000004 -+#define DTSEC_ECNTRL_SGMIIM 0x00000002 - #define DTSEC_ECNTRL_QSGMIIM 0x00000001 - - #define TCTRL_TTSE 0x00000040 -@@ -318,7 +317,8 @@ struct fman_mac { - void *fm; - struct fman_rev_info fm_rev_info; - bool basex_if; -- struct phy_device *tbiphy; -+ struct mdio_device *tbidev; -+ struct phylink_pcs pcs; - }; - - static void set_dflts(struct dtsec_cfg *cfg) -@@ -356,56 +356,14 @@ static int init(struct dtsec_regs __iome - phy_interface_t iface, u16 iface_speed, u64 addr, - u32 exception_mask, u8 tbi_addr) - { -- bool is_rgmii, is_sgmii, is_qsgmii; - enet_addr_t eth_addr; -- u32 tmp; -+ u32 tmp = 0; - int i; - - /* Soft reset */ - iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); - iowrite32be(0, ®s->maccfg1); - -- /* dtsec_id2 */ -- tmp = ioread32be(®s->tsec_id2); -- -- /* check RGMII support */ -- if (iface == PHY_INTERFACE_MODE_RGMII || -- iface == PHY_INTERFACE_MODE_RGMII_ID || -- iface == PHY_INTERFACE_MODE_RGMII_RXID || -- iface == PHY_INTERFACE_MODE_RGMII_TXID || -- iface == PHY_INTERFACE_MODE_RMII) -- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) -- return -EINVAL; -- -- if (iface == PHY_INTERFACE_MODE_SGMII || -- iface == PHY_INTERFACE_MODE_MII) -- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) -- return -EINVAL; -- -- is_rgmii = iface == PHY_INTERFACE_MODE_RGMII || -- iface == PHY_INTERFACE_MODE_RGMII_ID || -- iface == PHY_INTERFACE_MODE_RGMII_RXID || -- iface == PHY_INTERFACE_MODE_RGMII_TXID; -- is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; -- is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; -- -- tmp = 0; -- if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) -- tmp |= DTSEC_ECNTRL_GMIIM; -- if (is_sgmii) -- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); -- if (is_qsgmii) -- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | -- DTSEC_ECNTRL_QSGMIIM); -- if (is_rgmii) -- tmp |= DTSEC_ECNTRL_RPM; -- if (iface_speed == SPEED_100) -- tmp |= DTSEC_ECNTRL_R100M; -- -- iowrite32be(tmp, ®s->ecntrl); -- -- tmp = 0; -- - if (cfg->tx_pause_time) - tmp |= cfg->tx_pause_time; - if (cfg->tx_pause_time_extd) -@@ -446,17 +404,10 @@ static int init(struct dtsec_regs __iome - - tmp = 0; - -- if (iface_speed < SPEED_1000) -- tmp |= MACCFG2_NIBBLE_MODE; -- else if (iface_speed == SPEED_1000) -- tmp |= MACCFG2_BYTE_MODE; -- - tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & - MACCFG2_PREAMBLE_LENGTH_MASK; - if (cfg->tx_pad_crc) - tmp |= MACCFG2_PAD_CRC_EN; -- /* Full Duplex */ -- tmp |= MACCFG2_FULL_DUPLEX; - iowrite32be(tmp, ®s->maccfg2); - - tmp = (((cfg->non_back_to_back_ipg1 << -@@ -525,10 +476,6 @@ static void set_bucket(struct dtsec_regs - - static int check_init_parameters(struct fman_mac *dtsec) - { -- if (dtsec->max_speed >= SPEED_10000) { -- pr_err("1G MAC driver supports 1G or lower speeds\n"); -- return -EINVAL; -- } - if ((dtsec->dtsec_drv_param)->rx_prepend > - MAX_PACKET_ALIGNMENT) { - pr_err("packetAlignmentPadding can't be > than %d\n", -@@ -630,22 +577,10 @@ static int get_exception_flag(enum fman_ - return bit_mask; - } - --static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) --{ -- /* Checks if dTSEC driver parameters were initialized */ -- if (!dtsec_drv_params) -- return true; -- -- return false; --} -- - static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) - { - struct dtsec_regs __iomem *regs = dtsec->regs; - -- if (is_init_done(dtsec->dtsec_drv_param)) -- return 0; -- - return (u16)ioread32be(®s->maxfrm); - } - -@@ -682,6 +617,7 @@ static void dtsec_isr(void *handle) - dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); - if (event & DTSEC_IMASK_XFUNEN) { - /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ -+ /* FIXME: This races with the rest of the driver! */ - if (dtsec->fm_rev_info.major == 2) { - u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; - /* a. Write 0x00E0_0C00 to DTSEC_ID -@@ -814,6 +750,43 @@ static void free_init_resources(struct f - dtsec->unicast_addr_hash = NULL; - } - -+static struct fman_mac *pcs_to_dtsec(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct fman_mac, pcs); -+} -+ -+static void dtsec_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); -+} -+ -+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, -+ advertising); -+} -+ -+static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct fman_mac *dtsec = pcs_to_dtsec(pcs); -+ -+ phylink_mii_c22_pcs_an_restart(dtsec->tbidev); -+} -+ -+static const struct phylink_pcs_ops dtsec_pcs_ops = { -+ .pcs_get_state = dtsec_pcs_get_state, -+ .pcs_config = dtsec_pcs_config, -+ .pcs_an_restart = dtsec_pcs_an_restart, -+}; -+ - static void graceful_start(struct fman_mac *dtsec) - { - struct dtsec_regs __iomem *regs = dtsec->regs; -@@ -854,36 +827,11 @@ static void graceful_stop(struct fman_ma - - static int dtsec_enable(struct fman_mac *dtsec) - { -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- /* Enable */ -- tmp = ioread32be(®s->maccfg1); -- tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; -- iowrite32be(tmp, ®s->maccfg1); -- -- /* Graceful start - clear the graceful Rx/Tx stop bit */ -- graceful_start(dtsec); -- - return 0; - } - - static void dtsec_disable(struct fman_mac *dtsec) - { -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(dtsec->dtsec_drv_param)); -- -- /* Graceful stop - Assert the graceful Rx/Tx stop bit */ -- graceful_stop(dtsec); -- -- tmp = ioread32be(®s->maccfg1); -- tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); -- iowrite32be(tmp, ®s->maccfg1); - } - - static int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, -@@ -894,11 +842,6 @@ static int dtsec_set_tx_pause_frames(str - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 ptv = 0; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- - if (pause_time) { - /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ - if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { -@@ -919,8 +862,6 @@ static int dtsec_set_tx_pause_frames(str - iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, - ®s->maccfg1); - -- graceful_start(dtsec); -- - return 0; - } - -@@ -929,11 +870,6 @@ static int dtsec_accept_rx_pause_frames( - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 tmp; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- - tmp = ioread32be(®s->maccfg1); - if (en) - tmp |= MACCFG1_RX_FLOW; -@@ -941,17 +877,125 @@ static int dtsec_accept_rx_pause_frames( - tmp &= ~MACCFG1_RX_FLOW; - iowrite32be(tmp, ®s->maccfg1); - -+ return 0; -+} -+ -+static struct phylink_pcs *dtsec_select_pcs(struct phylink_config *config, -+ phy_interface_t iface) -+{ -+ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return &dtsec->pcs; -+ default: -+ return NULL; -+ } -+} -+ -+static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; -+ u32 tmp; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_RMII: -+ tmp = DTSEC_ECNTRL_RMM; -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; -+ break; -+ default: -+ dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", -+ phy_modes(state->interface)); -+ return; -+ } -+ -+ iowrite32be(tmp, ®s->ecntrl); -+} -+ -+static void dtsec_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 mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *dtsec = mac_dev->fman_mac; -+ struct dtsec_regs __iomem *regs = dtsec->regs; -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ u32 tmp; -+ -+ dtsec_set_tx_pause_frames(dtsec, 0, pause_time, 0); -+ dtsec_accept_rx_pause_frames(dtsec, rx_pause); -+ -+ tmp = ioread32be(®s->ecntrl); -+ if (speed == SPEED_100) -+ tmp |= DTSEC_ECNTRL_R100M; -+ else -+ tmp &= ~DTSEC_ECNTRL_R100M; -+ iowrite32be(tmp, ®s->ecntrl); -+ -+ tmp = ioread32be(®s->maccfg2); -+ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE | MACCFG2_FULL_DUPLEX); -+ if (speed >= SPEED_1000) -+ tmp |= MACCFG2_BYTE_MODE; -+ else -+ tmp |= MACCFG2_NIBBLE_MODE; -+ -+ if (duplex == DUPLEX_FULL) -+ tmp |= MACCFG2_FULL_DUPLEX; -+ -+ iowrite32be(tmp, ®s->maccfg2); -+ -+ mac_dev->update_speed(mac_dev, speed); -+ -+ /* Enable */ -+ tmp = ioread32be(®s->maccfg1); -+ tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; -+ iowrite32be(tmp, ®s->maccfg1); -+ -+ /* Graceful start - clear the graceful Rx/Tx stop bit */ - graceful_start(dtsec); -+} - -- return 0; -+static void dtsec_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; -+ struct dtsec_regs __iomem *regs = dtsec->regs; -+ u32 tmp; -+ -+ /* Graceful stop - Assert the graceful Rx/Tx stop bit */ -+ graceful_stop(dtsec); -+ -+ tmp = ioread32be(®s->maccfg1); -+ tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); -+ iowrite32be(tmp, ®s->maccfg1); - } - -+static const struct phylink_mac_ops dtsec_mac_ops = { -+ .validate = phylink_generic_validate, -+ .mac_select_pcs = dtsec_select_pcs, -+ .mac_config = dtsec_mac_config, -+ .mac_link_up = dtsec_link_up, -+ .mac_link_down = dtsec_link_down, -+}; -+ - static int dtsec_modify_mac_address(struct fman_mac *dtsec, - const enet_addr_t *enet_addr) - { -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - graceful_stop(dtsec); - - /* Initialize MAC Station Address registers (1 & 2) -@@ -975,9 +1019,6 @@ static int dtsec_add_hash_mac_address(st - u32 crc = 0xFFFFFFFF; - bool mcast, ghtx; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); -@@ -1037,9 +1078,6 @@ static int dtsec_set_allmulti(struct fma - u32 tmp; - struct dtsec_regs __iomem *regs = dtsec->regs; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->rctrl); - if (enable) - tmp |= RCTRL_MPROM; -@@ -1056,9 +1094,6 @@ static int dtsec_set_tstamp(struct fman_ - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 rctrl, tctrl; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - rctrl = ioread32be(®s->rctrl); - tctrl = ioread32be(®s->tctrl); - -@@ -1087,9 +1122,6 @@ static int dtsec_del_hash_mac_address(st - u32 crc = 0xFFFFFFFF; - bool mcast, ghtx; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); -@@ -1153,9 +1185,6 @@ static int dtsec_set_promiscuous(struct - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 tmp; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - /* Set unicast promiscuous */ - tmp = ioread32be(®s->rctrl); - if (new_val) -@@ -1177,90 +1206,12 @@ static int dtsec_set_promiscuous(struct - return 0; - } - --static int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) --{ -- struct dtsec_regs __iomem *regs = dtsec->regs; -- u32 tmp; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- graceful_stop(dtsec); -- -- tmp = ioread32be(®s->maccfg2); -- -- /* Full Duplex */ -- tmp |= MACCFG2_FULL_DUPLEX; -- -- tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); -- if (speed < SPEED_1000) -- tmp |= MACCFG2_NIBBLE_MODE; -- else if (speed == SPEED_1000) -- tmp |= MACCFG2_BYTE_MODE; -- iowrite32be(tmp, ®s->maccfg2); -- -- tmp = ioread32be(®s->ecntrl); -- if (speed == SPEED_100) -- tmp |= DTSEC_ECNTRL_R100M; -- else -- tmp &= ~DTSEC_ECNTRL_R100M; -- iowrite32be(tmp, ®s->ecntrl); -- -- graceful_start(dtsec); -- -- return 0; --} -- --static int dtsec_restart_autoneg(struct fman_mac *dtsec) --{ -- u16 tmp_reg16; -- -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- -- tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); -- -- tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); -- tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- -- return 0; --} -- --static void adjust_link_dtsec(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- struct fman_mac *fman_mac; -- bool rx_pause, tx_pause; -- int err; -- -- fman_mac = mac_dev->fman_mac; -- if (!phy_dev->link) { -- dtsec_restart_autoneg(fman_mac); -- -- return; -- } -- -- dtsec_adjust_link(fman_mac, phy_dev->speed); -- mac_dev->update_speed(mac_dev, phy_dev->speed); -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", -- err); --} -- - static int dtsec_set_exception(struct fman_mac *dtsec, - enum fman_mac_exceptions exception, bool enable) - { - struct dtsec_regs __iomem *regs = dtsec->regs; - u32 bit_mask = 0; - -- if (!is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { - bit_mask = get_exception_flag(exception); - if (bit_mask) { -@@ -1310,12 +1261,9 @@ static int dtsec_init(struct fman_mac *d - { - struct dtsec_regs __iomem *regs = dtsec->regs; - struct dtsec_cfg *dtsec_drv_param; -- u16 max_frm_ln; -+ u16 max_frm_ln, tbicon; - int err; - -- if (is_init_done(dtsec->dtsec_drv_param)) -- return -EINVAL; -- - if (DEFAULT_RESET_ON_INIT && - (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { - pr_err("Can't reset MAC!\n"); -@@ -1330,38 +1278,19 @@ static int dtsec_init(struct fman_mac *d - - err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, - dtsec->max_speed, dtsec->addr, dtsec->exceptions, -- dtsec->tbiphy->mdio.addr); -+ dtsec->tbidev->addr); - if (err) { - free_init_resources(dtsec); - pr_err("DTSEC version doesn't support this i/f mode\n"); - return err; - } - -- if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { -- u16 tmp_reg16; -- -- /* Configure the TBI PHY Control Register */ -- tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; -- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); -- -- tmp_reg16 = TBICON_CLK_SELECT; -- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); -- -- tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- -- if (dtsec->basex_if) -- tmp_reg16 = TBIANA_1000X; -- else -- tmp_reg16 = TBIANA_SGMII; -- phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); -+ /* Configure the TBI PHY Control Register */ -+ tbicon = TBICON_CLK_SELECT | TBICON_SOFT_RESET; -+ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); - -- tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | -- BMCR_FULLDPLX | BMCR_SPEED1000); -- -- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); -- } -+ tbicon = TBICON_CLK_SELECT; -+ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); - - /* Max Frame Length */ - max_frm_ln = (u16)ioread32be(®s->maxfrm); -@@ -1406,6 +1335,8 @@ static int dtsec_free(struct fman_mac *d - - kfree(dtsec->dtsec_drv_param); - dtsec->dtsec_drv_param = NULL; -+ if (!IS_ERR_OR_NULL(dtsec->tbidev)) -+ put_device(&dtsec->tbidev->dev); - kfree(dtsec); - - return 0; -@@ -1434,7 +1365,6 @@ static struct fman_mac *dtsec_config(str - - dtsec->regs = mac_dev->vaddr; - dtsec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); -- dtsec->max_speed = params->max_speed; - dtsec->phy_if = mac_dev->phy_if; - dtsec->mac_id = params->mac_id; - dtsec->exceptions = (DTSEC_IMASK_BREN | -@@ -1457,7 +1387,6 @@ static struct fman_mac *dtsec_config(str - dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en; - - dtsec->fm = params->fm; -- dtsec->basex_if = params->basex_if; - - /* Save FMan revision */ - fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); -@@ -1476,18 +1405,18 @@ int dtsec_initialization(struct mac_devi - int err; - struct fman_mac *dtsec; - struct device_node *phy_node; -+ unsigned long capabilities; -+ unsigned long *supported; - -+ mac_dev->phylink_ops = &dtsec_mac_ops; - mac_dev->set_promisc = dtsec_set_promiscuous; - mac_dev->change_addr = dtsec_modify_mac_address; - mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; -- mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; -- mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; - mac_dev->set_exception = dtsec_set_exception; - mac_dev->set_allmulti = dtsec_set_allmulti; - mac_dev->set_tstamp = dtsec_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = adjust_link_dtsec; - mac_dev->enable = dtsec_enable; - mac_dev->disable = dtsec_disable; - -@@ -1502,19 +1431,56 @@ int dtsec_initialization(struct mac_devi - dtsec->dtsec_drv_param->tx_pad_crc = true; - - phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); -- if (!phy_node) { -- pr_err("TBI PHY node is not available\n"); -+ if (!phy_node || of_device_is_available(phy_node)) { -+ of_node_put(phy_node); - err = -EINVAL; -+ dev_err_probe(mac_dev->dev, err, -+ "TBI PCS node is not available\n"); - goto _return_fm_mac_free; - } - -- dtsec->tbiphy = of_phy_find_device(phy_node); -- if (!dtsec->tbiphy) { -- pr_err("of_phy_find_device (TBI PHY) failed\n"); -- err = -EINVAL; -+ dtsec->tbidev = of_mdio_find_device(phy_node); -+ of_node_put(phy_node); -+ if (!dtsec->tbidev) { -+ err = -EPROBE_DEFER; -+ dev_err_probe(mac_dev->dev, err, -+ "could not find mdiodev for PCS\n"); - goto _return_fm_mac_free; - } -- put_device(&dtsec->tbiphy->mdio.dev); -+ dtsec->pcs.ops = &dtsec_pcs_ops; -+ dtsec->pcs.poll = true; -+ -+ supported = mac_dev->phylink_config.supported_interfaces; -+ -+ /* FIXME: Can we use DTSEC_ID2_INT_FULL_OFF to determine if these are -+ * supported? If not, we can determine support via the phy if SerDes -+ * support is added. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII || -+ mac_dev->phy_if == PHY_INTERFACE_MODE_1000BASEX) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); -+ } else if (mac_dev->phy_if == PHY_INTERFACE_MODE_2500BASEX) { -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -+ } -+ -+ if (!(ioread32be(&dtsec->regs->tsec_id2) & DTSEC_ID2_INT_REDUCED_OFF)) { -+ phy_interface_set_rgmii(supported); -+ -+ /* DTSEC_ID2_INT_REDUCED_OFF indicates that the dTSEC supports -+ * RMII and RGMII. However, the only SoCs which support RMII -+ * are the P1017 and P1023. Avoid advertising this mode on -+ * other SoCs. This is a bit of a moot point, since there's no -+ * in-tree support for ethernet on these platforms... -+ */ -+ if (of_machine_is_compatible("fsl,P1023") || -+ of_machine_is_compatible("fsl,P1023RDB")) -+ __set_bit(PHY_INTERFACE_MODE_RMII, supported); -+ } -+ -+ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; -+ capabilities |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; -+ mac_dev->phylink_config.mac_capabilities = capabilities; - - err = dtsec_init(dtsec); - if (err < 0) ---- a/drivers/net/ethernet/freescale/fman/fman_mac.h -+++ b/drivers/net/ethernet/freescale/fman/fman_mac.h -@@ -170,20 +170,10 @@ struct fman_mac_params { - * 0 - FM_MAX_NUM_OF_10G_MACS - */ - u8 mac_id; -- /* Note that the speed should indicate the maximum rate that -- * this MAC should support rather than the actual speed; -- */ -- u16 max_speed; - /* A handle to the FM object this port related to */ - void *fm; - fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ - fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ -- /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC -- * and phy or backplane; Note: 1000BaseX auto-negotiation relates only -- * to interface between MAC and phy/backplane, SGMII phy can still -- * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps -- */ -- bool basex_if; - }; - - struct eth_hash_t { ---- a/drivers/net/ethernet/freescale/fman/fman_memac.c -+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c -@@ -278,9 +278,6 @@ struct fman_mac { - struct memac_regs __iomem *regs; - /* MAC address of device */ - u64 addr; -- /* Ethernet physical interface */ -- phy_interface_t phy_if; -- u16 max_speed; - struct mac_device *dev_id; /* device cookie used by the exception cbs */ - fman_mac_exception_cb *exception_cb; - fman_mac_exception_cb *event_cb; -@@ -293,12 +290,12 @@ struct fman_mac { - struct memac_cfg *memac_drv_param; - void *fm; - struct fman_rev_info fm_rev_info; -- bool basex_if; - struct phy *serdes; - struct phylink_pcs *sgmii_pcs; - struct phylink_pcs *qsgmii_pcs; - struct phylink_pcs *xfi_pcs; - bool allmulti_enabled; -+ bool rgmii_no_half_duplex; - }; - - static void add_addr_in_paddr(struct memac_regs __iomem *regs, const u8 *adr, -@@ -356,7 +353,6 @@ static void set_exception(struct memac_r - } - - static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, -- phy_interface_t phy_if, u16 speed, bool slow_10g_if, - u32 exceptions) - { - u32 tmp; -@@ -384,41 +380,6 @@ static int init(struct memac_regs __iome - iowrite32be((u32)cfg->pause_quanta, ®s->pause_quanta[0]); - iowrite32be((u32)0, ®s->pause_thresh[0]); - -- /* IF_MODE */ -- tmp = 0; -- switch (phy_if) { -- case PHY_INTERFACE_MODE_XGMII: -- tmp |= IF_MODE_10G; -- break; -- case PHY_INTERFACE_MODE_MII: -- tmp |= IF_MODE_MII; -- break; -- default: -- tmp |= IF_MODE_GMII; -- if (phy_if == PHY_INTERFACE_MODE_RGMII || -- phy_if == PHY_INTERFACE_MODE_RGMII_ID || -- phy_if == PHY_INTERFACE_MODE_RGMII_RXID || -- phy_if == PHY_INTERFACE_MODE_RGMII_TXID) -- tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; -- } -- iowrite32be(tmp, ®s->if_mode); -- -- /* TX_FIFO_SECTIONS */ -- tmp = 0; -- if (phy_if == PHY_INTERFACE_MODE_XGMII) { -- if (slow_10g_if) { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); -- } else { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); -- } -- } else { -- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | -- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); -- } -- iowrite32be(tmp, ®s->tx_fifo_sections); -- - /* clear all pending events and set-up interrupts */ - iowrite32be(0xffffffff, ®s->ievent); - set_exception(regs, exceptions, true); -@@ -458,24 +419,6 @@ static u32 get_mac_addr_hash_code(u64 et - return xor_val; - } - --static void setup_sgmii_internal(struct fman_mac *memac, -- struct phylink_pcs *pcs, -- struct fixed_phy_status *fixed_link) --{ -- __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); -- phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : -- PHY_INTERFACE_MODE_SGMII; -- unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; -- -- linkmode_set_pause(advertising, true, true); -- pcs->ops->pcs_config(pcs, mode, iface, advertising, true); -- if (fixed_link) -- pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, -- fixed_link->duplex); -- else -- pcs->ops->pcs_an_restart(pcs); --} -- - static int check_init_parameters(struct fman_mac *memac) - { - if (!memac->exception_cb) { -@@ -581,41 +524,31 @@ static void free_init_resources(struct f - memac->unicast_addr_hash = NULL; - } - --static bool is_init_done(struct memac_cfg *memac_drv_params) --{ -- /* Checks if mEMAC driver parameters were initialized */ -- if (!memac_drv_params) -- return true; -- -- return false; --} -- - static int memac_enable(struct fman_mac *memac) - { -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -+ int ret; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -+ ret = phy_init(memac->serdes); -+ if (ret) { -+ dev_err(memac->dev_id->dev, -+ "could not initialize serdes: %pe\n", ERR_PTR(ret)); -+ return ret; -+ } - -- tmp = ioread32be(®s->command_config); -- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -- iowrite32be(tmp, ®s->command_config); -+ ret = phy_power_on(memac->serdes); -+ if (ret) { -+ dev_err(memac->dev_id->dev, -+ "could not power on serdes: %pe\n", ERR_PTR(ret)); -+ phy_exit(memac->serdes); -+ } - -- return 0; -+ return ret; - } - - static void memac_disable(struct fman_mac *memac) -- - { -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(memac->memac_drv_param)); -- -- tmp = ioread32be(®s->command_config); -- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -- iowrite32be(tmp, ®s->command_config); -+ phy_power_off(memac->serdes); -+ phy_exit(memac->serdes); - } - - static int memac_set_promiscuous(struct fman_mac *memac, bool new_val) -@@ -623,9 +556,6 @@ static int memac_set_promiscuous(struct - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (new_val) - tmp |= CMD_CFG_PROMIS_EN; -@@ -637,73 +567,12 @@ static int memac_set_promiscuous(struct - return 0; - } - --static int memac_adjust_link(struct fman_mac *memac, u16 speed) --{ -- struct memac_regs __iomem *regs = memac->regs; -- u32 tmp; -- -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- -- tmp = ioread32be(®s->if_mode); -- -- /* Set full duplex */ -- tmp &= ~IF_MODE_HD; -- -- if (phy_interface_mode_is_rgmii(memac->phy_if)) { -- /* Configure RGMII in manual mode */ -- tmp &= ~IF_MODE_RGMII_AUTO; -- tmp &= ~IF_MODE_RGMII_SP_MASK; -- /* Full duplex */ -- tmp |= IF_MODE_RGMII_FD; -- -- switch (speed) { -- case SPEED_1000: -- tmp |= IF_MODE_RGMII_1000; -- break; -- case SPEED_100: -- tmp |= IF_MODE_RGMII_100; -- break; -- case SPEED_10: -- tmp |= IF_MODE_RGMII_10; -- break; -- default: -- break; -- } -- } -- -- iowrite32be(tmp, ®s->if_mode); -- -- return 0; --} -- --static void adjust_link_memac(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- struct fman_mac *fman_mac; -- bool rx_pause, tx_pause; -- int err; -- -- fman_mac = mac_dev->fman_mac; -- memac_adjust_link(fman_mac, phy_dev->speed); -- mac_dev->update_speed(mac_dev, phy_dev->speed); -- -- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); -- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); -- if (err < 0) -- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", -- err); --} -- - static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, - u16 pause_time, u16 thresh_time) - { - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->tx_fifo_sections); - - GET_TX_EMPTY_DEFAULT_VALUE(tmp); -@@ -738,9 +607,6 @@ static int memac_accept_rx_pause_frames( - struct memac_regs __iomem *regs = memac->regs; - u32 tmp; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (en) - tmp &= ~CMD_CFG_PAUSE_IGNORE; -@@ -752,12 +618,175 @@ static int memac_accept_rx_pause_frames( - return 0; - } - -+static void memac_validate(struct phylink_config *config, -+ unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ unsigned long caps = config->mac_capabilities; -+ -+ if (phy_interface_mode_is_rgmii(state->interface) && -+ memac->rgmii_no_half_duplex) -+ caps &= ~(MAC_10HD | MAC_100HD); -+ -+ phylink_validate_mask_caps(supported, state, caps); -+} -+ -+/** -+ * memac_if_mode() - Convert an interface mode into an IF_MODE config -+ * @interface: A phy interface mode -+ * -+ * Return: A configuration word, suitable for programming into the lower bits -+ * of %IF_MODE. -+ */ -+static u32 memac_if_mode(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_MII: -+ return IF_MODE_MII; -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ return IF_MODE_GMII | IF_MODE_RGMII; -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return IF_MODE_GMII; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return IF_MODE_10G; -+ default: -+ WARN_ON_ONCE(1); -+ return 0; -+ } -+} -+ -+static struct phylink_pcs *memac_select_pcs(struct phylink_config *config, -+ phy_interface_t iface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ return memac->sgmii_pcs; -+ case PHY_INTERFACE_MODE_QSGMII: -+ return memac->qsgmii_pcs; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return memac->xfi_pcs; -+ default: -+ return NULL; -+ } -+} -+ -+static int memac_prepare(struct phylink_config *config, unsigned int mode, -+ phy_interface_t iface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ -+ switch (iface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_10GBASER: -+ return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -+ iface); -+ default: -+ return 0; -+ } -+} -+ -+static void memac_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mac_device *mac_dev = fman_config_to_mac(config); -+ struct memac_regs __iomem *regs = mac_dev->fman_mac->regs; -+ u32 tmp = ioread32be(®s->if_mode); -+ -+ tmp &= ~(IF_MODE_MASK | IF_MODE_RGMII); -+ tmp |= memac_if_mode(state->interface); -+ if (phylink_autoneg_inband(mode)) -+ tmp |= IF_MODE_RGMII_AUTO; -+ iowrite32be(tmp, ®s->if_mode); -+} -+ -+static void memac_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 mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *memac = mac_dev->fman_mac; -+ struct memac_regs __iomem *regs = memac->regs; -+ u32 tmp = memac_if_mode(interface); -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ -+ memac_set_tx_pause_frames(memac, 0, pause_time, 0); -+ memac_accept_rx_pause_frames(memac, rx_pause); -+ -+ if (duplex == DUPLEX_HALF) -+ tmp |= IF_MODE_HD; -+ -+ switch (speed) { -+ case SPEED_1000: -+ tmp |= IF_MODE_RGMII_1000; -+ break; -+ case SPEED_100: -+ tmp |= IF_MODE_RGMII_100; -+ break; -+ case SPEED_10: -+ tmp |= IF_MODE_RGMII_10; -+ break; -+ } -+ iowrite32be(tmp, ®s->if_mode); -+ -+ /* TODO: EEE? */ -+ -+ if (speed == SPEED_10000) { -+ if (memac->fm_rev_info.major == 6 && -+ memac->fm_rev_info.minor == 4) -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G; -+ else -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_10G; -+ tmp |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G; -+ } else { -+ tmp = TX_FIFO_SECTIONS_TX_AVAIL_1G | -+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G; -+ } -+ iowrite32be(tmp, ®s->tx_fifo_sections); -+ -+ mac_dev->update_speed(mac_dev, speed); -+ -+ tmp = ioread32be(®s->command_config); -+ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static void memac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; -+ struct memac_regs __iomem *regs = memac->regs; -+ u32 tmp; -+ -+ /* TODO: graceful */ -+ tmp = ioread32be(®s->command_config); -+ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static const struct phylink_mac_ops memac_mac_ops = { -+ .validate = memac_validate, -+ .mac_select_pcs = memac_select_pcs, -+ .mac_prepare = memac_prepare, -+ .mac_config = memac_mac_config, -+ .mac_link_up = memac_link_up, -+ .mac_link_down = memac_link_down, -+}; -+ - static int memac_modify_mac_address(struct fman_mac *memac, - const enet_addr_t *enet_addr) - { -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0); - - return 0; -@@ -771,9 +800,6 @@ static int memac_add_hash_mac_address(st - u32 hash; - u64 addr; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - if (!(addr & GROUP_ADDRESS)) { -@@ -802,9 +828,6 @@ static int memac_set_allmulti(struct fma - u32 entry; - struct memac_regs __iomem *regs = memac->regs; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - if (enable) { - for (entry = 0; entry < HASH_TABLE_SIZE; entry++) - iowrite32be(entry | HASH_CTRL_MCAST_EN, -@@ -834,9 +857,6 @@ static int memac_del_hash_mac_address(st - u32 hash; - u64 addr; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; -@@ -864,9 +884,6 @@ static int memac_set_exception(struct fm - { - u32 bit_mask = 0; - -- if (!is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - bit_mask = get_exception_flag(exception); - if (bit_mask) { - if (enable) -@@ -886,23 +903,15 @@ static int memac_init(struct fman_mac *m - { - struct memac_cfg *memac_drv_param; - enet_addr_t eth_addr; -- bool slow_10g_if = false; -- struct fixed_phy_status *fixed_link = NULL; - int err; - u32 reg32 = 0; - -- if (is_init_done(memac->memac_drv_param)) -- return -EINVAL; -- - err = check_init_parameters(memac); - if (err) - return err; - - memac_drv_param = memac->memac_drv_param; - -- if (memac->fm_rev_info.major == 6 && memac->fm_rev_info.minor == 4) -- slow_10g_if = true; -- - /* First, reset the MAC if desired. */ - if (memac_drv_param->reset_on_init) { - err = reset(memac->regs); -@@ -918,10 +927,7 @@ static int memac_init(struct fman_mac *m - add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0); - } - -- fixed_link = memac_drv_param->fixed_link; -- -- init(memac->regs, memac->memac_drv_param, memac->phy_if, -- memac->max_speed, slow_10g_if, memac->exceptions); -+ init(memac->regs, memac->memac_drv_param, memac->exceptions); - - /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround - * Exists only in FMan 6.0 and 6.3. -@@ -937,11 +943,6 @@ static int memac_init(struct fman_mac *m - iowrite32be(reg32, &memac->regs->command_config); - } - -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) -- setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); -- else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) -- setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); -- - /* Max Frame Length */ - err = fman_set_mac_max_frame(memac->fm, memac->mac_id, - memac_drv_param->max_frame_length); -@@ -970,9 +971,6 @@ static int memac_init(struct fman_mac *m - fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, - FMAN_INTR_TYPE_NORMAL, memac_exception, memac); - -- kfree(memac_drv_param); -- memac->memac_drv_param = NULL; -- - return 0; - } - -@@ -995,7 +993,6 @@ static int memac_free(struct fman_mac *m - pcs_put(memac->sgmii_pcs); - pcs_put(memac->qsgmii_pcs); - pcs_put(memac->xfi_pcs); -- - kfree(memac->memac_drv_param); - kfree(memac); - -@@ -1028,8 +1025,6 @@ static struct fman_mac *memac_config(str - memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); - - memac->regs = mac_dev->vaddr; -- memac->max_speed = params->max_speed; -- memac->phy_if = mac_dev->phy_if; - memac->mac_id = params->mac_id; - memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | - MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI); -@@ -1037,7 +1032,6 @@ static struct fman_mac *memac_config(str - memac->event_cb = params->event_cb; - memac->dev_id = mac_dev; - memac->fm = params->fm; -- memac->basex_if = params->basex_if; - - /* Save FMan revision */ - fman_get_revision(memac->fm, &memac->fm_rev_info); -@@ -1064,37 +1058,44 @@ static struct phylink_pcs *memac_pcs_cre - return pcs; - } - -+static bool memac_supports(struct mac_device *mac_dev, phy_interface_t iface) -+{ -+ /* If there's no serdes device, assume that it's been configured for -+ * whatever the default interface mode is. -+ */ -+ if (!mac_dev->fman_mac->serdes) -+ return mac_dev->phy_if == iface; -+ /* Otherwise, ask the serdes */ -+ return !phy_validate(mac_dev->fman_mac->serdes, PHY_MODE_ETHERNET, -+ iface, NULL); -+} -+ - int memac_initialization(struct mac_device *mac_dev, - struct device_node *mac_node, - struct fman_mac_params *params) - { - int err; -+ struct device_node *fixed; - struct phylink_pcs *pcs; -- struct fixed_phy_status *fixed_link; - struct fman_mac *memac; -+ unsigned long capabilities; -+ unsigned long *supported; - -+ mac_dev->phylink_ops = &memac_mac_ops; - mac_dev->set_promisc = memac_set_promiscuous; - mac_dev->change_addr = memac_modify_mac_address; - mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = memac_del_hash_mac_address; -- mac_dev->set_tx_pause = memac_set_tx_pause_frames; -- mac_dev->set_rx_pause = memac_accept_rx_pause_frames; - mac_dev->set_exception = memac_set_exception; - mac_dev->set_allmulti = memac_set_allmulti; - mac_dev->set_tstamp = memac_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = adjust_link_memac; - mac_dev->enable = memac_enable; - mac_dev->disable = memac_disable; - -- if (params->max_speed == SPEED_10000) -- mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII; -- - mac_dev->fman_mac = memac_config(mac_dev, params); -- if (!mac_dev->fman_mac) { -- err = -EINVAL; -- goto _return; -- } -+ if (!mac_dev->fman_mac) -+ return -EINVAL; - - memac = mac_dev->fman_mac; - memac->memac_drv_param->max_frame_length = fman_get_max_frm(); -@@ -1136,9 +1137,9 @@ int memac_initialization(struct mac_devi - else - pcs = memac_pcs_create(mac_node, err); - -- if (!pcs) { -- dev_err(mac_dev->dev, "missing pcs\n"); -- err = -ENOENT; -+ if (IS_ERR(pcs)) { -+ err = PTR_ERR(pcs); -+ dev_err_probe(mac_dev->dev, err, "missing pcs\n"); - goto _return_fm_mac_free; - } - -@@ -1159,84 +1160,100 @@ int memac_initialization(struct mac_devi - } else if (IS_ERR(memac->serdes)) { - dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); - goto _return_fm_mac_free; -- } else { -- err = phy_init(memac->serdes); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not initialize serdes\n"); -- goto _return_fm_mac_free; -- } -- -- err = phy_power_on(memac->serdes); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not power on serdes\n"); -- goto _return_phy_exit; -- } -- -- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || -- memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || -- memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || -- memac->phy_if == PHY_INTERFACE_MODE_QSGMII || -- memac->phy_if == PHY_INTERFACE_MODE_XGMII) { -- err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, -- memac->phy_if); -- if (err) { -- dev_err_probe(mac_dev->dev, err, -- "could not set serdes mode to %s\n", -- phy_modes(memac->phy_if)); -- goto _return_phy_power_off; -- } -- } - } - -- if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { -- struct phy_device *phy; -- -- err = of_phy_register_fixed_link(mac_node); -- if (err) -- goto _return_phy_power_off; -- -- fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); -- if (!fixed_link) { -- err = -ENOMEM; -- goto _return_phy_power_off; -- } -+ /* The internal connection to the serdes is XGMII, but this isn't -+ * really correct for the phy mode (which is the external connection). -+ * However, this is how all older device trees say that they want -+ * 10GBASE-R (aka XFI), so just convert it for them. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ mac_dev->phy_if = PHY_INTERFACE_MODE_10GBASER; - -- mac_dev->phy_node = of_node_get(mac_node); -- phy = of_phy_find_device(mac_dev->phy_node); -- if (!phy) { -- err = -EINVAL; -- of_node_put(mac_dev->phy_node); -- goto _return_fixed_link_free; -- } -+ /* TODO: The following interface modes are supported by (some) hardware -+ * but not by this driver: -+ * - 1000BASE-KX -+ * - 10GBASE-KR -+ * - XAUI/HiGig -+ */ -+ supported = mac_dev->phylink_config.supported_interfaces; - -- fixed_link->link = phy->link; -- fixed_link->speed = phy->speed; -- fixed_link->duplex = phy->duplex; -- fixed_link->pause = phy->pause; -- fixed_link->asym_pause = phy->asym_pause; -+ /* Note that half duplex is only supported on 10/100M interfaces. */ - -- put_device(&phy->mdio.dev); -- memac->memac_drv_param->fixed_link = fixed_link; -+ if (memac->sgmii_pcs && -+ (memac_supports(mac_dev, PHY_INTERFACE_MODE_SGMII) || -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_1000BASEX))) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); -+ } -+ -+ if (memac->sgmii_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_2500BASEX)) -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -+ -+ if (memac->qsgmii_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_QSGMII)) -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, supported); -+ else if (mac_dev->phy_if == PHY_INTERFACE_MODE_QSGMII) -+ dev_warn(mac_dev->dev, "no QSGMII pcs specified\n"); -+ -+ if (memac->xfi_pcs && -+ memac_supports(mac_dev, PHY_INTERFACE_MODE_10GBASER)) { -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ } else { -+ /* From what I can tell, no 10g macs support RGMII. */ -+ phy_interface_set_rgmii(supported); -+ __set_bit(PHY_INTERFACE_MODE_MII, supported); - } - -+ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100; -+ capabilities |= MAC_1000FD | MAC_2500FD | MAC_10000FD; -+ -+ /* These SoCs don't support half duplex at all; there's no different -+ * FMan version or compatible, so we just have to check the machine -+ * compatible instead -+ */ -+ if (of_machine_is_compatible("fsl,ls1043a") || -+ of_machine_is_compatible("fsl,ls1046a") || -+ of_machine_is_compatible("fsl,B4QDS")) -+ capabilities &= ~(MAC_10HD | MAC_100HD); -+ -+ mac_dev->phylink_config.mac_capabilities = capabilities; -+ -+ /* The T2080 and T4240 don't support half duplex RGMII. There is no -+ * other way to identify these SoCs, so just use the machine -+ * compatible. -+ */ -+ if (of_machine_is_compatible("fsl,T2080QDS") || -+ of_machine_is_compatible("fsl,T2080RDB") || -+ of_machine_is_compatible("fsl,T2081QDS") || -+ of_machine_is_compatible("fsl,T4240QDS") || -+ of_machine_is_compatible("fsl,T4240RDB")) -+ memac->rgmii_no_half_duplex = true; -+ -+ /* Most boards should use MLO_AN_INBAND, but existing boards don't have -+ * a managed property. Default to MLO_AN_INBAND if nothing else is -+ * specified. We need to be careful and not enable this if we have a -+ * fixed link or if we are using MII or RGMII, since those -+ * configurations modes don't use in-band autonegotiation. -+ */ -+ fixed = of_get_child_by_name(mac_node, "fixed-link"); -+ if (!fixed && !of_property_read_bool(mac_node, "fixed-link") && -+ !of_property_read_bool(mac_node, "managed") && -+ mac_dev->phy_if != PHY_INTERFACE_MODE_MII && -+ !phy_interface_mode_is_rgmii(mac_dev->phy_if)) -+ mac_dev->phylink_config.ovr_an_inband = true; -+ of_node_put(fixed); -+ - err = memac_init(mac_dev->fman_mac); - if (err < 0) -- goto _return_fixed_link_free; -+ goto _return_fm_mac_free; - - dev_info(mac_dev->dev, "FMan MEMAC\n"); - -- goto _return; -+ return 0; - --_return_phy_power_off: -- phy_power_off(memac->serdes); --_return_phy_exit: -- phy_exit(memac->serdes); --_return_fixed_link_free: -- kfree(fixed_link); - _return_fm_mac_free: - memac_free(mac_dev->fman_mac); --_return: - return err; - } ---- a/drivers/net/ethernet/freescale/fman/fman_tgec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - /* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ - #define TGEC_TX_IPG_LENGTH_MASK 0x000003ff -@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem - - static int check_init_parameters(struct fman_mac *tgec) - { -- if (tgec->max_speed < SPEED_10000) { -- pr_err("10G MAC driver only support 10G speed\n"); -- return -EINVAL; -- } - if (!tgec->exception_cb) { - pr_err("uninitialized exception_cb\n"); - return -EINVAL; -@@ -384,40 +381,13 @@ static void free_init_resources(struct f - tgec->unicast_addr_hash = NULL; - } - --static bool is_init_done(struct tgec_cfg *cfg) --{ -- /* Checks if tGEC driver parameters were initialized */ -- if (!cfg) -- return true; -- -- return false; --} -- - static int tgec_enable(struct fman_mac *tgec) - { -- struct tgec_regs __iomem *regs = tgec->regs; -- u32 tmp; -- -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- -- tmp = ioread32be(®s->command_config); -- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -- iowrite32be(tmp, ®s->command_config); -- - return 0; - } - - static void tgec_disable(struct fman_mac *tgec) - { -- struct tgec_regs __iomem *regs = tgec->regs; -- u32 tmp; -- -- WARN_ON_ONCE(!is_init_done(tgec->cfg)); -- -- tmp = ioread32be(®s->command_config); -- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -- iowrite32be(tmp, ®s->command_config); - } - - static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val) -@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct f - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (new_val) - tmp |= CMD_CFG_PROMIS_EN; -@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(stru - { - struct tgec_regs __iomem *regs = tgec->regs; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - iowrite32be((u32)pause_time, ®s->pause_quant); - - return 0; -@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(s - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - if (!en) - tmp |= CMD_CFG_PAUSE_IGNORE; -@@ -470,12 +431,53 @@ static int tgec_accept_rx_pause_frames(s - return 0; - } - -+static void tgec_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ -+static void tgec_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 mac_device *mac_dev = fman_config_to_mac(config); -+ struct fman_mac *tgec = mac_dev->fman_mac; -+ struct tgec_regs __iomem *regs = tgec->regs; -+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : -+ FSL_FM_PAUSE_TIME_DISABLE; -+ u32 tmp; -+ -+ tgec_set_tx_pause_frames(tgec, 0, pause_time, 0); -+ tgec_accept_rx_pause_frames(tgec, rx_pause); -+ mac_dev->update_speed(mac_dev, speed); -+ -+ tmp = ioread32be(®s->command_config); -+ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static void tgec_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac; -+ struct tgec_regs __iomem *regs = tgec->regs; -+ u32 tmp; -+ -+ tmp = ioread32be(®s->command_config); -+ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); -+ iowrite32be(tmp, ®s->command_config); -+} -+ -+static const struct phylink_mac_ops tgec_mac_ops = { -+ .validate = phylink_generic_validate, -+ .mac_config = tgec_mac_config, -+ .mac_link_up = tgec_link_up, -+ .mac_link_down = tgec_link_down, -+}; -+ - static int tgec_modify_mac_address(struct fman_mac *tgec, - const enet_addr_t *p_enet_addr) - { -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); - set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr)); - -@@ -490,9 +492,6 @@ static int tgec_add_hash_mac_address(str - u32 crc = 0xFFFFFFFF, hash; - u64 addr; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - addr = ENET_ADDR_TO_UINT64(*eth_addr); - - if (!(addr & GROUP_ADDRESS)) { -@@ -525,9 +524,6 @@ static int tgec_set_allmulti(struct fman - u32 entry; - struct tgec_regs __iomem *regs = tgec->regs; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - if (enable) { - for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++) - iowrite32be(entry | TGEC_HASH_MCAST_EN, -@@ -548,9 +544,6 @@ static int tgec_set_tstamp(struct fman_m - struct tgec_regs __iomem *regs = tgec->regs; - u32 tmp; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - tmp = ioread32be(®s->command_config); - - if (enable) -@@ -572,9 +565,6 @@ static int tgec_del_hash_mac_address(str - u32 crc = 0xFFFFFFFF, hash; - u64 addr; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - addr = ((*(u64 *)eth_addr) >> 16); - - /* CRC calculation */ -@@ -601,22 +591,12 @@ static int tgec_del_hash_mac_address(str - return 0; - } - --static void tgec_adjust_link(struct mac_device *mac_dev) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- -- mac_dev->update_speed(mac_dev, phy_dev->speed); --} -- - static int tgec_set_exception(struct fman_mac *tgec, - enum fman_mac_exceptions exception, bool enable) - { - struct tgec_regs __iomem *regs = tgec->regs; - u32 bit_mask = 0; - -- if (!is_init_done(tgec->cfg)) -- return -EINVAL; -- - bit_mask = get_exception_flag(exception); - if (bit_mask) { - if (enable) -@@ -641,9 +621,6 @@ static int tgec_init(struct fman_mac *tg - enet_addr_t eth_addr; - int err; - -- if (is_init_done(tgec->cfg)) -- return -EINVAL; -- - if (DEFAULT_RESET_ON_INIT && - (fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) { - pr_err("Can't reset MAC!\n"); -@@ -753,7 +730,6 @@ static struct fman_mac *tgec_config(stru - - tgec->regs = mac_dev->vaddr; - tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); -- tgec->max_speed = params->max_speed; - tgec->mac_id = params->mac_id; - tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT | - TGEC_IMASK_REM_FAULT | -@@ -788,17 +764,15 @@ int tgec_initialization(struct mac_devic - int err; - struct fman_mac *tgec; - -+ mac_dev->phylink_ops = &tgec_mac_ops; - mac_dev->set_promisc = tgec_set_promiscuous; - mac_dev->change_addr = tgec_modify_mac_address; - mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address; -- mac_dev->set_tx_pause = tgec_set_tx_pause_frames; -- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames; - mac_dev->set_exception = tgec_set_exception; - mac_dev->set_allmulti = tgec_set_allmulti; - mac_dev->set_tstamp = tgec_set_tstamp; - mac_dev->set_multi = fman_set_multi; -- mac_dev->adjust_link = tgec_adjust_link; - mac_dev->enable = tgec_enable; - mac_dev->disable = tgec_disable; - -@@ -808,6 +782,19 @@ int tgec_initialization(struct mac_devic - goto _return; - } - -+ /* The internal connection to the serdes is XGMII, but this isn't -+ * really correct for the phy mode (which is the external connection). -+ * However, this is how all older device trees say that they want -+ * XAUI, so just convert it for them. -+ */ -+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -+ mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI; -+ -+ __set_bit(PHY_INTERFACE_MODE_XAUI, -+ mac_dev->phylink_config.supported_interfaces); -+ mac_dev->phylink_config.mac_capabilities = -+ MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD; -+ - tgec = mac_dev->fman_mac; - tgec->cfg->max_frame_length = fman_get_max_frm(); - err = tgec_init(tgec); ---- a/drivers/net/ethernet/freescale/fman/mac.c -+++ b/drivers/net/ethernet/freescale/fman/mac.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -93,130 +94,8 @@ int fman_set_multi(struct net_device *ne - return 0; - } - --/** -- * fman_set_mac_active_pause -- * @mac_dev: A pointer to the MAC device -- * @rx: Pause frame setting for RX -- * @tx: Pause frame setting for TX -- * -- * Set the MAC RX/TX PAUSE frames settings -- * -- * Avoid redundant calls to FMD, if the MAC driver already contains the desired -- * active PAUSE settings. Otherwise, the new active settings should be reflected -- * in FMan. -- * -- * Return: 0 on success; Error code otherwise. -- */ --int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) --{ -- struct fman_mac *fman_mac = mac_dev->fman_mac; -- int err = 0; -- -- if (rx != mac_dev->rx_pause_active) { -- err = mac_dev->set_rx_pause(fman_mac, rx); -- if (likely(err == 0)) -- mac_dev->rx_pause_active = rx; -- } -- -- if (tx != mac_dev->tx_pause_active) { -- u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE : -- FSL_FM_PAUSE_TIME_DISABLE); -- -- err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0); -- -- if (likely(err == 0)) -- mac_dev->tx_pause_active = tx; -- } -- -- return err; --} --EXPORT_SYMBOL(fman_set_mac_active_pause); -- --/** -- * fman_get_pause_cfg -- * @mac_dev: A pointer to the MAC device -- * @rx_pause: Return value for RX setting -- * @tx_pause: Return value for TX setting -- * -- * Determine the MAC RX/TX PAUSE frames settings based on PHY -- * autonegotiation or values set by eththool. -- * -- * Return: Pointer to FMan device. -- */ --void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, -- bool *tx_pause) --{ -- struct phy_device *phy_dev = mac_dev->phy_dev; -- u16 lcl_adv, rmt_adv; -- u8 flowctrl; -- -- *rx_pause = *tx_pause = false; -- -- if (!phy_dev->duplex) -- return; -- -- /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings -- * are those set by ethtool. -- */ -- if (!mac_dev->autoneg_pause) { -- *rx_pause = mac_dev->rx_pause_req; -- *tx_pause = mac_dev->tx_pause_req; -- return; -- } -- -- /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE -- * settings depend on the result of the link negotiation. -- */ -- -- /* get local capabilities */ -- lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising); -- -- /* get link partner capabilities */ -- rmt_adv = 0; -- if (phy_dev->pause) -- rmt_adv |= LPA_PAUSE_CAP; -- if (phy_dev->asym_pause) -- rmt_adv |= LPA_PAUSE_ASYM; -- -- /* Calculate TX/RX settings based on local and peer advertised -- * symmetric/asymmetric PAUSE capabilities. -- */ -- flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); -- if (flowctrl & FLOW_CTRL_RX) -- *rx_pause = true; -- if (flowctrl & FLOW_CTRL_TX) -- *tx_pause = true; --} --EXPORT_SYMBOL(fman_get_pause_cfg); -- --#define DTSEC_SUPPORTED \ -- (SUPPORTED_10baseT_Half \ -- | SUPPORTED_10baseT_Full \ -- | SUPPORTED_100baseT_Half \ -- | SUPPORTED_100baseT_Full \ -- | SUPPORTED_Autoneg \ -- | SUPPORTED_Pause \ -- | SUPPORTED_Asym_Pause \ -- | SUPPORTED_FIBRE \ -- | SUPPORTED_MII) -- - static DEFINE_MUTEX(eth_lock); - --static const u16 phy2speed[] = { -- [PHY_INTERFACE_MODE_MII] = SPEED_100, -- [PHY_INTERFACE_MODE_GMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_TBI] = SPEED_1000, -- [PHY_INTERFACE_MODE_RMII] = SPEED_100, -- [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, -- [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, -- [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000, -- [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 --}; -- - static struct platform_device *dpaa_eth_add_device(int fman_id, - struct mac_device *mac_dev) - { -@@ -263,8 +142,8 @@ no_mem: - } - - static const struct of_device_id mac_match[] = { -- { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, -- { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, -+ { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, -+ { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, - { .compatible = "fsl,fman-memac", .data = memac_initialization }, - {} - }; -@@ -295,6 +174,7 @@ static int mac_probe(struct platform_dev - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ platform_set_drvdata(_of_dev, mac_dev); - - /* Save private information */ - mac_dev->priv = priv; -@@ -424,57 +304,21 @@ static int mac_probe(struct platform_dev - } - mac_dev->phy_if = phy_if; - -- priv->speed = phy2speed[mac_dev->phy_if]; -- params.max_speed = priv->speed; -- mac_dev->if_support = DTSEC_SUPPORTED; -- /* We don't support half-duplex in SGMII mode */ -- if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) -- mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | -- SUPPORTED_100baseT_Half); -- -- /* Gigabit support (no half-duplex) */ -- if (params.max_speed == 1000) -- mac_dev->if_support |= SUPPORTED_1000baseT_Full; -- -- /* The 10G interface only supports one mode */ -- if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) -- mac_dev->if_support = SUPPORTED_10000baseT_Full; -- -- /* Get the rest of the PHY information */ -- mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); -- -- params.basex_if = false; - params.mac_id = priv->cell_index; - params.fm = (void *)priv->fman; - params.exception_cb = mac_exception; - params.event_cb = mac_exception; - - err = init(mac_dev, mac_node, ¶ms); -- if (err < 0) { -- dev_err(dev, "mac_dev->init() = %d\n", err); -- of_node_put(mac_dev->phy_node); -- return err; -- } -- -- /* pause frame autonegotiation enabled */ -- mac_dev->autoneg_pause = true; -- -- /* By intializing the values to false, force FMD to enable PAUSE frames -- * on RX and TX -- */ -- mac_dev->rx_pause_req = true; -- mac_dev->tx_pause_req = true; -- mac_dev->rx_pause_active = false; -- mac_dev->tx_pause_active = false; -- err = fman_set_mac_active_pause(mac_dev, true, true); - if (err < 0) -- dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); -+ return err; - - if (!is_zero_ether_addr(mac_dev->addr)) - dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); - - priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); - if (IS_ERR(priv->eth_dev)) { -+ err = PTR_ERR(priv->eth_dev); - dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", - priv->cell_index); - priv->eth_dev = NULL; ---- a/drivers/net/ethernet/freescale/fman/mac.h -+++ b/drivers/net/ethernet/freescale/fman/mac.h -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - - #include "fman_port.h" -@@ -24,32 +25,22 @@ struct mac_device { - struct resource *res; - u8 addr[ETH_ALEN]; - struct fman_port *port[2]; -- u32 if_support; -- struct phy_device *phy_dev; -+ struct phylink *phylink; -+ struct phylink_config phylink_config; - phy_interface_t phy_if; -- struct device_node *phy_node; -- struct net_device *net_dev; - -- bool autoneg_pause; -- bool rx_pause_req; -- bool tx_pause_req; -- bool rx_pause_active; -- bool tx_pause_active; - bool promisc; - bool allmulti; - -+ const struct phylink_mac_ops *phylink_ops; - int (*enable)(struct fman_mac *mac_dev); - void (*disable)(struct fman_mac *mac_dev); -- void (*adjust_link)(struct mac_device *mac_dev); - int (*set_promisc)(struct fman_mac *mac_dev, bool enable); - int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr); - int (*set_allmulti)(struct fman_mac *mac_dev, bool enable); - int (*set_tstamp)(struct fman_mac *mac_dev, bool enable); - int (*set_multi)(struct net_device *net_dev, - struct mac_device *mac_dev); -- int (*set_rx_pause)(struct fman_mac *mac_dev, bool en); -- int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority, -- u16 pause_time, u16 thresh_time); - int (*set_exception)(struct fman_mac *mac_dev, - enum fman_mac_exceptions exception, bool enable); - int (*add_hash_mac_addr)(struct fman_mac *mac_dev, -@@ -63,6 +54,12 @@ struct mac_device { - struct mac_priv_s *priv; - }; - -+static inline struct mac_device -+*fman_config_to_mac(struct phylink_config *config) -+{ -+ return container_of(config, struct mac_device, phylink_config); -+} -+ - struct dpaa_eth_data { - struct mac_device *mac_dev; - int mac_hw_id; diff --git a/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch b/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch deleted file mode 100644 index 06c348b1cd..0000000000 --- a/target/linux/generic/backport-6.6/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch +++ /dev/null @@ -1,93 +0,0 @@ -From bf4de031052fe7c5309e8956c342d4e5ce79038e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Mon, 17 Oct 2022 16:22:35 -0400 -Subject: [PATCH 04/21] net: phylink: provide phylink_validate_mask_caps() - helper - -Provide a helper that restricts the link modes according to the -phylink capabilities. - -Signed-off-by: Russell King (Oracle) -[rebased on net-next/master and added documentation] -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 41 +++++++++++++++++++++++++++------------ - include/linux/phylink.h | 3 +++ - 2 files changed, 32 insertions(+), 12 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -564,31 +564,48 @@ unsigned long phylink_get_capabilities(p - EXPORT_SYMBOL_GPL(phylink_get_capabilities); - - /** -- * phylink_generic_validate() - generic validate() callback implementation -- * @config: a pointer to a &struct phylink_config. -+ * phylink_validate_mask_caps() - Restrict link modes based on caps - * @supported: ethtool bitmask for supported link modes. -- * @state: a pointer to a &struct phylink_link_state. -+ * @state: an (optional) pointer to a &struct phylink_link_state. -+ * @mac_capabilities: bitmask of MAC capabilities - * -- * Generic implementation of the validate() callback that MAC drivers can -- * use when they pass the range of supported interfaces and MAC capabilities. -- * This makes use of phylink_get_linkmodes(). -+ * Calculate the supported link modes based on @mac_capabilities, and restrict -+ * @supported and @state based on that. Use this function if your capabiliies -+ * aren't constant, such as if they vary depending on the interface. - */ --void phylink_generic_validate(struct phylink_config *config, -- unsigned long *supported, -- struct phylink_link_state *state) -+void phylink_validate_mask_caps(unsigned long *supported, -+ struct phylink_link_state *state, -+ unsigned long mac_capabilities) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - unsigned long caps; - - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); -- caps = phylink_get_capabilities(state->interface, -- config->mac_capabilities, -+ caps = phylink_get_capabilities(state->interface, mac_capabilities, - state->rate_matching); - phylink_caps_to_linkmodes(mask, caps); - - linkmode_and(supported, supported, mask); -- linkmode_and(state->advertising, state->advertising, mask); -+ if (state) -+ linkmode_and(state->advertising, state->advertising, mask); -+} -+EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); -+ -+/** -+ * phylink_generic_validate() - generic validate() callback implementation -+ * @config: a pointer to a &struct phylink_config. -+ * @supported: ethtool bitmask for supported link modes. -+ * @state: a pointer to a &struct phylink_link_state. -+ * -+ * Generic implementation of the validate() callback that MAC drivers can -+ * use when they pass the range of supported interfaces and MAC capabilities. -+ */ -+void phylink_generic_validate(struct phylink_config *config, -+ unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ phylink_validate_mask_caps(supported, state, config->mac_capabilities); - } - EXPORT_SYMBOL_GPL(phylink_generic_validate); - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -558,6 +558,9 @@ void phylink_caps_to_linkmodes(unsigned - unsigned long phylink_get_capabilities(phy_interface_t interface, - unsigned long mac_capabilities, - int rate_matching); -+void phylink_validate_mask_caps(unsigned long *supported, -+ struct phylink_link_state *state, -+ unsigned long caps); - void phylink_generic_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch b/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch deleted file mode 100644 index e3a1dda688..0000000000 --- a/target/linux/generic/backport-6.6/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2bf7e4a68c42eed909f3c29582e1fb85cb157e35 Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Tue, 25 Oct 2022 11:51:26 -0700 -Subject: [PATCH 05/21] phylink: require valid state argument to - phylink_validate_mask_caps() - -state is deferenced earlier in the function, the NULL check -is pointless. Since we don't have any crash reports presumably -it's safe to assume state is not NULL. - -Fixes: f392a1846489 ("net: phylink: provide phylink_validate_mask_caps() helper") -Reviewed-by: Sean Anderson -Link: https://lore.kernel.org/r/20221025185126.1720553-1-kuba@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -566,7 +566,7 @@ EXPORT_SYMBOL_GPL(phylink_get_capabiliti - /** - * phylink_validate_mask_caps() - Restrict link modes based on caps - * @supported: ethtool bitmask for supported link modes. -- * @state: an (optional) pointer to a &struct phylink_link_state. -+ * @state: pointer to a &struct phylink_link_state. - * @mac_capabilities: bitmask of MAC capabilities - * - * Calculate the supported link modes based on @mac_capabilities, and restrict -@@ -587,8 +587,7 @@ void phylink_validate_mask_caps(unsigned - phylink_caps_to_linkmodes(mask, caps); - - linkmode_and(supported, supported, mask); -- if (state) -- linkmode_and(state->advertising, state->advertising, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); - diff --git a/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch b/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch deleted file mode 100644 index c217ed87b5..0000000000 --- a/target/linux/generic/backport-6.6/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f8fc363bf0c023e4736a0328174b4a24b44ab23a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:37 +0100 -Subject: [PATCH 06/21] net: phylink: add phylink_get_link_timer_ns() helper - -Add a helper to convert the PHY interface mode to the required link -timer setting as stated by the appropriate standard. Inappropriate -interface modes return an error. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - include/linux/phylink.h | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -617,6 +617,30 @@ int phylink_speed_up(struct phylink *pl) - - void phylink_set_port_modes(unsigned long *bits); - -+/** -+ * phylink_get_link_timer_ns - return the PCS link timer value -+ * @interface: link &typedef phy_interface_t mode -+ * -+ * Return the PCS link timer setting in nanoseconds for the PHY @interface -+ * mode, or -EINVAL if not appropriate. -+ */ -+static inline int phylink_get_link_timer_ns(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: -+ return 1600000; -+ -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return 10000000; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ - void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, - u16 bmsr, u16 lpa); - void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, diff --git a/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch b/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch deleted file mode 100644 index 28154af920..0000000000 --- a/target/linux/generic/backport-6.6/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch +++ /dev/null @@ -1,250 +0,0 @@ -From b45b773a96b0e9e8d51e5d005485f4e376d6ce9a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 4 Nov 2022 17:13:01 +0000 -Subject: [PATCH 07/21] net: remove explicit phylink_generic_validate() - references - -Virtually all conventional network drivers are now converted to use -phylink_generic_validate() - only DSA drivers and fman_memac remain, -so lets remove the necessity for network drivers to explicitly set -this member, and default to phylink_generic_validate() when unset. -This is possible as .validate must currently be set. - -Any remaining instances that have not been addressed by this patch can -be fixed up later. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Vladimir Oltean -Link: https://lore.kernel.org/r/E1or0FZ-001tRa-DI@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/altera/altera_tse_main.c | 1 - - drivers/net/ethernet/atheros/ag71xx.c | 1 - - drivers/net/ethernet/cadence/macb_main.c | 1 - - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 1 - - drivers/net/ethernet/freescale/enetc/enetc_pf.c | 1 - - drivers/net/ethernet/freescale/fman/fman_dtsec.c | 1 - - drivers/net/ethernet/freescale/fman/fman_tgec.c | 1 - - drivers/net/ethernet/marvell/mvneta.c | 1 - - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 - - drivers/net/ethernet/marvell/prestera/prestera_main.c | 1 - - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - - drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c | 1 - - drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c | 1 - - drivers/net/ethernet/mscc/ocelot_net.c | 1 - - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 - - drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 - - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 - - drivers/net/phy/phylink.c | 5 ++++- - drivers/net/usb/asix_devices.c | 1 - - include/linux/phylink.h | 5 +++++ - 20 files changed, 9 insertions(+), 19 deletions(-) - ---- a/drivers/net/ethernet/altera/altera_tse_main.c -+++ b/drivers/net/ethernet/altera/altera_tse_main.c -@@ -1096,7 +1096,6 @@ static struct phylink_pcs *alt_tse_selec - } - - static const struct phylink_mac_ops alt_tse_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_an_restart = alt_tse_mac_an_restart, - .mac_config = alt_tse_mac_config, - .mac_link_down = alt_tse_mac_link_down, ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1086,7 +1086,6 @@ static void ag71xx_mac_link_up(struct ph - } - - static const struct phylink_mac_ops ag71xx_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = ag71xx_mac_config, - .mac_link_down = ag71xx_mac_link_down, - .mac_link_up = ag71xx_mac_link_up, ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -752,7 +752,6 @@ static struct phylink_pcs *macb_mac_sele - } - - static const struct phylink_mac_ops macb_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = macb_mac_select_pcs, - .mac_config = macb_mac_config, - .mac_link_down = macb_mac_link_down, ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -235,7 +235,6 @@ static void dpaa2_mac_link_down(struct p - } - - static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = dpaa2_mac_select_pcs, - .mac_config = dpaa2_mac_config, - .mac_link_up = dpaa2_mac_link_up, ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -1111,7 +1111,6 @@ static void enetc_pl_mac_link_down(struc - } - - static const struct phylink_mac_ops enetc_mac_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = enetc_pl_mac_select_pcs, - .mac_config = enetc_pl_mac_config, - .mac_link_up = enetc_pl_mac_link_up, ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -986,7 +986,6 @@ static void dtsec_link_down(struct phyli - } - - static const struct phylink_mac_ops dtsec_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = dtsec_select_pcs, - .mac_config = dtsec_mac_config, - .mac_link_up = dtsec_link_up, ---- a/drivers/net/ethernet/freescale/fman/fman_tgec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c -@@ -469,7 +469,6 @@ static void tgec_link_down(struct phylin - } - - static const struct phylink_mac_ops tgec_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = tgec_mac_config, - .mac_link_up = tgec_link_up, - .mac_link_down = tgec_link_down, ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -4228,7 +4228,6 @@ static void mvneta_mac_link_up(struct ph - } - - static const struct phylink_mac_ops mvneta_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mvneta_mac_select_pcs, - .mac_prepare = mvneta_mac_prepare, - .mac_config = mvneta_mac_config, ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6633,7 +6633,6 @@ static void mvpp2_mac_link_down(struct p - } - - static const struct phylink_mac_ops mvpp2_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mvpp2_select_pcs, - .mac_prepare = mvpp2_mac_prepare, - .mac_config = mvpp2_mac_config, ---- a/drivers/net/ethernet/marvell/prestera/prestera_main.c -+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c -@@ -360,7 +360,6 @@ static void prestera_pcs_an_restart(stru - } - - static const struct phylink_mac_ops prestera_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = prestera_mac_select_pcs, - .mac_config = prestera_mac_config, - .mac_link_down = prestera_mac_link_down, ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -654,7 +654,6 @@ static void mtk_mac_link_up(struct phyli - } - - static const struct phylink_mac_ops mtk_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = mtk_mac_select_pcs, - .mac_pcs_get_state = mtk_mac_pcs_get_state, - .mac_config = mtk_mac_config, ---- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c -+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c -@@ -125,7 +125,6 @@ static void lan966x_pcs_aneg_restart(str - } - - const struct phylink_mac_ops lan966x_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = lan966x_phylink_mac_select, - .mac_config = lan966x_phylink_mac_config, - .mac_prepare = lan966x_phylink_mac_prepare, ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -@@ -138,7 +138,6 @@ const struct phylink_pcs_ops sparx5_phyl - }; - - const struct phylink_mac_ops sparx5_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = sparx5_phylink_mac_select_pcs, - .mac_config = sparx5_phylink_mac_config, - .mac_link_down = sparx5_phylink_mac_link_down, ---- a/drivers/net/ethernet/mscc/ocelot_net.c -+++ b/drivers/net/ethernet/mscc/ocelot_net.c -@@ -1737,7 +1737,6 @@ static void vsc7514_phylink_mac_link_up( - } - - static const struct phylink_mac_ops ocelot_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_config = vsc7514_phylink_mac_config, - .mac_link_down = vsc7514_phylink_mac_link_down, - .mac_link_up = vsc7514_phylink_mac_link_up, ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -1090,7 +1090,6 @@ static void stmmac_mac_link_up(struct ph - } - - static const struct phylink_mac_ops stmmac_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = stmmac_mac_select_pcs, - .mac_config = stmmac_mac_config, - .mac_link_down = stmmac_mac_link_down, ---- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c -+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c -@@ -1493,7 +1493,6 @@ static void am65_cpsw_nuss_mac_link_up(s - } - - static const struct phylink_mac_ops am65_cpsw_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = am65_cpsw_nuss_mac_config, - .mac_link_down = am65_cpsw_nuss_mac_link_down, - .mac_link_up = am65_cpsw_nuss_mac_link_up, ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1736,7 +1736,6 @@ static void axienet_mac_link_up(struct p - } - - static const struct phylink_mac_ops axienet_phylink_ops = { -- .validate = phylink_generic_validate, - .mac_select_pcs = axienet_mac_select_pcs, - .mac_config = axienet_mac_config, - .mac_link_down = axienet_mac_link_down, ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -651,7 +651,10 @@ static int phylink_validate_mac_and_pcs( - } - - /* Then validate the link parameters with the MAC */ -- pl->mac_ops->validate(pl->config, supported, state); -+ if (pl->mac_ops->validate) -+ pl->mac_ops->validate(pl->config, supported, state); -+ else -+ phylink_generic_validate(pl->config, supported, state); - - return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; - } ---- a/drivers/net/usb/asix_devices.c -+++ b/drivers/net/usb/asix_devices.c -@@ -787,7 +787,6 @@ static void ax88772_mac_link_up(struct p - } - - static const struct phylink_mac_ops ax88772_phylink_mac_ops = { -- .validate = phylink_generic_validate, - .mac_config = ax88772_mac_config, - .mac_link_down = ax88772_mac_link_down, - .mac_link_up = ax88772_mac_link_up, ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -207,6 +207,11 @@ struct phylink_mac_ops { - * - * If the @state->interface mode is not supported, then the @supported - * mask must be cleared. -+ * -+ * This member is optional; if not set, the generic validator will be -+ * used making use of @config->mac_capabilities and -+ * @config->supported_interfaces to determine which link modes are -+ * supported. - */ - void validate(struct phylink_config *config, unsigned long *supported, - struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch b/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch deleted file mode 100644 index 37d82b2cd7..0000000000 --- a/target/linux/generic/backport-6.6/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch +++ /dev/null @@ -1,48 +0,0 @@ -From a90ac762d345890b40d88a1385a34a2449c2d75e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 24 Mar 2023 09:23:42 +0000 -Subject: [PATCH] net: sfp: make sfp_bus_find_fwnode() take a const fwnode - -sfp_bus_find_fwnode() does not write to the fwnode, so let's make it -const. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/phy/sfp-bus.c | 2 +- - include/linux/sfp.h | 5 +++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -603,7 +603,7 @@ static void sfp_upstream_clear(struct sf - * - %-ENOMEM if we failed to allocate the bus. - * - an error from the upstream's connect_phy() method. - */ --struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) -+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) - { - struct fwnode_reference_args ref; - struct sfp_bus *bus; ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -548,7 +548,7 @@ int sfp_get_module_eeprom_by_page(struct - void sfp_upstream_start(struct sfp_bus *bus); - void sfp_upstream_stop(struct sfp_bus *bus); - void sfp_bus_put(struct sfp_bus *bus); --struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode); -+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); - int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, - const struct sfp_upstream_ops *ops); - void sfp_bus_del_upstream(struct sfp_bus *bus); -@@ -610,7 +610,8 @@ static inline void sfp_bus_put(struct sf - { - } - --static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) -+static inline struct sfp_bus * -+sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) - { - return NULL; - } diff --git a/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch b/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch deleted file mode 100644 index 290cb8d161..0000000000 --- a/target/linux/generic/backport-6.6/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ecec0ebbc6381a5a375f1cf10c4858f24e91e2ef Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 15 Mar 2023 14:46:49 +0000 -Subject: [PATCH] net: pcs: lynx: don't print an_enabled in pcs_get_state() - -an_enabled will be going away, and in any case, pcs_get_state() should -not be updating this member. Remove the print. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Steen Hegelund -Signed-off-by: David S. Miller ---- - drivers/net/pcs/pcs-lynx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -115,11 +115,11 @@ static void lynx_pcs_get_state(struct ph - } - - dev_dbg(&lynx->mdio->dev, -- "mode=%s/%s/%s link=%u an_enabled=%u an_complete=%u\n", -+ "mode=%s/%s/%s link=%u an_complete=%u\n", - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), -- state->link, state->an_enabled, state->an_complete); -+ state->link, state->an_complete); - } - - static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, diff --git a/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch deleted file mode 100644 index 38ea265476..0000000000 --- a/target/linux/generic/backport-6.6/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 99d0f3a1095f4c938b1665025c29411edafe8a01 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:44 +0000 -Subject: [PATCH] net: dpaa2-mac: use Autoneg bit rather than an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. Thus, we will be removing state->an_enabled. - -Use the Autoneg bit in the advertising bitmap to indicate whether -autonegotiation should be used, rather than using the an_enabled -member which will be going away. This means we use the same condition -as phylink_mii_c22_pcs_config(). - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -158,7 +158,8 @@ static void dpaa2_mac_config(struct phyl - struct dpmac_link_state *dpmac_state = &mac->state; - int err; - -- if (state->an_enabled) -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; - else - dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; diff --git a/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch b/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch deleted file mode 100644 index cb9c411cfb..0000000000 --- a/target/linux/generic/backport-6.6/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 471c40bde606ec0b1ce8c616f7998739c7a783a6 Mon Sep 17 00:00:00 2001 -From: Ivan Bornyakov -Date: Fri, 10 Feb 2023 18:46:27 +0300 -Subject: [PATCH 10/21] net: phylink: support validated pause and autoneg in - fixed-link - -In fixed-link setup phylink_parse_fixedlink() unconditionally sets -Pause, Asym_Pause and Autoneg bits to "supported" bitmap, while MAC may -not support these. - -This leads to ethtool reporting: - - > Supported pause frame use: Symmetric Receive-only - > Supports auto-negotiation: Yes - -regardless of what is actually supported. - -Instead of unconditionally set Pause, Asym_Pause and Autoneg it is -sensible to set them according to validated "supported" bitmap, i.e. the -result of phylink_validate(). - -Signed-off-by: Ivan Bornyakov -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -709,6 +709,7 @@ static int phylink_parse_fixedlink(struc - struct fwnode_handle *fwnode) - { - struct fwnode_handle *fixed_node; -+ bool pause, asym_pause, autoneg; - const struct phy_setting *s; - struct gpio_desc *desc; - u32 speed; -@@ -781,13 +782,23 @@ static int phylink_parse_fixedlink(struc - linkmode_copy(pl->link_config.advertising, pl->supported); - phylink_validate(pl, pl->supported, &pl->link_config); - -+ pause = phylink_test(pl->supported, Pause); -+ asym_pause = phylink_test(pl->supported, Asym_Pause); -+ autoneg = phylink_test(pl->supported, Autoneg); - s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex, - pl->supported, true); - linkmode_zero(pl->supported); - phylink_set(pl->supported, MII); -- phylink_set(pl->supported, Pause); -- phylink_set(pl->supported, Asym_Pause); -- phylink_set(pl->supported, Autoneg); -+ -+ if (pause) -+ phylink_set(pl->supported, Pause); -+ -+ if (asym_pause) -+ phylink_set(pl->supported, Asym_Pause); -+ -+ if (autoneg) -+ phylink_set(pl->supported, Autoneg); -+ - if (s) { - __set_bit(s->bit, pl->supported); - __set_bit(s->bit, pl->link_config.lp_advertising); diff --git a/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch b/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch deleted file mode 100644 index 03b4f9d0c4..0000000000 --- a/target/linux/generic/backport-6.6/715-12-v6.4-net-phylink-remove-an_enabled.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 7211ffd70941933a7825a56cf480f07ee81c321c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:54 +0000 -Subject: [PATCH 11/21] net: phylink: remove an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. state->an_enabled is now no longer used by any -drivers, so lets kill this duplication. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 37 +++++++++++++++++-------------------- - include/linux/phylink.h | 2 -- - 2 files changed, 17 insertions(+), 22 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -841,7 +841,6 @@ static int phylink_parse_mode(struct phy - phylink_set(pl->supported, Autoneg); - phylink_set(pl->supported, Asym_Pause); - phylink_set(pl->supported, Pause); -- pl->link_config.an_enabled = true; - pl->cfg_link_an_mode = MLO_AN_INBAND; - - switch (pl->link_config.interface) { -@@ -944,9 +943,6 @@ static int phylink_parse_mode(struct phy - "failed to validate link configuration for in-band status\n"); - return -EINVAL; - } -- -- /* Check if MAC/PCS also supports Autoneg. */ -- pl->link_config.an_enabled = phylink_test(pl->supported, Autoneg); - } - - return 0; -@@ -956,7 +952,8 @@ static void phylink_apply_manual_flow(st - struct phylink_link_state *state) - { - /* If autoneg is disabled, pause AN is also disabled */ -- if (!state->an_enabled) -+ if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - state->pause &= ~MLO_PAUSE_AN; - - /* Manual configuration of pause modes */ -@@ -996,21 +993,22 @@ static void phylink_mac_config(struct ph - const struct phylink_link_state *state) - { - phylink_dbg(pl, -- "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", -+ "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u\n", - __func__, phylink_an_mode_str(pl->cur_link_an_mode), - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), - phy_rate_matching_to_str(state->rate_matching), - __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, -- state->pause, state->link, state->an_enabled); -+ state->pause, state->link); - - pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); - } - - static void phylink_mac_pcs_an_restart(struct phylink *pl) - { -- if (pl->link_config.an_enabled && -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ pl->link_config.advertising) && - phy_interface_mode_is_8023z(pl->link_config.interface) && - phylink_autoneg_inband(pl->cur_link_an_mode)) { - if (pl->pcs) -@@ -1137,9 +1135,9 @@ static void phylink_mac_pcs_get_state(st - linkmode_copy(state->advertising, pl->link_config.advertising); - linkmode_zero(state->lp_advertising); - state->interface = pl->link_config.interface; -- state->an_enabled = pl->link_config.an_enabled; - state->rate_matching = pl->link_config.rate_matching; -- if (state->an_enabled) { -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) { - state->speed = SPEED_UNKNOWN; - state->duplex = DUPLEX_UNKNOWN; - state->pause = MLO_PAUSE_NONE; -@@ -1531,7 +1529,6 @@ struct phylink *phylink_create(struct ph - pl->link_config.pause = MLO_PAUSE_AN; - pl->link_config.speed = SPEED_UNKNOWN; - pl->link_config.duplex = DUPLEX_UNKNOWN; -- pl->link_config.an_enabled = true; - pl->mac_ops = mac_ops; - __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); - timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -2155,8 +2152,9 @@ static void phylink_get_ksettings(const - kset->base.speed = state->speed; - kset->base.duplex = state->duplex; - } -- kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE : -- AUTONEG_DISABLE; -+ kset->base.autoneg = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising) ? -+ AUTONEG_ENABLE : AUTONEG_DISABLE; - } - - /** -@@ -2303,9 +2301,8 @@ int phylink_ethtool_ksettings_set(struct - /* We have ruled out the case with a PHY attached, and the - * fixed-link cases. All that is left are in-band links. - */ -- config.an_enabled = kset->base.autoneg == AUTONEG_ENABLE; - linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising, -- config.an_enabled); -+ kset->base.autoneg == AUTONEG_ENABLE); - - /* If this link is with an SFP, ensure that changes to advertised modes - * also cause the associated interface to be selected such that the -@@ -2339,13 +2336,14 @@ int phylink_ethtool_ksettings_set(struct - } - - /* If autonegotiation is enabled, we must have an advertisement */ -- if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ config.advertising) && -+ phylink_is_empty_linkmode(config.advertising)) - return -EINVAL; - - mutex_lock(&pl->state_mutex); - pl->link_config.speed = config.speed; - pl->link_config.duplex = config.duplex; -- pl->link_config.an_enabled = config.an_enabled; - - if (pl->link_config.interface != config.interface) { - /* The interface changed, e.g. 1000base-X <-> 2500base-X */ -@@ -2951,7 +2949,6 @@ static int phylink_sfp_config_phy(struct - config.speed = SPEED_UNKNOWN; - config.duplex = DUPLEX_UNKNOWN; - config.pause = MLO_PAUSE_AN; -- config.an_enabled = pl->link_config.an_enabled; - - /* Ignore errors if we're expecting a PHY to attach later */ - ret = phylink_validate(pl, support, &config); -@@ -3020,7 +3017,6 @@ static int phylink_sfp_config_optical(st - config.speed = SPEED_UNKNOWN; - config.duplex = DUPLEX_UNKNOWN; - config.pause = MLO_PAUSE_AN; -- config.an_enabled = true; - - /* For all the interfaces that are supported, reduce the sfp_support - * mask to only those link modes that can be supported. -@@ -3354,7 +3350,8 @@ void phylink_mii_c22_pcs_decode_state(st - /* If there is no link or autonegotiation is disabled, the LP advertisement - * data is not meaningful, so don't go any further. - */ -- if (!state->link || !state->an_enabled) -+ if (!state->link || !linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) - return; - - switch (state->interface) { ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -93,7 +93,6 @@ static inline bool phylink_autoneg_inban - * the medium link mode (@speed and @duplex) and the speed/duplex of the phy - * interface mode (@interface) are different. - * @link: true if the link is up. -- * @an_enabled: true if autonegotiation is enabled/desired. - * @an_complete: true if autonegotiation has completed. - */ - struct phylink_link_state { -@@ -105,7 +104,6 @@ struct phylink_link_state { - int pause; - int rate_matching; - unsigned int link:1; -- unsigned int an_enabled:1; - unsigned int an_complete:1; - }; - diff --git a/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch b/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch deleted file mode 100644 index c06a367b8b..0000000000 --- a/target/linux/generic/backport-6.6/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch +++ /dev/null @@ -1,88 +0,0 @@ -From a3555d1f5c208f0a63eafee77381f68d304a0512 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 12 May 2023 17:58:37 +0100 -Subject: [PATCH 12/21] net: phylink: constify fwnode arguments - -Both phylink_create() and phylink_fwnode_phy_connect() do not modify -the fwnode argument that they are passed, so lets constify these. - -Reviewed-by: Simon Horman -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 11 ++++++----- - include/linux/phylink.h | 9 +++++---- - 2 files changed, 11 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -706,7 +706,7 @@ static int phylink_validate(struct phyli - } - - static int phylink_parse_fixedlink(struct phylink *pl, -- struct fwnode_handle *fwnode) -+ const struct fwnode_handle *fwnode) - { - struct fwnode_handle *fixed_node; - bool pause, asym_pause, autoneg; -@@ -817,7 +817,8 @@ static int phylink_parse_fixedlink(struc - return 0; - } - --static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) -+static int phylink_parse_mode(struct phylink *pl, -+ const struct fwnode_handle *fwnode) - { - struct fwnode_handle *dn; - const char *managed; -@@ -1440,7 +1441,7 @@ static void phylink_fixed_poll(struct ti - static const struct sfp_upstream_ops sfp_phylink_ops; - - static int phylink_register_sfp(struct phylink *pl, -- struct fwnode_handle *fwnode) -+ const struct fwnode_handle *fwnode) - { - struct sfp_bus *bus; - int ret; -@@ -1479,7 +1480,7 @@ static int phylink_register_sfp(struct p - * must use IS_ERR() to check for errors from this function. - */ - struct phylink *phylink_create(struct phylink_config *config, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - phy_interface_t iface, - const struct phylink_mac_ops *mac_ops) - { -@@ -1809,7 +1810,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect - * Returns 0 on success or a negative errno. - */ - int phylink_fwnode_phy_connect(struct phylink *pl, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - u32 flags) - { - struct fwnode_handle *phy_fwnode; ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -568,16 +568,17 @@ void phylink_generic_validate(struct phy - unsigned long *supported, - struct phylink_link_state *state); - --struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, -- phy_interface_t iface, -- const struct phylink_mac_ops *mac_ops); -+struct phylink *phylink_create(struct phylink_config *, -+ const struct fwnode_handle *, -+ phy_interface_t, -+ const struct phylink_mac_ops *); - void phylink_destroy(struct phylink *); - bool phylink_expects_phy(struct phylink *pl); - - int phylink_connect_phy(struct phylink *, struct phy_device *); - int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); - int phylink_fwnode_phy_connect(struct phylink *pl, -- struct fwnode_handle *fwnode, -+ const struct fwnode_handle *fwnode, - u32 flags); - void phylink_disconnect_phy(struct phylink *); - diff --git a/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch b/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch deleted file mode 100644 index 2649634dc7..0000000000 --- a/target/linux/generic/backport-6.6/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 4a0faa02d419a6728abef0f1d8a32d8c35ef95e6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 24 Mar 2023 09:23:53 +0000 -Subject: [PATCH] net: phy: constify fwnode_get_phy_node() fwnode argument - -fwnode_get_phy_node() does not motify the fwnode structure, so make -the argument const, - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 2 +- - include/linux/phy.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3003,7 +3003,7 @@ EXPORT_SYMBOL_GPL(device_phy_find_device - * and "phy-device" are not supported in ACPI. DT supports all the three - * named references to the phy node. - */ --struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode) -+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode) - { - struct fwnode_handle *phy_node; - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1473,7 +1473,7 @@ int fwnode_get_phy_id(struct fwnode_hand - struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode); - struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode); - struct phy_device *device_phy_find_device(struct device *dev); --struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode); -+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode); - struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); - int phy_device_register(struct phy_device *phy); - void phy_device_free(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch deleted file mode 100644 index 5eba18b026..0000000000 --- a/target/linux/generic/backport-6.6/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch +++ /dev/null @@ -1,44 +0,0 @@ -From cc73de0411f7d3cdd157564a78f7a39058420ff8 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 13 May 2023 22:03:45 +0100 -Subject: [PATCH 13/21] net: phylink: fix ksettings_set() ethtool call - -While testing a Fiberstore SFP-10G-T module (which uses 10GBASE-R with -rate adaption) in a Clearfog platform (which can't do that) it was -found that the PHYs advertisement was not limited according to the -hosts capabilities when using ethtool to change it. - -Fix this by ensuring that we mask the advertisement with the computed -support mask as the very first thing we do. - -Fixes: cbc1bb1e4689 ("net: phylink: simplify phy case for ksettings_set method") -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2226,6 +2226,10 @@ int phylink_ethtool_ksettings_set(struct - - ASSERT_RTNL(); - -+ /* Mask out unsupported advertisements */ -+ linkmode_and(config.advertising, kset->link_modes.advertising, -+ pl->supported); -+ - if (pl->phydev) { - /* We can rely on phylib for this update; we also do not need - * to update the pl->link_config settings: -@@ -2250,10 +2254,6 @@ int phylink_ethtool_ksettings_set(struct - - config = pl->link_config; - -- /* Mask out unsupported advertisements */ -- linkmode_and(config.advertising, kset->link_modes.advertising, -- pl->supported); -- - /* FIXME: should we reject autoneg if phy/mac does not support it? */ - switch (kset->base.autoneg) { - case AUTONEG_DISABLE: diff --git a/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch b/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch deleted file mode 100644 index 79de6122b7..0000000000 --- a/target/linux/generic/backport-6.6/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0100d1c5789018ba77bf2f4fab3bd91ecece7b3b Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 17 May 2023 11:38:12 +0100 -Subject: [PATCH 14/21] net: sfp: add support for setting signalling rate - -Add support to the SFP layer to allow phylink to set the signalling -rate for a SFP module. The rate given will be in units of kilo-baud -(1000 baud). - -Reviewed-by: Simon Horman -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 24 ++++++++++++++++++++++++ - drivers/net/phy/sfp-bus.c | 20 ++++++++++++++++++++ - drivers/net/phy/sfp.c | 5 +++++ - drivers/net/phy/sfp.h | 1 + - include/linux/sfp.h | 6 ++++++ - 5 files changed, 56 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -156,6 +156,23 @@ static const char *phylink_an_mode_str(u - return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; - } - -+static unsigned int phylink_interface_signal_rate(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */ -+ return 1250; -+ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */ -+ return 3125; -+ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */ -+ return 5156; -+ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */ -+ return 10313; -+ default: -+ return 0; -+ } -+} -+ - /** - * phylink_interface_max_speed() - get the maximum speed of a phy interface - * @interface: phy interface mode defined by &typedef phy_interface_t -@@ -1024,6 +1041,7 @@ static void phylink_major_config(struct - { - struct phylink_pcs *pcs = NULL; - bool pcs_changed = false; -+ unsigned int rate_kbd; - int err; - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -@@ -1083,6 +1101,12 @@ static void phylink_major_config(struct - ERR_PTR(err)); - } - -+ if (pl->sfp_bus) { -+ rate_kbd = phylink_interface_signal_rate(state->interface); -+ if (rate_kbd) -+ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd); -+ } -+ - phylink_pcs_poll_start(pl); - } - ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -586,6 +586,26 @@ static void sfp_upstream_clear(struct sf - } - - /** -+ * sfp_upstream_set_signal_rate() - set data signalling rate -+ * @bus: a pointer to the &struct sfp_bus structure for the sfp module -+ * @rate_kbd: signalling rate in units of 1000 baud -+ * -+ * Configure the rate select settings on the SFP module for the signalling -+ * rate (not the same as the data rate). -+ * -+ * Locks that may be held: -+ * Phylink's state_mutex -+ * rtnl lock -+ * SFP's sm_mutex -+ */ -+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) -+{ -+ if (bus->registered) -+ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); -+} -+EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); -+ -+/** - * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode - * @fwnode: firmware node for the parent device (MAC or PHY) - * ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -2474,6 +2474,10 @@ static void sfp_stop(struct sfp *sfp) - sfp_sm_event(sfp, SFP_E_DEV_DOWN); - } - -+static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd) -+{ -+} -+ - static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) - { - /* locking... and check module is present */ -@@ -2552,6 +2556,7 @@ static const struct sfp_socket_ops sfp_m - .detach = sfp_detach, - .start = sfp_start, - .stop = sfp_stop, -+ .set_signal_rate = sfp_set_signal_rate, - .module_info = sfp_module_info, - .module_eeprom = sfp_module_eeprom, - .module_eeprom_by_page = sfp_module_eeprom_by_page, ---- a/drivers/net/phy/sfp.h -+++ b/drivers/net/phy/sfp.h -@@ -19,6 +19,7 @@ struct sfp_socket_ops { - void (*detach)(struct sfp *sfp); - void (*start)(struct sfp *sfp); - void (*stop)(struct sfp *sfp); -+ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd); - int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); - int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, - u8 *data); ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -547,6 +547,7 @@ int sfp_get_module_eeprom_by_page(struct - struct netlink_ext_ack *extack); - void sfp_upstream_start(struct sfp_bus *bus); - void sfp_upstream_stop(struct sfp_bus *bus); -+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd); - void sfp_bus_put(struct sfp_bus *bus); - struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); - int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, -@@ -606,6 +607,11 @@ static inline void sfp_upstream_stop(str - { - } - -+static inline void sfp_upstream_set_signal_rate(struct sfp_bus *bus, -+ unsigned int rate_kbd) -+{ -+} -+ - static inline void sfp_bus_put(struct sfp_bus *bus) - { - } diff --git a/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch b/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch deleted file mode 100644 index 8a694c86da..0000000000 --- a/target/linux/generic/backport-6.6/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch +++ /dev/null @@ -1,147 +0,0 @@ -From b84acdb07222a701bfc6403b374249c86f97d18d Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 19 May 2023 14:03:59 +0100 -Subject: [PATCH 15/21] net: phy: add helpers for comparing phy IDs - -There are several places which open code comparing PHY IDs. Provide a -couple of helpers to assist with this, using a slightly simpler test -than the original: - -- phy_id_compare() compares two arbitary PHY IDs and a mask of the - significant bits in the ID. -- phydev_id_compare() compares the bound phydev with the specified - PHY ID, using the bound driver's mask. - -Signed-off-by: Russell King -Reviewed-by: Simon Horman -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/micrel.c | 6 +++--- - drivers/net/phy/phy_device.c | 16 +++++++--------- - drivers/net/phy/phylink.c | 4 ++-- - include/linux/phy.h | 28 ++++++++++++++++++++++++++++ - 4 files changed, 40 insertions(+), 14 deletions(-) - ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -620,7 +620,7 @@ static int ksz8051_ksz8795_match_phy_dev - { - int ret; - -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) -+ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) - return 0; - - ret = phy_read(phydev, MII_BMSR); -@@ -1455,7 +1455,7 @@ static int ksz9x31_cable_test_fault_leng - * - * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity - */ -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) -+ if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) - dt = clamp(dt - 22, 0, 255); - - return (dt * 400) / 10; -@@ -1887,7 +1887,7 @@ static __always_inline int ksz886x_cable - */ - dt = FIELD_GET(data_mask, status); - -- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) -+ if (phydev_id_compare(phydev, PHY_ID_LAN8814)) - return ((dt - 22) * 800) / 10; - else - return (dt * 400) / 10; ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -422,8 +422,7 @@ int phy_unregister_fixup(const char *bus - fixup = list_entry(pos, struct phy_fixup, list); - - if ((!strcmp(fixup->bus_id, bus_id)) && -- ((fixup->phy_uid & phy_uid_mask) == -- (phy_uid & phy_uid_mask))) { -+ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { - list_del(&fixup->list); - kfree(fixup); - ret = 0; -@@ -459,8 +458,8 @@ static int phy_needs_fixup(struct phy_de - if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) - return 0; - -- if ((fixup->phy_uid & fixup->phy_uid_mask) != -- (phydev->phy_id & fixup->phy_uid_mask)) -+ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, -+ fixup->phy_uid_mask)) - if (fixup->phy_uid != PHY_ANY_UID) - return 0; - -@@ -507,15 +506,14 @@ static int phy_bus_match(struct device * - if (phydev->c45_ids.device_ids[i] == 0xffffffff) - continue; - -- if ((phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->c45_ids.device_ids[i] & -- phydrv->phy_id_mask)) -+ if (phy_id_compare(phydev->c45_ids.device_ids[i], -+ phydrv->phy_id, phydrv->phy_id_mask)) - return 1; - } - return 0; - } else { -- return (phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->phy_id & phydrv->phy_id_mask); -+ return phy_id_compare(phydev->phy_id, phydrv->phy_id, -+ phydrv->phy_id_mask); - } - } - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3151,8 +3151,8 @@ static void phylink_sfp_link_up(void *up - */ - static bool phylink_phy_no_inband(struct phy_device *phy) - { -- return phy->is_c45 && -- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; -+ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], -+ 0xae025150, 0xfffffff0); - } - - static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -993,6 +993,34 @@ struct phy_driver { - #define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) - #define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) - -+/** -+ * phy_id_compare - compare @id1 with @id2 taking account of @mask -+ * @id1: first PHY ID -+ * @id2: second PHY ID -+ * @mask: the PHY ID mask, set bits are significant in matching -+ * -+ * Return true if the bits from @id1 and @id2 specified by @mask match. -+ * This uses an equivalent test to (@id & @mask) == (@phy_id & @mask). -+ */ -+static inline bool phy_id_compare(u32 id1, u32 id2, u32 mask) -+{ -+ return !((id1 ^ id2) & mask); -+} -+ -+/** -+ * phydev_id_compare - compare @id with the PHY's Clause 22 ID -+ * @phydev: the PHY device -+ * @id: the PHY ID to be matched -+ * -+ * Compare the @phydev clause 22 ID with the provided @id and return true or -+ * false depending whether it matches, using the bound driver mask. The -+ * @phydev must be bound to a driver. -+ */ -+static inline bool phydev_id_compare(struct phy_device *phydev, u32 id) -+{ -+ return phy_id_compare(id, phydev->phy_id, phydev->drv->phy_id_mask); -+} -+ - /* A Structure for boards to register fixups with the PHY Lib */ - struct phy_fixup { - struct list_head list; diff --git a/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch b/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch deleted file mode 100644 index 5970355a6c..0000000000 --- a/target/linux/generic/backport-6.6/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 441e1e44301fc5762a06737f8ec04bf1ce3fb039 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 20 May 2023 11:41:42 +0100 -Subject: [PATCH 16/21] net: phylink: require supported_interfaces to be filled - -We have been requiring the supported_interfaces bitmap to be filled in -by MAC drivers that have a mac_select_pcs() method. Now that all MAC -drivers fill in the supported_interfaces bitmap, it is time to enforce -this. We have already required supported_interfaces to be set in order -for optical SFPs to be configured in commit f81fa96d8a6c ("net: phylink: -use phy_interface_t bitmaps for optical modules"). - -Refuse phylink creation if supported_interfaces is empty, and remove -code to deal with cases where this mask is empty. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/E1q0K1u-006EIP-ET@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 26 +++++++++++--------------- - 1 file changed, 11 insertions(+), 15 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -710,14 +710,11 @@ static int phylink_validate(struct phyli - { - const unsigned long *interfaces = pl->config->supported_interfaces; - -- if (!phy_interface_empty(interfaces)) { -- if (state->interface == PHY_INTERFACE_MODE_NA) -- return phylink_validate_mask(pl, supported, state, -- interfaces); -+ if (state->interface == PHY_INTERFACE_MODE_NA) -+ return phylink_validate_mask(pl, supported, state, interfaces); - -- if (!test_bit(state->interface, interfaces)) -- return -EINVAL; -- } -+ if (!test_bit(state->interface, interfaces)) -+ return -EINVAL; - - return phylink_validate_mac_and_pcs(pl, supported, state); - } -@@ -1512,19 +1509,18 @@ struct phylink *phylink_create(struct ph - struct phylink *pl; - int ret; - -- if (mac_ops->mac_select_pcs && -- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != -- ERR_PTR(-EOPNOTSUPP)) -- using_mac_select_pcs = true; -- - /* Validate the supplied configuration */ -- if (using_mac_select_pcs && -- phy_interface_empty(config->supported_interfaces)) { -+ if (phy_interface_empty(config->supported_interfaces)) { - dev_err(config->dev, -- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); -+ "phylink: error: empty supported_interfaces\n"); - return ERR_PTR(-EINVAL); - } - -+ if (mac_ops->mac_select_pcs && -+ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != -+ ERR_PTR(-EOPNOTSUPP)) -+ using_mac_select_pcs = true; -+ - pl = kzalloc(sizeof(*pl), GFP_KERNEL); - if (!pl) - return ERR_PTR(-ENOMEM); diff --git a/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch b/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch deleted file mode 100644 index 3a26b4b600..0000000000 --- a/target/linux/generic/backport-6.6/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 4b624a39f2ab523ca6a6ad9448fab1deb7b101e2 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 11:15:53 +0100 -Subject: [PATCH 17/21] net: phylink: remove duplicated linkmode pause - resolution - -Phylink had two chunks of code virtually the same for resolving the -negotiated pause modes. Factor this down to one function. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 15 ++++----------- - 1 file changed, 4 insertions(+), 11 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -976,11 +976,10 @@ static void phylink_apply_manual_flow(st - state->pause = pl->link_config.pause; - } - --static void phylink_resolve_flow(struct phylink_link_state *state) -+static void phylink_resolve_an_pause(struct phylink_link_state *state) - { - bool tx_pause, rx_pause; - -- state->pause = MLO_PAUSE_NONE; - if (state->duplex == DUPLEX_FULL) { - linkmode_resolve_pause(state->advertising, - state->lp_advertising, -@@ -1192,7 +1191,8 @@ static void phylink_get_fixed_state(stru - else if (pl->link_gpio) - state->link = !!gpiod_get_value_cansleep(pl->link_gpio); - -- phylink_resolve_flow(state); -+ state->pause = MLO_PAUSE_NONE; -+ phylink_resolve_an_pause(state); - } - - static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) -@@ -3215,7 +3215,6 @@ static const struct sfp_upstream_ops sfp - static void phylink_decode_c37_word(struct phylink_link_state *state, - uint16_t config_reg, int speed) - { -- bool tx_pause, rx_pause; - int fd_bit; - - if (speed == SPEED_2500) -@@ -3234,13 +3233,7 @@ static void phylink_decode_c37_word(stru - state->link = false; - } - -- linkmode_resolve_pause(state->advertising, state->lp_advertising, -- &tx_pause, &rx_pause); -- -- if (tx_pause) -- state->pause |= MLO_PAUSE_TX; -- if (rx_pause) -- state->pause |= MLO_PAUSE_RX; -+ phylink_resolve_an_pause(state); - } - - static void phylink_decode_sgmii_word(struct phylink_link_state *state, diff --git a/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch b/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch deleted file mode 100644 index 2b2634f80c..0000000000 --- a/target/linux/generic/backport-6.6/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch +++ /dev/null @@ -1,76 +0,0 @@ -From aa8b6bd2b1f235b262bd27f317a0516f196c2c6a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 11:15:58 +0100 -Subject: [PATCH 18/21] net: phylink: add function to resolve clause 73 - negotiation - -Add a function to resolve clause 73 negotiation according to the -priority resolution function described in clause 73.3.6. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 39 +++++++++++++++++++++++++++++++++++++++ - include/linux/phylink.h | 2 ++ - 2 files changed, 41 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3212,6 +3212,45 @@ static const struct sfp_upstream_ops sfp - - /* Helpers for MAC drivers */ - -+static struct { -+ int bit; -+ int speed; -+} phylink_c73_priority_resolution[] = { -+ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, -+ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, -+ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ -+ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, -+ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, -+ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, -+ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, -+ /* 5GBASE-KR not supported */ -+ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, -+ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, -+}; -+ -+void phylink_resolve_c73(struct phylink_link_state *state) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { -+ int bit = phylink_c73_priority_resolution[i].bit; -+ if (linkmode_test_bit(bit, state->advertising) && -+ linkmode_test_bit(bit, state->lp_advertising)) -+ break; -+ } -+ -+ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { -+ state->speed = phylink_c73_priority_resolution[i].speed; -+ state->duplex = DUPLEX_FULL; -+ } else { -+ /* negotiation failure */ -+ state->link = false; -+ } -+ -+ phylink_resolve_an_pause(state); -+} -+EXPORT_SYMBOL_GPL(phylink_resolve_c73); -+ - static void phylink_decode_c37_word(struct phylink_link_state *state, - uint16_t config_reg, int speed) - { ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -656,6 +656,8 @@ int phylink_mii_c22_pcs_config(struct md - const unsigned long *advertising); - void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); - -+void phylink_resolve_c73(struct phylink_link_state *state); -+ - void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, - struct phylink_link_state *state); - diff --git a/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch b/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch deleted file mode 100644 index eea99a5d78..0000000000 --- a/target/linux/generic/backport-6.6/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 796d709363135a6bd6a8ccc07b509c939e5b855f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 23 May 2023 16:31:50 +0100 -Subject: [PATCH 19/21] net: phylink: provide phylink_pcs_config() and - phylink_pcs_link_up() - -Add two helper functions for calling PCS methods. phylink_pcs_config() -allows us to handle PCS configuration specifics in one location, rather -than the two call sites. phylink_pcs_link_up() gives us consistency. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1q1TzK-007Exd-Rs@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 53 ++++++++++++++++++++++++--------------- - 1 file changed, 33 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -991,6 +991,25 @@ static void phylink_resolve_an_pause(str - } - } - -+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ const struct phylink_link_state *state, -+ bool permit_pause_to_mac) -+{ -+ if (!pcs) -+ return 0; -+ -+ return pcs->ops->pcs_config(pcs, mode, state->interface, -+ state->advertising, permit_pause_to_mac); -+} -+ -+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, int speed, -+ int duplex) -+{ -+ if (pcs && pcs->ops->pcs_link_up) -+ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); -+} -+ - static void phylink_pcs_poll_stop(struct phylink *pl) - { - if (pl->cfg_link_an_mode == MLO_AN_INBAND) -@@ -1074,18 +1093,15 @@ static void phylink_major_config(struct - - phylink_mac_config(pl, state); - -- if (pl->pcs) { -- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, -- state->interface, -- state->advertising, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -- if (err < 0) -- phylink_err(pl, "pcs_config failed: %pe\n", -- ERR_PTR(err)); -- if (err > 0) -- restart = true; -- } -+ err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, -+ !!(pl->link_config.pause & -+ MLO_PAUSE_AN)); -+ if (err < 0) -+ phylink_err(pl, "pcs_config failed: %pe\n", -+ ERR_PTR(err)); -+ else if (err > 0) -+ restart = true; -+ - if (restart) - phylink_mac_pcs_an_restart(pl); - -@@ -1136,11 +1152,9 @@ static int phylink_change_inband_advert( - * restart negotiation if the pcs_config() helper indicates that - * the programmed advertisement has changed. - */ -- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, -- pl->link_config.interface, -- pl->link_config.advertising, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -+ ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, -+ &pl->link_config, -+ !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (ret < 0) - return ret; - -@@ -1272,9 +1286,8 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- if (pl->pcs && pl->pcs->ops->pcs_link_up) -- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, -- pl->cur_interface, speed, duplex); -+ phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, -+ speed, duplex); - - pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex, diff --git a/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch b/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch deleted file mode 100644 index 2f7f7a5737..0000000000 --- a/target/linux/generic/backport-6.6/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 11933aa76865621d8e82553c8f3bc07796a5aaa2 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 1 Jun 2023 10:12:06 +0100 -Subject: [PATCH 20/21] net: phylink: actually fix ksettings_set() ethtool call - -Raju Lakkaraju reported that the below commit caused a regression -with Lan743x drivers and a 2.5G SFP. Sadly, this is because the commit -was utterly wrong. Let's fix this properly by not moving the -linkmode_and(), but instead copying the link ksettings and then -modifying the advertising mask before passing the modified link -ksettings to phylib. - -Fixes: df0acdc59b09 ("net: phylink: fix ksettings_set() ethtool call") -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1q4eLm-00Ayxk-GZ@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2259,11 +2259,13 @@ int phylink_ethtool_ksettings_set(struct - - ASSERT_RTNL(); - -- /* Mask out unsupported advertisements */ -- linkmode_and(config.advertising, kset->link_modes.advertising, -- pl->supported); -- - if (pl->phydev) { -+ struct ethtool_link_ksettings phy_kset = *kset; -+ -+ linkmode_and(phy_kset.link_modes.advertising, -+ phy_kset.link_modes.advertising, -+ pl->supported); -+ - /* We can rely on phylib for this update; we also do not need - * to update the pl->link_config settings: - * - the configuration returned via ksettings_get() will come -@@ -2282,10 +2284,13 @@ int phylink_ethtool_ksettings_set(struct - * the presence of a PHY, this should not be changed as that - * should be determined from the media side advertisement. - */ -- return phy_ethtool_ksettings_set(pl->phydev, kset); -+ return phy_ethtool_ksettings_set(pl->phydev, &phy_kset); - } - - config = pl->link_config; -+ /* Mask out unsupported advertisements */ -+ linkmode_and(config.advertising, kset->link_modes.advertising, -+ pl->supported); - - /* FIXME: should we reject autoneg if phy/mac does not support it? */ - switch (kset->base.autoneg) { diff --git a/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch b/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch deleted file mode 100644 index e1a8539aae..0000000000 --- a/target/linux/generic/backport-6.6/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch +++ /dev/null @@ -1,324 +0,0 @@ -From 79b07c3e9c4a2272927be8848c26b372516e1958 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:22 +0100 -Subject: [PATCH 21/21] net: phylink: add PCS negotiation mode - -PCS have to work out whether they should enable PCS negotiation by -looking at the "mode" and "interface" arguments, and the Autoneg bit -in the advertising mask. - -This leads to some complex logic, so lets pull that out into phylink -and instead pass a "neg_mode" argument to the PCS configuration and -link up methods, instead of the "mode" argument. - -In order to transition drivers, add a "neg_mode" flag to the phylink -PCS structure to PCS can indicate whether they want to be passed the -neg_mode or the old mode argument. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8De-00EaFA-Ht@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 45 +++++++++++++---- - include/linux/phylink.h | 104 +++++++++++++++++++++++++++++++++++--- - 2 files changed, 132 insertions(+), 17 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -71,6 +71,7 @@ struct phylink { - struct mutex state_mutex; - struct phylink_link_state phy_state; - struct work_struct resolve; -+ unsigned int pcs_neg_mode; - - bool mac_link_dropped; - bool using_mac_select_pcs; -@@ -991,23 +992,23 @@ static void phylink_resolve_an_pause(str - } - } - --static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - const struct phylink_link_state *state, - bool permit_pause_to_mac) - { - if (!pcs) - return 0; - -- return pcs->ops->pcs_config(pcs, mode, state->interface, -+ return pcs->ops->pcs_config(pcs, neg_mode, state->interface, - state->advertising, permit_pause_to_mac); - } - --static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, - int duplex) - { - if (pcs && pcs->ops->pcs_link_up) -- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); -+ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); - } - - static void phylink_pcs_poll_stop(struct phylink *pl) -@@ -1057,10 +1058,15 @@ static void phylink_major_config(struct - struct phylink_pcs *pcs = NULL; - bool pcs_changed = false; - unsigned int rate_kbd; -+ unsigned int neg_mode; - int err; - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); - -+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -+ state->interface, -+ state->advertising); -+ - if (pl->using_mac_select_pcs) { - pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); - if (IS_ERR(pcs)) { -@@ -1093,9 +1099,12 @@ static void phylink_major_config(struct - - phylink_mac_config(pl, state); - -- err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, -- !!(pl->link_config.pause & -- MLO_PAUSE_AN)); -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs && pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ -+ err = phylink_pcs_config(pl->pcs, neg_mode, state, -+ !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (err < 0) - phylink_err(pl, "pcs_config failed: %pe\n", - ERR_PTR(err)); -@@ -1130,6 +1139,7 @@ static void phylink_major_config(struct - */ - static int phylink_change_inband_advert(struct phylink *pl) - { -+ unsigned int neg_mode; - int ret; - - if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) -@@ -1148,12 +1158,20 @@ static int phylink_change_inband_advert( - __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, - pl->link_config.pause); - -+ /* Recompute the PCS neg mode */ -+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -+ pl->link_config.interface, -+ pl->link_config.advertising); -+ -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ - /* Modern PCS-based method; update the advert at the PCS, and - * restart negotiation if the pcs_config() helper indicates that - * the programmed advertisement has changed. - */ -- ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, -- &pl->link_config, -+ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config, - !!(pl->link_config.pause & MLO_PAUSE_AN)); - if (ret < 0) - return ret; -@@ -1256,6 +1274,7 @@ static void phylink_link_up(struct phyli - struct phylink_link_state link_state) - { - struct net_device *ndev = pl->netdev; -+ unsigned int neg_mode; - int speed, duplex; - bool rx_pause; - -@@ -1286,8 +1305,12 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, -- speed, duplex); -+ neg_mode = pl->cur_link_an_mode; -+ if (pl->pcs && pl->pcs->neg_mode) -+ neg_mode = pl->pcs_neg_mode; -+ -+ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, -+ duplex); - - pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex, ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -21,6 +21,24 @@ enum { - MLO_AN_FIXED, /* Fixed-link mode */ - MLO_AN_INBAND, /* In-band protocol */ - -+ /* PCS "negotiation" mode. -+ * PHYLINK_PCS_NEG_NONE - protocol has no inband capability -+ * PHYLINK_PCS_NEG_OUTBAND - some out of band or fixed link setting -+ * PHYLINK_PCS_NEG_INBAND_DISABLED - inband mode disabled, e.g. -+ * 1000base-X with autoneg off -+ * PHYLINK_PCS_NEG_INBAND_ENABLED - inband mode enabled -+ * Additionally, this can be tested using bitmasks: -+ * PHYLINK_PCS_NEG_INBAND - inband mode selected -+ * PHYLINK_PCS_NEG_ENABLED - negotiation mode enabled -+ */ -+ PHYLINK_PCS_NEG_NONE = 0, -+ PHYLINK_PCS_NEG_ENABLED = BIT(4), -+ PHYLINK_PCS_NEG_OUTBAND = BIT(5), -+ PHYLINK_PCS_NEG_INBAND = BIT(6), -+ PHYLINK_PCS_NEG_INBAND_DISABLED = PHYLINK_PCS_NEG_INBAND, -+ PHYLINK_PCS_NEG_INBAND_ENABLED = PHYLINK_PCS_NEG_INBAND | -+ PHYLINK_PCS_NEG_ENABLED, -+ - /* MAC_SYM_PAUSE and MAC_ASYM_PAUSE are used when configuring our - * autonegotiation advertisement. They correspond to the PAUSE and - * ASM_DIR bits defined by 802.3, respectively. -@@ -80,6 +98,70 @@ static inline bool phylink_autoneg_inban - } - - /** -+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode -+ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @interface: interface mode to be used -+ * @advertising: adertisement ethtool link mode mask -+ * -+ * Determines the negotiation mode to be used by the PCS, and returns -+ * one of: -+ * %PHYLINK_PCS_NEG_NONE: interface mode does not support inband -+ * %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) -+ * will be used. -+ * %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg disabled -+ * %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled -+ * -+ * Note: this is for cases where the PCS itself is involved in negotiation -+ * (e.g. Clause 37, SGMII and similar) not Clause 73. -+ */ -+static inline unsigned int phylink_pcs_neg_mode(unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising) -+{ -+ unsigned int neg_mode; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_QUSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: -+ /* These protocols are designed for use with a PHY which -+ * communicates its negotiation result back to the MAC via -+ * inband communication. Note: there exist PHYs that run -+ * with SGMII but do not send the inband data. -+ */ -+ if (!phylink_autoneg_inband(mode)) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ break; -+ -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ /* 1000base-X is designed for use media-side for Fibre -+ * connections, and thus the Autoneg bit needs to be -+ * taken into account. We also do this for 2500base-X -+ * as well, but drivers may not support this, so may -+ * need to override this. -+ */ -+ if (!phylink_autoneg_inband(mode)) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising)) -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ else -+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; -+ break; -+ -+ default: -+ neg_mode = PHYLINK_PCS_NEG_NONE; -+ break; -+ } -+ -+ return neg_mode; -+} -+ -+/** - * struct phylink_link_state - link state structure - * @advertising: ethtool bitmask containing advertised link modes - * @lp_advertising: ethtool bitmask containing link partner advertised link -@@ -436,6 +518,7 @@ struct phylink_pcs_ops; - /** - * struct phylink_pcs - PHYLINK PCS instance - * @ops: a pointer to the &struct phylink_pcs_ops structure -+ * @neg_mode: provide PCS neg mode via "mode" argument - * @poll: poll the PCS for link changes - * - * This structure is designed to be embedded within the PCS private data, -@@ -443,6 +526,7 @@ struct phylink_pcs_ops; - */ - struct phylink_pcs { - const struct phylink_pcs_ops *ops; -+ bool neg_mode; - bool poll; - }; - -@@ -460,12 +544,12 @@ struct phylink_pcs_ops { - const struct phylink_link_state *state); - void (*pcs_get_state)(struct phylink_pcs *pcs, - struct phylink_link_state *state); -- int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, -+ int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac); - void (*pcs_an_restart)(struct phylink_pcs *pcs); -- void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int mode, -+ void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, int duplex); - }; - -@@ -508,7 +592,7 @@ void pcs_get_state(struct phylink_pcs *p - /** - * pcs_config() - Configure the PCS mode and advertisement - * @pcs: a pointer to a &struct phylink_pcs. -- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @neg_mode: link negotiation mode (see below) - * @interface: interface mode to be used - * @advertising: adertisement ethtool link mode mask - * @permit_pause_to_mac: permit forwarding pause resolution to MAC -@@ -526,8 +610,12 @@ void pcs_get_state(struct phylink_pcs *p - * For 1000BASE-X, the advertisement should be programmed into the PCS. - * - * For most 10GBASE-R, there is no advertisement. -+ * -+ * The %neg_mode argument should be tested via the phylink_mode_*() family of -+ * functions, or for PCS that set pcs->neg_mode true, should be tested -+ * against the %PHYLINK_PCS_NEG_* definitions. - */ --int pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, const unsigned long *advertising, - bool permit_pause_to_mac); - -@@ -543,7 +631,7 @@ void pcs_an_restart(struct phylink_pcs * - /** - * pcs_link_up() - program the PCS for the resolved link configuration - * @pcs: a pointer to a &struct phylink_pcs. -- * @mode: link autonegotiation mode -+ * @neg_mode: link negotiation mode (see below) - * @interface: link &typedef phy_interface_t mode - * @speed: link speed - * @duplex: link duplex -@@ -552,8 +640,12 @@ void pcs_an_restart(struct phylink_pcs * - * the resolved link parameters. For example, a PCS operating in SGMII - * mode without in-band AN needs to be manually configured for the link - * and duplex setting. Otherwise, this should be a no-op. -+ * -+ * The %mode argument should be tested via the phylink_mode_*() family of -+ * functions, or for PCS that set pcs->neg_mode true, should be tested -+ * against the %PHYLINK_PCS_NEG_* definitions. - */ --void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, int speed, int duplex); - #endif - diff --git a/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch b/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch deleted file mode 100644 index 473e9d5836..0000000000 --- a/target/linux/generic/backport-6.6/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch +++ /dev/null @@ -1,45 +0,0 @@ -From cdb08aa0473730315dbc088d5394e59622314034 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:27 +0100 -Subject: [PATCH 1/2] net: phylink: convert phylink_mii_c22_pcs_config() to - neg_mode - -Use phylink_pcs_neg_mode() for phylink_mii_c22_pcs_config(). This -results in no functional change. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Dj-00EaFG-Mt@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3558,6 +3558,7 @@ int phylink_mii_c22_pcs_config(struct md - phy_interface_t interface, - const unsigned long *advertising) - { -+ unsigned int neg_mode; - bool changed = 0; - u16 bmcr; - int ret, adv; -@@ -3571,15 +3572,13 @@ int phylink_mii_c22_pcs_config(struct md - changed = ret; - } - -- /* Ensure ISOLATE bit is disabled */ -- if (mode == MLO_AN_INBAND && -- (interface == PHY_INTERFACE_MODE_SGMII || -- interface == PHY_INTERFACE_MODE_QSGMII || -- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising))) -+ neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) - bmcr = BMCR_ANENABLE; - else - bmcr = 0; - -+ /* Configure the inband state. Ensure ISOLATE bit is disabled */ - ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); - if (ret < 0) - return ret; diff --git a/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch b/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch deleted file mode 100644 index 5572850e95..0000000000 --- a/target/linux/generic/backport-6.6/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch +++ /dev/null @@ -1,187 +0,0 @@ -From febf2aaf05641f3258cc30e072aff65cffc7c82c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:32 +0100 -Subject: [PATCH 2/2] net: phylink: pass neg_mode into - phylink_mii_c22_pcs_config() - -Convert fman_dtsec, xilinx_axienet and pcs-lynx to pass the neg_mode -into phylink_mii_c22_pcs_config(). Where appropriate, drivers are -updated to have neg_mode passed into their pcs_config() and -pcs_link_up() functions. For other drivers, we just hoist the call -to phylink_pcs_neg_mode() to their pcs_config() method out of -phylink_mii_c22_pcs_config(). - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Do-00EaFM-Ra@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - .../net/ethernet/freescale/fman/fman_dtsec.c | 7 ++++--- - .../net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++-- - drivers/net/pcs/pcs-lynx.c | 18 ++++++++++++------ - drivers/net/phy/phylink.c | 9 ++++----- - include/linux/phylink.h | 5 +++-- - 5 files changed, 27 insertions(+), 18 deletions(-) - ---- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c -+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c -@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct p - phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); - } - --static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct fman_mac *dtsec = pcs_to_dtsec(pcs); - -- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, -- advertising); -+ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface, -+ advertising, neg_mode); - } - - static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) -@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_devi - goto _return_fm_mac_free; - } - dtsec->pcs.ops = &dtsec_pcs_ops; -+ dtsec->pcs.neg_mode = true; - dtsec->pcs.poll = true; - - supported = mac_dev->phylink_config.supported_interfaces; ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struc - phylink_mii_c22_pcs_an_restart(pcs_phy); - } - --static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) -@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phy - } - } - -- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising); -+ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising, -+ neg_mode); - if (ret < 0) - netdev_warn(ndev, "Failed to configure PCS: %d\n", ret); - -@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform - } - of_node_put(np); - lp->pcs.ops = &axienet_pcs_ops; -+ lp->pcs.neg_mode = true; - lp->pcs.poll = true; - } - ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -122,9 +122,10 @@ static void lynx_pcs_get_state(struct ph - state->link, state->an_complete); - } - --static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, -+static int lynx_pcs_config_giga(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising) -+ const unsigned long *advertising, -+ unsigned int neg_mode) - { - u32 link_timer; - u16 if_mode; -@@ -137,8 +138,9 @@ static int lynx_pcs_config_giga(struct m - - if_mode = 0; - } else { -+ /* SGMII and QSGMII */ - if_mode = IF_MODE_SGMII_EN; -- if (mode == MLO_AN_INBAND) { -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { - if_mode |= IF_MODE_USE_SGMII_AN; - - /* Adjust link timer for SGMII */ -@@ -154,7 +156,8 @@ static int lynx_pcs_config_giga(struct m - if (err) - return err; - -- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising); -+ return phylink_mii_c22_pcs_config(pcs, interface, advertising, -+ neg_mode); - } - - static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, -@@ -181,13 +184,16 @@ static int lynx_pcs_config(struct phylin - bool permit) - { - struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); -+ unsigned int neg_mode; -+ -+ neg_mode = phylink_pcs_neg_mode(mode, ifmode, advertising); - - switch (ifmode) { - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode, -- advertising); -+ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, -+ neg_mode); - case PHY_INTERFACE_MODE_2500BASEX: - if (phylink_autoneg_inband(mode)) { - dev_err(&lynx->mdio->dev, ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3545,20 +3545,20 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_en - /** - * phylink_mii_c22_pcs_config() - configure clause 22 PCS - * @pcs: a pointer to a &struct mdio_device. -- * @mode: link autonegotiation mode - * @interface: the PHY interface mode being configured - * @advertising: the ethtool advertisement mask -+ * @neg_mode: PCS negotiation mode - * - * Configure a Clause 22 PCS PHY with the appropriate negotiation - * parameters for the @mode, @interface and @advertising parameters. - * Returns negative error number on failure, zero if the advertisement - * has not changed, or positive if there is a change. - */ --int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, -+int phylink_mii_c22_pcs_config(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising) -+ const unsigned long *advertising, -+ unsigned int neg_mode) - { -- unsigned int neg_mode; - bool changed = 0; - u16 bmcr; - int ret, adv; -@@ -3572,7 +3572,6 @@ int phylink_mii_c22_pcs_config(struct md - changed = ret; - } - -- neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) - bmcr = BMCR_ANENABLE; - else ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -743,9 +743,10 @@ void phylink_mii_c22_pcs_get_state(struc - struct phylink_link_state *state); - int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, - const unsigned long *advertising); --int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, -+int phylink_mii_c22_pcs_config(struct mdio_device *pcs, - phy_interface_t interface, -- const unsigned long *advertising); -+ const unsigned long *advertising, -+ unsigned int neg_mode); - void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); - - void phylink_resolve_c73(struct phylink_link_state *state); diff --git a/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch b/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch deleted file mode 100644 index 5e0128766c..0000000000 --- a/target/linux/generic/backport-6.6/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 3b2de56a146f34e3f70a84cc3a1897064e445d16 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 16 Jun 2023 13:06:43 +0100 -Subject: [PATCH] net: pcs: lynxi: update PCS driver to use neg_mode - -Update the Lynxi PCS driver to use neg_mode rather than the mode -argument. This ensures that the link_up() method will always program -the speed and duplex when negotiation is disabled. - -Signed-off-by: Russell King (Oracle) -Link: https://lore.kernel.org/r/E1qA8Dz-00EaFY-5A@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-mtk-lynxi.c | 39 ++++++++++++++------------------- - 1 file changed, 16 insertions(+), 23 deletions(-) - ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(stru - FIELD_GET(SGMII_LPA, adv)); - } - --static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, -+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -- bool mode_changed = false, changed, use_an; -+ bool mode_changed = false, changed; - unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; - -@@ -121,30 +121,22 @@ static int mtk_pcs_lynxi_config(struct p - * we assume that fixes it's speed at bitrate = line rate (in - * other words, 1000Mbps or 2500Mbps). - */ -- if (interface == PHY_INTERFACE_MODE_SGMII) { -+ if (interface == PHY_INTERFACE_MODE_SGMII) - sgm_mode = SGMII_IF_MODE_SGMII; -- if (phylink_autoneg_inband(mode)) { -- sgm_mode |= SGMII_REMOTE_FAULT_DIS | -- SGMII_SPEED_DUPLEX_AN; -- use_an = true; -- } else { -- use_an = false; -- } -- } else if (phylink_autoneg_inband(mode)) { -- /* 1000base-X or 2500base-X autoneg */ -- sgm_mode = SGMII_REMOTE_FAULT_DIS; -- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -- advertising); -- } else { -+ else - /* 1000base-X or 2500base-X without autoneg */ - sgm_mode = 0; -- use_an = false; -- } - -- if (use_an) -+ if (neg_mode & PHYLINK_PCS_NEG_INBAND) -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS; -+ -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { -+ if (interface == PHY_INTERFACE_MODE_SGMII) -+ sgm_mode |= SGMII_SPEED_DUPLEX_AN; - bmcr = BMCR_ANENABLE; -- else -+ } else { - bmcr = 0; -+ } - - if (mpcs->interface != interface) { - link_timer = phylink_get_link_timer_ns(interface); -@@ -216,14 +208,15 @@ static void mtk_pcs_lynxi_restart_an(str - regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); - } - --static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, -+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, -+ unsigned int neg_mode, - phy_interface_t interface, int speed, - int duplex) - { - struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); - unsigned int sgm_mode; - -- if (!phylink_autoneg_inband(mode)) { -+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { - /* Force the speed and duplex setting */ - if (speed == SPEED_10) - sgm_mode = SGMII_SPEED_10; -@@ -286,6 +279,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create - mpcs->regmap = regmap; - mpcs->flags = flags; - mpcs->pcs.ops = &mtk_pcs_lynxi_ops; -+ mpcs->pcs.neg_mode = true; - mpcs->pcs.poll = true; - mpcs->interface = PHY_INTERFACE_MODE_NA; - diff --git a/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch b/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch deleted file mode 100644 index 3dd22d2916..0000000000 --- a/target/linux/generic/backport-6.6/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 459fd2f11204c962e3153020f4f56748e0e10afb Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 21 Mar 2023 15:58:49 +0000 -Subject: [PATCH] net: pcs: xpcs: use Autoneg bit rather than an_enabled - -The Autoneg bit in the advertising bitmap and state->an_enabled are -always identical. Thus, we will be removing state->an_enabled. - -Use the Autoneg bit in the advertising bitmap to indicate whether -autonegotiation should be used, rather than using the an_enabled -member which will be going away. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Simon Horman -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-xpcs.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -931,6 +931,7 @@ static int xpcs_get_state_c73(struct dw_ - struct phylink_link_state *state, - const struct xpcs_compat *compat) - { -+ bool an_enabled; - int ret; - - /* Link needs to be read first ... */ -@@ -948,11 +949,13 @@ static int xpcs_get_state_c73(struct dw_ - return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); - } - -- if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { -+ an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising); -+ if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { - state->an_complete = true; - xpcs_read_lpa_c73(xpcs, state); - xpcs_resolve_lpa_c73(xpcs, state); -- } else if (state->an_enabled) { -+ } else if (an_enabled) { - state->link = 0; - } else if (state->link) { - xpcs_resolve_pma(xpcs, state); -@@ -1007,7 +1010,8 @@ static int xpcs_get_state_c37_1000basex( - { - int lpa, bmsr; - -- if (state->an_enabled) { -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ state->advertising)) { - /* Reset link state */ - state->link = false; - diff --git a/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch b/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch deleted file mode 100644 index 7cae8515fa..0000000000 --- a/target/linux/generic/backport-6.6/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 43fb622d91a9f408322735d2f736495c1009f575 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 9 May 2023 12:50:04 +0100 -Subject: [PATCH] net: pcs: xpcs: fix incorrect number of interfaces - -In synopsys_xpcs_compat[], the DW_XPCS_2500BASEX entry was setting -the number of interfaces using the xpcs_2500basex_features array -rather than xpcs_2500basex_interfaces. This causes us to overflow -the array of interfaces. Fix this. - -Fixes: f27abde3042a ("net: pcs: add 2500BASEX support for Intel mGbE controller") -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Reviewed-by: Leon Romanovsky -Signed-off-by: David S. Miller ---- - drivers/net/pcs/pcs-xpcs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -1211,7 +1211,7 @@ static const struct xpcs_compat synopsys - [DW_XPCS_2500BASEX] = { - .supported = xpcs_2500basex_features, - .interface = xpcs_2500basex_interfaces, -- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features), -+ .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces), - .an_mode = DW_2500BASEX, - }, - }; diff --git a/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch b/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch deleted file mode 100644 index 816aa67787..0000000000 --- a/target/linux/generic/backport-6.6/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 1b9827ceab08450308f7971d6fd700ec88b6ce67 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 3 Dec 2022 14:20:37 +0100 -Subject: [PATCH 098/250] net: mtk_eth_soc: enable flow offload support for - MT7986 SoC - -Since Wireless Ethernet Dispatcher is now available for mt7986 in mt76, -enable hw flow support for MT7986 SoC. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/fdcaacd827938e6a8c4aa1ac2c13e46d2c08c821.1670072898.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4333,6 +4333,7 @@ static const struct mtk_soc_data mt7986_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7986_CLKS_BITMAP, - .required_pctl = false, -+ .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), - .txrx = { diff --git a/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch b/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch deleted file mode 100644 index c48613929d..0000000000 --- a/target/linux/generic/backport-6.6/729-01-v6.1-net-ethernet-mtk_wed-introduce-wed-mcu-support.patch +++ /dev/null @@ -1,591 +0,0 @@ -From: Sujuan Chen -Date: Sat, 5 Nov 2022 23:36:18 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: introduce wed mcu support - -Introduce WED mcu support used to configure WED WO chip. -This is a preliminary patch in order to add RX Wireless -Ethernet Dispatch available on MT7986 SoC. - -Tested-by: Daniel Golle -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Sujuan Chen -Signed-off-by: David S. Miller ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -5,7 +5,7 @@ - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o - mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o --mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o -+mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o - ifdef CONFIG_DEBUG_FS - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o - endif ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -0,0 +1,359 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2022 MediaTek Inc. -+ * -+ * Author: Lorenzo Bianconi -+ * Sujuan Chen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "mtk_wed_regs.h" -+#include "mtk_wed_wo.h" -+#include "mtk_wed.h" -+ -+static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) -+{ -+ return readl(wo->boot.addr + reg); -+} -+ -+static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) -+{ -+ writel(val, wo->boot.addr + reg); -+} -+ -+static struct sk_buff * -+mtk_wed_mcu_msg_alloc(const void *data, int data_len) -+{ -+ int length = sizeof(struct mtk_wed_mcu_hdr) + data_len; -+ struct sk_buff *skb; -+ -+ skb = alloc_skb(length, GFP_KERNEL); -+ if (!skb) -+ return NULL; -+ -+ memset(skb->head, 0, length); -+ skb_reserve(skb, sizeof(struct mtk_wed_mcu_hdr)); -+ if (data && data_len) -+ skb_put_data(skb, data, data_len); -+ -+ return skb; -+} -+ -+static struct sk_buff * -+mtk_wed_mcu_get_response(struct mtk_wed_wo *wo, unsigned long expires) -+{ -+ if (!time_is_after_jiffies(expires)) -+ return NULL; -+ -+ wait_event_timeout(wo->mcu.wait, !skb_queue_empty(&wo->mcu.res_q), -+ expires - jiffies); -+ return skb_dequeue(&wo->mcu.res_q); -+} -+ -+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb) -+{ -+ skb_queue_tail(&wo->mcu.res_q, skb); -+ wake_up(&wo->mcu.wait); -+} -+ -+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, -+ struct sk_buff *skb) -+{ -+ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ -+ switch (hdr->cmd) { -+ case MTK_WED_WO_EVT_LOG_DUMP: { -+ const char *msg = (const char *)(skb->data + sizeof(*hdr)); -+ -+ dev_notice(wo->hw->dev, "%s\n", msg); -+ break; -+ } -+ case MTK_WED_WO_EVT_PROFILING: { -+ struct mtk_wed_wo_log_info *info; -+ u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); -+ int i; -+ -+ info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); -+ for (i = 0 ; i < count ; i++) -+ dev_notice(wo->hw->dev, -+ "SN:%u latency: total=%u, rro:%u, mod:%u\n", -+ le32_to_cpu(info[i].sn), -+ le32_to_cpu(info[i].total), -+ le32_to_cpu(info[i].rro), -+ le32_to_cpu(info[i].mod)); -+ break; -+ } -+ case MTK_WED_WO_EVT_RXCNT_INFO: -+ break; -+ default: -+ break; -+ } -+ -+ dev_kfree_skb(skb); -+} -+ -+static int -+mtk_wed_mcu_skb_send_msg(struct mtk_wed_wo *wo, struct sk_buff *skb, -+ int id, int cmd, u16 *wait_seq, bool wait_resp) -+{ -+ struct mtk_wed_mcu_hdr *hdr; -+ -+ /* TODO: make it dynamic based on cmd */ -+ wo->mcu.timeout = 20 * HZ; -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb_push(skb, sizeof(*hdr)); -+ hdr->cmd = cmd; -+ hdr->length = cpu_to_le16(skb->len); -+ -+ if (wait_resp && wait_seq) { -+ u16 seq = ++wo->mcu.seq; -+ -+ if (!seq) -+ seq = ++wo->mcu.seq; -+ *wait_seq = seq; -+ -+ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_NEED_RSP); -+ hdr->seq = cpu_to_le16(seq); -+ } -+ if (id == MTK_WED_MODULE_ID_WO) -+ hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); -+ -+ dev_kfree_skb(skb); -+ return 0; -+} -+ -+static int -+mtk_wed_mcu_parse_response(struct mtk_wed_wo *wo, struct sk_buff *skb, -+ int cmd, int seq) -+{ -+ struct mtk_wed_mcu_hdr *hdr; -+ -+ if (!skb) { -+ dev_err(wo->hw->dev, "Message %08x (seq %d) timeout\n", -+ cmd, seq); -+ return -ETIMEDOUT; -+ } -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ if (le16_to_cpu(hdr->seq) != seq) -+ return -EAGAIN; -+ -+ skb_pull(skb, sizeof(*hdr)); -+ switch (cmd) { -+ case MTK_WED_WO_CMD_RXCNT_INFO: -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, -+ const void *data, int len, bool wait_resp) -+{ -+ unsigned long expires; -+ struct sk_buff *skb; -+ u16 seq; -+ int ret; -+ -+ skb = mtk_wed_mcu_msg_alloc(data, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ mutex_lock(&wo->mcu.mutex); -+ -+ ret = mtk_wed_mcu_skb_send_msg(wo, skb, id, cmd, &seq, wait_resp); -+ if (ret || !wait_resp) -+ goto unlock; -+ -+ expires = jiffies + wo->mcu.timeout; -+ do { -+ skb = mtk_wed_mcu_get_response(wo, expires); -+ ret = mtk_wed_mcu_parse_response(wo, skb, cmd, seq); -+ dev_kfree_skb(skb); -+ } while (ret == -EAGAIN); -+ -+unlock: -+ mutex_unlock(&wo->mcu.mutex); -+ -+ return ret; -+} -+ -+static int -+mtk_wed_get_memory_region(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ struct reserved_mem *rmem; -+ struct device_node *np; -+ int index; -+ -+ index = of_property_match_string(wo->hw->node, "memory-region-names", -+ region->name); -+ if (index < 0) -+ return index; -+ -+ np = of_parse_phandle(wo->hw->node, "memory-region", index); -+ if (!np) -+ return -ENODEV; -+ -+ rmem = of_reserved_mem_lookup(np); -+ of_node_put(np); -+ -+ if (!rmem) -+ return -ENODEV; -+ -+ region->phy_addr = rmem->base; -+ region->size = rmem->size; -+ region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); -+ -+ return !region->addr ? -EINVAL : 0; -+} -+ -+static int -+mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ const u8 *first_region_ptr, *region_ptr, *trailer_ptr, *ptr = fw->data; -+ const struct mtk_wed_fw_trailer *trailer; -+ const struct mtk_wed_fw_region *fw_region; -+ -+ trailer_ptr = fw->data + fw->size - sizeof(*trailer); -+ trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; -+ region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); -+ first_region_ptr = region_ptr; -+ -+ while (region_ptr < trailer_ptr) { -+ u32 length; -+ -+ fw_region = (const struct mtk_wed_fw_region *)region_ptr; -+ length = le32_to_cpu(fw_region->len); -+ -+ if (region->phy_addr != le32_to_cpu(fw_region->addr)) -+ goto next; -+ -+ if (region->size < length) -+ goto next; -+ -+ if (first_region_ptr < ptr + length) -+ goto next; -+ -+ if (region->shared && region->consumed) -+ return 0; -+ -+ if (!region->shared || !region->consumed) { -+ memcpy_toio(region->addr, ptr, length); -+ region->consumed = true; -+ return 0; -+ } -+next: -+ region_ptr += sizeof(*fw_region); -+ ptr += length; -+ } -+ -+ return -EINVAL; -+} -+ -+static int -+mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) -+{ -+ static struct mtk_wed_wo_memory_region mem_region[] = { -+ [MTK_WED_WO_REGION_EMI] = { -+ .name = "wo-emi", -+ }, -+ [MTK_WED_WO_REGION_ILM] = { -+ .name = "wo-ilm", -+ }, -+ [MTK_WED_WO_REGION_DATA] = { -+ .name = "wo-data", -+ .shared = true, -+ }, -+ }; -+ const struct mtk_wed_fw_trailer *trailer; -+ const struct firmware *fw; -+ const char *fw_name; -+ u32 val, boot_cr; -+ int ret, i; -+ -+ /* load firmware region metadata */ -+ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -+ ret = mtk_wed_get_memory_region(wo, &mem_region[i]); -+ if (ret) -+ return ret; -+ } -+ -+ wo->boot.name = "wo-boot"; -+ ret = mtk_wed_get_memory_region(wo, &wo->boot); -+ if (ret) -+ return ret; -+ -+ /* set dummy cr */ -+ wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, -+ wo->hw->index + 1); -+ -+ /* load firmware */ -+ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ ret = request_firmware(&fw, fw_name, wo->hw->dev); -+ if (ret) -+ return ret; -+ -+ trailer = (void *)(fw->data + fw->size - -+ sizeof(struct mtk_wed_fw_trailer)); -+ dev_info(wo->hw->dev, -+ "MTK WED WO Firmware Version: %.10s, Build Time: %.15s\n", -+ trailer->fw_ver, trailer->build_date); -+ dev_info(wo->hw->dev, "MTK WED WO Chip ID %02x Region %d\n", -+ trailer->chip_id, trailer->num_region); -+ -+ for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -+ ret = mtk_wed_mcu_run_firmware(wo, fw, &mem_region[i]); -+ if (ret) -+ goto out; -+ } -+ -+ /* set the start address */ -+ boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR -+ : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; -+ wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); -+ /* wo firmware reset */ -+ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); -+ -+ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); -+ val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK -+ : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; -+ wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); -+out: -+ release_firmware(fw); -+ -+ return ret; -+} -+ -+static u32 -+mtk_wed_mcu_read_fw_dl(struct mtk_wed_wo *wo) -+{ -+ return wed_r32(wo->hw->wed_dev, -+ MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL); -+} -+ -+int mtk_wed_mcu_init(struct mtk_wed_wo *wo) -+{ -+ u32 val; -+ int ret; -+ -+ skb_queue_head_init(&wo->mcu.res_q); -+ init_waitqueue_head(&wo->mcu.wait); -+ mutex_init(&wo->mcu.mutex); -+ -+ ret = mtk_wed_mcu_load_firmware(wo); -+ if (ret) -+ return ret; -+ -+ return readx_poll_timeout(mtk_wed_mcu_read_fw_dl, wo, val, !val, -+ 100, MTK_FW_DL_TIMEOUT); -+} -+ -+MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); -+MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -152,6 +152,7 @@ struct mtk_wdma_desc { - - #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) - -+#define MTK_WED_SCR0 0x3c0 - #define MTK_WED_WPDMA_INT_TRIGGER 0x504 - #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) - #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -0,0 +1,150 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2022 Lorenzo Bianconi */ -+ -+#ifndef __MTK_WED_WO_H -+#define __MTK_WED_WO_H -+ -+#include -+#include -+ -+struct mtk_wed_hw; -+ -+struct mtk_wed_mcu_hdr { -+ /* DW0 */ -+ u8 version; -+ u8 cmd; -+ __le16 length; -+ -+ /* DW1 */ -+ __le16 seq; -+ __le16 flag; -+ -+ /* DW2 */ -+ __le32 status; -+ -+ /* DW3 */ -+ u8 rsv[20]; -+}; -+ -+struct mtk_wed_wo_log_info { -+ __le32 sn; -+ __le32 total; -+ __le32 rro; -+ __le32 mod; -+}; -+ -+enum mtk_wed_wo_event { -+ MTK_WED_WO_EVT_LOG_DUMP = 0x1, -+ MTK_WED_WO_EVT_PROFILING = 0x2, -+ MTK_WED_WO_EVT_RXCNT_INFO = 0x3, -+}; -+ -+#define MTK_WED_MODULE_ID_WO 1 -+#define MTK_FW_DL_TIMEOUT 4000000 /* us */ -+#define MTK_WOCPU_TIMEOUT 2000000 /* us */ -+ -+enum { -+ MTK_WED_WARP_CMD_FLAG_RSP = BIT(0), -+ MTK_WED_WARP_CMD_FLAG_NEED_RSP = BIT(1), -+ MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), -+}; -+ -+enum { -+ MTK_WED_WO_REGION_EMI, -+ MTK_WED_WO_REGION_ILM, -+ MTK_WED_WO_REGION_DATA, -+ MTK_WED_WO_REGION_BOOT, -+ __MTK_WED_WO_REGION_MAX, -+}; -+ -+enum mtk_wed_dummy_cr_idx { -+ MTK_WED_DUMMY_CR_FWDL, -+ MTK_WED_DUMMY_CR_WO_STATUS, -+}; -+ -+#define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" -+#define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" -+ -+#define MTK_WO_MCU_CFG_LS_BASE 0 -+#define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) -+#define MTK_WO_MCU_CFG_LS_FW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x004) -+#define MTK_WO_MCU_CFG_LS_CFG_DBG1_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x00c) -+#define MTK_WO_MCU_CFG_LS_CFG_DBG2_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x010) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x014) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_SET_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x018) -+#define MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x01c) -+#define MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x050) -+#define MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x060) -+#define MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x064) -+ -+#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) -+#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) -+ -+struct mtk_wed_wo_memory_region { -+ const char *name; -+ void __iomem *addr; -+ phys_addr_t phy_addr; -+ u32 size; -+ bool shared:1; -+ bool consumed:1; -+}; -+ -+struct mtk_wed_fw_region { -+ __le32 decomp_crc; -+ __le32 decomp_len; -+ __le32 decomp_blk_sz; -+ u8 rsv0[4]; -+ __le32 addr; -+ __le32 len; -+ u8 feature_set; -+ u8 rsv1[15]; -+} __packed; -+ -+struct mtk_wed_fw_trailer { -+ u8 chip_id; -+ u8 eco_code; -+ u8 num_region; -+ u8 format_ver; -+ u8 format_flag; -+ u8 rsv[2]; -+ char fw_ver[10]; -+ char build_date[15]; -+ u32 crc; -+}; -+ -+struct mtk_wed_wo { -+ struct mtk_wed_hw *hw; -+ struct mtk_wed_wo_memory_region boot; -+ -+ struct { -+ struct mutex mutex; -+ int timeout; -+ u16 seq; -+ -+ struct sk_buff_head res_q; -+ wait_queue_head_t wait; -+ } mcu; -+}; -+ -+static inline int -+mtk_wed_mcu_check_msg(struct mtk_wed_wo *wo, struct sk_buff *skb) -+{ -+ struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ -+ if (hdr->version) -+ return -EINVAL; -+ -+ if (skb->len < sizeof(*hdr) || skb->len != le16_to_cpu(hdr->length)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb); -+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, -+ struct sk_buff *skb); -+int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, -+ const void *data, int len, bool wait_resp); -+int mtk_wed_mcu_init(struct mtk_wed_wo *wo); -+ -+#endif /* __MTK_WED_WO_H */ ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -11,6 +11,35 @@ - struct mtk_wed_hw; - struct mtk_wdma_desc; - -+enum mtk_wed_wo_cmd { -+ MTK_WED_WO_CMD_WED_CFG, -+ MTK_WED_WO_CMD_WED_RX_STAT, -+ MTK_WED_WO_CMD_RRO_SER, -+ MTK_WED_WO_CMD_DBG_INFO, -+ MTK_WED_WO_CMD_DEV_INFO, -+ MTK_WED_WO_CMD_BSS_INFO, -+ MTK_WED_WO_CMD_STA_REC, -+ MTK_WED_WO_CMD_DEV_INFO_DUMP, -+ MTK_WED_WO_CMD_BSS_INFO_DUMP, -+ MTK_WED_WO_CMD_STA_REC_DUMP, -+ MTK_WED_WO_CMD_BA_INFO_DUMP, -+ MTK_WED_WO_CMD_FBCMD_Q_DUMP, -+ MTK_WED_WO_CMD_FW_LOG_CTRL, -+ MTK_WED_WO_CMD_LOG_FLUSH, -+ MTK_WED_WO_CMD_CHANGE_STATE, -+ MTK_WED_WO_CMD_CPU_STATS_ENABLE, -+ MTK_WED_WO_CMD_CPU_STATS_DUMP, -+ MTK_WED_WO_CMD_EXCEPTION_INIT, -+ MTK_WED_WO_CMD_PROF_CTRL, -+ MTK_WED_WO_CMD_STA_BA_DUMP, -+ MTK_WED_WO_CMD_BA_CTRL_DUMP, -+ MTK_WED_WO_CMD_RXCNT_CTRL, -+ MTK_WED_WO_CMD_RXCNT_INFO, -+ MTK_WED_WO_CMD_SET_CAP, -+ MTK_WED_WO_CMD_CCIF_RING_DUMP, -+ MTK_WED_WO_CMD_WED_END -+}; -+ - enum mtk_wed_bus_tye { - MTK_WED_BUS_PCIE, - MTK_WED_BUS_AXI, diff --git a/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch deleted file mode 100644 index fd5f45df2a..0000000000 --- a/target/linux/generic/backport-6.6/729-02-v6.1-net-ethernet-mtk_wed-introduce-wed-wo-support.patch +++ /dev/null @@ -1,737 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:19 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: introduce wed wo support - -Introduce WO chip support to mtk wed driver. MTK WED WO is used to -implement RX Wireless Ethernet Dispatch and offload traffic received by -wlan nic to the wired interface. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -5,7 +5,7 @@ - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o - mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o --mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.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 - endif ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -16,6 +16,7 @@ - #include "mtk_wed_regs.h" - #include "mtk_wed.h" - #include "mtk_ppe.h" -+#include "mtk_wed_wo.h" - - #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) - -@@ -355,6 +356,8 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wed_free_buffer(dev); - mtk_wed_free_tx_rings(dev); -+ if (hw->version != 1) -+ mtk_wed_wo_deinit(hw); - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { - struct device_node *wlan_node; -@@ -878,9 +881,11 @@ mtk_wed_attach(struct mtk_wed_device *de - } - - mtk_wed_hw_init_early(dev); -- if (hw->hifsys) -+ if (hw->version == 1) - regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, - BIT(hw->index), 0); -+ else -+ ret = mtk_wed_wo_init(hw); - - out: - mutex_unlock(&hw_lock); ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -10,6 +10,7 @@ - #include - - struct mtk_eth; -+struct mtk_wed_wo; - - struct mtk_wed_hw { - struct device_node *node; -@@ -22,6 +23,7 @@ struct mtk_wed_hw { - struct regmap *mirror; - struct dentry *debugfs_dir; - struct mtk_wed_device *wed_dev; -+ struct mtk_wed_wo *wed_wo; - u32 debugfs_reg; - u32 num_flows; - u8 version; ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -122,8 +122,7 @@ mtk_wed_mcu_skb_send_msg(struct mtk_wed_ - if (id == MTK_WED_MODULE_ID_WO) - hdr->flag |= cpu_to_le16(MTK_WED_WARP_CMD_FLAG_FROM_TO_WO); - -- dev_kfree_skb(skb); -- return 0; -+ return mtk_wed_wo_queue_tx_skb(wo, &wo->q_tx, skb); - } - - static int ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -0,0 +1,508 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2022 MediaTek Inc. -+ * -+ * Author: Lorenzo Bianconi -+ * Sujuan Chen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mtk_wed.h" -+#include "mtk_wed_regs.h" -+#include "mtk_wed_wo.h" -+ -+static u32 -+mtk_wed_mmio_r32(struct mtk_wed_wo *wo, u32 reg) -+{ -+ u32 val; -+ -+ if (regmap_read(wo->mmio.regs, reg, &val)) -+ val = ~0; -+ -+ return val; -+} -+ -+static void -+mtk_wed_mmio_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) -+{ -+ regmap_write(wo->mmio.regs, reg, val); -+} -+ -+static u32 -+mtk_wed_wo_get_isr(struct mtk_wed_wo *wo) -+{ -+ u32 val = mtk_wed_mmio_r32(wo, MTK_WED_WO_CCIF_RCHNUM); -+ -+ return val & MTK_WED_WO_CCIF_RCHNUM_MASK; -+} -+ -+static void -+mtk_wed_wo_set_isr(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_IRQ0_MASK, mask); -+} -+ -+static void -+mtk_wed_wo_set_ack(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_ACK, mask); -+} -+ -+static void -+mtk_wed_wo_set_isr_mask(struct mtk_wed_wo *wo, u32 mask, u32 val, bool set) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wo->mmio.lock, flags); -+ wo->mmio.irq_mask &= ~mask; -+ wo->mmio.irq_mask |= val; -+ if (set) -+ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); -+ spin_unlock_irqrestore(&wo->mmio.lock, flags); -+} -+ -+static void -+mtk_wed_wo_irq_enable(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_wo_set_isr_mask(wo, 0, mask, false); -+ tasklet_schedule(&wo->mmio.irq_tasklet); -+} -+ -+static void -+mtk_wed_wo_irq_disable(struct mtk_wed_wo *wo, u32 mask) -+{ -+ mtk_wed_wo_set_isr_mask(wo, mask, 0, true); -+} -+ -+static void -+mtk_wed_wo_kickout(struct mtk_wed_wo *wo) -+{ -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_BUSY, 1 << MTK_WED_WO_TXCH_NUM); -+ mtk_wed_mmio_w32(wo, MTK_WED_WO_CCIF_TCHNUM, MTK_WED_WO_TXCH_NUM); -+} -+ -+static void -+mtk_wed_wo_queue_kick(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ u32 val) -+{ -+ wmb(); -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, val); -+} -+ -+static void * -+mtk_wed_wo_dequeue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, u32 *len, -+ bool flush) -+{ -+ int buf_len = SKB_WITH_OVERHEAD(q->buf_size); -+ int index = (q->tail + 1) % q->n_desc; -+ struct mtk_wed_wo_queue_entry *entry; -+ struct mtk_wed_wo_queue_desc *desc; -+ void *buf; -+ -+ if (!q->queued) -+ return NULL; -+ -+ if (flush) -+ q->desc[index].ctrl |= cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE); -+ else if (!(q->desc[index].ctrl & cpu_to_le32(MTK_WED_WO_CTL_DMA_DONE))) -+ return NULL; -+ -+ q->tail = index; -+ q->queued--; -+ -+ desc = &q->desc[index]; -+ entry = &q->entry[index]; -+ buf = entry->buf; -+ if (len) -+ *len = FIELD_GET(MTK_WED_WO_CTL_SD_LEN0, -+ le32_to_cpu(READ_ONCE(desc->ctrl))); -+ if (buf) -+ dma_unmap_single(wo->hw->dev, entry->addr, buf_len, -+ DMA_FROM_DEVICE); -+ entry->buf = NULL; -+ -+ return buf; -+} -+ -+static int -+mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ gfp_t gfp, bool rx) -+{ -+ enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; -+ int n_buf = 0; -+ -+ spin_lock_bh(&q->lock); -+ while (q->queued < q->n_desc) { -+ void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); -+ struct mtk_wed_wo_queue_entry *entry; -+ dma_addr_t addr; -+ -+ if (!buf) -+ break; -+ -+ addr = dma_map_single(wo->hw->dev, buf, q->buf_size, dir); -+ if (unlikely(dma_mapping_error(wo->hw->dev, addr))) { -+ skb_free_frag(buf); -+ break; -+ } -+ -+ q->head = (q->head + 1) % q->n_desc; -+ entry = &q->entry[q->head]; -+ entry->addr = addr; -+ entry->len = q->buf_size; -+ q->entry[q->head].buf = buf; -+ -+ if (rx) { -+ struct mtk_wed_wo_queue_desc *desc = &q->desc[q->head]; -+ u32 ctrl = MTK_WED_WO_CTL_LAST_SEC0 | -+ FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, -+ entry->len); -+ -+ WRITE_ONCE(desc->buf0, cpu_to_le32(addr)); -+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); -+ } -+ q->queued++; -+ n_buf++; -+ } -+ spin_unlock_bh(&q->lock); -+ -+ return n_buf; -+} -+ -+static void -+mtk_wed_wo_rx_complete(struct mtk_wed_wo *wo) -+{ -+ mtk_wed_wo_set_ack(wo, MTK_WED_WO_RXCH_INT_MASK); -+ mtk_wed_wo_irq_enable(wo, MTK_WED_WO_RXCH_INT_MASK); -+} -+ -+static void -+mtk_wed_wo_rx_run_queue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ for (;;) { -+ struct mtk_wed_mcu_hdr *hdr; -+ struct sk_buff *skb; -+ void *data; -+ u32 len; -+ -+ data = mtk_wed_wo_dequeue(wo, q, &len, false); -+ if (!data) -+ break; -+ -+ skb = build_skb(data, q->buf_size); -+ if (!skb) { -+ skb_free_frag(data); -+ continue; -+ } -+ -+ __skb_put(skb, len); -+ if (mtk_wed_mcu_check_msg(wo, skb)) { -+ dev_kfree_skb(skb); -+ continue; -+ } -+ -+ hdr = (struct mtk_wed_mcu_hdr *)skb->data; -+ if (hdr->flag & cpu_to_le16(MTK_WED_WARP_CMD_FLAG_RSP)) -+ mtk_wed_mcu_rx_event(wo, skb); -+ else -+ mtk_wed_mcu_rx_unsolicited_event(wo, skb); -+ } -+ -+ if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { -+ u32 index = (q->head - 1) % q->n_desc; -+ -+ mtk_wed_wo_queue_kick(wo, q, index); -+ } -+} -+ -+static irqreturn_t -+mtk_wed_wo_irq_handler(int irq, void *data) -+{ -+ struct mtk_wed_wo *wo = data; -+ -+ mtk_wed_wo_set_isr(wo, 0); -+ tasklet_schedule(&wo->mmio.irq_tasklet); -+ -+ return IRQ_HANDLED; -+} -+ -+static void mtk_wed_wo_irq_tasklet(struct tasklet_struct *t) -+{ -+ struct mtk_wed_wo *wo = from_tasklet(wo, t, mmio.irq_tasklet); -+ u32 intr, mask; -+ -+ /* disable interrupts */ -+ mtk_wed_wo_set_isr(wo, 0); -+ -+ intr = mtk_wed_wo_get_isr(wo); -+ intr &= wo->mmio.irq_mask; -+ mask = intr & (MTK_WED_WO_RXCH_INT_MASK | MTK_WED_WO_EXCEPTION_INT_MASK); -+ mtk_wed_wo_irq_disable(wo, mask); -+ -+ if (intr & MTK_WED_WO_RXCH_INT_MASK) { -+ mtk_wed_wo_rx_run_queue(wo, &wo->q_rx); -+ mtk_wed_wo_rx_complete(wo); -+ } -+} -+ -+/* mtk wed wo hw queues */ -+ -+static int -+mtk_wed_wo_queue_alloc(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ int n_desc, int buf_size, int index, -+ struct mtk_wed_wo_queue_regs *regs) -+{ -+ spin_lock_init(&q->lock); -+ q->regs = *regs; -+ q->n_desc = n_desc; -+ q->buf_size = buf_size; -+ -+ q->desc = dmam_alloc_coherent(wo->hw->dev, n_desc * sizeof(*q->desc), -+ &q->desc_dma, GFP_KERNEL); -+ if (!q->desc) -+ return -ENOMEM; -+ -+ q->entry = devm_kzalloc(wo->hw->dev, n_desc * sizeof(*q->entry), -+ GFP_KERNEL); -+ if (!q->entry) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void -+mtk_wed_wo_queue_free(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); -+ dma_free_coherent(wo->hw->dev, q->n_desc * sizeof(*q->desc), q->desc, -+ q->desc_dma); -+} -+ -+static void -+mtk_wed_wo_queue_tx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ struct page *page; -+ int i; -+ -+ spin_lock_bh(&q->lock); -+ for (i = 0; i < q->n_desc; i++) { -+ struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; -+ -+ dma_unmap_single(wo->hw->dev, entry->addr, entry->len, -+ DMA_TO_DEVICE); -+ skb_free_frag(entry->buf); -+ entry->buf = NULL; -+ } -+ spin_unlock_bh(&q->lock); -+ -+ if (!q->cache.va) -+ return; -+ -+ page = virt_to_page(q->cache.va); -+ __page_frag_cache_drain(page, q->cache.pagecnt_bias); -+ memset(&q->cache, 0, sizeof(q->cache)); -+} -+ -+static void -+mtk_wed_wo_queue_rx_clean(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ struct page *page; -+ -+ spin_lock_bh(&q->lock); -+ for (;;) { -+ void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); -+ -+ if (!buf) -+ break; -+ -+ skb_free_frag(buf); -+ } -+ spin_unlock_bh(&q->lock); -+ -+ if (!q->cache.va) -+ return; -+ -+ page = virt_to_page(q->cache.va); -+ __page_frag_cache_drain(page, q->cache.pagecnt_bias); -+ memset(&q->cache, 0, sizeof(q->cache)); -+} -+ -+static void -+mtk_wed_wo_queue_reset(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q) -+{ -+ mtk_wed_mmio_w32(wo, q->regs.cpu_idx, 0); -+ mtk_wed_mmio_w32(wo, q->regs.desc_base, q->desc_dma); -+ mtk_wed_mmio_w32(wo, q->regs.ring_size, q->n_desc); -+} -+ -+int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -+ struct sk_buff *skb) -+{ -+ struct mtk_wed_wo_queue_entry *entry; -+ struct mtk_wed_wo_queue_desc *desc; -+ int ret = 0, index; -+ u32 ctrl; -+ -+ spin_lock_bh(&q->lock); -+ -+ q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); -+ index = (q->head + 1) % q->n_desc; -+ if (q->tail == index) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ entry = &q->entry[index]; -+ if (skb->len > entry->len) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ desc = &q->desc[index]; -+ q->head = index; -+ -+ dma_sync_single_for_cpu(wo->hw->dev, entry->addr, skb->len, -+ DMA_TO_DEVICE); -+ memcpy(entry->buf, skb->data, skb->len); -+ dma_sync_single_for_device(wo->hw->dev, entry->addr, skb->len, -+ DMA_TO_DEVICE); -+ -+ ctrl = FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0, skb->len) | -+ MTK_WED_WO_CTL_LAST_SEC0 | MTK_WED_WO_CTL_DMA_DONE; -+ WRITE_ONCE(desc->buf0, cpu_to_le32(entry->addr)); -+ WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); -+ -+ mtk_wed_wo_queue_kick(wo, q, q->head); -+ mtk_wed_wo_kickout(wo); -+out: -+ spin_unlock_bh(&q->lock); -+ -+ dev_kfree_skb(skb); -+ -+ return ret; -+} -+ -+static int -+mtk_wed_wo_exception_init(struct mtk_wed_wo *wo) -+{ -+ return 0; -+} -+ -+static int -+mtk_wed_wo_hardware_init(struct mtk_wed_wo *wo) -+{ -+ struct mtk_wed_wo_queue_regs regs; -+ struct device_node *np; -+ int ret; -+ -+ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ccif", 0); -+ if (!np) -+ return -ENODEV; -+ -+ wo->mmio.regs = syscon_regmap_lookup_by_phandle(np, NULL); -+ if (IS_ERR_OR_NULL(wo->mmio.regs)) -+ return PTR_ERR(wo->mmio.regs); -+ -+ wo->mmio.irq = irq_of_parse_and_map(np, 0); -+ wo->mmio.irq_mask = MTK_WED_WO_ALL_INT_MASK; -+ spin_lock_init(&wo->mmio.lock); -+ tasklet_setup(&wo->mmio.irq_tasklet, mtk_wed_wo_irq_tasklet); -+ -+ ret = devm_request_irq(wo->hw->dev, wo->mmio.irq, -+ mtk_wed_wo_irq_handler, IRQF_TRIGGER_HIGH, -+ KBUILD_MODNAME, wo); -+ if (ret) -+ goto error; -+ -+ regs.desc_base = MTK_WED_WO_CCIF_DUMMY1; -+ regs.ring_size = MTK_WED_WO_CCIF_DUMMY2; -+ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW4; -+ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY3; -+ -+ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_tx, MTK_WED_WO_RING_SIZE, -+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_TXCH_NUM, -+ ®s); -+ if (ret) -+ goto error; -+ -+ mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); -+ mtk_wed_wo_queue_reset(wo, &wo->q_tx); -+ -+ regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; -+ regs.ring_size = MTK_WED_WO_CCIF_DUMMY6; -+ regs.dma_idx = MTK_WED_WO_CCIF_SHADOW8; -+ regs.cpu_idx = MTK_WED_WO_CCIF_DUMMY7; -+ -+ ret = mtk_wed_wo_queue_alloc(wo, &wo->q_rx, MTK_WED_WO_RING_SIZE, -+ MTK_WED_WO_CMD_LEN, MTK_WED_WO_RXCH_NUM, -+ ®s); -+ if (ret) -+ goto error; -+ -+ mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); -+ mtk_wed_wo_queue_reset(wo, &wo->q_rx); -+ -+ /* rx queue irqmask */ -+ mtk_wed_wo_set_isr(wo, wo->mmio.irq_mask); -+ -+ return 0; -+ -+error: -+ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); -+ -+ return ret; -+} -+ -+static void -+mtk_wed_wo_hw_deinit(struct mtk_wed_wo *wo) -+{ -+ /* disable interrupts */ -+ mtk_wed_wo_set_isr(wo, 0); -+ -+ tasklet_disable(&wo->mmio.irq_tasklet); -+ -+ disable_irq(wo->mmio.irq); -+ devm_free_irq(wo->hw->dev, wo->mmio.irq, wo); -+ -+ mtk_wed_wo_queue_tx_clean(wo, &wo->q_tx); -+ mtk_wed_wo_queue_rx_clean(wo, &wo->q_rx); -+ mtk_wed_wo_queue_free(wo, &wo->q_tx); -+ mtk_wed_wo_queue_free(wo, &wo->q_rx); -+} -+ -+int mtk_wed_wo_init(struct mtk_wed_hw *hw) -+{ -+ struct mtk_wed_wo *wo; -+ int ret; -+ -+ wo = devm_kzalloc(hw->dev, sizeof(*wo), GFP_KERNEL); -+ if (!wo) -+ return -ENOMEM; -+ -+ hw->wed_wo = wo; -+ wo->hw = hw; -+ -+ ret = mtk_wed_wo_hardware_init(wo); -+ if (ret) -+ return ret; -+ -+ ret = mtk_wed_mcu_init(wo); -+ if (ret) -+ return ret; -+ -+ return mtk_wed_wo_exception_init(wo); -+} -+ -+void mtk_wed_wo_deinit(struct mtk_wed_hw *hw) -+{ -+ struct mtk_wed_wo *wo = hw->wed_wo; -+ -+ mtk_wed_wo_hw_deinit(wo); -+} ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -80,6 +80,54 @@ enum mtk_wed_dummy_cr_idx { - #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK BIT(5) - #define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK BIT(0) - -+#define MTK_WED_WO_RING_SIZE 256 -+#define MTK_WED_WO_CMD_LEN 1504 -+ -+#define MTK_WED_WO_TXCH_NUM 0 -+#define MTK_WED_WO_RXCH_NUM 1 -+#define MTK_WED_WO_RXCH_WO_EXCEPTION 7 -+ -+#define MTK_WED_WO_TXCH_INT_MASK BIT(0) -+#define MTK_WED_WO_RXCH_INT_MASK BIT(1) -+#define MTK_WED_WO_EXCEPTION_INT_MASK BIT(7) -+#define MTK_WED_WO_ALL_INT_MASK (MTK_WED_WO_RXCH_INT_MASK | \ -+ MTK_WED_WO_EXCEPTION_INT_MASK) -+ -+#define MTK_WED_WO_CCIF_BUSY 0x004 -+#define MTK_WED_WO_CCIF_START 0x008 -+#define MTK_WED_WO_CCIF_TCHNUM 0x00c -+#define MTK_WED_WO_CCIF_RCHNUM 0x010 -+#define MTK_WED_WO_CCIF_RCHNUM_MASK GENMASK(7, 0) -+ -+#define MTK_WED_WO_CCIF_ACK 0x014 -+#define MTK_WED_WO_CCIF_IRQ0_MASK 0x018 -+#define MTK_WED_WO_CCIF_IRQ1_MASK 0x01c -+#define MTK_WED_WO_CCIF_DUMMY1 0x020 -+#define MTK_WED_WO_CCIF_DUMMY2 0x024 -+#define MTK_WED_WO_CCIF_DUMMY3 0x028 -+#define MTK_WED_WO_CCIF_DUMMY4 0x02c -+#define MTK_WED_WO_CCIF_SHADOW1 0x030 -+#define MTK_WED_WO_CCIF_SHADOW2 0x034 -+#define MTK_WED_WO_CCIF_SHADOW3 0x038 -+#define MTK_WED_WO_CCIF_SHADOW4 0x03c -+#define MTK_WED_WO_CCIF_DUMMY5 0x050 -+#define MTK_WED_WO_CCIF_DUMMY6 0x054 -+#define MTK_WED_WO_CCIF_DUMMY7 0x058 -+#define MTK_WED_WO_CCIF_DUMMY8 0x05c -+#define MTK_WED_WO_CCIF_SHADOW5 0x060 -+#define MTK_WED_WO_CCIF_SHADOW6 0x064 -+#define MTK_WED_WO_CCIF_SHADOW7 0x068 -+#define MTK_WED_WO_CCIF_SHADOW8 0x06c -+ -+#define MTK_WED_WO_CTL_SD_LEN1 GENMASK(13, 0) -+#define MTK_WED_WO_CTL_LAST_SEC1 BIT(14) -+#define MTK_WED_WO_CTL_BURST BIT(15) -+#define MTK_WED_WO_CTL_SD_LEN0_SHIFT 16 -+#define MTK_WED_WO_CTL_SD_LEN0 GENMASK(29, 16) -+#define MTK_WED_WO_CTL_LAST_SEC0 BIT(30) -+#define MTK_WED_WO_CTL_DMA_DONE BIT(31) -+#define MTK_WED_WO_INFO_WINFO GENMASK(15, 0) -+ - struct mtk_wed_wo_memory_region { - const char *name; - void __iomem *addr; -@@ -112,10 +160,53 @@ struct mtk_wed_fw_trailer { - u32 crc; - }; - -+struct mtk_wed_wo_queue_regs { -+ u32 desc_base; -+ u32 ring_size; -+ u32 cpu_idx; -+ u32 dma_idx; -+}; -+ -+struct mtk_wed_wo_queue_desc { -+ __le32 buf0; -+ __le32 ctrl; -+ __le32 buf1; -+ __le32 info; -+ __le32 reserved[4]; -+} __packed __aligned(32); -+ -+struct mtk_wed_wo_queue_entry { -+ dma_addr_t addr; -+ void *buf; -+ u32 len; -+}; -+ -+struct mtk_wed_wo_queue { -+ struct mtk_wed_wo_queue_regs regs; -+ -+ struct page_frag_cache cache; -+ spinlock_t lock; -+ -+ struct mtk_wed_wo_queue_desc *desc; -+ dma_addr_t desc_dma; -+ -+ struct mtk_wed_wo_queue_entry *entry; -+ -+ u16 head; -+ u16 tail; -+ int n_desc; -+ int queued; -+ int buf_size; -+ -+}; -+ - struct mtk_wed_wo { - struct mtk_wed_hw *hw; - struct mtk_wed_wo_memory_region boot; - -+ struct mtk_wed_wo_queue q_tx; -+ struct mtk_wed_wo_queue q_rx; -+ - struct { - struct mutex mutex; - int timeout; -@@ -124,6 +215,15 @@ struct mtk_wed_wo { - struct sk_buff_head res_q; - wait_queue_head_t wait; - } mcu; -+ -+ struct { -+ struct regmap *regs; -+ -+ spinlock_t lock; -+ struct tasklet_struct irq_tasklet; -+ int irq; -+ u32 irq_mask; -+ } mmio; - }; - - static inline int -@@ -146,5 +246,9 @@ void mtk_wed_mcu_rx_unsolicited_event(st - int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, - const void *data, int len, bool wait_resp); - int mtk_wed_mcu_init(struct mtk_wed_wo *wo); -+int mtk_wed_wo_init(struct mtk_wed_hw *hw); -+void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); -+int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *dev, struct mtk_wed_wo_queue *q, -+ struct sk_buff *skb); - - #endif /* __MTK_WED_WO_H */ diff --git a/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch b/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch deleted file mode 100644 index a002a5f851..0000000000 --- a/target/linux/generic/backport-6.6/729-03-v6.1-net-ethernet-mtk_wed-rename-tx_wdma-array-in-rx_wdma.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:20 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: rename tx_wdma array in rx_wdma - -Rename tx_wdma queue array in rx_wdma since this is rx side of wdma soc. -Moreover rename mtk_wed_wdma_ring_setup routine in -mtk_wed_wdma_rx_ring_setup() - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -253,8 +253,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_dev - - for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) - mtk_wed_free_ring(dev, &dev->tx_ring[i]); -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) -- mtk_wed_free_ring(dev, &dev->tx_wdma[i]); -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) -+ mtk_wed_free_ring(dev, &dev->rx_wdma[i]); - } - - static void -@@ -688,10 +688,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device - } - - static int --mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; -+ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; - - if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) - return -ENOMEM; -@@ -805,9 +805,9 @@ mtk_wed_start(struct mtk_wed_device *dev - { - int i; - -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) -- if (!dev->tx_wdma[i].desc) -- mtk_wed_wdma_ring_setup(dev, i, 16); -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) -+ if (!dev->rx_wdma[i].desc) -+ mtk_wed_wdma_rx_ring_setup(dev, i, 16); - - mtk_wed_hw_init(dev); - mtk_wed_configure_irq(dev, irq_mask); -@@ -916,7 +916,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - sizeof(*ring->desc))) - return -ENOMEM; - -- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_TX(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -7,6 +7,7 @@ - #include - - #define MTK_WED_TX_QUEUES 2 -+#define MTK_WED_RX_QUEUES 2 - - struct mtk_wed_hw; - struct mtk_wdma_desc; -@@ -66,7 +67,7 @@ struct mtk_wed_device { - - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring txfree_ring; -- struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; -+ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; - - struct { - int size; diff --git a/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch b/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch deleted file mode 100644 index eca29739b4..0000000000 --- a/target/linux/generic/backport-6.6/729-04-v6.1-net-ethernet-mtk_wed-add-configure-wed-wo-support.patch +++ /dev/null @@ -1,1521 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:21 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add configure wed wo support - -Enable RX Wireless Ethernet Dispatch available on MT7986 Soc. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -23,6 +24,7 @@ - #define MTK_WED_PKT_SIZE 1900 - #define MTK_WED_BUF_SIZE 2048 - #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) -+#define MTK_WED_RX_RING_SIZE 1536 - - #define MTK_WED_TX_RING_SIZE 2048 - #define MTK_WED_WDMA_RING_SIZE 1024 -@@ -31,6 +33,10 @@ - #define MTK_WED_PER_GROUP_PKT 128 - - #define MTK_WED_FBUF_SIZE 128 -+#define MTK_WED_MIOD_CNT 16 -+#define MTK_WED_FB_CMD_CNT 1024 -+#define MTK_WED_RRO_QUE_CNT 8192 -+#define MTK_WED_MIOD_ENTRY_CNT 128 - - static struct mtk_wed_hw *hw_list[2]; - static DEFINE_MUTEX(hw_lock); -@@ -65,12 +71,76 @@ wdma_set(struct mtk_wed_device *dev, u32 - wdma_m32(dev, reg, 0, mask); - } - -+static void -+wdma_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) -+{ -+ wdma_m32(dev, reg, mask, 0); -+} -+ -+static u32 -+wifi_r32(struct mtk_wed_device *dev, u32 reg) -+{ -+ return readl(dev->wlan.base + reg); -+} -+ -+static void -+wifi_w32(struct mtk_wed_device *dev, u32 reg, u32 val) -+{ -+ writel(val, dev->wlan.base + reg); -+} -+ - static u32 - mtk_wed_read_reset(struct mtk_wed_device *dev) - { - return wed_r32(dev, MTK_WED_RESET); - } - -+static u32 -+mtk_wdma_read_reset(struct mtk_wed_device *dev) -+{ -+ return wdma_r32(dev, MTK_WDMA_GLO_CFG); -+} -+ -+static void -+mtk_wdma_rx_reset(struct mtk_wed_device *dev) -+{ -+ u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; -+ int i; -+ -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); -+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 1000)) -+ dev_err(dev->hw->dev, "rx reset failed\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { -+ if (dev->rx_wdma[i].desc) -+ continue; -+ -+ wdma_w32(dev, -+ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ } -+} -+ -+static void -+mtk_wdma_tx_reset(struct mtk_wed_device *dev) -+{ -+ u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; -+ int i; -+ -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 1000)) -+ dev_err(dev->hw->dev, "tx reset failed\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { -+ if (dev->tx_wdma[i].desc) -+ continue; -+ -+ wdma_w32(dev, -+ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ } -+} -+ - static void - mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) - { -@@ -82,6 +152,54 @@ mtk_wed_reset(struct mtk_wed_device *dev - WARN_ON_ONCE(1); - } - -+static u32 -+mtk_wed_wo_read_status(struct mtk_wed_device *dev) -+{ -+ return wed_r32(dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_WO_STATUS); -+} -+ -+static void -+mtk_wed_wo_reset(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ u8 state = MTK_WED_WO_STATE_DISABLE; -+ void __iomem *reg; -+ u32 val; -+ -+ mtk_wdma_tx_reset(dev); -+ mtk_wed_reset(dev, MTK_WED_RESET_WED); -+ -+ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &state, -+ sizeof(state), false); -+ -+ if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, -+ val == MTK_WED_WOIF_DISABLE_DONE, -+ 100, MTK_WOCPU_TIMEOUT)) -+ dev_err(dev->hw->dev, "failed to disable wed-wo\n"); -+ -+ reg = ioremap(MTK_WED_WO_CPU_MCUSYS_RESET_ADDR, 4); -+ -+ val = readl(reg); -+ switch (dev->hw->index) { -+ case 0: -+ val |= MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ val &= ~MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ break; -+ case 1: -+ val |= MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ val &= ~MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK; -+ writel(val, reg); -+ break; -+ default: -+ break; -+ } -+ iounmap(reg); -+} -+ - static struct mtk_wed_hw * - mtk_wed_assign(struct mtk_wed_device *dev) - { -@@ -116,7 +234,7 @@ out: - } - - static int --mtk_wed_buffer_alloc(struct mtk_wed_device *dev) -+mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) - { - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; -@@ -133,16 +251,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi - if (!page_list) - return -ENOMEM; - -- dev->buf_ring.size = ring_size; -- dev->buf_ring.pages = page_list; -+ dev->tx_buf_ring.size = ring_size; -+ dev->tx_buf_ring.pages = page_list; - - desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), - &desc_phys, GFP_KERNEL); - if (!desc) - return -ENOMEM; - -- dev->buf_ring.desc = desc; -- dev->buf_ring.desc_phys = desc_phys; -+ dev->tx_buf_ring.desc = desc; -+ dev->tx_buf_ring.desc_phys = desc_phys; - - for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { - dma_addr_t page_phys, buf_phys; -@@ -203,10 +321,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_devi - } - - static void --mtk_wed_free_buffer(struct mtk_wed_device *dev) -+mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) - { -- struct mtk_wdma_desc *desc = dev->buf_ring.desc; -- void **page_list = dev->buf_ring.pages; -+ struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; -+ void **page_list = dev->tx_buf_ring.pages; - int page_idx; - int i; - -@@ -216,7 +334,8 @@ mtk_wed_free_buffer(struct mtk_wed_devic - if (!desc) - goto free_pagelist; - -- for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { -+ for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; -+ i += MTK_WED_BUF_PER_PAGE) { - void *page = page_list[page_idx++]; - dma_addr_t buf_addr; - -@@ -229,13 +348,59 @@ mtk_wed_free_buffer(struct mtk_wed_devic - __free_page(page); - } - -- dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), -- desc, dev->buf_ring.desc_phys); -+ dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), -+ desc, dev->tx_buf_ring.desc_phys); - - free_pagelist: - kfree(page_list); - } - -+static int -+mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) -+{ -+ struct mtk_rxbm_desc *desc; -+ dma_addr_t desc_phys; -+ -+ dev->rx_buf_ring.size = dev->wlan.rx_nbuf; -+ desc = dma_alloc_coherent(dev->hw->dev, -+ dev->wlan.rx_nbuf * sizeof(*desc), -+ &desc_phys, GFP_KERNEL); -+ if (!desc) -+ return -ENOMEM; -+ -+ dev->rx_buf_ring.desc = desc; -+ dev->rx_buf_ring.desc_phys = desc_phys; -+ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); -+ -+ return 0; -+} -+ -+static void -+mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) -+{ -+ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; -+ -+ if (!desc) -+ return; -+ -+ dev->wlan.release_rx_buf(dev); -+ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), -+ desc, dev->rx_buf_ring.desc_phys); -+} -+ -+static void -+mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD, -+ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size)); -+ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys); -+ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL | -+ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt)); -+ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, -+ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+} -+ - static void - mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) - { -@@ -247,6 +412,13 @@ mtk_wed_free_ring(struct mtk_wed_device - } - - static void -+mtk_wed_free_rx_rings(struct mtk_wed_device *dev) -+{ -+ mtk_wed_free_rx_buffer(dev); -+ mtk_wed_free_ring(dev, &dev->rro.ring); -+} -+ -+static void - mtk_wed_free_tx_rings(struct mtk_wed_device *dev) - { - int i; -@@ -291,6 +463,38 @@ mtk_wed_set_512_support(struct mtk_wed_d - } - } - -+#define MTK_WFMDA_RX_DMA_EN BIT(2) -+static void -+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) -+{ -+ u32 val; -+ int i; -+ -+ if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) -+ return; /* queue is not configured by mt76 */ -+ -+ for (i = 0; i < 3; i++) { -+ u32 cur_idx; -+ -+ cur_idx = wed_r32(dev, -+ MTK_WED_WPDMA_RING_RX_DATA(idx) + -+ MTK_WED_RING_OFS_CPU_IDX); -+ if (cur_idx == MTK_WED_RX_RING_SIZE - 1) -+ break; -+ -+ usleep_range(100000, 200000); -+ } -+ -+ if (i == 3) { -+ dev_err(dev->hw->dev, "rx dma enable failed\n"); -+ return; -+ } -+ -+ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | -+ MTK_WFMDA_RX_DMA_EN; -+ wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); -+} -+ - static void - mtk_wed_dma_disable(struct mtk_wed_device *dev) - { -@@ -304,20 +508,25 @@ mtk_wed_dma_disable(struct mtk_wed_devic - MTK_WED_GLO_CFG_TX_DMA_EN | - MTK_WED_GLO_CFG_RX_DMA_EN); - -- wdma_m32(dev, MTK_WDMA_GLO_CFG, -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, - MTK_WDMA_GLO_CFG_TX_DMA_EN | - MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | -- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0); -+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); - - if (dev->hw->version == 1) { - regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); -- wdma_m32(dev, MTK_WDMA_GLO_CFG, -- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0); -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, -+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); - } else { - wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); - -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_EN); -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -+ - mtk_wed_set_512_support(dev, false); - } - } -@@ -338,6 +547,13 @@ mtk_wed_stop(struct mtk_wed_device *dev) - wdma_w32(dev, MTK_WDMA_INT_MASK, 0); - wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); - wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); -+ -+ if (dev->hw->version == 1) -+ return; -+ -+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); -+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); - } - - static void -@@ -353,11 +569,21 @@ mtk_wed_detach(struct mtk_wed_device *de - wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - - mtk_wed_reset(dev, MTK_WED_RESET_WED); -+ if (mtk_wed_get_rx_capa(dev)) { -+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -+ } - -- mtk_wed_free_buffer(dev); -+ mtk_wed_free_tx_buffer(dev); - mtk_wed_free_tx_rings(dev); -- if (hw->version != 1) -+ -+ if (mtk_wed_get_rx_capa(dev)) { -+ mtk_wed_wo_reset(dev); -+ mtk_wed_free_rx_rings(dev); - mtk_wed_wo_deinit(hw); -+ mtk_wdma_rx_reset(dev); -+ } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { - struct device_node *wlan_node; -@@ -434,10 +660,12 @@ mtk_wed_set_wpdma(struct mtk_wed_device - } else { - mtk_wed_bus_init(dev); - -- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); -- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); -- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); -- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); -+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); -+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); -+ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); - } - } - -@@ -487,6 +715,132 @@ mtk_wed_hw_init_early(struct mtk_wed_dev - } - } - -+static int -+mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, -+ int size) -+{ -+ ring->desc = dma_alloc_coherent(dev->hw->dev, -+ size * sizeof(*ring->desc), -+ &ring->desc_phys, GFP_KERNEL); -+ if (!ring->desc) -+ return -ENOMEM; -+ -+ ring->desc_size = sizeof(*ring->desc); -+ ring->size = size; -+ memset(ring->desc, 0, size); -+ -+ return 0; -+} -+ -+#define MTK_WED_MIOD_COUNT (MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT) -+static int -+mtk_wed_rro_alloc(struct mtk_wed_device *dev) -+{ -+ struct reserved_mem *rmem; -+ struct device_node *np; -+ int index; -+ -+ index = of_property_match_string(dev->hw->node, "memory-region-names", -+ "wo-dlm"); -+ if (index < 0) -+ return index; -+ -+ np = of_parse_phandle(dev->hw->node, "memory-region", index); -+ if (!np) -+ return -ENODEV; -+ -+ rmem = of_reserved_mem_lookup(np); -+ of_node_put(np); -+ -+ if (!rmem) -+ return -ENODEV; -+ -+ dev->rro.miod_phys = rmem->base; -+ dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; -+ -+ return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, -+ MTK_WED_RRO_QUE_CNT); -+} -+ -+static int -+mtk_wed_rro_cfg(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ struct { -+ struct { -+ __le32 base; -+ __le32 cnt; -+ __le32 unit; -+ } ring[2]; -+ __le32 wed; -+ u8 version; -+ } req = { -+ .ring[0] = { -+ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE), -+ .cnt = cpu_to_le32(MTK_WED_MIOD_CNT), -+ .unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT), -+ }, -+ .ring[1] = { -+ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE + -+ MTK_WED_MIOD_COUNT), -+ .cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT), -+ .unit = cpu_to_le32(4), -+ }, -+ }; -+ -+ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_WED_CFG, -+ &req, sizeof(req), true); -+} -+ -+static void -+mtk_wed_rro_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG, -+ FIELD_PREP(MTK_WED_RROQM_MIOD_MID_DW, 0x70 >> 2) | -+ FIELD_PREP(MTK_WED_RROQM_MIOD_MOD_DW, 0x10 >> 2) | -+ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW, -+ MTK_WED_MIOD_ENTRY_CNT >> 2)); -+ -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys); -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1, -+ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT)); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1, -+ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT)); -+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0); -+ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys); -+ -+ wed_set(dev, MTK_WED_RROQM_RST_IDX, -+ MTK_WED_RROQM_RST_IDX_MIOD | -+ MTK_WED_RROQM_RST_IDX_FDBK); -+ -+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); -+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL2, MTK_WED_MIOD_CNT - 1); -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); -+} -+ -+static void -+mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev) -+{ -+ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM); -+ -+ for (;;) { -+ usleep_range(100, 200); -+ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM)) -+ break; -+ } -+ -+ /* configure RX_ROUTE_QM */ -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); -+ wed_set(dev, MTK_WED_RTQM_GLO_CFG, -+ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); -+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); -+ /* enable RX_ROUTE_QM */ -+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); -+} -+ - static void - mtk_wed_hw_init(struct mtk_wed_device *dev) - { -@@ -498,11 +852,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d - wed_w32(dev, MTK_WED_TX_BM_CTRL, - MTK_WED_TX_BM_CTRL_PAUSE | - FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, -- dev->buf_ring.size / 128) | -+ dev->tx_buf_ring.size / 128) | - FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, - MTK_WED_TX_RING_SIZE / 256)); - -- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); -+ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); - - wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); - -@@ -529,9 +883,9 @@ mtk_wed_hw_init(struct mtk_wed_device *d - wed_w32(dev, MTK_WED_TX_TKID_CTRL, - MTK_WED_TX_TKID_CTRL_PAUSE | - FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM, -- dev->buf_ring.size / 128) | -+ dev->tx_buf_ring.size / 128) | - FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, -- dev->buf_ring.size / 128)); -+ dev->tx_buf_ring.size / 128)); - wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, - FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | - MTK_WED_TX_TKID_DYN_THR_HI); -@@ -539,18 +893,28 @@ mtk_wed_hw_init(struct mtk_wed_device *d - - mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); - -- if (dev->hw->version == 1) -+ if (dev->hw->version == 1) { - wed_set(dev, MTK_WED_CTRL, - MTK_WED_CTRL_WED_TX_BM_EN | - MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -- else -+ } else { - wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); -+ /* rx hw init */ -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, -+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | -+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); -+ -+ mtk_wed_rx_buffer_hw_init(dev); -+ mtk_wed_rro_hw_init(dev); -+ mtk_wed_route_qm_hw_init(dev); -+ } - - wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); - } - - static void --mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size) -+mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx) - { - void *head = (void *)ring->desc; - int i; -@@ -560,7 +924,10 @@ mtk_wed_ring_reset(struct mtk_wed_ring * - - desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size); - desc->buf0 = 0; -- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); -+ if (tx) -+ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); -+ else -+ desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST); - desc->buf1 = 0; - desc->info = 0; - } -@@ -616,7 +983,8 @@ mtk_wed_reset_dma(struct mtk_wed_device - if (!dev->tx_ring[i].desc) - continue; - -- mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE); -+ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE, -+ true); - } - - if (mtk_wed_poll_busy(dev)) -@@ -634,6 +1002,9 @@ mtk_wed_reset_dma(struct mtk_wed_device - wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); - wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - -+ if (mtk_wed_get_rx_capa(dev)) -+ mtk_wdma_rx_reset(dev); -+ - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); -@@ -668,12 +1039,11 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WPDMA_RESET_IDX_RX); - wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); - } -- - } - - static int - mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, -- int size, u32 desc_size) -+ int size, u32 desc_size, bool tx) - { - ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size, - &ring->desc_phys, GFP_KERNEL); -@@ -682,7 +1052,7 @@ mtk_wed_ring_alloc(struct mtk_wed_device - - ring->desc_size = desc_size; - ring->size = size; -- mtk_wed_ring_reset(ring, size); -+ mtk_wed_ring_reset(ring, size, tx); - - return 0; - } -@@ -691,9 +1061,14 @@ static int - mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx]; -+ struct mtk_wed_ring *wdma; - -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size)) -+ if (idx >= ARRAY_SIZE(dev->rx_wdma)) -+ return -EINVAL; -+ -+ wdma = &dev->rx_wdma[idx]; -+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -+ true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, -@@ -710,6 +1085,60 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - return 0; - } - -+static int -+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+{ -+ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; -+ struct mtk_wed_ring *wdma; -+ -+ if (idx >= ARRAY_SIZE(dev->tx_wdma)) -+ return -EINVAL; -+ -+ wdma = &dev->tx_wdma[idx]; -+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -+ true)) -+ return -ENOMEM; -+ -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, -+ wdma->desc_phys); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, -+ size); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); -+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); -+ -+ if (!idx) { -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, -+ wdma->desc_phys); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT, -+ size); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX, -+ 0); -+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX, -+ 0); -+ } -+ -+ return 0; -+} -+ -+static void -+mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb, -+ u32 reason, u32 hash) -+{ -+ struct mtk_eth *eth = dev->hw->eth; -+ struct ethhdr *eh; -+ -+ if (!skb) -+ return; -+ -+ if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -+ return; -+ -+ skb_set_mac_header(skb, 0); -+ eh = eth_hdr(skb); -+ skb->protocol = eh->h_proto; -+ mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash); -+} -+ - static void - mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask) - { -@@ -732,6 +1161,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev - - wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); - } else { -+ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, -+ GENMASK(1, 0)); - /* initail tx interrupt trigger */ - wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, - MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | -@@ -750,6 +1181,16 @@ mtk_wed_configure_irq(struct mtk_wed_dev - FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, - dev->wlan.txfree_tbit)); - -+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, -+ MTK_WED_WPDMA_INT_CTRL_RX0_EN | -+ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | -+ MTK_WED_WPDMA_INT_CTRL_RX1_EN | -+ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | -+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, -+ dev->wlan.rx_tbit[0]) | -+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, -+ dev->wlan.rx_tbit[1])); -+ - wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); - wed_set(dev, MTK_WED_WDMA_INT_CTRL, - FIELD_PREP(MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL, -@@ -787,9 +1228,15 @@ mtk_wed_dma_enable(struct mtk_wed_device - wdma_set(dev, MTK_WDMA_GLO_CFG, - MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); - } else { -+ int i; -+ - wed_set(dev, MTK_WED_WPDMA_CTRL, - MTK_WED_WPDMA_CTRL_SDL1_FIXED); - -+ wed_set(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | -+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -+ - wed_set(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); -@@ -797,6 +1244,15 @@ mtk_wed_dma_enable(struct mtk_wed_device - wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | - MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); -+ -+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_EN | -+ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | -+ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, -+ 0x2)); -+ -+ for (i = 0; i < MTK_WED_RX_QUEUES; i++) -+ mtk_wed_check_wfdma_rx_fill(dev, i); - } - } - -@@ -822,7 +1278,19 @@ mtk_wed_start(struct mtk_wed_device *dev - val |= BIT(0) | (BIT(1) * !!dev->hw->index); - regmap_write(dev->hw->mirror, dev->hw->index * 4, val); - } else { -- mtk_wed_set_512_support(dev, true); -+ /* driver set mid ready and only once */ -+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, -+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); -+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, -+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); -+ -+ wed_r32(dev, MTK_WED_EXT_INT_MASK1); -+ wed_r32(dev, MTK_WED_EXT_INT_MASK2); -+ -+ if (mtk_wed_rro_cfg(dev)) -+ return; -+ -+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); - } - - mtk_wed_dma_enable(dev); -@@ -856,7 +1324,7 @@ mtk_wed_attach(struct mtk_wed_device *de - if (!hw) { - module_put(THIS_MODULE); - ret = -ENODEV; -- goto out; -+ goto unlock; - } - - device = dev->wlan.bus_type == MTK_WED_BUS_PCIE -@@ -869,15 +1337,24 @@ mtk_wed_attach(struct mtk_wed_device *de - dev->dev = hw->dev; - dev->irq = hw->irq; - dev->wdma_idx = hw->index; -+ dev->version = hw->version; - - if (hw->eth->dma_dev == hw->eth->dev && - of_dma_is_coherent(hw->eth->dev->of_node)) - mtk_eth_set_dma_device(hw->eth, hw->dev); - -- ret = mtk_wed_buffer_alloc(dev); -- if (ret) { -- mtk_wed_detach(dev); -+ ret = mtk_wed_tx_buffer_alloc(dev); -+ if (ret) - goto out; -+ -+ if (mtk_wed_get_rx_capa(dev)) { -+ ret = mtk_wed_rx_buffer_alloc(dev); -+ if (ret) -+ goto out; -+ -+ ret = mtk_wed_rro_alloc(dev); -+ if (ret) -+ goto out; - } - - mtk_wed_hw_init_early(dev); -@@ -886,8 +1363,10 @@ mtk_wed_attach(struct mtk_wed_device *de - BIT(hw->index), 0); - else - ret = mtk_wed_wo_init(hw); -- - out: -+ if (ret) -+ mtk_wed_detach(dev); -+unlock: - mutex_unlock(&hw_lock); - - return ret; -@@ -910,10 +1389,11 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - * WDMA RX. - */ - -- BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring)); -+ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) -+ return -EINVAL; - - if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -- sizeof(*ring->desc))) -+ sizeof(*ring->desc), true)) - return -ENOMEM; - - if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -@@ -960,6 +1440,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed - return 0; - } - -+static int -+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+{ -+ struct mtk_wed_ring *ring = &dev->rx_ring[idx]; -+ -+ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) -+ return -EINVAL; -+ -+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -+ sizeof(*ring->desc), false)) -+ return -ENOMEM; -+ -+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ return -ENOMEM; -+ -+ ring->reg_base = MTK_WED_RING_RX_DATA(idx); -+ ring->wpdma = regs; -+ ring->flags |= MTK_WED_RING_CONFIGURED; -+ -+ /* WPDMA -> WED */ -+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); -+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_RX_RING_SIZE); -+ -+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_BASE, -+ ring->desc_phys); -+ wed_w32(dev, MTK_WED_WPDMA_RING_RX_DATA(idx) + MTK_WED_RING_OFS_COUNT, -+ MTK_WED_RX_RING_SIZE); -+ -+ return 0; -+} -+ - static u32 - mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) - { -@@ -1056,7 +1567,9 @@ void mtk_wed_add_hw(struct device_node * - static const struct mtk_wed_ops wed_ops = { - .attach = mtk_wed_attach, - .tx_ring_setup = mtk_wed_tx_ring_setup, -+ .rx_ring_setup = mtk_wed_rx_ring_setup, - .txfree_ring_setup = mtk_wed_txfree_ring_setup, -+ .msg_update = mtk_wed_mcu_msg_update, - .start = mtk_wed_start, - .stop = mtk_wed_stop, - .reset_dma = mtk_wed_reset_dma, -@@ -1065,6 +1578,7 @@ void mtk_wed_add_hw(struct device_node * - .irq_get = mtk_wed_irq_get, - .irq_set_mask = mtk_wed_irq_set_mask, - .detach = mtk_wed_detach, -+ .ppe_check = mtk_wed_ppe_check, - }; - struct device_node *eth_np = eth->dev->of_node; - struct platform_device *pdev; ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -87,6 +87,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, - } - - static inline u32 -+wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg) -+{ -+ if (!dev->rx_ring[ring].wpdma) -+ return 0; -+ -+ return readl(dev->rx_ring[ring].wpdma + reg); -+} -+ -+static inline void -+wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) -+{ -+ if (!dev->rx_ring[ring].wpdma) -+ return; -+ -+ writel(val, dev->rx_ring[ring].wpdma + reg); -+} -+ -+static inline u32 - wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) - { - if (!dev->txfree_ring.wpdma) -@@ -128,6 +146,7 @@ static inline int mtk_wed_flow_add(int i - static inline void mtk_wed_flow_remove(int index) - { - } -+ - #endif - - #ifdef CONFIG_DEBUG_FS ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "mtk_wed_regs.h" - #include "mtk_wed_wo.h" -@@ -60,24 +61,37 @@ void mtk_wed_mcu_rx_event(struct mtk_wed - wake_up(&wo->mcu.wait); - } - -+static void -+mtk_wed_update_rx_stats(struct mtk_wed_device *wed, struct sk_buff *skb) -+{ -+ u32 count = get_unaligned_le32(skb->data); -+ struct mtk_wed_wo_rx_stats *stats; -+ int i; -+ -+ if (count * sizeof(*stats) > skb->len - sizeof(u32)) -+ return; -+ -+ stats = (struct mtk_wed_wo_rx_stats *)(skb->data + sizeof(u32)); -+ for (i = 0 ; i < count ; i++) -+ wed->wlan.update_wo_rx_stats(wed, &stats[i]); -+} -+ - void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, - struct sk_buff *skb) - { - struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data; - -- switch (hdr->cmd) { -- case MTK_WED_WO_EVT_LOG_DUMP: { -- const char *msg = (const char *)(skb->data + sizeof(*hdr)); -+ skb_pull(skb, sizeof(*hdr)); - -- dev_notice(wo->hw->dev, "%s\n", msg); -+ switch (hdr->cmd) { -+ case MTK_WED_WO_EVT_LOG_DUMP: -+ dev_notice(wo->hw->dev, "%s\n", skb->data); - break; -- } - case MTK_WED_WO_EVT_PROFILING: { -- struct mtk_wed_wo_log_info *info; -- u32 count = (skb->len - sizeof(*hdr)) / sizeof(*info); -+ struct mtk_wed_wo_log_info *info = (void *)skb->data; -+ u32 count = skb->len / sizeof(*info); - int i; - -- info = (struct mtk_wed_wo_log_info *)(skb->data + sizeof(*hdr)); - for (i = 0 ; i < count ; i++) - dev_notice(wo->hw->dev, - "SN:%u latency: total=%u, rro:%u, mod:%u\n", -@@ -88,6 +102,7 @@ void mtk_wed_mcu_rx_unsolicited_event(st - break; - } - case MTK_WED_WO_EVT_RXCNT_INFO: -+ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); - break; - default: - break; -@@ -144,6 +159,8 @@ mtk_wed_mcu_parse_response(struct mtk_we - skb_pull(skb, sizeof(*hdr)); - switch (cmd) { - case MTK_WED_WO_CMD_RXCNT_INFO: -+ mtk_wed_update_rx_stats(wo->hw->wed_dev, skb); -+ break; - default: - break; - } -@@ -182,6 +199,18 @@ unlock: - return ret; - } - -+int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, -+ int len) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ -+ if (dev->hw->version == 1) -+ return 0; -+ -+ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, -+ true); -+} -+ - static int - mtk_wed_get_memory_region(struct mtk_wed_wo *wo, - struct mtk_wed_wo_memory_region *region) ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -4,6 +4,7 @@ - #ifndef __MTK_WED_REGS_H - #define __MTK_WED_REGS_H - -+#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8) - #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) - #define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0) - #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) -@@ -28,6 +29,8 @@ struct mtk_wdma_desc { - #define MTK_WED_RESET_WED_TX_DMA BIT(12) - #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) - #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) -+#define MTK_WED_RESET_RX_RRO_QM BIT(20) -+#define MTK_WED_RESET_RX_ROUTE_QM BIT(21) - #define MTK_WED_RESET_WED BIT(31) - - #define MTK_WED_CTRL 0x00c -@@ -39,8 +42,12 @@ struct mtk_wdma_desc { - #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) - #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) - #define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) --#define MTK_WED_CTRL_RESERVE_EN BIT(12) --#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) -+#define MTK_WED_CTRL_WED_RX_BM_EN BIT(12) -+#define MTK_WED_CTRL_WED_RX_BM_BUSY BIT(13) -+#define MTK_WED_CTRL_RX_RRO_QM_EN BIT(14) -+#define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) -+#define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) -+#define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) - #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) - #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) - #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) -@@ -62,6 +69,9 @@ struct mtk_wdma_desc { - #define MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR BIT(22) - #define MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR BIT(23) - #define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) -+#define MTK_WED_EXT_INT_STATUS_RX_DRV_GET_BM_DMAD_SKIP BIT(25) -+#define MTK_WED_EXT_INT_STATUS_WPDMA_RX_D_DRV_ERR BIT(26) -+#define MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY BIT(27) - #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ - MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ - MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ -@@ -71,6 +81,8 @@ struct mtk_wdma_desc { - MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR) - - #define MTK_WED_EXT_INT_MASK 0x028 -+#define MTK_WED_EXT_INT_MASK1 0x02c -+#define MTK_WED_EXT_INT_MASK2 0x030 - - #define MTK_WED_STATUS 0x060 - #define MTK_WED_STATUS_TX GENMASK(15, 8) -@@ -151,6 +163,7 @@ struct mtk_wdma_desc { - #define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) - - #define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) -+#define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) - - #define MTK_WED_SCR0 0x3c0 - #define MTK_WED_WPDMA_INT_TRIGGER 0x504 -@@ -213,6 +226,12 @@ struct mtk_wdma_desc { - #define MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG GENMASK(14, 10) - - #define MTK_WED_WPDMA_INT_CTRL_RX 0x534 -+#define MTK_WED_WPDMA_INT_CTRL_RX0_EN BIT(0) -+#define MTK_WED_WPDMA_INT_CTRL_RX0_CLR BIT(1) -+#define MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG GENMASK(6, 2) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_EN BIT(8) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_CLR BIT(9) -+#define MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG GENMASK(14, 10) - - #define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538 - #define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0) -@@ -242,11 +261,34 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) - #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) -+#define MTK_WED_WPDMA_RING_RX_DATA(_n) (0x730 + (_n) * 0x10) -+ -+#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c -+#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) -+#define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) -+#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) -+ -+#define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 -+#define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) -+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) -+ -+#define MTK_WED_WPDMA_RX_GLO_CFG 0x76c -+#define MTK_WED_WPDMA_RX_RING 0x770 -+ -+#define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c -+ -+#define MTK_WED_WDMA_RING_TX 0x800 -+ -+#define MTK_WED_WDMA_TX_MIB 0x810 -+ - #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) - #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) - - #define MTK_WED_WDMA_GLO_CFG 0xa04 - #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) -+#define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) - #define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) - #define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) - #define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) -@@ -291,6 +333,20 @@ struct mtk_wdma_desc { - #define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) - #define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) - -+#define MTK_WED_RX_BM_RX_DMAD 0xd80 -+#define MTK_WED_RX_BM_RX_DMAD_SDL0 GENMASK(13, 0) -+ -+#define MTK_WED_RX_BM_BASE 0xd84 -+#define MTK_WED_RX_BM_INIT_PTR 0xd88 -+#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0) -+#define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16) -+ -+#define MTK_WED_RX_PTR 0xd8c -+ -+#define MTK_WED_RX_BM_DYN_ALLOC_TH 0xdb4 -+#define MTK_WED_RX_BM_DYN_ALLOC_TH_H GENMASK(31, 16) -+#define MTK_WED_RX_BM_DYN_ALLOC_TH_L GENMASK(15, 0) -+ - #define MTK_WED_RING_OFS_BASE 0x00 - #define MTK_WED_RING_OFS_COUNT 0x04 - #define MTK_WED_RING_OFS_CPU_IDX 0x08 -@@ -301,7 +357,9 @@ struct mtk_wdma_desc { - - #define MTK_WDMA_GLO_CFG 0x204 - #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0) -+#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1) - #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2) -+#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3) - #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26) - #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27) - #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28) -@@ -330,4 +388,70 @@ struct mtk_wdma_desc { - /* DMA channel mapping */ - #define HIFSYS_DMA_AG_MAP 0x008 - -+#define MTK_WED_RTQM_GLO_CFG 0xb00 -+#define MTK_WED_RTQM_BUSY BIT(1) -+#define MTK_WED_RTQM_Q_RST BIT(2) -+#define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) -+#define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) -+ -+#define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) -+#define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) -+#define MTK_WED_RTQM_Q2N_MIB 0xb80 -+#define MTK_WED_RTQM_Q2H_MIB(_n) (0xb84 + (_n) * 0x4) -+ -+#define MTK_WED_RTQM_Q2B_MIB 0xb8c -+#define MTK_WED_RTQM_PFDBK_MIB 0xb90 -+ -+#define MTK_WED_RROQM_GLO_CFG 0xc04 -+#define MTK_WED_RROQM_RST_IDX 0xc08 -+#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) -+#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4) -+ -+#define MTK_WED_RROQM_MIOD_CTRL0 0xc40 -+#define MTK_WED_RROQM_MIOD_CTRL1 0xc44 -+#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0) -+ -+#define MTK_WED_RROQM_MIOD_CTRL2 0xc48 -+#define MTK_WED_RROQM_MIOD_CTRL3 0xc4c -+ -+#define MTK_WED_RROQM_FDBK_CTRL0 0xc50 -+#define MTK_WED_RROQM_FDBK_CTRL1 0xc54 -+#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0) -+ -+#define MTK_WED_RROQM_FDBK_CTRL2 0xc58 -+ -+#define MTK_WED_RROQ_BASE_L 0xc80 -+#define MTK_WED_RROQ_BASE_H 0xc84 -+ -+#define MTK_WED_RROQM_MIOD_CFG 0xc8c -+#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0) -+#define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8) -+#define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16) -+ -+#define MTK_WED_RROQM_MID_MIB 0xcc0 -+#define MTK_WED_RROQM_MOD_MIB 0xcc4 -+#define MTK_WED_RROQM_MOD_COHERENT_MIB 0xcc8 -+#define MTK_WED_RROQM_FDBK_MIB 0xcd0 -+#define MTK_WED_RROQM_FDBK_COHERENT_MIB 0xcd4 -+#define MTK_WED_RROQM_FDBK_IND_MIB 0xce0 -+#define MTK_WED_RROQM_FDBK_ENQ_MIB 0xce4 -+#define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8 -+#define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec -+ -+#define MTK_WED_RX_BM_RX_DMAD 0xd80 -+#define MTK_WED_RX_BM_BASE 0xd84 -+#define MTK_WED_RX_BM_INIT_PTR 0xd88 -+#define MTK_WED_RX_BM_PTR 0xd8c -+#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16) -+#define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0) -+ -+#define MTK_WED_RX_BM_BLEN 0xd90 -+#define MTK_WED_RX_BM_STS 0xd94 -+#define MTK_WED_RX_BM_INTF2 0xd98 -+#define MTK_WED_RX_BM_INTF 0xd9c -+#define MTK_WED_RX_BM_ERR_STS 0xda8 -+ -+#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 -+#define MTK_WED_PCIE_INT_MASK 0x0 -+ - #endif ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -49,6 +49,10 @@ enum { - MTK_WED_WARP_CMD_FLAG_FROM_TO_WO = BIT(2), - }; - -+#define MTK_WED_WO_CPU_MCUSYS_RESET_ADDR 0x15194050 -+#define MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK 0x20 -+#define MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK 0x1 -+ - enum { - MTK_WED_WO_REGION_EMI, - MTK_WED_WO_REGION_ILM, -@@ -57,6 +61,28 @@ enum { - __MTK_WED_WO_REGION_MAX, - }; - -+enum mtk_wed_wo_state { -+ MTK_WED_WO_STATE_UNDEFINED, -+ MTK_WED_WO_STATE_INIT, -+ MTK_WED_WO_STATE_ENABLE, -+ MTK_WED_WO_STATE_DISABLE, -+ MTK_WED_WO_STATE_HALT, -+ MTK_WED_WO_STATE_GATING, -+ MTK_WED_WO_STATE_SER_RESET, -+ MTK_WED_WO_STATE_WF_RESET, -+}; -+ -+enum mtk_wed_wo_done_state { -+ MTK_WED_WOIF_UNDEFINED, -+ MTK_WED_WOIF_DISABLE_DONE, -+ MTK_WED_WOIF_TRIGGER_ENABLE, -+ MTK_WED_WOIF_ENABLE_DONE, -+ MTK_WED_WOIF_TRIGGER_GATING, -+ MTK_WED_WOIF_GATING_DONE, -+ MTK_WED_WOIF_TRIGGER_HALT, -+ MTK_WED_WOIF_HALT_DONE, -+}; -+ - enum mtk_wed_dummy_cr_idx { - MTK_WED_DUMMY_CR_FWDL, - MTK_WED_DUMMY_CR_WO_STATUS, -@@ -245,6 +271,8 @@ void mtk_wed_mcu_rx_unsolicited_event(st - struct sk_buff *skb); - int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd, - const void *data, int len, bool wait_resp); -+int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, -+ int len); - int mtk_wed_mcu_init(struct mtk_wed_wo *wo); - int mtk_wed_wo_init(struct mtk_wed_hw *hw); - void mtk_wed_wo_deinit(struct mtk_wed_hw *hw); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -5,10 +5,13 @@ - #include - #include - #include -+#include - - #define MTK_WED_TX_QUEUES 2 - #define MTK_WED_RX_QUEUES 2 - -+#define WED_WO_STA_REC 0x6 -+ - struct mtk_wed_hw; - struct mtk_wdma_desc; - -@@ -41,21 +44,37 @@ enum mtk_wed_wo_cmd { - MTK_WED_WO_CMD_WED_END - }; - -+struct mtk_rxbm_desc { -+ __le32 buf0; -+ __le32 token; -+} __packed __aligned(4); -+ - enum mtk_wed_bus_tye { - MTK_WED_BUS_PCIE, - MTK_WED_BUS_AXI, - }; - -+#define MTK_WED_RING_CONFIGURED BIT(0) - struct mtk_wed_ring { - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; - u32 desc_size; - int size; -+ u32 flags; - - u32 reg_base; - void __iomem *wpdma; - }; - -+struct mtk_wed_wo_rx_stats { -+ __le16 wlan_idx; -+ __le16 tid; -+ __le32 rx_pkt_cnt; -+ __le32 rx_byte_cnt; -+ __le32 rx_err_cnt; -+ __le32 rx_drop_cnt; -+}; -+ - struct mtk_wed_device { - #ifdef CONFIG_NET_MEDIATEK_SOC_WED - const struct mtk_wed_ops *ops; -@@ -64,9 +83,12 @@ struct mtk_wed_device { - bool init_done, running; - int wdma_idx; - int irq; -+ u8 version; - - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; -+ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; - struct mtk_wed_ring txfree_ring; -+ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; - - struct { -@@ -74,7 +96,20 @@ struct mtk_wed_device { - void **pages; - struct mtk_wdma_desc *desc; - dma_addr_t desc_phys; -- } buf_ring; -+ } tx_buf_ring; -+ -+ struct { -+ int size; -+ struct page_frag_cache rx_page; -+ struct mtk_rxbm_desc *desc; -+ dma_addr_t desc_phys; -+ } rx_buf_ring; -+ -+ struct { -+ struct mtk_wed_ring ring; -+ dma_addr_t miod_phys; -+ dma_addr_t fdbk_phys; -+ } rro; - - /* filled by driver: */ - struct { -@@ -83,22 +118,36 @@ struct mtk_wed_device { - struct pci_dev *pci_dev; - }; - enum mtk_wed_bus_tye bus_type; -+ void __iomem *base; -+ u32 phy_base; - - u32 wpdma_phys; - u32 wpdma_int; - u32 wpdma_mask; - u32 wpdma_tx; - u32 wpdma_txfree; -+ u32 wpdma_rx_glo; -+ u32 wpdma_rx; -+ -+ bool wcid_512; - - u16 token_start; - unsigned int nbuf; -+ unsigned int rx_nbuf; -+ unsigned int rx_npkt; -+ unsigned int rx_size; - - u8 tx_tbit[MTK_WED_TX_QUEUES]; -+ u8 rx_tbit[MTK_WED_RX_QUEUES]; - u8 txfree_tbit; - - u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); - int (*offload_enable)(struct mtk_wed_device *wed); - void (*offload_disable)(struct mtk_wed_device *wed); -+ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size); -+ void (*release_rx_buf)(struct mtk_wed_device *wed); -+ void (*update_wo_rx_stats)(struct mtk_wed_device *wed, -+ struct mtk_wed_wo_rx_stats *stats); - } wlan; - #endif - }; -@@ -107,9 +156,15 @@ struct mtk_wed_ops { - int (*attach)(struct mtk_wed_device *dev); - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs); -+ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, -+ void __iomem *regs); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, - void __iomem *regs); -+ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, -+ void *data, int len); - void (*detach)(struct mtk_wed_device *dev); -+ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb, -+ u32 reason, u32 hash); - - void (*stop)(struct mtk_wed_device *dev); - void (*start)(struct mtk_wed_device *dev, u32 irq_mask); -@@ -144,6 +199,16 @@ mtk_wed_device_attach(struct mtk_wed_dev - return ret; - } - -+static inline bool -+mtk_wed_get_rx_capa(struct mtk_wed_device *dev) -+{ -+#ifdef CONFIG_NET_MEDIATEK_SOC_WED -+ return dev->version != 1; -+#else -+ return false; -+#endif -+} -+ - #ifdef CONFIG_NET_MEDIATEK_SOC_WED - #define mtk_wed_device_active(_dev) !!(_dev)->ops - #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) -@@ -160,6 +225,12 @@ mtk_wed_device_attach(struct mtk_wed_dev - (_dev)->ops->irq_get(_dev, _mask) - #define mtk_wed_device_irq_set_mask(_dev, _mask) \ - (_dev)->ops->irq_set_mask(_dev, _mask) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ -+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ -+ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) -+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ -+ (_dev)->ops->msg_update(_dev, _id, _msg, _len) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -173,6 +244,9 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) - #define mtk_wed_device_irq_get(_dev, _mask) 0 - #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) -+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch b/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch deleted file mode 100644 index bb1066dece..0000000000 --- a/target/linux/generic/backport-6.6/729-05-v6.1-net-ethernet-mtk_wed-add-rx-mib-counters.patch +++ /dev/null @@ -1,149 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:22 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add rx mib counters - -Introduce WED RX MIB counters support available on MT7986a SoC. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -2,6 +2,7 @@ - /* Copyright (C) 2021 Felix Fietkau */ - - #include -+#include - #include "mtk_wed.h" - #include "mtk_wed_regs.h" - -@@ -18,6 +19,8 @@ enum { - DUMP_TYPE_WDMA, - DUMP_TYPE_WPDMA_TX, - DUMP_TYPE_WPDMA_TXFREE, -+ DUMP_TYPE_WPDMA_RX, -+ DUMP_TYPE_WED_RRO, - }; - - #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } -@@ -36,6 +39,9 @@ enum { - - #define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) - #define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) -+#define DUMP_WPDMA_RX_RING(_n) DUMP_RING("WPDMA_RX" #_n, 0, DUMP_TYPE_WPDMA_RX, _n) -+#define DUMP_WED_RRO_RING(_base)DUMP_RING("WED_RRO_MIOD", MTK_##_base, DUMP_TYPE_WED_RRO) -+#define DUMP_WED_RRO_FDBK(_base)DUMP_RING("WED_RRO_FDBK", MTK_##_base, DUMP_TYPE_WED_RRO) - - static void - print_reg_val(struct seq_file *s, const char *name, u32 val) -@@ -57,6 +63,7 @@ dump_wed_regs(struct seq_file *s, struct - cur > regs ? "\n" : "", - cur->name); - continue; -+ case DUMP_TYPE_WED_RRO: - case DUMP_TYPE_WED: - val = wed_r32(dev, cur->offset); - break; -@@ -69,6 +76,9 @@ dump_wed_regs(struct seq_file *s, struct - case DUMP_TYPE_WPDMA_TXFREE: - val = wpdma_txfree_r32(dev, cur->offset); - break; -+ case DUMP_TYPE_WPDMA_RX: -+ val = wpdma_rx_r32(dev, cur->base, cur->offset); -+ break; - } - print_reg_val(s, cur->name, val); - } -@@ -132,6 +142,80 @@ wed_txinfo_show(struct seq_file *s, void - } - DEFINE_SHOW_ATTRIBUTE(wed_txinfo); - -+static int -+wed_rxinfo_show(struct seq_file *s, void *data) -+{ -+ static const struct reg_dump regs[] = { -+ DUMP_STR("WPDMA RX"), -+ DUMP_WPDMA_RX_RING(0), -+ DUMP_WPDMA_RX_RING(1), -+ -+ DUMP_STR("WPDMA RX"), -+ DUMP_WED(WED_WPDMA_RX_D_MIB(0)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(0)), -+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(0)), -+ DUMP_WED(WED_WPDMA_RX_D_MIB(1)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX_DATA(1)), -+ DUMP_WED(WED_WPDMA_RX_D_PROCESSED_MIB(1)), -+ DUMP_WED(WED_WPDMA_RX_D_COHERENT_MIB), -+ -+ DUMP_STR("WED RX"), -+ DUMP_WED_RING(WED_RING_RX_DATA(0)), -+ DUMP_WED_RING(WED_RING_RX_DATA(1)), -+ -+ DUMP_STR("WED RRO"), -+ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), -+ DUMP_WED(WED_RROQM_MID_MIB), -+ DUMP_WED(WED_RROQM_MOD_MIB), -+ DUMP_WED(WED_RROQM_MOD_COHERENT_MIB), -+ DUMP_WED_RRO_FDBK(WED_RROQM_FDBK_CTRL0), -+ DUMP_WED(WED_RROQM_FDBK_IND_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ENQ_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ANC_MIB), -+ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), -+ -+ DUMP_STR("WED Route QM"), -+ DUMP_WED(WED_RTQM_R2H_MIB(0)), -+ DUMP_WED(WED_RTQM_R2Q_MIB(0)), -+ DUMP_WED(WED_RTQM_Q2H_MIB(0)), -+ DUMP_WED(WED_RTQM_R2H_MIB(1)), -+ DUMP_WED(WED_RTQM_R2Q_MIB(1)), -+ DUMP_WED(WED_RTQM_Q2H_MIB(1)), -+ DUMP_WED(WED_RTQM_Q2N_MIB), -+ DUMP_WED(WED_RTQM_Q2B_MIB), -+ DUMP_WED(WED_RTQM_PFDBK_MIB), -+ -+ DUMP_STR("WED WDMA TX"), -+ DUMP_WED(WED_WDMA_TX_MIB), -+ DUMP_WED_RING(WED_WDMA_RING_TX), -+ -+ DUMP_STR("WDMA TX"), -+ DUMP_WDMA(WDMA_GLO_CFG), -+ DUMP_WDMA_RING(WDMA_RING_TX(0)), -+ DUMP_WDMA_RING(WDMA_RING_TX(1)), -+ -+ DUMP_STR("WED RX BM"), -+ DUMP_WED(WED_RX_BM_BASE), -+ DUMP_WED(WED_RX_BM_RX_DMAD), -+ DUMP_WED(WED_RX_BM_PTR), -+ DUMP_WED(WED_RX_BM_TKID_MIB), -+ DUMP_WED(WED_RX_BM_BLEN), -+ DUMP_WED(WED_RX_BM_STS), -+ DUMP_WED(WED_RX_BM_INTF2), -+ DUMP_WED(WED_RX_BM_INTF), -+ DUMP_WED(WED_RX_BM_ERR_STS), -+ }; -+ struct mtk_wed_hw *hw = s->private; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ -+ if (!dev) -+ return 0; -+ -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ -+ return 0; -+} -+DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); - - static int - mtk_wed_reg_set(void *data, u64 val) -@@ -175,4 +259,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w - debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); - debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); - debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); -+ if (hw->version != 1) -+ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, -+ &wed_rxinfo_fops); - } diff --git a/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch b/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch deleted file mode 100644 index cefe1eefff..0000000000 --- a/target/linux/generic/backport-6.6/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 17 Nov 2022 00:58:46 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: remove cpu_relax in - mtk_pending_work - -Get rid of cpu_relax in mtk_pending_work routine since MTK_RESETTING is -set only in mtk_pending_work() and it runs holding rtnl lock - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3480,11 +3480,8 @@ static void mtk_pending_work(struct work - rtnl_lock(); - - dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); -+ set_bit(MTK_RESETTING, ð->state); - -- while (test_and_set_bit_lock(MTK_RESETTING, ð->state)) -- cpu_relax(); -- -- dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__); - /* stop all devices to make sure that dma is properly shut down */ - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!eth->netdev[i]) -@@ -3518,7 +3515,7 @@ static void mtk_pending_work(struct work - - dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); - -- clear_bit_unlock(MTK_RESETTING, ð->state); -+ clear_bit(MTK_RESETTING, ð->state); - - rtnl_unlock(); - } diff --git a/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch b/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch deleted file mode 100644 index 117ccc0902..0000000000 --- a/target/linux/generic/backport-6.6/729-09-v6.2-net-ethernet-mtk_wed-add-wcid-overwritten-support-fo.patch +++ /dev/null @@ -1,80 +0,0 @@ -From: Sujuan Chen -Date: Thu, 24 Nov 2022 11:18:14 +0800 -Subject: [PATCH] net: ethernet: mtk_wed: add wcid overwritten support for wed - v1 - -All wed versions should enable the wcid overwritten feature, -since the wcid size is controlled by the wlan driver. - -Tested-by: Sujuan Chen -Co-developed-by: Bo Jiao -Signed-off-by: Bo Jiao -Signed-off-by: Sujuan Chen -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -526,9 +526,9 @@ mtk_wed_dma_disable(struct mtk_wed_devic - MTK_WED_WPDMA_RX_D_RX_DRV_EN); - wed_clr(dev, MTK_WED_WDMA_GLO_CFG, - MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); -- -- mtk_wed_set_512_support(dev, false); - } -+ -+ mtk_wed_set_512_support(dev, false); - } - - static void -@@ -1290,9 +1290,10 @@ mtk_wed_start(struct mtk_wed_device *dev - if (mtk_wed_rro_cfg(dev)) - return; - -- mtk_wed_set_512_support(dev, dev->wlan.wcid_512); - } - -+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512); -+ - mtk_wed_dma_enable(dev); - dev->running = true; - } -@@ -1358,11 +1359,13 @@ mtk_wed_attach(struct mtk_wed_device *de - } - - mtk_wed_hw_init_early(dev); -- if (hw->version == 1) -+ if (hw->version == 1) { - regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, - BIT(hw->index), 0); -- else -+ } else { -+ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID); - ret = mtk_wed_wo_init(hw); -+ } - out: - if (ret) - mtk_wed_detach(dev); ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -20,6 +20,8 @@ struct mtk_wdma_desc { - __le32 info; - } __packed __aligned(4); - -+#define MTK_WED_REV_ID 0x004 -+ - #define MTK_WED_RESET 0x008 - #define MTK_WED_RESET_TX_BM BIT(0) - #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -85,6 +85,9 @@ struct mtk_wed_device { - int irq; - u8 version; - -+ /* used by wlan driver */ -+ u32 rev_id; -+ - struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; - struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES]; - struct mtk_wed_ring txfree_ring; diff --git a/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch b/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch deleted file mode 100644 index ec58c3fc57..0000000000 --- a/target/linux/generic/backport-6.6/729-10-v6.2-net-ethernet-mtk_wed-return-status-value-in-mtk_wdma.patch +++ /dev/null @@ -1,85 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:51 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: return status value in - mtk_wdma_rx_reset - -Move MTK_WDMA_RESET_IDX configuration in mtk_wdma_rx_reset routine. -Increase poll timeout to 10ms in order to be aligned with vendor sdk. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -101,17 +101,21 @@ mtk_wdma_read_reset(struct mtk_wed_devic - return wdma_r32(dev, MTK_WDMA_GLO_CFG); - } - --static void -+static int - mtk_wdma_rx_reset(struct mtk_wed_device *dev) - { - u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY; -- int i; -+ int i, ret; - - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN); -- if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -- !(status & mask), 0, 1000)) -+ ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status, -+ !(status & mask), 0, 10000); -+ if (ret) - dev_err(dev->hw->dev, "rx reset failed\n"); - -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -+ - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) { - if (dev->rx_wdma[i].desc) - continue; -@@ -119,6 +123,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device - wdma_w32(dev, - MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); - } -+ -+ return ret; - } - - static void -@@ -565,9 +571,7 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wed_stop(dev); - -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- -+ mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - if (mtk_wed_get_rx_capa(dev)) { - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -@@ -582,7 +586,6 @@ mtk_wed_detach(struct mtk_wed_device *de - mtk_wed_wo_reset(dev); - mtk_wed_free_rx_rings(dev); - mtk_wed_wo_deinit(hw); -- mtk_wdma_rx_reset(dev); - } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { -@@ -999,11 +1002,7 @@ mtk_wed_reset_dma(struct mtk_wed_device - wed_w32(dev, MTK_WED_RESET_IDX, 0); - } - -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- -- if (mtk_wed_get_rx_capa(dev)) -- mtk_wdma_rx_reset(dev); -+ mtk_wdma_rx_reset(dev); - - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); diff --git a/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch b/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch deleted file mode 100644 index 10c1732c96..0000000000 --- a/target/linux/generic/backport-6.6/729-11-v6.2-net-ethernet-mtk_wed-move-MTK_WDMA_RESET_IDX_TX-conf.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:52 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: move MTK_WDMA_RESET_IDX_TX - configuration in mtk_wdma_tx_reset - -Remove duplicated code. Increase poll timeout to 10ms in order to be -aligned with vendor sdk. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -135,16 +135,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device - - wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); - if (readx_poll_timeout(mtk_wdma_read_reset, dev, status, -- !(status & mask), 0, 1000)) -+ !(status & mask), 0, 10000)) - dev_err(dev->hw->dev, "tx reset failed\n"); - -- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) { -- if (dev->tx_wdma[i].desc) -- continue; -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); - -+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) - wdma_w32(dev, - MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0); -- } - } - - static void -@@ -573,12 +572,6 @@ mtk_wed_detach(struct mtk_wed_device *de - - mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); -- if (mtk_wed_get_rx_capa(dev)) { -- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); -- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -- } -- - mtk_wed_free_tx_buffer(dev); - mtk_wed_free_tx_rings(dev); - diff --git a/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch b/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch deleted file mode 100644 index f4e842d515..0000000000 --- a/target/linux/generic/backport-6.6/729-12-v6.2-net-ethernet-mtk_wed-update-mtk_wed_stop.patch +++ /dev/null @@ -1,98 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:53 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: update mtk_wed_stop - -Update mtk_wed_stop routine and rename old mtk_wed_stop() to -mtk_wed_deinit(). This is a preliminary patch to add Wireless Ethernet -Dispatcher reset support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -539,14 +539,8 @@ mtk_wed_dma_disable(struct mtk_wed_devic - static void - mtk_wed_stop(struct mtk_wed_device *dev) - { -- mtk_wed_dma_disable(dev); - mtk_wed_set_ext_int(dev, false); - -- wed_clr(dev, MTK_WED_CTRL, -- MTK_WED_CTRL_WDMA_INT_AGENT_EN | -- MTK_WED_CTRL_WPDMA_INT_AGENT_EN | -- MTK_WED_CTRL_WED_TX_BM_EN | -- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); - wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); - wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); - wdma_w32(dev, MTK_WDMA_INT_MASK, 0); -@@ -558,7 +552,27 @@ mtk_wed_stop(struct mtk_wed_device *dev) - - wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); - wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0); -- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+} -+ -+static void -+mtk_wed_deinit(struct mtk_wed_device *dev) -+{ -+ mtk_wed_stop(dev); -+ mtk_wed_dma_disable(dev); -+ -+ wed_clr(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WDMA_INT_AGENT_EN | -+ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | -+ MTK_WED_CTRL_WED_TX_BM_EN | -+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -+ -+ if (dev->hw->version == 1) -+ return; -+ -+ wed_clr(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_ROUTE_QM_EN | -+ MTK_WED_CTRL_WED_RX_BM_EN | -+ MTK_WED_CTRL_RX_RRO_QM_EN); - } - - static void -@@ -568,7 +582,7 @@ mtk_wed_detach(struct mtk_wed_device *de - - mutex_lock(&hw_lock); - -- mtk_wed_stop(dev); -+ mtk_wed_deinit(dev); - - mtk_wdma_rx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); -@@ -670,7 +684,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev - { - u32 mask, set; - -- mtk_wed_stop(dev); -+ mtk_wed_deinit(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - mtk_wed_set_wpdma(dev); - ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -234,6 +234,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ - (_dev)->ops->msg_update(_dev, _id, _msg, _len) -+#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) -+#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -250,6 +252,8 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV -+#define mtk_wed_device_stop(_dev) do {} while (0) -+#define mtk_wed_device_dma_reset(_dev) do {} while (0) - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch b/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch deleted file mode 100644 index a0fc9da99e..0000000000 --- a/target/linux/generic/backport-6.6/729-13-v6.2-net-ethernet-mtk_wed-add-mtk_wed_rx_reset-routine.patch +++ /dev/null @@ -1,309 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:54 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add mtk_wed_rx_reset routine - -Introduce mtk_wed_rx_reset routine in order to reset rx DMA for Wireless -Ethernet Dispatcher available on MT7986 SoC. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -944,42 +944,130 @@ mtk_wed_ring_reset(struct mtk_wed_ring * - } - - static u32 --mtk_wed_check_busy(struct mtk_wed_device *dev) -+mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) - { -- if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) & -- MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) & -- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) -- return true; -- -- if (wdma_r32(dev, MTK_WDMA_GLO_CFG) & -- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) -- return true; -- -- if (wed_r32(dev, MTK_WED_CTRL) & -- (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY)) -- return true; -- -- return false; -+ return !!(wed_r32(dev, reg) & mask); - } - - static int --mtk_wed_poll_busy(struct mtk_wed_device *dev) -+mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) - { - int sleep = 15000; - int timeout = 100 * sleep; - u32 val; - - return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, -- timeout, false, dev); -+ timeout, false, dev, reg, mask); -+} -+ -+static int -+mtk_wed_rx_reset(struct mtk_wed_device *dev) -+{ -+ struct mtk_wed_wo *wo = dev->hw->wed_wo; -+ u8 val = MTK_WED_WO_STATE_SER_RESET; -+ int i, ret; -+ -+ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &val, -+ sizeof(val), true); -+ if (ret) -+ return ret; -+ -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); -+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV); -+ } else { -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, -+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | -+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); -+ -+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | -+ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); -+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, -+ MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE | -+ MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE); -+ -+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); -+ } -+ -+ /* reset rro qm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_RRO_QM_BUSY); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM); -+ } else { -+ wed_set(dev, MTK_WED_RROQM_RST_IDX, -+ MTK_WED_RROQM_RST_IDX_MIOD | -+ MTK_WED_RROQM_RST_IDX_FDBK); -+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); -+ } -+ -+ /* reset route qm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); -+ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_RX_ROUTE_QM_BUSY); -+ if (ret) -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); -+ else -+ wed_set(dev, MTK_WED_RTQM_GLO_CFG, -+ MTK_WED_RTQM_Q_RST); -+ -+ /* reset tx wdma */ -+ mtk_wdma_tx_reset(dev); -+ -+ /* reset tx wdma drv */ -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN); -+ mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); -+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); -+ -+ /* reset wed rx dma */ -+ ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, -+ MTK_WED_GLO_CFG_RX_DMA_BUSY); -+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN); -+ if (ret) { -+ mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); -+ } else { -+ struct mtk_eth *eth = dev->hw->eth; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ wed_set(dev, MTK_WED_RESET_IDX, -+ MTK_WED_RESET_IDX_RX_V2); -+ else -+ wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, 0); -+ } -+ -+ /* reset rx bm */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); -+ mtk_wed_poll_busy(dev, MTK_WED_CTRL, -+ MTK_WED_CTRL_WED_RX_BM_BUSY); -+ mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); -+ -+ /* wo change to enable state */ -+ val = MTK_WED_WO_STATE_ENABLE; -+ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &val, -+ sizeof(val), true); -+ if (ret) -+ return ret; -+ -+ /* wed_rx_ring_reset */ -+ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) { -+ if (!dev->rx_ring[i].desc) -+ continue; -+ -+ mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE, -+ false); -+ } -+ mtk_wed_free_rx_buffer(dev); -+ -+ return 0; - } - - static void -@@ -997,19 +1085,23 @@ mtk_wed_reset_dma(struct mtk_wed_device - true); - } - -- if (mtk_wed_poll_busy(dev)) -- busy = mtk_wed_check_busy(dev); -- -+ /* 1. reset WED tx DMA */ -+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN); -+ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, -+ MTK_WED_GLO_CFG_TX_DMA_BUSY); - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); - } else { -- wed_w32(dev, MTK_WED_RESET_IDX, -- MTK_WED_RESET_IDX_TX | -- MTK_WED_RESET_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX); - wed_w32(dev, MTK_WED_RESET_IDX, 0); - } - -- mtk_wdma_rx_reset(dev); -+ /* 2. reset WDMA rx DMA */ -+ busy = !!mtk_wdma_rx_reset(dev); -+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); -+ if (!busy) -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG, -+ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY); - - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); -@@ -1026,6 +1118,9 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); - } - -+ /* 3. reset WED WPDMA tx */ -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -+ - for (i = 0; i < 100; i++) { - val = wed_r32(dev, MTK_WED_TX_BM_INTF); - if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) -@@ -1033,8 +1128,19 @@ mtk_wed_reset_dma(struct mtk_wed_device - } - - mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT); -+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN); - mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); - -+ /* 4. reset WED WPDMA tx */ -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY); -+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | -+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); -+ if (!busy) -+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY); -+ - if (busy) { - mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); - mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); -@@ -1045,6 +1151,17 @@ mtk_wed_reset_dma(struct mtk_wed_device - MTK_WED_WPDMA_RESET_IDX_RX); - wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); - } -+ -+ dev->init_done = false; -+ if (dev->hw->version == 1) -+ return; -+ -+ if (!busy) { -+ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX); -+ wed_w32(dev, MTK_WED_RESET_IDX, 0); -+ } -+ -+ mtk_wed_rx_reset(dev); - } - - static int -@@ -1267,6 +1384,9 @@ mtk_wed_start(struct mtk_wed_device *dev - { - int i; - -+ if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev)) -+ return; -+ - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) - if (!dev->rx_wdma[i].desc) - mtk_wed_wdma_rx_ring_setup(dev, i, 16); -@@ -1355,10 +1475,6 @@ mtk_wed_attach(struct mtk_wed_device *de - goto out; - - if (mtk_wed_get_rx_capa(dev)) { -- ret = mtk_wed_rx_buffer_alloc(dev); -- if (ret) -- goto out; -- - ret = mtk_wed_rro_alloc(dev); - if (ret) - goto out; ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -24,11 +24,15 @@ struct mtk_wdma_desc { - - #define MTK_WED_RESET 0x008 - #define MTK_WED_RESET_TX_BM BIT(0) -+#define MTK_WED_RESET_RX_BM BIT(1) - #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) - #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) - #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) -+#define MTK_WED_RESET_WPDMA_RX_D_DRV BIT(10) - #define MTK_WED_RESET_WPDMA_INT_AGENT BIT(11) - #define MTK_WED_RESET_WED_TX_DMA BIT(12) -+#define MTK_WED_RESET_WED_RX_DMA BIT(13) -+#define MTK_WED_RESET_WDMA_TX_DRV BIT(16) - #define MTK_WED_RESET_WDMA_RX_DRV BIT(17) - #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) - #define MTK_WED_RESET_RX_RRO_QM BIT(20) -@@ -158,6 +162,8 @@ struct mtk_wdma_desc { - #define MTK_WED_RESET_IDX 0x20c - #define MTK_WED_RESET_IDX_TX GENMASK(3, 0) - #define MTK_WED_RESET_IDX_RX GENMASK(17, 16) -+#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6) -+#define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30) - - #define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) - #define MTK_WED_RX_MIB(_n) (0x2e0 + (_n) * 4) -@@ -267,6 +273,9 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c - #define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0) -+#define MTK_WED_WPDMA_RX_D_RX_DRV_BUSY BIT(1) -+#define MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE BIT(3) -+#define MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE BIT(4) - #define MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL GENMASK(11, 7) - #define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24) - diff --git a/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch deleted file mode 100644 index 4404971cc7..0000000000 --- a/target/linux/generic/backport-6.6/729-14-v6.2-net-ethernet-mtk_wed-add-reset-to-tx_ring_setup-call.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 24 Nov 2022 16:22:55 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset to tx_ring_setup callback - -Introduce reset parameter to mtk_wed_tx_ring_setup signature. -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1181,7 +1181,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device - } - - static int --mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, -+ bool reset) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; - struct mtk_wed_ring *wdma; -@@ -1190,8 +1191,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - return -EINVAL; - - wdma = &dev->rx_wdma[idx]; -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -- true)) -+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, -+ desc_size, true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1389,7 +1390,7 @@ mtk_wed_start(struct mtk_wed_device *dev - - for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) - if (!dev->rx_wdma[i].desc) -- mtk_wed_wdma_rx_ring_setup(dev, i, 16); -+ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false); - - mtk_wed_hw_init(dev); - mtk_wed_configure_irq(dev, irq_mask); -@@ -1498,7 +1499,8 @@ unlock: - } - - static int --mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, -+ bool reset) - { - struct mtk_wed_ring *ring = &dev->tx_ring[idx]; - -@@ -1517,11 +1519,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev - if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring))) - return -EINVAL; - -- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -- sizeof(*ring->desc), true)) -+ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, -+ sizeof(*ring->desc), true)) - return -ENOMEM; - -- if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, -+ reset)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_TX(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -158,7 +158,7 @@ struct mtk_wed_device { - struct mtk_wed_ops { - int (*attach)(struct mtk_wed_device *dev); - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, -- void __iomem *regs); -+ void __iomem *regs, bool reset); - int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, -@@ -216,8 +216,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - #define mtk_wed_device_active(_dev) !!(_dev)->ops - #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) - #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask) --#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \ -- (_dev)->ops->tx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \ -+ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset) - #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \ - (_dev)->ops->txfree_ring_setup(_dev, _regs) - #define mtk_wed_device_reg_read(_dev, _reg) \ -@@ -243,7 +243,7 @@ static inline bool mtk_wed_device_active - } - #define mtk_wed_device_detach(_dev) do {} while (0) - #define mtk_wed_device_start(_dev, _mask) do {} while (0) --#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV - #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV - #define mtk_wed_device_reg_read(_dev, _reg) 0 - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) diff --git a/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch b/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch deleted file mode 100644 index f9b11326b1..0000000000 --- a/target/linux/generic/backport-6.6/729-15-v6.2-net-ethernet-mtk_wed-fix-sleep-while-atomic-in-mtk_w.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 1 Dec 2022 16:26:53 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix sleep while atomic in - mtk_wed_wo_queue_refill - -In order to fix the following sleep while atomic bug always alloc pages -with GFP_ATOMIC in mtk_wed_wo_queue_refill since page_frag_alloc runs in -spin_lock critical section. - -[ 9.049719] Hardware name: MediaTek MT7986a RFB (DT) -[ 9.054665] Call trace: -[ 9.057096] dump_backtrace+0x0/0x154 -[ 9.060751] show_stack+0x14/0x1c -[ 9.064052] dump_stack_lvl+0x64/0x7c -[ 9.067702] dump_stack+0x14/0x2c -[ 9.071001] ___might_sleep+0xec/0x120 -[ 9.074736] __might_sleep+0x4c/0x9c -[ 9.078296] __alloc_pages+0x184/0x2e4 -[ 9.082030] page_frag_alloc_align+0x98/0x1ac -[ 9.086369] mtk_wed_wo_queue_refill+0x134/0x234 -[ 9.090974] mtk_wed_wo_init+0x174/0x2c0 -[ 9.094881] mtk_wed_attach+0x7c8/0x7e0 -[ 9.098701] mt7915_mmio_wed_init+0x1f0/0x3a0 [mt7915e] -[ 9.103940] mt7915_pci_probe+0xec/0x3bc [mt7915e] -[ 9.108727] pci_device_probe+0xac/0x13c -[ 9.112638] really_probe.part.0+0x98/0x2f4 -[ 9.116807] __driver_probe_device+0x94/0x13c -[ 9.121147] driver_probe_device+0x40/0x114 -[ 9.125314] __driver_attach+0x7c/0x180 -[ 9.129133] bus_for_each_dev+0x5c/0x90 -[ 9.132953] driver_attach+0x20/0x2c -[ 9.136513] bus_add_driver+0x104/0x1fc -[ 9.140333] driver_register+0x74/0x120 -[ 9.144153] __pci_register_driver+0x40/0x50 -[ 9.148407] mt7915_init+0x5c/0x1000 [mt7915e] -[ 9.152848] do_one_initcall+0x40/0x25c -[ 9.156669] do_init_module+0x44/0x230 -[ 9.160403] load_module+0x1f30/0x2750 -[ 9.164135] __do_sys_init_module+0x150/0x200 -[ 9.168475] __arm64_sys_init_module+0x18/0x20 -[ 9.172901] invoke_syscall.constprop.0+0x4c/0xe0 -[ 9.177589] do_el0_svc+0x48/0xe0 -[ 9.180889] el0_svc+0x14/0x50 -[ 9.183929] el0t_64_sync_handler+0x9c/0x120 -[ 9.188183] el0t_64_sync+0x158/0x15c - -Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Pavan Chebbi -Link: https://lore.kernel.org/r/67ca94bdd3d9eaeb86e52b3050fbca0bcf7bb02f.1669908312.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -133,17 +133,18 @@ mtk_wed_wo_dequeue(struct mtk_wed_wo *wo - - static int - mtk_wed_wo_queue_refill(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q, -- gfp_t gfp, bool rx) -+ bool rx) - { - enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - int n_buf = 0; - - spin_lock_bh(&q->lock); - while (q->queued < q->n_desc) { -- void *buf = page_frag_alloc(&q->cache, q->buf_size, gfp); - struct mtk_wed_wo_queue_entry *entry; - dma_addr_t addr; -+ void *buf; - -+ buf = page_frag_alloc(&q->cache, q->buf_size, GFP_ATOMIC); - if (!buf) - break; - -@@ -215,7 +216,7 @@ mtk_wed_wo_rx_run_queue(struct mtk_wed_w - mtk_wed_mcu_rx_unsolicited_event(wo, skb); - } - -- if (mtk_wed_wo_queue_refill(wo, q, GFP_ATOMIC, true)) { -+ if (mtk_wed_wo_queue_refill(wo, q, true)) { - u32 index = (q->head - 1) % q->n_desc; - - mtk_wed_wo_queue_kick(wo, q, index); -@@ -432,7 +433,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ - if (ret) - goto error; - -- mtk_wed_wo_queue_refill(wo, &wo->q_tx, GFP_KERNEL, false); -+ mtk_wed_wo_queue_refill(wo, &wo->q_tx, false); - mtk_wed_wo_queue_reset(wo, &wo->q_tx); - - regs.desc_base = MTK_WED_WO_CCIF_DUMMY5; -@@ -446,7 +447,7 @@ mtk_wed_wo_hardware_init(struct mtk_wed_ - if (ret) - goto error; - -- mtk_wed_wo_queue_refill(wo, &wo->q_rx, GFP_KERNEL, true); -+ mtk_wed_wo_queue_refill(wo, &wo->q_rx, true); - mtk_wed_wo_queue_reset(wo, &wo->q_rx); - - /* rx queue irqmask */ diff --git a/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch b/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch deleted file mode 100644 index fa6f56dbe7..0000000000 --- a/target/linux/generic/backport-6.6/729-16-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-rx-qu.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Lorenzo Bianconi -Date: Tue, 10 Jan 2023 10:31:26 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for rx queue - -Queue spinlock is currently held in mtk_wed_wo_queue_rx_clean and -mtk_wed_wo_queue_refill routines for MTK Wireless Ethernet Dispatcher -MCU rx queue. mtk_wed_wo_queue_refill() is running during initialization -and in rx tasklet while mtk_wed_wo_queue_rx_clean() is running in -mtk_wed_wo_hw_deinit() during hw de-init phase after rx tasklet has been -disabled. Since mtk_wed_wo_queue_rx_clean and mtk_wed_wo_queue_refill -routines can't run concurrently get rid of spinlock for mcu rx queue. - -Reviewed-by: Alexander Duyck -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/36ec3b729542ea60898471d890796f745479ba32.1673342990.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -138,7 +138,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w - enum dma_data_direction dir = rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - int n_buf = 0; - -- spin_lock_bh(&q->lock); - while (q->queued < q->n_desc) { - struct mtk_wed_wo_queue_entry *entry; - dma_addr_t addr; -@@ -172,7 +171,6 @@ mtk_wed_wo_queue_refill(struct mtk_wed_w - q->queued++; - n_buf++; - } -- spin_unlock_bh(&q->lock); - - return n_buf; - } -@@ -316,7 +314,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed - { - struct page *page; - -- spin_lock_bh(&q->lock); - for (;;) { - void *buf = mtk_wed_wo_dequeue(wo, q, NULL, true); - -@@ -325,7 +322,6 @@ mtk_wed_wo_queue_rx_clean(struct mtk_wed - - skb_free_frag(buf); - } -- spin_unlock_bh(&q->lock); - - if (!q->cache.va) - return; diff --git a/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch b/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch deleted file mode 100644 index 9b1e4c3250..0000000000 --- a/target/linux/generic/backport-6.6/729-17-v6.3-net-ethernet-mtk_wed-get-rid-of-queue-lock-for-tx-qu.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Lorenzo Bianconi -Date: Thu, 12 Jan 2023 10:21:29 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: get rid of queue lock for tx queue - -Similar to MTK Wireless Ethernet Dispatcher (WED) MCU rx queue, -we do not need to protect WED MCU tx queue with a spin lock since -the tx queue is accessed in the two following routines: -- mtk_wed_wo_queue_tx_skb(): - it is run at initialization and during mt7915 normal operation. - Moreover MCU messages are serialized through MCU mutex. -- mtk_wed_wo_queue_tx_clean(): - it runs just at mt7915 driver module unload when no more messages - are sent to the MCU. - -Remove tx queue spinlock. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/7bd0337b2a13ab1a63673b7c03fd35206b3b284e.1673515140.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c -@@ -258,7 +258,6 @@ mtk_wed_wo_queue_alloc(struct mtk_wed_wo - int n_desc, int buf_size, int index, - struct mtk_wed_wo_queue_regs *regs) - { -- spin_lock_init(&q->lock); - q->regs = *regs; - q->n_desc = n_desc; - q->buf_size = buf_size; -@@ -290,7 +289,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed - struct page *page; - int i; - -- spin_lock_bh(&q->lock); - for (i = 0; i < q->n_desc; i++) { - struct mtk_wed_wo_queue_entry *entry = &q->entry[i]; - -@@ -299,7 +297,6 @@ mtk_wed_wo_queue_tx_clean(struct mtk_wed - skb_free_frag(entry->buf); - entry->buf = NULL; - } -- spin_unlock_bh(&q->lock); - - if (!q->cache.va) - return; -@@ -347,8 +344,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w - int ret = 0, index; - u32 ctrl; - -- spin_lock_bh(&q->lock); -- - q->tail = mtk_wed_mmio_r32(wo, q->regs.dma_idx); - index = (q->head + 1) % q->n_desc; - if (q->tail == index) { -@@ -379,8 +374,6 @@ int mtk_wed_wo_queue_tx_skb(struct mtk_w - mtk_wed_wo_queue_kick(wo, q, q->head); - mtk_wed_wo_kickout(wo); - out: -- spin_unlock_bh(&q->lock); -- - dev_kfree_skb(skb); - - return ret; ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -211,7 +211,6 @@ struct mtk_wed_wo_queue { - struct mtk_wed_wo_queue_regs regs; - - struct page_frag_cache cache; -- spinlock_t lock; - - struct mtk_wed_wo_queue_desc *desc; - dma_addr_t desc_dma; diff --git a/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch b/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch deleted file mode 100644 index c91861a8f1..0000000000 --- a/target/linux/generic/backport-6.6/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:28 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_reset utility - routine - -This is a preliminary patch to add Wireless Ethernet Dispatcher reset -support. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3256,6 +3256,27 @@ static void mtk_set_mcr_max_rx(struct mt - mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); - } - -+static void mtk_hw_reset(struct mtk_eth *eth) -+{ -+ u32 val; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -+ val = RSTCTRL_PPE0_V2; -+ } else { -+ val = RSTCTRL_PPE0; -+ } -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1; -+ -+ ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -+ 0x3ffffff); -+} -+ - static int mtk_hw_init(struct mtk_eth *eth) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3295,22 +3316,9 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -- val = RSTCTRL_PPE0_V2; -- } else { -- val = RSTCTRL_PPE0; -- } -- -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= RSTCTRL_PPE1; -- -- ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); -+ mtk_hw_reset(eth); - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -- 0x3ffffff); -- - /* Set FE to PDMAv2 if necessary */ - val = mtk_r32(eth, MTK_FE_GLO_MISC); - mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); diff --git a/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch b/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch deleted file mode 100644 index 6597eb5b74..0000000000 --- a/target/linux/generic/backport-6.6/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch +++ /dev/null @@ -1,107 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:29 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_warm_reset - support - -Introduce mtk_hw_warm_reset utility routine. This is a preliminary patch -to align reset procedure to vendor sdk and avoid to power down the chip -during hw reset. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3277,7 +3277,54 @@ static void mtk_hw_reset(struct mtk_eth - 0x3ffffff); - } - --static int mtk_hw_init(struct mtk_eth *eth) -+static u32 mtk_hw_reset_read(struct mtk_eth *eth) -+{ -+ u32 val; -+ -+ regmap_read(eth->ethsys, ETHSYS_RSTCTRL, &val); -+ return val; -+} -+ -+static void mtk_hw_warm_reset(struct mtk_eth *eth) -+{ -+ u32 rst_mask, val; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, RSTCTRL_FE, -+ RSTCTRL_FE); -+ if (readx_poll_timeout_atomic(mtk_hw_reset_read, eth, val, -+ val & RSTCTRL_FE, 1, 1000)) { -+ dev_err(eth->dev, "warm reset failed\n"); -+ mtk_hw_reset(eth); -+ return; -+ } -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; -+ else -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); -+ -+ udelay(1); -+ val = mtk_hw_reset_read(eth); -+ if (!(val & rst_mask)) -+ dev_err(eth->dev, "warm reset stage0 failed %08x (%08x)\n", -+ val, rst_mask); -+ -+ rst_mask |= RSTCTRL_FE; -+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, ~rst_mask); -+ -+ udelay(1); -+ val = mtk_hw_reset_read(eth); -+ if (val & rst_mask) -+ dev_err(eth->dev, "warm reset stage1 failed %08x (%08x)\n", -+ val, rst_mask); -+} -+ -+static int mtk_hw_init(struct mtk_eth *eth, bool reset) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | - ETHSYS_DMA_AG_MAP_PPE; -@@ -3316,7 +3363,12 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - } - -- mtk_hw_reset(eth); -+ msleep(100); -+ -+ if (reset) -+ mtk_hw_warm_reset(eth); -+ else -+ mtk_hw_reset(eth); - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - /* Set FE to PDMAv2 if necessary */ -@@ -3507,7 +3559,7 @@ static void mtk_pending_work(struct work - if (eth->dev->pins) - pinctrl_select_state(eth->dev->pins->p, - eth->dev->pins->default_state); -- mtk_hw_init(eth); -+ mtk_hw_init(eth, true); - - /* restart DMA and enable IRQs */ - for (i = 0; i < MTK_MAC_COUNT; i++) { -@@ -4109,7 +4161,7 @@ static int mtk_probe(struct platform_dev - eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); - INIT_WORK(ð->pending_work, mtk_pending_work); - -- err = mtk_hw_init(eth); -+ err = mtk_hw_init(eth, false); - if (err) - goto err_wed_exit; - diff --git a/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch b/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch deleted file mode 100644 index 55ab19f4c8..0000000000 --- a/target/linux/generic/backport-6.6/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch +++ /dev/null @@ -1,262 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: align reset procedure to vendor - sdk - -Avoid to power-down the ethernet chip during hw reset and align reset -procedure to vendor sdk. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2844,14 +2844,29 @@ static void mtk_dma_free(struct mtk_eth - kfree(eth->scratch_head); - } - -+static bool mtk_hw_reset_check(struct mtk_eth *eth) -+{ -+ u32 val = mtk_r32(eth, MTK_INT_STATUS2); -+ -+ return (val & MTK_FE_INT_FQ_EMPTY) || (val & MTK_FE_INT_RFIFO_UF) || -+ (val & MTK_FE_INT_RFIFO_OV) || (val & MTK_FE_INT_TSO_FAIL) || -+ (val & MTK_FE_INT_TSO_ALIGN) || (val & MTK_FE_INT_TSO_ILLEGAL); -+} -+ - static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) - { - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - -+ if (test_bit(MTK_RESETTING, ð->state)) -+ return; -+ -+ if (!mtk_hw_reset_check(eth)) -+ return; -+ - eth->netdev[mac->id]->stats.tx_errors++; -- netif_err(eth, tx_err, dev, -- "transmit timed out\n"); -+ netif_err(eth, tx_err, dev, "transmit timed out\n"); -+ - schedule_work(ð->pending_work); - } - -@@ -3331,15 +3346,17 @@ static int mtk_hw_init(struct mtk_eth *e - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - int i, val, ret; - -- if (test_and_set_bit(MTK_HW_INIT, ð->state)) -+ if (!reset && test_and_set_bit(MTK_HW_INIT, ð->state)) - return 0; - -- pm_runtime_enable(eth->dev); -- pm_runtime_get_sync(eth->dev); -+ if (!reset) { -+ pm_runtime_enable(eth->dev); -+ pm_runtime_get_sync(eth->dev); - -- ret = mtk_clk_enable(eth); -- if (ret) -- goto err_disable_pm; -+ ret = mtk_clk_enable(eth); -+ if (ret) -+ goto err_disable_pm; -+ } - - if (eth->ethsys) - regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, -@@ -3468,8 +3485,10 @@ static int mtk_hw_init(struct mtk_eth *e - return 0; - - err_disable_pm: -- pm_runtime_put_sync(eth->dev); -- pm_runtime_disable(eth->dev); -+ if (!reset) { -+ pm_runtime_put_sync(eth->dev); -+ pm_runtime_disable(eth->dev); -+ } - - return ret; - } -@@ -3531,30 +3550,53 @@ static int mtk_do_ioctl(struct net_devic - return -EOPNOTSUPP; - } - -+static void mtk_prepare_for_reset(struct mtk_eth *eth) -+{ -+ u32 val; -+ int i; -+ -+ /* disabe FE P3 and P4 */ -+ val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= MTK_FE_LINK_DOWN_P4; -+ mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ -+ /* adjust PPE configurations to prepare for reset */ -+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) -+ mtk_ppe_prepare_reset(eth->ppe[i]); -+ -+ /* disable NETSYS interrupts */ -+ mtk_w32(eth, 0, MTK_FE_INT_ENABLE); -+ -+ /* force link down GMAC */ -+ for (i = 0; i < 2; i++) { -+ val = mtk_r32(eth, MTK_MAC_MCR(i)) & ~MAC_MCR_FORCE_LINK; -+ mtk_w32(eth, val, MTK_MAC_MCR(i)); -+ } -+} -+ - static void mtk_pending_work(struct work_struct *work) - { - struct mtk_eth *eth = container_of(work, struct mtk_eth, pending_work); -- int err, i; - unsigned long restart = 0; -+ u32 val; -+ int i; - - rtnl_lock(); -- -- dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); - set_bit(MTK_RESETTING, ð->state); - -+ 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++) { -- if (!eth->netdev[i]) -+ if (!eth->netdev[i] || !netif_running(eth->netdev[i])) - continue; -+ - mtk_stop(eth->netdev[i]); - __set_bit(i, &restart); - } -- dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__); - -- /* restart underlying hardware such as power, clock, pin mux -- * and the connected phy -- */ -- mtk_hw_deinit(eth); -+ usleep_range(15000, 16000); - - if (eth->dev->pins) - pinctrl_select_state(eth->dev->pins->p, -@@ -3565,15 +3607,19 @@ static void mtk_pending_work(struct work - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!test_bit(i, &restart)) - continue; -- err = mtk_open(eth->netdev[i]); -- if (err) { -+ -+ if (mtk_open(eth->netdev[i])) { - netif_alert(eth, ifup, eth->netdev[i], -- "Driver up/down cycle failed, closing device.\n"); -+ "Driver up/down cycle failed\n"); - dev_close(eth->netdev[i]); - } - } - -- dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); -+ /* enabe FE P3 and P4 */ -+ val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val &= ~MTK_FE_LINK_DOWN_P4; -+ mtk_w32(eth, val, MTK_FE_GLO_CFG); - - clear_bit(MTK_RESETTING, ð->state); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -72,12 +72,24 @@ - #define MTK_HW_LRO_REPLACE_DELTA 1000 - #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 - -+/* Frame Engine Global Configuration */ -+#define MTK_FE_GLO_CFG 0x00 -+#define MTK_FE_LINK_DOWN_P3 BIT(11) -+#define MTK_FE_LINK_DOWN_P4 BIT(12) -+ - /* Frame Engine Global Reset Register */ - #define MTK_RST_GL 0x04 - #define RST_GL_PSE BIT(0) - - /* Frame Engine Interrupt Status Register */ - #define MTK_INT_STATUS2 0x08 -+#define MTK_FE_INT_ENABLE 0x0c -+#define MTK_FE_INT_FQ_EMPTY BIT(8) -+#define MTK_FE_INT_TSO_FAIL BIT(12) -+#define MTK_FE_INT_TSO_ILLEGAL BIT(13) -+#define MTK_FE_INT_TSO_ALIGN BIT(14) -+#define MTK_FE_INT_RFIFO_OV BIT(18) -+#define MTK_FE_INT_RFIFO_UF BIT(19) - #define MTK_GDM1_AF BIT(28) - #define MTK_GDM2_AF BIT(29) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -710,6 +710,33 @@ int mtk_foe_entry_idle_time(struct mtk_p - return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); - } - -+int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) -+{ -+ if (!ppe) -+ return -EINVAL; -+ -+ /* disable KA */ -+ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); -+ ppe_clear(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); -+ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0); -+ usleep_range(10000, 11000); -+ -+ /* set KA timer to maximum */ -+ ppe_set(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE); -+ ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0xffffffff); -+ -+ /* set KA tick select */ -+ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_TICK_SEL); -+ ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE); -+ usleep_range(10000, 11000); -+ -+ /* disable scan mode */ -+ ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_SCAN_MODE); -+ usleep_range(10000, 11000); -+ -+ return mtk_ppe_wait_busy(ppe); -+} -+ - struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, - int version, int index) - { ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -306,6 +306,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - void mtk_ppe_deinit(struct mtk_eth *eth); - void mtk_ppe_start(struct mtk_ppe *ppe); - int mtk_ppe_stop(struct mtk_ppe *ppe); -+int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); - - void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -58,6 +58,12 @@ - #define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16) - #define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18) - #define MTK_PPE_TB_CFG_INFO_SEL BIT(20) -+#define MTK_PPE_TB_TICK_SEL BIT(24) -+ -+#define MTK_PPE_BIND_LMT1 0x230 -+#define MTK_PPE_NTU_KEEPALIVE GENMASK(23, 16) -+ -+#define MTK_PPE_KEEPALIVE 0x234 - - enum { - MTK_PPE_SCAN_MODE_DISABLED, diff --git a/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch b/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch deleted file mode 100644 index d5a7c0eba2..0000000000 --- a/target/linux/generic/backport-6.6/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch +++ /dev/null @@ -1,249 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:31 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add dma checks to - mtk_hw_reset_check - -Introduce mtk_hw_check_dma_hang routine to monitor possible dma hangs. - -Reviewed-by: Leon Romanovsky -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -50,6 +50,7 @@ static const struct mtk_reg_map mtk_reg_ - .delay_irq = 0x0a0c, - .irq_status = 0x0a20, - .irq_mask = 0x0a28, -+ .adma_rx_dbg0 = 0x0a38, - .int_grp = 0x0a50, - }, - .qdma = { -@@ -79,6 +80,8 @@ static const struct mtk_reg_map mtk_reg_ - [0] = 0x2800, - [1] = 0x2c00, - }, -+ .pse_iq_sta = 0x0110, -+ .pse_oq_sta = 0x0118, - }; - - static const struct mtk_reg_map mt7628_reg_map = { -@@ -109,6 +112,7 @@ static const struct mtk_reg_map mt7986_r - .delay_irq = 0x620c, - .irq_status = 0x6220, - .irq_mask = 0x6228, -+ .adma_rx_dbg0 = 0x6238, - .int_grp = 0x6250, - }, - .qdma = { -@@ -138,6 +142,8 @@ static const struct mtk_reg_map mt7986_r - [0] = 0x4800, - [1] = 0x4c00, - }, -+ .pse_iq_sta = 0x0180, -+ .pse_oq_sta = 0x01a0, - }; - - /* strings used by ethtool */ -@@ -3339,6 +3345,102 @@ static void mtk_hw_warm_reset(struct mtk - val, rst_mask); - } - -+static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) -+{ -+ const struct mtk_reg_map *reg_map = eth->soc->reg_map; -+ bool gmac1_tx, gmac2_tx, gdm1_tx, gdm2_tx; -+ bool oq_hang, cdm1_busy, adma_busy; -+ bool wtx_busy, cdm_full, oq_free; -+ u32 wdidx, val, gdm1_fc, gdm2_fc; -+ bool qfsm_hang, qfwd_hang; -+ bool ret = false; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) -+ return false; -+ -+ /* WDMA sanity checks */ -+ wdidx = mtk_r32(eth, reg_map->wdma_base[0] + 0xc); -+ -+ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x204); -+ wtx_busy = FIELD_GET(MTK_TX_DMA_BUSY, val); -+ -+ val = mtk_r32(eth, reg_map->wdma_base[0] + 0x230); -+ cdm_full = !FIELD_GET(MTK_CDM_TXFIFO_RDY, val); -+ -+ oq_free = (!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(24, 16)) && -+ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x4) & GENMASK(8, 0)) && -+ !(mtk_r32(eth, reg_map->pse_oq_sta + 0x10) & GENMASK(24, 16))); -+ -+ if (wdidx == eth->reset.wdidx && wtx_busy && cdm_full && oq_free) { -+ if (++eth->reset.wdma_hang_count > 2) { -+ eth->reset.wdma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ /* QDMA sanity checks */ -+ qfsm_hang = !!mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x234); -+ qfwd_hang = !mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x308); -+ -+ gdm1_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM1_FSM)) > 0; -+ gdm2_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM2_FSM)) > 0; -+ gmac1_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(0))) != 1; -+ gmac2_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(1))) != 1; -+ gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x24); -+ gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x64); -+ -+ if (qfsm_hang && qfwd_hang && -+ ((gdm1_tx && gmac1_tx && gdm1_fc < 1) || -+ (gdm2_tx && gmac2_tx && gdm2_fc < 1))) { -+ if (++eth->reset.qdma_hang_count > 2) { -+ eth->reset.qdma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ /* ADMA sanity checks */ -+ oq_hang = !!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(8, 0)); -+ cdm1_busy = !!(mtk_r32(eth, MTK_FE_CDM1_FSM) & GENMASK(31, 16)); -+ adma_busy = !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & GENMASK(4, 0)) && -+ !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & BIT(6)); -+ -+ if (oq_hang && cdm1_busy && adma_busy) { -+ if (++eth->reset.adma_hang_count > 2) { -+ eth->reset.adma_hang_count = 0; -+ ret = true; -+ } -+ goto out; -+ } -+ -+ eth->reset.wdma_hang_count = 0; -+ eth->reset.qdma_hang_count = 0; -+ eth->reset.adma_hang_count = 0; -+out: -+ eth->reset.wdidx = wdidx; -+ -+ return ret; -+} -+ -+static void mtk_hw_reset_monitor_work(struct work_struct *work) -+{ -+ struct delayed_work *del_work = to_delayed_work(work); -+ struct mtk_eth *eth = container_of(del_work, struct mtk_eth, -+ reset.monitor_work); -+ -+ if (test_bit(MTK_RESETTING, ð->state)) -+ goto out; -+ -+ /* DMA stuck checks */ -+ if (mtk_hw_check_dma_hang(eth)) -+ schedule_work(ð->pending_work); -+ -+out: -+ schedule_delayed_work(ð->reset.monitor_work, -+ MTK_DMA_MONITOR_TIMEOUT); -+} -+ - static int mtk_hw_init(struct mtk_eth *eth, bool reset) - { - u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3657,6 +3759,7 @@ static int mtk_cleanup(struct mtk_eth *e - mtk_unreg_dev(eth); - mtk_free_dev(eth); - cancel_work_sync(ð->pending_work); -+ cancel_delayed_work_sync(ð->reset.monitor_work); - - return 0; - } -@@ -4094,6 +4197,7 @@ static int mtk_probe(struct platform_dev - - eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; - INIT_WORK(ð->rx_dim.work, mtk_dim_rx); -+ INIT_DELAYED_WORK(ð->reset.monitor_work, mtk_hw_reset_monitor_work); - - eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; - INIT_WORK(ð->tx_dim.work, mtk_dim_tx); -@@ -4296,6 +4400,8 @@ static int mtk_probe(struct platform_dev - netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx); - - platform_set_drvdata(pdev, eth); -+ schedule_delayed_work(ð->reset.monitor_work, -+ MTK_DMA_MONITOR_TIMEOUT); - - return 0; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -257,6 +257,8 @@ - - #define MTK_RX_DONE_INT_V2 BIT(14) - -+#define MTK_CDM_TXFIFO_RDY BIT(7) -+ - /* QDMA Interrupt grouping registers */ - #define MTK_RLS_DONE_INT BIT(0) - -@@ -542,6 +544,17 @@ - #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) - #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) - -+#define MTK_FE_CDM1_FSM 0x220 -+#define MTK_FE_CDM2_FSM 0x224 -+#define MTK_FE_CDM3_FSM 0x238 -+#define MTK_FE_CDM4_FSM 0x298 -+#define MTK_FE_CDM5_FSM 0x318 -+#define MTK_FE_CDM6_FSM 0x328 -+#define MTK_FE_GDM1_FSM 0x228 -+#define MTK_FE_GDM2_FSM 0x22C -+ -+#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) -+ - struct mtk_rx_dma { - unsigned int rxd1; - unsigned int rxd2; -@@ -938,6 +951,7 @@ struct mtk_reg_map { - u32 delay_irq; /* delay interrupt */ - u32 irq_status; /* interrupt status */ - u32 irq_mask; /* interrupt mask */ -+ u32 adma_rx_dbg0; - u32 int_grp; - } pdma; - struct { -@@ -964,6 +978,8 @@ struct mtk_reg_map { - u32 gdma_to_ppe; - u32 ppe_base; - u32 wdma_base[2]; -+ u32 pse_iq_sta; -+ u32 pse_oq_sta; - }; - - /* struct mtk_eth_data - This is the structure holding all differences -@@ -1006,6 +1022,8 @@ struct mtk_soc_data { - } txrx; - }; - -+#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) -+ - /* currently no SoC has more than 2 macs */ - #define MTK_MAX_DEVS 2 - -@@ -1128,6 +1146,14 @@ struct mtk_eth { - struct rhashtable flow_table; - - struct bpf_prog __rcu *prog; -+ -+ struct { -+ struct delayed_work monitor_work; -+ u32 wdidx; -+ u8 wdma_hang_count; -+ u8 qdma_hang_count; -+ u8 adma_hang_count; -+ } reset; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the diff --git a/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch b/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch deleted file mode 100644 index c21d094ae8..0000000000 --- a/target/linux/generic/backport-6.6/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch +++ /dev/null @@ -1,124 +0,0 @@ -From: Lorenzo Bianconi -Date: Sat, 14 Jan 2023 18:01:32 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset/reset_complete callbacks - -Introduce reset and reset_complete wlan callback to schedule WLAN driver -reset when ethernet/wed driver is resetting. - -Tested-by: Daniel Golle -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Paolo Abeni ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3688,6 +3688,11 @@ static void mtk_pending_work(struct work - set_bit(MTK_RESETTING, ð->state); - - mtk_prepare_for_reset(eth); -+ mtk_wed_fe_reset(); -+ /* Run again reset preliminary configuration in order to avoid any -+ * possible race during FE reset since it can run releasing RTNL lock. -+ */ -+ 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++) { -@@ -3725,6 +3730,8 @@ static void mtk_pending_work(struct work - - clear_bit(MTK_RESETTING, ð->state); - -+ mtk_wed_fe_reset_complete(); -+ - rtnl_unlock(); - } - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -205,6 +205,48 @@ mtk_wed_wo_reset(struct mtk_wed_device * - iounmap(reg); - } - -+void mtk_wed_fe_reset(void) -+{ -+ int i; -+ -+ mutex_lock(&hw_lock); -+ -+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { -+ struct mtk_wed_hw *hw = hw_list[i]; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ int err; -+ -+ if (!dev || !dev->wlan.reset) -+ continue; -+ -+ /* reset callback blocks until WLAN reset is completed */ -+ err = dev->wlan.reset(dev); -+ if (err) -+ dev_err(dev->dev, "wlan reset failed: %d\n", err); -+ } -+ -+ mutex_unlock(&hw_lock); -+} -+ -+void mtk_wed_fe_reset_complete(void) -+{ -+ int i; -+ -+ mutex_lock(&hw_lock); -+ -+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { -+ struct mtk_wed_hw *hw = hw_list[i]; -+ struct mtk_wed_device *dev = hw->wed_dev; -+ -+ if (!dev || !dev->wlan.reset_complete) -+ continue; -+ -+ dev->wlan.reset_complete(dev); -+ } -+ -+ mutex_unlock(&hw_lock); -+} -+ - static struct mtk_wed_hw * - mtk_wed_assign(struct mtk_wed_device *dev) - { ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -128,6 +128,8 @@ void mtk_wed_add_hw(struct device_node * - void mtk_wed_exit(void); - int mtk_wed_flow_add(int index); - void mtk_wed_flow_remove(int index); -+void mtk_wed_fe_reset(void); -+void mtk_wed_fe_reset_complete(void); - #else - static inline void - mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, -@@ -147,6 +149,13 @@ static inline void mtk_wed_flow_remove(i - { - } - -+static inline void mtk_wed_fe_reset(void) -+{ -+} -+ -+static inline void mtk_wed_fe_reset_complete(void) -+{ -+} - #endif - - #ifdef CONFIG_DEBUG_FS ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -151,6 +151,8 @@ struct mtk_wed_device { - void (*release_rx_buf)(struct mtk_wed_device *wed); - void (*update_wo_rx_stats)(struct mtk_wed_device *wed, - struct mtk_wed_wo_rx_stats *stats); -+ int (*reset)(struct mtk_wed_device *wed); -+ void (*reset_complete)(struct mtk_wed_device *wed); - } wlan; - #endif - }; diff --git a/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch b/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch deleted file mode 100644 index c63628da99..0000000000 --- a/target/linux/generic/backport-6.6/729-23-v6.3-net-ethernet-mtk_wed-add-reset-to-rx_ring_setup-call.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Lorenzo Bianconi -Date: Mon, 5 Dec 2022 12:34:42 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: add reset to rx_ring_setup callback - -This patch adds reset parameter to mtk_wed_rx_ring_setup signature -in order to align rx_ring_setup callback to tx_ring_setup one introduced -in 'commit 23dca7a90017 ("net: ethernet: mtk_wed: add reset to -tx_ring_setup callback")' - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Link: https://lore.kernel.org/r/29c6e7a5469e784406cf3e2920351d1207713d05.1670239984.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1252,7 +1252,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we - } - - static int --mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size) -+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, -+ bool reset) - { - u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; - struct mtk_wed_ring *wdma; -@@ -1261,8 +1262,8 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we - return -EINVAL; - - wdma = &dev->tx_wdma[idx]; -- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size, -- true)) -+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, -+ desc_size, true)) - return -ENOMEM; - - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1272,6 +1273,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); - wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0); - -+ if (reset) -+ mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true); -+ - if (!idx) { - wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE, - wdma->desc_phys); -@@ -1611,18 +1615,20 @@ mtk_wed_txfree_ring_setup(struct mtk_wed - } - - static int --mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) -+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs, -+ bool reset) - { - struct mtk_wed_ring *ring = &dev->rx_ring[idx]; - - if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring))) - return -EINVAL; - -- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -- sizeof(*ring->desc), false)) -+ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, -+ sizeof(*ring->desc), false)) - return -ENOMEM; - -- if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) -+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, -+ reset)) - return -ENOMEM; - - ring->reg_base = MTK_WED_RING_RX_DATA(idx); ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -162,7 +162,7 @@ struct mtk_wed_ops { - int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, - void __iomem *regs, bool reset); - int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring, -- void __iomem *regs); -+ void __iomem *regs, bool reset); - int (*txfree_ring_setup)(struct mtk_wed_device *dev, - void __iomem *regs); - int (*msg_update)(struct mtk_wed_device *dev, int cmd_id, -@@ -230,8 +230,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->irq_get(_dev, _mask) - #define mtk_wed_device_irq_set_mask(_dev, _mask) \ - (_dev)->ops->irq_set_mask(_dev, _mask) --#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \ -- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs) -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \ -+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset) - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \ - (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \ -@@ -251,7 +251,7 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) - #define mtk_wed_device_irq_get(_dev, _mask) 0 - #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) --#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV -+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV - #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) do {} while (0) - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #define mtk_wed_device_stop(_dev) do {} while (0) diff --git a/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch b/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch deleted file mode 100644 index 45af898cf0..0000000000 --- a/target/linux/generic/backport-6.6/730-01-v6.3-net-ethernet-mtk_eth_soc-account-for-vlan-in-rx-head.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 19:50:31 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: account for vlan in rx - header length - -The network stack assumes that devices can handle an extra VLAN tag without -increasing the MTU - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -29,7 +29,7 @@ - #define MTK_TX_DMA_BUF_LEN_V2 0xffff - #define MTK_DMA_SIZE 512 - #define MTK_MAC_COUNT 2 --#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) -+#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 - #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ diff --git a/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch b/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch deleted file mode 100644 index 046a581224..0000000000 --- a/target/linux/generic/backport-6.6/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch +++ /dev/null @@ -1,143 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 19:53:57 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: increase tx ring side for - QDMA devices - -In order to use the hardware traffic shaper feature, a larger tx ring is -needed, especially for the scratch ring, which the hardware shaper uses to -reorder packets. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -944,7 +944,7 @@ static int mtk_init_fq_dma(struct mtk_et - { - const struct mtk_soc_data *soc = eth->soc; - dma_addr_t phy_ring_tail; -- int cnt = MTK_DMA_SIZE; -+ int cnt = MTK_QDMA_RING_SIZE; - dma_addr_t dma_addr; - int i; - -@@ -2208,19 +2208,25 @@ static int mtk_tx_alloc(struct mtk_eth * - struct mtk_tx_ring *ring = ð->tx_ring; - int i, sz = soc->txrx.txd_size; - struct mtk_tx_dma_v2 *txd; -+ int ring_size; - -- ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf), -+ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) -+ ring_size = MTK_QDMA_RING_SIZE; -+ else -+ ring_size = MTK_DMA_SIZE; -+ -+ ring->buf = kcalloc(ring_size, sizeof(*ring->buf), - GFP_KERNEL); - if (!ring->buf) - goto no_tx_mem; - -- ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, -+ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, - &ring->phys, GFP_KERNEL); - if (!ring->dma) - goto no_tx_mem; - -- for (i = 0; i < MTK_DMA_SIZE; i++) { -- int next = (i + 1) % MTK_DMA_SIZE; -+ for (i = 0; i < ring_size; i++) { -+ int next = (i + 1) % ring_size; - u32 next_ptr = ring->phys + next * sz; - - txd = ring->dma + i * sz; -@@ -2240,22 +2246,22 @@ static int mtk_tx_alloc(struct mtk_eth * - * descriptors in ring->dma_pdma. - */ - if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { -- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, -+ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, - &ring->phys_pdma, GFP_KERNEL); - if (!ring->dma_pdma) - goto no_tx_mem; - -- for (i = 0; i < MTK_DMA_SIZE; i++) { -+ for (i = 0; i < ring_size; i++) { - ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF; - ring->dma_pdma[i].txd4 = 0; - } - } - -- ring->dma_size = MTK_DMA_SIZE; -- atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); -+ ring->dma_size = ring_size; -+ atomic_set(&ring->free_count, ring_size - 2); - ring->next_free = ring->dma; - ring->last_free = (void *)txd; -- ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); -+ ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz)); - ring->thresh = MAX_SKB_FRAGS; - - /* make sure that all changes to the dma ring are flushed before we -@@ -2267,14 +2273,14 @@ static int mtk_tx_alloc(struct mtk_eth * - mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); - mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); - mtk_w32(eth, -- ring->phys + ((MTK_DMA_SIZE - 1) * sz), -+ ring->phys + ((ring_size - 1) * sz), - soc->reg_map->qdma.crx_ptr); - mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); - mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, - soc->reg_map->qdma.qtx_cfg); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); -- mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0); -+ mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); - mtk_w32(eth, 0, MT7628_TX_CTX_IDX0); - mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx); - } -@@ -2292,7 +2298,7 @@ static void mtk_tx_clean(struct mtk_eth - int i; - - if (ring->buf) { -- for (i = 0; i < MTK_DMA_SIZE; i++) -+ for (i = 0; i < ring->dma_size; i++) - mtk_tx_unmap(eth, &ring->buf[i], NULL, false); - kfree(ring->buf); - ring->buf = NULL; -@@ -2300,14 +2306,14 @@ static void mtk_tx_clean(struct mtk_eth - - if (ring->dma) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ ring->dma_size * soc->txrx.txd_size, - ring->dma, ring->phys); - ring->dma = NULL; - } - - if (ring->dma_pdma) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ ring->dma_size * soc->txrx.txd_size, - ring->dma_pdma, ring->phys_pdma); - ring->dma_pdma = NULL; - } -@@ -2832,7 +2838,7 @@ static void mtk_dma_free(struct mtk_eth - netdev_reset_queue(eth->netdev[i]); - if (eth->scratch_ring) { - dma_free_coherent(eth->dma_dev, -- MTK_DMA_SIZE * soc->txrx.txd_size, -+ MTK_QDMA_RING_SIZE * soc->txrx.txd_size, - eth->scratch_ring, eth->phy_scratch_ring); - eth->scratch_ring = NULL; - eth->phy_scratch_ring = 0; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -27,6 +27,7 @@ - #define MTK_MAX_RX_LENGTH_2K 2048 - #define MTK_TX_DMA_BUF_LEN 0x3fff - #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) diff --git a/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch b/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch deleted file mode 100644 index 7e879ca1d5..0000000000 --- a/target/linux/generic/backport-6.6/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Nov 2022 19:49:08 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: avoid port_mg assignment on - MT7622 and newer - -On newer chips, this field is unused and contains some bits related to queue -assignment. Initialize it to 0 in those cases. -Fix offload_version on MT7621 and MT7623, which still need the previous value. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4479,7 +4479,7 @@ static const struct mtk_soc_data mt7621_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7621_CLKS_BITMAP, - .required_pctl = false, -- .offload_version = 2, -+ .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { -@@ -4518,7 +4518,7 @@ static const struct mtk_soc_data mt7623_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -- .offload_version = 2, -+ .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -175,6 +175,8 @@ int mtk_foe_entry_prepare(struct mtk_eth - val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, pse_port) | - FIELD_PREP(MTK_FOE_IB2_PORT_AG_V2, 0xf); - } else { -+ int port_mg = eth->soc->offload_version > 1 ? 0 : 0x3f; -+ - val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | - FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | - FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | -@@ -182,7 +184,7 @@ int mtk_foe_entry_prepare(struct mtk_eth - entry->ib1 = val; - - val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port) | -- FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | -+ FIELD_PREP(MTK_FOE_IB2_PORT_MG, port_mg) | - FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f); - } - diff --git a/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch b/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch deleted file mode 100644 index 8ceba7831e..0000000000 --- a/target/linux/generic/backport-6.6/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch +++ /dev/null @@ -1,654 +0,0 @@ -From: Felix Fietkau -Date: Thu, 27 Oct 2022 20:17:27 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: implement multi-queue - support for per-port queues - -When sending traffic to multiple ports with different link speeds, queued -packets to one port can drown out tx to other ports. -In order to better handle transmission to multiple ports, use the hardware -shaper feature to implement weighted fair queueing between ports. -Weight and maximum rate are automatically adjusted based on the link speed -of the port. -The first 3 queues are unrestricted and reserved for non-DSA direct tx on -GMAC ports. The following queues are automatically assigned by the MTK DSA -tag driver based on the target port number. -The PPE offload code configures the queues for offloaded traffic in the same -way. -This feature is only supported on devices supporting QDMA. All queues still -share the same DMA ring and descriptor pool. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -55,6 +55,7 @@ static const struct mtk_reg_map mtk_reg_ - }, - .qdma = { - .qtx_cfg = 0x1800, -+ .qtx_sch = 0x1804, - .rx_ptr = 0x1900, - .rx_cnt_cfg = 0x1904, - .qcrx_ptr = 0x1908, -@@ -62,6 +63,7 @@ static const struct mtk_reg_map mtk_reg_ - .rst_idx = 0x1a08, - .delay_irq = 0x1a0c, - .fc_th = 0x1a10, -+ .tx_sch_rate = 0x1a14, - .int_grp = 0x1a20, - .hred = 0x1a44, - .ctx_ptr = 0x1b00, -@@ -117,6 +119,7 @@ static const struct mtk_reg_map mt7986_r - }, - .qdma = { - .qtx_cfg = 0x4400, -+ .qtx_sch = 0x4404, - .rx_ptr = 0x4500, - .rx_cnt_cfg = 0x4504, - .qcrx_ptr = 0x4508, -@@ -134,6 +137,7 @@ static const struct mtk_reg_map mt7986_r - .fq_tail = 0x4724, - .fq_count = 0x4728, - .fq_blen = 0x472c, -+ .tx_sch_rate = 0x4798, - }, - .gdm1_cnt = 0x1c00, - .gdma_to_ppe = 0x3333, -@@ -620,6 +624,75 @@ static void mtk_mac_link_down(struct phy - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); - } - -+static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -+ int speed) -+{ -+ const struct mtk_soc_data *soc = eth->soc; -+ u32 ofs, val; -+ -+ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) -+ return; -+ -+ val = MTK_QTX_SCH_MIN_RATE_EN | -+ /* minimum: 10 Mbps */ -+ 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)) -+ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; -+ -+ if (IS_ENABLED(CONFIG_SOC_MT7621)) { -+ switch (speed) { -+ case SPEED_10: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_100: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3); -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_1000: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); -+ break; -+ default: -+ break; -+ } -+ } else { -+ switch (speed) { -+ case SPEED_10: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_100: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5); -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); -+ break; -+ case SPEED_1000: -+ val |= MTK_QTX_SCH_MAX_RATE_EN | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ ofs = MTK_QTX_OFFSET * idx; -+ 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, -@@ -645,6 +718,8 @@ static void mtk_mac_link_up(struct phyli - break; - } - -+ mtk_set_queue_speed(mac->hw, mac->id, speed); -+ - /* Configure duplex */ - if (duplex == DUPLEX_FULL) - mcr |= MAC_MCR_FORCE_DPX; -@@ -1105,7 +1180,8 @@ static void mtk_tx_set_dma_desc_v1(struc - - WRITE_ONCE(desc->txd1, info->addr); - -- data = TX_DMA_SWC | TX_DMA_PLEN0(info->size); -+ data = TX_DMA_SWC | TX_DMA_PLEN0(info->size) | -+ FIELD_PREP(TX_DMA_PQID, info->qid); - if (info->last) - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); -@@ -1139,9 +1215,6 @@ static void mtk_tx_set_dma_desc_v2(struc - data |= TX_DMA_LS0; - WRITE_ONCE(desc->txd3, data); - -- if (!info->qid && mac->id) -- info->qid = MTK_QDMA_GMAC2_QID; -- - 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); -@@ -1185,11 +1258,12 @@ static int mtk_tx_map(struct sk_buff *sk - .gso = gso, - .csum = skb->ip_summed == CHECKSUM_PARTIAL, - .vlan = skb_vlan_tag_present(skb), -- .qid = skb->mark & MTK_QDMA_TX_MASK, -+ .qid = skb_get_queue_mapping(skb), - .vlan_tci = skb_vlan_tag_get(skb), - .first = true, - .last = !skb_is_nonlinear(skb), - }; -+ struct netdev_queue *txq; - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - const struct mtk_soc_data *soc = eth->soc; -@@ -1197,8 +1271,10 @@ static int mtk_tx_map(struct sk_buff *sk - struct mtk_tx_dma *itxd_pdma, *txd_pdma; - struct mtk_tx_buf *itx_buf, *tx_buf; - int i, n_desc = 1; -+ int queue = skb_get_queue_mapping(skb); - int k = 0; - -+ txq = netdev_get_tx_queue(dev, queue); - itxd = ring->next_free; - itxd_pdma = qdma_to_pdma(ring, itxd); - if (itxd == ring->last_free) -@@ -1247,7 +1323,7 @@ static int mtk_tx_map(struct sk_buff *sk - memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); - txd_info.size = min_t(unsigned int, frag_size, - soc->txrx.dma_max_len); -- txd_info.qid = skb->mark & MTK_QDMA_TX_MASK; -+ txd_info.qid = queue; - txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && - !(frag_size - txd_info.size); - txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, -@@ -1286,7 +1362,7 @@ static int mtk_tx_map(struct sk_buff *sk - txd_pdma->txd2 |= TX_DMA_LS1; - } - -- netdev_sent_queue(dev, skb->len); -+ netdev_tx_sent_queue(txq, skb->len); - skb_tx_timestamp(skb); - - ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); -@@ -1298,8 +1374,7 @@ static int mtk_tx_map(struct sk_buff *sk - wmb(); - - if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { -- if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || -- !netdev_xmit_more()) -+ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) - mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); - } else { - int next_idx; -@@ -1368,7 +1443,7 @@ static void mtk_wake_queue(struct mtk_et - for (i = 0; i < MTK_MAC_COUNT; i++) { - if (!eth->netdev[i]) - continue; -- netif_wake_queue(eth->netdev[i]); -+ netif_tx_wake_all_queues(eth->netdev[i]); - } - } - -@@ -1392,7 +1467,7 @@ static netdev_tx_t mtk_start_xmit(struct - - tx_num = mtk_cal_txd_req(eth, skb); - if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { -- netif_stop_queue(dev); -+ netif_tx_stop_all_queues(dev); - netif_err(eth, tx_queued, dev, - "Tx Ring full when queue awake!\n"); - spin_unlock(ð->page_lock); -@@ -1418,7 +1493,7 @@ static netdev_tx_t mtk_start_xmit(struct - goto drop; - - if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) -- netif_stop_queue(dev); -+ netif_tx_stop_all_queues(dev); - - spin_unlock(ð->page_lock); - -@@ -1585,10 +1660,12 @@ static int mtk_xdp_submit_frame(struct m - struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); - const struct mtk_soc_data *soc = eth->soc; - struct mtk_tx_ring *ring = ð->tx_ring; -+ struct mtk_mac *mac = netdev_priv(dev); - struct mtk_tx_dma_desc_info txd_info = { - .size = xdpf->len, - .first = true, - .last = !xdp_frame_has_frags(xdpf), -+ .qid = mac->id, - }; - int err, index = 0, n_desc = 1, nr_frags; - struct mtk_tx_buf *htx_buf, *tx_buf; -@@ -1638,6 +1715,7 @@ static int mtk_xdp_submit_frame(struct m - memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); - txd_info.size = skb_frag_size(&sinfo->frags[index]); - txd_info.last = index + 1 == nr_frags; -+ txd_info.qid = mac->id; - data = skb_frag_address(&sinfo->frags[index]); - - index++; -@@ -1992,8 +2070,46 @@ rx_done: - return done; - } - -+struct mtk_poll_state { -+ struct netdev_queue *txq; -+ unsigned int total; -+ unsigned int done; -+ unsigned int bytes; -+}; -+ -+static void -+mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac, -+ struct sk_buff *skb) -+{ -+ struct netdev_queue *txq; -+ struct net_device *dev; -+ unsigned int bytes = skb->len; -+ -+ state->total++; -+ eth->tx_packets++; -+ eth->tx_bytes += bytes; -+ -+ dev = eth->netdev[mac]; -+ if (!dev) -+ return; -+ -+ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); -+ if (state->txq == txq) { -+ state->done++; -+ state->bytes += bytes; -+ return; -+ } -+ -+ if (state->txq) -+ netdev_tx_completed_queue(state->txq, state->done, state->bytes); -+ -+ state->txq = txq; -+ state->done = 1; -+ state->bytes = bytes; -+} -+ - static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, -- unsigned int *done, unsigned int *bytes) -+ struct mtk_poll_state *state) - { - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - struct mtk_tx_ring *ring = ð->tx_ring; -@@ -2025,12 +2141,9 @@ static int mtk_poll_tx_qdma(struct mtk_e - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { -- if (tx_buf->type == MTK_TYPE_SKB) { -- struct sk_buff *skb = tx_buf->data; -+ if (tx_buf->type == MTK_TYPE_SKB) -+ mtk_poll_tx_done(eth, state, mac, tx_buf->data); - -- bytes[mac] += skb->len; -- done[mac]++; -- } - budget--; - } - mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2049,7 +2162,7 @@ static int mtk_poll_tx_qdma(struct mtk_e - } - - static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, -- unsigned int *done, unsigned int *bytes) -+ struct mtk_poll_state *state) - { - struct mtk_tx_ring *ring = ð->tx_ring; - struct mtk_tx_buf *tx_buf; -@@ -2067,12 +2180,8 @@ static int mtk_poll_tx_pdma(struct mtk_e - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { -- if (tx_buf->type == MTK_TYPE_SKB) { -- struct sk_buff *skb = tx_buf->data; -- -- bytes[0] += skb->len; -- done[0]++; -- } -+ if (tx_buf->type == MTK_TYPE_SKB) -+ mtk_poll_tx_done(eth, state, 0, tx_buf->data); - budget--; - } - mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2094,26 +2203,15 @@ static int mtk_poll_tx(struct mtk_eth *e - { - struct mtk_tx_ring *ring = ð->tx_ring; - struct dim_sample dim_sample = {}; -- unsigned int done[MTK_MAX_DEVS]; -- unsigned int bytes[MTK_MAX_DEVS]; -- int total = 0, i; -- -- memset(done, 0, sizeof(done)); -- memset(bytes, 0, sizeof(bytes)); -+ struct mtk_poll_state state = {}; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -- budget = mtk_poll_tx_qdma(eth, budget, done, bytes); -+ budget = mtk_poll_tx_qdma(eth, budget, &state); - else -- budget = mtk_poll_tx_pdma(eth, budget, done, bytes); -+ budget = mtk_poll_tx_pdma(eth, budget, &state); - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i] || !done[i]) -- continue; -- netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); -- total += done[i]; -- eth->tx_packets += done[i]; -- eth->tx_bytes += bytes[i]; -- } -+ if (state.txq) -+ netdev_tx_completed_queue(state.txq, state.done, state.bytes); - - dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, - &dim_sample); -@@ -2123,7 +2221,7 @@ static int mtk_poll_tx(struct mtk_eth *e - (atomic_read(&ring->free_count) > ring->thresh)) - mtk_wake_queue(eth); - -- return total; -+ return state.total; - } - - static void mtk_handle_status_irq(struct mtk_eth *eth) -@@ -2209,6 +2307,7 @@ static int mtk_tx_alloc(struct mtk_eth * - int i, sz = soc->txrx.txd_size; - struct mtk_tx_dma_v2 *txd; - int ring_size; -+ u32 ofs, val; - - if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) - ring_size = MTK_QDMA_RING_SIZE; -@@ -2276,8 +2375,25 @@ static int mtk_tx_alloc(struct mtk_eth * - ring->phys + ((ring_size - 1) * sz), - soc->reg_map->qdma.crx_ptr); - mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); -- mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, -- soc->reg_map->qdma.qtx_cfg); -+ -+ for (i = 0, ofs = 0; i < MTK_QDMA_NUM_QUEUES; i++) { -+ val = (QDMA_RES_THRES << 8) | QDMA_RES_THRES; -+ mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs); -+ -+ val = MTK_QTX_SCH_MIN_RATE_EN | -+ /* minimum: 10 Mbps */ -+ 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)) -+ val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; -+ mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); -+ ofs += MTK_QTX_OFFSET; -+ } -+ val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); -+ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); - mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); -@@ -2962,7 +3078,7 @@ static int mtk_start_dma(struct mtk_eth - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) - val |= MTK_MUTLI_CNT | MTK_RESV_BUF | - MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | -- MTK_CHK_DDONE_EN; -+ MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; - else - val |= MTK_RX_BT_32DWORDS; - mtk_w32(eth, val, reg_map->qdma.glo_cfg); -@@ -3008,6 +3124,45 @@ static void mtk_gdm_config(struct mtk_et - mtk_w32(eth, 0, MTK_RST_GL); - } - -+static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr) -+{ -+ struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier); -+ struct mtk_eth *eth = mac->hw; -+ struct net_device *dev = netdev_notifier_info_to_dev(ptr); -+ struct ethtool_link_ksettings s; -+ struct net_device *ldev; -+ struct list_head *iter; -+ struct dsa_port *dp; -+ -+ if (event != NETDEV_CHANGE) -+ return NOTIFY_DONE; -+ -+ netdev_for_each_lower_dev(dev, ldev, iter) { -+ if (netdev_priv(ldev) == mac) -+ goto found; -+ } -+ -+ return NOTIFY_DONE; -+ -+found: -+ if (!dsa_slave_dev_check(dev)) -+ return NOTIFY_DONE; -+ -+ if (__ethtool_get_link_ksettings(dev, &s)) -+ return NOTIFY_DONE; -+ -+ if (s.base.speed == 0 || s.base.speed == ((__u32)-1)) -+ return NOTIFY_DONE; -+ -+ dp = dsa_port_from_netdev(dev); -+ if (dp->index >= MTK_QDMA_NUM_QUEUES) -+ return NOTIFY_DONE; -+ -+ mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); -+ -+ return NOTIFY_DONE; -+} -+ - static int mtk_open(struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); -@@ -3050,7 +3205,8 @@ static int mtk_open(struct net_device *d - refcount_inc(ð->dma_refcnt); - - phylink_start(mac->phylink); -- netif_start_queue(dev); -+ netif_tx_start_all_queues(dev); -+ - return 0; - } - -@@ -3759,8 +3915,12 @@ static int mtk_unreg_dev(struct mtk_eth - int i; - - for (i = 0; i < MTK_MAC_COUNT; i++) { -+ struct mtk_mac *mac; - if (!eth->netdev[i]) - continue; -+ mac = netdev_priv(eth->netdev[i]); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ unregister_netdevice_notifier(&mac->device_notifier); - unregister_netdev(eth->netdev[i]); - } - -@@ -3977,6 +4137,23 @@ static int mtk_set_rxnfc(struct net_devi - return ret; - } - -+static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, -+ struct net_device *sb_dev) -+{ -+ struct mtk_mac *mac = netdev_priv(dev); -+ unsigned int queue = 0; -+ -+ if (netdev_uses_dsa(dev)) -+ queue = skb_get_queue_mapping(skb) + 3; -+ else -+ queue = mac->id; -+ -+ if (queue >= dev->num_tx_queues) -+ queue = 0; -+ -+ return queue; -+} -+ - static const struct ethtool_ops mtk_ethtool_ops = { - .get_link_ksettings = mtk_get_link_ksettings, - .set_link_ksettings = mtk_set_link_ksettings, -@@ -4011,6 +4188,7 @@ static const struct net_device_ops mtk_n - .ndo_setup_tc = mtk_eth_setup_tc, - .ndo_bpf = mtk_xdp, - .ndo_xdp_xmit = mtk_xdp_xmit, -+ .ndo_select_queue = mtk_select_queue, - }; - - static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) -@@ -4020,6 +4198,7 @@ static int mtk_add_mac(struct mtk_eth *e - struct phylink *phylink; - struct mtk_mac *mac; - int id, err; -+ int txqs = 1; - - if (!_id) { - dev_err(eth->dev, "missing mac id\n"); -@@ -4037,7 +4216,10 @@ static int mtk_add_mac(struct mtk_eth *e - return -EINVAL; - } - -- eth->netdev[id] = alloc_etherdev(sizeof(*mac)); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ txqs = MTK_QDMA_NUM_QUEUES; -+ -+ eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1); - if (!eth->netdev[id]) { - dev_err(eth->dev, "alloc_etherdev failed\n"); - return -ENOMEM; -@@ -4145,6 +4327,11 @@ static int mtk_add_mac(struct mtk_eth *e - else - eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { -+ mac->device_notifier.notifier_call = mtk_device_event; -+ register_netdevice_notifier(&mac->device_notifier); -+ } -+ - return 0; - - free_netdev: ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -22,6 +22,7 @@ - #include - #include "mtk_ppe.h" - -+#define MTK_QDMA_NUM_QUEUES 16 - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 - #define MTK_MAX_RX_LENGTH_2K 2048 -@@ -216,8 +217,26 @@ - #define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3) - - /* QDMA TX Queue Configuration Registers */ -+#define MTK_QTX_OFFSET 0x10 - #define QDMA_RES_THRES 4 - -+/* QDMA Tx Queue Scheduler Configuration Registers */ -+#define MTK_QTX_SCH_TX_SEL BIT(31) -+#define MTK_QTX_SCH_TX_SEL_V2 GENMASK(31, 30) -+ -+#define MTK_QTX_SCH_LEAKY_BUCKET_EN BIT(30) -+#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE GENMASK(29, 28) -+#define MTK_QTX_SCH_MIN_RATE_EN BIT(27) -+#define MTK_QTX_SCH_MIN_RATE_MAN GENMASK(26, 20) -+#define MTK_QTX_SCH_MIN_RATE_EXP GENMASK(19, 16) -+#define MTK_QTX_SCH_MAX_RATE_WEIGHT GENMASK(15, 12) -+#define MTK_QTX_SCH_MAX_RATE_EN BIT(11) -+#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4) -+#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0) -+ -+/* QDMA TX Scheduler Rate Control Register */ -+#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15) -+ - /* QDMA Global Configuration Register */ - #define MTK_RX_2B_OFFSET BIT(31) - #define MTK_RX_BT_32DWORDS (3 << 11) -@@ -236,6 +255,7 @@ - #define MTK_WCOMP_EN BIT(24) - #define MTK_RESV_BUF (0x40 << 16) - #define MTK_MUTLI_CNT (0x4 << 12) -+#define MTK_LEAKY_BUCKET_EN BIT(11) - - /* QDMA Flow Control Register */ - #define FC_THRES_DROP_MODE BIT(20) -@@ -266,8 +286,6 @@ - #define MTK_STAT_OFFSET 0x40 - - /* QDMA TX NUM */ --#define MTK_QDMA_TX_NUM 16 --#define MTK_QDMA_TX_MASK (MTK_QDMA_TX_NUM - 1) - #define QID_BITS_V2(x) (((x) & 0x3f) << 16) - #define MTK_QDMA_GMAC2_QID 8 - -@@ -297,6 +315,7 @@ - #define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) - #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) - #define TX_DMA_SWC BIT(14) -+#define TX_DMA_PQID GENMASK(3, 0) - - /* PDMA on MT7628 */ - #define TX_DMA_DONE BIT(31) -@@ -957,6 +976,7 @@ struct mtk_reg_map { - } pdma; - struct { - u32 qtx_cfg; /* tx queue configuration */ -+ u32 qtx_sch; /* tx queue scheduler configuration */ - u32 rx_ptr; /* rx base pointer */ - u32 rx_cnt_cfg; /* rx max count configuration */ - u32 qcrx_ptr; /* rx cpu pointer */ -@@ -974,6 +994,7 @@ struct mtk_reg_map { - u32 fq_tail; /* fq tail pointer */ - u32 fq_count; /* fq free page count */ - u32 fq_blen; /* fq free page buffer length */ -+ u32 tx_sch_rate; /* tx scheduler rate control registers */ - } qdma; - u32 gdm1_cnt; - u32 gdma_to_ppe; -@@ -1177,6 +1198,7 @@ struct mtk_mac { - __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; - int hwlro_ip_cnt; - unsigned int syscfg0; -+ struct notifier_block device_notifier; - }; - - /* the struct describing the SoC. these are declared in the soc_xyz.c files */ diff --git a/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch b/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch deleted file mode 100644 index 186df4bdc9..0000000000 --- a/target/linux/generic/backport-6.6/730-05-v6.3-net-dsa-tag_mtk-assign-per-port-queues.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Felix Fietkau -Date: Fri, 28 Oct 2022 18:16:03 +0200 -Subject: [PATCH] net: dsa: tag_mtk: assign per-port queues - -Keeps traffic sent to the switch within link speed limits - -Signed-off-by: Felix Fietkau ---- - ---- a/net/dsa/tag_mtk.c -+++ b/net/dsa/tag_mtk.c -@@ -25,6 +25,8 @@ static struct sk_buff *mtk_tag_xmit(stru - u8 xmit_tpid; - u8 *mtk_tag; - -+ skb_set_queue_mapping(skb, dp->index); -+ - /* Build the special tag after the MAC Source Address. If VLAN header - * is present, it's required that VLAN header and special tag is - * being combined. Only in this way we can allow the switch can parse diff --git a/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch b/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch deleted file mode 100644 index d29177eee7..0000000000 --- a/target/linux/generic/backport-6.6/730-06-v6.3-net-ethernet-mediatek-ppe-assign-per-port-queues-for.patch +++ /dev/null @@ -1,93 +0,0 @@ -From: Felix Fietkau -Date: Thu, 3 Nov 2022 17:49:44 +0100 -Subject: [PATCH] net: ethernet: mediatek: ppe: assign per-port queues - for offloaded traffic - -Keeps traffic sent to the switch within link speed limits - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -399,6 +399,24 @@ int mtk_foe_entry_set_wdma(struct mtk_et - return 0; - } - -+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, -+ unsigned int queue) -+{ -+ u32 *ib2 = mtk_foe_entry_ib2(eth, entry); -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ *ib2 &= ~MTK_FOE_IB2_QID_V2; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); -+ *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; -+ } else { -+ *ib2 &= ~MTK_FOE_IB2_QID; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, queue); -+ *ib2 |= MTK_FOE_IB2_PSE_QOS; -+ } -+ -+ return 0; -+} -+ - static bool - mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry, - struct mtk_foe_entry *data) ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -68,7 +68,9 @@ enum { - #define MTK_FOE_IB2_DSCP GENMASK(31, 24) - - /* CONFIG_MEDIATEK_NETSYS_V2 */ -+#define MTK_FOE_IB2_QID_V2 GENMASK(6, 0) - #define MTK_FOE_IB2_PORT_MG_V2 BIT(7) -+#define MTK_FOE_IB2_PSE_QOS_V2 BIT(8) - #define MTK_FOE_IB2_DEST_PORT_V2 GENMASK(12, 9) - #define MTK_FOE_IB2_MULTICAST_V2 BIT(13) - #define MTK_FOE_IB2_WDMA_WINFO_V2 BIT(19) -@@ -351,6 +353,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e - int sid); - int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, - int wdma_idx, int txq, int bss, int wcid); -+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, -+ unsigned int queue); - int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -188,7 +188,7 @@ mtk_flow_set_output_device(struct mtk_et - int *wed_index) - { - struct mtk_wdma_info info = {}; -- int pse_port, dsa_port; -+ int pse_port, dsa_port, queue; - - if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { - mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, -@@ -212,8 +212,6 @@ mtk_flow_set_output_device(struct mtk_et - } - - dsa_port = mtk_flow_get_dsa_port(&dev); -- if (dsa_port >= 0) -- mtk_foe_entry_set_dsa(eth, foe, dsa_port); - - if (dev == eth->netdev[0]) - pse_port = 1; -@@ -222,6 +220,14 @@ mtk_flow_set_output_device(struct mtk_et - else - return -EOPNOTSUPP; - -+ if (dsa_port >= 0) { -+ mtk_foe_entry_set_dsa(eth, foe, dsa_port); -+ queue = 3 + dsa_port; -+ } else { -+ queue = pse_port - 1; -+ } -+ mtk_foe_entry_set_queue(eth, foe, queue); -+ - out: - mtk_foe_entry_set_pse_port(eth, foe, pse_port); - diff --git a/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch b/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch deleted file mode 100644 index 6b7f3d6018..0000000000 --- a/target/linux/generic/backport-6.6/730-08-v6.3-net-dsa-add-support-for-DSA-rx-offloading-via-metada.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Felix Fietkau -Date: Tue, 8 Nov 2022 15:03:15 +0100 -Subject: [PATCH] net: dsa: add support for DSA rx offloading via - metadata dst - -If a metadata dst is present with the type METADATA_HW_PORT_MUX on a dsa cpu -port netdev, assume that it carries the port number and that there is no DSA -tag present in the skb data. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/core/flow_dissector.c -+++ b/net/core/flow_dissector.c -@@ -971,12 +971,14 @@ bool __skb_flow_dissect(const struct net - #if IS_ENABLED(CONFIG_NET_DSA) - if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) && - proto == htons(ETH_P_XDSA))) { -+ struct metadata_dst *md_dst = skb_metadata_dst(skb); - const struct dsa_device_ops *ops; - int offset = 0; - - ops = skb->dev->dsa_ptr->tag_ops; - /* Only DSA header taggers break flow dissection */ -- if (ops->needed_headroom) { -+ if (ops->needed_headroom && -+ (!md_dst || md_dst->type != METADATA_HW_PORT_MUX)) { - if (ops->flow_dissect) - ops->flow_dissect(skb, &proto, &offset); - else ---- a/net/dsa/dsa.c -+++ b/net/dsa/dsa.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include "dsa_priv.h" - -@@ -216,6 +217,7 @@ static bool dsa_skb_defer_rx_timestamp(s - static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *unused) - { -+ struct metadata_dst *md_dst = skb_metadata_dst(skb); - struct dsa_port *cpu_dp = dev->dsa_ptr; - struct sk_buff *nskb = NULL; - struct dsa_slave_priv *p; -@@ -229,7 +231,22 @@ static int dsa_switch_rcv(struct sk_buff - if (!skb) - return 0; - -- nskb = cpu_dp->rcv(skb, dev); -+ if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) { -+ unsigned int port = md_dst->u.port_info.port_id; -+ -+ skb_dst_drop(skb); -+ if (!skb_has_extensions(skb)) -+ skb->slow_gro = 0; -+ -+ skb->dev = dsa_master_find_slave(dev, 0, port); -+ if (likely(skb->dev)) { -+ dsa_default_offload_fwd_mark(skb); -+ nskb = skb; -+ } -+ } else { -+ nskb = cpu_dp->rcv(skb, dev); -+ } -+ - if (!nskb) { - kfree_skb(skb); - return 0; diff --git a/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch b/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch deleted file mode 100644 index b8e3452f30..0000000000 --- a/target/linux/generic/backport-6.6/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch +++ /dev/null @@ -1,192 +0,0 @@ -From: Felix Fietkau -Date: Fri, 28 Oct 2022 11:01:12 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix VLAN rx hardware - acceleration - -- enable VLAN untagging for PDMA rx -- make it possible to disable the feature via ethtool -- pass VLAN tag to the DSA driver -- untag special tag on PDMA only if no non-DSA devices are in use -- disable special tag untagging on 7986 for now, since it's not working yet - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "mtk_eth_soc.h" - #include "mtk_wed.h" -@@ -2021,16 +2022,22 @@ static int mtk_poll_rx(struct napi_struc - htons(RX_DMA_VPID(trxd.rxd4)), - RX_DMA_VID(trxd.rxd4)); - } else if (trxd.rxd2 & RX_DMA_VTAG) { -- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), -+ __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), - RX_DMA_VID(trxd.rxd3)); - } -+ } -+ -+ /* When using VLAN untagging in combination with DSA, the -+ * hardware treats the MTK special tag as a VLAN and untags it. -+ */ -+ if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { -+ unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); - -- /* If the device is attached to a dsa switch, the special -- * tag inserted in VLAN field by hw switch can * be offloaded -- * by RX HW VLAN offload. Clear vlan info. -- */ -- if (netdev_uses_dsa(netdev)) -- __vlan_hwaccel_clear_tag(skb); -+ if (port < ARRAY_SIZE(eth->dsa_meta) && -+ eth->dsa_meta[port]) -+ skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -+ -+ __vlan_hwaccel_clear_tag(skb); - } - - skb_record_rx_queue(skb, 0); -@@ -2858,15 +2865,30 @@ static netdev_features_t mtk_fix_feature - - static int mtk_set_features(struct net_device *dev, netdev_features_t features) - { -- int err = 0; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ netdev_features_t diff = dev->features ^ features; -+ int i; -+ -+ if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) -+ mtk_hwlro_netdev_disable(dev); - -- if (!((dev->features ^ features) & NETIF_F_LRO)) -+ /* Set RX VLAN offloading */ -+ if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) - return 0; - -- if (!(features & NETIF_F_LRO)) -- mtk_hwlro_netdev_disable(dev); -+ mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), -+ MTK_CDMP_EG_CTRL); - -- return err; -+ /* sync features with other MAC */ -+ for (i = 0; i < MTK_MAC_COUNT; i++) { -+ if (!eth->netdev[i] || eth->netdev[i] == dev) -+ continue; -+ eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; -+ eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; -+ } -+ -+ return 0; - } - - /* wait for DMA to finish whatever it is doing before we start using it again */ -@@ -3163,11 +3185,45 @@ found: - return NOTIFY_DONE; - } - -+static bool mtk_uses_dsa(struct net_device *dev) -+{ -+#if IS_ENABLED(CONFIG_NET_DSA) -+ return netdev_uses_dsa(dev) && -+ dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_MTK; -+#else -+ return false; -+#endif -+} -+ - static int mtk_open(struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; -- int err; -+ int i, err; -+ -+ if (mtk_uses_dsa(dev) && !eth->prog) { -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ struct metadata_dst *md_dst = eth->dsa_meta[i]; -+ -+ if (md_dst) -+ continue; -+ -+ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -+ GFP_KERNEL); -+ if (!md_dst) -+ return -ENOMEM; -+ -+ md_dst->u.port_info.port_id = i; -+ eth->dsa_meta[i] = md_dst; -+ } -+ } else { -+ /* Hardware special tag parsing needs to be disabled if at least -+ * one MAC does not use DSA. -+ */ -+ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ val &= ~MTK_CDMP_STAG_EN; -+ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -+ } - - err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); - if (err) { -@@ -3688,6 +3744,10 @@ 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)) { -+ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); -+ } - - /* Enable RX VLan Offloading */ - mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -@@ -3907,6 +3967,12 @@ static int mtk_free_dev(struct mtk_eth * - free_netdev(eth->netdev[i]); - } - -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ if (!eth->dsa_meta[i]) -+ break; -+ metadata_dst_free(eth->dsa_meta[i]); -+ } -+ - return 0; - } - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -22,6 +22,9 @@ - #include - #include "mtk_ppe.h" - -+#define MTK_MAX_DSA_PORTS 7 -+#define MTK_DSA_PORT_MASK GENMASK(2, 0) -+ - #define MTK_QDMA_NUM_QUEUES 16 - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 -@@ -105,6 +108,9 @@ - #define MTK_CDMQ_IG_CTRL 0x1400 - #define MTK_CDMQ_STAG_EN BIT(0) - -+/* CDMQ Exgress Control Register */ -+#define MTK_CDMQ_EG_CTRL 0x1404 -+ - /* CDMP Ingress Control Register */ - #define MTK_CDMP_IG_CTRL 0x400 - #define MTK_CDMP_STAG_EN BIT(0) -@@ -1164,6 +1170,8 @@ struct mtk_eth { - - int ip_align; - -+ struct metadata_dst *dsa_meta[MTK_MAX_DSA_PORTS]; -+ - struct mtk_ppe *ppe[2]; - struct rhashtable flow_table; - diff --git a/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch b/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch deleted file mode 100644 index a88df2b8e3..0000000000 --- a/target/linux/generic/backport-6.6/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sat, 28 Jan 2023 12:42:32 +0300 -Subject: [PATCH] net: ethernet: mtk_eth_soc: disable hardware DSA untagging - for second MAC -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -According to my tests on MT7621AT and MT7623NI SoCs, hardware DSA untagging -won't work on the second MAC. Therefore, disable this feature when the -second MAC of the MT7621 and MT7623 SoCs is being used. - -Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") -Link: https://lore.kernel.org/netdev/6249fc14-b38a-c770-36b4-5af6d41c21d3@arinc9.com/ -Tested-by: Arınç ÜNAL -Signed-off-by: Arınç ÜNAL -Link: https://lore.kernel.org/r/20230128094232.2451947-1-arinc.unal@arinc9.com -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3201,7 +3201,8 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if (mtk_uses_dsa(dev) && !eth->prog) { -+ if ((mtk_uses_dsa(dev) && !eth->prog) && -+ !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { - for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { - struct metadata_dst *md_dst = eth->dsa_meta[i]; - -@@ -3218,7 +3219,8 @@ static int mtk_open(struct net_device *d - } - } else { - /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA. -+ * one MAC does not use DSA, or the second MAC of the MT7621 and -+ * MT7623 SoCs is being used. - */ - u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch b/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch deleted file mode 100644 index 8da728b9e9..0000000000 --- a/target/linux/generic/backport-6.6/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sun, 5 Feb 2023 20:53:31 +0300 -Subject: [PATCH] net: ethernet: mtk_eth_soc: enable special tag when any MAC - uses DSA -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The special tag is only enabled when the first MAC uses DSA. However, it -must be enabled when any MAC uses DSA. Change the check accordingly. - -This fixes hardware DSA untagging not working on the second MAC of the -MT7621 and MT7623 SoCs, and likely other SoCs too. Therefore, remove the -check that disables hardware DSA untagging for the second MAC of the MT7621 -and MT7623 SoCs. - -Fixes: a1f47752fd62 ("net: ethernet: mtk_eth_soc: disable hardware DSA untagging for second MAC") -Co-developed-by: Richard van Schagen -Signed-off-by: Richard van Schagen -Signed-off-by: Arınç ÜNAL -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3136,7 +3136,7 @@ static void mtk_gdm_config(struct mtk_et - - val |= config; - -- if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) -+ if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) - val |= MTK_GDMA_SPECIAL_TAG; - - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3201,8 +3201,7 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if ((mtk_uses_dsa(dev) && !eth->prog) && -- !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) { -+ if (mtk_uses_dsa(dev) && !eth->prog) { - for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { - struct metadata_dst *md_dst = eth->dsa_meta[i]; - -@@ -3219,8 +3218,7 @@ static int mtk_open(struct net_device *d - } - } else { - /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA, or the second MAC of the MT7621 and -- * MT7623 SoCs is being used. -+ * one MAC does not use DSA. - */ - u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - val &= ~MTK_CDMP_STAG_EN; diff --git a/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch b/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch deleted file mode 100644 index 51cd572ab2..0000000000 --- a/target/linux/generic/backport-6.6/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Vladimir Oltean -Date: Tue, 7 Feb 2023 12:30:27 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix DSA TX tag hwaccel for switch - port 0 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Arınç reports that on his MT7621AT Unielec U7621-06 board and MT7623NI -Bananapi BPI-R2, packets received by the CPU over mt7530 switch port 0 -(of which this driver acts as the DSA master) are not processed -correctly by software. More precisely, they arrive without a DSA tag -(in packet or in the hwaccel area - skb_metadata_dst()), so DSA cannot -demux them towards the switch's interface for port 0. Traffic from other -ports receives a skb_metadata_dst() with the correct port and is demuxed -properly. - -Looking at mtk_poll_rx(), it becomes apparent that this driver uses the -skb vlan hwaccel area: - - union { - u32 vlan_all; - struct { - __be16 vlan_proto; - __u16 vlan_tci; - }; - }; - -as a temporary storage for the VLAN hwaccel tag, or the DSA hwaccel tag. -If this is a DSA master it's a DSA hwaccel tag, and finally clears up -the skb VLAN hwaccel header. - -I'm guessing that the problem is the (mis)use of API. -skb_vlan_tag_present() looks like this: - - #define skb_vlan_tag_present(__skb) (!!(__skb)->vlan_all) - -So if both vlan_proto and vlan_tci are zeroes, skb_vlan_tag_present() -returns precisely false. I don't know for sure what is the format of the -DSA hwaccel tag, but I surely know that lowermost 3 bits of vlan_proto -are 0 when receiving from port 0: - - unsigned int port = vlan_proto & GENMASK(2, 0); - -If the RX descriptor has no other bits set to non-zero values in -RX_DMA_VTAG, then the call to __vlan_hwaccel_put_tag() will not, in -fact, make the subsequent skb_vlan_tag_present() return true, because -it's implemented like this: - -static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb, - __be16 vlan_proto, u16 vlan_tci) -{ - skb->vlan_proto = vlan_proto; - skb->vlan_tci = vlan_tci; -} - -What we need to do to fix this problem (assuming this is the problem) is -to stop using skb->vlan_all as temporary storage for driver affairs, and -just create some local variables that serve the same purpose, but -hopefully better. Instead of calling skb_vlan_tag_present(), let's look -at a boolean has_hwaccel_tag which we set to true when the RX DMA -descriptors have something. Disambiguate based on netdev_uses_dsa() -whether this is a VLAN or DSA hwaccel tag, and only call -__vlan_hwaccel_put_tag() if we're certain it's a VLAN tag. - -Arınç confirms that the treatment works, so this validates the -assumption. - -Link: https://lore.kernel.org/netdev/704f3a72-fc9e-714a-db54-272e17612637@arinc9.com/ -Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") -Reported-by: Arınç ÜNAL -Tested-by: Arınç ÜNAL -Signed-off-by: Vladimir Oltean -Reviewed-by: Felix Fietkau -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1877,7 +1877,9 @@ static int mtk_poll_rx(struct napi_struc - - while (done < budget) { - unsigned int pktlen, *rxdcsum; -+ bool has_hwaccel_tag = false; - struct net_device *netdev; -+ u16 vlan_proto, vlan_tci; - dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; -@@ -2017,27 +2019,29 @@ static int mtk_poll_rx(struct napi_struc - - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- if (trxd.rxd3 & RX_DMA_VTAG_V2) -- __vlan_hwaccel_put_tag(skb, -- htons(RX_DMA_VPID(trxd.rxd4)), -- RX_DMA_VID(trxd.rxd4)); -+ if (trxd.rxd3 & RX_DMA_VTAG_V2) { -+ vlan_proto = RX_DMA_VPID(trxd.rxd4); -+ vlan_tci = RX_DMA_VID(trxd.rxd4); -+ has_hwaccel_tag = true; -+ } - } else if (trxd.rxd2 & RX_DMA_VTAG) { -- __vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)), -- RX_DMA_VID(trxd.rxd3)); -+ vlan_proto = RX_DMA_VPID(trxd.rxd3); -+ vlan_tci = RX_DMA_VID(trxd.rxd3); -+ has_hwaccel_tag = true; - } - } - - /* When using VLAN untagging in combination with DSA, the - * hardware treats the MTK special tag as a VLAN and untags it. - */ -- if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) { -- unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0); -+ if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { -+ unsigned int port = vlan_proto & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && - eth->dsa_meta[port]) - skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -- -- __vlan_hwaccel_clear_tag(skb); -+ } else if (has_hwaccel_tag) { -+ __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); - } - - skb_record_rx_queue(skb, 0); diff --git a/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch b/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch deleted file mode 100644 index a3bb1c5db7..0000000000 --- a/target/linux/generic/backport-6.6/730-15-v6.3-net-ethernet-mtk_wed-No-need-to-clear-memory-after-a.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Christophe JAILLET -Date: Sun, 12 Feb 2023 07:51:51 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: No need to clear memory after a - dma_alloc_coherent() call - -dma_alloc_coherent() already clears the allocated memory, there is no need -to explicitly call memset(). - -Moreover, it is likely that the size in the memset() is incorrect and -should be "size * sizeof(*ring->desc)". - -Signed-off-by: Christophe JAILLET -Link: https://lore.kernel.org/r/d5acce7dd108887832c9719f62c7201b4c83b3fb.1676184599.git.christophe.jaillet@wanadoo.fr -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -779,7 +779,6 @@ mtk_wed_rro_ring_alloc(struct mtk_wed_de - - ring->desc_size = sizeof(*ring->desc); - ring->size = size; -- memset(ring->desc, 0, size); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch b/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch deleted file mode 100644 index e043a681da..0000000000 --- a/target/linux/generic/backport-6.6/730-16-v6.3-net-ethernet-mtk_wed-fix-some-possible-NULL-pointer-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From: Lorenzo Bianconi -Date: Wed, 7 Dec 2022 15:04:54 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix some possible NULL pointer - dereferences - -Fix possible NULL pointer dereference in mtk_wed_detach routine checking -wo pointer is properly allocated before running mtk_wed_wo_reset() and -mtk_wed_wo_deinit(). -Even if it is just a theoretical issue at the moment check wo pointer is -not NULL in mtk_wed_mcu_msg_update. -Moreover, honor mtk_wed_mcu_send_msg return value in mtk_wed_wo_reset() - -Fixes: 799684448e3e ("net: ethernet: mtk_wed: introduce wed wo support") -Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -174,9 +174,10 @@ mtk_wed_wo_reset(struct mtk_wed_device * - mtk_wdma_tx_reset(dev); - mtk_wed_reset(dev, MTK_WED_RESET_WED); - -- mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -- MTK_WED_WO_CMD_CHANGE_STATE, &state, -- sizeof(state), false); -+ if (mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -+ MTK_WED_WO_CMD_CHANGE_STATE, &state, -+ sizeof(state), false)) -+ return; - - if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val, - val == MTK_WED_WOIF_DISABLE_DONE, -@@ -632,9 +633,11 @@ mtk_wed_detach(struct mtk_wed_device *de - mtk_wed_free_tx_rings(dev); - - if (mtk_wed_get_rx_capa(dev)) { -- mtk_wed_wo_reset(dev); -+ if (hw->wed_wo) -+ mtk_wed_wo_reset(dev); - mtk_wed_free_rx_rings(dev); -- mtk_wed_wo_deinit(hw); -+ if (hw->wed_wo) -+ mtk_wed_wo_deinit(hw); - } - - if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) { ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -207,6 +207,9 @@ int mtk_wed_mcu_msg_update(struct mtk_we - if (dev->hw->version == 1) - return 0; - -+ if (WARN_ON(!wo)) -+ return -ENODEV; -+ - return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, - true); - } diff --git a/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch b/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch deleted file mode 100644 index 0afe7106e5..0000000000 --- a/target/linux/generic/backport-6.6/730-17-v6.3-net-ethernet-mtk_wed-fix-possible-deadlock-if-mtk_we.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Lorenzo Bianconi -Date: Wed, 7 Dec 2022 15:04:55 +0100 -Subject: [PATCH] net: ethernet: mtk_wed: fix possible deadlock if - mtk_wed_wo_init fails - -Introduce __mtk_wed_detach() in order to avoid a deadlock in -mtk_wed_attach routine if mtk_wed_wo_init fails since both -mtk_wed_attach and mtk_wed_detach run holding hw_lock mutex. - -Fixes: 4c5de09eb0d0 ("net: ethernet: mtk_wed: add configure wed wo support") -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Leon Romanovsky -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -619,12 +619,10 @@ mtk_wed_deinit(struct mtk_wed_device *de - } - - static void --mtk_wed_detach(struct mtk_wed_device *dev) -+__mtk_wed_detach(struct mtk_wed_device *dev) - { - struct mtk_wed_hw *hw = dev->hw; - -- mutex_lock(&hw_lock); -- - mtk_wed_deinit(dev); - - mtk_wdma_rx_reset(dev); -@@ -657,6 +655,13 @@ mtk_wed_detach(struct mtk_wed_device *de - module_put(THIS_MODULE); - - hw->wed_dev = NULL; -+} -+ -+static void -+mtk_wed_detach(struct mtk_wed_device *dev) -+{ -+ mutex_lock(&hw_lock); -+ __mtk_wed_detach(dev); - mutex_unlock(&hw_lock); - } - -@@ -1538,8 +1543,10 @@ mtk_wed_attach(struct mtk_wed_device *de - ret = mtk_wed_wo_init(hw); - } - out: -- if (ret) -- mtk_wed_detach(dev); -+ if (ret) { -+ dev_err(dev->hw->dev, "failed to attach wed device\n"); -+ __mtk_wed_detach(dev); -+ } - unlock: - mutex_unlock(&hw_lock); - diff --git a/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch b/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch deleted file mode 100644 index ca5b6b3a3e..0000000000 --- a/target/linux/generic/backport-6.6/730-18-v6.3-net-ethernet-mtk_eth_soc-fix-tx-throughput-regressio.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Felix Fietkau -Date: Fri, 24 Mar 2023 14:56:58 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix tx throughput regression with - direct 1G links - -Using the QDMA tx scheduler to throttle tx to line speed works fine for -switch ports, but apparently caused a regression on non-switch ports. - -Based on a number of tests, it seems that this throttling can be safely -dropped without re-introducing the issues on switch ports that the -tx scheduling changes resolved. - -Link: https://lore.kernel.org/netdev/trinity-92c3826f-c2c8-40af-8339-bc6d0d3ffea4-1678213958520@3c-app-gmx-bs16/ -Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") -Reported-by: Frank Wunderlich -Reported-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -719,8 +719,6 @@ static void mtk_mac_link_up(struct phyli - break; - } - -- mtk_set_queue_speed(mac->hw, mac->id, speed); -- - /* Configure duplex */ - if (duplex == DUPLEX_FULL) - mcr |= MAC_MCR_FORCE_DPX; diff --git a/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch b/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch deleted file mode 100644 index 850b806410..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-02-net-mtk_eth_soc-add-definitions-for-PCS.patch +++ /dev/null @@ -1,55 +0,0 @@ -From b6a709cb51f7bdc55c01cec886098a9753ce8c28 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:42 +0100 -Subject: [PATCH 01/10] net: mtk_eth_soc: add definitions for PCS - -As a result of help from Frank Wunderlich to investigate and test, we -know a bit more about the PCS on the Mediatek platforms. Update the -definitions from this investigation. - -This PCS appears similar, but not identical to the Lynx PCS. - -Although not included in this patch, but for future reference, the PHY -ID registers at offset 4 read as 0x4d544950 'MTIP'. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -504,8 +504,10 @@ - #define ETHSYS_DMA_AG_MAP_PPE BIT(2) - - /* SGMII subsystem config registers */ --/* Register to auto-negotiation restart */ -+/* BMCR (low 16) BMSR (high 16) */ - #define SGMSYS_PCS_CONTROL_1 0x0 -+#define SGMII_BMCR GENMASK(15, 0) -+#define SGMII_BMSR GENMASK(31, 16) - #define SGMII_AN_RESTART BIT(9) - #define SGMII_ISOLATE BIT(10) - #define SGMII_AN_ENABLE BIT(12) -@@ -515,13 +517,18 @@ - #define SGMII_PCS_FAULT BIT(23) - #define SGMII_AN_EXPANSION_CLR BIT(30) - -+#define SGMSYS_PCS_ADVERTISE 0x8 -+#define SGMII_ADVERTISE GENMASK(15, 0) -+#define SGMII_LPA GENMASK(31, 16) -+ - /* Register to programmable link timer, the unit in 2 * 8ns */ - #define SGMSYS_PCS_LINK_TIMER 0x18 --#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0)) -+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) -+#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) - - /* Register to control remote fault */ - #define SGMSYS_SGMII_MODE 0x20 --#define SGMII_IF_MODE_BIT0 BIT(0) -+#define SGMII_IF_MODE_SGMII BIT(0) - #define SGMII_SPEED_DUPLEX_AN BIT(1) - #define SGMII_SPEED_MASK GENMASK(3, 2) - #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) diff --git a/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch b/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch deleted file mode 100644 index 4ea428c9d6..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-03-net-mtk_eth_soc-eliminate-unnecessary-error-handling.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 5cf7797526ee81bea0f627bccaa3d887f48f53e0 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:47 +0100 -Subject: [PATCH 02/10] net: mtk_eth_soc: eliminate unnecessary error handling - -The functions called by the pcs_config() method always return zero, so -there is no point trying to handle an error from these functions. Make -these functions void, eliminate the "err" variable and simply return -zero from the pcs_config() function itself. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -20,7 +20,7 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st - } - - /* For SGMII interface mode */ --static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) -+static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { - unsigned int val; - -@@ -39,16 +39,13 @@ static int mtk_pcs_setup_mode_an(struct - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); - val &= ~SGMII_PHYA_PWD; - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -- -- return 0; -- - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a - * fixed speed. - */ --static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -- phy_interface_t interface) -+static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -+ phy_interface_t interface) - { - unsigned int val; - -@@ -73,8 +70,6 @@ static int mtk_pcs_setup_mode_force(stru - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); - val &= ~SGMII_PHYA_PWD; - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -- -- return 0; - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -83,15 +78,14 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- int err = 0; - - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) -- err = mtk_pcs_setup_mode_force(mpcs, interface); -+ mtk_pcs_setup_mode_force(mpcs, interface); - else if (phylink_autoneg_inband(mode)) -- err = mtk_pcs_setup_mode_an(mpcs); -+ mtk_pcs_setup_mode_an(mpcs); - -- return err; -+ return 0; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch b/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch deleted file mode 100644 index 64a4a72fa6..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-04-net-mtk_eth_soc-add-pcs_get_state-implementation.patch +++ /dev/null @@ -1,46 +0,0 @@ -From c000dca098002da193b98099df051c9ead0cacb4 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:52 +0100 -Subject: [PATCH 03/10] net: mtk_eth_soc: add pcs_get_state() implementation - -Add a pcs_get_state() implementation which uses the advertisements -to compute the resulting link modes, and BMSR contents to determine -negotiation and link status. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -19,6 +19,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st - return container_of(pcs, struct mtk_pcs, pcs); - } - -+static void mtk_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int bm, adv; -+ -+ /* Read the BMSR and LPA */ -+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -+ -+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -+ FIELD_GET(SGMII_LPA, adv)); -+} -+ - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -@@ -117,6 +131,7 @@ static void mtk_pcs_link_up(struct phyli - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { -+ .pcs_get_state = mtk_pcs_get_state, - .pcs_config = mtk_pcs_config, - .pcs_an_restart = mtk_pcs_restart_an, - .pcs_link_up = mtk_pcs_link_up, diff --git a/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch b/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch deleted file mode 100644 index 24610fe11e..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-05-net-mtk_eth_soc-convert-mtk_sgmii-to-use-regmap_upda.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0d2351dc2768061689abd4de1529fa206bbd574e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:10:58 +0100 -Subject: [PATCH 04/10] net: mtk_eth_soc: convert mtk_sgmii to use - regmap_update_bits() - -mtk_sgmii does a lot of read-modify-write operations, for which there -is a specific regmap function. Use this function instead of open-coding -the operations. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 61 ++++++++++------------- - 1 file changed, 26 insertions(+), 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -36,23 +36,18 @@ static void mtk_pcs_get_state(struct phy - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -- unsigned int val; -- - /* Setup the link timer and QPHY power up inside SGMIISYS */ - regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, - SGMII_LINK_TIMER_DEFAULT); - -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val |= SGMII_REMOTE_FAULT_DIS; -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -- -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val |= SGMII_AN_RESTART; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -- -- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); -- val &= ~SGMII_PHYA_PWD; -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART, SGMII_AN_RESTART); -+ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -@@ -61,29 +56,26 @@ static void mtk_pcs_setup_mode_an(struct - static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, - phy_interface_t interface) - { -- unsigned int val; -+ unsigned int rgc3; - -- regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); -- val &= ~RG_PHY_SPEED_MASK; - if (interface == PHY_INTERFACE_MODE_2500BASEX) -- val |= RG_PHY_SPEED_3_125G; -- regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); -+ rgc3 = RG_PHY_SPEED_3_125G; -+ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); - - /* Disable SGMII AN */ -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val &= ~SGMII_AN_ENABLE; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_ENABLE, 0); - - /* Set the speed etc but leave the duplex unchanged */ -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; -- val |= SGMII_SPEED_1000; -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, -+ SGMII_SPEED_1000); - - /* Release PHYA power down state */ -- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); -- val &= ~SGMII_PHYA_PWD; -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -105,29 +97,28 @@ static int mtk_pcs_config(struct phylink - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int val; - -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); -- val |= SGMII_AN_RESTART; -- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART, SGMII_AN_RESTART); - } - - static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, int speed, int duplex) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int val; -+ unsigned int sgm_mode; - - if (!phy_interface_mode_is_8023z(interface)) - return; - - /* SGMII force duplex setting */ -- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); -- val &= ~SGMII_DUPLEX_FULL; - if (duplex == DUPLEX_FULL) -- val |= SGMII_DUPLEX_FULL; -+ sgm_mode = SGMII_DUPLEX_FULL; -+ else -+ sgm_mode = 0; - -- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_FULL, sgm_mode); - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch b/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch deleted file mode 100644 index ba76ca40ff..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-06-net-mtk_eth_soc-add-out-of-band-forcing-of-speed-and.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 12198c3a410fe69843e335c1bbf6d4c2a4d48e4e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:03 +0100 -Subject: [PATCH 05/10] net: mtk_eth_soc: add out of band forcing of speed and - duplex in pcs_link_up - -Add support for forcing the link speed and duplex setting in the -pcs_link_up() method for out of band modes, which will be useful when -we finish converting the pcs_config() method. Until then, we still have -to force duplex for 802.3z modes to work correctly. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 28 ++++++++++++++--------- - 1 file changed, 17 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -108,17 +108,23 @@ static void mtk_pcs_link_up(struct phyli - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int sgm_mode; - -- if (!phy_interface_mode_is_8023z(interface)) -- return; -+ if (!phylink_autoneg_inband(mode) || -+ phy_interface_mode_is_8023z(interface)) { -+ /* Force the speed and duplex setting */ -+ if (speed == SPEED_10) -+ sgm_mode = SGMII_SPEED_10; -+ else if (speed == SPEED_100) -+ sgm_mode = SGMII_SPEED_100; -+ else -+ sgm_mode = SGMII_SPEED_1000; - -- /* SGMII force duplex setting */ -- if (duplex == DUPLEX_FULL) -- sgm_mode = SGMII_DUPLEX_FULL; -- else -- sgm_mode = 0; -+ if (duplex == DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_FULL; - -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_FULL, sgm_mode); -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, -+ sgm_mode); -+ } - } - - static const struct phylink_pcs_ops mtk_pcs_ops = { diff --git a/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch b/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch deleted file mode 100644 index b76e159275..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-07-net-mtk_eth_soc-move-PHY-power-up.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6f38fffe2179dd29612aea2c67c46ed6682b4e46 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:08 +0100 -Subject: [PATCH 06/10] net: mtk_eth_soc: move PHY power up - -The PHY power up is common to both configuration paths, so move it into -the parent function. We need to do this for all serdes modes. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -45,9 +45,6 @@ static void mtk_pcs_setup_mode_an(struct - - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_RESTART, SGMII_AN_RESTART); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); - } - - /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -@@ -72,10 +69,6 @@ static void mtk_pcs_setup_mode_force(str - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, - SGMII_SPEED_1000); -- -- /* Release PHYA power down state */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); - } - - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -91,6 +84,10 @@ static int mtk_pcs_config(struct phylink - else if (phylink_autoneg_inband(mode)) - mtk_pcs_setup_mode_an(mpcs); - -+ /* Release PHYA power down state */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, 0); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch b/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch deleted file mode 100644 index cd9f0699b3..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-08-net-mtk_eth_soc-move-interface-speed-selection.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f752c0df13dfeb721c11d3debb79f08cf437344f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:13 +0100 -Subject: [PATCH 07/10] net: mtk_eth_soc: move interface speed selection - -Move the selection of the underlying interface speed to the pcs_config -function, so we always program the interface speed. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++++++-------- - 1 file changed, 10 insertions(+), 8 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -53,14 +53,6 @@ static void mtk_pcs_setup_mode_an(struct - static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, - phy_interface_t interface) - { -- unsigned int rgc3; -- -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -- - /* Disable SGMII AN */ - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_ENABLE, 0); -@@ -77,6 +69,16 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int rgc3; -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = RG_PHY_SPEED_3_125G; -+ else -+ rgc3 = 0; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); - - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) diff --git a/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch b/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch deleted file mode 100644 index f08358e963..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-09-net-mtk_eth_soc-add-advertisement-programming.patch +++ /dev/null @@ -1,52 +0,0 @@ -From c125c66ea71b9377ae2478c4f1b87b180cc5c6ef Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:18 +0100 -Subject: [PATCH 08/10] net: mtk_eth_soc: add advertisement programming - -Program the advertisement into the mtk PCS block. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -70,16 +70,27 @@ static int mtk_pcs_config(struct phylink - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int rgc3; -+ int advertise; -+ bool changed; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; - else - rgc3 = 0; - -+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -+ advertising); -+ if (advertise < 0) -+ return advertise; -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); - -+ /* Update the advertisement, noting whether it has changed */ -+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -+ SGMII_ADVERTISE, advertise, &changed); -+ - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) - mtk_pcs_setup_mode_force(mpcs, interface); -@@ -90,7 +101,7 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, 0); - -- return 0; -+ return changed; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch b/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch deleted file mode 100644 index 602d52c6f4..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-10-net-mtk_eth_soc-move-and-correct-link-timer-programm.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3027d89f87707e7f3e5b683e0d37a32afb5bde96 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:23 +0100 -Subject: [PATCH 09/10] net: mtk_eth_soc: move and correct link timer - programming - -Program the link timer appropriately for the interface mode being -used, using the newly introduced phylink helper that provides the -nanosecond link timer interval. - -The intervals are 1.6ms for SGMII based protocols and 10ms for -802.3z based protocols. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -36,10 +36,6 @@ static void mtk_pcs_get_state(struct phy - /* For SGMII interface mode */ - static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) - { -- /* Setup the link timer and QPHY power up inside SGMIISYS */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, -- SGMII_LINK_TIMER_DEFAULT); -- - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); - -@@ -69,8 +65,8 @@ static int mtk_pcs_config(struct phylink - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ int advertise, link_timer; - unsigned int rgc3; -- int advertise; - bool changed; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) -@@ -83,6 +79,10 @@ static int mtk_pcs_config(struct phylink - if (advertise < 0) - return advertise; - -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); -@@ -91,6 +91,9 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, - SGMII_ADVERTISE, advertise, &changed); - -+ /* Setup the link timer and QPHY power up inside SGMIISYS */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -+ - /* Setup SGMIISYS with the determined property */ - if (interface != PHY_INTERFACE_MODE_SGMII) - mtk_pcs_setup_mode_force(mpcs, interface); diff --git a/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch b/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch deleted file mode 100644 index 0e9a0535a7..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-11-net-mtk_eth_soc-add-support-for-in-band-802.3z-negot.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 81b0f12a2a8a1699a7d49c3995e5f71e4ec018e6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 27 Oct 2022 14:11:28 +0100 -Subject: [PATCH 10/10] net: mtk_eth_soc: add support for in-band 802.3z - negotiation - -As a result of help from Frank Wunderlich to investigate and test, we -now know how to program this PCS for in-band 802.3z negotiation. Add -support for this by moving the contents of the two functions into the -common mtk_pcs_config() function and adding the register settings for -802.3z negotiation. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 77 ++++++++++++----------- - 1 file changed, 42 insertions(+), 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -33,41 +33,15 @@ static void mtk_pcs_get_state(struct phy - FIELD_GET(SGMII_LPA, adv)); - } - --/* For SGMII interface mode */ --static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) --{ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART, SGMII_AN_RESTART); --} -- --/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a -- * fixed speed. -- */ --static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, -- phy_interface_t interface) --{ -- /* Disable SGMII AN */ -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_ENABLE, 0); -- -- /* Set the speed etc but leave the duplex unchanged */ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL, -- SGMII_SPEED_1000); --} -- - static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -+ unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; -- unsigned int rgc3; -- bool changed; -+ bool changed, use_an; - - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; -@@ -83,6 +57,37 @@ static int mtk_pcs_config(struct phylink - if (link_timer < 0) - return link_timer; - -+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -+ * we assume that fixes it's speed at bitrate = line rate (in -+ * other words, 1000Mbps or 2500Mbps). -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII) { -+ sgm_mode = SGMII_IF_MODE_SGMII; -+ if (phylink_autoneg_inband(mode)) { -+ sgm_mode |= SGMII_REMOTE_FAULT_DIS | -+ SGMII_SPEED_DUPLEX_AN; -+ use_an = true; -+ } else { -+ use_an = false; -+ } -+ } else if (phylink_autoneg_inband(mode)) { -+ /* 1000base-X or 2500base-X autoneg */ -+ sgm_mode = SGMII_REMOTE_FAULT_DIS; -+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ advertising); -+ } else { -+ /* 1000base-X or 2500base-X without autoneg */ -+ sgm_mode = 0; -+ use_an = false; -+ } -+ -+ if (use_an) { -+ /* FIXME: Do we need to set AN_RESTART here? */ -+ bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; -+ } else { -+ bmcr = 0; -+ } -+ - /* Configure the underlying interface speed */ - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); -@@ -94,11 +99,14 @@ static int mtk_pcs_config(struct phylink - /* Setup the link timer and QPHY power up inside SGMIISYS */ - regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); - -- /* Setup SGMIISYS with the determined property */ -- if (interface != PHY_INTERFACE_MODE_SGMII) -- mtk_pcs_setup_mode_force(mpcs, interface); -- else if (phylink_autoneg_inband(mode)) -- mtk_pcs_setup_mode_an(mpcs); -+ /* Update the sgmsys mode register */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -+ SGMII_IF_MODE_SGMII, sgm_mode); -+ -+ /* Update the BMCR */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -+ SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); - - /* Release PHYA power down state */ - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -@@ -121,8 +129,7 @@ static void mtk_pcs_link_up(struct phyli - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int sgm_mode; - -- if (!phylink_autoneg_inband(mode) || -- phy_interface_mode_is_8023z(interface)) { -+ if (!phylink_autoneg_inband(mode)) { - /* Force the speed and duplex setting */ - if (speed == SPEED_10) - sgm_mode = SGMII_SPEED_10; diff --git a/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch b/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch deleted file mode 100644 index a02c583deb..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-12-net-mediatek-sgmii-ensure-the-SGMII-PHY-is-powered-d.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001 -From: Alexander Couzens -Date: Wed, 1 Feb 2023 19:23:29 +0100 -Subject: [PATCH 11/13] net: mediatek: sgmii: ensure the SGMII PHY is powered - down on configuration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The code expect the PHY to be in power down which is only true after reset. -Allow changes of the SGMII parameters more than once. - -Only power down when reconfiguring to avoid bouncing the link when there's -no reason to - based on code from Russell King. - -There are cases when the SGMII_PHYA_PWD register contains 0x9 which -prevents SGMII from working. The SGMII still shows link but no traffic -can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -taken from a good working state of the SGMII interface. - -Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC") -Suggested-by: Russell King (Oracle) -Signed-off-by: Alexander Couzens -[ bmork: rebased and squashed into one patch ] -Reviewed-by: Russell King (Oracle) -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 39 +++++++++++++++------ - 2 files changed, 30 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1067,11 +1067,13 @@ struct mtk_soc_data { - * @regmap: The register map pointing at the range used to setup - * SGMII modes - * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap -+ * @interface: Currently configured interface mode - * @pcs: Phylink PCS structure - */ - struct mtk_pcs { - struct regmap *regmap; - u32 ana_rgc3; -+ phy_interface_t interface; - struct phylink_pcs pcs; - }; - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink - int advertise, link_timer; - bool changed, use_an; - -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- else -- rgc3 = 0; -- - advertise = phylink_mii_c22_pcs_encode_advertisement(interface, - advertising); - if (advertise < 0) -@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink - bmcr = 0; - } - -- /* Configure the underlying interface speed */ -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -+ if (mpcs->interface != interface) { -+ /* PHYA power down */ -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -+ SGMII_PHYA_PWD, SGMII_PHYA_PWD); -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ rgc3 = RG_PHY_SPEED_3_125G; -+ else -+ rgc3 = 0; -+ -+ /* Configure the underlying interface speed */ -+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -+ RG_PHY_SPEED_3_125G, rgc3); -+ -+ mpcs->interface = interface; -+ } - - /* Update the advertisement, noting whether it has changed */ - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, - SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); - -- /* Release PHYA power down state */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, 0); -+ /* Release PHYA power down state -+ * Only removing bit SGMII_PHYA_PWD isn't enough. -+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -+ * prevents SGMII from working. The SGMII still shows link but no traffic -+ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -+ * taken from a good working state of the SGMII interface. -+ * Unknown how much the QPHY needs but it is racy without a sleep. -+ * Tested on mt7622 & mt7986. -+ */ -+ usleep_range(50, 100); -+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); - - return changed; - } -@@ -171,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - return PTR_ERR(ss->pcs[i].regmap); - - ss->pcs[i].pcs.ops = &mtk_pcs_ops; -+ ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; - } - - return 0; diff --git a/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch b/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch deleted file mode 100644 index a06298c0a9..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-13-net-mediatek-sgmii-fix-duplex-configuration.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 9d32637122de88f1ef614c29703f0e050cad342e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= -Date: Wed, 1 Feb 2023 19:23:30 +0100 -Subject: [PATCH 12/13] net: mediatek: sgmii: fix duplex configuration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The logic of the duplex bit is inverted. Setting it means half -duplex, not full duplex. - -Fix and rename macro to avoid confusion. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -534,7 +534,7 @@ - #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) - #define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) - #define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) --#define SGMII_DUPLEX_FULL BIT(4) -+#define SGMII_DUPLEX_HALF BIT(4) - #define SGMII_IF_MODE_BIT5 BIT(5) - #define SGMII_REMOTE_FAULT_DIS BIT(8) - #define SGMII_CODE_SYNC_SET_VAL BIT(9) ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -154,11 +154,11 @@ static void mtk_pcs_link_up(struct phyli - else - sgm_mode = SGMII_SPEED_1000; - -- if (duplex == DUPLEX_FULL) -- sgm_mode |= SGMII_DUPLEX_FULL; -+ if (duplex != DUPLEX_FULL) -+ sgm_mode |= SGMII_DUPLEX_HALF; - - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, -+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, - sgm_mode); - } - } diff --git a/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch b/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch deleted file mode 100644 index 56d7a1348f..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.2-14-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3337a6e04ddf2923a1bdcf3d31b3b52412bf82dd Mon Sep 17 00:00:00 2001 -From: Alexander Couzens -Date: Wed, 1 Feb 2023 19:23:31 +0100 -Subject: [PATCH 13/13] mtk_sgmii: enable PCS polling to allow SFP work -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently there is no IRQ handling (even the SGMII supports it). -Enable polling to support SFP ports. - -Fixes: 14a44ab0330d ("net: mtk_eth_soc: partially convert to phylink_pcs") -Reviewed-by: Russell King (Oracle) -Signed-off-by: Alexander Couzens -[ bmork: changed "1" => "true" ] -Signed-off-by: Bjørn Mork -Acked-by: Daniel Golle -Tested-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -187,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - return PTR_ERR(ss->pcs[i].regmap); - - ss->pcs[i].pcs.ops = &mtk_pcs_ops; -+ ss->pcs[i].pcs.poll = true; - ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; - } - diff --git a/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch b/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch deleted file mode 100644 index 6acc62d4ab..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-15-net-ethernet-mtk_eth_soc-reset-PCS-state.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 611e2dabb4b3243d176739fd6a5a34d007fa3f86 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 14 Mar 2023 00:34:26 +0000 -Subject: [PATCH 1/2] net: ethernet: mtk_eth_soc: reset PCS state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reset the internal PCS state machine when changing interface mode. -This prevents confusing the state machine when changing interface -modes, e.g. from SGMII to 2500Base-X or vice-versa. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -542,6 +542,10 @@ - #define SGMII_SEND_AN_ERROR_EN BIT(11) - #define SGMII_IF_MODE_MASK GENMASK(5, 1) - -+/* Register to reset SGMII design */ -+#define SGMII_RESERVED_0 0x34 -+#define SGMII_SW_RESET BIT(0) -+ - /* Register to set SGMII speed, ANA RG_ Control Signals III*/ - #define SGMSYS_ANA_RG_CS3 0x2028 - #define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -88,6 +88,10 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); - -+ /* Reset SGMII PCS state */ -+ regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, -+ SGMII_SW_RESET, SGMII_SW_RESET); -+ - if (interface == PHY_INTERFACE_MODE_2500BASEX) - rgc3 = RG_PHY_SPEED_3_125G; - else diff --git a/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch b/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch deleted file mode 100644 index 0fabeea20c..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-16-net-ethernet-mtk_eth_soc-only-write-values-if-needed.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 6e933a804c7db8be64f367f33e63cd7dcc302ebb Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 14 Mar 2023 00:34:45 +0000 -Subject: [PATCH 2/2] net: ethernet: mtk_eth_soc: only write values if needed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Only restart auto-negotiation and write link timer if actually -necessary. This prevents losing the link in case of minor -changes. - -Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII") -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 24 +++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink - const unsigned long *advertising, - bool permit_pause_to_mac) - { -+ bool mode_changed = false, changed, use_an; - struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); - unsigned int rgc3, sgm_mode, bmcr; - int advertise, link_timer; -- bool changed, use_an; - - advertise = phylink_mii_c22_pcs_encode_advertisement(interface, - advertising); - if (advertise < 0) - return advertise; - -- link_timer = phylink_get_link_timer_ns(interface); -- if (link_timer < 0) -- return link_timer; -- - /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and - * we assume that fixes it's speed at bitrate = line rate (in - * other words, 1000Mbps or 2500Mbps). -@@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink - } - - if (use_an) { -- /* FIXME: Do we need to set AN_RESTART here? */ -- bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE; -+ bmcr = SGMII_AN_ENABLE; - } else { - bmcr = 0; - } - - if (mpcs->interface != interface) { -+ link_timer = phylink_get_link_timer_ns(interface); -+ if (link_timer < 0) -+ return link_timer; -+ - /* PHYA power down */ - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); -@@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, - RG_PHY_SPEED_3_125G, rgc3); - -+ /* Setup the link timer */ -+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -+ - mpcs->interface = interface; -+ mode_changed = true; - } - - /* Update the advertisement, noting whether it has changed */ - regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, - SGMII_ADVERTISE, advertise, &changed); - -- /* Setup the link timer and QPHY power up inside SGMIISYS */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -- - /* Update the sgmsys mode register */ - regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, - SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -@@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink - - /* Update the BMCR */ - regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); -+ SGMII_AN_ENABLE, bmcr); - - /* Release PHYA power down state - * Only removing bit SGMII_PHYA_PWD isn't enough. -@@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink - usleep_range(50, 100); - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); - -- return changed; -+ return changed || mode_changed; - } - - static void mtk_pcs_restart_an(struct phylink_pcs *pcs) diff --git a/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch deleted file mode 100644 index a1247218b0..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch +++ /dev/null @@ -1,206 +0,0 @@ -From f5d43ddd334b7c32fcaed9ba46afbd85cb467f1f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:56:28 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for MT7981 SoC - -The MediaTek MT7981 SoC comes with two 1G/2.5G SGMII ports, just like -MT7986. - -In addition MT7981 is equipped with a built-in 1000Base-T PHY which can -be used with GMAC1. - -As many MT7981 boards make use of inverting SGMII signal polarity, add -new device-tree attribute 'mediatek,pn_swap' to support them. - -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 31 ++++++++++++++++++++ - drivers/net/ethernet/mediatek/mtk_sgmii.c | 10 +++++++ - 4 files changed, 73 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_path.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c -@@ -96,12 +96,20 @@ static int set_mux_gmac2_gmac0_to_gephy( - - static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) - { -- unsigned int val = 0; -+ unsigned int val = 0, mask = 0, reg = 0; - bool updated = true; - - switch (path) { - case MTK_ETH_PATH_GMAC2_SGMII: -- val = CO_QPHY_SEL; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) { -+ reg = USB_PHY_SWITCH_REG; -+ val = SGMII_QPHY_SEL; -+ mask = QPHY_SEL_MASK; -+ } else { -+ reg = INFRA_MISC2; -+ val = CO_QPHY_SEL; -+ mask = val; -+ } - break; - default: - updated = false; -@@ -109,7 +117,7 @@ static int set_mux_u3_gmac2_to_qphy(stru - } - - if (updated) -- regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val); -+ regmap_update_bits(eth->infra, reg, mask, val); - - dev_dbg(eth->dev, "path %s in %s updated = %d\n", - mtk_eth_path_name(path), __func__, updated); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4803,6 +4803,26 @@ static const struct mtk_soc_data mt7629_ - }, - }; - -+static const struct mtk_soc_data mt7981_data = { -+ .reg_map = &mt7986_reg_map, -+ .ana_rgc3 = 0x128, -+ .caps = MT7981_CAPS, -+ .hw_features = MTK_HW_FEATURES, -+ .required_clks = MT7981_CLKS_BITMAP, -+ .required_pctl = false, -+ .offload_version = 2, -+ .hash_offset = 4, -+ .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .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 mt7986_data = { - .reg_map = &mt7986_reg_map, - .ana_rgc3 = 0x128, -@@ -4845,6 +4865,7 @@ const struct of_device_id of_mtk_match[] - { .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}, - {}, ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -556,11 +556,22 @@ - #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 - #define SGMII_PHYA_PWD BIT(4) - -+/* Register to QPHY wrapper control */ -+#define SGMSYS_QPHY_WRAP_CTRL 0xec -+#define SGMII_PN_SWAP_MASK GENMASK(1, 0) -+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) -+#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -+ - /* Infrasys subsystem config registers */ - #define INFRA_MISC2 0x70c - #define CO_QPHY_SEL BIT(0) - #define GEPHY_MAC_SEL BIT(1) - -+/* Top misc registers */ -+#define USB_PHY_SWITCH_REG 0x218 -+#define QPHY_SEL_MASK GENMASK(1, 0) -+#define SGMII_QPHY_SEL 0x2 -+ - /* MT7628/88 specific stuff */ - #define MT7628_PDMA_OFFSET 0x0800 - #define MT7628_SDM_OFFSET 0x0c00 -@@ -741,6 +752,17 @@ enum mtk_clks_map { - 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) | \ -@@ -854,6 +876,7 @@ enum mkt_eth_capabilities { - MTK_NETSYS_V2_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, -+ MTK_U3_COPHY_V2_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -888,6 +911,7 @@ enum mkt_eth_capabilities { - #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) -+#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -960,6 +984,11 @@ enum mkt_eth_capabilities { - MTK_MUX_U3_GMAC2_TO_QPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA) - -+#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ -+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ -+ 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) -@@ -1073,12 +1102,14 @@ struct mtk_soc_data { - * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap - * @interface: Currently configured interface mode - * @pcs: Phylink PCS structure -+ * @flags: Flags indicating hardware properties - */ - struct mtk_pcs { - struct regmap *regmap; - u32 ana_rgc3; - phy_interface_t interface; - struct phylink_pcs pcs; -+ u32 flags; - }; - - /* struct mtk_sgmii - This is the structure holding sgmii regmap and its ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -87,6 +87,11 @@ static int mtk_pcs_config(struct phylink - regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, - SGMII_PHYA_PWD, SGMII_PHYA_PWD); - -+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -+ SGMII_PN_SWAP_MASK, -+ SGMII_PN_SWAP_TX_RX); -+ - /* Reset SGMII PCS state */ - regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, - SGMII_SW_RESET, SGMII_SW_RESET); -@@ -186,6 +191,11 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, - - ss->pcs[i].ana_rgc3 = ana_rgc3; - ss->pcs[i].regmap = syscon_node_to_regmap(np); -+ -+ ss->pcs[i].flags = 0; -+ if (of_property_read_bool(np, "mediatek,pnswap")) -+ ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; -+ - of_node_put(np); - if (IS_ERR(ss->pcs[i].regmap)) - return PTR_ERR(ss->pcs[i].regmap); diff --git a/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch b/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch deleted file mode 100644 index 1cb1f40538..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c0a440031d4314d1023c1b87f43a4233634eebdb Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:15 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: set MDIO bus clock frequency -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Set MDIO bus clock frequency and allow setting a custom maximum -frequency from device tree. - -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 +++++++ - 2 files changed, 28 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -744,8 +744,10 @@ static const struct phylink_mac_ops mtk_ - - static int mtk_mdio_init(struct mtk_eth *eth) - { -+ unsigned int max_clk = 2500000, divider; - struct device_node *mii_np; - int ret; -+ u32 val; - - mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus"); - if (!mii_np) { -@@ -772,6 +774,25 @@ static int mtk_mdio_init(struct mtk_eth - eth->mii_bus->parent = eth->dev; - - snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); -+ -+ if (!of_property_read_u32(mii_np, "clock-frequency", &val)) { -+ if (val > MDC_MAX_FREQ || val < MDC_MAX_FREQ / MDC_MAX_DIVIDER) { -+ dev_err(eth->dev, "MDIO clock frequency out of range"); -+ ret = -EINVAL; -+ goto err_put_node; -+ } -+ max_clk = val; -+ } -+ divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); -+ -+ /* Configure MDC Divider */ -+ val = mtk_r32(eth, MTK_PPSC); -+ val &= ~PPSC_MDC_CFG; -+ val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; -+ mtk_w32(eth, val, MTK_PPSC); -+ -+ dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); -+ - ret = of_mdiobus_register(eth->mii_bus, mii_np); - - err_put_node: ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -363,6 +363,13 @@ - #define RX_DMA_VTAG_V2 BIT(0) - #define RX_DMA_L4_VALID_V2 BIT(2) - -+/* PHY Polling and SMI Master Control registers */ -+#define MTK_PPSC 0x10000 -+#define PPSC_MDC_CFG GENMASK(29, 24) -+#define PPSC_MDC_TURBO BIT(20) -+#define MDC_MAX_FREQ 25000000 -+#define MDC_MAX_DIVIDER 63 -+ - /* PHY Indirect Access Control registers */ - #define MTK_PHY_IAC 0x10004 - #define PHY_IAC_ACCESS BIT(31) diff --git a/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch b/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch deleted file mode 100644 index 110944658d..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch +++ /dev/null @@ -1,512 +0,0 @@ -From 2a3ec7ae313310c1092e4256208cc04d1958e469 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:58:02 +0000 -Subject: [PATCH] net: ethernet: mtk_eth_soc: switch to external PCS driver - -Now that we got a PCS driver, use it and remove the now redundant -PCS code and it's header macros from the Ethernet driver. - -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich -Reviewed-by: Russell King (Oracle) -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/Kconfig | 2 + - drivers/net/ethernet/mediatek/Makefile | 2 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 61 +++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 93 +-------- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 217 -------------------- - 5 files changed, 56 insertions(+), 319 deletions(-) - delete mode 100644 drivers/net/ethernet/mediatek/mtk_sgmii.c - ---- a/drivers/net/ethernet/mediatek/Kconfig -+++ b/drivers/net/ethernet/mediatek/Kconfig -@@ -19,6 +19,8 @@ config NET_MEDIATEK_SOC - select DIMLIB - select PAGE_POOL - select PAGE_POOL_STATS -+ select PCS_MTK_LYNXI -+ select REGMAP_MMIO - help - This driver supports the gigabit ethernet MACs in the - MediaTek SoC family. ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -4,7 +4,7 @@ - # - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o --mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.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_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_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -400,7 +401,7 @@ static struct phylink_pcs *mtk_mac_selec - sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? - 0 : mac->id; - -- return mtk_sgmii_select_pcs(eth->sgmii, sid); -+ return eth->sgmii_pcs[sid]; - } - - return NULL; -@@ -4016,8 +4017,17 @@ static int mtk_unreg_dev(struct mtk_eth - return 0; - } - -+static void mtk_sgmii_destroy(struct mtk_eth *eth) -+{ -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) -+ mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]); -+} -+ - static int mtk_cleanup(struct mtk_eth *eth) - { -+ mtk_sgmii_destroy(eth); - mtk_unreg_dev(eth); - mtk_free_dev(eth); - cancel_work_sync(ð->pending_work); -@@ -4457,6 +4467,36 @@ void mtk_eth_set_dma_device(struct mtk_e - rtnl_unlock(); - } - -+static int mtk_sgmii_init(struct mtk_eth *eth) -+{ -+ struct device_node *np; -+ struct regmap *regmap; -+ u32 flags; -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i); -+ if (!np) -+ break; -+ -+ regmap = syscon_node_to_regmap(np); -+ flags = 0; -+ if (of_property_read_bool(np, "mediatek,pnswap")) -+ flags |= MTK_SGMII_FLAG_PN_SWAP; -+ -+ of_node_put(np); -+ -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, regmap, -+ eth->soc->ana_rgc3, -+ flags); -+ } -+ -+ return 0; -+} -+ - static int mtk_probe(struct platform_device *pdev) - { - struct resource *res = NULL; -@@ -4520,13 +4560,7 @@ static int mtk_probe(struct platform_dev - } - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { -- eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), -- GFP_KERNEL); -- if (!eth->sgmii) -- return -ENOMEM; -- -- err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node, -- eth->soc->ana_rgc3); -+ err = mtk_sgmii_init(eth); - - if (err) - return err; -@@ -4537,14 +4571,17 @@ static int mtk_probe(struct platform_dev - "mediatek,pctl"); - if (IS_ERR(eth->pctl)) { - dev_err(&pdev->dev, "no pctl regmap found\n"); -- return PTR_ERR(eth->pctl); -+ err = PTR_ERR(eth->pctl); -+ goto err_destroy_sgmii; - } - } - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!res) -- return -EINVAL; -+ if (!res) { -+ err = -EINVAL; -+ goto err_destroy_sgmii; -+ } - } - - if (eth->soc->offload_version) { -@@ -4703,6 +4740,8 @@ err_deinit_hw: - mtk_hw_deinit(eth); - err_wed_exit: - mtk_wed_exit(); -+err_destroy_sgmii: -+ mtk_sgmii_destroy(eth); - - return err; - } ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -510,65 +510,6 @@ - #define ETHSYS_DMA_AG_MAP_QDMA BIT(1) - #define ETHSYS_DMA_AG_MAP_PPE BIT(2) - --/* SGMII subsystem config registers */ --/* BMCR (low 16) BMSR (high 16) */ --#define SGMSYS_PCS_CONTROL_1 0x0 --#define SGMII_BMCR GENMASK(15, 0) --#define SGMII_BMSR GENMASK(31, 16) --#define SGMII_AN_RESTART BIT(9) --#define SGMII_ISOLATE BIT(10) --#define SGMII_AN_ENABLE BIT(12) --#define SGMII_LINK_STATYS BIT(18) --#define SGMII_AN_ABILITY BIT(19) --#define SGMII_AN_COMPLETE BIT(21) --#define SGMII_PCS_FAULT BIT(23) --#define SGMII_AN_EXPANSION_CLR BIT(30) -- --#define SGMSYS_PCS_ADVERTISE 0x8 --#define SGMII_ADVERTISE GENMASK(15, 0) --#define SGMII_LPA GENMASK(31, 16) -- --/* Register to programmable link timer, the unit in 2 * 8ns */ --#define SGMSYS_PCS_LINK_TIMER 0x18 --#define SGMII_LINK_TIMER_MASK GENMASK(19, 0) --#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK) -- --/* Register to control remote fault */ --#define SGMSYS_SGMII_MODE 0x20 --#define SGMII_IF_MODE_SGMII BIT(0) --#define SGMII_SPEED_DUPLEX_AN BIT(1) --#define SGMII_SPEED_MASK GENMASK(3, 2) --#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) --#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) --#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) --#define SGMII_DUPLEX_HALF BIT(4) --#define SGMII_IF_MODE_BIT5 BIT(5) --#define SGMII_REMOTE_FAULT_DIS BIT(8) --#define SGMII_CODE_SYNC_SET_VAL BIT(9) --#define SGMII_CODE_SYNC_SET_EN BIT(10) --#define SGMII_SEND_AN_ERROR_EN BIT(11) --#define SGMII_IF_MODE_MASK GENMASK(5, 1) -- --/* Register to reset SGMII design */ --#define SGMII_RESERVED_0 0x34 --#define SGMII_SW_RESET BIT(0) -- --/* Register to set SGMII speed, ANA RG_ Control Signals III*/ --#define SGMSYS_ANA_RG_CS3 0x2028 --#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3)) --#define RG_PHY_SPEED_1_25G 0x0 --#define RG_PHY_SPEED_3_125G BIT(2) -- --/* Register to power up QPHY */ --#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 --#define SGMII_PHYA_PWD BIT(4) -- --/* Register to QPHY wrapper control */ --#define SGMSYS_QPHY_WRAP_CTRL 0xec --#define SGMII_PN_SWAP_MASK GENMASK(1, 0) --#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) --#define MTK_SGMII_FLAG_PN_SWAP BIT(0) -- - /* Infrasys subsystem config registers */ - #define INFRA_MISC2 0x70c - #define CO_QPHY_SEL BIT(0) -@@ -1102,31 +1043,6 @@ struct mtk_soc_data { - /* currently no SoC has more than 2 macs */ - #define MTK_MAX_DEVS 2 - --/* struct mtk_pcs - This structure holds each sgmii regmap and associated -- * data -- * @regmap: The register map pointing at the range used to setup -- * SGMII modes -- * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap -- * @interface: Currently configured interface mode -- * @pcs: Phylink PCS structure -- * @flags: Flags indicating hardware properties -- */ --struct mtk_pcs { -- struct regmap *regmap; -- u32 ana_rgc3; -- phy_interface_t interface; -- struct phylink_pcs pcs; -- u32 flags; --}; -- --/* struct mtk_sgmii - This is the structure holding sgmii regmap and its -- * characteristics -- * @pcs Array of individual PCS structures -- */ --struct mtk_sgmii { -- struct mtk_pcs pcs[MTK_MAX_DEVS]; --}; -- - /* struct mtk_eth - This is the main datasructure for holding the state - * of the driver - * @dev: The device pointer -@@ -1146,6 +1062,7 @@ struct mtk_sgmii { - * MII modes - * @infra: The register map pointing at the range used to setup - * SGMII and GePHY path -+ * @sgmii_pcs: Pointers to mtk-pcs-lynxi phylink_pcs instances - * @pctl: The register map pointing at the range used to setup - * GMAC port drive/slew values - * @dma_refcnt: track how many netdevs are using the DMA engine -@@ -1186,8 +1103,8 @@ struct mtk_eth { - u32 msg_enable; - unsigned long sysclk; - struct regmap *ethsys; -- struct regmap *infra; -- struct mtk_sgmii *sgmii; -+ struct regmap *infra; -+ struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS]; - struct regmap *pctl; - bool hwlro; - refcount_t dma_refcnt; -@@ -1349,10 +1266,6 @@ void mtk_stats_update_mac(struct mtk_mac - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); - u32 mtk_r32(struct mtk_eth *eth, unsigned reg); - --struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id); --int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, -- u32 ana_rgc3); -- - int mtk_gmac_sgmii_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); ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ /dev/null -@@ -1,217 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --// Copyright (c) 2018-2019 MediaTek Inc. -- --/* A library for MediaTek SGMII circuit -- * -- * Author: Sean Wang -- * -- */ -- --#include --#include --#include --#include -- --#include "mtk_eth_soc.h" -- --static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs) --{ -- return container_of(pcs, struct mtk_pcs, pcs); --} -- --static void mtk_pcs_get_state(struct phylink_pcs *pcs, -- struct phylink_link_state *state) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int bm, adv; -- -- /* Read the BMSR and LPA */ -- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm); -- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); -- -- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), -- FIELD_GET(SGMII_LPA, adv)); --} -- --static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertising, -- bool permit_pause_to_mac) --{ -- bool mode_changed = false, changed, use_an; -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int rgc3, sgm_mode, bmcr; -- int advertise, link_timer; -- -- advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -- advertising); -- if (advertise < 0) -- return advertise; -- -- /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and -- * we assume that fixes it's speed at bitrate = line rate (in -- * other words, 1000Mbps or 2500Mbps). -- */ -- if (interface == PHY_INTERFACE_MODE_SGMII) { -- sgm_mode = SGMII_IF_MODE_SGMII; -- if (phylink_autoneg_inband(mode)) { -- sgm_mode |= SGMII_REMOTE_FAULT_DIS | -- SGMII_SPEED_DUPLEX_AN; -- use_an = true; -- } else { -- use_an = false; -- } -- } else if (phylink_autoneg_inband(mode)) { -- /* 1000base-X or 2500base-X autoneg */ -- sgm_mode = SGMII_REMOTE_FAULT_DIS; -- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -- advertising); -- } else { -- /* 1000base-X or 2500base-X without autoneg */ -- sgm_mode = 0; -- use_an = false; -- } -- -- if (use_an) { -- bmcr = SGMII_AN_ENABLE; -- } else { -- bmcr = 0; -- } -- -- if (mpcs->interface != interface) { -- link_timer = phylink_get_link_timer_ns(interface); -- if (link_timer < 0) -- return link_timer; -- -- /* PHYA power down */ -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, -- SGMII_PHYA_PWD, SGMII_PHYA_PWD); -- -- if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP) -- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL, -- SGMII_PN_SWAP_MASK, -- SGMII_PN_SWAP_TX_RX); -- -- /* Reset SGMII PCS state */ -- regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0, -- SGMII_SW_RESET, SGMII_SW_RESET); -- -- if (interface == PHY_INTERFACE_MODE_2500BASEX) -- rgc3 = RG_PHY_SPEED_3_125G; -- else -- rgc3 = 0; -- -- /* Configure the underlying interface speed */ -- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, -- RG_PHY_SPEED_3_125G, rgc3); -- -- /* Setup the link timer */ -- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8); -- -- mpcs->interface = interface; -- mode_changed = true; -- } -- -- /* Update the advertisement, noting whether it has changed */ -- regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, -- SGMII_ADVERTISE, advertise, &changed); -- -- /* Update the sgmsys mode register */ -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN | -- SGMII_IF_MODE_SGMII, sgm_mode); -- -- /* Update the BMCR */ -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_ENABLE, bmcr); -- -- /* Release PHYA power down state -- * Only removing bit SGMII_PHYA_PWD isn't enough. -- * There are cases when the SGMII_PHYA_PWD register contains 0x9 which -- * prevents SGMII from working. The SGMII still shows link but no traffic -- * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was -- * taken from a good working state of the SGMII interface. -- * Unknown how much the QPHY needs but it is racy without a sleep. -- * Tested on mt7622 & mt7986. -- */ -- usleep_range(50, 100); -- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); -- -- return changed || mode_changed; --} -- --static void mtk_pcs_restart_an(struct phylink_pcs *pcs) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- -- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, -- SGMII_AN_RESTART, SGMII_AN_RESTART); --} -- --static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, int speed, int duplex) --{ -- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); -- unsigned int sgm_mode; -- -- if (!phylink_autoneg_inband(mode)) { -- /* Force the speed and duplex setting */ -- if (speed == SPEED_10) -- sgm_mode = SGMII_SPEED_10; -- else if (speed == SPEED_100) -- sgm_mode = SGMII_SPEED_100; -- else -- sgm_mode = SGMII_SPEED_1000; -- -- if (duplex != DUPLEX_FULL) -- sgm_mode |= SGMII_DUPLEX_HALF; -- -- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, -- SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, -- sgm_mode); -- } --} -- --static const struct phylink_pcs_ops mtk_pcs_ops = { -- .pcs_get_state = mtk_pcs_get_state, -- .pcs_config = mtk_pcs_config, -- .pcs_an_restart = mtk_pcs_restart_an, -- .pcs_link_up = mtk_pcs_link_up, --}; -- --int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) --{ -- struct device_node *np; -- int i; -- -- for (i = 0; i < MTK_MAX_DEVS; i++) { -- np = of_parse_phandle(r, "mediatek,sgmiisys", i); -- if (!np) -- break; -- -- ss->pcs[i].ana_rgc3 = ana_rgc3; -- ss->pcs[i].regmap = syscon_node_to_regmap(np); -- -- ss->pcs[i].flags = 0; -- if (of_property_read_bool(np, "mediatek,pnswap")) -- ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP; -- -- of_node_put(np); -- if (IS_ERR(ss->pcs[i].regmap)) -- return PTR_ERR(ss->pcs[i].regmap); -- -- ss->pcs[i].pcs.ops = &mtk_pcs_ops; -- ss->pcs[i].pcs.poll = true; -- ss->pcs[i].interface = PHY_INTERFACE_MODE_NA; -- } -- -- return 0; --} -- --struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id) --{ -- if (!ss->pcs[id].regmap) -- return NULL; -- -- return &ss->pcs[id].pcs; --} diff --git a/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch b/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch deleted file mode 100644 index 9ce2735951..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-21-net-mtk_eth_soc-use-WO-firmware-for-MT7981.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f5af7931d2a2cae66d0f9dad4ba517b1b00620b3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Apr 2023 19:07:23 +0100 -Subject: [PATCH] net: mtk_eth_soc: use WO firmware for MT7981 - -In order to support wireless offloading on MT7981 we need to load the -appropriate firmware. Recognize MT7981 and load mt7981_wo.bin. - -Signed-off-by: Daniel Golle ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 7 ++++++- - drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 + - 2 files changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -326,7 +326,11 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - wo->hw->index + 1); - - /* load firmware */ -- fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed")) -+ fw_name = MT7981_FIRMWARE_WO; -+ else -+ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; -+ - ret = request_firmware(&fw, fw_name, wo->hw->dev); - if (ret) - return ret; -@@ -386,5 +390,6 @@ int mtk_wed_mcu_init(struct mtk_wed_wo * - 100, MTK_FW_DL_TIMEOUT); - } - -+MODULE_FIRMWARE(MT7981_FIRMWARE_WO); - MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); - MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -88,6 +88,7 @@ enum mtk_wed_dummy_cr_idx { - MTK_WED_DUMMY_CR_WO_STATUS, - }; - -+#define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" - #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" - #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" - diff --git a/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch b/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch deleted file mode 100644 index d715c4aa68..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-22-net-ethernet-mtk_eth_soc-fix-NULL-pointer-dereferenc.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7c83e28f10830aa5105c25eaabe890e3adac36aa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 9 May 2023 03:20:06 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix NULL pointer dereference - -Check for NULL pointer to avoid kernel crashing in case of missing WO -firmware in case only a single WEDv2 device has been initialized, e.g. on -MT7981 which can connect just one wireless frontend. - -Fixes: 86ce0d09e424 ("net: ethernet: mtk_eth_soc: use WO firmware for MT7981") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -647,7 +647,7 @@ __mtk_wed_detach(struct mtk_wed_device * - BIT(hw->index), BIT(hw->index)); - } - -- if (!hw_list[!hw->index]->wed_dev && -+ if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) && - hw->eth->dma_dev != hw->eth->dev) - mtk_eth_set_dma_device(hw->eth, hw->eth->dev); - diff --git a/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch b/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch deleted file mode 100644 index 93eaffa19e..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch +++ /dev/null @@ -1,403 +0,0 @@ -From f601293f37c4be618c5efaef85d2ee21f97e82e0 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:35 +0000 -Subject: [PATCH 092/250] net: ethernet: mtk_eth_soc: ppe: add support for flow - accounting -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The PPE units found in MT7622 and newer support packet and byte -accounting of hw-offloaded flows. Add support for reading those counters -as found in MediaTek's SDK[1]. - -[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92 -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + - drivers/net/ethernet/mediatek/mtk_ppe.c | 114 +++++++++++++++++- - drivers/net/ethernet/mediatek/mtk_ppe.h | 25 +++- - .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +- - .../net/ethernet/mediatek/mtk_ppe_offload.c | 8 ++ - drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++ - 7 files changed, 172 insertions(+), 9 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4691,8 +4691,8 @@ static int mtk_probe(struct platform_dev - for (i = 0; i < num_ppe; i++) { - u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; - -- eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, -- eth->soc->offload_version, i); -+ eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, i); -+ - if (!eth->ppe[i]) { - err = -ENOMEM; - goto err_deinit_ppe; -@@ -4816,6 +4816,7 @@ static const struct mtk_soc_data mt7622_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 2, -+ .has_accounting = true, - .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), -@@ -4853,6 +4854,7 @@ static const struct mtk_soc_data mt7629_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7629_CLKS_BITMAP, - .required_pctl = false, -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4873,6 +4875,7 @@ static const struct mtk_soc_data mt7981_ - .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4893,6 +4896,7 @@ static const struct mtk_soc_data mt7986_ - .offload_version = 2, - .hash_offset = 4, - .foe_entry_size = sizeof(struct mtk_foe_entry), -+ .has_accounting = true, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1011,6 +1011,8 @@ struct mtk_reg_map { - * the extra setup for those pins used by GMAC. - * @hash_offset Flow table hash offset. - * @foe_entry_size Foe table entry size. -+ * @has_accounting Bool indicating support for accounting of -+ * offloaded flows. - * @txd_size Tx DMA descriptor size. - * @rxd_size Rx DMA descriptor size. - * @rx_irq_done_mask Rx irq done register mask. -@@ -1028,6 +1030,7 @@ struct mtk_soc_data { - u8 hash_offset; - u16 foe_entry_size; - netdev_features_t hw_features; -+ bool has_accounting; - struct { - u32 txd_size; - u32 rxd_size; ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -74,6 +74,48 @@ static int mtk_ppe_wait_busy(struct mtk_ - return ret; - } - -+static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) -+{ -+ int ret; -+ u32 val; -+ -+ ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, -+ !(val & MTK_PPE_MIB_SER_CR_ST), -+ 20, MTK_PPE_WAIT_TIMEOUT_US); -+ -+ if (ret) -+ dev_err(ppe->dev, "MIB table busy"); -+ -+ return ret; -+} -+ -+static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) -+{ -+ u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; -+ u32 val, cnt_r0, cnt_r1, cnt_r2; -+ int ret; -+ -+ val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; -+ ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); -+ -+ ret = mtk_ppe_mib_wait_busy(ppe); -+ if (ret) -+ return ret; -+ -+ cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); -+ cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); -+ cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); -+ -+ byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -+ byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -+ pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -+ pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -+ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -+ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ -+ return 0; -+} -+ - static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) - { - ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); -@@ -459,6 +501,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp - hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); - dma_wmb(); - mtk_ppe_cache_clear(ppe); -+ if (ppe->accounting) { -+ struct mtk_foe_accounting *acct; -+ -+ acct = ppe->acct_table + entry->hash * sizeof(*acct); -+ acct->packets = 0; -+ acct->bytes = 0; -+ } - } - entry->hash = 0xffff; - -@@ -566,6 +615,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - wmb(); - hwe->ib1 = entry->ib1; - -+ if (ppe->accounting) -+ *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; -+ - dma_wmb(); - - mtk_ppe_cache_clear(ppe); -@@ -757,11 +809,39 @@ int mtk_ppe_prepare_reset(struct mtk_ppe - return mtk_ppe_wait_busy(ppe); - } - --struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, -- int version, int index) -+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, -+ struct mtk_foe_accounting *diff) -+{ -+ struct mtk_foe_accounting *acct; -+ int size = sizeof(struct mtk_foe_accounting); -+ u64 bytes, packets; -+ -+ if (!ppe->accounting) -+ return NULL; -+ -+ if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) -+ return NULL; -+ -+ acct = ppe->acct_table + index * size; -+ -+ acct->bytes += bytes; -+ acct->packets += packets; -+ -+ if (diff) { -+ diff->bytes = bytes; -+ diff->packets = packets; -+ } -+ -+ return acct; -+} -+ -+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) - { -+ bool accounting = eth->soc->has_accounting; - const struct mtk_soc_data *soc = eth->soc; -+ struct mtk_foe_accounting *acct; - struct device *dev = eth->dev; -+ struct mtk_mib_entry *mib; - struct mtk_ppe *ppe; - u32 foe_flow_size; - void *foe; -@@ -778,7 +858,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - ppe->base = base; - ppe->eth = eth; - ppe->dev = dev; -- ppe->version = version; -+ ppe->version = eth->soc->offload_version; -+ ppe->accounting = accounting; - - foe = dmam_alloc_coherent(ppe->dev, - MTK_PPE_ENTRIES * soc->foe_entry_size, -@@ -794,6 +875,23 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ - if (!ppe->foe_flow) - goto err_free_l2_flows; - -+ if (accounting) { -+ mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), -+ &ppe->mib_phys, GFP_KERNEL); -+ if (!mib) -+ return NULL; -+ -+ ppe->mib_table = mib; -+ -+ acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), -+ GFP_KERNEL); -+ -+ if (!acct) -+ return NULL; -+ -+ ppe->acct_table = acct; -+ } -+ - mtk_ppe_debugfs_init(ppe, index); - - return ppe; -@@ -923,6 +1021,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); - ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); - } -+ -+ if (ppe->accounting && ppe->mib_phys) { -+ ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys); -+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, -+ MTK_PPE_MIB_CFG_EN); -+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, -+ MTK_PPE_MIB_CFG_RD_CLR); -+ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, -+ MTK_PPE_MIB_CFG_RD_CLR); -+ } - } - - int mtk_ppe_stop(struct mtk_ppe *ppe) ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -57,6 +57,7 @@ enum { - #define MTK_FOE_IB2_MULTICAST BIT(8) - - #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) -+#define MTK_FOE_IB2_MIB_CNT BIT(15) - #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) - #define MTK_FOE_IB2_WDMA_WINFO BIT(17) - -@@ -285,16 +286,34 @@ struct mtk_flow_entry { - unsigned long cookie; - }; - -+struct mtk_mib_entry { -+ u32 byt_cnt_l; -+ u16 byt_cnt_h; -+ u32 pkt_cnt_l; -+ u8 pkt_cnt_h; -+ u8 _rsv0; -+ u32 _rsv1; -+} __packed; -+ -+struct mtk_foe_accounting { -+ u64 bytes; -+ u64 packets; -+}; -+ - struct mtk_ppe { - struct mtk_eth *eth; - struct device *dev; - void __iomem *base; - int version; - char dirname[5]; -+ bool accounting; - - void *foe_table; - dma_addr_t foe_phys; - -+ struct mtk_mib_entry *mib_table; -+ dma_addr_t mib_phys; -+ - u16 foe_check_time[MTK_PPE_ENTRIES]; - struct hlist_head *foe_flow; - -@@ -303,8 +322,8 @@ struct mtk_ppe { - void *acct_table; - }; - --struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, -- int version, int index); -+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); -+ - void mtk_ppe_deinit(struct mtk_eth *eth); - void mtk_ppe_start(struct mtk_ppe *ppe); - int mtk_ppe_stop(struct mtk_ppe *ppe); -@@ -359,5 +378,7 @@ int mtk_foe_entry_commit(struct mtk_ppe - void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); - int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); -+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, -+ struct mtk_foe_accounting *diff); - - #endif ---- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -@@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file - struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i); - struct mtk_foe_mac_info *l2; - struct mtk_flow_addr_info ai = {}; -+ struct mtk_foe_accounting *acct; - unsigned char h_source[ETH_ALEN]; - unsigned char h_dest[ETH_ALEN]; - int type, state; -@@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file - if (bind && state != MTK_FOE_STATE_BIND) - continue; - -+ acct = mtk_foe_entry_get_mib(ppe, i, NULL); -+ - type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); - seq_printf(m, "%05x %s %7s", i, - mtk_foe_entry_state_str(state), -@@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file - *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); - - seq_printf(m, " eth=%pM->%pM etype=%04x" -- " vlan=%d,%d ib1=%08x ib2=%08x\n", -+ " vlan=%d,%d ib1=%08x ib2=%08x" -+ " packets=%llu bytes=%llu\n", - h_source, h_dest, ntohs(l2->etype), -- l2->vlan1, l2->vlan2, entry->ib1, ib2); -+ l2->vlan1, l2->vlan2, entry->ib1, ib2, -+ acct ? acct->packets : 0, acct ? acct->bytes : 0); - } - - return 0; ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -497,6 +497,7 @@ static int - mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) - { - struct mtk_flow_entry *entry; -+ struct mtk_foe_accounting diff; - u32 idle; - - entry = rhashtable_lookup(ð->flow_table, &f->cookie, -@@ -507,6 +508,13 @@ mtk_flow_offload_stats(struct mtk_eth *e - idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); - f->stats.lastused = jiffies - idle * HZ; - -+ if (entry->hash != 0xFFFF && -+ mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, -+ &diff)) { -+ f->stats.pkts += diff.packets; -+ f->stats.bytes += diff.bytes; -+ } -+ - return 0; - } - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -149,6 +149,20 @@ enum { - - #define MTK_PPE_MIB_TB_BASE 0x338 - -+#define MTK_PPE_MIB_SER_CR 0x33C -+#define MTK_PPE_MIB_SER_CR_ST BIT(16) -+#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0) -+ -+#define MTK_PPE_MIB_SER_R0 0x340 -+#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0) -+ -+#define MTK_PPE_MIB_SER_R1 0x344 -+#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16) -+#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0) -+ -+#define MTK_PPE_MIB_SER_R2 0x348 -+#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) -+ - #define MTK_PPE_MIB_CACHE_CTL 0x350 - #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) - #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch b/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch deleted file mode 100644 index 64352426ae..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-24-net-ethernet-mediatek-fix-ppe-flow-accounting-for-v1.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 88a0fd5927b7c2c7aecd6dc747d898eb38043d2b Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 20 Apr 2023 22:06:42 +0100 -Subject: [PATCH 093/250] net: mtk_eth_soc: mediatek: fix ppe flow accounting - for v1 hardware - -Older chips (like MT7622) use a different bit in ib2 to enable hardware -counter support. Add macros for both and select the appropriate bit. - -Fixes: 3fbe4d8c0e53 ("net: ethernet: mtk_eth_soc: ppe: add support for flow accounting") -Signed-off-by: Felix Fietkau -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe.c | 10 ++++++++-- - drivers/net/ethernet/mediatek/mtk_ppe.h | 3 ++- - 2 files changed, 10 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -599,6 +599,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - struct mtk_eth *eth = ppe->eth; - u16 timestamp = mtk_eth_timestamp(eth); - struct mtk_foe_entry *hwe; -+ u32 val; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; -@@ -615,8 +616,13 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - wmb(); - hwe->ib1 = entry->ib1; - -- if (ppe->accounting) -- *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; -+ if (ppe->accounting) { -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ val = MTK_FOE_IB2_MIB_CNT_V2; -+ else -+ val = MTK_FOE_IB2_MIB_CNT; -+ *mtk_foe_entry_ib2(eth, hwe) |= val; -+ } - - dma_wmb(); - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -55,9 +55,10 @@ enum { - #define MTK_FOE_IB2_PSE_QOS BIT(4) - #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) - #define MTK_FOE_IB2_MULTICAST BIT(8) -+#define MTK_FOE_IB2_MIB_CNT BIT(10) - - #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) --#define MTK_FOE_IB2_MIB_CNT BIT(15) -+#define MTK_FOE_IB2_MIB_CNT_V2 BIT(15) - #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) - #define MTK_FOE_IB2_WDMA_WINFO BIT(17) - diff --git a/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch b/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch deleted file mode 100644 index 217e517c3a..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch +++ /dev/null @@ -1,201 +0,0 @@ -From: Felix Fietkau -Date: Sun, 20 Nov 2022 23:01:00 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: drop generic vlan rx offload, - only use DSA untagging - -Through testing I found out that hardware vlan rx offload support seems to -have some hardware issues. At least when using multiple MACs and when receiving -tagged packets on the secondary MAC, the hardware can sometimes start to emit -wrong tags on the first MAC as well. - -In order to avoid such issues, drop the feature configuration and use the -offload feature only for DSA hardware untagging on MT7621/MT7622 devices which -only use one MAC. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1897,9 +1897,7 @@ static int mtk_poll_rx(struct napi_struc - - while (done < budget) { - unsigned int pktlen, *rxdcsum; -- bool has_hwaccel_tag = false; - struct net_device *netdev; -- u16 vlan_proto, vlan_tci; - dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; -@@ -2034,36 +2032,21 @@ static int mtk_poll_rx(struct napi_struc - skb_checksum_none_assert(skb); - skb->protocol = eth_type_trans(skb, netdev); - -- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -- mtk_ppe_check_skb(eth->ppe[0], skb, hash); -- -- if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -- if (trxd.rxd3 & RX_DMA_VTAG_V2) { -- vlan_proto = RX_DMA_VPID(trxd.rxd4); -- vlan_tci = RX_DMA_VID(trxd.rxd4); -- has_hwaccel_tag = true; -- } -- } else if (trxd.rxd2 & RX_DMA_VTAG) { -- vlan_proto = RX_DMA_VPID(trxd.rxd3); -- vlan_tci = RX_DMA_VID(trxd.rxd3); -- has_hwaccel_tag = true; -- } -- } -- - /* When using VLAN untagging in combination with DSA, the - * hardware treats the MTK special tag as a VLAN and untags it. - */ -- if (has_hwaccel_tag && netdev_uses_dsa(netdev)) { -- unsigned int port = vlan_proto & GENMASK(2, 0); -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && -+ (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { -+ unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && - eth->dsa_meta[port]) - skb_dst_set_noref(skb, ð->dsa_meta[port]->dst); -- } else if (has_hwaccel_tag) { -- __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci); - } - -+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -+ mtk_ppe_check_skb(eth->ppe[0], skb, hash); -+ - skb_record_rx_queue(skb, 0); - napi_gro_receive(napi, skb); - -@@ -2889,29 +2872,11 @@ static netdev_features_t mtk_fix_feature - - static int mtk_set_features(struct net_device *dev, netdev_features_t features) - { -- struct mtk_mac *mac = netdev_priv(dev); -- struct mtk_eth *eth = mac->hw; - netdev_features_t diff = dev->features ^ features; -- int i; - - if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) - mtk_hwlro_netdev_disable(dev); - -- /* Set RX VLAN offloading */ -- if (!(diff & NETIF_F_HW_VLAN_CTAG_RX)) -- return 0; -- -- mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), -- MTK_CDMP_EG_CTRL); -- -- /* sync features with other MAC */ -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i] || eth->netdev[i] == dev) -- continue; -- eth->netdev[i]->features &= ~NETIF_F_HW_VLAN_CTAG_RX; -- eth->netdev[i]->features |= features & NETIF_F_HW_VLAN_CTAG_RX; -- } -- - return 0; - } - -@@ -3225,30 +3190,6 @@ static int mtk_open(struct net_device *d - struct mtk_eth *eth = mac->hw; - int i, err; - -- if (mtk_uses_dsa(dev) && !eth->prog) { -- for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -- struct metadata_dst *md_dst = eth->dsa_meta[i]; -- -- if (md_dst) -- continue; -- -- md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -- GFP_KERNEL); -- if (!md_dst) -- return -ENOMEM; -- -- md_dst->u.port_info.port_id = i; -- eth->dsa_meta[i] = md_dst; -- } -- } else { -- /* Hardware special tag parsing needs to be disabled if at least -- * one MAC does not use DSA. -- */ -- u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -- val &= ~MTK_CDMP_STAG_EN; -- mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -- } -- - err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); - if (err) { - netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3287,6 +3228,35 @@ static int mtk_open(struct net_device *d - phylink_start(mac->phylink); - netif_tx_start_all_queues(dev); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ return 0; -+ -+ if (mtk_uses_dsa(dev) && !eth->prog) { -+ for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { -+ struct metadata_dst *md_dst = eth->dsa_meta[i]; -+ -+ if (md_dst) -+ continue; -+ -+ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, -+ GFP_KERNEL); -+ if (!md_dst) -+ return -ENOMEM; -+ -+ md_dst->u.port_info.port_id = i; -+ eth->dsa_meta[i] = md_dst; -+ } -+ } else { -+ /* Hardware special tag parsing needs to be disabled if at least -+ * one MAC does not use DSA. -+ */ -+ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); -+ val &= ~MTK_CDMP_STAG_EN; -+ mtk_w32(eth, val, MTK_CDMP_IG_CTRL); -+ -+ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); -+ } -+ - return 0; - } - -@@ -3771,10 +3741,9 @@ static int mtk_hw_init(struct mtk_eth *e - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { - val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); -- } - -- /* Enable RX VLan Offloading */ -- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -+ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -+ } - - /* set interrupt delays based on current Net DIM sample */ - mtk_dim_rx(ð->rx_dim.work); -@@ -4414,7 +4383,7 @@ static int mtk_add_mac(struct mtk_eth *e - eth->netdev[id]->hw_features |= NETIF_F_LRO; - - eth->netdev[id]->vlan_features = eth->soc->hw_features & -- ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); -+ ~NETIF_F_HW_VLAN_CTAG_TX; - eth->netdev[id]->features |= eth->soc->hw_features; - eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -48,7 +48,6 @@ - #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ - NETIF_F_RXCSUM | \ - NETIF_F_HW_VLAN_CTAG_TX | \ -- NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_SG | NETIF_F_TSO | \ - NETIF_F_TSO6 | \ - NETIF_F_IPV6_CSUM |\ diff --git a/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch b/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch deleted file mode 100644 index 2704faec12..0000000000 --- a/target/linux/generic/backport-6.6/733-v6.5-26-net-ethernet-mtk_eth_soc-always-mtk_get_ib1_pkt_type.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b804f765485109f9644cc05d1e8fc79ca6c6e4aa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Jul 2023 01:39:36 +0100 -Subject: [PATCH 094/250] net: ethernet: mtk_eth_soc: always - mtk_get_ib1_pkt_type - -entries and bind debugfs files would display wrong data on NETSYS_V2 and -later because instead of using mtk_get_ib1_pkt_type the driver would use -MTK_FOE_IB1_PACKET_TYPE which corresponds to NETSYS_V1(.x) SoCs. -Use mtk_get_ib1_pkt_type so entries and bind records display correctly. - -Fixes: 03a3180e5c09e ("net: ethernet: mtk_eth_soc: introduce flow offloading support for mt7986") -Signed-off-by: Daniel Golle -Acked-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/c0ae03d0182f4d27b874cbdf0059bc972c317f3c.1689727134.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file - - acct = mtk_foe_entry_get_mib(ppe, i, NULL); - -- type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1); - seq_printf(m, "%05x %s %7s", i, - mtk_foe_entry_state_str(state), - mtk_foe_pkt_type_str(type)); diff --git a/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch b/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch deleted file mode 100644 index d7d1c08fce..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 5ea0e1312bcfebc06b5f91d1bb82b823d6395125 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Wed, 19 Jul 2023 12:29:49 +0200 -Subject: [PATCH 095/250] net: ethernet: mtk_ppe: add MTK_FOE_ENTRY_V{1,2}_SIZE - macros - -Introduce MTK_FOE_ENTRY_V{1,2}_SIZE macros in order to make more -explicit foe_entry size for different chipset revisions. - -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +++++----- - drivers/net/ethernet/mediatek/mtk_ppe.h | 3 +++ - 2 files changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4765,7 +4765,7 @@ static const struct mtk_soc_data mt7621_ - .required_pctl = false, - .offload_version = 1, - .hash_offset = 2, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4786,7 +4786,7 @@ static const struct mtk_soc_data mt7622_ - .offload_version = 2, - .hash_offset = 2, - .has_accounting = true, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4805,7 +4805,7 @@ static const struct mtk_soc_data mt7623_ - .required_pctl = true, - .offload_version = 1, - .hash_offset = 2, -- .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, -+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4843,8 +4843,8 @@ static const struct mtk_soc_data mt7981_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 4, -- .foe_entry_size = sizeof(struct mtk_foe_entry), - .has_accounting = true, -+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4864,8 +4864,8 @@ static const struct mtk_soc_data mt7986_ - .required_pctl = false, - .offload_version = 2, - .hash_offset = 4, -- .foe_entry_size = sizeof(struct mtk_foe_entry), - .has_accounting = true, -+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -216,6 +216,9 @@ struct mtk_foe_ipv6_6rd { - struct mtk_foe_mac_info l2; - }; - -+#define MTK_FOE_ENTRY_V1_SIZE 80 -+#define MTK_FOE_ENTRY_V2_SIZE 96 -+ - struct mtk_foe_entry { - u32 ib1; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch b/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch deleted file mode 100644 index fb54f404b2..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 8cfa2576d79f9379d167a8994f0fca935c07a8bc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 22 Jul 2023 21:32:49 +0100 -Subject: [PATCH 096/250] net: ethernet: mtk_eth_soc: remove incorrect PLL - configuration - -MT7623 GMAC0 attempts to configure the system clocking according to the -required speed in the .mac_config callback for non-SGMII, non-baseX and -non-TRGMII modes. - -state->speed setting has never been reliable in the .mac_config -callback - there are cases where this is not the link speed, -particularly via ethtool paths, so this has always been unreliable (as -detailed in phylink's documentation.) - -There is the additional issue that mtk_gmac0_rgmii_adjust() will only -be called if state->interface changes, which means it only configures -the system clocking on the very first .mac_config call, which will be -made when the network device is first brought up before any link is -established. - -Essentially, this code is incredibly buggy, and probably never worked. - -Moreover, checking the in-kernel DT files, it seems no platform makes -use of this code path. - -Therefore, let's remove it, and disable interface modes for port 0 that -are not SGMII, 1000base-X, 2500base-X or TRGMII on the MT7623. - -Reviewed-by: Daniel Golle -Tested-by: Daniel Golle -Tested-by: Frank Wunderlich -Signed-off-by: Russell King (Oracle) -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 54 ++++++--------------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + - 2 files changed, 17 insertions(+), 38 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -352,7 +352,7 @@ static int mt7621_gmac0_rgmii_adjust(str - } - - static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, -- phy_interface_t interface, int speed) -+ phy_interface_t interface) - { - u32 val; - int ret; -@@ -366,26 +366,7 @@ static void mtk_gmac0_rgmii_adjust(struc - return; - } - -- val = (speed == SPEED_1000) ? -- INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100; -- mtk_w32(eth, val, INTF_MODE); -- -- regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0, -- ETHSYS_TRGMII_CLK_SEL362_5, -- ETHSYS_TRGMII_CLK_SEL362_5); -- -- val = (speed == SPEED_1000) ? 250000000 : 500000000; -- ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val); -- if (ret) -- dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret); -- -- val = (speed == SPEED_1000) ? -- RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100; -- mtk_w32(eth, val, TRGMII_RCK_CTRL); -- -- val = (speed == SPEED_1000) ? -- TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100; -- mtk_w32(eth, val, TRGMII_TCK_CTRL); -+ dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); - } - - static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, -@@ -471,17 +452,8 @@ static void mtk_mac_config(struct phylin - state->interface)) - goto err_phy; - } else { -- /* FIXME: this is incorrect. Not only does it -- * use state->speed (which is not guaranteed -- * to be correct) but it also makes use of it -- * in a code path that will only be reachable -- * when the PHY interface mode changes, not -- * when the speed changes. Consequently, RGMII -- * is probably broken. -- */ - mtk_gmac0_rgmii_adjust(mac->hw, -- state->interface, -- state->speed); -+ state->interface); - - /* mt7623_pad_clk_setup */ - for (i = 0 ; i < NUM_TRGMII_CTRL; i++) -@@ -4342,13 +4314,19 @@ static int mtk_add_mac(struct mtk_eth *e - mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; - -- __set_bit(PHY_INTERFACE_MODE_MII, -- mac->phylink_config.supported_interfaces); -- __set_bit(PHY_INTERFACE_MODE_GMII, -- mac->phylink_config.supported_interfaces); -+ /* MT7623 gmac0 is now missing its speed-specific PLL configuration -+ * in its .mac_config method (since state->speed is not valid there. -+ * Disable support for MII, GMII and RGMII. -+ */ -+ if (!mac->hw->soc->disable_pll_modes || mac->id != 0) { -+ __set_bit(PHY_INTERFACE_MODE_MII, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_GMII, -+ mac->phylink_config.supported_interfaces); - -- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) -- phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); -+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) -+ phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); -+ } - - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) - __set_bit(PHY_INTERFACE_MODE_TRGMII, -@@ -4806,6 +4784,7 @@ static const struct mtk_soc_data mt7623_ - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -+ .disable_pll_modes = true, - .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 -@@ -1030,6 +1030,7 @@ struct mtk_soc_data { - u16 foe_entry_size; - netdev_features_t hw_features; - bool has_accounting; -+ bool disable_pll_modes; - struct { - u32 txd_size; - u32 rxd_size; diff --git a/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch b/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch deleted file mode 100644 index 293066fa9a..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch +++ /dev/null @@ -1,81 +0,0 @@ -From a4c2233b1e4359b6c64b6f9ba98c8718a11fffee Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 22 Jul 2023 21:32:54 +0100 -Subject: [PATCH 097/250] net: ethernet: mtk_eth_soc: remove mac_pcs_get_state - and modernise - -Remove the .mac_pcs_get_state function, since as far as I can tell is -never called - no DT appears to specify an in-band-status management -nor SFP support for this driver. - -Removal of this, along with the previous patch to remove the incorrect -clocking configuration, means that the driver becomes non-legacy, so -we can remove the "legacy_pre_march2020" status from this driver. - -Reviewed-by: Daniel Golle -Tested-by: Daniel Golle -Tested-by: Frank Wunderlich -Signed-off-by: Russell King (Oracle) -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 --------------------- - 1 file changed, 35 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -555,38 +555,6 @@ static int mtk_mac_finish(struct phylink - return 0; - } - --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); -- u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id)); -- -- state->link = (pmsr & MAC_MSR_LINK); -- state->duplex = (pmsr & MAC_MSR_DPX) >> 1; -- -- switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) { -- case 0: -- state->speed = SPEED_10; -- break; -- case MAC_MSR_SPEED_100: -- state->speed = SPEED_100; -- break; -- case MAC_MSR_SPEED_1000: -- state->speed = SPEED_1000; -- break; -- default: -- state->speed = SPEED_UNKNOWN; -- break; -- } -- -- state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); -- if (pmsr & MAC_MSR_RX_FC) -- state->pause |= MLO_PAUSE_RX; -- if (pmsr & MAC_MSR_TX_FC) -- state->pause |= MLO_PAUSE_TX; --} -- - static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, - phy_interface_t interface) - { -@@ -708,7 +676,6 @@ static void mtk_mac_link_up(struct phyli - - static const struct phylink_mac_ops mtk_phylink_ops = { - .mac_select_pcs = mtk_mac_select_pcs, -- .mac_pcs_get_state = mtk_mac_pcs_get_state, - .mac_config = mtk_mac_config, - .mac_finish = mtk_mac_finish, - .mac_link_down = mtk_mac_link_down, -@@ -4309,8 +4276,6 @@ static int mtk_add_mac(struct mtk_eth *e - - mac->phylink_config.dev = ð->netdev[id]->dev; - mac->phylink_config.type = PHYLINK_NETDEV; -- /* This driver makes use of state->speed in mac_config */ -- mac->phylink_config.legacy_pre_march2020 = true; - mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch b/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch deleted file mode 100644 index 25c87b0415..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch +++ /dev/null @@ -1,550 +0,0 @@ -From 5d8d05fbf804b4485646d39551ac27452e45afd3 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:02 +0100 -Subject: [PATCH 099/250] net: ethernet: mtk_eth_soc: add version in - mtk_soc_data - -Introduce version field in mtk_soc_data data structure in order to -make mtk_eth driver easier to maintain for chipset configuration -codebase. Get rid of MTK_NETSYS_V2 bit in chip capabilities. -This is a preliminary patch to introduce support for MT7988 SoC. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e52fae302ca135436e5cdd26d38d87be2da63055.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 55 +++++++++++-------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 36 +++++++----- - drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++--- - .../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- - drivers/net/ethernet/mediatek/mtk_wed.c | 4 +- - 5 files changed, 66 insertions(+), 49 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -580,7 +580,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_is_netsys_v1(eth)) - val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; - - if (IS_ENABLED(CONFIG_SOC_MT7621)) { -@@ -955,7 +955,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_is_netsys_v2_or_greater(eth)) { - rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); - rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); - } -@@ -1013,7 +1013,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_is_netsys_v2_or_greater(eth)) { - txd->txd5 = 0; - txd->txd6 = 0; - txd->txd7 = 0; -@@ -1204,7 +1204,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_is_netsys_v2_or_greater(eth)) - mtk_tx_set_dma_desc_v2(dev, txd, info); - else - mtk_tx_set_dma_desc_v1(dev, txd, info); -@@ -1511,7 +1511,7 @@ static void mtk_update_rx_cpu_idx(struct - - static bool mtk_page_pool_enabled(struct mtk_eth *eth) - { -- return MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2); -+ return eth->soc->version == 2; - } - - static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, -@@ -1853,7 +1853,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_is_netsys_v2_or_greater(eth)) - 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)) -@@ -1949,7 +1949,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_is_netsys_v2_or_greater(eth)) { - reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); - hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; - if (hash != MTK_RXD5_FOE_ENTRY) -@@ -1974,8 +1974,8 @@ 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) && -- (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { -+ if (mtk_is_netsys_v1(eth) && (trxd.rxd2 & RX_DMA_VTAG) && -+ netdev_uses_dsa(netdev)) { - unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); - - if (port < ARRAY_SIZE(eth->dsa_meta) && -@@ -2285,7 +2285,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_is_netsys_v2_or_greater(eth)) { - txd->txd5 = 0; - txd->txd6 = 0; - txd->txd7 = 0; -@@ -2338,14 +2338,14 @@ 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_is_netsys_v1(eth)) - val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; - mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); - ofs += MTK_QTX_OFFSET; - } - val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16); - mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate); -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); - } else { - mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); -@@ -2474,7 +2474,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_is_netsys_v2_or_greater(eth)) { - rxd->rxd5 = 0; - rxd->rxd6 = 0; - rxd->rxd7 = 0; -@@ -3025,7 +3025,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_is_netsys_v2_or_greater(eth)) - val |= MTK_MUTLI_CNT | MTK_RESV_BUF | - MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | - MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; -@@ -3167,7 +3167,7 @@ static int mtk_open(struct net_device *d - phylink_start(mac->phylink); - netif_tx_start_all_queues(dev); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return 0; - - if (mtk_uses_dsa(dev) && !eth->prog) { -@@ -3432,7 +3432,7 @@ static void mtk_hw_reset(struct mtk_eth - { - u32 val; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); - val = RSTCTRL_PPE0_V2; - } else { -@@ -3444,7 +3444,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_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, - 0x3ffffff); - } -@@ -3470,7 +3470,7 @@ static void mtk_hw_warm_reset(struct mtk - return; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; - else - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -@@ -3640,7 +3640,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_is_netsys_v2_or_greater(eth)) { - /* Set FE to PDMAv2 if necessary */ - val = mtk_r32(eth, MTK_FE_GLO_MISC); - mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); -@@ -3677,7 +3677,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_is_netsys_v1(eth)) { - val = mtk_r32(eth, MTK_CDMP_IG_CTRL); - mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); - -@@ -3699,7 +3699,7 @@ 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_is_netsys_v2_or_greater(eth)) { - /* PSE should not drop port8 and port9 packets from WDMA Tx */ - mtk_w32(eth, 0x00000300, PSE_DROP_CFG); - -@@ -4488,7 +4488,7 @@ static int mtk_probe(struct platform_dev - } - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - err = -EINVAL; -@@ -4596,9 +4596,8 @@ static int mtk_probe(struct platform_dev - } - - if (eth->soc->offload_version) { -- u32 num_ppe; -+ u32 num_ppe = mtk_is_netsys_v2_or_greater(eth) ? 2 : 1; - -- num_ppe = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; - num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); - for (i = 0; i < num_ppe; i++) { - u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; -@@ -4690,6 +4689,7 @@ static const struct mtk_soc_data mt2701_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -+ .version = 1, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4706,6 +4706,7 @@ static const struct mtk_soc_data mt7621_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7621_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4726,6 +4727,7 @@ static const struct mtk_soc_data mt7622_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7622_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .offload_version = 2, - .hash_offset = 2, - .has_accounting = true, -@@ -4746,6 +4748,7 @@ static const struct mtk_soc_data mt7623_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7623_CLKS_BITMAP, - .required_pctl = true, -+ .version = 1, - .offload_version = 1, - .hash_offset = 2, - .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4768,6 +4771,7 @@ static const struct mtk_soc_data mt7629_ - .required_clks = MT7629_CLKS_BITMAP, - .required_pctl = false, - .has_accounting = true, -+ .version = 1, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma), - .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4785,6 +4789,7 @@ static const struct mtk_soc_data mt7981_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7981_CLKS_BITMAP, - .required_pctl = false, -+ .version = 2, - .offload_version = 2, - .hash_offset = 4, - .has_accounting = true, -@@ -4806,6 +4811,7 @@ static const struct mtk_soc_data mt7986_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7986_CLKS_BITMAP, - .required_pctl = false, -+ .version = 2, - .offload_version = 2, - .hash_offset = 4, - .has_accounting = true, -@@ -4826,6 +4832,7 @@ static const struct mtk_soc_data rt5350_ - .hw_features = MTK_HW_FEATURES_MT7628, - .required_clks = MT7628_CLKS_BITMAP, - .required_pctl = false, -+ .version = 1, - .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 -@@ -820,7 +820,6 @@ enum mkt_eth_capabilities { - MTK_SHARED_INT_BIT, - MTK_TRGMII_MT7621_CLK_BIT, - MTK_QDMA_BIT, -- MTK_NETSYS_V2_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, - MTK_U3_COPHY_V2_BIT, -@@ -855,7 +854,6 @@ 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_V2 BIT(MTK_NETSYS_V2_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) -@@ -934,11 +932,11 @@ enum mkt_eth_capabilities { - #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ -- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) -+ 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) -+ MTK_RSTCTRL_PPE1) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; -@@ -1009,6 +1007,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. -+ * @version SoC version. - * @foe_entry_size Foe table entry size. - * @has_accounting Bool indicating support for accounting of - * offloaded flows. -@@ -1027,6 +1026,7 @@ struct mtk_soc_data { - bool required_pctl; - u8 offload_version; - u8 hash_offset; -+ u8 version; - u16 foe_entry_size; - netdev_features_t hw_features; - bool has_accounting; -@@ -1183,6 +1183,16 @@ struct mtk_mac { - /* the struct describing the SoC. these are declared in the soc_xyz.c files */ - extern const struct of_device_id of_mtk_match[]; - -+static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) -+{ -+ return eth->soc->version == 1; -+} -+ -+static inline bool mtk_is_netsys_v2_or_greater(struct mtk_eth *eth) -+{ -+ return eth->soc->version > 1; -+} -+ - static inline struct mtk_foe_entry * - mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) - { -@@ -1193,7 +1203,7 @@ mtk_foe_get_entry(struct mtk_ppe *ppe, u - - static inline u32 mtk_get_ib1_ts_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_TIMESTAMP_V2; - - return MTK_FOE_IB1_BIND_TIMESTAMP; -@@ -1201,7 +1211,7 @@ static inline u32 mtk_get_ib1_ts_mask(st - - static inline u32 mtk_get_ib1_ppoe_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_PPPOE_V2; - - return MTK_FOE_IB1_BIND_PPPOE; -@@ -1209,7 +1219,7 @@ static inline u32 mtk_get_ib1_ppoe_mask( - - static inline u32 mtk_get_ib1_vlan_tag_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_VLAN_TAG_V2; - - return MTK_FOE_IB1_BIND_VLAN_TAG; -@@ -1217,7 +1227,7 @@ static inline u32 mtk_get_ib1_vlan_tag_m - - static inline u32 mtk_get_ib1_vlan_layer_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_BIND_VLAN_LAYER_V2; - - return MTK_FOE_IB1_BIND_VLAN_LAYER; -@@ -1225,7 +1235,7 @@ static inline u32 mtk_get_ib1_vlan_layer - - static inline u32 mtk_prep_ib1_vlan_layer(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); - - return FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, val); -@@ -1233,7 +1243,7 @@ static inline u32 mtk_prep_ib1_vlan_laye - - static inline u32 mtk_get_ib1_vlan_layer(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER_V2, val); - - return FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, val); -@@ -1241,7 +1251,7 @@ static inline u32 mtk_get_ib1_vlan_layer - - static inline u32 mtk_get_ib1_pkt_type_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB1_PACKET_TYPE_V2; - - return MTK_FOE_IB1_PACKET_TYPE; -@@ -1249,7 +1259,7 @@ static inline u32 mtk_get_ib1_pkt_type_m - - static inline u32 mtk_get_ib1_pkt_type(struct mtk_eth *eth, u32 val) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE_V2, val); - - return FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, val); -@@ -1257,7 +1267,7 @@ static inline u32 mtk_get_ib1_pkt_type(s - - static inline u32 mtk_get_ib2_multicast_mask(struct mtk_eth *eth) - { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - return MTK_FOE_IB2_MULTICAST_V2; - - return MTK_FOE_IB2_MULTICAST; ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -207,7 +207,7 @@ int mtk_foe_entry_prepare(struct mtk_eth - - memset(entry, 0, sizeof(*entry)); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | - FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE_V2, type) | - FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | -@@ -271,7 +271,7 @@ int mtk_foe_entry_set_pse_port(struct mt - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - u32 val = *ib2; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - val &= ~MTK_FOE_IB2_DEST_PORT_V2; - val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, port); - } else { -@@ -422,7 +422,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et - struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | - MTK_FOE_IB2_WDMA_WINFO_V2; -@@ -446,7 +446,7 @@ int mtk_foe_entry_set_queue(struct mtk_e - { - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - *ib2 &= ~MTK_FOE_IB2_QID_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue); - *ib2 |= MTK_FOE_IB2_PSE_QOS_V2; -@@ -601,7 +601,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - struct mtk_foe_entry *hwe; - u32 val; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP_V2; - entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP_V2, - timestamp); -@@ -617,7 +617,7 @@ __mtk_foe_entry_commit(struct mtk_ppe *p - hwe->ib1 = entry->ib1; - - if (ppe->accounting) { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - val = MTK_FOE_IB2_MIB_CNT_V2; - else - val = MTK_FOE_IB2_MIB_CNT; -@@ -965,7 +965,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | - FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, - MTK_PPE_ENTRIES_SHIFT); -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_TB_CFG_INFO_SEL; - ppe_w32(ppe, MTK_PPE_TB_CFG, val); - -@@ -981,7 +981,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_FLOW_CFG_IP4_NAPT | - MTK_PPE_FLOW_CFG_IP4_DSLITE | - MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_MD_TOAP_BYP_CRSN0 | - MTK_PPE_MD_TOAP_BYP_CRSN1 | - MTK_PPE_MD_TOAP_BYP_CRSN2 | -@@ -1023,7 +1023,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); - -- if (MTK_HAS_CAPS(ppe->eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(ppe->eth)) { - ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); - ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); - } ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -193,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_et - if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { - mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, - info.bss, info.wcid); -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) { - switch (info.wdma_idx) { - case 0: - pse_port = 8; ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1084,7 +1084,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * - } else { - struct mtk_eth *eth = dev->hw->eth; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) -+ if (mtk_is_netsys_v2_or_greater(eth)) - wed_set(dev, MTK_WED_RESET_IDX, - MTK_WED_RESET_IDX_RX_V2); - else -@@ -1806,7 +1806,7 @@ void mtk_wed_add_hw(struct device_node * - hw->wdma = wdma; - hw->index = index; - hw->irq = irq; -- hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; -+ hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; - - if (hw->version == 1) { - hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, diff --git a/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch b/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch deleted file mode 100644 index 7b945bb869..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-06-net-ethernet-mtk_eth_soc-increase-MAX_DEVS-to-3.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f8fb8dbd158c585be7574faf92db7d614b6722ff Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:27 +0100 -Subject: [PATCH 100/250] net: ethernet: mtk_eth_soc: increase MAX_DEVS to 3 - -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 -Link: https://lore.kernel.org/r/3563e5fab367e7d79a7f1296fabaa5c20f202d7a.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1043,8 +1043,8 @@ 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 -+/* currently no SoC has more than 3 macs */ -+#define MTK_MAX_DEVS 3 - - /* struct mtk_eth - This is the main datasructure for holding the state - * of the driver diff --git a/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch b/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch deleted file mode 100644 index 8071658313..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 856be974290f28d7943be2ac5a382c4139486196 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:44 +0100 -Subject: [PATCH 101/250] net: ethernet: mtk_eth_soc: rely on MTK_MAX_DEVS and - remove MTK_MAC_COUNT - -Get rid of MTK_MAC_COUNT since it is a duplicated of MTK_MAX_DEVS. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/1856f4266f2fc80677807b1bad867659e7b00c65.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++++++--------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - - 2 files changed, 27 insertions(+), 23 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -881,7 +881,7 @@ static void mtk_stats_update(struct mtk_ - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->mac[i] || !eth->mac[i]->hw_stats) - continue; - if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { -@@ -1386,7 +1386,7 @@ static int mtk_queue_stopped(struct mtk_ - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - if (netif_queue_stopped(eth->netdev[i])) -@@ -1400,7 +1400,7 @@ static void mtk_wake_queue(struct mtk_et - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - netif_tx_wake_all_queues(eth->netdev[i]); -@@ -1859,7 +1859,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 >= MTK_MAX_DEVS || - !eth->netdev[mac])) - goto release_desc; - -@@ -2899,7 +2899,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 < MTK_MAX_DEVS; i++) - if (eth->netdev[i]) - netdev_reset_queue(eth->netdev[i]); - if (eth->scratch_ring) { -@@ -3053,8 +3053,13 @@ 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++) { -- u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ u32 val; -+ -+ if (!eth->netdev[i]) -+ continue; -+ -+ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); - - /* default setup the forward port to send frame to PDMA */ - val &= ~0xffff; -@@ -3064,7 +3069,7 @@ static void mtk_gdm_config(struct mtk_et - - val |= config; - -- if (eth->netdev[i] && netdev_uses_dsa(eth->netdev[i])) -+ if (netdev_uses_dsa(eth->netdev[i])) - val |= MTK_GDMA_SPECIAL_TAG; - - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3661,15 +3666,15 @@ 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 < MTK_MAX_DEVS; i++) { - struct net_device *dev = eth->netdev[i]; - -- mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); -- if (dev) { -- struct mtk_mac *mac = netdev_priv(dev); -+ if (!dev) -+ continue; - -- mtk_set_mcr_max_rx(mac, dev->mtu + MTK_RX_ETH_HLEN); -- } -+ mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); -+ mtk_set_mcr_max_rx(netdev_priv(dev), -+ dev->mtu + MTK_RX_ETH_HLEN); - } - - /* Indicates CDM to parse the MTK special tag from CPU -@@ -3849,7 +3854,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 < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i] || !netif_running(eth->netdev[i])) - continue; - -@@ -3865,8 +3870,8 @@ 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++) { -- if (!test_bit(i, &restart)) -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ if (!eth->netdev[i] || !test_bit(i, &restart)) - continue; - - if (mtk_open(eth->netdev[i])) { -@@ -3893,7 +3898,7 @@ static int mtk_free_dev(struct mtk_eth * - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; - free_netdev(eth->netdev[i]); -@@ -3912,7 +3917,7 @@ static int mtk_unreg_dev(struct mtk_eth - { - int i; - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - struct mtk_mac *mac; - if (!eth->netdev[i]) - continue; -@@ -4213,7 +4218,7 @@ static int mtk_add_mac(struct mtk_eth *e - } - - id = be32_to_cpup(_id); -- if (id >= MTK_MAC_COUNT) { -+ if (id >= MTK_MAX_DEVS) { - dev_err(eth->dev, "%d is not a valid mac id\n", id); - return -EINVAL; - } -@@ -4358,7 +4363,7 @@ void mtk_eth_set_dma_device(struct mtk_e - - rtnl_lock(); - -- for (i = 0; i < MTK_MAC_COUNT; i++) { -+ for (i = 0; i < MTK_MAX_DEVS; i++) { - dev = eth->netdev[i]; - - if (!dev || !(dev->flags & IFF_UP)) -@@ -4664,7 +4669,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 < MTK_MAX_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/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch b/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch deleted file mode 100644 index 1a9b31f526..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch +++ /dev/null @@ -1,307 +0,0 @@ -From a41d535855976838d246c079143c948dcf0f7931 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:52:59 +0100 -Subject: [PATCH 102/250] net: ethernet: mtk_eth_soc: add NETSYS_V3 version - support - -Introduce NETSYS_V3 chipset version support. -This is a preliminary patch to introduce support for MT7988 SoC. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/0db2260910755d76fa48e303b9f9bdf4e5a82340.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 105 ++++++++++++++------ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 +++++++-- - 2 files changed, 116 insertions(+), 37 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -861,17 +861,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_is_netsys_v3_or_greater(eth)) { -+ 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); -@@ -1175,7 +1190,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); - -@@ -1186,6 +1204,8 @@ static void mtk_tx_set_dma_desc_v2(struc - /* tx checksum offload */ - if (info->csum) - data |= TX_DMA_CHKSUM_V2; -+ if (mtk_is_netsys_v3_or_greater(eth) && netdev_uses_dsa(dev)) -+ data |= TX_DMA_SPTAG_V3; - } - WRITE_ONCE(desc->txd5, data); - -@@ -1251,8 +1271,7 @@ 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; -+ itx_buf->mac_id = mac->id; - setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, - k++); - -@@ -1300,8 +1319,7 @@ 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; -+ tx_buf->mac_id = mac->id; - - setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, - txd_info.size, k++); -@@ -1603,7 +1621,7 @@ static int mtk_xdp_frame_map(struct mtk_ - } - mtk_tx_set_dma_desc(dev, txd, txd_info); - -- tx_buf->flags |= !mac->id ? MTK_TX_FLAGS_FPORT0 : MTK_TX_FLAGS_FPORT1; -+ tx_buf->mac_id = mac->id; - tx_buf->type = dma_map ? MTK_TYPE_XDP_NDO : MTK_TYPE_XDP_TX; - tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; - -@@ -1853,11 +1871,24 @@ static int mtk_poll_rx(struct napi_struc - break; - - /* find out which mac the packet come from. values start at 1 */ -- if (mtk_is_netsys_v2_or_greater(eth)) -- 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_is_netsys_v2_or_greater(eth)) { -+ 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 >= MTK_MAX_DEVS || - !eth->netdev[mac])) -@@ -2079,7 +2110,6 @@ static int mtk_poll_tx_qdma(struct mtk_e - - while ((cpu != dma) && budget) { - u32 next_cpu = desc->txd2; -- int mac = 0; - - desc = mtk_qdma_phys_to_virt(ring, desc->txd2); - if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) -@@ -2087,15 +2117,13 @@ 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; -- - if (!tx_buf->data) - break; - - if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { - if (tx_buf->type == MTK_TYPE_SKB) -- mtk_poll_tx_done(eth, state, mac, tx_buf->data); -+ mtk_poll_tx_done(eth, state, tx_buf->mac_id, -+ tx_buf->data); - - budget--; - } -@@ -3704,7 +3732,24 @@ 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_is_netsys_v2_or_greater(eth)) { -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ /* 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 */ -+ mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, 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_is_netsys_v1(eth)) { - /* PSE should not drop port8 and port9 packets from WDMA Tx */ - mtk_w32(eth, 0x00000300, PSE_DROP_CFG); - -@@ -4266,7 +4311,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_is_netsys_v3_or_greater(eth)) -+ 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 -@@ -122,6 +122,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 - -@@ -287,8 +288,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 -@@ -301,6 +300,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 -@@ -634,12 +635,6 @@ enum mtk_tx_flags { - */ - MTK_TX_FLAGS_SINGLE0 = 0x01, - MTK_TX_FLAGS_PAGE0 = 0x02, -- -- /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted -- * SKB out instead of looking up through hardware TX descriptor. -- */ -- MTK_TX_FLAGS_FPORT0 = 0x04, -- MTK_TX_FLAGS_FPORT1 = 0x08, - }; - - /* This enum allows us to identify how the clock is defined on the array of the -@@ -725,6 +720,35 @@ 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 -+}; -+ - enum mtk_tx_buf_type { - MTK_TYPE_SKB, - MTK_TYPE_XDP_TX, -@@ -743,7 +767,8 @@ struct mtk_tx_buf { - enum mtk_tx_buf_type type; - void *data; - -- u32 flags; -+ u16 mac_id; -+ u16 flags; - DEFINE_DMA_UNMAP_ADDR(dma_addr0); - DEFINE_DMA_UNMAP_LEN(dma_len0); - DEFINE_DMA_UNMAP_ADDR(dma_addr1); -@@ -1192,6 +1217,11 @@ static inline bool mtk_is_netsys_v2_or_g - return eth->soc->version > 1; - } - -+static inline bool mtk_is_netsys_v3_or_greater(struct mtk_eth *eth) -+{ -+ return eth->soc->version > 2; -+} -+ - static inline struct mtk_foe_entry * - mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash) - { diff --git a/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch b/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch deleted file mode 100644 index 7a0b285f2c..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-09-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch +++ /dev/null @@ -1,193 +0,0 @@ -From db797ae0542220a98658229397da464c383c991c Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:53:13 +0100 -Subject: [PATCH 103/250] 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 -Link: https://lore.kernel.org/r/9499ac3670b2fc5b444404b84e8a4a169beabbf2.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 ++++---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 56 ++++++++++---------- - 2 files changed, 39 insertions(+), 39 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 -@@ -866,41 +866,41 @@ 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_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_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) -@@ -1045,7 +1045,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/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch b/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch deleted file mode 100644 index 5947d385f2..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-10-net-ethernet-mtk_eth_soc-convert-clock-bitmap-to-u64.patch +++ /dev/null @@ -1,132 +0,0 @@ -From a1c9f7d1d24e90294f6a6755b137fcf306851e93 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 25 Jul 2023 01:53:28 +0100 -Subject: [PATCH 104/250] net: ethernet: mtk_eth_soc: convert clock bitmap to - u64 - -The to-be-added MT7988 SoC adds many new clocks which need to be -controlled by the Ethernet driver, which will result in their total -number exceeding 32. -Prepare by converting clock bitmaps into 64-bit types. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/6960a39bb0078cf84d7642a9558e6a91c6cc9df3.1690246066.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 96 +++++++++++---------- - 1 file changed, 49 insertions(+), 47 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -666,54 +666,56 @@ enum mtk_clks_map { - 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)) - - enum mtk_dev_state { - MTK_HW_INIT, -@@ -1046,7 +1048,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/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch b/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch deleted file mode 100644 index 8c24321dd4..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch +++ /dev/null @@ -1,477 +0,0 @@ -From 94f825a7eadfc8b4c8828efdb7705d9703f9c73e Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 25 Jul 2023 01:57:42 +0100 -Subject: [PATCH 105/250] net: ethernet: mtk_eth_soc: add basic support for - MT7988 SoC - -Introduce support for ethernet chip available in MT7988 SoC to -mtk_eth_soc driver. As a first step support only the first GMAC which -is hard-wired to the internal DSA switch having 4 built-in gigabit -Ethernet PHYs. - -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/25c8377095b95d186872eeda7aa055da83e8f0ca.1690246605.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_path.c | 14 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 201 +++++++++++++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 86 +++++++- - 3 files changed, 273 insertions(+), 28 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_path.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c -@@ -43,7 +43,7 @@ static const char *mtk_eth_path_name(u64 - static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) - { - bool updated = true; -- u32 val, mask, set; -+ u32 mask, set, reg; - - switch (path) { - case MTK_ETH_PATH_GMAC1_SGMII: -@@ -59,11 +59,13 @@ static int set_mux_gdm1_to_gmac1_esw(str - break; - } - -- if (updated) { -- val = mtk_r32(eth, MTK_MAC_MISC); -- val = (val & mask) | set; -- mtk_w32(eth, val, MTK_MAC_MISC); -- } -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ reg = MTK_MAC_MISC_V3; -+ else -+ reg = MTK_MAC_MISC; -+ -+ if (updated) -+ mtk_m32(eth, mask, set, reg); - - dev_dbg(eth->dev, "path %s in %s updated = %d\n", - mtk_eth_path_name(path), __func__, updated); ---- 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_ppe = 0x3333, -+ .ppe_base = 0x2000, -+ .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) -@@ -195,7 +287,7 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne - return __raw_readl(eth->base + reg); - } - --static u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg) -+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg) - { - u32 val; - -@@ -369,6 +461,19 @@ static void mtk_gmac0_rgmii_adjust(struc - dev_err(eth->dev, "Missing PLL configuration, ethernet may not work\n"); - } - -+static void mtk_setup_bridge_switch(struct mtk_eth *eth) -+{ -+ /* Force Port1 XGMAC Link Up */ -+ mtk_m32(eth, 0, MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID), -+ MTK_XGMAC_STS(MTK_GMAC1_ID)); -+ -+ /* Adjust GSW bridge IPG to 11 */ -+ mtk_m32(eth, GSWTX_IPG_MASK | GSWRX_IPG_MASK, -+ (GSW_IPG_11 << GSWTX_IPG_SHIFT) | -+ (GSW_IPG_11 << GSWRX_IPG_SHIFT), -+ MTK_GSW_CFG); -+} -+ - static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, - phy_interface_t interface) - { -@@ -438,6 +543,8 @@ static void mtk_mac_config(struct phylin - goto init_err; - } - break; -+ case PHY_INTERFACE_MODE_INTERNAL: -+ break; - default: - goto err_phy; - } -@@ -515,6 +622,15 @@ static void mtk_mac_config(struct phylin - return; - } - -+ /* Setup gmac */ -+ if (mtk_is_netsys_v3_or_greater(eth) && -+ 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)); -+ -+ mtk_setup_bridge_switch(eth); -+ } -+ - return; - - err_phy: -@@ -725,11 +841,15 @@ 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_is_netsys_v3_or_greater(eth)) -+ mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3); -+ - /* Configure MDC Divider */ -- val = mtk_r32(eth, MTK_PPSC); -- val &= ~PPSC_MDC_CFG; -- val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; -- mtk_w32(eth, val, MTK_PPSC); -+ val = FIELD_PREP(PPSC_MDC_CFG, divider); -+ if (!mtk_is_netsys_v3_or_greater(eth)) -+ val |= PPSC_MDC_TURBO; -+ mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC); - - dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); - -@@ -1190,10 +1310,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); - -@@ -4360,6 +4489,17 @@ static int mtk_add_mac(struct mtk_eth *e - mac->phylink_config.supported_interfaces); - } - -+ if (mtk_is_netsys_v3_or_greater(mac->hw) && -+ MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW_BIT) && -+ 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); -+ } -+ - phylink = phylink_create(&mac->phylink_config, - of_fwnode_handle(mac->of_node), - phy_mode, &mtk_phylink_ops); -@@ -4880,6 +5020,24 @@ 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, -+ .version = 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, -@@ -4898,14 +5056,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 -@@ -117,7 +117,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) ({ typeof(x) _x = (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) -@@ -126,6 +127,11 @@ - #define MTK_GDMA_TO_PDMA 0x0 - #define MTK_GDMA_DROP_ALL 0x7777 - -+/* GDM Egress Control Register */ -+#define MTK_GDMA_EG_CTRL(x) ({ typeof(x) _x = (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)) - -@@ -389,7 +395,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)) -@@ -647,6 +672,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, -@@ -663,6 +693,27 @@ 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 - }; - -@@ -716,6 +767,36 @@ enum mtk_clks_map { - 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, -@@ -964,6 +1045,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1) - -+#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) -+ - struct mtk_tx_dma_desc_info { - dma_addr_t addr; - u32 size; -@@ -1309,6 +1392,7 @@ void mtk_stats_update_mac(struct mtk_mac - - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); - u32 mtk_r32(struct mtk_eth *eth, unsigned reg); -+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); - - int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); - int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); diff --git a/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch deleted file mode 100644 index 3dc4662d1a..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 38a7eb76220731eff40602cf433f24880be0a6c2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Thu, 27 Jul 2023 09:02:26 +0200 -Subject: [PATCH 106/250] net: ethernet: mtk_eth_soc: enable page_pool support - for MT7988 SoC - -In order to recycle pages, enable page_pool allocator for MT7988 SoC. - -Tested-by: Daniel Golle -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/fd4e8693980e47385a543e7b002eec0b88bd09df.1690440675.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1658,7 +1658,7 @@ static void mtk_update_rx_cpu_idx(struct - - static bool mtk_page_pool_enabled(struct mtk_eth *eth) - { -- return eth->soc->version == 2; -+ return mtk_is_netsys_v2_or_greater(eth); - } - - static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, diff --git a/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch b/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch deleted file mode 100644 index 32f26d7d27..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 199e7d5a7f03dd377f3a7a458360dbedd71d50ba Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Thu, 27 Jul 2023 09:07:28 +0200 -Subject: [PATCH 107/250] net: ethernet: mtk_eth_soc: enable nft hw - flowtable_offload for MT7988 SoC - -Enable hw Packet Process Engine (PPE) for MT7988 SoC. - -Tested-by: Daniel Golle -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/5e86341b0220a49620dadc02d77970de5ded9efc.1690441576.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ - drivers/net/ethernet/mediatek/mtk_ppe.c | 19 +++++++++++++++---- - drivers/net/ethernet/mediatek/mtk_ppe.h | 19 ++++++++++++++++++- - 3 files changed, 36 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5028,6 +5028,9 @@ static const struct mtk_soc_data mt7988_ - .required_clks = MT7988_CLKS_BITMAP, - .required_pctl = false, - .version = 3, -+ .offload_version = 2, -+ .hash_offset = 4, -+ .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), - .rxd_size = sizeof(struct mtk_rx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -422,13 +422,22 @@ int mtk_foe_entry_set_wdma(struct mtk_et - struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); - u32 *ib2 = mtk_foe_entry_ib2(eth, entry); - -- if (mtk_is_netsys_v2_or_greater(eth)) { -+ switch (eth->soc->version) { -+ case 3: -+ *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; -+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | -+ MTK_FOE_IB2_WDMA_WINFO_V2; -+ l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | -+ FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); -+ break; -+ case 2: - *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; - *ib2 |= FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq) | - MTK_FOE_IB2_WDMA_WINFO_V2; - l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) | - FIELD_PREP(MTK_FOE_WINFO_BSS, bss); -- } else { -+ break; -+ default: - *ib2 &= ~MTK_FOE_IB2_PORT_MG; - *ib2 |= MTK_FOE_IB2_WDMA_WINFO; - if (wdma_idx) -@@ -436,6 +445,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et - l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | - FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | - FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); -+ break; - } - - return 0; -@@ -950,8 +960,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - mtk_ppe_init_foe_table(ppe); - ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); - -- val = MTK_PPE_TB_CFG_ENTRY_80B | -- MTK_PPE_TB_CFG_AGE_NON_L4 | -+ val = MTK_PPE_TB_CFG_AGE_NON_L4 | - MTK_PPE_TB_CFG_AGE_UNBIND | - MTK_PPE_TB_CFG_AGE_TCP | - MTK_PPE_TB_CFG_AGE_UDP | -@@ -967,6 +976,8 @@ void mtk_ppe_start(struct mtk_ppe *ppe) - MTK_PPE_ENTRIES_SHIFT); - if (mtk_is_netsys_v2_or_greater(ppe->eth)) - val |= MTK_PPE_TB_CFG_INFO_SEL; -+ if (!mtk_is_netsys_v3_or_greater(ppe->eth)) -+ val |= MTK_PPE_TB_CFG_ENTRY_80B; - ppe_w32(ppe, MTK_PPE_TB_CFG, val); - - ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -85,6 +85,17 @@ enum { - #define MTK_FOE_WINFO_BSS GENMASK(5, 0) - #define MTK_FOE_WINFO_WCID GENMASK(15, 6) - -+#define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) -+#define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) -+ -+#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) -+#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) -+#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) -+#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) -+#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) -+#define MTK_FOE_WINFO_PAO_HF BIT(23) -+#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) -+ - enum { - MTK_FOE_STATE_INVALID, - MTK_FOE_STATE_UNBIND, -@@ -106,8 +117,13 @@ struct mtk_foe_mac_info { - u16 pppoe_id; - u16 src_mac_lo; - -+ /* netsys_v2 */ - u16 minfo; - u16 winfo; -+ -+ /* netsys_v3 */ -+ u32 w3info; -+ u32 wpao; - }; - - /* software-only entry type */ -@@ -218,6 +234,7 @@ struct mtk_foe_ipv6_6rd { - - #define MTK_FOE_ENTRY_V1_SIZE 80 - #define MTK_FOE_ENTRY_V2_SIZE 96 -+#define MTK_FOE_ENTRY_V3_SIZE 128 - - struct mtk_foe_entry { - u32 ib1; -@@ -228,7 +245,7 @@ struct mtk_foe_entry { - struct mtk_foe_ipv4_dslite dslite; - struct mtk_foe_ipv6 ipv6; - struct mtk_foe_ipv6_6rd ipv6_6rd; -- u32 data[23]; -+ u32 data[31]; - }; - }; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch b/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch deleted file mode 100644 index 876bdd5dd3..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0c024632c1e7ff69914329bfd87bec749b9c0aed Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 2 Aug 2023 04:31:09 +0100 -Subject: [PATCH 108/250] net: ethernet: mtk_eth_soc: support per-flow - accounting on MT7988 - -NETSYS_V3 uses 64 bits for each counters while older SoCs are using -48/40 bits for each counter. -Support reading per-flow byte and package counters on NETSYS_V3. - -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Link: https://lore.kernel.org/r/37a0928fa8c1253b197884c68ce1f54239421ac5.1690946442.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + - drivers/net/ethernet/mediatek/mtk_ppe.c | 21 +++++++++++++------- - drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 2 ++ - 3 files changed, 17 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5030,6 +5030,7 @@ static const struct mtk_soc_data mt7988_ - .version = 3, - .offload_version = 2, - .hash_offset = 4, -+ .has_accounting = true, - .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, - .txrx = { - .txd_size = sizeof(struct mtk_tx_dma_v2), ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -91,7 +91,6 @@ static int mtk_ppe_mib_wait_busy(struct - - static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) - { -- u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; - u32 val, cnt_r0, cnt_r1, cnt_r2; - int ret; - -@@ -106,12 +105,20 @@ static int mtk_mib_entry_read(struct mtk - cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); - cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); - -- byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -- byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -- pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -- pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -- *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -- *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ if (mtk_is_netsys_v3_or_greater(ppe->eth)) { -+ /* 64 bit for each counter */ -+ u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); -+ *bytes = ((u64)cnt_r1 << 32) | cnt_r0; -+ *packets = ((u64)cnt_r3 << 32) | cnt_r2; -+ } else { -+ /* 48 bit byte counter, 40 bit packet counter */ -+ u32 byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); -+ u32 byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); -+ u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); -+ u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); -+ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -+ *packets = (pkt_cnt_high << 16) | pkt_cnt_low; -+ } - - return 0; - } ---- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -163,6 +163,8 @@ enum { - #define MTK_PPE_MIB_SER_R2 0x348 - #define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0) - -+#define MTK_PPE_MIB_SER_R3 0x34c -+ - #define MTK_PPE_MIB_CACHE_CTL 0x350 - #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) - #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) diff --git a/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch b/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch deleted file mode 100644 index 6f1639a572..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-15-net-ethernet-mtk_eth_soc-fix-NULL-pointer-on-hw-rese.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 3b12f42772c26869d60398c1710aa27b27cd945c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 21 Aug 2023 17:12:44 +0100 -Subject: [PATCH 109/250] net: ethernet: mtk_eth_soc: fix NULL pointer on hw - reset - -When a hardware reset is triggered on devices not initializing WED the -calls to mtk_wed_fe_reset and mtk_wed_fe_reset_complete dereference a -pointer on uninitialized stack memory. -Break out of both functions in case a hw_list entry is 0. - -Fixes: 08a764a7c51b ("net: ethernet: mtk_wed: add reset/reset_complete callbacks") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Acked-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/5465c1609b464cc7407ae1530c40821dcdf9d3e6.1692634266.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -214,9 +214,13 @@ void mtk_wed_fe_reset(void) - - for (i = 0; i < ARRAY_SIZE(hw_list); i++) { - struct mtk_wed_hw *hw = hw_list[i]; -- struct mtk_wed_device *dev = hw->wed_dev; -+ struct mtk_wed_device *dev; - int err; - -+ if (!hw) -+ break; -+ -+ dev = hw->wed_dev; - if (!dev || !dev->wlan.reset) - continue; - -@@ -237,8 +241,12 @@ void mtk_wed_fe_reset_complete(void) - - for (i = 0; i < ARRAY_SIZE(hw_list); i++) { - struct mtk_wed_hw *hw = hw_list[i]; -- struct mtk_wed_device *dev = hw->wed_dev; -+ struct mtk_wed_device *dev; -+ -+ if (!hw) -+ break; - -+ dev = hw->wed_dev; - if (!dev || !dev->wlan.reset_complete) - continue; - diff --git a/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch b/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch deleted file mode 100644 index 2190761fdd..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-16-net-ethernet-mtk_eth_soc-fix-register-definitions-fo.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 489aea123d74a846ce746bfdb3efe1e7ad512e0d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:31:24 +0100 -Subject: [PATCH 110/250] net: ethernet: mtk_eth_soc: fix register definitions - for MT7988 - -More register macros need to be adjusted for the 3rd GMAC on MT7988. -Account for added bit in SYSCFG0_SGMII_MASK. - -Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") -Signed-off-by: Daniel Golle -Reviewed-by: Simon Horman -Link: https://lore.kernel.org/r/1c8da012e2ca80939906d85f314138c552139f0f.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -133,10 +133,12 @@ - #define MTK_GDMA_XGDM_SEL BIT(31) - - /* Unicast Filter MAC Address Register - Low */ --#define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) -+#define MTK_GDMA_MAC_ADRL(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x548 : 0x508 + (_x * 0x1000); }) - - /* Unicast Filter MAC Address Register - High */ --#define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000)) -+#define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ -+ 0x54C : 0x50C + (_x * 0x1000); }) - - /* FE global misc reg*/ - #define MTK_FE_GLO_MISC 0x124 -@@ -503,7 +505,7 @@ - #define ETHSYS_SYSCFG0 0x14 - #define SYSCFG0_GE_MASK 0x3 - #define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2))) --#define SYSCFG0_SGMII_MASK GENMASK(9, 8) -+#define SYSCFG0_SGMII_MASK GENMASK(9, 7) - #define SYSCFG0_SGMII_GMAC1 ((2 << 8) & SYSCFG0_SGMII_MASK) - #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) - #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) diff --git a/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch b/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch deleted file mode 100644 index 05a18364d6..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 15a84d1c44ae8c1451c265ee60500588a24e8cd6 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:32:03 +0100 -Subject: [PATCH 111/250] net: ethernet: mtk_eth_soc: add reset bits for MT7988 - -Add bits needed to reset the frame engine on MT7988. - -Fixes: 445eb6448ed3 ("net: ethernet: mtk_eth_soc: add basic support for MT7988 SoC") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/89b6c38380e7a3800c1362aa7575600717bc7543.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 76 +++++++++++++++------ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 +++-- - 2 files changed, 68 insertions(+), 24 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3594,19 +3594,34 @@ static void mtk_hw_reset(struct mtk_eth - { - u32 val; - -- if (mtk_is_netsys_v2_or_greater(eth)) { -+ if (mtk_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ val = RSTCTRL_PPE0_V3; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1_V3; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val |= RSTCTRL_PPE2; -+ -+ val |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; -+ } else if (mtk_is_netsys_v2_or_greater(eth)) { - val = RSTCTRL_PPE0_V2; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= RSTCTRL_PPE1; - } else { - val = RSTCTRL_PPE0; - } - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= RSTCTRL_PPE1; -- - ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); - -- if (mtk_is_netsys_v2_or_greater(eth)) -+ if (mtk_is_netsys_v3_or_greater(eth)) -+ regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, -+ 0x6f8ff); -+ else if (mtk_is_netsys_v2_or_greater(eth)) - regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, - 0x3ffffff); - } -@@ -3632,13 +3647,21 @@ static void mtk_hw_warm_reset(struct mtk - return; - } - -- if (mtk_is_netsys_v2_or_greater(eth)) -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1_V3; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ rst_mask |= RSTCTRL_PPE2; -+ -+ rst_mask |= RSTCTRL_WDMA0 | RSTCTRL_WDMA1 | RSTCTRL_WDMA2; -+ } else if (mtk_is_netsys_v2_or_greater(eth)) { - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; -- else -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ rst_mask |= RSTCTRL_PPE1; -+ } else { - rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -- -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- rst_mask |= RSTCTRL_PPE1; -+ } - - regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); - -@@ -3990,11 +4013,17 @@ static void mtk_prepare_for_reset(struct - u32 val; - int i; - -- /* disabe FE P3 and P4 */ -- val = mtk_r32(eth, MTK_FE_GLO_CFG) | MTK_FE_LINK_DOWN_P3; -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val |= MTK_FE_LINK_DOWN_P4; -- mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ /* set FE PPE ports link down */ -+ for (i = MTK_GMAC1_ID; -+ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); -+ i += 2) { -+ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) | MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val |= MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val |= MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); -+ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); -+ } - - /* adjust PPE configurations to prepare for reset */ - for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) -@@ -4055,11 +4084,18 @@ static void mtk_pending_work(struct work - } - } - -- /* enabe FE P3 and P4 */ -- val = mtk_r32(eth, MTK_FE_GLO_CFG) & ~MTK_FE_LINK_DOWN_P3; -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -- val &= ~MTK_FE_LINK_DOWN_P4; -- mtk_w32(eth, val, MTK_FE_GLO_CFG); -+ /* set FE PPE ports link up */ -+ for (i = MTK_GMAC1_ID; -+ i <= (mtk_is_netsys_v3_or_greater(eth) ? MTK_GMAC3_ID : MTK_GMAC2_ID); -+ i += 2) { -+ val = mtk_r32(eth, MTK_FE_GLO_CFG(i)) & ~MTK_FE_LINK_DOWN_P(PSE_PPE0_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) -+ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE1_PORT); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE2)) -+ val &= ~MTK_FE_LINK_DOWN_P(PSE_PPE2_PORT); -+ -+ mtk_w32(eth, val, MTK_FE_GLO_CFG(i)); -+ } - - clear_bit(MTK_RESETTING, ð->state); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -76,9 +76,8 @@ - #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 - - /* Frame Engine Global Configuration */ --#define MTK_FE_GLO_CFG 0x00 --#define MTK_FE_LINK_DOWN_P3 BIT(11) --#define MTK_FE_LINK_DOWN_P4 BIT(12) -+#define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00) -+#define MTK_FE_LINK_DOWN_P(x) BIT(((x) + 8) % 16) - - /* Frame Engine Global Reset Register */ - #define MTK_RST_GL 0x04 -@@ -522,9 +521,15 @@ - /* ethernet reset control register */ - #define ETHSYS_RSTCTRL 0x34 - #define RSTCTRL_FE BIT(6) -+#define RSTCTRL_WDMA0 BIT(24) -+#define RSTCTRL_WDMA1 BIT(25) -+#define RSTCTRL_WDMA2 BIT(26) - #define RSTCTRL_PPE0 BIT(31) - #define RSTCTRL_PPE0_V2 BIT(30) - #define RSTCTRL_PPE1 BIT(31) -+#define RSTCTRL_PPE0_V3 BIT(29) -+#define RSTCTRL_PPE1_V3 BIT(30) -+#define RSTCTRL_PPE2 BIT(31) - #define RSTCTRL_ETH BIT(23) - - /* ethernet reset check idle register */ -@@ -931,6 +936,7 @@ enum mkt_eth_capabilities { - MTK_QDMA_BIT, - MTK_SOC_MT7628_BIT, - MTK_RSTCTRL_PPE1_BIT, -+ MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, - - /* MUX BITS*/ -@@ -965,6 +971,7 @@ enum mkt_eth_capabilities { - #define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) - #define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) - #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) -+#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ -@@ -1047,7 +1054,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1) - --#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1) -+#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -+ MTK_RSTCTRL_PPE2) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch b/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch deleted file mode 100644 index 74ac8dc898..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch +++ /dev/null @@ -1,254 +0,0 @@ -From 25ce45fe40b574e5d7ffa407f7f2db03e7d5a910 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:32:54 +0100 -Subject: [PATCH 112/250] net: ethernet: mtk_eth_soc: add support for in-SoC - SRAM - -MT7981, MT7986 and MT7988 come with in-SoC SRAM dedicated for Ethernet -DMA rings. Support using the SRAM without breaking existing device tree -bindings, ie. only new SoC starting from MT7988 will have the SRAM -declared as additional resource in device tree. For MT7981 and MT7986 -an offset on top of the main I/O base is used. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e45e0f230c63ad58869e8fe35b95a2fb8925b625.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 88 ++++++++++++++++----- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++- - 2 files changed, 78 insertions(+), 22 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1118,10 +1118,13 @@ static int mtk_init_fq_dma(struct mtk_et - dma_addr_t dma_addr; - int i; - -- eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, -- cnt * soc->txrx.txd_size, -- ð->phy_scratch_ring, -- GFP_KERNEL); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) -+ eth->scratch_ring = eth->sram_base; -+ else -+ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, -+ cnt * soc->txrx.txd_size, -+ ð->phy_scratch_ring, -+ GFP_KERNEL); - if (unlikely(!eth->scratch_ring)) - return -ENOMEM; - -@@ -2429,8 +2432,14 @@ static int mtk_tx_alloc(struct mtk_eth * - if (!ring->buf) - goto no_tx_mem; - -- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, -- &ring->phys, GFP_KERNEL); -+ if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) { -+ ring->dma = eth->sram_base + ring_size * sz; -+ ring->phys = eth->phy_scratch_ring + ring_size * (dma_addr_t)sz; -+ } else { -+ ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, -+ &ring->phys, GFP_KERNEL); -+ } -+ - if (!ring->dma) - goto no_tx_mem; - -@@ -2529,8 +2538,7 @@ static void mtk_tx_clean(struct mtk_eth - kfree(ring->buf); - ring->buf = NULL; - } -- -- if (ring->dma) { -+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { - dma_free_coherent(eth->dma_dev, - ring->dma_size * soc->txrx.txd_size, - ring->dma, ring->phys); -@@ -2549,9 +2557,14 @@ static int mtk_rx_alloc(struct mtk_eth * - { - const struct mtk_reg_map *reg_map = eth->soc->reg_map; - struct mtk_rx_ring *ring; -- int rx_data_len, rx_dma_size; -+ int rx_data_len, rx_dma_size, tx_ring_size; - int i; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ tx_ring_size = MTK_QDMA_RING_SIZE; -+ else -+ tx_ring_size = MTK_DMA_SIZE; -+ - if (rx_flag == MTK_RX_FLAGS_QDMA) { - if (ring_no) - return -EINVAL; -@@ -2586,9 +2599,20 @@ static int mtk_rx_alloc(struct mtk_eth * - ring->page_pool = pp; - } - -- ring->dma = dma_alloc_coherent(eth->dma_dev, -- rx_dma_size * eth->soc->txrx.rxd_size, -- &ring->phys, GFP_KERNEL); -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || -+ rx_flag != MTK_RX_FLAGS_NORMAL) { -+ ring->dma = dma_alloc_coherent(eth->dma_dev, -+ rx_dma_size * eth->soc->txrx.rxd_size, -+ &ring->phys, GFP_KERNEL); -+ } else { -+ struct mtk_tx_ring *tx_ring = ð->tx_ring; -+ -+ ring->dma = tx_ring->dma + tx_ring_size * -+ eth->soc->txrx.txd_size * (ring_no + 1); -+ ring->phys = tx_ring->phys + tx_ring_size * -+ eth->soc->txrx.txd_size * (ring_no + 1); -+ } -+ - if (!ring->dma) - return -ENOMEM; - -@@ -2673,7 +2697,7 @@ static int mtk_rx_alloc(struct mtk_eth * - return 0; - } - --static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) -+static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) - { - int i; - -@@ -2696,7 +2720,7 @@ static void mtk_rx_clean(struct mtk_eth - ring->data = NULL; - } - -- if (ring->dma) { -+ if (!in_sram && ring->dma) { - dma_free_coherent(eth->dma_dev, - ring->dma_size * eth->soc->txrx.rxd_size, - ring->dma, ring->phys); -@@ -3059,7 +3083,7 @@ static void mtk_dma_free(struct mtk_eth - for (i = 0; i < MTK_MAX_DEVS; i++) - if (eth->netdev[i]) - netdev_reset_queue(eth->netdev[i]); -- if (eth->scratch_ring) { -+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { - dma_free_coherent(eth->dma_dev, - MTK_QDMA_RING_SIZE * soc->txrx.txd_size, - eth->scratch_ring, eth->phy_scratch_ring); -@@ -3067,13 +3091,13 @@ static void mtk_dma_free(struct mtk_eth - eth->phy_scratch_ring = 0; - } - mtk_tx_clean(eth); -- mtk_rx_clean(eth, ð->rx_ring[0]); -- mtk_rx_clean(eth, ð->rx_ring_qdma); -+ mtk_rx_clean(eth, ð->rx_ring[0], MTK_HAS_CAPS(soc->caps, MTK_SRAM)); -+ mtk_rx_clean(eth, ð->rx_ring_qdma, false); - - if (eth->hwlro) { - mtk_hwlro_rx_uninit(eth); - for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) -- mtk_rx_clean(eth, ð->rx_ring[i]); -+ mtk_rx_clean(eth, ð->rx_ring[i], false); - } - - kfree(eth->scratch_head); -@@ -4641,7 +4665,7 @@ static int mtk_sgmii_init(struct mtk_eth - - static int mtk_probe(struct platform_device *pdev) - { -- struct resource *res = NULL; -+ struct resource *res = NULL, *res_sram; - struct device_node *mac_np; - struct mtk_eth *eth; - int err, i; -@@ -4661,6 +4685,20 @@ static int mtk_probe(struct platform_dev - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) - eth->ip_align = NET_IP_ALIGN; - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { -+ /* SRAM is actual memory and supports transparent access just like DRAM. -+ * Hence we don't require __iomem being set and don't need to use accessor -+ * functions to read from or write to SRAM. -+ */ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1); -+ if (IS_ERR(eth->sram_base)) -+ return PTR_ERR(eth->sram_base); -+ } else { -+ eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET; -+ } -+ } -+ - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); -@@ -4724,6 +4762,18 @@ static int mtk_probe(struct platform_dev - err = -EINVAL; - goto err_destroy_sgmii; - } -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ res_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (!res_sram) { -+ err = -EINVAL; -+ goto err_destroy_sgmii; -+ } -+ eth->phy_scratch_ring = res_sram->start; -+ } else { -+ eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET; -+ } -+ } - } - - if (eth->soc->offload_version) { ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -139,6 +139,9 @@ - #define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ - 0x54C : 0x50C + (_x * 0x1000); }) - -+/* Internal SRAM offset */ -+#define MTK_ETH_SRAM_OFFSET 0x40000 -+ - /* FE global misc reg*/ - #define MTK_FE_GLO_MISC 0x124 - -@@ -938,6 +941,7 @@ enum mkt_eth_capabilities { - MTK_RSTCTRL_PPE1_BIT, - MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, -+ MTK_SRAM_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -973,6 +977,7 @@ enum mkt_eth_capabilities { - #define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) - #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) -+#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -1048,14 +1053,14 @@ enum mkt_eth_capabilities { - #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ -- MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1 | MTK_SRAM) - - #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ -- MTK_RSTCTRL_PPE1) -+ MTK_RSTCTRL_PPE1 | MTK_SRAM) - - #define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -- MTK_RSTCTRL_PPE2) -+ MTK_RSTCTRL_PPE2 | MTK_SRAM) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; -@@ -1215,6 +1220,7 @@ struct mtk_eth { - struct device *dev; - struct device *dma_dev; - void __iomem *base; -+ void *sram_base; - spinlock_t page_lock; - spinlock_t tx_irq_lock; - spinlock_t rx_irq_lock; diff --git a/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch b/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch deleted file mode 100644 index 1584dfd07c..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0b0d606eb9650fa01dd5621e072aa29a10544399 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 22 Aug 2023 17:33:12 +0100 -Subject: [PATCH 113/250] net: ethernet: mtk_eth_soc: support 36-bit DMA - addressing on MT7988 - -Systems having 4 GiB of RAM and more require DMA addressing beyond the -current 32-bit limit. Starting from MT7988 the hardware now supports -36-bit DMA addressing, let's use that new capability in the driver to -avoid running into swiotlb on systems with 4 GiB of RAM or more. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/95b919c98876c9e49761e44662e7c937479eecb8.1692721443.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++++++++++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 22 +++++++++++++-- - 2 files changed, 48 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1311,6 +1311,10 @@ static void mtk_tx_set_dma_desc_v2(struc - data = TX_DMA_PLEN0(info->size); - if (info->last) - data |= TX_DMA_LS0; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ data |= TX_DMA_PREP_ADDR64(info->addr); -+ - WRITE_ONCE(desc->txd3, data); - - /* set forward port */ -@@ -1980,6 +1984,7 @@ static int mtk_poll_rx(struct napi_struc - bool xdp_flush = false; - int idx; - struct sk_buff *skb; -+ u64 addr64 = 0; - u8 *data, *new_data; - struct mtk_rx_dma_v2 *rxd, trxd; - int done = 0, bytes = 0; -@@ -2095,7 +2100,10 @@ static int mtk_poll_rx(struct napi_struc - goto release_desc; - } - -- dma_unmap_single(eth->dma_dev, trxd.rxd1, -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ addr64 = RX_DMA_GET_ADDR64(trxd.rxd2); -+ -+ dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64), - ring->buf_size, DMA_FROM_DEVICE); - - skb = build_skb(data, ring->frag_size); -@@ -2161,6 +2169,9 @@ release_desc: - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); -+ - ring->calc_idx = idx; - done++; - } -@@ -2653,6 +2664,9 @@ static int mtk_rx_alloc(struct mtk_eth * - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); -+ - rxd->rxd3 = 0; - rxd->rxd4 = 0; - if (mtk_is_netsys_v2_or_greater(eth)) { -@@ -2699,6 +2713,7 @@ static int mtk_rx_alloc(struct mtk_eth * - - static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) - { -+ u64 addr64 = 0; - int i; - - if (ring->data && ring->dma) { -@@ -2712,7 +2727,10 @@ static void mtk_rx_clean(struct mtk_eth - if (!rxd->rxd1) - continue; - -- dma_unmap_single(eth->dma_dev, rxd->rxd1, -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ addr64 = RX_DMA_GET_ADDR64(rxd->rxd2); -+ -+ dma_unmap_single(eth->dma_dev, ((u64)rxd->rxd1 | addr64), - ring->buf_size, DMA_FROM_DEVICE); - mtk_rx_put_buff(ring, ring->data[i], false); - } -@@ -4699,6 +4717,14 @@ static int mtk_probe(struct platform_dev - } - } - -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { -+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); -+ if (err) { -+ dev_err(&pdev->dev, "Wrong DMA config\n"); -+ return -EINVAL; -+ } -+ } -+ - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -331,6 +331,14 @@ - #define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) - #define TX_DMA_SWC BIT(14) - #define TX_DMA_PQID GENMASK(3, 0) -+#define TX_DMA_ADDR64_MASK GENMASK(3, 0) -+#if IS_ENABLED(CONFIG_64BIT) -+# define TX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(TX_DMA_ADDR64_MASK, (x))) << 32) -+# define TX_DMA_PREP_ADDR64(x) FIELD_PREP(TX_DMA_ADDR64_MASK, ((x) >> 32)) -+#else -+# define TX_DMA_GET_ADDR64(x) (0) -+# define TX_DMA_PREP_ADDR64(x) (0) -+#endif - - /* PDMA on MT7628 */ - #define TX_DMA_DONE BIT(31) -@@ -343,6 +351,14 @@ - #define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) - #define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) - #define RX_DMA_VTAG BIT(15) -+#define RX_DMA_ADDR64_MASK GENMASK(3, 0) -+#if IS_ENABLED(CONFIG_64BIT) -+# define RX_DMA_GET_ADDR64(x) (((u64)FIELD_GET(RX_DMA_ADDR64_MASK, (x))) << 32) -+# define RX_DMA_PREP_ADDR64(x) FIELD_PREP(RX_DMA_ADDR64_MASK, ((x) >> 32)) -+#else -+# define RX_DMA_GET_ADDR64(x) (0) -+# define RX_DMA_PREP_ADDR64(x) (0) -+#endif - - /* QDMA descriptor rxd3 */ - #define RX_DMA_VID(x) ((x) & VLAN_VID_MASK) -@@ -942,6 +958,7 @@ enum mkt_eth_capabilities { - MTK_RSTCTRL_PPE2_BIT, - MTK_U3_COPHY_V2_BIT, - MTK_SRAM_BIT, -+ MTK_36BIT_DMA_BIT, - - /* MUX BITS*/ - MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, -@@ -978,6 +995,7 @@ enum mkt_eth_capabilities { - #define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT) - #define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) - #define MTK_SRAM BIT_ULL(MTK_SRAM_BIT) -+#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT) - - #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ - BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) -@@ -1059,8 +1077,8 @@ enum mkt_eth_capabilities { - MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ - MTK_RSTCTRL_PPE1 | MTK_SRAM) - --#define MT7988_CAPS (MTK_GDM1_ESW | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ -- MTK_RSTCTRL_PPE2 | MTK_SRAM) -+#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \ -+ MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) - - struct mtk_tx_dma_desc_info { - dma_addr_t addr; diff --git a/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch b/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch deleted file mode 100644 index 5b27458eb8..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch +++ /dev/null @@ -1,44 +0,0 @@ -From e10a35abb3da12b812cfb6fc6137926a0c81e39a Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 10 Sep 2023 22:40:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix uninitialized variable - -Variable dma_addr in function mtk_poll_rx can be uninitialized on -some of the error paths. In practise this doesn't matter, even random -data present in uninitialized stack memory can safely be used in the -way it happens in the error path. - -However, in order to make Smatch happy make sure the variable is -always initialized. - -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1988,11 +1988,11 @@ static int mtk_poll_rx(struct napi_struc - u8 *data, *new_data; - struct mtk_rx_dma_v2 *rxd, trxd; - int done = 0, bytes = 0; -+ dma_addr_t dma_addr = DMA_MAPPING_ERROR; - - while (done < budget) { - unsigned int pktlen, *rxdcsum; - struct net_device *netdev; -- dma_addr_t dma_addr; - u32 hash, reason; - int mac = 0; - -@@ -2169,7 +2169,8 @@ release_desc: - else - rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) && -+ likely(dma_addr != DMA_MAPPING_ERROR)) - rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); - - ring->calc_idx = idx; diff --git a/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch b/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch deleted file mode 100644 index ac3e3a3e67..0000000000 --- a/target/linux/generic/backport-6.6/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 5a124b1fd3e6cb15a943f0cdfe96aa8f6d3d2f39 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 9 Sep 2023 20:41:56 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix pse_port configuration for - MT7988 - -MT7988 SoC support 3 NICs. Fix pse_port configuration in -mtk_flow_set_output_device routine if the traffic is offloaded to eth2. -Rely on mtk_pse_port definitions. - -Fixes: 88efedf517e6 ("net: ethernet: mtk_eth_soc: enable nft hw flowtable_offload for MT7988 SoC") -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -214,9 +214,11 @@ mtk_flow_set_output_device(struct mtk_et - dsa_port = mtk_flow_get_dsa_port(&dev); - - if (dev == eth->netdev[0]) -- pse_port = 1; -+ pse_port = PSE_GDM1_PORT; - else if (dev == eth->netdev[1]) -- pse_port = 2; -+ pse_port = PSE_GDM2_PORT; -+ else if (dev == eth->netdev[2]) -+ pse_port = PSE_GDM3_PORT; - else - return -EOPNOTSUPP; - diff --git a/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch b/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch deleted file mode 100644 index 46da5b283f..0000000000 --- a/target/linux/generic/backport-6.6/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch +++ /dev/null @@ -1,271 +0,0 @@ -From: Felix Fietkau -Date: Mon, 20 Mar 2023 11:44:30 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows - from wlan devices - -WED version 2 (on MT7986 and later) can offload flows originating from wireless -devices. In order to make that work, ndo_setup_tc needs to be implemented on -the netdevs. This adds the required code to offload flows coming in from WED, -while keeping track of the incoming wed index used for selecting the correct -PPE device. - -Signed-off-by: Felix Fietkau ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + - .../net/ethernet/mediatek/mtk_ppe_offload.c | 37 ++++--- - drivers/net/ethernet/mediatek/mtk_wed.c | 101 ++++++++++++++++++ - include/linux/soc/mediatek/mtk_wed.h | 6 ++ - 4 files changed, 133 insertions(+), 14 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1435,6 +1435,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk - int mtk_eth_offload_init(struct mtk_eth *eth); - int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, - void *type_data); -+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, -+ int ppe_index); -+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); - - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -237,7 +237,8 @@ out: - } - - static int --mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) -+mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, -+ int ppe_index) - { - struct flow_rule *rule = flow_cls_offload_flow_rule(f); - struct flow_action_entry *act; -@@ -454,6 +455,7 @@ mtk_flow_offload_replace(struct mtk_eth - entry->cookie = f->cookie; - memcpy(&entry->data, &foe, sizeof(entry->data)); - entry->wed_index = wed_index; -+ entry->ppe_index = ppe_index; - - err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry); - if (err < 0) -@@ -522,25 +524,15 @@ mtk_flow_offload_stats(struct mtk_eth *e - - static DEFINE_MUTEX(mtk_flow_offload_mutex); - --static int --mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls, -+ int ppe_index) - { -- struct flow_cls_offload *cls = type_data; -- struct net_device *dev = cb_priv; -- struct mtk_mac *mac = netdev_priv(dev); -- struct mtk_eth *eth = mac->hw; - int err; - -- if (!tc_can_offload(dev)) -- return -EOPNOTSUPP; -- -- if (type != TC_SETUP_CLSFLOWER) -- return -EOPNOTSUPP; -- - mutex_lock(&mtk_flow_offload_mutex); - switch (cls->command) { - case FLOW_CLS_REPLACE: -- err = mtk_flow_offload_replace(eth, cls); -+ err = mtk_flow_offload_replace(eth, cls, ppe_index); - break; - case FLOW_CLS_DESTROY: - err = mtk_flow_offload_destroy(eth, cls); -@@ -558,6 +550,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ - } - - static int -+mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+{ -+ struct flow_cls_offload *cls = type_data; -+ struct net_device *dev = cb_priv; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ -+ if (!tc_can_offload(dev)) -+ return -EOPNOTSUPP; -+ -+ if (type != TC_SETUP_CLSFLOWER) -+ return -EOPNOTSUPP; -+ -+ return mtk_flow_offload_cmd(eth, cls, 0); -+} -+ -+static int - mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f) - { - struct mtk_mac *mac = netdev_priv(dev); ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -13,6 +13,8 @@ - #include - #include - #include -+#include -+#include - #include "mtk_eth_soc.h" - #include "mtk_wed_regs.h" - #include "mtk_wed.h" -@@ -41,6 +43,11 @@ - static struct mtk_wed_hw *hw_list[2]; - static DEFINE_MUTEX(hw_lock); - -+struct mtk_wed_flow_block_priv { -+ struct mtk_wed_hw *hw; -+ struct net_device *dev; -+}; -+ - static void - wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) - { -@@ -1753,6 +1760,99 @@ out: - mutex_unlock(&hw_lock); - } - -+static int -+mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+{ -+ struct mtk_wed_flow_block_priv *priv = cb_priv; -+ struct flow_cls_offload *cls = type_data; -+ struct mtk_wed_hw *hw = priv->hw; -+ -+ if (!tc_can_offload(priv->dev)) -+ return -EOPNOTSUPP; -+ -+ if (type != TC_SETUP_CLSFLOWER) -+ return -EOPNOTSUPP; -+ -+ return mtk_flow_offload_cmd(hw->eth, cls, hw->index); -+} -+ -+static int -+mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev, -+ struct flow_block_offload *f) -+{ -+ struct mtk_wed_flow_block_priv *priv; -+ static LIST_HEAD(block_cb_list); -+ struct flow_block_cb *block_cb; -+ struct mtk_eth *eth = hw->eth; -+ flow_setup_cb_t *cb; -+ -+ if (!eth->soc->offload_version) -+ return -EOPNOTSUPP; -+ -+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) -+ return -EOPNOTSUPP; -+ -+ cb = mtk_wed_setup_tc_block_cb; -+ f->driver_block_list = &block_cb_list; -+ -+ switch (f->command) { -+ case FLOW_BLOCK_BIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (block_cb) { -+ flow_block_cb_incref(block_cb); -+ return 0; -+ } -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->hw = hw; -+ priv->dev = dev; -+ block_cb = flow_block_cb_alloc(cb, dev, priv, NULL); -+ if (IS_ERR(block_cb)) { -+ kfree(priv); -+ return PTR_ERR(block_cb); -+ } -+ -+ flow_block_cb_incref(block_cb); -+ flow_block_cb_add(block_cb, f); -+ list_add_tail(&block_cb->driver_list, &block_cb_list); -+ return 0; -+ case FLOW_BLOCK_UNBIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (!block_cb) -+ return -ENOENT; -+ -+ if (!flow_block_cb_decref(block_cb)) { -+ flow_block_cb_remove(block_cb, f); -+ list_del(&block_cb->driver_list); -+ kfree(block_cb->cb_priv); -+ } -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+static int -+mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev, -+ enum tc_setup_type type, void *type_data) -+{ -+ struct mtk_wed_hw *hw = wed->hw; -+ -+ if (hw->version < 2) -+ return -EOPNOTSUPP; -+ -+ switch (type) { -+ case TC_SETUP_BLOCK: -+ case TC_SETUP_FT: -+ return mtk_wed_setup_tc_block(hw, dev, type_data); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ - void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, - void __iomem *wdma, phys_addr_t wdma_phy, - int index) -@@ -1772,6 +1872,7 @@ void mtk_wed_add_hw(struct device_node * - .irq_set_mask = mtk_wed_irq_set_mask, - .detach = mtk_wed_detach, - .ppe_check = mtk_wed_ppe_check, -+ .setup_tc = mtk_wed_setup_tc, - }; - struct device_node *eth_np = eth->dev->of_node; - struct platform_device *pdev; ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - - #define MTK_WED_TX_QUEUES 2 - #define MTK_WED_RX_QUEUES 2 -@@ -180,6 +181,8 @@ struct mtk_wed_ops { - - u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask); - void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); -+ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, -+ enum tc_setup_type type, void *type_data); - }; - - extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; -@@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic - (_dev)->ops->msg_update(_dev, _id, _msg, _len) - #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev) - #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) -+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ -+ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) - #else - static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) - { -@@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active - #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV - #define mtk_wed_device_stop(_dev) do {} while (0) - #define mtk_wed_device_dma_reset(_dev) do {} while (0) -+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP - #endif - - #endif diff --git a/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch b/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch deleted file mode 100644 index b1796641a3..0000000000 --- a/target/linux/generic/backport-6.6/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Felix Fietkau -Date: Mon, 20 Mar 2023 15:37:55 +0100 -Subject: [PATCH] net: ethernet: mediatek: mtk_ppe: prefer newly added l2 - flows over existing ones - -When a device is roaming between interfaces and a new flow entry is created, -we should assume that its output device is more up to date than whatever -entry existed already. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -656,10 +656,20 @@ void mtk_foe_entry_clear(struct mtk_ppe - static int - mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) - { -+ struct mtk_flow_entry *prev; -+ - entry->type = MTK_FLOW_TYPE_L2; - -- return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node, -- mtk_flow_l2_ht_params); -+ prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &entry->l2_node, -+ mtk_flow_l2_ht_params); -+ if (likely(!prev)) -+ return 0; -+ -+ if (IS_ERR(prev)) -+ return PTR_ERR(prev); -+ -+ return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node, -+ &entry->l2_node, mtk_flow_l2_ht_params); - } - - int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) diff --git a/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch b/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch deleted file mode 100644 index a224b62624..0000000000 --- a/target/linux/generic/backport-6.6/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Lorenzo Bianconi -Date: Sun, 27 Aug 2023 19:31:41 +0200 -Subject: [PATCH] net: ethernet: mtk_wed: add some more info in wed_txinfo_show - handler - -Add some new info in Wireless Ethernet Dispatcher wed_txinfo_show -debugfs handler useful during debugging. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/3390292655d568180b73d2a25576f61aa63310e5.1693157377.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -127,8 +127,17 @@ wed_txinfo_show(struct seq_file *s, void - DUMP_WDMA_RING(WDMA_RING_RX(0)), - DUMP_WDMA_RING(WDMA_RING_RX(1)), - -- DUMP_STR("TX FREE"), -+ DUMP_STR("WED TX FREE"), - DUMP_WED(WED_RX_MIB(0)), -+ DUMP_WED_RING(WED_RING_RX(0)), -+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), -+ DUMP_WED(WED_RX_MIB(1)), -+ DUMP_WED_RING(WED_RING_RX(1)), -+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), -+ -+ DUMP_STR("WED WPDMA TX FREE"), -+ DUMP_WED_RING(WED_WPDMA_RING_RX(0)), -+ DUMP_WED_RING(WED_WPDMA_RING_RX(1)), - }; - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; ---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h -@@ -266,6 +266,8 @@ struct mtk_wdma_desc { - - #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) - #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) -+#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) - - #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) - #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) diff --git a/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch b/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch deleted file mode 100644 index df6edfdf94..0000000000 --- a/target/linux/generic/backport-6.6/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch +++ /dev/null @@ -1,47 +0,0 @@ -From: Lorenzo Bianconi -Date: Sun, 27 Aug 2023 19:33:47 +0200 -Subject: [PATCH] net: ethernet: mtk_wed: minor change in wed_{tx,rx}info_show - -No functional changes, just cosmetic ones. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/71e046c72a978745f0435af265dda610aa9bfbcf.1693157578.git.lorenzo@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct - } - } - -- - static int - wed_txinfo_show(struct seq_file *s, void *data) - { -@@ -142,10 +141,8 @@ wed_txinfo_show(struct seq_file *s, void - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; - -- if (!dev) -- return 0; -- -- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ if (dev) -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); - - return 0; - } -@@ -217,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void - struct mtk_wed_hw *hw = s->private; - struct mtk_wed_device *dev = hw->wed_dev; - -- if (!dev) -- return 0; -- -- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); -+ if (dev) -+ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch b/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch deleted file mode 100644 index c0320ad6f9..0000000000 --- a/target/linux/generic/backport-6.6/777-v6.2-04-net-dsa-qca8k-introduce-single-mii-read-write-lo-hi.patch +++ /dev/null @@ -1,150 +0,0 @@ -From cfbd6de588ef659c198083205dc954a6d3ed2aec Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 29 Dec 2022 17:33:35 +0100 -Subject: [PATCH 4/5] net: dsa: qca8k: introduce single mii read/write lo/hi - -It may be useful to read/write just the lo or hi half of a reg. - -This is especially useful for phy poll with the use of mdio master. -The mdio master reg is composed by the first 16 bit related to setup and -the other half with the returned data or data to write. - -Refactor the mii function to permit single mii read/write of lo or hi -half of the reg. - -Tested-by: Ronald Wahl -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 106 ++++++++++++++++++++++++------- - 1 file changed, 84 insertions(+), 22 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -37,42 +37,104 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u - } - - static int --qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+qca8k_mii_write_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) - { - int ret; -+ u16 lo; - -- ret = bus->read(bus, phy_id, regnum); -- if (ret >= 0) { -- *val = ret; -- ret = bus->read(bus, phy_id, regnum + 1); -- *val |= ret << 16; -- } -+ lo = val & 0xffff; -+ ret = bus->write(bus, phy_id, regnum, lo); -+ if (ret < 0) -+ dev_err_ratelimited(&bus->dev, -+ "failed to write qca8k 32bit lo register\n"); -+ -+ return ret; -+} - -- if (ret < 0) { -+static int -+qca8k_mii_write_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+{ -+ int ret; -+ u16 hi; -+ -+ hi = (u16)(val >> 16); -+ ret = bus->write(bus, phy_id, regnum, hi); -+ if (ret < 0) - dev_err_ratelimited(&bus->dev, -- "failed to read qca8k 32bit register\n"); -- *val = 0; -- return ret; -- } -+ "failed to write qca8k 32bit hi register\n"); - -+ return ret; -+} -+ -+static int -+qca8k_mii_read_lo(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+{ -+ int ret; -+ -+ ret = bus->read(bus, phy_id, regnum); -+ if (ret < 0) -+ goto err; -+ -+ *val = ret & 0xffff; - return 0; -+ -+err: -+ dev_err_ratelimited(&bus->dev, -+ "failed to read qca8k 32bit lo register\n"); -+ *val = 0; -+ -+ return ret; - } - --static void --qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+static int -+qca8k_mii_read_hi(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) - { -- u16 lo, hi; - int ret; - -- lo = val & 0xffff; -- hi = (u16)(val >> 16); -+ ret = bus->read(bus, phy_id, regnum); -+ if (ret < 0) -+ goto err; - -- ret = bus->write(bus, phy_id, regnum, lo); -- if (ret >= 0) -- ret = bus->write(bus, phy_id, regnum + 1, hi); -+ *val = ret << 16; -+ return 0; -+ -+err: -+ dev_err_ratelimited(&bus->dev, -+ "failed to read qca8k 32bit hi register\n"); -+ *val = 0; -+ -+ return ret; -+} -+ -+static int -+qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) -+{ -+ u32 hi, lo; -+ int ret; -+ -+ *val = 0; -+ -+ ret = qca8k_mii_read_lo(bus, phy_id, regnum, &lo); - if (ret < 0) -- dev_err_ratelimited(&bus->dev, -- "failed to write qca8k 32bit register\n"); -+ goto err; -+ -+ ret = qca8k_mii_read_hi(bus, phy_id, regnum + 1, &hi); -+ if (ret < 0) -+ goto err; -+ -+ *val = lo | hi; -+ -+err: -+ return ret; -+} -+ -+static void -+qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) -+{ -+ if (qca8k_mii_write_lo(bus, phy_id, regnum, val) < 0) -+ return; -+ -+ qca8k_mii_write_hi(bus, phy_id, regnum + 1, val); - } - - static int diff --git a/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch b/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch deleted file mode 100644 index dcafad0fd5..0000000000 --- a/target/linux/generic/backport-6.6/777-v6.2-05-net-dsa-qca8k-improve-mdio-master-read-write-by-usin.patch +++ /dev/null @@ -1,73 +0,0 @@ -From a4165830ca237f2b3318faf62562bce8ce12a389 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 29 Dec 2022 17:33:36 +0100 -Subject: [PATCH 5/5] net: dsa: qca8k: improve mdio master read/write by using - single lo/hi - -Improve mdio master read/write by using singe mii read/write lo/hi. - -In a read and write we need to poll the mdio master regs in a busy loop -to check for a specific bit present in the upper half of the reg. We can -ignore the other half since it won't contain useful data. This will save -an additional useless read for each read and write operation. - -In a read operation the returned data is present in the mdio master reg -lower half. We can ignore the other half since it won't contain useful -data. This will save an additional useless read for each read operation. - -In a read operation it's needed to just set the hi half of the mdio -master reg as the lo half will be replaced by the result. This will save -an additional useless write for each read operation. - -Tested-by: Ronald Wahl -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -754,9 +754,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus - - qca8k_split_addr(reg, &r1, &r2, &page); - -- ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, -+ ret = read_poll_timeout(qca8k_mii_read_hi, ret1, !(val & mask), 0, - QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -- bus, 0x10 | r2, r1, &val); -+ bus, 0x10 | r2, r1 + 1, &val); - - /* Check if qca8k_read has failed for a different reason - * before returnting -ETIMEDOUT -@@ -798,7 +798,7 @@ qca8k_mdio_write(struct qca8k_priv *priv - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); - - mutex_unlock(&bus->mdio_lock); - -@@ -828,18 +828,18 @@ qca8k_mdio_read(struct qca8k_priv *priv, - if (ret) - goto exit; - -- qca8k_mii_write32(bus, 0x10 | r2, r1, val); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, val); - - ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - if (ret) - goto exit; - -- ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); -+ ret = qca8k_mii_read_lo(bus, 0x10 | r2, r1, &val); - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write_hi(bus, 0x10 | r2, r1 + 1, 0); - - mutex_unlock(&bus->mdio_lock); - diff --git a/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch b/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch deleted file mode 100644 index 9331fd536d..0000000000 --- a/target/linux/generic/backport-6.6/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e03cea60c3db8c6b011cc36ecef9281dff8377f3 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jan 2023 21:35:16 +0100 -Subject: [PATCH] net: dsa: qca8k: add QCA8K_ATU_TABLE_SIZE define for fdb - access - -Add and use QCA8K_ATU_TABLE_SIZE instead of hardcoding the ATU size with -a pure number and using sizeof on the array. - -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-common.c | 10 ++++++---- - drivers/net/dsa/qca/qca8k.h | 2 ++ - 2 files changed, 8 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -150,11 +150,12 @@ static int qca8k_busy_wait(struct qca8k_ - - static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) - { -- u32 reg[3]; -+ u32 reg[QCA8K_ATU_TABLE_SIZE]; - int ret; - - /* load the ARL table into an array */ -- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); -+ ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); - if (ret) - return ret; - -@@ -178,7 +179,7 @@ static int qca8k_fdb_read(struct qca8k_p - static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, - const u8 *mac, u8 aging) - { -- u32 reg[3] = { 0 }; -+ u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 }; - - /* vid - 83:72 */ - reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); -@@ -195,7 +196,8 @@ static void qca8k_fdb_write(struct qca8k - reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); - - /* load the array into the ARL table */ -- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); -+ qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); - } - - static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -148,6 +148,8 @@ - #define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 - - /* Lookup registers */ -+#define QCA8K_ATU_TABLE_SIZE 3 /* 12 bytes wide table / sizeof(u32) */ -+ - #define QCA8K_REG_ATU_DATA0 0x600 - #define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24) - #define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16) diff --git a/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch b/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch deleted file mode 100644 index b8f8071b0a..0000000000 --- a/target/linux/generic/backport-6.6/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch +++ /dev/null @@ -1,261 +0,0 @@ -From c766e077d927e1775902c18827205ea2ade3a35d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jan 2023 21:35:17 +0100 -Subject: [PATCH] net: dsa: qca8k: convert to regmap read/write API - -Convert qca8k to regmap read/write bulk API. The mgmt eth can write up -to 32 bytes of data at times. Currently we use a custom function to do -it but regmap now supports declaration of read/write bulk even without a -bus. - -Drop the custom function and rework the regmap function to this new -implementation. - -Rework the qca8k_fdb_read/write function to use the new -regmap_bulk_read/write as the old qca8k_bulk_read/write are now dropped. - -Cc: Mark Brown -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 92 ++++++++++++++++++++++++------ - drivers/net/dsa/qca/qca8k-common.c | 47 ++------------- - drivers/net/dsa/qca/qca8k.h | 3 - - 3 files changed, 77 insertions(+), 65 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8 - } - - static int --qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) -+qca8k_read_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t *val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - int ret; - -- if (!qca8k_read_eth(priv, reg, val, sizeof(*val))) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -451,16 +447,12 @@ exit: - } - - static int --qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) -+qca8k_write_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - int ret; - -- if (!qca8k_write_eth(priv, reg, &val, sizeof(val))) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -477,17 +469,14 @@ exit: - } - - static int --qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) -+qca8k_regmap_update_bits_mii(struct qca8k_priv *priv, uint32_t reg, -+ uint32_t mask, uint32_t write_val) - { -- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; - -- if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) -- return 0; -- - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -510,17 +499,84 @@ exit: - return ret; - } - -+static int -+qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len, -+ void *val_buf, size_t val_len) -+{ -+ int i, count = val_len / sizeof(u32), ret; -+ u32 reg = *(u32 *)reg_buf & U16_MAX; -+ struct qca8k_priv *priv = ctx; -+ -+ if (priv->mgmt_master && -+ !qca8k_read_eth(priv, reg, val_buf, val_len)) -+ return 0; -+ -+ /* loop count times and increment reg of 4 */ -+ for (i = 0; i < count; i++, reg += sizeof(u32)) { -+ ret = qca8k_read_mii(priv, reg, val_buf + i); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len, -+ const void *val_buf, size_t val_len) -+{ -+ int i, count = val_len / sizeof(u32), ret; -+ u32 reg = *(u32 *)reg_buf & U16_MAX; -+ struct qca8k_priv *priv = ctx; -+ u32 *val = (u32 *)val_buf; -+ -+ if (priv->mgmt_master && -+ !qca8k_write_eth(priv, reg, val, val_len)) -+ return 0; -+ -+ /* loop count times, increment reg of 4 and increment val ptr to -+ * the next value -+ */ -+ for (i = 0; i < count; i++, reg += sizeof(u32), val++) { -+ ret = qca8k_write_mii(priv, reg, *val); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_bulk_write(void *ctx, const void *data, size_t bytes) -+{ -+ return qca8k_bulk_gather_write(ctx, data, sizeof(u16), data + sizeof(u16), -+ bytes - sizeof(u16)); -+} -+ -+static int -+qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) -+{ -+ struct qca8k_priv *priv = ctx; -+ -+ if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) -+ return 0; -+ -+ return qca8k_regmap_update_bits_mii(priv, reg, mask, write_val); -+} -+ - static struct regmap_config qca8k_regmap_config = { - .reg_bits = 16, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x16ac, /* end MIB - Port6 range */ -- .reg_read = qca8k_regmap_read, -- .reg_write = qca8k_regmap_write, -+ .read = qca8k_bulk_read, -+ .write = qca8k_bulk_write, - .reg_update_bits = qca8k_regmap_update_bits, - .rd_table = &qca8k_readable_table, - .disable_locking = true, /* Locking is handled by qca8k read/write */ - .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ -+ .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ -+ .max_raw_write = 32, - }; - - static int -@@ -2112,8 +2168,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, - - static const struct qca8k_info_ops qca8xxx_ops = { - .autocast_mib = qca8k_get_ethtool_stats_eth, -- .read_eth = qca8k_read_eth, -- .write_eth = qca8k_write_eth, - }; - - static const struct qca8k_match_data qca8327 = { ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_r - .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), - }; - --/* TODO: remove these extra ops when we can support regmap bulk read/write */ --static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) --{ -- int i, count = len / sizeof(u32), ret; -- -- if (priv->mgmt_master && priv->info->ops->read_eth && -- !priv->info->ops->read_eth(priv, reg, val, len)) -- return 0; -- -- for (i = 0; i < count; i++) { -- ret = regmap_read(priv->regmap, reg + (i * 4), val + i); -- if (ret < 0) -- return ret; -- } -- -- return 0; --} -- --/* TODO: remove these extra ops when we can support regmap bulk read/write */ --static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len) --{ -- int i, count = len / sizeof(u32), ret; -- u32 tmp; -- -- if (priv->mgmt_master && priv->info->ops->write_eth && -- !priv->info->ops->write_eth(priv, reg, val, len)) -- return 0; -- -- for (i = 0; i < count; i++) { -- tmp = val[i]; -- -- ret = regmap_write(priv->regmap, reg + (i * 4), tmp); -- if (ret < 0) -- return ret; -- } -- -- return 0; --} -- - static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) - { - u32 val; -@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_p - int ret; - - /* load the ARL table into an array */ -- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, -- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); -+ ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE); - if (ret) - return ret; - -@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k - reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); - - /* load the array into the ARL table */ -- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, -- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); -+ regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg, -+ QCA8K_ATU_TABLE_SIZE); - } - - static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -330,9 +330,6 @@ struct qca8k_priv; - - struct qca8k_info_ops { - int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data); -- /* TODO: remove these extra ops when we can support regmap bulk read/write */ -- int (*read_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); -- int (*write_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); - }; - - struct qca8k_match_data { diff --git a/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch b/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch deleted file mode 100644 index 3619440f07..0000000000 --- a/target/linux/generic/backport-6.6/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 2c39dd025da489cf87d26469d9f5ff19715324a0 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 24 Jul 2023 05:25:28 +0200 -Subject: [PATCH 1/4] net: dsa: qca8k: enable use_single_write for qca8xxx - -The qca8xxx switch supports 2 way to write reg values, a slow way using -mdio and a fast way by sending specially crafted mgmt packet to -read/write reg. - -The fast way can support up to 32 bytes of data as eth packet are used -to send/receive. - -This correctly works for almost the entire regmap of the switch but with -the use of some kernel selftests for dsa drivers it was found a funny -and interesting hw defect/limitation. - -For some specific reg, bulk write won't work and will result in writing -only part of the requested regs resulting in half data written. This was -especially hard to track and discover due to the total strangeness of -the problem and also by the specific regs where this occurs. - -This occurs in the specific regs of the ATU table, where multiple entry -needs to be written to compose the entire entry. -It was discovered that with a bulk write of 12 bytes on -QCA8K_REG_ATU_DATA0 only QCA8K_REG_ATU_DATA0 and QCA8K_REG_ATU_DATA2 -were written, but QCA8K_REG_ATU_DATA1 was always zero. -Tcpdump was used to make sure the specially crafted packet was correct -and this was confirmed. - -The problem was hard to track as the lack of QCA8K_REG_ATU_DATA1 -resulted in an entry somehow possible as the first bytes of the mac -address are set in QCA8K_REG_ATU_DATA0 and the entry type is set in -QCA8K_REG_ATU_DATA2. - -Funlly enough writing QCA8K_REG_ATU_DATA1 results in the same problem -with QCA8K_REG_ATU_DATA2 empty and QCA8K_REG_ATU_DATA1 and -QCA8K_REG_ATU_FUNC correctly written. -A speculation on the problem might be that there are some kind of -indirection internally when accessing these regs and they can't be -accessed all together, due to the fact that it's really a table mapped -somewhere in the switch SRAM. - -Even more funny is the fact that every other reg was tested with all -kind of combination and they are not affected by this problem. Read -operation was also tested and always worked so it's not affected by this -problem. - -The problem is not present if we limit writing a single reg at times. - -To handle this hardware defect, enable use_single_write so that bulk -api can correctly split the write in multiple different operation -effectively reverting to a non-bulk write. - -Cc: Mark Brown -Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") -Signed-off-by: Christian Marangi -Cc: stable@vger.kernel.org -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -575,8 +575,11 @@ static struct regmap_config qca8k_regmap - .rd_table = &qca8k_readable_table, - .disable_locking = true, /* Locking is handled by qca8k read/write */ - .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ -- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ -- .max_raw_write = 32, -+ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */ -+ /* ATU regs suffer from a bug where some data are not correctly -+ * written. Disable bulk write to correctly write ATU entry. -+ */ -+ .use_single_write = true, - }; - - static int diff --git a/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch b/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch deleted file mode 100644 index d31789370e..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:10 +0200 -Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off - if standalone - -Address learning should initially be turned off by the driver for port -operation in standalone mode, then the DSA core handles changes to it -via ds->ops->port_bridge_flags(). - -Currently this is not the case for qca8k where learning is enabled -unconditionally in qca8k_setup for every user port. - -Handle ports configured in standalone mode by making the learning -configurable and not enabling it by default. - -Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to -enable learning for bridge that request it and tweak -.port_stp_state_set to correctly disable learning when port is -configured in standalone mode. - -Signed-off-by: Christian Marangi -Reviewed-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++-- - drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ - drivers/net/dsa/qca/qca8k.h | 6 ++++ - 3 files changed, 58 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1905,9 +1905,8 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -- /* Enable ARP Auto-learning by default */ -- ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_LEARN); -+ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -+ QCA8K_PORT_LOOKUP_LEARN); - if (ret) - return ret; - -@@ -2013,6 +2012,8 @@ static const struct dsa_switch_ops qca8k - .port_change_mtu = qca8k_port_change_mtu, - .port_max_mtu = qca8k_port_max_mtu, - .port_stp_state_set = qca8k_port_stp_state_set, -+ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, -+ .port_bridge_flags = qca8k_port_bridge_flags, - .port_bridge_join = qca8k_port_bridge_join, - .port_bridge_leave = qca8k_port_bridge_leave, - .port_fast_age = qca8k_port_fast_age, ---- a/drivers/net/dsa/qca/qca8k-common.c -+++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch - return 0; - } - -+static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, -+ bool learning) -+{ -+ struct qca8k_priv *priv = ds->priv; -+ -+ if (learning) -+ return regmap_set_bits(priv->regmap, -+ QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+ else -+ return regmap_clear_bits(priv->regmap, -+ QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+} -+ - void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) - { -+ struct dsa_port *dp = dsa_to_port(ds, port); - struct qca8k_priv *priv = ds->priv; -+ bool learning = false; - u32 stp_state; - - switch (state) { -@@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa - break; - case BR_STATE_LEARNING: - stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; -+ learning = dp->learning; - break; - case BR_STATE_FORWARDING: -+ learning = dp->learning; -+ fallthrough; - default: - stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; - break; -@@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa - - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), - QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); -+ -+ qca8k_port_configure_learning(ds, port, learning); -+} -+ -+int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ if (flags.mask & ~BR_LEARNING) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ int ret; -+ -+ if (flags.mask & BR_LEARNING) { -+ ret = qca8k_port_configure_learning(ds, port, -+ flags.val & BR_LEARNING); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; - } - - int qca8k_port_bridge_join(struct dsa_switch *ds, int port, ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch - - /* Common bridge function */ - void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); -+int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack); -+int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack); - int qca8k_port_bridge_join(struct dsa_switch *ds, int port, - struct dsa_bridge bridge, - bool *tx_fwd_offload, diff --git a/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch b/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch deleted file mode 100644 index 4b457f67de..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 18e8feae4a807994e4906d659116d249bfecd4c5 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:11 +0200 -Subject: [PATCH 2/4] net: dsa: qca8k: limit user ports access to the first CPU - port on setup - -In preparation for multi-CPU support, set CPU port LOOKUP MEMBER outside -the port loop and setup the LOOKUP MEMBER mask for user ports only to -the first CPU port. - -This is to handle flooding condition where every CPU port is set as -target and prevent packet duplication for unknown frames from user ports. - -Secondary CPU port LOOKUP MEMBER mask will be setup later when -port_change_master will be implemented. - -Signed-off-by: Christian Marangi -Reviewed-by: Simon Horman -Reviewed-by: Florian Fainelli -Reviewed-by: Vladimir Oltean -Link: https://lore.kernel.org/r/20230730074113.21889-3-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1885,18 +1885,16 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -+ /* CPU port gets connected to all user ports of the switch */ -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), -+ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -+ if (ret) -+ return ret; -+ - /* Setup connection between CPU port & user ports - * Configure specific switch configuration for ports - */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) { -- /* CPU port gets connected to all user ports of the switch */ -- if (dsa_is_cpu_port(ds, i)) { -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -- if (ret) -- return ret; -- } -- - /* Individual user ports get connected to CPU port only */ - if (dsa_is_user_port(ds, i)) { - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), diff --git a/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch b/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch deleted file mode 100644 index f556628b5b..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch +++ /dev/null @@ -1,111 +0,0 @@ -From a9108b0712bf018dc69020864b21485b71b17dfc Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:12 +0200 -Subject: [PATCH 3/4] net: dsa: qca8k: move qca8xxx hol fixup to separate - function - -Move qca8xxx hol fixup to separate function to tidy things up and to -permit using a more efficent loop in future patch. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-4-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 78 +++++++++++++++++--------------- - 1 file changed, 42 insertions(+), 36 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1795,6 +1795,46 @@ static int qca8k_connect_tag_protocol(st - return 0; - } - -+static void qca8k_setup_hol_fixup(struct qca8k_priv *priv, int port) -+{ -+ u32 mask; -+ -+ switch (port) { -+ /* The 2 CPU port and port 5 requires some different -+ * priority than any other ports. -+ */ -+ case 0: -+ case 5: -+ case 6: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); -+ break; -+ default: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); -+ } -+ regmap_write(priv->regmap, QCA8K_REG_PORT_HOL_CTRL0(port), mask); -+ -+ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN; -+ regmap_update_bits(priv->regmap, QCA8K_REG_PORT_HOL_CTRL1(port), -+ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN, -+ mask); -+} -+ - static int - qca8k_setup(struct dsa_switch *ds) - { -@@ -1930,42 +1970,8 @@ qca8k_setup(struct dsa_switch *ds) - * missing settings to improve switch stability under load condition. - * This problem is limited to qca8337 and other qca8k switch are not affected. - */ -- if (priv->switch_id == QCA8K_ID_QCA8337) { -- switch (i) { -- /* The 2 CPU port and port 5 requires some different -- * priority than any other ports. -- */ -- case 0: -- case 5: -- case 6: -- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | -- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); -- break; -- default: -- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | -- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | -- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); -- } -- qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); -- -- mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | -- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_WRED_EN; -- qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), -- QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | -- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -- QCA8K_PORT_HOL_CTRL1_WRED_EN, -- mask); -- } -+ if (priv->switch_id == QCA8K_ID_QCA8337) -+ qca8k_setup_hol_fixup(priv, i); - } - - /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ diff --git a/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch b/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch deleted file mode 100644 index faa0142ca9..0000000000 --- a/target/linux/generic/backport-6.6/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 01e6f8ad8d26ced14b0cf288c42e55d03a7c5070 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 30 Jul 2023 09:41:13 +0200 -Subject: [PATCH 4/4] net: dsa: qca8k: use dsa_for_each macro instead of for - loop - -Convert for loop to dsa_for_each macro to save some redundant write on -unconnected/unused port and tidy things up. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230730074113.21889-5-ansuelsmth@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 107 ++++++++++++++++--------------- - 1 file changed, 54 insertions(+), 53 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1839,7 +1839,8 @@ static int - qca8k_setup(struct dsa_switch *ds) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; -- int cpu_port, ret, i; -+ struct dsa_port *dp; -+ int cpu_port, ret; - u32 mask; - - cpu_port = qca8k_find_cpu_port(ds); -@@ -1890,27 +1891,27 @@ qca8k_setup(struct dsa_switch *ds) - dev_warn(priv->dev, "mib init failed"); - - /* Initial setup of all ports */ -- for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ dsa_switch_for_each_port(dp, ds) { - /* Disable forwarding by default on all ports */ -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(dp->index), - QCA8K_PORT_LOOKUP_MEMBER, 0); - if (ret) - return ret; -+ } - -- /* Enable QCA header mode on all cpu ports */ -- if (dsa_is_cpu_port(ds, i)) { -- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), -- FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | -- FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); -- if (ret) { -- dev_err(priv->dev, "failed enabling QCA header mode"); -- return ret; -- } -+ /* Disable MAC by default on all user ports */ -+ dsa_switch_for_each_user_port(dp, ds) -+ qca8k_port_set_status(priv, dp->index, 0); -+ -+ /* Enable QCA header mode on all cpu ports */ -+ dsa_switch_for_each_cpu_port(dp, ds) { -+ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(dp->index), -+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | -+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); -+ if (ret) { -+ dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); -+ return ret; - } -- -- /* Disable MAC by default on all user ports */ -- if (dsa_is_user_port(ds, i)) -- qca8k_port_set_status(priv, i, 0); - } - - /* Forward all unknown frames to CPU port for Linux processing -@@ -1932,48 +1933,48 @@ qca8k_setup(struct dsa_switch *ds) - return ret; - - /* Setup connection between CPU port & user ports -- * Configure specific switch configuration for ports -+ * Individual user ports get connected to CPU port only - */ -- for (i = 0; i < QCA8K_NUM_PORTS; i++) { -- /* Individual user ports get connected to CPU port only */ -- if (dsa_is_user_port(ds, i)) { -- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, -- BIT(cpu_port)); -- if (ret) -- return ret; -- -- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_LEARN); -- if (ret) -- return ret; -- -- /* For port based vlans to work we need to set the -- * default egress vid -- */ -- ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), -- QCA8K_EGREES_VLAN_PORT_MASK(i), -- QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); -- if (ret) -- return ret; -- -- ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), -- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -- if (ret) -- return ret; -- } -+ dsa_switch_for_each_user_port(dp, ds) { -+ u8 port = dp->index; - -- /* The port 5 of the qca8337 have some problem in flood condition. The -- * original legacy driver had some specific buffer and priority settings -- * for the different port suggested by the QCA switch team. Add this -- * missing settings to improve switch stability under load condition. -- * This problem is limited to qca8337 and other qca8k switch are not affected. -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_MEMBER, -+ BIT(cpu_port)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_LEARN); -+ if (ret) -+ return ret; -+ -+ /* For port based vlans to work we need to set the -+ * default egress vid - */ -- if (priv->switch_id == QCA8K_ID_QCA8337) -- qca8k_setup_hol_fixup(priv, i); -+ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), -+ QCA8K_EGREES_VLAN_PORT_MASK(port), -+ QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); -+ if (ret) -+ return ret; -+ -+ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), -+ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -+ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -+ if (ret) -+ return ret; - } - -+ /* The port 5 of the qca8337 have some problem in flood condition. The -+ * original legacy driver had some specific buffer and priority settings -+ * for the different port suggested by the QCA switch team. Add this -+ * missing settings to improve switch stability under load condition. -+ * This problem is limited to qca8337 and other qca8k switch are not affected. -+ */ -+ if (priv->switch_id == QCA8K_ID_QCA8337) -+ dsa_switch_for_each_available_port(dp, ds) -+ qca8k_setup_hol_fixup(priv, dp->index); -+ - /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ - if (priv->switch_id == QCA8K_ID_QCA8327) { - mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | diff --git a/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch b/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch deleted file mode 100644 index 632f422d1f..0000000000 --- a/target/linux/generic/backport-6.6/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5652d1741574eb89cc02576e50ee3e348bd6dd77 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Wed, 4 Oct 2023 11:19:03 +0200 -Subject: [PATCH 1/2] net: dsa: qca8k: fix regmap bulk read/write methods on - big endian systems -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit c766e077d927 ("net: dsa: qca8k: convert to regmap read/write -API") introduced bulk read/write methods to qca8k's regmap. - -The regmap bulk read/write methods get the register address in a buffer -passed as a void pointer parameter (the same buffer contains also the -read/written values). The register address occupies only as many bytes -as it requires at the beginning of this buffer. For example if the -.reg_bits member in regmap_config is 16 (as is the case for this -driver), the register address occupies only the first 2 bytes in this -buffer, so it can be cast to u16. - -But the original commit implementing these bulk read/write methods cast -the buffer to u32: - u32 reg = *(u32 *)reg_buf & U16_MAX; -taking the first 4 bytes. This works on little endian systems where the -first 2 bytes of the buffer correspond to the low 16-bits, but it -obviously cannot work on big endian systems. - -Fix this by casting the beginning of the buffer to u16 as - u32 reg = *(u16 *)reg_buf; - -Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") -Signed-off-by: Marek Behún -Tested-by: Christian Marangi -Reviewed-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -504,8 +504,8 @@ qca8k_bulk_read(void *ctx, const void *r - void *val_buf, size_t val_len) - { - int i, count = val_len / sizeof(u32), ret; -- u32 reg = *(u32 *)reg_buf & U16_MAX; - struct qca8k_priv *priv = ctx; -+ u32 reg = *(u16 *)reg_buf; - - if (priv->mgmt_master && - !qca8k_read_eth(priv, reg, val_buf, val_len)) -@@ -526,8 +526,8 @@ qca8k_bulk_gather_write(void *ctx, const - const void *val_buf, size_t val_len) - { - int i, count = val_len / sizeof(u32), ret; -- u32 reg = *(u32 *)reg_buf & U16_MAX; - struct qca8k_priv *priv = ctx; -+ u32 reg = *(u16 *)reg_buf; - u32 *val = (u32 *)val_buf; - - if (priv->mgmt_master && diff --git a/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch b/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch deleted file mode 100644 index 8010076fc0..0000000000 --- a/target/linux/generic/backport-6.6/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch +++ /dev/null @@ -1,514 +0,0 @@ -From patchwork Thu Mar 9 10:57:44 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: Daniel Golle -X-Patchwork-Id: 13167235 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -Date: Thu, 9 Mar 2023 10:57:44 +0000 -From: Daniel Golle -To: netdev@vger.kernel.org, linux-mediatek@lists.infradead.org, - linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, - Russell King , - Heiner Kallweit , - Lorenzo Bianconi , - Mark Lee , - John Crispin , Felix Fietkau , - AngeloGioacchino Del Regno - , - Matthias Brugger , - DENG Qingfang , - Landen Chao , - Sean Wang , - Paolo Abeni , - Jakub Kicinski , - Eric Dumazet , - "David S. Miller" , - Vladimir Oltean , - Florian Fainelli , - Andrew Lunn , - Vladimir Oltean -Cc: =?iso-8859-1?q?Bj=F8rn?= Mork , - Frank Wunderlich , - Alexander Couzens -Subject: [PATCH net-next v13 11/16] net: dsa: mt7530: use external PCS driver -Message-ID: - <2ac2ee40d3b0e705461b50613fda6a7edfdbc4b3.1678357225.git.daniel@makrotopia.org> -References: -MIME-Version: 1.0 -Content-Disposition: inline -In-Reply-To: -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -Implement regmap access wrappers, for now only to be used by the -pcs-mtk driver. -Make use of external PCS driver and drop the reduntant implementation -in mt7530.c. -As a nice side effect the SGMII registers can now also more easily be -inspected for debugging via /sys/kernel/debug/regmap. - -Reviewed-by: Russell King (Oracle) -Tested-by: Bjørn Mork -Signed-off-by: Daniel Golle -Tested-by: Frank Wunderlich ---- - drivers/net/dsa/Kconfig | 1 + - drivers/net/dsa/mt7530.c | 277 ++++++++++----------------------------- - drivers/net/dsa/mt7530.h | 47 +------ - 3 files changed, 71 insertions(+), 254 deletions(-) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -37,6 +37,7 @@ config NET_DSA_MT7530 - tristate "MediaTek MT753x and MT7621 Ethernet switch support" - select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY -+ select PCS_MTK_LYNXI - help - This enables support for the MediaTek MT7530, MT7531, and MT7621 - Ethernet switch chips. ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2615,128 +2616,11 @@ static int mt7531_rgmii_setup(struct mt7 - return 0; - } - --static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -- phy_interface_t interface, int speed, int duplex) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- unsigned int val; -- -- /* For adjusting speed and duplex of SGMII force mode. */ -- if (interface != PHY_INTERFACE_MODE_SGMII || -- phylink_autoneg_inband(mode)) -- return; -- -- /* SGMII force mode setting */ -- val = mt7530_read(priv, MT7531_SGMII_MODE(port)); -- val &= ~MT7531_SGMII_IF_MODE_MASK; -- -- switch (speed) { -- case SPEED_10: -- val |= MT7531_SGMII_FORCE_SPEED_10; -- break; -- case SPEED_100: -- val |= MT7531_SGMII_FORCE_SPEED_100; -- break; -- case SPEED_1000: -- val |= MT7531_SGMII_FORCE_SPEED_1000; -- break; -- } -- -- /* MT7531 SGMII 1G force mode can only work in full duplex mode, -- * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -- * -- * The speed check is unnecessary as the MAC capabilities apply -- * this restriction. --rmk -- */ -- if ((speed == SPEED_10 || speed == SPEED_100) && -- duplex != DUPLEX_FULL) -- val |= MT7531_SGMII_FORCE_HALF_DUPLEX; -- -- mt7530_write(priv, MT7531_SGMII_MODE(port), val); --} -- - static bool mt753x_is_mac_port(u32 port) - { - return (port == 5 || port == 6); - } - --static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, -- phy_interface_t interface) --{ -- u32 val; -- -- if (!mt753x_is_mac_port(port)) -- return -EINVAL; -- -- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -- MT7531_SGMII_PHYA_PWD); -- -- val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); -- val &= ~MT7531_RG_TPHY_SPEED_MASK; -- /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B -- * encoding. -- */ -- val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ? -- MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G; -- mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); -- -- mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -- -- /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex -- * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -- */ -- mt7530_rmw(priv, MT7531_SGMII_MODE(port), -- MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS, -- MT7531_SGMII_FORCE_SPEED_1000); -- -- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -- -- return 0; --} -- --static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, -- phy_interface_t interface) --{ -- if (!mt753x_is_mac_port(port)) -- return -EINVAL; -- -- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -- MT7531_SGMII_PHYA_PWD); -- -- mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), -- MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G); -- -- mt7530_set(priv, MT7531_SGMII_MODE(port), -- MT7531_SGMII_REMOTE_FAULT_DIS | -- MT7531_SGMII_SPEED_DUPLEX_AN); -- -- mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port), -- MT7531_SGMII_TX_CONFIG_MASK, 1); -- -- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -- -- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART); -- -- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -- -- return 0; --} -- --static void mt7531_pcs_an_restart(struct phylink_pcs *pcs) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- u32 val; -- -- /* Only restart AN when AN is enabled */ -- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- if (val & MT7531_SGMII_AN_ENABLE) { -- val |= MT7531_SGMII_AN_RESTART; -- mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -- } --} -- - static int - mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - phy_interface_t interface) -@@ -2759,11 +2643,11 @@ mt7531_mac_config(struct dsa_switch *ds, - phydev = dp->slave->phydev; - return mt7531_rgmii_setup(priv, port, interface, phydev); - case PHY_INTERFACE_MODE_SGMII: -- return mt7531_sgmii_setup_mode_an(priv, port, interface); - case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: -- return mt7531_sgmii_setup_mode_force(priv, port, interface); -+ /* handled in SGMII PCS driver */ -+ return 0; - default: - return -EINVAL; - } -@@ -2788,11 +2672,11 @@ mt753x_phylink_mac_select_pcs(struct dsa - - switch (interface) { - case PHY_INTERFACE_MODE_TRGMII: -+ return &priv->pcs[port].pcs; - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_2500BASEX: -- return &priv->pcs[port].pcs; -- -+ return priv->ports[port].sgmii_pcs; - default: - return NULL; - } -@@ -3033,86 +2917,6 @@ static void mt7530_pcs_get_state(struct - state->pause |= MLO_PAUSE_TX; - } - --static int --mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, -- struct phylink_link_state *state) --{ -- u32 status, val; -- u16 config_reg; -- -- status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- state->link = !!(status & MT7531_SGMII_LINK_STATUS); -- state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE); -- if (state->interface == PHY_INTERFACE_MODE_SGMII && -- (status & MT7531_SGMII_AN_ENABLE)) { -- val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port)); -- config_reg = val >> 16; -- -- switch (config_reg & LPA_SGMII_SPD_MASK) { -- case LPA_SGMII_1000: -- state->speed = SPEED_1000; -- break; -- case LPA_SGMII_100: -- state->speed = SPEED_100; -- break; -- case LPA_SGMII_10: -- state->speed = SPEED_10; -- break; -- default: -- dev_err(priv->dev, "invalid sgmii PHY speed\n"); -- state->link = false; -- return -EINVAL; -- } -- -- if (config_reg & LPA_SGMII_FULL_DUPLEX) -- state->duplex = DUPLEX_FULL; -- else -- state->duplex = DUPLEX_HALF; -- } -- -- return 0; --} -- --static void --mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port, -- struct phylink_link_state *state) --{ -- unsigned int val; -- -- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -- state->link = !!(val & MT7531_SGMII_LINK_STATUS); -- if (!state->link) -- return; -- -- state->an_complete = state->link; -- -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -- state->speed = SPEED_2500; -- else -- state->speed = SPEED_1000; -- -- state->duplex = DUPLEX_FULL; -- state->pause = MLO_PAUSE_NONE; --} -- --static void mt7531_pcs_get_state(struct phylink_pcs *pcs, -- struct phylink_link_state *state) --{ -- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; -- int port = pcs_to_mt753x_pcs(pcs)->port; -- -- if (state->interface == PHY_INTERFACE_MODE_SGMII) { -- mt7531_sgmii_pcs_get_state_an(priv, port, state); -- return; -- } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) || -- (state->interface == PHY_INTERFACE_MODE_2500BASEX)) { -- mt7531_sgmii_pcs_get_state_inband(priv, port, state); -- return; -- } -- -- state->link = false; --} -- - static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, -@@ -3132,18 +2936,57 @@ static const struct phylink_pcs_ops mt75 - .pcs_an_restart = mt7530_pcs_an_restart, - }; - --static const struct phylink_pcs_ops mt7531_pcs_ops = { -- .pcs_validate = mt753x_pcs_validate, -- .pcs_get_state = mt7531_pcs_get_state, -- .pcs_config = mt753x_pcs_config, -- .pcs_an_restart = mt7531_pcs_an_restart, -- .pcs_link_up = mt7531_pcs_link_up, -+static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ *val = mt7530_read(priv, reg); -+ return 0; -+}; -+ -+static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ mt7530_write(priv, reg, val); -+ return 0; -+}; -+ -+static int mt7530_regmap_update_bits(void *context, unsigned int reg, -+ unsigned int mask, unsigned int val) -+{ -+ struct mt7530_priv *priv = context; -+ -+ mt7530_rmw(priv, reg, mask, val); -+ return 0; -+}; -+ -+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, -+}; -+ -+#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 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)), - }; - - static int - mt753x_setup(struct dsa_switch *ds) - { - struct mt7530_priv *priv = ds->priv; -+ struct regmap *regmap; - int i, ret; - - /* Initialise the PCS devices */ -@@ -3151,8 +2994,6 @@ mt753x_setup(struct dsa_switch *ds) - priv->pcs[i].pcs.ops = priv->info->pcs_ops; - priv->pcs[i].priv = priv; - priv->pcs[i].port = i; -- if (mt753x_is_mac_port(i)) -- priv->pcs[i].pcs.poll = 1; - } - - ret = priv->info->sw_setup(ds); -@@ -3167,6 +3008,16 @@ 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); -+ } -+ - return ret; - } - -@@ -3258,7 +3109,7 @@ static const struct mt753x_info mt753x_t - }, - [ID_MT7531] = { - .id = ID_MT7531, -- .pcs_ops = &mt7531_pcs_ops, -+ .pcs_ops = &mt7530_pcs_ops, - .sw_setup = mt7531_setup, - .phy_read = mt7531_ind_phy_read, - .phy_write = mt7531_ind_phy_write, -@@ -3366,7 +3217,7 @@ static void - mt7530_remove(struct mdio_device *mdiodev) - { - struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -- int ret = 0; -+ int ret = 0, i; - - if (!priv) - return; -@@ -3385,6 +3236,10 @@ mt7530_remove(struct mdio_device *mdiode - mt7530_free_irq(priv); - - dsa_unregister_switch(priv->ds); -+ -+ for (i = 0; i < 2; ++i) -+ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); -+ - mutex_destroy(&priv->reg_mutex); - } - ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -371,47 +371,8 @@ enum mt7530_vlan_port_acc_frm { - CCR_TX_OCT_CNT_BAD) - - /* MT7531 SGMII register group */ --#define MT7531_SGMII_REG_BASE 0x5000 --#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ -- ((p) - 5) * 0x1000 + (r)) -- --/* Register forSGMII PCS_CONTROL_1 */ --#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) --#define MT7531_SGMII_LINK_STATUS BIT(18) --#define MT7531_SGMII_AN_ENABLE BIT(12) --#define MT7531_SGMII_AN_RESTART BIT(9) --#define MT7531_SGMII_AN_COMPLETE BIT(21) -- --/* Register for SGMII PCS_SPPED_ABILITY */ --#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08) --#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0) --#define MT7531_SGMII_TX_CONFIG BIT(0) -- --/* Register for SGMII_MODE */ --#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) --#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) --#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) --#define MT7531_SGMII_FORCE_DUPLEX BIT(4) --#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2) --#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) --#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) --#define MT7531_SGMII_FORCE_SPEED_10 0 --#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1) -- --enum mt7531_sgmii_force_duplex { -- MT7531_SGMII_FORCE_FULL_DUPLEX = 0, -- MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10, --}; -- --/* Fields of QPHY_PWR_STATE_CTRL */ --#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) --#define MT7531_SGMII_PHYA_PWD BIT(4) -- --/* Values of SGMII SPEED */ --#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) --#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) --#define MT7531_RG_TPHY_SPEED_1_25G 0x0 --#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) -+#define MT7531_SGMII_REG_BASE(p) (0x5000 + ((p) - 5) * 0x1000) -+#define MT7531_PHYA_CTRL_SIGNAL3 0x128 - - /* Register for system reset */ - #define MT7530_SYS_CTRL 0x7000 -@@ -710,13 +671,13 @@ struct mt7530_fdb { - * @pm: The matrix used to show all connections with the port. - * @pvid: The VLAN specified is to be considered a PVID at ingress. Any - * untagged frames will be assigned to the related VLAN. -- * @vlan_filtering: The flags indicating whether the port that can recognize -- * VLAN-tagged frames. -+ * @sgmii_pcs: Pointer to PCS instance for SerDes ports - */ - struct mt7530_port { - bool enable; - u32 pm; - u16 pvid; -+ struct phylink_pcs *sgmii_pcs; - }; - - /* Port 5 interface select definitions */ diff --git a/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch b/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch deleted file mode 100644 index 4d024b063a..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c3552d3f85f06cf4b4818bd84c4fcc09d8d45165 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:19 +0100 -Subject: [PATCH 01/13] 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-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch b/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch deleted file mode 100644 index 5667449296..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch +++ /dev/null @@ -1,111 +0,0 @@ -From b896355fc4988216d4f38582d07add9252a795ae Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:30 +0100 -Subject: [PATCH 02/13] 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 -@@ -2968,26 +2968,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 */ -@@ -3009,15 +3039,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-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch b/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch deleted file mode 100644 index 3b4689fb19..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 33396408776385f3d2f6069646169a6b5b28e3b3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:40 +0100 -Subject: [PATCH 03/13] 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 -@@ -2941,7 +2941,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; - }; - -@@ -2949,23 +2949,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 -@@ -2991,6 +2993,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-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch b/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch deleted file mode 100644 index 04033f14f4..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 743cba4345cb366248f9d375c6a9e50243dc0677 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:17:52 +0100 -Subject: [PATCH 04/13] 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 -@@ -2937,22 +2958,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) - { -@@ -2965,7 +2970,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, - }; -@@ -2998,7 +3003,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); -@@ -3163,6 +3168,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; - -@@ -3242,6 +3248,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 -@@ -754,6 +754,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 -@@ -774,6 +775,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-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch b/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch deleted file mode 100644 index 6c5bebdd80..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f3cf1d06e2aef644b426c23b4bb570780b1f8d47 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:04 +0100 -Subject: [PATCH 05/13] 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 -@@ -3049,12 +3049,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; - } - -@@ -3171,6 +3165,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; - -@@ -3263,6 +3258,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-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch b/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch deleted file mode 100644 index a8933d2cf4..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch +++ /dev/null @@ -1,273 +0,0 @@ -From e4729ae7c095c0c87794bff47ea43e35d69de986 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:16 +0100 -Subject: [PATCH 06/13] 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; - } -@@ -1125,7 +1125,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; - -@@ -1136,7 +1135,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; -@@ -1157,7 +1156,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; - } -@@ -1958,10 +1957,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) { -@@ -1997,7 +1996,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 -@@ -2006,7 +2005,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-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch b/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch deleted file mode 100644 index 6c68dc0c4f..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0d7ae94a0c581f86939bebec0b6ccd66e640d1d8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:28 +0100 -Subject: [PATCH 07/13] 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 -@@ -689,24 +689,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-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch b/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch deleted file mode 100644 index dc4fcb6aa1..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 4d632005c90e253c000d0db73b7cdb9d8dc2e2dd Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:39 +0100 -Subject: [PATCH 08/13] 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 -@@ -3177,44 +3177,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; - -@@ -3228,23 +3205,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)) { -@@ -3253,12 +3260,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-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch b/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch deleted file mode 100644 index 5df859d2df..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 69b838d2629e6b82bcd9e0ab3c1c03f46e5e01d3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:18:50 +0100 -Subject: [PATCH 09/13] 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 -@@ -3295,6 +3295,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); -@@ -3313,15 +3324,10 @@ 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); - } - - static void mt7530_shutdown(struct mdio_device *mdiodev) diff --git a/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch deleted file mode 100644 index d203711884..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ /dev/null @@ -1,691 +0,0 @@ -From 8eceed6dbd74067dbf4d8e39f14734f4d2f35176 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:13 +0100 -Subject: [PATCH 10/13] 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 | 16 +- - 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, 301 insertions(+), 258 deletions(-) - create mode 100644 drivers/net/dsa/mt7530-mdio.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13062,6 +13062,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_RZN1_A5PSW) += rzn1_a5psw.o - obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.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) - { -@@ -2975,72 +2926,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) - { -@@ -3099,7 +2984,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, -@@ -3133,8 +3018,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, -@@ -3167,16 +3053,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; -@@ -3213,88 +3092,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) -@@ -3304,55 +3104,7 @@ 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); --} -- --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); -+EXPORT_SYMBOL_GPL(mt7530_remove_common); - - MODULE_AUTHOR("Sean Wang "); - MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -814,4 +814,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-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch b/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch deleted file mode 100644 index 01011ed1a0..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch +++ /dev/null @@ -1,47 +0,0 @@ -From a52cadbf76593f8fcb2f4f62cb006e3f2a22ad06 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:28 +0100 -Subject: [PATCH 11/13] 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-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch deleted file mode 100644 index 63bf0e77fa..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ /dev/null @@ -1,421 +0,0 @@ -From b361015763fedea439f13b336b15ef7bdf1f7d4f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 3 Apr 2023 02:19:40 +0100 -Subject: [PATCH 12/13] 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 | 135 +++++++++++++++++++++++++++++++++- - drivers/net/dsa/mt7530.h | 12 +-- - 6 files changed, 253 insertions(+), 10 deletions(-) - create mode 100644 drivers/net/dsa/mt7530-mmio.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13060,9 +13060,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_RZN1_A5PSW) += rzn1_a5psw.o - obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.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 -@@ -2005,6 +2005,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; -@@ -2038,8 +2079,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; -@@ -2538,6 +2586,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) - { -@@ -2614,6 +2681,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) - { -@@ -2683,7 +2761,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 */ -@@ -2761,7 +2840,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; -@@ -2841,6 +2921,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) - { -@@ -2986,6 +3081,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, -@@ -3054,6 +3170,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*/ -@@ -302,9 +303,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-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch b/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch deleted file mode 100644 index 5b5f25e7af..0000000000 --- a/target/linux/generic/backport-6.6/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch +++ /dev/null @@ -1,118 +0,0 @@ -From eb1dd407b4be7ca38166a38c56c8edf52c6a399f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 16 Apr 2023 13:08:14 +0100 -Subject: [PATCH 13/13] 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 -@@ -3048,6 +3048,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 -@@ -748,10 +748,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; -@@ -770,7 +770,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*/ -@@ -778,6 +777,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-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch deleted file mode 100644 index 4cdd67cdcc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ /dev/null @@ -1,1724 +0,0 @@ -From 70479a40954cf353e87a486997a3477108c75aa9 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 28 Oct 2022 17:26:21 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8521 gigabit ethernet - phy - -Add a driver for the motorcomm yt8521 gigabit ethernet phy. We have verified - the driver on StarFive VisionFive development board, which is developed by - Shanghai StarFive Technology Co., Ltd.. On the board, yt8521 gigabit ethernet - phy works in utp mode, RGMII interface, supports 1000M/100M/10M speeds, and - wol(magic package). - -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 1 + - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 1635 ++++++++++++++++++++++++++++++++++- - 3 files changed, 1635 insertions(+), 3 deletions(-) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h - - MOTORCOMM PHY DRIVER - M: Peter Geis -+M: Frank - L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/phy/motorcomm.c ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511 gigabit PHY. -+ Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,15 +1,106 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Driver for Motorcomm PHYs -+ * Motorcomm 8511/8521 PHY driver. - * - * Author: Peter Geis -+ * Author: Frank - */ - -+#include - #include - #include - #include - - #define PHY_ID_YT8511 0x0000010a -+#define PHY_ID_YT8521 0x0000011A -+ -+/* YT8521 Register Overview -+ * UTP Register space | FIBER Register space -+ * ------------------------------------------------------------ -+ * | UTP MII | FIBER MII | -+ * | UTP MMD | | -+ * | UTP Extended | FIBER Extended | -+ * ------------------------------------------------------------ -+ * | Common Extended | -+ * ------------------------------------------------------------ -+ */ -+ -+/* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */ -+ -+/* Specific Function Control Register */ -+#define YTPHY_SPECIFIC_FUNCTION_CONTROL_REG 0x10 -+ -+/* 2b00 Manual MDI configuration -+ * 2b01 Manual MDIX configuration -+ * 2b10 Reserved -+ * 2b11 Enable automatic crossover for all modes *default* -+ */ -+#define YTPHY_SFCR_MDI_CROSSOVER_MODE_MASK (BIT(6) | BIT(5)) -+#define YTPHY_SFCR_CROSSOVER_EN BIT(3) -+#define YTPHY_SFCR_SQE_TEST_EN BIT(2) -+#define YTPHY_SFCR_POLARITY_REVERSAL_EN BIT(1) -+#define YTPHY_SFCR_JABBER_DIS BIT(0) -+ -+/* Specific Status Register */ -+#define YTPHY_SPECIFIC_STATUS_REG 0x11 -+#define YTPHY_SSR_SPEED_MODE_OFFSET 14 -+ -+#define YTPHY_SSR_SPEED_MODE_MASK (BIT(15) | BIT(14)) -+#define YTPHY_SSR_SPEED_10M 0x0 -+#define YTPHY_SSR_SPEED_100M 0x1 -+#define YTPHY_SSR_SPEED_1000M 0x2 -+#define YTPHY_SSR_DUPLEX_OFFSET 13 -+#define YTPHY_SSR_DUPLEX BIT(13) -+#define YTPHY_SSR_PAGE_RECEIVED BIT(12) -+#define YTPHY_SSR_SPEED_DUPLEX_RESOLVED BIT(11) -+#define YTPHY_SSR_LINK BIT(10) -+#define YTPHY_SSR_MDIX_CROSSOVER BIT(6) -+#define YTPHY_SSR_DOWNGRADE BIT(5) -+#define YTPHY_SSR_TRANSMIT_PAUSE BIT(3) -+#define YTPHY_SSR_RECEIVE_PAUSE BIT(2) -+#define YTPHY_SSR_POLARITY BIT(1) -+#define YTPHY_SSR_JABBER BIT(0) -+ -+/* Interrupt enable Register */ -+#define YTPHY_INTERRUPT_ENABLE_REG 0x12 -+#define YTPHY_IER_WOL BIT(6) -+ -+/* Interrupt Status Register */ -+#define YTPHY_INTERRUPT_STATUS_REG 0x13 -+#define YTPHY_ISR_AUTONEG_ERR BIT(15) -+#define YTPHY_ISR_SPEED_CHANGED BIT(14) -+#define YTPHY_ISR_DUPLEX_CHANGED BIT(13) -+#define YTPHY_ISR_PAGE_RECEIVED BIT(12) -+#define YTPHY_ISR_LINK_FAILED BIT(11) -+#define YTPHY_ISR_LINK_SUCCESSED BIT(10) -+#define YTPHY_ISR_WOL BIT(6) -+#define YTPHY_ISR_WIRESPEED_DOWNGRADE BIT(5) -+#define YTPHY_ISR_SERDES_LINK_FAILED BIT(3) -+#define YTPHY_ISR_SERDES_LINK_SUCCESSED BIT(2) -+#define YTPHY_ISR_POLARITY_CHANGED BIT(1) -+#define YTPHY_ISR_JABBER_HAPPENED BIT(0) -+ -+/* Speed Auto Downgrade Control Register */ -+#define YTPHY_SPEED_AUTO_DOWNGRADE_CONTROL_REG 0x14 -+#define YTPHY_SADCR_SPEED_DOWNGRADE_EN BIT(5) -+ -+/* If these bits are set to 3, the PHY attempts five times ( 3(set value) + -+ * additional 2) before downgrading, default 0x3 -+ */ -+#define YTPHY_SADCR_SPEED_RETRY_LIMIT (0x3 << 2) -+ -+/* Rx Error Counter Register */ -+#define YTPHY_RX_ERROR_COUNTER_REG 0x15 -+ -+/* Extended Register's Address Offset Register */ -+#define YTPHY_PAGE_SELECT 0x1E -+ -+/* Extended Register's Data Register */ -+#define YTPHY_PAGE_DATA 0x1F -+ -+/* FIBER Auto-Negotiation link partner ability */ -+#define YTPHY_FLPA_PAUSE (0x3 << 7) -+#define YTPHY_FLPA_ASYM_PAUSE (0x2 << 7) - - #define YT8511_PAGE_SELECT 0x1e - #define YT8511_PAGE 0x1f -@@ -38,6 +129,352 @@ - #define YT8511_DELAY_FE_TX_EN (0xf << 12) - #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) - -+/* Extended register is different from MMD Register and MII Register. -+ * We can use ytphy_read_ext/ytphy_write_ext/ytphy_modify_ext function to -+ * operate extended register. -+ * Extended Register start -+ */ -+ -+/* Phy gmii clock gating Register */ -+#define YT8521_CLOCK_GATING_REG 0xC -+#define YT8521_CGR_RX_CLK_EN BIT(12) -+ -+#define YT8521_EXTREG_SLEEP_CONTROL1_REG 0x27 -+#define YT8521_ESC1R_SLEEP_SW BIT(15) -+#define YT8521_ESC1R_PLLON_SLP BIT(14) -+ -+/* Phy fiber Link timer cfg2 Register */ -+#define YT8521_LINK_TIMER_CFG2_REG 0xA5 -+#define YT8521_LTCR_EN_AUTOSEN BIT(15) -+ -+/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+ * of yt8521 phy. There is no need to switch reg space when operating these -+ * registers. -+ */ -+ -+#define YT8521_REG_SPACE_SELECT_REG 0xA000 -+#define YT8521_RSSR_SPACE_MASK BIT(1) -+#define YT8521_RSSR_FIBER_SPACE (0x1 << 1) -+#define YT8521_RSSR_UTP_SPACE (0x0 << 1) -+#define YT8521_RSSR_TO_BE_ARBITRATED (0xFF) -+ -+#define YT8521_CHIP_CONFIG_REG 0xA001 -+#define YT8521_CCR_SW_RST BIT(15) -+ -+#define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) -+#define YT8521_CCR_MODE_UTP_TO_RGMII 0 -+#define YT8521_CCR_MODE_FIBER_TO_RGMII 1 -+#define YT8521_CCR_MODE_UTP_FIBER_TO_RGMII 2 -+#define YT8521_CCR_MODE_UTP_TO_SGMII 3 -+#define YT8521_CCR_MODE_SGPHY_TO_RGMAC 4 -+#define YT8521_CCR_MODE_SGMAC_TO_RGPHY 5 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_AUTO 6 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_FORCE 7 -+ -+/* 3 phy polling modes,poll mode combines utp and fiber mode*/ -+#define YT8521_MODE_FIBER 0x1 -+#define YT8521_MODE_UTP 0x2 -+#define YT8521_MODE_POLL 0x3 -+ -+#define YT8521_RGMII_CONFIG1_REG 0xA003 -+ -+/* TX Gig-E Delay is bits 3:0, default 0x1 -+ * TX Fast-E Delay is bits 7:4, default 0xf -+ * RX Delay is bits 13:10, default 0x0 -+ * Delay = 150ps * N -+ * On = 2250ps, off = 0ps -+ */ -+#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) -+#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) -+#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+ -+#define YTPHY_MISC_CONFIG_REG 0xA006 -+#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -+#define YTPHY_MCR_FIBER_1000BX (0x1 << 0) -+#define YTPHY_MCR_FIBER_100FX (0x0 << 0) -+ -+/* WOL MAC ADDR: MACADDR2(highest), MACADDR1(middle), MACADDR0(lowest) */ -+#define YTPHY_WOL_MACADDR2_REG 0xA007 -+#define YTPHY_WOL_MACADDR1_REG 0xA008 -+#define YTPHY_WOL_MACADDR0_REG 0xA009 -+ -+#define YTPHY_WOL_CONFIG_REG 0xA00A -+#define YTPHY_WCR_INTR_SEL BIT(6) -+#define YTPHY_WCR_ENABLE BIT(3) -+ -+/* 2b00 84ms -+ * 2b01 168ms *default* -+ * 2b10 336ms -+ * 2b11 672ms -+ */ -+#define YTPHY_WCR_PULSE_WIDTH_MASK (BIT(2) | BIT(1)) -+#define YTPHY_WCR_PULSE_WIDTH_672MS (BIT(2) | BIT(1)) -+ -+/* 1b0 Interrupt and WOL events is level triggered and active LOW *default* -+ * 1b1 Interrupt and WOL events is pulse triggered and active LOW -+ */ -+#define YTPHY_WCR_TYPE_PULSE BIT(0) -+ -+/* Extended Register end */ -+ -+struct yt8521_priv { -+ /* combo_advertising is used for case of YT8521 in combo mode, -+ * this means that yt8521 may work in utp or fiber mode which depends -+ * on which media is connected (YT8521_RSSR_TO_BE_ARBITRATED). -+ */ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(combo_advertising); -+ -+ /* YT8521_MODE_FIBER / YT8521_MODE_UTP / YT8521_MODE_POLL*/ -+ u8 polling_mode; -+ u8 strap_mode; /* 8 working modes */ -+ /* current reg page of yt8521 phy: -+ * YT8521_RSSR_UTP_SPACE -+ * YT8521_RSSR_FIBER_SPACE -+ * YT8521_RSSR_TO_BE_ARBITRATED -+ */ -+ u8 reg_page; -+}; -+ -+/** -+ * ytphy_read_ext() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_read(phydev, YTPHY_PAGE_DATA); -+} -+ -+/** -+ * ytphy_read_ext_with_lock() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_read_ext(phydev, regnum); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_write_ext() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext(struct phy_device *phydev, u16 regnum, u16 val) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_write(phydev, YTPHY_PAGE_DATA, val); -+} -+ -+/** -+ * ytphy_write_ext_with_lock() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 val) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_write_ext(phydev, regnum, val); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_modify_ext() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, -+ u16 set) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_modify(phydev, YTPHY_PAGE_DATA, mask, set); -+} -+ -+/** -+ * ytphy_modify_ext_with_lock() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 mask, u16 set) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_modify_ext(phydev, regnum, mask, set); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_get_wol() - report whether wake-on-lan is enabled -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG is common ext reg. -+ */ -+static void ytphy_get_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ int wol_config; -+ -+ wol->supported = WAKE_MAGIC; -+ wol->wolopts = 0; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return; -+ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ wol->wolopts |= WAKE_MAGIC; -+} -+ -+/** -+ * ytphy_set_wol() - turn wake-on-lan on or off -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG, YTPHY_WOL_MACADDR2_REG, YTPHY_WOL_MACADDR1_REG -+ * and YTPHY_WOL_MACADDR0_REG are common ext reg. The -+ * YTPHY_INTERRUPT_ENABLE_REG of UTP is special, fiber also use this register. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) -+{ -+ struct net_device *p_attached_dev; -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ int old_page; -+ int ret = 0; -+ u16 mask; -+ u16 val; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ p_attached_dev = phydev->attached_dev; -+ if (!p_attached_dev) -+ return -ENODEV; -+ -+ mac_addr = (const u8 *)p_attached_dev->dev_addr; -+ if (!is_valid_ether_addr(mac_addr)) -+ return -EINVAL; -+ -+ /* lock mdio bus then switch to utp reg space */ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, val); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* Enable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ } else { -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -111,6 +548,1181 @@ err_restore_page: - return phy_restore_page(phydev, oldpage, ret); - } - -+/** -+ * yt8521_read_page() - read reg page -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns current reg space of yt8521 (YT8521_RSSR_FIBER_SPACE/ -+ * YT8521_RSSR_UTP_SPACE) or negative errno code -+ */ -+static int yt8521_read_page(struct phy_device *phydev) -+{ -+ int old_page; -+ -+ old_page = ytphy_read_ext(phydev, YT8521_REG_SPACE_SELECT_REG); -+ if (old_page < 0) -+ return old_page; -+ -+ if ((old_page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ return YT8521_RSSR_FIBER_SPACE; -+ -+ return YT8521_RSSR_UTP_SPACE; -+}; -+ -+/** -+ * yt8521_write_page() - write reg page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to write. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_write_page(struct phy_device *phydev, int page) -+{ -+ int mask = YT8521_RSSR_SPACE_MASK; -+ int set; -+ -+ if ((page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ set = YT8521_RSSR_FIBER_SPACE; -+ else -+ set = YT8521_RSSR_UTP_SPACE; -+ -+ return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set); -+}; -+ -+/** -+ * yt8521_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct yt8521_priv *priv; -+ int chip_config; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ chip_config = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); -+ if (chip_config < 0) -+ return chip_config; -+ -+ priv->strap_mode = chip_config & YT8521_CCR_MODE_SEL_MASK; -+ switch (priv->strap_mode) { -+ case YT8521_CCR_MODE_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_SGPHY_TO_RGMAC: -+ case YT8521_CCR_MODE_SGMAC_TO_RGPHY: -+ priv->polling_mode = YT8521_MODE_FIBER; -+ priv->reg_page = YT8521_RSSR_FIBER_SPACE; -+ phydev->port = PORT_FIBRE; -+ break; -+ case YT8521_CCR_MODE_UTP_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_AUTO: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_FORCE: -+ priv->polling_mode = YT8521_MODE_POLL; -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ break; -+ case YT8521_CCR_MODE_UTP_TO_SGMII: -+ case YT8521_CCR_MODE_UTP_TO_RGMII: -+ priv->polling_mode = YT8521_MODE_UTP; -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ phydev->port = PORT_TP; -+ break; -+ } -+ /* set default reg space */ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_lpa(struct phy_device *phydev) -+{ -+ int lpa, lpagb; -+ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (!phydev->autoneg_complete) { -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ 0); -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ return 0; -+ } -+ -+ if (phydev->is_gigabit_capable) { -+ lpagb = __phy_read(phydev, MII_STAT1000); -+ if (lpagb < 0) -+ return lpagb; -+ -+ if (lpagb & LPA_1000MSFAIL) { -+ int adv = __phy_read(phydev, MII_CTRL1000); -+ -+ if (adv < 0) -+ return adv; -+ -+ if (adv & CTL1000_ENABLE_MASTER) -+ phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n"); -+ else -+ phydev_err(phydev, "Master/Slave resolution failed\n"); -+ return -ENOLINK; -+ } -+ -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ lpagb); -+ } -+ -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); -+ } else { -+ linkmode_zero(phydev->lp_advertising); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_adjust_status() - update speed and duplex to phydev. when in fiber -+ * mode, adjust speed and duplex. -+ * @phydev: a pointer to a &struct phy_device -+ * @status: yt8521 status read from YTPHY_SPECIFIC_STATUS_REG -+ * @is_utp: false(yt8521 work in fiber mode) or true(yt8521 work in utp mode) -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 -+ */ -+static int yt8521_adjust_status(struct phy_device *phydev, int status, -+ bool is_utp) -+{ -+ int speed_mode, duplex; -+ int speed; -+ int err; -+ int lpa; -+ -+ if (is_utp) -+ duplex = (status & YTPHY_SSR_DUPLEX) >> YTPHY_SSR_DUPLEX_OFFSET; -+ else -+ duplex = DUPLEX_FULL; /* for fiber, it always DUPLEX_FULL */ -+ -+ speed_mode = (status & YTPHY_SSR_SPEED_MODE_MASK) >> -+ YTPHY_SSR_SPEED_MODE_OFFSET; -+ -+ switch (speed_mode) { -+ case YTPHY_SSR_SPEED_10M: -+ if (is_utp) -+ speed = SPEED_10; -+ else -+ /* for fiber, it will never run here, default to -+ * SPEED_UNKNOWN -+ */ -+ speed = SPEED_UNKNOWN; -+ break; -+ case YTPHY_SSR_SPEED_100M: -+ speed = SPEED_100; -+ break; -+ case YTPHY_SSR_SPEED_1000M: -+ speed = SPEED_1000; -+ break; -+ default: -+ speed = SPEED_UNKNOWN; -+ break; -+ } -+ -+ phydev->speed = speed; -+ phydev->duplex = duplex; -+ -+ if (is_utp) { -+ err = ytphy_utp_read_lpa(phydev); -+ if (err < 0) -+ return err; -+ -+ phy_resolve_aneg_pause(phydev); -+ } else { -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ /* only support 1000baseX Full */ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->lp_advertising, lpa & LPA_1000XFULL); -+ -+ if (!(lpa & YTPHY_FLPA_PAUSE)) { -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ } else if ((lpa & YTPHY_FLPA_ASYM_PAUSE)) { -+ phydev->pause = 1; -+ phydev->asym_pause = 1; -+ } else { -+ phydev->pause = 1; -+ phydev->asym_pause = 0; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_read_status_paged() - determines the speed and duplex of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 1 (utp or fiber link),0 (no link) or negative errno code -+ */ -+static int yt8521_read_status_paged(struct phy_device *phydev, int page) -+{ -+ int fiber_latch_val; -+ int fiber_curr_val; -+ int old_page; -+ int ret = 0; -+ int status; -+ int link; -+ -+ linkmode_zero(phydev->lp_advertising); -+ phydev->duplex = DUPLEX_UNKNOWN; -+ phydev->speed = SPEED_UNKNOWN; -+ phydev->asym_pause = 0; -+ phydev->pause = 0; -+ -+ /* YT8521 has two reg space (utp/fiber) for linkup with utp/fiber -+ * respectively. but for utp/fiber combo mode, reg space should be -+ * arbitrated based on media priority. by default, utp takes -+ * priority. reg space should be properly set before read -+ * YTPHY_SPECIFIC_STATUS_REG. -+ */ -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Read YTPHY_SPECIFIC_STATUS_REG, which indicates the speed and duplex -+ * of the PHY is actually using. -+ */ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ status = ret; -+ link = !!(status & YTPHY_SSR_LINK); -+ -+ /* When PHY is in fiber mode, speed transferred from 1000Mbps to -+ * 100Mbps,there is not link down from YTPHY_SPECIFIC_STATUS_REG, so -+ * we need check MII_BMSR to identify such case. -+ */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_latch_val = ret; -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_curr_val = ret; -+ if (link && fiber_latch_val != fiber_curr_val) { -+ link = 0; -+ phydev_info(phydev, -+ "%s, fiber link down detect, latch = %04x, curr = %04x\n", -+ __func__, fiber_latch_val, fiber_curr_val); -+ } -+ } else { -+ /* Read autonegotiation status */ -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ phydev->autoneg_complete = ret & BMSR_ANEGCOMPLETE ? 1 : 0; -+ } -+ -+ if (link) { -+ if (page == YT8521_RSSR_UTP_SPACE) -+ yt8521_adjust_status(phydev, status, true); -+ else -+ yt8521_adjust_status(phydev, status, false); -+ } -+ return phy_restore_page(phydev, old_page, link); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_read_status() - determines the negotiated speed and duplex -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_read_status(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_read_status_paged(phydev, priv->reg_page); -+ if (link < 0) -+ return link; -+ } else { -+ /* when page is YT8521_RSSR_TO_BE_ARBITRATED, arbitration is -+ * needed. by default, utp is higher priority. -+ */ -+ -+ link_utp = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ -+ link = link_utp || link_fiber; -+ } -+ -+ if (link) { -+ if (phydev->link == 0) { -+ /* arbitrate reg space based on linkup media type. */ -+ if (priv->polling_mode == YT8521_MODE_POLL && -+ priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ if (link_fiber) -+ priv->reg_page = -+ YT8521_RSSR_FIBER_SPACE; -+ else -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ -+ phydev->port = link_fiber ? PORT_FIBRE : PORT_TP; -+ -+ phydev_info(phydev, "%s, link up, media: %s\n", -+ __func__, -+ (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ } -+ } -+ phydev->link = 1; -+ } else { -+ if (phydev->link == 1) { -+ phydev_info(phydev, "%s, link down, media: %s\n", -+ __func__, (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ -+ /* When in YT8521_MODE_POLL mode, need prepare for next -+ * arbitration. -+ */ -+ if (priv->polling_mode == YT8521_MODE_POLL) { -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ } -+ } -+ -+ phydev->link = 0; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_modify_bmcr_paged - bits modify a PHY's BMCR register of one page -+ * @phydev: the phy_device struct -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to operate -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * If it is reset, it will wait for completion. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_bmcr_paged(struct phy_device *phydev, int page, -+ u16 mask, u16 set) -+{ -+ int max_cnt = 500; /* the max wait time of reset ~ 500 ms */ -+ int old_page; -+ int ret = 0; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_modify(phydev, MII_BMCR, mask, set); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* If it is reset, need to wait for the reset to complete */ -+ if (set == BMCR_RESET) { -+ while (max_cnt--) { -+ usleep_range(1000, 1100); -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ if (!(ret & BMCR_RESET)) -+ return phy_restore_page(phydev, old_page, 0); -+ } -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_modify_utp_fiber_bmcr - bits modify a PHY's BMCR register -+ * @phydev: the phy_device struct -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_utp_fiber_bmcr(struct phy_device *phydev, u16 mask, -+ u16 set) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_modify_bmcr_paged(phydev, priv->reg_page, mask, -+ set); -+ if (ret < 0) -+ return ret; -+ } else { -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_UTP_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_FIBER_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_soft_reset() - called to issue a PHY software reset -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_soft_reset(struct phy_device *phydev) -+{ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_RESET); -+} -+ -+/** -+ * yt8521_suspend() - suspend the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_suspend(struct phy_device *phydev) -+{ -+ int wol_config; -+ -+ /* YTPHY_WOL_CONFIG_REG is common ext reg */ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN); -+} -+ -+/** -+ * yt8521_resume() - resume the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_resume(struct phy_device *phydev) -+{ -+ int ret; -+ int wol_config; -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0); -+} -+ -+/** -+ * yt8521_config_init() - called to initialize the PHY -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_init(struct phy_device *phydev) -+{ -+ int old_page; -+ int ret = 0; -+ u16 val; -+ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ break; -+ default: /* do not support other modes */ -+ ret = -EOPNOTSUPP; -+ goto err_restore_page; -+ } -+ -+ /* set rgmii delay mode */ -+ if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -+ ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -+ (YT8521_RC1R_RX_DELAY_MASK | -+ YT8521_RC1R_FE_TX_DELAY_MASK | -+ YT8521_RC1R_GE_TX_DELAY_MASK), -+ val); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_prepare_fiber_features() - A small helper function that setup -+ * fiber's features. -+ * @phydev: a pointer to a &struct phy_device -+ * @dst: a pointer to store fiber's features -+ */ -+static void yt8521_prepare_fiber_features(struct phy_device *phydev, -+ unsigned long *dst) -+{ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, dst); -+} -+ -+/** -+ * yt8521_fiber_setup_forced - configures/forces speed from @phydev -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_setup_forced(struct phy_device *phydev) -+{ -+ u16 val; -+ int ret; -+ -+ if (phydev->speed == SPEED_1000) -+ val = YTPHY_MCR_FIBER_1000BX; -+ else if (phydev->speed == SPEED_100) -+ val = YTPHY_MCR_FIBER_100FX; -+ else -+ return -EINVAL; -+ -+ ret = __phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* disable Fiber auto sensing */ -+ ret = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ YT8521_LTCR_EN_AUTOSEN, 0); -+ if (ret < 0) -+ return ret; -+ -+ ret = ytphy_modify_ext(phydev, YTPHY_MISC_CONFIG_REG, -+ YTPHY_MCR_FIBER_SPEED_MASK, val); -+ if (ret < 0) -+ return ret; -+ -+ return ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+} -+ -+/** -+ * ytphy_check_and_restart_aneg - Enable and restart auto-negotiation -+ * @phydev: target phy_device struct -+ * @restart: whether aneg restart is requested -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) -+{ -+ int ret; -+ -+ if (!restart) { -+ /* Advertisement hasn't changed, but maybe aneg was never on to -+ * begin with? Or maybe phy was isolated? -+ */ -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ return ret; -+ -+ if (!(ret & BMCR_ANENABLE) || (ret & BMCR_ISOLATE)) -+ restart = true; -+ } -+ /* Enable and Restart Autonegotiation -+ * Don't isolate the PHY if we're negotiating -+ */ -+ if (restart) -+ return __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, -+ BMCR_ANENABLE | BMCR_ANRESTART); -+ -+ return 0; -+} -+ -+/** -+ * yt8521_fiber_config_aneg - restart auto-negotiation or write -+ * YTPHY_MISC_CONFIG_REG. -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_config_aneg(struct phy_device *phydev) -+{ -+ int err, changed = 0; -+ int bmcr; -+ u16 adv; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) -+ return yt8521_fiber_setup_forced(phydev); -+ -+ /* enable Fiber auto sensing */ -+ err = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ 0, YT8521_LTCR_EN_AUTOSEN); -+ if (err < 0) -+ return err; -+ -+ err = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+ if (err < 0) -+ return err; -+ -+ bmcr = __phy_read(phydev, MII_BMCR); -+ if (bmcr < 0) -+ return bmcr; -+ -+ /* When it is coming from fiber forced mode, add bmcr power down -+ * and power up to let aneg work fine. -+ */ -+ if (!(bmcr & BMCR_ANENABLE)) { -+ __phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN); -+ usleep_range(1000, 1100); -+ __phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0); -+ } -+ -+ adv = linkmode_adv_to_mii_adv_x(phydev->advertising, -+ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); -+ -+ /* Setup fiber advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_1000XHALF | ADVERTISE_1000XFULL | -+ ADVERTISE_1000XPAUSE | -+ ADVERTISE_1000XPSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ -+ if (err > 0) -+ changed = 1; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * ytphy_setup_master_slave -+ * @phydev: target phy_device struct -+ * -+ * NOTE: The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_setup_master_slave(struct phy_device *phydev) -+{ -+ u16 ctl = 0; -+ -+ if (!phydev->is_gigabit_capable) -+ return 0; -+ -+ switch (phydev->master_slave_set) { -+ case MASTER_SLAVE_CFG_MASTER_PREFERRED: -+ ctl |= CTL1000_PREFER_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_SLAVE_PREFERRED: -+ break; -+ case MASTER_SLAVE_CFG_MASTER_FORCE: -+ ctl |= CTL1000_AS_MASTER; -+ fallthrough; -+ case MASTER_SLAVE_CFG_SLAVE_FORCE: -+ ctl |= CTL1000_ENABLE_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_UNKNOWN: -+ case MASTER_SLAVE_CFG_UNSUPPORTED: -+ return 0; -+ default: -+ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ return __phy_modify_changed(phydev, MII_CTRL1000, -+ (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER | -+ CTL1000_PREFER_MASTER), ctl); -+} -+ -+/** -+ * ytphy_utp_config_advert - sanitize and advertise auto-negotiation parameters -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Writes MII_ADVERTISE with the appropriate values, -+ * after sanitizing the values to make sure we only advertise -+ * what is supported. Returns < 0 on error, 0 if the PHY's advertisement -+ * hasn't changed, and > 0 if it has changed. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_advert(struct phy_device *phydev) -+{ -+ int err, bmsr, changed = 0; -+ u32 adv; -+ -+ /* Only allow advertising what this PHY supports */ -+ linkmode_and(phydev->advertising, phydev->advertising, -+ phydev->supported); -+ -+ adv = linkmode_adv_to_mii_adv_t(phydev->advertising); -+ -+ /* Setup standard advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_ALL | ADVERTISE_100BASE4 | -+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ bmsr = __phy_read(phydev, MII_BMSR); -+ if (bmsr < 0) -+ return bmsr; -+ -+ /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all -+ * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a -+ * logical 1. -+ */ -+ if (!(bmsr & BMSR_ESTATEN)) -+ return changed; -+ -+ adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); -+ -+ err = __phy_modify_changed(phydev, MII_CTRL1000, -+ ADVERTISE_1000FULL | ADVERTISE_1000HALF, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ return changed; -+} -+ -+/** -+ * ytphy_utp_config_aneg - restart auto-negotiation or write BMCR -+ * @phydev: target phy_device struct -+ * @changed: whether autoneg is requested -+ * -+ * NOTE: If auto-negotiation is enabled, we configure the -+ * advertising, and then restart auto-negotiation. If it is not -+ * enabled, then we write the BMCR. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_aneg(struct phy_device *phydev, bool changed) -+{ -+ int err; -+ u16 ctl; -+ -+ err = ytphy_setup_master_slave(phydev); -+ if (err < 0) -+ return err; -+ else if (err) -+ changed = true; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) { -+ /* configures/forces speed/duplex from @phydev */ -+ -+ ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex); -+ -+ return __phy_modify(phydev, MII_BMCR, ~(BMCR_LOOPBACK | -+ BMCR_ISOLATE | BMCR_PDOWN), ctl); -+ } -+ -+ err = ytphy_utp_config_advert(phydev); -+ if (err < 0) /* error */ -+ return err; -+ else if (err) -+ changed = true; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * yt8521_config_aneg_paged() - switch reg space then call genphy_config_aneg -+ * of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg_paged(struct phy_device *phydev, int page) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(fiber_supported); -+ struct yt8521_priv *priv = phydev->priv; -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising should be updated. -+ */ -+ if (priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ linkmode_zero(fiber_supported); -+ yt8521_prepare_fiber_features(phydev, fiber_supported); -+ -+ /* prepare fiber_supported, then setup advertising. */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ fiber_supported); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ fiber_supported); -+ linkmode_and(phydev->advertising, -+ priv->combo_advertising, fiber_supported); -+ } else { -+ /* ETHTOOL_LINK_MODE_Autoneg_BIT is also used in utp */ -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ fiber_supported); -+ linkmode_andnot(phydev->advertising, -+ priv->combo_advertising, -+ fiber_supported); -+ } -+ } -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) -+ ret = yt8521_fiber_config_aneg(phydev); -+ else -+ ret = ytphy_utp_config_aneg(phydev, false); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_config_aneg() - change reg space then call yt8521_config_aneg_paged -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_config_aneg_paged(phydev, priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising need to be saved at first run. -+ * Because it contains the advertising which supported by both -+ * mac and yt8521(utp and fiber). -+ */ -+ if (linkmode_empty(priv->combo_advertising)) { -+ linkmode_copy(priv->combo_advertising, -+ phydev->advertising); -+ } -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_FIBER_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* we don't known which will be link, so restore -+ * phydev->advertising as default value. -+ */ -+ linkmode_copy(phydev->advertising, priv->combo_advertising); -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_aneg_done_paged() - determines the auto negotiation result of one -+ * page. -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ int link; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ link = !!(ret & YTPHY_SSR_LINK); -+ ret = link; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_aneg_done() - determines the auto negotiation result -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_aneg_done_paged(phydev, priv->reg_page); -+ } else { -+ link_utp = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ link = link_fiber || link_utp; -+ phydev_info(phydev, "%s, link_fiber: %d, link_utp: %d\n", -+ __func__, link_fiber, link_utp); -+ } -+ -+ return link; -+} -+ -+/** -+ * ytphy_utp_read_abilities - read PHY abilities from Clause 22 registers -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Reads the PHY's abilities and populates -+ * phydev->supported accordingly. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_abilities(struct phy_device *phydev) -+{ -+ int val; -+ -+ linkmode_set_bit_array(phy_basic_ports_array, -+ ARRAY_SIZE(phy_basic_ports_array), -+ phydev->supported); -+ -+ val = __phy_read(phydev, MII_BMSR); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported, -+ val & BMSR_ANEGCAPABLE); -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported, -+ val & BMSR_100FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported, -+ val & BMSR_100HALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported, -+ val & BMSR_10FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported, -+ val & BMSR_10HALF); -+ -+ if (val & BMSR_ESTATEN) { -+ val = __phy_read(phydev, MII_ESTATUS); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_TFULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, -+ phydev->supported, val & ESTATUS_1000_THALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_XFULL); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_get_features_paged() - read supported link modes for one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_zero(phydev->supported); -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } else { -+ ret = ytphy_utp_read_abilities(phydev); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_get_features - switch reg space then call yt8521_get_features_paged -+ * @phydev: target phy_device struct -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_get_features_paged(phydev, priv->reg_page); -+ } else { -+ ret = yt8521_get_features_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* add fiber's features to phydev->supported */ -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } -+ return ret; -+} -+ - static struct phy_driver motorcomm_phy_drvs[] = { - { - PHY_ID_MATCH_EXACT(PHY_ID_YT8511), -@@ -121,16 +1733,35 @@ static struct phy_driver motorcomm_phy_d - .read_page = yt8511_read_page, - .write_page = yt8511_write_page, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8521), -+ .name = "YT8521 Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8521_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); - MODULE_AUTHOR("Peter Geis"); -+MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); - - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { /* sentinal */ } - }; - diff --git a/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch b/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch deleted file mode 100644 index cce71c8d84..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-02-net-phy-fix-yt8521-duplicated-argument-to-or.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4e0243e7128c9b25ea2739136076a95d6adaba5e Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 4 Nov 2022 16:44:41 +0800 -Subject: [PATCH] net: phy: fix yt8521 duplicated argument to & or | - -cocci warnings: (new ones prefixed by >>) ->> drivers/net/phy/motorcomm.c:1122:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1126:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1130:8-34: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1134:8-34: duplicated argument to & or | - - The second YT8521_RC1R_GE_TX_DELAY_xx should be YT8521_RC1R_FE_TX_DELAY_xx. - -Fixes: 70479a40954c ("net: phy: Add driver for Motorcomm yt8521 gigabit ethernet phy") -Reported-by: kernel test robot -Reported-by: Julia Lawall -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1119,19 +1119,19 @@ static int yt8521_config_init(struct phy - - switch (phydev->interface) { - case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_SGMII: diff --git a/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch deleted file mode 100644 index d22cc69425..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 813abcd98fb1b2cccf850cdfa092a4bfc50b2363 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Tue, 22 Nov 2022 16:42:32 +0800 -Subject: [PATCH] net: phy: add Motorcomm YT8531S phy id. - -We added patch for motorcomm.c to support YT8531S. This patch has -been tested on AM335x platform which has one YT8531S interface -card and passed all test cases. -The tested cases indluding: YT8531S UTP function with support of -10M/100M/1000M; YT8531S Fiber function with support of 100M/1000M; -and YT8531S Combo function that supports auto detection of media type. - -Since most functions of YT8531S are similar to YT8521 and we reuse some -codes for YT8521 in the patch file. - -Signed-off-by: Frank -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 52 +++++++++++++++++++++++++++++++++---- - 2 files changed, 48 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. -+ Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521 PHY driver. -+ * Motorcomm 8511/8521/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -12,9 +12,10 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8531S 0x4F51E91A - --/* YT8521 Register Overview -+/* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space - * ------------------------------------------------------------ - * | UTP MII | FIBER MII | -@@ -147,7 +148,7 @@ - #define YT8521_LINK_TIMER_CFG2_REG 0xA5 - #define YT8521_LTCR_EN_AUTOSEN BIT(15) - --/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+/* 0xA000, 0xA001, 0xA003, 0xA006 ~ 0xA00A and 0xA012 are common ext registers - * of yt8521 phy. There is no need to switch reg space when operating these - * registers. - */ -@@ -221,6 +222,9 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YT8531S_SYNCE_CFG_REG 0xA012 -+#define YT8531S_SCR_SYNCE_ENABLE BIT(6) -+ - /* Extended Register end */ - - struct yt8521_priv { -@@ -648,6 +652,26 @@ static int yt8521_probe(struct phy_devic - } - - /** -+ * yt8531s_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8531s_probe(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Disable SyncE clock output by default */ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -+ YT8531S_SCR_SYNCE_ENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* same as yt8521_probe */ -+ return yt8521_probe(phydev); -+} -+ -+/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1750,11 +1774,28 @@ static struct phy_driver motorcomm_phy_d - .suspend = yt8521_suspend, - .resume = yt8521_resume, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), -+ .name = "YT8531S Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8531s_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1762,6 +1803,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinal */ } - }; - diff --git a/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch b/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch deleted file mode 100644 index 94fc32aadb..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-04-net-phy-fix-the-spelling-problem-of-Sentinel.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 4104a713204d62aca482eebb0c6226d82a0721eb Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:57 +0800 -Subject: [PATCH] net: phy: fix the spelling problem of Sentinel - -CHECK: 'sentinal' may be misspelled - perhaps 'sentinel'? - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-1-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1804,7 +1804,7 @@ static const struct mdio_device_id __may - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, -- { /* sentinal */ } -+ { /* sentinel */ } - }; - - MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); diff --git a/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch b/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch deleted file mode 100644 index 076fa82d26..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-05-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 3c1dc22162d673d595855d24f95200ed2643f88f Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:58 +0800 -Subject: [PATCH] net: phy: motorcomm: change the phy id of yt8521 and yt8531s - to lowercase - -The phy id is usually defined in lower case. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-2-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -12,8 +12,8 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A --#define PHY_ID_YT8531S 0x4F51E91A -+#define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space diff --git a/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch deleted file mode 100644 index ba9a6ab4cc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-06-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 4869a146cd60fc8115230f0a45e15e534c531922 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:34 +0800 -Subject: [PATCH] net: phy: Add BIT macro for Motorcomm yt8521/yt8531 gigabit - ethernet phy - -Add BIT macro for Motorcomm yt8521/yt8531 gigabit ethernet phy. - This is a preparatory patch. Add BIT macro for 0xA012 reg, and - supplement for 0xA001 and 0xA003 reg. These will be used to support dts. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 55 ++++++++++++++++++++++++++++++++++--- - 1 file changed, 51 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -161,6 +161,11 @@ - - #define YT8521_CHIP_CONFIG_REG 0xA001 - #define YT8521_CCR_SW_RST BIT(15) -+/* 1b0 disable 1.9ns rxc clock delay *default* -+ * 1b1 enable 1.9ns rxc clock delay -+ */ -+#define YT8521_CCR_RXC_DLY_EN BIT(8) -+#define YT8521_CCR_RXC_DLY_1_900_NS 1900 - - #define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) - #define YT8521_CCR_MODE_UTP_TO_RGMII 0 -@@ -178,22 +183,41 @@ - #define YT8521_MODE_POLL 0x3 - - #define YT8521_RGMII_CONFIG1_REG 0xA003 -- -+/* 1b0 use original tx_clk_rgmii *default* -+ * 1b1 use inverted tx_clk_rgmii. -+ */ -+#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) - /* TX Gig-E Delay is bits 3:0, default 0x1 - * TX Fast-E Delay is bits 7:4, default 0xf - * RX Delay is bits 13:10, default 0x0 - * Delay = 150ps * N - * On = 2250ps, off = 0ps - */ --#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) - #define YT8521_RC1R_RX_DELAY_EN (0xF << 10) - #define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) --#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) - #define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) - #define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) --#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) - #define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) - #define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+#define YT8521_RC1R_RGMII_0_000_NS 0 -+#define YT8521_RC1R_RGMII_0_150_NS 1 -+#define YT8521_RC1R_RGMII_0_300_NS 2 -+#define YT8521_RC1R_RGMII_0_450_NS 3 -+#define YT8521_RC1R_RGMII_0_600_NS 4 -+#define YT8521_RC1R_RGMII_0_750_NS 5 -+#define YT8521_RC1R_RGMII_0_900_NS 6 -+#define YT8521_RC1R_RGMII_1_050_NS 7 -+#define YT8521_RC1R_RGMII_1_200_NS 8 -+#define YT8521_RC1R_RGMII_1_350_NS 9 -+#define YT8521_RC1R_RGMII_1_500_NS 10 -+#define YT8521_RC1R_RGMII_1_650_NS 11 -+#define YT8521_RC1R_RGMII_1_800_NS 12 -+#define YT8521_RC1R_RGMII_1_950_NS 13 -+#define YT8521_RC1R_RGMII_2_100_NS 14 -+#define YT8521_RC1R_RGMII_2_250_NS 15 - - #define YTPHY_MISC_CONFIG_REG 0xA006 - #define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -@@ -222,6 +246,29 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YTPHY_SYNCE_CFG_REG 0xA012 -+#define YT8521_SCR_SYNCE_ENABLE BIT(5) -+/* 1b0 output 25m clock -+ * 1b1 output 125m clock *default* -+ */ -+#define YT8521_SCR_CLK_FRE_SEL_125M BIT(3) -+#define YT8521_SCR_CLK_SRC_MASK GENMASK(2, 1) -+#define YT8521_SCR_CLK_SRC_PLL_125M 0 -+#define YT8521_SCR_CLK_SRC_UTP_RX 1 -+#define YT8521_SCR_CLK_SRC_SDS_RX 2 -+#define YT8521_SCR_CLK_SRC_REF_25M 3 -+#define YT8531_SCR_SYNCE_ENABLE BIT(6) -+/* 1b0 output 25m clock *default* -+ * 1b1 output 125m clock -+ */ -+#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4) -+#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1) -+#define YT8531_SCR_CLK_SRC_PLL_125M 0 -+#define YT8531_SCR_CLK_SRC_UTP_RX 1 -+#define YT8531_SCR_CLK_SRC_SDS_RX 2 -+#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 -+#define YT8531_SCR_CLK_SRC_REF_25M 4 -+#define YT8531_SCR_CLK_SRC_SSC_25M 5 - #define YT8531S_SYNCE_CFG_REG 0xA012 - #define YT8531S_SCR_SYNCE_ENABLE BIT(6) - diff --git a/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch deleted file mode 100644 index 6d89fae84c..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-07-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch +++ /dev/null @@ -1,343 +0,0 @@ -From a6e68f0f8769f79c67cdcfb6302feecd36197dec Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:35 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8521 gigabit - ethernet phy - -Add dts support for Motorcomm yt8521 gigabit ethernet phy. - Add ytphy_rgmii_clk_delay_config function to support dst config for - the delay of rgmii clk. This funciont is common for yt8521, yt8531s - and yt8531. - This patch has been verified on AM335x platform. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 253 ++++++++++++++++++++++++++++-------- - 1 file changed, 199 insertions(+), 54 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -@@ -187,21 +188,9 @@ - * 1b1 use inverted tx_clk_rgmii. - */ - #define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) --/* TX Gig-E Delay is bits 3:0, default 0x1 -- * TX Fast-E Delay is bits 7:4, default 0xf -- * RX Delay is bits 13:10, default 0x0 -- * Delay = 150ps * N -- * On = 2250ps, off = 0ps -- */ - #define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) --#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) --#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) - #define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) --#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) --#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) - #define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) --#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) --#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) - #define YT8521_RC1R_RGMII_0_000_NS 0 - #define YT8521_RC1R_RGMII_0_150_NS 1 - #define YT8521_RC1R_RGMII_0_300_NS 2 -@@ -274,6 +263,10 @@ - - /* Extended Register end */ - -+#define YTPHY_DTS_OUTPUT_CLK_DIS 0 -+#define YTPHY_DTS_OUTPUT_CLK_25M 25000000 -+#define YTPHY_DTS_OUTPUT_CLK_125M 125000000 -+ - struct yt8521_priv { - /* combo_advertising is used for case of YT8521 in combo mode, - * this means that yt8521 may work in utp or fiber mode which depends -@@ -641,6 +634,142 @@ static int yt8521_write_page(struct phy_ - }; - - /** -+ * struct ytphy_cfg_reg_map - map a config value to a register value -+ * @cfg: value in device configuration -+ * @reg: value in the register -+ */ -+struct ytphy_cfg_reg_map { -+ u32 cfg; -+ u32 reg; -+}; -+ -+static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = { -+ /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */ -+ { 0, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */ -+ { 2100, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250, YT8521_RC1R_RGMII_2_250_NS }, -+ -+ /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */ -+ { 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS }, -+ { 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS } -+}; -+ -+static u32 ytphy_get_delay_reg_value(struct phy_device *phydev, -+ const char *prop_name, -+ const struct ytphy_cfg_reg_map *tbl, -+ int tb_size, -+ u16 *rxc_dly_en, -+ u32 dflt) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int tb_size_half = tb_size / 2; -+ u32 val; -+ int i; -+ -+ if (of_property_read_u32(node, prop_name, &val)) -+ goto err_dts_val; -+ -+ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of -+ * tb_size is valid. -+ */ -+ if (!rxc_dly_en) -+ tb_size = tb_size_half; -+ -+ for (i = 0; i < tb_size; i++) { -+ if (tbl[i].cfg == val) { -+ if (rxc_dly_en && i < tb_size_half) -+ *rxc_dly_en = 0; -+ return tbl[i].reg; -+ } -+ } -+ -+ phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n", -+ val, prop_name, dflt); -+ -+err_dts_val: -+ /* when rxc_dly_en is not NULL, it is get the delay for rx. -+ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps, -+ * so YT8521_CCR_RXC_DLY_EN should not be set. -+ */ -+ if (rxc_dly_en) -+ *rxc_dly_en = 0; -+ -+ return dflt; -+} -+ -+static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) -+{ -+ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays); -+ u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN; -+ u32 rx_reg, tx_reg; -+ u16 mask, val = 0; -+ int ret; -+ -+ rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, -+ &rxc_dly_en, -+ YT8521_RC1R_RGMII_1_950_NS); -+ tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, NULL, -+ YT8521_RC1R_RGMII_1_950_NS); -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ rxc_dly_en = 0; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ rxc_dly_en = 0; -+ val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) | -+ FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ default: /* do not support other modes */ -+ return -EOPNOTSUPP; -+ } -+ -+ ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_RXC_DLY_EN, rxc_dly_en); -+ if (ret < 0) -+ return ret; -+ -+ /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */ -+ mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK; -+ return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); -+} -+ -+/** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device - * -@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_ - */ - static int yt8521_probe(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - struct device *dev = &phydev->mdio.dev; - struct yt8521_priv *priv; - int chip_config; -+ u16 mask, val; -+ u32 freq; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_devic - return ret; - } - -- return 0; -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ if (phydev->drv->phy_id == PHY_ID_YT8521) { -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8521_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -+ return 0; -+ } else { -+ phydev_warn(phydev, "PHY id err\n"); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); - } - - /** -@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_devi - */ - static int yt8521_config_init(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - int old_page; - int ret = 0; -- u16 val; - - old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); - if (old_page < 0) - goto err_restore_page; - -- switch (phydev->interface) { -- case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_SGMII: -- break; -- default: /* do not support other modes */ -- ret = -EOPNOTSUPP; -- goto err_restore_page; -- } -- - /* set rgmii delay mode */ - if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -- ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -- (YT8521_RC1R_RX_DELAY_MASK | -- YT8521_RC1R_FE_TX_DELAY_MASK | -- YT8521_RC1R_GE_TX_DELAY_MASK), -- val); -+ ret = ytphy_rgmii_clk_delay_config(phydev); - if (ret < 0) - goto err_restore_page; - } - -- /* disable auto sleep */ -- ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -- YT8521_ESC1R_SLEEP_SW, 0); -- if (ret < 0) -- goto err_restore_page; -- -- /* enable RXC clock when no wire plug */ -- ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -- YT8521_CGR_RX_CLK_EN, 0); -- if (ret < 0) -- goto err_restore_page; -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } diff --git a/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch b/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch deleted file mode 100644 index 86fc04695c..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-08-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 36152f87dda4af221b16258751451d9cd3d0fb0b Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:36 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8531s gigabit - ethernet phy - -Add dts support for Motorcomm yt8531s gigabit ethernet phy. - Change yt8521_probe to support clk config of yt8531s. Becase - yt8521_probe does the things which yt8531s is needed, so - removed yt8531s function. - This patch has been verified on AM335x platform with yt8531s board. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 51 ++++++++++++++++++++----------------- - 1 file changed, 27 insertions(+), 24 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -258,8 +258,6 @@ - #define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 - #define YT8531_SCR_CLK_SRC_REF_25M 4 - #define YT8531_SCR_CLK_SRC_SSC_25M 5 --#define YT8531S_SYNCE_CFG_REG 0xA012 --#define YT8531S_SCR_SYNCE_ENABLE BIT(6) - - /* Extended Register end */ - -@@ -858,7 +856,32 @@ static int yt8521_probe(struct phy_devic - return -EINVAL; - } - } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -- return 0; -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } - } else { - phydev_warn(phydev, "PHY id err\n"); - return -EINVAL; -@@ -869,26 +892,6 @@ static int yt8521_probe(struct phy_devic - } - - /** -- * yt8531s_probe() - read chip config then set suitable polling_mode -- * @phydev: a pointer to a &struct phy_device -- * -- * returns 0 or negative errno code -- */ --static int yt8531s_probe(struct phy_device *phydev) --{ -- int ret; -- -- /* Disable SyncE clock output by default */ -- ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -- YT8531S_SCR_SYNCE_ENABLE, 0); -- if (ret < 0) -- return ret; -- -- /* same as yt8521_probe */ -- return yt8521_probe(phydev); --} -- --/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1970,7 +1973,7 @@ static struct phy_driver motorcomm_phy_d - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -- .probe = yt8531s_probe, -+ .probe = yt8521_probe, - .read_page = yt8521_read_page, - .write_page = yt8521_write_page, - .get_wol = ytphy_get_wol, diff --git a/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch deleted file mode 100644 index 60eea4fa47..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 4ac94f728a588e7096dd5010cd7141a309ea7805 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:37 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8531 gigabit ethernet - phy - -Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have - verified the driver on AM335x platform with yt8531 board. On the - board, yt8531 gigabit ethernet phy works in utp mode, RGMII - interface, supports 1000M/100M/10M speeds, and wol(magic package). - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 208 +++++++++++++++++++++++++++++++++++- - 2 files changed, 207 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -257,7 +257,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. -+ Currently supports YT85xx Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521/8531S PHY driver. -+ * Motorcomm 8511/8521/8531/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -14,6 +14,7 @@ - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531 0x4f51e91b - #define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview -@@ -517,6 +518,61 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_set_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ u16 mask, val; -+ int ret; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ mac_addr = phydev->attached_dev->dev_addr; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext_with_lock(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ return ret; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, val); -+ if (ret < 0) -+ return ret; -+ -+ /* Enable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -767,6 +823,17 @@ static int ytphy_rgmii_clk_delay_config( - return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); - } - -+static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_rgmii_clk_delay_config(phydev); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ - /** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device -@@ -891,6 +958,43 @@ static int yt8521_probe(struct phy_devic - val); - } - -+static int yt8531_probe(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ u16 mask, val; -+ u32 freq; -+ -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); -+} -+ - /** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device -@@ -1387,6 +1491,94 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_config_init(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int ret; -+ -+ ret = ytphy_rgmii_clk_delay_config_with_lock(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8531_link_change_notify() - Adjust the tx clock direction according to -+ * the current speed and dts config. -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE: This function is only used to adapt to VF2 with JH7110 SoC. Please -+ * keep "motorcomm,tx-clk-adj-enabled" not exist in dts when the soc is not -+ * JH7110. -+ */ -+static void yt8531_link_change_notify(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ bool tx_clk_adj_enabled = false; -+ bool tx_clk_1000_inverted; -+ bool tx_clk_100_inverted; -+ bool tx_clk_10_inverted; -+ u16 val = 0; -+ int ret; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-adj-enabled")) -+ tx_clk_adj_enabled = true; -+ -+ if (!tx_clk_adj_enabled) -+ return; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-10-inverted")) -+ tx_clk_10_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-100-inverted")) -+ tx_clk_100_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-1000-inverted")) -+ tx_clk_1000_inverted = true; -+ -+ if (phydev->speed < 0) -+ return; -+ -+ switch (phydev->speed) { -+ case SPEED_1000: -+ if (tx_clk_1000_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_100: -+ if (tx_clk_100_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_10: -+ if (tx_clk_10_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ default: -+ return; -+ } -+ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8521_RGMII_CONFIG1_REG, -+ YT8521_RC1R_TX_CLK_SEL_INVERTED, val); -+ if (ret < 0) -+ phydev_warn(phydev, "Modify TX_CLK_SEL err:%d\n", ret); -+} -+ - /** - * yt8521_prepare_fiber_features() - A small helper function that setup - * fiber's features. -@@ -1970,6 +2162,17 @@ static struct phy_driver motorcomm_phy_d - .resume = yt8521_resume, - }, - { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531), -+ .name = "YT8531 Gigabit Ethernet", -+ .probe = yt8531_probe, -+ .config_init = yt8531_config_init, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .get_wol = ytphy_get_wol, -+ .set_wol = yt8531_set_wol, -+ .link_change_notify = yt8531_link_change_notify, -+ }, -+ { - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -@@ -1990,7 +2193,7 @@ static struct phy_driver motorcomm_phy_d - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1998,6 +2201,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinel */ } - }; diff --git a/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch b/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch deleted file mode 100644 index 29ae86dbbc..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.3-10-net-phy-motorcomm-uninitialized-variables-in.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 9753613f7399601f9bae6ee81e9d4274246c98ab Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 15 Feb 2023 07:21:47 +0300 -Subject: [PATCH] net: phy: motorcomm: uninitialized variables in - yt8531_link_change_notify() - -These booleans are never set to false, but are just used without being -initialized. - -Fixes: 4ac94f728a58 ("net: phy: Add driver for Motorcomm yt8531 gigabit ethernet phy") -Signed-off-by: Dan Carpenter -Reviewed-by: Frank Sae -Link: https://lore.kernel.org/r/Y+xd2yJet2ImHLoQ@kili -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1533,10 +1533,10 @@ static int yt8531_config_init(struct phy - static void yt8531_link_change_notify(struct phy_device *phydev) - { - struct device_node *node = phydev->mdio.dev.of_node; -+ bool tx_clk_1000_inverted = false; -+ bool tx_clk_100_inverted = false; -+ bool tx_clk_10_inverted = false; - bool tx_clk_adj_enabled = false; -- bool tx_clk_1000_inverted; -- bool tx_clk_100_inverted; -- bool tx_clk_10_inverted; - u16 val = 0; - int ret; - diff --git a/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch deleted file mode 100644 index 010ca9b68a..0000000000 --- a/target/linux/generic/backport-6.6/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 -From: Samin Guo -Date: Thu, 20 Jul 2023 19:15:09 +0800 -Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support - -The motorcomm phy (YT8531) supports the ability to adjust the drive -strength of the rx_clk/rx_data, and the default strength may not be -suitable for all boards. So add configurable options to better match -the boards.(e.g. StarFive VisionFive 2) - -When we configure the drive strength, we need to read the current -LDO voltage value to ensure that it is a legal value at that LDO -voltage. - -Reviewed-by: Hal Feng -Signed-off-by: Samin Guo -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 118 insertions(+) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -163,6 +163,10 @@ - - #define YT8521_CHIP_CONFIG_REG 0xA001 - #define YT8521_CCR_SW_RST BIT(15) -+#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) -+#define YT8531_LDO_VOL_3V3 0x0 -+#define YT8531_LDO_VOL_1V8 0x2 -+ - /* 1b0 disable 1.9ns rxc clock delay *default* - * 1b1 enable 1.9ns rxc clock delay - */ -@@ -236,6 +240,12 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 -+#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) -+#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ -+#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ -+#define YT8531_RGMII_RX_DS_DEFAULT 0x3 -+ - #define YTPHY_SYNCE_CFG_REG 0xA012 - #define YT8521_SCR_SYNCE_ENABLE BIT(5) - /* 1b0 output 25m clock -@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ - } - - /** -+ * struct ytphy_ldo_vol_map - map a current value to a register value -+ * @vol: ldo voltage -+ * @ds: value in the register -+ * @cur: value in device configuration -+ */ -+struct ytphy_ldo_vol_map { -+ u32 vol; -+ u32 ds; -+ u32 cur; -+}; -+ -+static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, -+ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, -+ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, -+}; -+ -+static u32 yt8531_get_ldo_vol(struct phy_device *phydev) -+{ -+ u32 val; -+ -+ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); -+ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); -+ -+ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; -+} -+ -+static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) -+{ -+ u32 vol; -+ int i; -+ -+ vol = yt8531_get_ldo_vol(phydev); -+ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { -+ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) -+ return yt8531_ldo_vol[i].ds; -+ } -+ -+ return -EINVAL; -+} -+ -+static int yt8531_set_ds(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ u32 ds_field_low, ds_field_hi, val; -+ int ret, ds; -+ -+ /* set rgmii rx clk driver strength */ -+ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { -+ ds = yt8531_get_ds_map(phydev, val); -+ if (ds < 0) -+ return dev_err_probe(&phydev->mdio.dev, ds, -+ "No matching current value was found.\n"); -+ } else { -+ ds = YT8531_RGMII_RX_DS_DEFAULT; -+ } -+ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YTPHY_PAD_DRIVE_STRENGTH_REG, -+ YT8531_RGMII_RXC_DS_MASK, -+ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); -+ if (ret < 0) -+ return ret; -+ -+ /* set rgmii rx data driver strength */ -+ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { -+ ds = yt8531_get_ds_map(phydev, val); -+ if (ds < 0) -+ return dev_err_probe(&phydev->mdio.dev, ds, -+ "No matching current value was found.\n"); -+ } else { -+ ds = YT8531_RGMII_RX_DS_DEFAULT; -+ } -+ -+ ds_field_hi = FIELD_GET(BIT(2), ds); -+ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); -+ -+ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); -+ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); -+ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YTPHY_PAD_DRIVE_STRENGTH_REG, -+ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, -+ ds_field_low | ds_field_hi); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+/** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device - * -@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy - return ret; - } - -+ ret = yt8531_set_ds(phydev); -+ if (ret < 0) -+ return ret; -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch deleted file mode 100644 index f82c8fc622..0000000000 --- a/target/linux/generic/backport-6.6/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 13 Jul 2023 09:42:07 +0100 -Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods - -Add phylink PCS enable/disable callbacks that will allow us to place -IEEE 802.3 register compliant PCS in power-down mode while not being -used. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++-------- - include/linux/phylink.h | 16 +++++++++++++ - 2 files changed, 55 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -34,6 +34,10 @@ enum { - PHYLINK_DISABLE_STOPPED, - PHYLINK_DISABLE_LINK, - PHYLINK_DISABLE_MAC_WOL, -+ -+ PCS_STATE_DOWN = 0, -+ PCS_STATE_STARTING, -+ PCS_STATE_STARTED, - }; - - /** -@@ -72,6 +76,7 @@ struct phylink { - struct phylink_link_state phy_state; - struct work_struct resolve; - unsigned int pcs_neg_mode; -+ unsigned int pcs_state; - - bool mac_link_dropped; - bool using_mac_select_pcs; -@@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str - } - } - -+static void phylink_pcs_disable(struct phylink_pcs *pcs) -+{ -+ if (pcs && pcs->ops->pcs_disable) -+ pcs->ops->pcs_disable(pcs); -+} -+ -+static int phylink_pcs_enable(struct phylink_pcs *pcs) -+{ -+ int err = 0; -+ -+ if (pcs && pcs->ops->pcs_enable) -+ err = pcs->ops->pcs_enable(pcs); -+ -+ return err; -+} -+ - static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, - const struct phylink_link_state *state, - bool permit_pause_to_mac) -@@ -1094,11 +1115,17 @@ static void phylink_major_config(struct - /* If we have a new PCS, switch to the new PCS after preparing the MAC - * for the change. - */ -- if (pcs_changed) -+ if (pcs_changed) { -+ phylink_pcs_disable(pl->pcs); -+ - pl->pcs = pcs; -+ } - - phylink_mac_config(pl, state); - -+ if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) -+ phylink_pcs_enable(pl->pcs); -+ - neg_mode = pl->cur_link_an_mode; - if (pl->pcs && pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; -@@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph - pl->link_config.pause = MLO_PAUSE_AN; - pl->link_config.speed = SPEED_UNKNOWN; - pl->link_config.duplex = DUPLEX_UNKNOWN; -+ pl->pcs_state = PCS_STATE_DOWN; - pl->mac_ops = mac_ops; - __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); - timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl) - if (pl->netdev) - netif_carrier_off(pl->netdev); - -+ pl->pcs_state = PCS_STATE_STARTING; -+ - /* Apply the link configuration to the MAC when starting. This allows - * a fixed-link to start with the correct parameters, and also - * ensures that we set the appropriate advertisement for Serdes links. -@@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl) - */ - phylink_mac_initial_config(pl, true); - -+ pl->pcs_state = PCS_STATE_STARTED; -+ - phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); - - if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl) - poll = true; - } - -- switch (pl->cfg_link_an_mode) { -- case MLO_AN_FIXED: -+ if (pl->cfg_link_an_mode == MLO_AN_FIXED) - poll |= pl->config->poll_fixed_state; -- break; -- case MLO_AN_INBAND: -- if (pl->pcs) -- poll |= pl->pcs->poll; -- break; -- } -+ - if (poll) - mod_timer(&pl->link_poll, jiffies + HZ); - if (pl->phydev) -@@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl) - } - - phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); -+ -+ pl->pcs_state = PCS_STATE_DOWN; -+ -+ phylink_pcs_disable(pl->pcs); - } - EXPORT_SYMBOL_GPL(phylink_stop); - ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -533,6 +533,8 @@ struct phylink_pcs { - /** - * struct phylink_pcs_ops - MAC PCS operations structure. - * @pcs_validate: validate the link configuration. -+ * @pcs_enable: enable the PCS. -+ * @pcs_disable: disable the PCS. - * @pcs_get_state: read the current MAC PCS link state from the hardware. - * @pcs_config: configure the MAC PCS for the selected mode and state. - * @pcs_an_restart: restart 802.3z BaseX autonegotiation. -@@ -542,6 +544,8 @@ struct phylink_pcs { - struct phylink_pcs_ops { - int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state); -+ int (*pcs_enable)(struct phylink_pcs *pcs); -+ void (*pcs_disable)(struct phylink_pcs *pcs); - void (*pcs_get_state)(struct phylink_pcs *pcs, - struct phylink_link_state *state); - int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, -@@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs - const struct phylink_link_state *state); - - /** -+ * pcs_enable() - enable the PCS. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ */ -+int pcs_enable(struct phylink_pcs *pcs); -+ -+/** -+ * pcs_disable() - disable the PCS. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ */ -+void pcs_disable(struct phylink_pcs *pcs); -+ -+/** - * pcs_get_state() - Read the current inband link state from the hardware - * @pcs: a pointer to a &struct phylink_pcs. - * @state: a pointer to a &struct phylink_link_state. diff --git a/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch b/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch deleted file mode 100644 index 6b6369761a..0000000000 --- a/target/linux/generic/backport-6.6/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch +++ /dev/null @@ -1,44 +0,0 @@ -From e4ccdfb78a47132f2d215658aab8902fc457c4b4 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:07:46 +0100 -Subject: [PATCH 082/125] net: pcs: lynxi: implement pcs_disable op - -When switching from 10GBase-R/5GBase-R/USXGMII to one of the interface -modes provided by mtk-pcs-lynxi we need to make sure to always perform -a full configuration of the PHYA. - -Implement pcs_disable op which resets the stored interface mode to -PHY_INTERFACE_MODE_NA to trigger a full reconfiguration once the LynxI -PCS driver had previously been deselected in favor of another PCS -driver such as the to-be-added driver for the USXGMII PCS found in -MT7988. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/f23d1a60d2c9d2fb72e32dcb0eaa5f7e867a3d68.1692327891.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-mtk-lynxi.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -234,11 +234,19 @@ static void mtk_pcs_lynxi_link_up(struct - } - } - -+static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) -+{ -+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); -+ -+ mpcs->interface = PHY_INTERFACE_MODE_NA; -+} -+ - static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { - .pcs_get_state = mtk_pcs_lynxi_get_state, - .pcs_config = mtk_pcs_lynxi_config, - .pcs_an_restart = mtk_pcs_lynxi_restart_an, - .pcs_link_up = mtk_pcs_lynxi_link_up, -+ .pcs_disable = mtk_pcs_lynxi_disable, - }; - - struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, diff --git a/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch deleted file mode 100644 index c4141eee93..0000000000 --- a/target/linux/generic/backport-6.6/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch +++ /dev/null @@ -1,136 +0,0 @@ -From: Andy Ren -Date: Mon, 7 Nov 2022 09:42:42 -0800 -Subject: [PATCH] net/core: Allow live renaming when an interface is up - -Allow a network interface to be renamed when the interface -is up. - -As described in the netconsole documentation [1], when netconsole is -used as a built-in, it will bring up the specified interface as soon as -possible. As a result, user space will not be able to rename the -interface since the kernel disallows renaming of interfaces that are -administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set -by the kernel. - -The original solution [2] to this problem was to add a new parameter to -the netconsole configuration parameters that allows renaming of -the interface used by netconsole while it is administratively up. -However, during the discussion that followed, it became apparent that we -have no reason to keep the current restriction and instead we should -allow user space to rename interfaces regardless of their administrative -state: - -1. The restriction was put in place over 20 years ago when renaming was -only possible via IOCTL and before rtnetlink started notifying user -space about such changes like it does today. - -2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version -5.2 and no regressions were reported. - -3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about -the administrative state of interface. - -Therefore, allow user space to rename running interfaces by removing the -restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in -possible triage by emitting a message to the kernel log that an -interface was renamed while UP. - -[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst -[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ - -Signed-off-by: Andy Ren -Reviewed-by: Ido Schimmel -Reviewed-by: David Ahern -Signed-off-by: David S. Miller ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -1691,7 +1691,6 @@ struct net_device_ops { - * @IFF_FAILOVER: device is a failover master device - * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device - * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device -- * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running - * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with - * skb_headlen(skb) == 0 (data starts from frag0) - * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN -@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { - IFF_FAILOVER = 1<<27, - IFF_FAILOVER_SLAVE = 1<<28, - IFF_L3MDEV_RX_HANDLER = 1<<29, -- IFF_LIVE_RENAME_OK = 1<<30, -+ /* was IFF_LIVE_RENAME_OK */ - IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), - IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), - }; -@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { - #define IFF_FAILOVER IFF_FAILOVER - #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE - #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER --#define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK - #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR - - /* Specifies the type of the struct net_device::ml_priv pointer */ ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1188,22 +1188,6 @@ int dev_change_name(struct net_device *d - - net = dev_net(dev); - -- /* Some auto-enslaved devices e.g. failover slaves are -- * special, as userspace might rename the device after -- * the interface had been brought up and running since -- * the point kernel initiated auto-enslavement. Allow -- * live name change even when these slave devices are -- * up and running. -- * -- * Typically, users of these auto-enslaving devices -- * don't actually care about slave name change, as -- * they are supposed to operate on master interface -- * directly. -- */ -- if (dev->flags & IFF_UP && -- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) -- return -EBUSY; -- - down_write(&devnet_rename_sem); - - if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { -@@ -1220,7 +1204,8 @@ int dev_change_name(struct net_device *d - } - - if (oldname[0] && !strchr(oldname, '%')) -- netdev_info(dev, "renamed from %s\n", oldname); -+ netdev_info(dev, "renamed from %s%s\n", oldname, -+ dev->flags & IFF_UP ? " (while UP)" : ""); - - old_assign_type = dev->name_assign_type; - dev->name_assign_type = NET_NAME_RENAMED; ---- a/net/core/failover.c -+++ b/net/core/failover.c -@@ -80,14 +80,14 @@ static int failover_slave_register(struc - goto err_upper_link; - } - -- slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; - - if (fops && fops->slave_register && - !fops->slave_register(slave_dev, failover_dev)) - return NOTIFY_OK; - - netdev_upper_dev_unlink(slave_dev, failover_dev); -- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; - err_upper_link: - netdev_rx_handler_unregister(slave_dev); - done: -@@ -121,7 +121,7 @@ int failover_slave_unregister(struct net - - netdev_rx_handler_unregister(slave_dev); - netdev_upper_dev_unlink(slave_dev, failover_dev); -- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); -+ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; - - if (fops && fops->slave_unregister && - !fops->slave_unregister(slave_dev, failover_dev)) diff --git a/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch b/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch deleted file mode 100644 index 17131c16d3..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-02-cdc_ether-no-need-to-blacklist-any-r8152-devices.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 69649ef8405320f81497f4757faac8234f61b167 Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Fri, 6 Jan 2023 17:07:39 +0100 -Subject: [PATCH] cdc_ether: no need to blacklist any r8152 devices -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The r8152 driver does not need this anymore. - -Dropping blacklist entries adds optional support for these -devices in ECM mode. - -The 8153 devices are handled by the r8153_ecm driver when -in ECM mode, and must still be blacklisted here. - -Signed-off-by: Bjørn Mork -Signed-off-by: David S. Miller ---- - drivers/net/usb/cdc_ether.c | 114 ------------------------------------ - 1 file changed, 114 deletions(-) - ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -768,13 +768,6 @@ static const struct usb_device_id produc - .driver_info = 0, - }, - --/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- - /* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ - { - USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, -@@ -782,119 +775,12 @@ static const struct usb_device_id produc - .driver_info = 0, - }, - --/* Samsung USB Ethernet Adapters */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --#if IS_ENABLED(CONFIG_USB_RTL8152) --/* Linksys USB3GIGV1 Ethernet Adapter */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, --#endif -- --/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- - /* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ - { - USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), - .driver_info = 0, - }, -- --/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface 2 dock (based on Realtek RTL8152) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- --/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, - - /* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */ - { diff --git a/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch b/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch deleted file mode 100644 index 565fbb3074..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-05-r8152-reduce-the-control-transfer-of-rtl8152_get_ver.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 02767440e1dda9861a11ca1dbe0f19a760b1d5c2 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Thu, 19 Jan 2023 15:40:43 +0800 -Subject: [PATCH] r8152: reduce the control transfer of rtl8152_get_version() - -Reduce the control transfer by moving calling rtl8152_get_version() in -rtl8152_probe(). This could prevent from calling rtl8152_get_version() -for unnecessary situations. For example, after setting config #2 for the -device, there are two interfaces and rtl8152_probe() may be called -twice. However, we don't need to call rtl8152_get_version() for this -situation. - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -9638,20 +9638,21 @@ static int rtl8152_probe(struct usb_inte - const struct usb_device_id *id) - { - struct usb_device *udev = interface_to_usbdev(intf); -- u8 version = rtl8152_get_version(intf); - struct r8152 *tp; - struct net_device *netdev; -+ u8 version; - int ret; - -- if (version == RTL_VER_UNKNOWN) -- return -ENODEV; -- - if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) - return -ENODEV; - - if (!rtl_check_vendor_ok(intf)) - return -ENODEV; - -+ version = rtl8152_get_version(intf); -+ if (version == RTL_VER_UNKNOWN) -+ return -ENODEV; -+ - usb_reset_device(udev); - netdev = alloc_etherdev(sizeof(struct r8152)); - if (!netdev) { diff --git a/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch b/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch deleted file mode 100644 index cdabca36d2..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.3-06-r8152-Add-__GFP_NOWARN-to-big-allocations.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 5cc33f139e11b893ff6dc60d8a0ae865a65521ac Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Thu, 6 Apr 2023 17:14:26 -0700 -Subject: [PATCH] r8152: Add __GFP_NOWARN to big allocations - -When memory is a little tight on my system, it's pretty easy to see -warnings that look like this. - - ksoftirqd/0: page allocation failure: order:3, mode:0x40a20(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0 - ... - Call trace: - dump_backtrace+0x0/0x1e8 - show_stack+0x20/0x2c - dump_stack_lvl+0x60/0x78 - dump_stack+0x18/0x38 - warn_alloc+0x104/0x174 - __alloc_pages+0x588/0x67c - alloc_rx_agg+0xa0/0x190 [r8152 ...] - r8152_poll+0x270/0x760 [r8152 ...] - __napi_poll+0x44/0x1ec - net_rx_action+0x100/0x300 - __do_softirq+0xec/0x38c - run_ksoftirqd+0x38/0xec - smpboot_thread_fn+0xb8/0x248 - kthread+0x134/0x154 - ret_from_fork+0x10/0x20 - -On a fragmented system it's normal that order 3 allocations will -sometimes fail, especially atomic ones. The driver handles these -failures fine and the WARN just creates spam in the logs for this -case. The __GFP_NOWARN flag is exactly for this situation, so add it -to the allocation. - -NOTE: my testing is on a 5.15 system, but there should be no reason -that this would be fundamentally different on a mainline kernel. - -Signed-off-by: Douglas Anderson -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20230406171411.1.I84dbef45786af440fd269b71e9436a96a8e7a152@changeid -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1947,7 +1947,7 @@ static struct rx_agg *alloc_rx_agg(struc - if (!rx_agg) - return NULL; - -- rx_agg->page = alloc_pages(mflags | __GFP_COMP, order); -+ rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order); - if (!rx_agg->page) - goto free_rx; - diff --git a/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch b/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch deleted file mode 100644 index 3ba79d6cc6..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-08-r8152-adjust-generic_ocp_write-function.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 26 Jul 2023 11:08:07 +0800 -Subject: [PATCH] r8152: adjust generic_ocp_write function - -Reduce the control transfer if all bytes of first or the last DWORD are -written. - -The original method is to split the control transfer into three parts -(the first DWORD, middle continuous data, and the last DWORD). However, -they could be combined if whole bytes of the first DWORD or last DWORD -are written. That is, the first DWORD or the last DWORD could be combined -with the middle continuous data, if the byte_en is 0xff. - -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 29 ++++++++++++++++++----------- - 1 file changed, 18 insertions(+), 11 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1313,16 +1313,24 @@ static int generic_ocp_write(struct r815 - byteen_end = byteen & BYTE_EN_END_MASK; - - byen = byteen_start | (byteen_start << 4); -- ret = set_registers(tp, index, type | byen, 4, data); -- if (ret < 0) -- goto error1; -- -- index += 4; -- data += 4; -- size -= 4; - -- if (size) { -+ /* Split the first DWORD if the byte_en is not 0xff */ -+ if (byen != BYTE_EN_DWORD) { -+ ret = set_registers(tp, index, type | byen, 4, data); -+ if (ret < 0) -+ goto error1; -+ -+ index += 4; -+ data += 4; - size -= 4; -+ } -+ -+ if (size) { -+ byen = byteen_end | (byteen_end >> 4); -+ -+ /* Split the last DWORD if the byte_en is not 0xff */ -+ if (byen != BYTE_EN_DWORD) -+ size -= 4; - - while (size) { - if (size > limit) { -@@ -1349,10 +1357,9 @@ static int generic_ocp_write(struct r815 - } - } - -- byen = byteen_end | (byteen_end >> 4); -- ret = set_registers(tp, index, type | byen, 4, data); -- if (ret < 0) -- goto error1; -+ /* Set the last DWORD */ -+ if (byen != BYTE_EN_DWORD) -+ ret = set_registers(tp, index, type | byen, 4, data); - } - - error1: diff --git a/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch b/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch deleted file mode 100644 index bc70c5af02..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-09-r8152-set-bp-in-bulk.patch +++ /dev/null @@ -1,129 +0,0 @@ -From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 26 Jul 2023 11:08:08 +0800 -Subject: [PATCH] r8152: set bp in bulk - -PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we -could combine the control transfers into one control transfer. - -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 75 ++++++++++++++--------------------------- - 1 file changed, 25 insertions(+), 50 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -3990,29 +3990,10 @@ static void rtl_reset_bmu(struct r8152 * - /* Clear the bp to stop the firmware before loading a new one */ - static void rtl_clear_bp(struct r8152 *tp, u16 type) - { -- switch (tp->version) { -- case RTL_VER_01: -- case RTL_VER_02: -- case RTL_VER_07: -- break; -- case RTL_VER_03: -- case RTL_VER_04: -- case RTL_VER_05: -- case RTL_VER_06: -- ocp_write_byte(tp, type, PLA_BP_EN, 0); -- break; -- case RTL_VER_14: -- ocp_write_word(tp, type, USB_BP2_EN, 0); -+ u16 bp[16] = {0}; -+ u16 bp_num; - -- ocp_write_word(tp, type, USB_BP_8, 0); -- ocp_write_word(tp, type, USB_BP_9, 0); -- ocp_write_word(tp, type, USB_BP_10, 0); -- ocp_write_word(tp, type, USB_BP_11, 0); -- ocp_write_word(tp, type, USB_BP_12, 0); -- ocp_write_word(tp, type, USB_BP_13, 0); -- ocp_write_word(tp, type, USB_BP_14, 0); -- ocp_write_word(tp, type, USB_BP_15, 0); -- break; -+ switch (tp->version) { - case RTL_VER_08: - case RTL_VER_09: - case RTL_VER_10: -@@ -4020,32 +4001,31 @@ static void rtl_clear_bp(struct r8152 *t - case RTL_VER_12: - case RTL_VER_13: - case RTL_VER_15: -- default: - if (type == MCU_TYPE_USB) { - ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); -- -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0); -- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0); -- } else { -- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); -+ bp_num = 16; -+ break; - } -+ fallthrough; -+ case RTL_VER_03: -+ case RTL_VER_04: -+ case RTL_VER_05: -+ case RTL_VER_06: -+ ocp_write_byte(tp, type, PLA_BP_EN, 0); -+ fallthrough; -+ case RTL_VER_01: -+ case RTL_VER_02: -+ case RTL_VER_07: -+ bp_num = 8; -+ break; -+ case RTL_VER_14: -+ default: -+ ocp_write_word(tp, type, USB_BP2_EN, 0); -+ bp_num = 16; - break; - } - -- ocp_write_word(tp, type, PLA_BP_0, 0); -- ocp_write_word(tp, type, PLA_BP_1, 0); -- ocp_write_word(tp, type, PLA_BP_2, 0); -- ocp_write_word(tp, type, PLA_BP_3, 0); -- ocp_write_word(tp, type, PLA_BP_4, 0); -- ocp_write_word(tp, type, PLA_BP_5, 0); -- ocp_write_word(tp, type, PLA_BP_6, 0); -- ocp_write_word(tp, type, PLA_BP_7, 0); -+ generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type); - - /* wait 3 ms to make sure the firmware is stopped */ - usleep_range(3000, 6000); -@@ -5022,10 +5002,9 @@ static void rtl8152_fw_phy_nc_apply(stru - - static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) - { -- u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg; -+ u16 bp_en_addr, type, fw_ver_reg; - u32 length; - u8 *data; -- int i; - - switch (__le32_to_cpu(mac->blk_hdr.type)) { - case RTL_FW_PLA: -@@ -5067,12 +5046,8 @@ static void rtl8152_fw_mac_apply(struct - ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr), - __le16_to_cpu(mac->bp_ba_value)); - -- bp_index = __le16_to_cpu(mac->bp_start); -- bp_num = __le16_to_cpu(mac->bp_num); -- for (i = 0; i < bp_num; i++) { -- ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i])); -- bp_index += 2; -- } -+ generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD, -+ __le16_to_cpu(mac->bp_num) << 1, mac->bp, type); - - bp_en_addr = __le16_to_cpu(mac->bp_en_addr); - if (bp_en_addr) diff --git a/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch b/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch deleted file mode 100644 index d7fdcdb2c6..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-10-eth-r8152-try-to-use-a-normal-budget.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cf74eb5a5bc867258e7d0b0d1c3c4a60e1e3de2f Mon Sep 17 00:00:00 2001 -From: Jakub Kicinski -Date: Mon, 14 Aug 2023 08:35:21 -0700 -Subject: [PATCH] eth: r8152: try to use a normal budget - -Mario reports that loading r8152 on his system leads to a: - - netif_napi_add_weight() called with weight 256 - -warning getting printed. We don't have any solid data -on why such high budget was chosen, and it may cause -stalls in processing other softirqs and rt threads. -So try to switch back to the default (64) weight. - -If this slows down someone's system we should investigate -which part of stopping starting the NAPI poll in this -driver are expensive. - -Reported-by: Mario Limonciello -Link: https://lore.kernel.org/all/0bfd445a-81f7-f702-08b0-bd5a72095e49@amd.com/ -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20230814153521.2697982-1-kuba@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -9784,8 +9784,7 @@ static int rtl8152_probe(struct usb_inte - - usb_set_intfdata(intf, tp); - -- netif_napi_add_weight(netdev, &tp->napi, r8152_poll, -- tp->support_2500full ? 256 : 64); -+ netif_napi_add(netdev, &tp->napi, r8152_poll); - - ret = register_netdev(netdev); - if (ret != 0) { diff --git a/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch b/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch deleted file mode 100644 index 8901767be5..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-13-r8152-Block-future-register-access-if-register-acces.patch +++ /dev/null @@ -1,398 +0,0 @@ -From d9962b0d42029bcb40fe3c38bce06d1870fa4df4 Mon Sep 17 00:00:00 2001 -From: Douglas Anderson -Date: Fri, 20 Oct 2023 14:06:59 -0700 -Subject: [PATCH] r8152: Block future register access if register access fails - -Even though the functions to read/write registers can fail, most of -the places in the r8152 driver that read/write register values don't -check error codes. The lack of error code checking is problematic in -at least two ways. - -The first problem is that the r8152 driver often uses code patterns -similar to this: - x = read_register() - x = x | SOME_BIT; - write_register(x); - -...with the above pattern, if the read_register() fails and returns -garbage then we'll end up trying to write modified garbage back to the -Realtek adapter. If the write_register() succeeds that's bad. Note -that as of commit f53a7ad18959 ("r8152: Set memory to all 0xFFs on -failed reg reads") the "garbage" returned by read_register() will at -least be consistent garbage, but it is still garbage. - -It turns out that this problem is very serious. Writing garbage to -some of the hardware registers on the Ethernet adapter can put the -adapter in such a bad state that it needs to be power cycled (fully -unplugged and plugged in again) before it can enumerate again. - -The second problem is that the r8152 driver generally has functions -that are long sequences of register writes. Assuming everything will -be OK if a random register write fails in the middle isn't a great -assumption. - -One might wonder if the above two problems are real. You could ask if -we would really have a successful write after a failed read. It turns -out that the answer appears to be "yes, this can happen". In fact, -we've seen at least two distinct failure modes where this happens. - -On a sc7180-trogdor Chromebook if you drop into kdb for a while and -then resume, you can see: -1. We get a "Tx timeout" -2. The "Tx timeout" queues up a USB reset. -3. In rtl8152_pre_reset() we try to reinit the hardware. -4. The first several (2-9) register accesses fail with a timeout, then - things recover. - -The above test case was actually fixed by the patch ("r8152: Increase -USB control msg timeout to 5000ms as per spec") but at least shows -that we really can see successful calls after failed ones. - -On a different (AMD) based Chromebook with a particular adapter, we -found that during reboot tests we'd also sometimes get a transitory -failure. In this case we saw -EPIPE being returned sometimes. Retrying -worked, but retrying is not always safe for all register accesses -since reading/writing some registers might have side effects (like -registers that clear on read). - -Let's fully lock out all register access if a register access fails. -When we do this, we'll try to queue up a USB reset and try to unlock -register access after the reset. This is slightly tricker than it -sounds since the r8152 driver has an optimized reset sequence that -only works reliably after probe happens. In order to handle this, we -avoid the optimized reset if probe didn't finish. Instead, we simply -retry the probe routine in this case. - -When locking out access, we'll use the existing infrastructure that -the driver was using when it detected we were unplugged. This keeps us -from getting stuck in delay loops in some parts of the driver. - -Signed-off-by: Douglas Anderson -Reviewed-by: Grant Grundler -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 207 ++++++++++++++++++++++++++++++++++------ - 1 file changed, 176 insertions(+), 31 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -772,6 +772,9 @@ enum rtl8152_flags { - SCHEDULE_TASKLET, - GREEN_ETHERNET, - RX_EPROTO, -+ IN_PRE_RESET, -+ PROBED_WITH_NO_ERRORS, -+ PROBE_SHOULD_RETRY, - }; - - #define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB 0x721e -@@ -952,6 +955,8 @@ struct r8152 { - u8 version; - u8 duplex; - u8 autoneg; -+ -+ unsigned int reg_access_reset_count; - }; - - /** -@@ -1199,6 +1204,96 @@ static unsigned int agg_buf_sz = 16384; - - #define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) - -+/* If register access fails then we block access and issue a reset. If this -+ * happens too many times in a row without a successful access then we stop -+ * trying to reset and just leave access blocked. -+ */ -+#define REGISTER_ACCESS_MAX_RESETS 3 -+ -+static void rtl_set_inaccessible(struct r8152 *tp) -+{ -+ set_bit(RTL8152_INACCESSIBLE, &tp->flags); -+ smp_mb__after_atomic(); -+} -+ -+static void rtl_set_accessible(struct r8152 *tp) -+{ -+ clear_bit(RTL8152_INACCESSIBLE, &tp->flags); -+ smp_mb__after_atomic(); -+} -+ -+static -+int r8152_control_msg(struct r8152 *tp, unsigned int pipe, __u8 request, -+ __u8 requesttype, __u16 value, __u16 index, void *data, -+ __u16 size, const char *msg_tag) -+{ -+ struct usb_device *udev = tp->udev; -+ int ret; -+ -+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) -+ return -ENODEV; -+ -+ ret = usb_control_msg(udev, pipe, request, requesttype, -+ value, index, data, size, -+ USB_CTRL_GET_TIMEOUT); -+ -+ /* No need to issue a reset to report an error if the USB device got -+ * unplugged; just return immediately. -+ */ -+ if (ret == -ENODEV) -+ return ret; -+ -+ /* If the write was successful then we're done */ -+ if (ret >= 0) { -+ tp->reg_access_reset_count = 0; -+ return ret; -+ } -+ -+ dev_err(&udev->dev, -+ "Failed to %s %d bytes at %#06x/%#06x (%d)\n", -+ msg_tag, size, value, index, ret); -+ -+ /* Block all future register access until we reset. Much of the code -+ * in the driver doesn't check for errors. Notably, many parts of the -+ * driver do a read/modify/write of a register value without -+ * confirming that the read succeeded. Writing back modified garbage -+ * like this can fully wedge the adapter, requiring a power cycle. -+ */ -+ rtl_set_inaccessible(tp); -+ -+ /* If probe hasn't yet finished, then we'll request a retry of the -+ * whole probe routine if we get any control transfer errors. We -+ * never have to clear this bit since we free/reallocate the whole "tp" -+ * structure if we retry probe. -+ */ -+ if (!test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) { -+ set_bit(PROBE_SHOULD_RETRY, &tp->flags); -+ return ret; -+ } -+ -+ /* Failing to access registers in pre-reset is not surprising since we -+ * wouldn't be resetting if things were behaving normally. The register -+ * access we do in pre-reset isn't truly mandatory--we're just reusing -+ * the disable() function and trying to be nice by powering the -+ * adapter down before resetting it. Thus, if we're in pre-reset, -+ * we'll return right away and not try to queue up yet another reset. -+ * We know the post-reset is already coming. -+ */ -+ if (test_bit(IN_PRE_RESET, &tp->flags)) -+ return ret; -+ -+ if (tp->reg_access_reset_count < REGISTER_ACCESS_MAX_RESETS) { -+ usb_queue_reset_device(tp->intf); -+ tp->reg_access_reset_count++; -+ } else if (tp->reg_access_reset_count == REGISTER_ACCESS_MAX_RESETS) { -+ dev_err(&udev->dev, -+ "Tried to reset %d times; giving up.\n", -+ REGISTER_ACCESS_MAX_RESETS); -+ } -+ -+ return ret; -+} -+ - static - int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) - { -@@ -1209,9 +1304,10 @@ int get_registers(struct r8152 *tp, u16 - if (!tmp) - return -ENOMEM; - -- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_in, -- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -- value, index, tmp, size, USB_CTRL_GET_TIMEOUT); -+ ret = r8152_control_msg(tp, tp->pipe_ctrl_in, -+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -+ value, index, tmp, size, "read"); -+ - if (ret < 0) - memset(data, 0xff, size); - else -@@ -1232,9 +1328,9 @@ int set_registers(struct r8152 *tp, u16 - if (!tmp) - return -ENOMEM; - -- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_out, -- RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, -- value, index, tmp, size, USB_CTRL_SET_TIMEOUT); -+ ret = r8152_control_msg(tp, tp->pipe_ctrl_out, -+ RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, -+ value, index, tmp, size, "write"); - - kfree(tmp); - -@@ -1243,10 +1339,8 @@ int set_registers(struct r8152 *tp, u16 - - static void rtl_set_unplug(struct r8152 *tp) - { -- if (tp->udev->state == USB_STATE_NOTATTACHED) { -- set_bit(RTL8152_INACCESSIBLE, &tp->flags); -- smp_mb__after_atomic(); -- } -+ if (tp->udev->state == USB_STATE_NOTATTACHED) -+ rtl_set_inaccessible(tp); - } - - static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, -@@ -8275,7 +8369,7 @@ static int rtl8152_pre_reset(struct usb_ - struct r8152 *tp = usb_get_intfdata(intf); - struct net_device *netdev; - -- if (!tp) -+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) - return 0; - - netdev = tp->netdev; -@@ -8290,7 +8384,9 @@ static int rtl8152_pre_reset(struct usb_ - napi_disable(&tp->napi); - if (netif_carrier_ok(netdev)) { - mutex_lock(&tp->control); -+ set_bit(IN_PRE_RESET, &tp->flags); - tp->rtl_ops.disable(tp); -+ clear_bit(IN_PRE_RESET, &tp->flags); - mutex_unlock(&tp->control); - } - -@@ -8303,9 +8399,11 @@ static int rtl8152_post_reset(struct usb - struct net_device *netdev; - struct sockaddr sa; - -- if (!tp) -+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) - return 0; - -+ rtl_set_accessible(tp); -+ - /* reset the MAC address in case of policy change */ - if (determine_ethernet_addr(tp, &sa) >= 0) { - rtnl_lock(); -@@ -9507,17 +9605,29 @@ static u8 __rtl_get_hw_ver(struct usb_de - __le32 *tmp; - u8 version; - int ret; -+ int i; - - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - return 0; - -- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), -- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -- PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), -- USB_CTRL_GET_TIMEOUT); -- if (ret > 0) -- ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; -+ /* Retry up to 3 times in case there is a transitory error. We do this -+ * since retrying a read of the version is always safe and this -+ * function doesn't take advantage of r8152_control_msg(). -+ */ -+ for (i = 0; i < 3; i++) { -+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), -+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, -+ PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), -+ USB_CTRL_GET_TIMEOUT); -+ if (ret > 0) { -+ ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; -+ break; -+ } -+ } -+ -+ if (i != 0 && ret > 0) -+ dev_warn(&udev->dev, "Needed %d retries to read version\n", i); - - kfree(tmp); - -@@ -9616,25 +9726,14 @@ static bool rtl8152_supports_lenovo_macp - return 0; - } - --static int rtl8152_probe(struct usb_interface *intf, -- const struct usb_device_id *id) -+static int rtl8152_probe_once(struct usb_interface *intf, -+ const struct usb_device_id *id, u8 version) - { - struct usb_device *udev = interface_to_usbdev(intf); - struct r8152 *tp; - struct net_device *netdev; -- u8 version; - int ret; - -- if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) -- return -ENODEV; -- -- if (!rtl_check_vendor_ok(intf)) -- return -ENODEV; -- -- version = rtl8152_get_version(intf); -- if (version == RTL_VER_UNKNOWN) -- return -ENODEV; -- - usb_reset_device(udev); - netdev = alloc_etherdev(sizeof(struct r8152)); - if (!netdev) { -@@ -9797,10 +9896,20 @@ static int rtl8152_probe(struct usb_inte - else - device_set_wakeup_enable(&udev->dev, false); - -+ /* If we saw a control transfer error while probing then we may -+ * want to try probe() again. Consider this an error. -+ */ -+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) -+ goto out2; -+ -+ set_bit(PROBED_WITH_NO_ERRORS, &tp->flags); - netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); - - return 0; - -+out2: -+ unregister_netdev(netdev); -+ - out1: - tasklet_kill(&tp->tx_tl); - cancel_delayed_work_sync(&tp->hw_phy_work); -@@ -9809,10 +9918,46 @@ out1: - rtl8152_release_firmware(tp); - usb_set_intfdata(intf, NULL); - out: -+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags)) -+ ret = -EAGAIN; -+ - free_netdev(netdev); - return ret; - } - -+#define RTL8152_PROBE_TRIES 3 -+ -+static int rtl8152_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ u8 version; -+ int ret; -+ int i; -+ -+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) -+ return -ENODEV; -+ -+ if (!rtl_check_vendor_ok(intf)) -+ return -ENODEV; -+ -+ version = rtl8152_get_version(intf); -+ if (version == RTL_VER_UNKNOWN) -+ return -ENODEV; -+ -+ for (i = 0; i < RTL8152_PROBE_TRIES; i++) { -+ ret = rtl8152_probe_once(intf, id, version); -+ if (ret != -EAGAIN) -+ break; -+ } -+ if (ret == -EAGAIN) { -+ dev_err(&intf->dev, -+ "r8152 failed probe after %d tries; giving up\n", i); -+ return -ENODEV; -+ } -+ -+ return ret; -+} -+ - static void rtl8152_disconnect(struct usb_interface *intf) - { - struct r8152 *tp = usb_get_intfdata(intf); diff --git a/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch b/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch deleted file mode 100644 index 7bbd1be820..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-14-r8152-break-the-loop-when-the-budget-is-exhausted.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 66eee612a1ba39f9a76a9ace4a34d012044767fb Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Tue, 26 Sep 2023 19:17:13 +0800 -Subject: [PATCH] r8152: break the loop when the budget is exhausted - -[ Upstream commit 2cf51f931797d9a47e75d999d0993a68cbd2a560 ] - -A bulk transfer of the USB may contain many packets. And, the total -number of the packets in the bulk transfer may be more than budget. - -Originally, only budget packets would be handled by napi_gro_receive(), -and the other packets would be queued in the driver for next schedule. - -This patch would break the loop about getting next bulk transfer, when -the budget is exhausted. That is, only the current bulk transfer would -be handled, and the other bulk transfers would be queued for next -schedule. Besides, the packets which are more than the budget in the -current bulk trasnfer would be still queued in the driver, as the -original method. - -In addition, a bulk transfer wouldn't contain more than 400 packets, so -the check of queue length is unnecessary. Therefore, I replace it with -WARN_ON_ONCE(). - -Fixes: cf74eb5a5bc8 ("eth: r8152: try to use a normal budget") -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/20230926111714.9448-433-nic_swsd@realtek.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Sasha Levin ---- - drivers/net/usb/r8152.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -2542,7 +2542,7 @@ static int rx_bottom(struct r8152 *tp, i - } - } - -- if (list_empty(&tp->rx_done)) -+ if (list_empty(&tp->rx_done) || work_done >= budget) - goto out1; - - clear_bit(RX_EPROTO, &tp->flags); -@@ -2558,6 +2558,15 @@ static int rx_bottom(struct r8152 *tp, i - struct urb *urb; - u8 *rx_data; - -+ /* A bulk transfer of USB may contain may packets, so the -+ * total packets may more than the budget. Deal with all -+ * packets in current bulk transfer, and stop to handle the -+ * next bulk transfer until next schedule, if budget is -+ * exhausted. -+ */ -+ if (work_done >= budget) -+ break; -+ - list_del_init(cursor); - - agg = list_entry(cursor, struct rx_agg, list); -@@ -2577,9 +2586,7 @@ static int rx_bottom(struct r8152 *tp, i - unsigned int pkt_len, rx_frag_head_sz; - struct sk_buff *skb; - -- /* limit the skb numbers for rx_queue */ -- if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000)) -- break; -+ WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000); - - pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; - if (pkt_len < ETH_ZLEN) -@@ -2657,9 +2664,10 @@ submit: - } - } - -+ /* Splice the remained list back to rx_done for next schedule */ - if (!list_empty(&rx_queue)) { - spin_lock_irqsave(&tp->rx_lock, flags); -- list_splice_tail(&rx_queue, &tp->rx_done); -+ list_splice(&rx_queue, &tp->rx_done); - spin_unlock_irqrestore(&tp->rx_lock, flags); - } - diff --git a/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch b/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch deleted file mode 100644 index c858152067..0000000000 --- a/target/linux/generic/backport-6.6/795-v6.6-15-net-usb-cdc_ether-add-u-blox-0x1313-composition.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 1b0fce8c8e69485e49a7d34aac3d4c2a2aa15d62 Mon Sep 17 00:00:00 2001 -From: Davide Tronchin -Date: Thu, 29 Jun 2023 12:37:36 +0200 -Subject: [PATCH] net: usb: cdc_ether: add u-blox 0x1313 composition. - -Add CDC-ECM support for LARA-R6 01B. - -The new LARA-R6 product variant identified by the "01B" string can be -configured (by AT interface) in three different USB modes: -* Default mode (Vendor ID: 0x1546 Product ID: 0x1311) with 4 serial -interfaces -* RmNet mode (Vendor ID: 0x1546 Product ID: 0x1312) with 4 serial -interfaces and 1 RmNet virtual network interface -* CDC-ECM mode (Vendor ID: 0x1546 Product ID: 0x1313) with 4 serial -interface and 1 CDC-ECM virtual network interface -The first 4 interfaces of all the 3 configurations (default, RmNet, ECM) -are the same. - -In CDC-ECM mode LARA-R6 01B exposes the following interfaces: -If 0: Diagnostic -If 1: AT parser -If 2: AT parser -If 3: AT parset/alternative functions -If 4: CDC-ECM interface - -Signed-off-by: Davide Tronchin -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/usb/cdc_ether.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -879,6 +879,12 @@ static const struct usb_device_id produc - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&wwan_info, - }, { -+ /* U-blox LARA-R6 01B */ -+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM, -+ USB_CDC_SUBCLASS_ETHERNET, -+ USB_CDC_PROTO_NONE), -+ .driver_info = (unsigned long)&wwan_info, -+}, { - /* ZTE modules */ - USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM, - USB_CDC_SUBCLASS_ETHERNET, diff --git a/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch b/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch deleted file mode 100644 index 592111fb95..0000000000 --- a/target/linux/generic/backport-6.6/800-v6.3-leds-Move-led_init_default_state_get-to-the-global-h.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 156a5bb89ca6f3edd2be0bfd0de15e575442927e Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Tue, 3 Jan 2023 15:12:47 +0200 -Subject: [PATCH] leds: Move led_init_default_state_get() to the global header - -There are users inside and outside LED framework that have implemented -a local copy of led_init_default_state_get(). In order to deduplicate -that, as the first step move the declaration from LED header to the -global one. - -Signed-off-by: Andy Shevchenko -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230103131256.33894-3-andriy.shevchenko@linux.intel.com ---- - drivers/leds/leds.h | 1 - - include/linux/leds.h | 2 ++ - 2 files changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/leds/leds.h -+++ b/drivers/leds/leds.h -@@ -27,7 +27,6 @@ ssize_t led_trigger_read(struct file *fi - ssize_t led_trigger_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t pos, size_t count); --enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); - - extern struct rw_semaphore leds_list_lock; - extern struct list_head leds_list; ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -63,6 +63,8 @@ struct led_init_data { - bool devname_mandatory; - }; - -+enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); -+ - struct led_hw_trigger_type { - int dummy; - }; diff --git a/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch b/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch deleted file mode 100644 index f6a025fa12..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 3e8b4d6277fd19d98c817576954dd6a4ff3caa2b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:23 +0200 -Subject: [PATCH 1/9] net: dsa: qca8k: move qca8k_port_to_phy() to header - -Move qca8k_port_to_phy() to qca8k header as it's useful for future -reference in Switch LEDs module since the same logic is applied to get -the right index of the switch port. -Make it inline as it's simple function that just decrease the port. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Michal Kubiak -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-8xxx.c | 15 --------------- - drivers/net/dsa/qca/qca8k.h | 14 ++++++++++++++ - 2 files changed, 14 insertions(+), 15 deletions(-) - ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -789,21 +789,6 @@ err_clear_skb: - return ret; - } - --static u32 --qca8k_port_to_phy(int port) --{ -- /* From Andrew Lunn: -- * Port 0 has no internal phy. -- * Port 1 has an internal PHY at MDIO address 0. -- * Port 2 has an internal PHY at MDIO address 1. -- * ... -- * Port 5 has an internal PHY at MDIO address 4. -- * Port 6 has no internal PHY. -- */ -- -- return port - 1; --} -- - static int - qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) - { ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -421,6 +421,20 @@ struct qca8k_fdb { - u8 mac[6]; - }; - -+static inline u32 qca8k_port_to_phy(int port) -+{ -+ /* From Andrew Lunn: -+ * Port 0 has no internal phy. -+ * Port 1 has an internal PHY at MDIO address 0. -+ * Port 2 has an internal PHY at MDIO address 1. -+ * ... -+ * Port 5 has an internal PHY at MDIO address 4. -+ * Port 6 has no internal PHY. -+ */ -+ -+ return port - 1; -+} -+ - /* Common setup function */ - extern const struct qca8k_mib_desc ar8327_mib[]; - extern const struct regmap_access_table qca8k_readable_table; diff --git a/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch b/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch deleted file mode 100644 index 409fe9c7a1..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch +++ /dev/null @@ -1,435 +0,0 @@ -From 1e264f9d2918b5737023c44a23ae04def1095210 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:24 +0200 -Subject: [PATCH 2/9] net: dsa: qca8k: add LEDs basic support - -Add LEDs basic support for qca8k Switch Family by adding basic -brightness_set() support. - -Since these LEDs refelect port status, the default label is set to -":port". DT binding should describe the color and function of the -LEDs using standard LEDs api. -Each LED always have the device name as prefix. The device name is -composed from the mii bus id and the PHY addr resulting in example -names like: -- qca8k-0.0:00:amber:lan -- qca8k-0.0:00:white:lan -- qca8k-0.0:01:amber:lan -- qca8k-0.0:01:white:lan - -These LEDs supports only blocking variant of the brightness_set() -function since they can sleep during access of the switch leds to set -the brightness. - -While at it add to the qca8k header file each mode defined by the Switch -Documentation for future use. - -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/Kconfig | 8 ++ - drivers/net/dsa/qca/Makefile | 3 + - drivers/net/dsa/qca/qca8k-8xxx.c | 5 + - drivers/net/dsa/qca/qca8k-leds.c | 239 +++++++++++++++++++++++++++++++ - drivers/net/dsa/qca/qca8k.h | 60 ++++++++ - drivers/net/dsa/qca/qca8k_leds.h | 16 +++ - 6 files changed, 331 insertions(+) - create mode 100644 drivers/net/dsa/qca/qca8k-leds.c - create mode 100644 drivers/net/dsa/qca/qca8k_leds.h - ---- a/drivers/net/dsa/qca/Kconfig -+++ b/drivers/net/dsa/qca/Kconfig -@@ -15,3 +15,11 @@ config NET_DSA_QCA8K - help - This enables support for the Qualcomm Atheros QCA8K Ethernet - switch chips. -+ -+config NET_DSA_QCA8K_LEDS_SUPPORT -+ bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support" -+ depends on NET_DSA_QCA8K -+ depends on LEDS_CLASS -+ help -+ This enabled support for LEDs present on the Qualcomm Atheros -+ QCA8K Ethernet switch chips. ---- a/drivers/net/dsa/qca/Makefile -+++ b/drivers/net/dsa/qca/Makefile -@@ -2,3 +2,6 @@ - obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o - obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o - qca8k-y += qca8k-common.o qca8k-8xxx.o -+ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT -+qca8k-y += qca8k-leds.o -+endif ---- a/drivers/net/dsa/qca/qca8k-8xxx.c -+++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -22,6 +22,7 @@ - #include - - #include "qca8k.h" -+#include "qca8k_leds.h" - - static void - qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -@@ -1851,6 +1852,10 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -+ ret = qca8k_setup_led_ctrl(priv); -+ if (ret) -+ return ret; -+ - qca8k_setup_pcs(priv, &priv->pcs_port_0, 0); - qca8k_setup_pcs(priv, &priv->pcs_port_6, 6); - ---- /dev/null -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -0,0 +1,239 @@ -+// SPDX-License-Identifier: GPL-2.0 -+#include -+#include -+ -+#include "qca8k.h" -+#include "qca8k_leds.h" -+ -+static int -+qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) -+{ -+ switch (port_num) { -+ case 0: -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; -+ break; -+ case 1: -+ case 2: -+ case 3: -+ /* Port 123 are controlled on a different reg */ -+ reg_info->reg = QCA8K_LED_CTRL3_REG; -+ reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num); -+ break; -+ case 4: -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int -+qca8k_led_brightness_set(struct qca8k_led *led, -+ enum led_brightness brightness) -+{ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 mask, val; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ val = QCA8K_LED_ALWAYS_OFF; -+ if (brightness) -+ val = QCA8K_LED_ALWAYS_ON; -+ -+ /* HW regs to control brightness is special and port 1-2-3 -+ * are placed in a different reg. -+ * -+ * To control port 0 brightness: -+ * - the 2 bit (15, 14) of: -+ * - QCA8K_LED_CTRL0_REG for led1 -+ * - QCA8K_LED_CTRL1_REG for led2 -+ * - QCA8K_LED_CTRL2_REG for led3 -+ * -+ * To control port 4: -+ * - the 2 bit (31, 30) of: -+ * - QCA8K_LED_CTRL0_REG for led1 -+ * - QCA8K_LED_CTRL1_REG for led2 -+ * - QCA8K_LED_CTRL2_REG for led3 -+ * -+ * To control port 1: -+ * - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To control port 2: -+ * - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To control port 3: -+ * - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1 -+ * - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2 -+ * - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3 -+ * -+ * To abstract this and have less code, we use the port and led numm -+ * to calculate the shift and the correct reg due to this problem of -+ * not having a 1:1 map of LED with the regs. -+ */ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, -+ mask << reg_info.shift, -+ val << reg_info.shift); -+} -+ -+static int -+qca8k_cled_brightness_set_blocking(struct led_classdev *ldev, -+ enum led_brightness brightness) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ return qca8k_led_brightness_set(led, brightness); -+} -+ -+static enum led_brightness -+qca8k_led_brightness_get(struct qca8k_led *led) -+{ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ int ret; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ ret = regmap_read(priv->regmap, reg_info.reg, &val); -+ if (ret) -+ return 0; -+ -+ val >>= reg_info.shift; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ val &= QCA8K_LED_PATTERN_EN_MASK; -+ val >>= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ /* Assume brightness ON only when the LED is set to always ON */ -+ return val == QCA8K_LED_ALWAYS_ON; -+} -+ -+static int -+qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) -+{ -+ struct fwnode_handle *led = NULL, *leds = NULL; -+ struct led_init_data init_data = { }; -+ struct dsa_switch *ds = priv->ds; -+ enum led_default_state state; -+ struct qca8k_led *port_led; -+ int led_num, led_index; -+ int ret; -+ -+ leds = fwnode_get_named_child_node(port, "leds"); -+ if (!leds) { -+ dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n", -+ port_num); -+ return 0; -+ } -+ -+ fwnode_for_each_child_node(leds, led) { -+ /* Reg represent the led number of the port. -+ * Each port can have at most 3 leds attached -+ * Commonly: -+ * 1. is gigabit led -+ * 2. is mbit led -+ * 3. additional status led -+ */ -+ if (fwnode_property_read_u32(led, "reg", &led_num)) -+ continue; -+ -+ if (led_num >= QCA8K_LED_PORT_COUNT) { -+ dev_warn(priv->dev, "Invalid LED reg %d defined for port %d", -+ led_num, port_num); -+ continue; -+ } -+ -+ led_index = QCA8K_LED_PORT_INDEX(port_num, led_num); -+ -+ port_led = &priv->ports_led[led_index]; -+ port_led->port_num = port_num; -+ port_led->led_num = led_num; -+ port_led->priv = priv; -+ -+ state = led_init_default_state_get(led); -+ switch (state) { -+ case LEDS_DEFSTATE_ON: -+ port_led->cdev.brightness = 1; -+ qca8k_led_brightness_set(port_led, 1); -+ break; -+ case LEDS_DEFSTATE_KEEP: -+ port_led->cdev.brightness = -+ qca8k_led_brightness_get(port_led); -+ break; -+ default: -+ port_led->cdev.brightness = 0; -+ qca8k_led_brightness_set(port_led, 0); -+ } -+ -+ port_led->cdev.max_brightness = 1; -+ port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; -+ init_data.default_label = ":port"; -+ init_data.fwnode = led; -+ init_data.devname_mandatory = true; -+ init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->slave_mii_bus->id, -+ port_num); -+ if (!init_data.devicename) -+ return -ENOMEM; -+ -+ ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data); -+ if (ret) -+ dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num); -+ -+ kfree(init_data.devicename); -+ } -+ -+ return 0; -+} -+ -+int -+qca8k_setup_led_ctrl(struct qca8k_priv *priv) -+{ -+ struct fwnode_handle *ports, *port; -+ int port_num; -+ int ret; -+ -+ ports = device_get_named_child_node(priv->dev, "ports"); -+ if (!ports) { -+ dev_info(priv->dev, "No ports node specified in device tree!"); -+ return 0; -+ } -+ -+ fwnode_for_each_child_node(ports, port) { -+ if (fwnode_property_read_u32(port, "reg", &port_num)) -+ continue; -+ -+ /* Skip checking for CPU port 0 and CPU port 6 as not supported */ -+ if (port_num == 0 || port_num == 6) -+ continue; -+ -+ /* Each port can have at most 3 different leds attached. -+ * Switch port starts from 0 to 6, but port 0 and 6 are CPU -+ * port. The port index needs to be decreased by one to identify -+ * the correct port for LED setup. -+ */ -+ ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num)); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} ---- a/drivers/net/dsa/qca/qca8k.h -+++ b/drivers/net/dsa/qca/qca8k.h -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - - #define QCA8K_ETHERNET_MDIO_PRIORITY 7 -@@ -85,6 +86,51 @@ - #define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x) - #define QCA8K_MDIO_MASTER_MAX_PORTS 5 - #define QCA8K_MDIO_MASTER_MAX_REG 32 -+ -+/* LED control register */ -+#define QCA8K_LED_PORT_COUNT 3 -+#define QCA8K_LED_COUNT ((QCA8K_NUM_PORTS - QCA8K_NUM_CPU_PORTS) * QCA8K_LED_PORT_COUNT) -+#define QCA8K_LED_RULE_COUNT 6 -+#define QCA8K_LED_RULE_MAX 11 -+#define QCA8K_LED_PORT_INDEX(_phy, _led) (((_phy) * QCA8K_LED_PORT_COUNT) + (_led)) -+ -+#define QCA8K_LED_PHY123_PATTERN_EN_SHIFT(_phy, _led) ((((_phy) - 1) * 6) + 8 + (2 * (_led))) -+#define QCA8K_LED_PHY123_PATTERN_EN_MASK GENMASK(1, 0) -+ -+#define QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT 0 -+#define QCA8K_LED_PHY4_CONTROL_RULE_SHIFT 16 -+ -+#define QCA8K_LED_CTRL_REG(_i) (0x050 + (_i) * 4) -+#define QCA8K_LED_CTRL0_REG 0x50 -+#define QCA8K_LED_CTRL1_REG 0x54 -+#define QCA8K_LED_CTRL2_REG 0x58 -+#define QCA8K_LED_CTRL3_REG 0x5C -+#define QCA8K_LED_CTRL_SHIFT(_i) (((_i) % 2) * 16) -+#define QCA8K_LED_CTRL_MASK GENMASK(15, 0) -+#define QCA8K_LED_RULE_MASK GENMASK(13, 0) -+#define QCA8K_LED_BLINK_FREQ_MASK GENMASK(1, 0) -+#define QCA8K_LED_BLINK_FREQ_SHITF 0 -+#define QCA8K_LED_BLINK_2HZ 0 -+#define QCA8K_LED_BLINK_4HZ 1 -+#define QCA8K_LED_BLINK_8HZ 2 -+#define QCA8K_LED_BLINK_AUTO 3 -+#define QCA8K_LED_LINKUP_OVER_MASK BIT(2) -+#define QCA8K_LED_TX_BLINK_MASK BIT(4) -+#define QCA8K_LED_RX_BLINK_MASK BIT(5) -+#define QCA8K_LED_COL_BLINK_MASK BIT(7) -+#define QCA8K_LED_LINK_10M_EN_MASK BIT(8) -+#define QCA8K_LED_LINK_100M_EN_MASK BIT(9) -+#define QCA8K_LED_LINK_1000M_EN_MASK BIT(10) -+#define QCA8K_LED_POWER_ON_LIGHT_MASK BIT(11) -+#define QCA8K_LED_HALF_DUPLEX_MASK BIT(12) -+#define QCA8K_LED_FULL_DUPLEX_MASK BIT(13) -+#define QCA8K_LED_PATTERN_EN_MASK GENMASK(15, 14) -+#define QCA8K_LED_PATTERN_EN_SHIFT 14 -+#define QCA8K_LED_ALWAYS_OFF 0 -+#define QCA8K_LED_ALWAYS_BLINK_4HZ 1 -+#define QCA8K_LED_ALWAYS_ON 2 -+#define QCA8K_LED_RULE_CONTROLLED 3 -+ - #define QCA8K_GOL_MAC_ADDR0 0x60 - #define QCA8K_GOL_MAC_ADDR1 0x64 - #define QCA8K_MAX_FRAME_SIZE 0x78 -@@ -382,6 +428,19 @@ struct qca8k_pcs { - int port; - }; - -+struct qca8k_led_pattern_en { -+ u32 reg; -+ u8 shift; -+}; -+ -+struct qca8k_led { -+ u8 port_num; -+ u8 led_num; -+ u16 old_rule; -+ struct qca8k_priv *priv; -+ struct led_classdev cdev; -+}; -+ - struct qca8k_priv { - u8 switch_id; - u8 switch_revision; -@@ -406,6 +465,7 @@ struct qca8k_priv { - struct qca8k_pcs pcs_port_0; - struct qca8k_pcs pcs_port_6; - const struct qca8k_match_data *info; -+ struct qca8k_led ports_led[QCA8K_LED_COUNT]; - }; - - struct qca8k_mib_desc { ---- /dev/null -+++ b/drivers/net/dsa/qca/qca8k_leds.h -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#ifndef __QCA8K_LEDS_H -+#define __QCA8K_LEDS_H -+ -+/* Leds Support function */ -+#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT -+int qca8k_setup_led_ctrl(struct qca8k_priv *priv); -+#else -+static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv) -+{ -+ return 0; -+} -+#endif -+ -+#endif /* __QCA8K_LEDS_H */ diff --git a/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch b/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch deleted file mode 100644 index 231c4156df..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 91acadcc6e599dfc62717abcdad58a459cfb1684 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 17 Apr 2023 17:17:25 +0200 -Subject: [PATCH 3/9] net: dsa: qca8k: add LEDs blink_set() support - -Add LEDs blink_set() support to qca8k Switch Family. -These LEDs support hw accellerated blinking at a fixed rate -of 4Hz. - -Reject any other value since not supported by the LEDs switch. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Pavel Machek -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 38 ++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -128,6 +128,43 @@ qca8k_led_brightness_get(struct qca8k_le - } - - static int -+qca8k_cled_blink_set(struct led_classdev *ldev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ; -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ -+ if (*delay_on == 0 && *delay_off == 0) { -+ *delay_on = 125; -+ *delay_off = 125; -+ } -+ -+ if (*delay_on != 125 || *delay_off != 125) { -+ /* The hardware only supports blinking at 4Hz. Fall back -+ * to software implementation in other cases. -+ */ -+ return -EINVAL; -+ } -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, -+ val << reg_info.shift); -+ -+ return 0; -+} -+ -+static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { - struct fwnode_handle *led = NULL, *leds = NULL; -@@ -186,6 +223,7 @@ qca8k_parse_port_leds(struct qca8k_priv - - port_led->cdev.max_brightness = 1; - port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; -+ port_led->cdev.blink_set = qca8k_cled_blink_set; - init_data.default_label = ":port"; - init_data.fwnode = led; - init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch b/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch deleted file mode 100644 index bc905b4468..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-04-leds-Provide-stubs-for-when-CLASS_LED-NEW_LEDS-are-d.patch +++ /dev/null @@ -1,59 +0,0 @@ -From e5029edd53937a29801ef507cee12e657ff31ea9 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:26 +0200 -Subject: [PATCH 4/9] leds: Provide stubs for when CLASS_LED & NEW_LEDS are - disabled - -Provide stubs for devm_led_classdev_register_ext() and -led_init_default_state_get() so that LED drivers embedded within other -drivers such as PHYs and Ethernet switches still build when LEDS_CLASS -or NEW_LEDS are disabled. This also helps with Kconfig dependencies, -which are somewhat hairy for phylib and mdio and only get worse when -adding a dependency on LED_CLASS. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -63,7 +63,15 @@ struct led_init_data { - bool devname_mandatory; - }; - -+#if IS_ENABLED(CONFIG_NEW_LEDS) - enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); -+#else -+static inline enum led_default_state -+led_init_default_state_get(struct fwnode_handle *fwnode) -+{ -+ return LEDS_DEFSTATE_OFF; -+} -+#endif - - struct led_hw_trigger_type { - int dummy; -@@ -198,9 +206,19 @@ static inline int led_classdev_register( - return led_classdev_register_ext(parent, led_cdev, NULL); - } - -+#if IS_ENABLED(CONFIG_LEDS_CLASS) - int devm_led_classdev_register_ext(struct device *parent, - struct led_classdev *led_cdev, - struct led_init_data *init_data); -+#else -+static inline int -+devm_led_classdev_register_ext(struct device *parent, -+ struct led_classdev *led_cdev, -+ struct led_init_data *init_data) -+{ -+ return 0; -+} -+#endif - - static inline int devm_led_classdev_register(struct device *parent, - struct led_classdev *led_cdev) diff --git a/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch deleted file mode 100644 index 0d2c0bcd83..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 01e5b728e9e43ae444e0369695a5f72209906464 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:27 +0200 -Subject: [PATCH 5/9] net: phy: Add a binding for PHY LEDs - -Define common binding parsing for all PHY drivers with LEDs using -phylib. Parse the DT as part of the phy_probe and add LEDs to the -linux LED class infrastructure. For the moment, provide a dummy -brightness function, which will later be replaced with a call into the -PHY driver. This allows testing since the LED core might otherwise -reject an LED whose brightness cannot be set. - -Add a dependency on LED_CLASS. It either needs to be built in, or not -enabled, since a modular build can result in linker errors. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 1 + - drivers/net/phy/phy_device.c | 76 ++++++++++++++++++++++++++++++++++++ - include/linux/phy.h | 16 ++++++++ - 3 files changed, 93 insertions(+) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -18,6 +18,7 @@ menuconfig PHYLIB - depends on NETDEVICES - select MDIO_DEVICE - select MDIO_DEVRES -+ depends on LEDS_CLASS || LEDS_CLASS=n - help - Ethernet controllers are usually attached to PHY - devices. This option provides infrastructure for ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -19,10 +19,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -642,6 +644,7 @@ struct phy_device *phy_device_create(str - device_initialize(&mdiodev->dev); - - dev->state = PHY_DOWN; -+ INIT_LIST_HEAD(&dev->leds); - - mutex_init(&dev->lock); - INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); -@@ -3035,6 +3038,74 @@ static bool phy_drv_supports_irq(struct - return phydrv->config_intr && phydrv->handle_interrupt; - } - -+/* Dummy implementation until calls into PHY driver are added */ -+static int phy_led_set_brightness(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ return 0; -+} -+ -+static int of_phy_led(struct phy_device *phydev, -+ struct device_node *led) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct led_init_data init_data = {}; -+ struct led_classdev *cdev; -+ struct phy_led *phyled; -+ int err; -+ -+ phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); -+ if (!phyled) -+ return -ENOMEM; -+ -+ cdev = &phyled->led_cdev; -+ -+ err = of_property_read_u8(led, "reg", &phyled->index); -+ if (err) -+ return err; -+ -+ cdev->brightness_set_blocking = phy_led_set_brightness; -+ cdev->max_brightness = 1; -+ init_data.devicename = dev_name(&phydev->mdio.dev); -+ init_data.fwnode = of_fwnode_handle(led); -+ init_data.devname_mandatory = true; -+ -+ err = devm_led_classdev_register_ext(dev, cdev, &init_data); -+ if (err) -+ return err; -+ -+ list_add(&phyled->list, &phydev->leds); -+ -+ return 0; -+} -+ -+static int of_phy_leds(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ struct device_node *leds, *led; -+ int err; -+ -+ if (!IS_ENABLED(CONFIG_OF_MDIO)) -+ return 0; -+ -+ if (!node) -+ return 0; -+ -+ leds = of_get_child_by_name(node, "leds"); -+ if (!leds) -+ return 0; -+ -+ for_each_available_child_of_node(leds, led) { -+ err = of_phy_led(phydev, led); -+ if (err) { -+ of_node_put(led); -+ return err; -+ } -+ } -+ -+ return 0; -+} -+ - /** - * fwnode_mdio_find_device - Given a fwnode, find the mdio_device - * @fwnode: pointer to the mdio_device's fwnode -@@ -3213,6 +3284,11 @@ static int phy_probe(struct device *dev) - /* Set the state to READY by default */ - phydev->state = PHY_READY; - -+ /* Get the LEDs from the device tree, and instantiate standard -+ * LEDs for them. -+ */ -+ err = of_phy_leds(phydev); -+ - out: - /* Re-assert the reset signal on error */ - if (err) ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -606,6 +607,7 @@ struct macsec_ops; - * @phy_num_led_triggers: Number of triggers in @phy_led_triggers - * @led_link_trigger: LED trigger for link up/down - * @last_triggered: last LED trigger for link speed -+ * @leds: list of PHY LED structures - * @master_slave_set: User requested master/slave configuration - * @master_slave_get: Current master/slave advertisement - * @master_slave_state: Current master/slave configuration -@@ -698,6 +700,7 @@ struct phy_device { - - struct phy_led_trigger *led_link_trigger; - #endif -+ struct list_head leds; - - /* - * Interrupt number for this PHY -@@ -772,6 +775,19 @@ struct phy_tdr_config { - #define PHY_PAIR_ALL -1 - - /** -+ * struct phy_led: An LED driven by the PHY -+ * -+ * @list: List of LEDs -+ * @led_cdev: Standard LED class structure -+ * @index: Number of the LED -+ */ -+struct phy_led { -+ struct list_head list; -+ struct led_classdev led_cdev; -+ u8 index; -+}; -+ -+/** - * struct phy_driver - Driver structure for a particular PHY type - * - * @mdiodrv: Data common to all MDIO devices diff --git a/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 4873c40a77..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 684818189b04b095b34964ed4a3ea5249a840eab Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:28 +0200 -Subject: [PATCH 6/9] net: phy: phy_device: Call into the PHY driver to set LED - brightness - -Linux LEDs can be software controlled via the brightness file in /sys. -LED drivers need to implement a brightness_set function which the core -will call. Implement an intermediary in phy_device, which will call -into the phy driver if it implements the necessary function. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 15 ++++++++++++--- - include/linux/phy.h | 13 +++++++++++++ - 2 files changed, 25 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3038,11 +3038,18 @@ static bool phy_drv_supports_irq(struct - return phydrv->config_intr && phydrv->handle_interrupt; - } - --/* Dummy implementation until calls into PHY driver are added */ - static int phy_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness value) - { -- return 0; -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_brightness_set(phydev, phyled->index, value); -+ mutex_unlock(&phydev->lock); -+ -+ return err; - } - - static int of_phy_led(struct phy_device *phydev, -@@ -3059,12 +3066,14 @@ static int of_phy_led(struct phy_device - return -ENOMEM; - - cdev = &phyled->led_cdev; -+ phyled->phydev = phydev; - - err = of_property_read_u8(led, "reg", &phyled->index); - if (err) - return err; - -- cdev->brightness_set_blocking = phy_led_set_brightness; -+ if (phydev->drv->led_brightness_set) -+ cdev->brightness_set_blocking = phy_led_set_brightness; - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -778,15 +778,19 @@ struct phy_tdr_config { - * struct phy_led: An LED driven by the PHY - * - * @list: List of LEDs -+ * @phydev: PHY this LED is attached to - * @led_cdev: Standard LED class structure - * @index: Number of the LED - */ - struct phy_led { - struct list_head list; -+ struct phy_device *phydev; - struct led_classdev led_cdev; - u8 index; - }; - -+#define to_phy_led(d) container_of(d, struct phy_led, led_cdev) -+ - /** - * struct phy_driver - Driver structure for a particular PHY type - * -@@ -1001,6 +1005,15 @@ struct phy_driver { - int (*get_sqi)(struct phy_device *dev); - /** @get_sqi_max: Get the maximum signal quality indication */ - int (*get_sqi_max)(struct phy_device *dev); -+ -+ /** -+ * @led_brightness_set: Set a PHY LED brightness. Index -+ * indicates which of the PHYs led should be set. Value -+ * follows the standard LED class meaning, e.g. LED_OFF, -+ * LED_HALF, LED_FULL. -+ */ -+ int (*led_brightness_set)(struct phy_device *dev, -+ u8 index, enum led_brightness value); - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch b/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch deleted file mode 100644 index 5114c0e6da..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-07-net-phy-marvell-Add-software-control-of-the-LEDs.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 2d3960e58ef7c83fe1dbf952f056b9e906cb6df8 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:29 +0200 -Subject: [PATCH 7/9] net: phy: marvell: Add software control of the LEDs - -Add a brightness function, so the LEDs can be controlled from -software using the standard Linux LED infrastructure. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/marvell.c | 45 ++++++++++++++++++++++++++++++++++----- - 1 file changed, 40 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -144,11 +144,13 @@ - /* WOL Event Interrupt Enable */ - #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7) - --/* LED Timer Control Register */ --#define MII_88E1318S_PHY_LED_TCR 0x12 --#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) --#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) --#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) -+#define MII_88E1318S_PHY_LED_FUNC 0x10 -+#define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) -+#define MII_88E1318S_PHY_LED_FUNC_ON (0x9) -+#define MII_88E1318S_PHY_LED_TCR 0x12 -+#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) -+#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) -+#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) - - /* Magic Packet MAC address registers */ - #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17 -@@ -2832,6 +2834,34 @@ static int marvell_hwmon_probe(struct ph - } - #endif - -+static int m88e1318_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int reg; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ reg &= ~(0xf << (4 * index)); -+ if (value == LED_OFF) -+ reg |= MII_88E1318S_PHY_LED_FUNC_OFF << (4 * index); -+ else -+ reg |= MII_88E1318S_PHY_LED_FUNC_ON << (4 * index); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3081,6 +3111,7 @@ static struct phy_driver marvell_drivers - .get_sset_count = marvell_get_sset_count, - .get_strings = marvell_get_strings, - .get_stats = marvell_get_stats, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3187,6 +3218,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3213,6 +3245,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3239,6 +3272,7 @@ static struct phy_driver marvell_drivers - .cable_test_start = marvell_vct7_cable_test_start, - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3380,6 +3414,7 @@ static struct phy_driver marvell_drivers - .get_stats = marvell_get_stats, - .get_tunable = m88e1540_get_tunable, - .set_tunable = m88e1540_set_tunable, -+ .led_brightness_set = m88e1318_led_brightness_set, - }, - }; - diff --git a/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 00bdcc5468..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4e901018432e38eab35d2a352661ce4727795be1 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:30 +0200 -Subject: [PATCH 8/9] net: phy: phy_device: Call into the PHY driver to set LED - blinking - -Linux LEDs can be requested to perform hardware accelerated -blinking. Pass this to the PHY driver, if it implements the op. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 18 ++++++++++++++++++ - include/linux/phy.h | 12 ++++++++++++ - 2 files changed, 30 insertions(+) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3052,6 +3052,22 @@ static int phy_led_set_brightness(struct - return err; - } - -+static int phy_led_blink_set(struct led_classdev *led_cdev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_blink_set(phydev, phyled->index, -+ delay_on, delay_off); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ - static int of_phy_led(struct phy_device *phydev, - struct device_node *led) - { -@@ -3074,6 +3090,8 @@ static int of_phy_led(struct phy_device - - if (phydev->drv->led_brightness_set) - cdev->brightness_set_blocking = phy_led_set_brightness; -+ if (phydev->drv->led_blink_set) -+ cdev->blink_set = phy_led_blink_set; - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1014,6 +1014,18 @@ struct phy_driver { - */ - int (*led_brightness_set)(struct phy_device *dev, - u8 index, enum led_brightness value); -+ -+ /** -+ * @led_blink_set: Set a PHY LED brightness. Index indicates -+ * which of the PHYs led should be configured to blink. Delays -+ * are in milliseconds and if both are zero then a sensible -+ * default should be chosen. The call should adjust the -+ * timings in that case and if it can't match the values -+ * specified exactly. -+ */ -+ int (*led_blink_set)(struct phy_device *dev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off); - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch b/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch deleted file mode 100644 index 8d5081a43c..0000000000 --- a/target/linux/generic/backport-6.6/801-v6.4-09-net-phy-marvell-Implement-led_blink_set.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ea9e86485decb2ac1750005bd96c166c9b780406 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 17 Apr 2023 17:17:31 +0200 -Subject: [PATCH 9/9] net: phy: marvell: Implement led_blink_set() - -The Marvell PHY can blink the LEDs, simple on/off. All LEDs blink at -the same rate, and the reset default is 84ms per blink, which is -around 12Hz. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/phy/marvell.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -147,6 +147,8 @@ - #define MII_88E1318S_PHY_LED_FUNC 0x10 - #define MII_88E1318S_PHY_LED_FUNC_OFF (0x8) - #define MII_88E1318S_PHY_LED_FUNC_ON (0x9) -+#define MII_88E1318S_PHY_LED_FUNC_HI_Z (0xa) -+#define MII_88E1318S_PHY_LED_FUNC_BLINK (0xb) - #define MII_88E1318S_PHY_LED_TCR 0x12 - #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) - #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) -@@ -2862,6 +2864,35 @@ static int m88e1318_led_brightness_set(s - MII_88E1318S_PHY_LED_FUNC, reg); - } - -+static int m88e1318_led_blink_set(struct phy_device *phydev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ int reg; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ reg &= ~(0xf << (4 * index)); -+ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -+ /* Reset default is 84ms */ -+ *delay_on = 84 / 2; -+ *delay_off = 84 / 2; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3112,6 +3143,7 @@ static struct phy_driver marvell_drivers - .get_strings = marvell_get_strings, - .get_stats = marvell_get_stats, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3219,6 +3251,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3246,6 +3279,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3273,6 +3307,7 @@ static struct phy_driver marvell_drivers - .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3415,6 +3450,7 @@ static struct phy_driver marvell_drivers - .get_tunable = m88e1540_get_tunable, - .set_tunable = m88e1540_set_tunable, - .led_brightness_set = m88e1318_led_brightness_set, -+ .led_blink_set = m88e1318_led_blink_set, - }, - }; - diff --git a/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch b/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch deleted file mode 100644 index 56df3f095e..0000000000 --- a/target/linux/generic/backport-6.6/802-v6.4-net-phy-marvell-Fix-inconsistent-indenting-in-led_bl.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 4774ad841bef97cc51df90195338c5b2573dd4cb Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 23 Apr 2023 19:28:00 +0200 -Subject: [PATCH] net: phy: marvell: Fix inconsistent indenting in - led_blink_set - -Fix inconsistent indeinting in m88e1318_led_blink_set reported by kernel -test robot, probably done by the presence of an if condition dropped in -later revision of the same code. - -Reported-by: kernel test robot -Link: https://lore.kernel.org/oe-kbuild-all/202304240007.0VEX8QYG-lkp@intel.com/ -Fixes: ea9e86485dec ("net: phy: marvell: Implement led_blink_set()") -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230423172800.3470-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2880,10 +2880,10 @@ static int m88e1318_led_blink_set(struct - case 1: - case 2: - reg &= ~(0xf << (4 * index)); -- reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -- /* Reset default is 84ms */ -- *delay_on = 84 / 2; -- *delay_off = 84 / 2; -+ reg |= MII_88E1318S_PHY_LED_FUNC_BLINK << (4 * index); -+ /* Reset default is 84ms */ -+ *delay_on = 84 / 2; -+ *delay_off = 84 / 2; - break; - default: - return -EINVAL; diff --git a/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch b/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch deleted file mode 100644 index 3170c26058..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-02-leds-trigger-netdev-Drop-NETDEV_LED_MODE_LINKUP-from.patch +++ /dev/null @@ -1,87 +0,0 @@ -From e2f24cb1b5daf9a4f6f3ba574c1fa74aab9807a4 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:40 +0200 -Subject: [PATCH 2/5] leds: trigger: netdev: Drop NETDEV_LED_MODE_LINKUP from - mode - -Putting NETDEV_LED_MODE_LINKUP in the same list of the netdev trigger -modes is wrong as it's used to set the link state of the device and not -to set a blink mode as it's done by NETDEV_LED_LINK, NETDEV_LED_TX and -NETDEV_LED_RX. It's also wrong to put this state in the same bitmap of the -netdev trigger mode and should be external to it. - -Drop NETDEV_LED_MODE_LINKUP from mode list and convert to a simple bool -that will be true or false based on the carrier link. No functional -change intended. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-3-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -50,10 +50,10 @@ struct led_netdev_data { - unsigned int last_activity; - - unsigned long mode; -+ bool carrier_link_up; - #define NETDEV_LED_LINK 0 - #define NETDEV_LED_TX 1 - #define NETDEV_LED_RX 2 --#define NETDEV_LED_MODE_LINKUP 3 - }; - - enum netdev_led_attr { -@@ -73,9 +73,9 @@ static void set_baseline_state(struct le - if (!led_cdev->blink_brightness) - led_cdev->blink_brightness = led_cdev->max_brightness; - -- if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) -+ if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); -- else { -+ } else { - if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); -@@ -131,10 +131,9 @@ static ssize_t device_name_store(struct - trigger_data->net_dev = - dev_get_by_name(&init_net, trigger_data->device_name); - -- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = false; - if (trigger_data->net_dev != NULL) -- if (netif_carrier_ok(trigger_data->net_dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); - - trigger_data->last_activity = 0; - -@@ -315,11 +314,10 @@ static int netdev_trig_notify(struct not - - spin_lock_bh(&trigger_data->lock); - -- clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = false; - switch (evt) { - case NETDEV_CHANGENAME: -- if (netif_carrier_ok(dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(dev); - fallthrough; - case NETDEV_REGISTER: - if (trigger_data->net_dev) -@@ -333,8 +331,7 @@ static int netdev_trig_notify(struct not - break; - case NETDEV_UP: - case NETDEV_CHANGE: -- if (netif_carrier_ok(dev)) -- set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); -+ trigger_data->carrier_link_up = netif_carrier_ok(dev); - break; - } - diff --git a/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch b/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch deleted file mode 100644 index 19cc1d7c9e..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-03-leds-trigger-netdev-Rename-add-namespace-to-netdev-t.patch +++ /dev/null @@ -1,149 +0,0 @@ -From bdec9cb83936e0ac4cb87fed5b49fad0175f7dec Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:41 +0200 -Subject: [PATCH 3/5] leds: trigger: netdev: Rename add namespace to netdev - trigger enum modes - -Rename NETDEV trigger enum modes to a more symbolic name and add a -namespace to them. - -Also add __TRIGGER_NETDEV_MAX to identify the max modes of the netdev -trigger. - -This is a cleanup to drop the define and no behaviour change are -intended. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-4-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 58 ++++++++++++--------------- - 1 file changed, 25 insertions(+), 33 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -51,15 +51,15 @@ struct led_netdev_data { - - unsigned long mode; - bool carrier_link_up; --#define NETDEV_LED_LINK 0 --#define NETDEV_LED_TX 1 --#define NETDEV_LED_RX 2 - }; - --enum netdev_led_attr { -- NETDEV_ATTR_LINK, -- NETDEV_ATTR_TX, -- NETDEV_ATTR_RX -+enum led_trigger_netdev_modes { -+ TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_TX, -+ TRIGGER_NETDEV_RX, -+ -+ /* Keep last */ -+ __TRIGGER_NETDEV_MAX, - }; - - static void set_baseline_state(struct led_netdev_data *trigger_data) -@@ -76,7 +76,7 @@ static void set_baseline_state(struct le - if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); - } else { -- if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); - else -@@ -85,8 +85,8 @@ static void set_baseline_state(struct le - /* If we are looking for RX/TX start periodically - * checking stats - */ -- if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || -- test_bit(NETDEV_LED_RX, &trigger_data->mode)) -+ if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) - schedule_delayed_work(&trigger_data->work, 0); - } - } -@@ -146,20 +146,16 @@ static ssize_t device_name_store(struct - static DEVICE_ATTR_RW(device_name); - - static ssize_t netdev_led_attr_show(struct device *dev, char *buf, -- enum netdev_led_attr attr) -+ enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - int bit; - - switch (attr) { -- case NETDEV_ATTR_LINK: -- bit = NETDEV_LED_LINK; -- break; -- case NETDEV_ATTR_TX: -- bit = NETDEV_LED_TX; -- break; -- case NETDEV_ATTR_RX: -- bit = NETDEV_LED_RX; -+ case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_TX: -+ case TRIGGER_NETDEV_RX: -+ bit = attr; - break; - default: - return -EINVAL; -@@ -169,7 +165,7 @@ static ssize_t netdev_led_attr_show(stru - } - - static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, -- size_t size, enum netdev_led_attr attr) -+ size_t size, enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - unsigned long state; -@@ -181,14 +177,10 @@ static ssize_t netdev_led_attr_store(str - return ret; - - switch (attr) { -- case NETDEV_ATTR_LINK: -- bit = NETDEV_LED_LINK; -- break; -- case NETDEV_ATTR_TX: -- bit = NETDEV_LED_TX; -- break; -- case NETDEV_ATTR_RX: -- bit = NETDEV_LED_RX; -+ case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_TX: -+ case TRIGGER_NETDEV_RX: -+ bit = attr; - break; - default: - return -EINVAL; -@@ -360,21 +352,21 @@ static void netdev_trig_work(struct work - } - - /* If we are not looking for RX/TX then return */ -- if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && -- !test_bit(NETDEV_LED_RX, &trigger_data->mode)) -+ if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && -+ !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) - return; - - dev_stats = dev_get_stats(trigger_data->net_dev, &temp); - new_activity = -- (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? -+ (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? - dev_stats->tx_packets : 0) + -- (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? -+ (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? - dev_stats->rx_packets : 0); - - if (trigger_data->last_activity != new_activity) { - led_stop_software_blink(trigger_data->led_cdev); - -- invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); -+ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ diff --git a/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch b/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch deleted file mode 100644 index 3b45951f57..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-04-leds-trigger-netdev-Convert-device-attr-to-macro.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 164b67d53476a9d114be85c885bd31f783835be4 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:42 +0200 -Subject: [PATCH 4/5] leds: trigger: netdev: Convert device attr to macro - -Convert link tx and rx device attr to a common macro to reduce common -code and in preparation for additional attr. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-5-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 57 ++++++++------------------- - 1 file changed, 16 insertions(+), 41 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -198,47 +198,22 @@ static ssize_t netdev_led_attr_store(str - return size; - } - --static ssize_t link_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); --} -- --static ssize_t link_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); --} -- --static DEVICE_ATTR_RW(link); -- --static ssize_t tx_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); --} -- --static ssize_t tx_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); --} -- --static DEVICE_ATTR_RW(tx); -- --static ssize_t rx_show(struct device *dev, -- struct device_attribute *attr, char *buf) --{ -- return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); --} -- --static ssize_t rx_store(struct device *dev, -- struct device_attribute *attr, const char *buf, size_t size) --{ -- return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); --} -- --static DEVICE_ATTR_RW(rx); -+#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ -+ static ssize_t trigger_name##_show(struct device *dev, \ -+ struct device_attribute *attr, char *buf) \ -+ { \ -+ return netdev_led_attr_show(dev, buf, trigger); \ -+ } \ -+ static ssize_t trigger_name##_store(struct device *dev, \ -+ struct device_attribute *attr, const char *buf, size_t size) \ -+ { \ -+ return netdev_led_attr_store(dev, buf, size, trigger); \ -+ } \ -+ static DEVICE_ATTR_RW(trigger_name) -+ -+DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); -+DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); -+DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - - static ssize_t interval_show(struct device *dev, - struct device_attribute *attr, char *buf) diff --git a/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch b/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch deleted file mode 100644 index 180bee9612..0000000000 --- a/target/linux/generic/backport-6.6/803-v6.5-05-leds-trigger-netdev-Use-mutex-instead-of-spinlocks.patch +++ /dev/null @@ -1,106 +0,0 @@ -From d1b9e1391ab2dc80e9db87fe8b2de015c651e4c9 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 19 Apr 2023 23:07:43 +0200 -Subject: [PATCH 5/5] leds: trigger: netdev: Use mutex instead of spinlocks - -Some LEDs may require to sleep while doing some operation like setting -brightness and other cleanup. - -For this reason, using a spinlock will cause a sleep under spinlock -warning. - -It should be safe to convert this to a sleepable lock since: -- sysfs read/write can sleep -- netdev_trig_work is a work queue and can sleep -- netdev _trig_notify can sleep - -The spinlock was used when brightness didn't support sleeping, but this -changed and now it supported with brightness_set_blocking(). - -Convert to mutex lock to permit sleeping using brightness_set_blocking(). - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20230419210743.3594-6-ansuelsmth@gmail.com ---- - drivers/leds/trigger/ledtrig-netdev.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -20,7 +20,7 @@ - #include - #include - #include --#include -+#include - #include - #include "../leds.h" - -@@ -37,7 +37,7 @@ - */ - - struct led_netdev_data { -- spinlock_t lock; -+ struct mutex lock; - - struct delayed_work work; - struct notifier_block notifier; -@@ -97,9 +97,9 @@ static ssize_t device_name_show(struct d - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - ssize_t len; - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - len = sprintf(buf, "%s\n", trigger_data->device_name); -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return len; - } -@@ -115,7 +115,7 @@ static ssize_t device_name_store(struct - - cancel_delayed_work_sync(&trigger_data->work); - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - - if (trigger_data->net_dev) { - dev_put(trigger_data->net_dev); -@@ -138,7 +138,7 @@ static ssize_t device_name_store(struct - trigger_data->last_activity = 0; - - set_baseline_state(trigger_data); -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return size; - } -@@ -279,7 +279,7 @@ static int netdev_trig_notify(struct not - - cancel_delayed_work_sync(&trigger_data->work); - -- spin_lock_bh(&trigger_data->lock); -+ mutex_lock(&trigger_data->lock); - - trigger_data->carrier_link_up = false; - switch (evt) { -@@ -304,7 +304,7 @@ static int netdev_trig_notify(struct not - - set_baseline_state(trigger_data); - -- spin_unlock_bh(&trigger_data->lock); -+ mutex_unlock(&trigger_data->lock); - - return NOTIFY_DONE; - } -@@ -365,7 +365,7 @@ static int netdev_trig_activate(struct l - if (!trigger_data) - return -ENOMEM; - -- spin_lock_init(&trigger_data->lock); -+ mutex_init(&trigger_data->lock); - - trigger_data->notifier.notifier_call = netdev_trig_notify; - trigger_data->notifier.priority = 10; diff --git a/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch deleted file mode 100644 index ac18611733..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-01-leds-add-APIs-for-LEDs-hw-control.patch +++ /dev/null @@ -1,74 +0,0 @@ -From ed554d3f945179c5b159bddfad7be34b403fe11a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:31 +0200 -Subject: [PATCH 01/13] leds: add APIs for LEDs hw control - -Add an option to permit LED driver to declare support for a specific -trigger to use hw control and setup the LED to blink based on specific -provided modes. - -Add APIs for LEDs hw control. These functions will be used to activate -hardware control where a LED will use the provided flags, from an -unique defined supported trigger, to setup the LED to be driven by -hardware. - -Add hw_control_is_supported() to ask the LED driver if the requested -mode by the trigger are supported and the LED can be setup to follow -the requested modes. - -Deactivate hardware blink control by setting brightness to LED_OFF via -the brightness_set() callback. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 37 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -164,6 +164,43 @@ struct led_classdev { - - /* LEDs that have private triggers have this set */ - struct led_hw_trigger_type *trigger_type; -+ -+ /* Unique trigger name supported by LED set in hw control mode */ -+ const char *hw_control_trigger; -+ /* -+ * Check if the LED driver supports the requested mode provided by the -+ * defined supported trigger to setup the LED to hw control mode. -+ * -+ * Return 0 on success. Return -EOPNOTSUPP when the passed flags are not -+ * supported and software fallback needs to be used. -+ * Return a negative error number on any other case for check fail due -+ * to various reason like device not ready or timeouts. -+ */ -+ int (*hw_control_is_supported)(struct led_classdev *led_cdev, -+ unsigned long flags); -+ /* -+ * Activate hardware control, LED driver will use the provided flags -+ * from the supported trigger and setup the LED to be driven by hardware -+ * following the requested mode from the trigger flags. -+ * Deactivate hardware blink control by setting brightness to LED_OFF via -+ * the brightness_set() callback. -+ * -+ * Return 0 on success, a negative error number on flags apply fail. -+ */ -+ int (*hw_control_set)(struct led_classdev *led_cdev, -+ unsigned long flags); -+ /* -+ * Get from the LED driver the current mode that the LED is set in hw -+ * control mode and put them in flags. -+ * Trigger can use this to get the initial state of a LED already set in -+ * hardware blink control. -+ * -+ * Return 0 on success, a negative error number on failing parsing the -+ * initial mode. Error from this function is NOT FATAL as the device -+ * may be in a not supported initial state by the attached LED trigger. -+ */ -+ int (*hw_control_get)(struct led_classdev *led_cdev, -+ unsigned long *flags); - #endif - - #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch b/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch deleted file mode 100644 index 1a221727a0..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-02-leds-add-API-to-get-attached-device-for-LED-hw-contr.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 052c38eb17e866c5b4cd43924e7a5e20167b55c0 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:32 +0200 -Subject: [PATCH 02/13] leds: add API to get attached device for LED hw control - -Some specific LED triggers blink the LED based on events from a device -or subsystem. -For example, an LED could be blinked to indicate a network device is -receiving packets, or a disk is reading blocks. To correctly enable and -request the hw control of the LED, the trigger has to check if the -network interface or block device configured via a /sys/class/led file -match the one the LED driver provide for hw control for. - -Provide an API call to get the device which the LED blinks for. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - include/linux/leds.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -201,6 +201,12 @@ struct led_classdev { - */ - int (*hw_control_get)(struct led_classdev *led_cdev, - unsigned long *flags); -+ /* -+ * Get the device this LED blinks in response to. -+ * e.g. for a PHY LED, it is the network device. If the LED is -+ * not yet associated to a device, return NULL. -+ */ -+ struct device *(*hw_control_get_device)(struct led_classdev *led_cdev); - #endif - - #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED diff --git a/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch b/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch deleted file mode 100644 index af9fb7fdc3..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-03-Documentation-leds-leds-class-Document-new-Hardware-.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 8aa2fd7b66980ecd2e45e95af61cf7eafede1211 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:33 +0200 -Subject: [PATCH 03/13] Documentation: leds: leds-class: Document new Hardware - driven LEDs APIs - -Document new Hardware driven LEDs APIs. - -Some LEDs can be programmed to be driven by hardware. This is not -limited to blink but also to turn off or on autonomously. -To support this feature, a LED needs to implement various additional -ops and needs to declare specific support for the supported triggers. - -Add documentation for each required value and API to make hw control -possible and implementable by both LEDs and triggers. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - Documentation/leds/leds-class.rst | 81 +++++++++++++++++++++++++++++++ - 1 file changed, 81 insertions(+) - ---- a/Documentation/leds/leds-class.rst -+++ b/Documentation/leds/leds-class.rst -@@ -169,6 +169,87 @@ Setting the brightness to zero with brig - should completely turn off the LED and cancel the previously programmed - hardware blinking function, if any. - -+Hardware driven LEDs -+==================== -+ -+Some LEDs can be programmed to be driven by hardware. This is not -+limited to blink but also to turn off or on autonomously. -+To support this feature, a LED needs to implement various additional -+ops and needs to declare specific support for the supported triggers. -+ -+With hw control we refer to the LED driven by hardware. -+ -+LED driver must define the following value to support hw control: -+ -+ - hw_control_trigger: -+ unique trigger name supported by the LED in hw control -+ mode. -+ -+LED driver must implement the following API to support hw control: -+ - hw_control_is_supported: -+ check if the flags passed by the supported trigger can -+ be parsed and activate hw control on the LED. -+ -+ Return 0 if the passed flags mask is supported and -+ can be set with hw_control_set(). -+ -+ If the passed flags mask is not supported -EOPNOTSUPP -+ must be returned, the LED trigger will use software -+ fallback in this case. -+ -+ Return a negative error in case of any other error like -+ device not ready or timeouts. -+ -+ - hw_control_set: -+ activate hw control. LED driver will use the provided -+ flags passed from the supported trigger, parse them to -+ a set of mode and setup the LED to be driven by hardware -+ following the requested modes. -+ -+ Set LED_OFF via the brightness_set to deactivate hw control. -+ -+ Return 0 on success, a negative error number on failing to -+ apply flags. -+ -+ - hw_control_get: -+ get active modes from a LED already in hw control, parse -+ them and set in flags the current active flags for the -+ supported trigger. -+ -+ Return 0 on success, a negative error number on failing -+ parsing the initial mode. -+ Error from this function is NOT FATAL as the device may -+ be in a not supported initial state by the attached LED -+ trigger. -+ -+ - hw_control_get_device: -+ return the device associated with the LED driver in -+ hw control. A trigger might use this to match the -+ returned device from this function with a configured -+ device for the trigger as the source for blinking -+ events and correctly enable hw control. -+ (example a netdev trigger configured to blink for a -+ particular dev match the returned dev from get_device -+ to set hw control) -+ -+ Returns a pointer to a struct device or NULL if nothing -+ is currently attached. -+ -+LED driver can activate additional modes by default to workaround the -+impossibility of supporting each different mode on the supported trigger. -+Examples are hardcoding the blink speed to a set interval, enable special -+feature like bypassing blink if some requirements are not met. -+ -+A trigger should first check if the hw control API are supported by the LED -+driver and check if the trigger is supported to verify if hw control is possible, -+use hw_control_is_supported to check if the flags are supported and only at -+the end use hw_control_set to activate hw control. -+ -+A trigger can use hw_control_get to check if a LED is already in hw control -+and init their flags. -+ -+When the LED is in hw control, no software blink is possible and doing so -+will effectively disable hw control. - - Known Issues - ============ diff --git a/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch b/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch deleted file mode 100644 index 3c804c0b41..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-04-leds-trigger-netdev-refactor-code-setting-device-nam.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 28a6a2ef18ad840a390d519840c303b03040961c Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:34 +0200 -Subject: [PATCH 04/13] leds: trigger: netdev: refactor code setting device - name - -Move the code into a helper, ready for it to be called at -other times. No intended behaviour change. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 29 ++++++++++++++++++--------- - 1 file changed, 20 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -104,15 +104,9 @@ static ssize_t device_name_show(struct d - return len; - } - --static ssize_t device_name_store(struct device *dev, -- struct device_attribute *attr, const char *buf, -- size_t size) -+static int set_device_name(struct led_netdev_data *trigger_data, -+ const char *name, size_t size) - { -- struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -- -- if (size >= IFNAMSIZ) -- return -EINVAL; -- - cancel_delayed_work_sync(&trigger_data->work); - - mutex_lock(&trigger_data->lock); -@@ -122,7 +116,7 @@ static ssize_t device_name_store(struct - trigger_data->net_dev = NULL; - } - -- memcpy(trigger_data->device_name, buf, size); -+ memcpy(trigger_data->device_name, name, size); - trigger_data->device_name[size] = 0; - if (size > 0 && trigger_data->device_name[size - 1] == '\n') - trigger_data->device_name[size - 1] = 0; -@@ -140,6 +134,23 @@ static ssize_t device_name_store(struct - set_baseline_state(trigger_data); - mutex_unlock(&trigger_data->lock); - -+ return 0; -+} -+ -+static ssize_t device_name_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, -+ size_t size) -+{ -+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -+ int ret; -+ -+ if (size >= IFNAMSIZ) -+ return -EINVAL; -+ -+ ret = set_device_name(trigger_data, buf, size); -+ -+ if (ret < 0) -+ return ret; - return size; - } - diff --git a/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch b/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch deleted file mode 100644 index 284b519482..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-05-leds-trigger-netdev-introduce-check-for-possible-hw-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4fd1b6d47a7a38e81fdc6f8be2ccd4216b3f93db Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:35 +0200 -Subject: [PATCH 05/13] leds: trigger: netdev: introduce check for possible hw - control - -Introduce function to check if the requested mode can use hw control in -preparation for hw control support. Currently everything is handled in -software so can_hw_control will always return false. - -Add knob with the new value hw_control in trigger_data struct to -set hw control possible. Useful for future implementation to implement -in set_baseline_state() the required function to set the requested mode -using LEDs hw control ops and in other function to reject set if hw -control is currently active. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -51,6 +51,7 @@ struct led_netdev_data { - - unsigned long mode; - bool carrier_link_up; -+ bool hw_control; - }; - - enum led_trigger_netdev_modes { -@@ -91,6 +92,11 @@ static void set_baseline_state(struct le - } - } - -+static bool can_hw_control(struct led_netdev_data *trigger_data) -+{ -+ return false; -+} -+ - static ssize_t device_name_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -204,6 +210,8 @@ static ssize_t netdev_led_attr_store(str - else - clear_bit(bit, &trigger_data->mode); - -+ trigger_data->hw_control = can_hw_control(trigger_data); -+ - set_baseline_state(trigger_data); - - return size; diff --git a/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch b/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch deleted file mode 100644 index 09759bc623..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-06-leds-trigger-netdev-add-basic-check-for-hw-control-s.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6352f25f9fadba59d5df2ba7139495759ccc81d5 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:36 +0200 -Subject: [PATCH 06/13] leds: trigger: netdev: add basic check for hw control - support - -Add basic check for hw control support. Check if the required API are -defined and check if the defined trigger supported in hw control for the -LED driver match netdev. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -92,8 +92,22 @@ static void set_baseline_state(struct le - } - } - -+static bool supports_hw_control(struct led_classdev *led_cdev) -+{ -+ if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || -+ !led_cdev->hw_control_is_supported) -+ return false; -+ -+ return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); -+} -+ - static bool can_hw_control(struct led_netdev_data *trigger_data) - { -+ struct led_classdev *led_cdev = trigger_data->led_cdev; -+ -+ if (!supports_hw_control(led_cdev)) -+ return false; -+ - return false; - } - diff --git a/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch b/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch deleted file mode 100644 index 6634906800..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-07-leds-trigger-netdev-reject-interval-store-for-hw_con.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c84c80c7388f887b10dafd70fc55bc6c5fe9fa5a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:37 +0200 -Subject: [PATCH 07/13] leds: trigger: netdev: reject interval store for - hw_control - -Reject interval store with hw_control enabled. It's are currently not -supported and MUST be set to the default value with hw control enabled. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -265,6 +265,9 @@ static ssize_t interval_store(struct dev - unsigned long value; - int ret; - -+ if (trigger_data->hw_control) -+ return -EINVAL; -+ - ret = kstrtoul(buf, 0, &value); - if (ret) - return ret; diff --git a/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch b/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch deleted file mode 100644 index 52faa4809b..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-08-leds-trigger-netdev-add-support-for-LED-hw-control.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 7c145a34ba6e380616af93262fcab9fc7261d851 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:38 +0200 -Subject: [PATCH 08/13] leds: trigger: netdev: add support for LED hw control - -Add support for LED hw control for the netdev trigger. - -The trigger on calling set_baseline_state to configure a new mode, will -do various check to verify if hw control can be used for the requested -mode in can_hw_control() function. - -It will first check if the LED driver supports hw control for the netdev -trigger, then will use hw_control_is_supported() and finally will call -hw_control_set() to apply the requested mode. - -To use such mode, interval MUST be set to the default value and net_dev -MUST be set. If one of these 2 value are not valid, hw control will -never be used and normal software fallback is used. - -The default interval value is moved to a define to make sure they are -always synced. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 43 +++++++++++++++++++++++++-- - 1 file changed, 41 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -24,6 +24,8 @@ - #include - #include "../leds.h" - -+#define NETDEV_LED_DEFAULT_INTERVAL 50 -+ - /* - * Configurable sysfs attributes: - * -@@ -68,6 +70,13 @@ static void set_baseline_state(struct le - int current_brightness; - struct led_classdev *led_cdev = trigger_data->led_cdev; - -+ /* Already validated, hw control is possible with the requested mode */ -+ if (trigger_data->hw_control) { -+ led_cdev->hw_control_set(led_cdev, trigger_data->mode); -+ -+ return; -+ } -+ - current_brightness = led_cdev->brightness; - if (current_brightness) - led_cdev->blink_brightness = current_brightness; -@@ -103,12 +112,42 @@ static bool supports_hw_control(struct l - - static bool can_hw_control(struct led_netdev_data *trigger_data) - { -+ unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); -+ unsigned int interval = atomic_read(&trigger_data->interval); - struct led_classdev *led_cdev = trigger_data->led_cdev; -+ int ret; - - if (!supports_hw_control(led_cdev)) - return false; - -- return false; -+ /* -+ * Interval must be set to the default -+ * value. Any different value is rejected if in hw -+ * control. -+ */ -+ if (interval != default_interval) -+ return false; -+ -+ /* -+ * net_dev must be set with hw control, otherwise no -+ * blinking can be happening and there is nothing to -+ * offloaded. -+ */ -+ if (!trigger_data->net_dev) -+ return false; -+ -+ /* Check if the requested mode is supported */ -+ ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); -+ /* Fall back to software blinking if not supported */ -+ if (ret == -EOPNOTSUPP) -+ return false; -+ if (ret) { -+ dev_warn(led_cdev->dev, -+ "Current mode check failed with error %d\n", ret); -+ return false; -+ } -+ -+ return true; - } - - static ssize_t device_name_show(struct device *dev, -@@ -413,7 +452,7 @@ static int netdev_trig_activate(struct l - trigger_data->device_name[0] = 0; - - trigger_data->mode = 0; -- atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); -+ atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); - trigger_data->last_activity = 0; - - led_set_trigger_data(led_cdev, trigger_data); diff --git a/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch deleted file mode 100644 index c129ffa4f5..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-09-leds-trigger-netdev-validate-configured-netdev.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 33ec0b53befff2c0a7f3aa19ff08556d60585d6b Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:39 +0200 -Subject: [PATCH 09/13] leds: trigger: netdev: validate configured netdev - -The netdev which the LED should blink for is configurable in -/sys/class/led/foo/device_name. Ensure when offloading that the -configured netdev is the same as the netdev the LED is associated -with. If it is not, only perform software blinking. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 24 ++++++++++++++++++++++-- - 1 file changed, 22 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -110,6 +110,24 @@ static bool supports_hw_control(struct l - return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); - } - -+/* -+ * Validate the configured netdev is the same as the one associated with -+ * the LED driver in hw control. -+ */ -+static bool validate_net_dev(struct led_classdev *led_cdev, -+ struct net_device *net_dev) -+{ -+ struct device *dev = led_cdev->hw_control_get_device(led_cdev); -+ struct net_device *ndev; -+ -+ if (!dev) -+ return false; -+ -+ ndev = to_net_dev(dev); -+ -+ return ndev == net_dev; -+} -+ - static bool can_hw_control(struct led_netdev_data *trigger_data) - { - unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); -@@ -131,9 +149,11 @@ static bool can_hw_control(struct led_ne - /* - * net_dev must be set with hw control, otherwise no - * blinking can be happening and there is nothing to -- * offloaded. -+ * offloaded. Additionally, for hw control to be -+ * valid, the configured netdev must be the same as -+ * netdev associated to the LED. - */ -- if (!trigger_data->net_dev) -+ if (!validate_net_dev(led_cdev, trigger_data->net_dev)) - return false; - - /* Check if the requested mode is supported */ diff --git a/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch b/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch deleted file mode 100644 index e20594c99a..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-10-leds-trigger-netdev-init-mode-if-hw-control-already-.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0316cc5629d15880dd3f097d221c55ca648bcd61 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:40 +0200 -Subject: [PATCH 10/13] leds: trigger: netdev: init mode if hw control already - active - -On netdev trigger activation, hw control may be already active by -default. If this is the case and a device is actually provided by -hw_control_get_device(), init the already active mode and set the -bool to hw_control bool to true to reflect the already set mode in the -trigger_data. - -Co-developed-by: Andrew Lunn -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -454,6 +454,8 @@ static void netdev_trig_work(struct work - static int netdev_trig_activate(struct led_classdev *led_cdev) - { - struct led_netdev_data *trigger_data; -+ unsigned long mode; -+ struct device *dev; - int rc; - - trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); -@@ -475,6 +477,21 @@ static int netdev_trig_activate(struct l - atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); - trigger_data->last_activity = 0; - -+ /* Check if hw control is active by default on the LED. -+ * Init already enabled mode in hw control. -+ */ -+ if (supports_hw_control(led_cdev) && -+ !led_cdev->hw_control_get(led_cdev, &mode)) { -+ dev = led_cdev->hw_control_get_device(led_cdev); -+ if (dev) { -+ const char *name = dev_name(dev); -+ -+ set_device_name(trigger_data, name, strlen(name)); -+ trigger_data->hw_control = true; -+ trigger_data->mode = mode; -+ } -+ } -+ - led_set_trigger_data(led_cdev, trigger_data); - - rc = register_netdevice_notifier(&trigger_data->notifier); diff --git a/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch b/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch deleted file mode 100644 index 70aed850d1..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-11-leds-trigger-netdev-expose-netdev-trigger-modes-in-l.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 947acacab5ea151291b861cdfbde16ff5cf1b08c Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:41 +0200 -Subject: [PATCH 11/13] leds: trigger: netdev: expose netdev trigger modes in - linux include - -Expose netdev trigger modes to make them accessible by LED driver that -will support netdev trigger for hw control. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 9 --------- - include/linux/leds.h | 10 ++++++++++ - 2 files changed, 10 insertions(+), 9 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -56,15 +56,6 @@ struct led_netdev_data { - bool hw_control; - }; - --enum led_trigger_netdev_modes { -- TRIGGER_NETDEV_LINK = 0, -- TRIGGER_NETDEV_TX, -- TRIGGER_NETDEV_RX, -- -- /* Keep last */ -- __TRIGGER_NETDEV_MAX, --}; -- - static void set_baseline_state(struct led_netdev_data *trigger_data) - { - int current_brightness; ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -527,6 +527,16 @@ static inline void *led_get_trigger_data - - #endif /* CONFIG_LEDS_TRIGGERS */ - -+/* Trigger specific enum */ -+enum led_trigger_netdev_modes { -+ TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_TX, -+ TRIGGER_NETDEV_RX, -+ -+ /* Keep last */ -+ __TRIGGER_NETDEV_MAX, -+}; -+ - /* Trigger specific functions */ - #ifdef CONFIG_LEDS_TRIGGER_DISK - void ledtrig_disk_activity(bool write); diff --git a/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch b/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch deleted file mode 100644 index ad76d89b7b..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-12-net-dsa-qca8k-implement-hw_control-ops.patch +++ /dev/null @@ -1,200 +0,0 @@ -From e0256648c831af13cbfe4a1787327fcec01c2807 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 29 May 2023 18:32:42 +0200 -Subject: [PATCH 12/13] net: dsa: qca8k: implement hw_control ops - -Implement hw_control ops to drive Switch LEDs based on hardware events. - -Netdev trigger is the declared supported trigger for hw control -operation and supports the following mode: -- tx -- rx - -When hw_control_set is called, LEDs are set to follow the requested -mode. -Each LEDs will blink at 4Hz by default. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 154 +++++++++++++++++++++++++++++++ - 1 file changed, 154 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -32,6 +32,43 @@ qca8k_get_enable_led_reg(int port_num, i - } - - static int -+qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) -+{ -+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num); -+ -+ /* 6 total control rule: -+ * 3 control rules for phy0-3 that applies to all their leds -+ * 3 control rules for phy4 -+ */ -+ if (port_num == 4) -+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; -+ else -+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; -+ -+ return 0; -+} -+ -+static int -+qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger) -+{ -+ /* Parsing specific to netdev trigger */ -+ if (test_bit(TRIGGER_NETDEV_TX, &rules)) -+ *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; -+ if (test_bit(TRIGGER_NETDEV_RX, &rules)) -+ *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; -+ -+ if (rules && !*offload_trigger) -+ return -EOPNOTSUPP; -+ -+ /* Enable some default rule by default to the requested mode: -+ * - Blink at 4Hz by default -+ */ -+ *offload_trigger |= QCA8K_LED_BLINK_4HZ; -+ -+ return 0; -+} -+ -+static int - qca8k_led_brightness_set(struct qca8k_led *led, - enum led_brightness brightness) - { -@@ -165,6 +202,119 @@ qca8k_cled_blink_set(struct led_classdev - } - - static int -+qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 mask, val = QCA8K_LED_ALWAYS_OFF; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ if (enable) -+ val = QCA8K_LED_RULE_CONTROLLED; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ mask = QCA8K_LED_PATTERN_EN_MASK; -+ val <<= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, -+ val << reg_info.shift); -+} -+ -+static bool -+qca8k_cled_hw_control_status(struct led_classdev *ldev) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ -+ qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); -+ -+ regmap_read(priv->regmap, reg_info.reg, &val); -+ -+ val >>= reg_info.shift; -+ -+ if (led->port_num == 0 || led->port_num == 4) { -+ val &= QCA8K_LED_PATTERN_EN_MASK; -+ val >>= QCA8K_LED_PATTERN_EN_SHIFT; -+ } else { -+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; -+ } -+ -+ return val == QCA8K_LED_RULE_CONTROLLED; -+} -+ -+static int -+qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) -+{ -+ u32 offload_trigger = 0; -+ -+ return qca8k_parse_netdev(rules, &offload_trigger); -+} -+ -+static int -+qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 offload_trigger = 0; -+ int ret; -+ -+ ret = qca8k_parse_netdev(rules, &offload_trigger); -+ if (ret) -+ return ret; -+ -+ ret = qca8k_cled_trigger_offload(ldev, true); -+ if (ret) -+ return ret; -+ -+ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); -+ -+ return regmap_update_bits(priv->regmap, reg_info.reg, -+ QCA8K_LED_RULE_MASK << reg_info.shift, -+ offload_trigger << reg_info.shift); -+} -+ -+static int -+qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_led_pattern_en reg_info; -+ struct qca8k_priv *priv = led->priv; -+ u32 val; -+ int ret; -+ -+ /* With hw control not active return err */ -+ if (!qca8k_cled_hw_control_status(ldev)) -+ return -EINVAL; -+ -+ qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); -+ -+ ret = regmap_read(priv->regmap, reg_info.reg, &val); -+ if (ret) -+ return ret; -+ -+ val >>= reg_info.shift; -+ val &= QCA8K_LED_RULE_MASK; -+ -+ /* Parsing specific to netdev trigger */ -+ if (val & QCA8K_LED_TX_BLINK_MASK) -+ set_bit(TRIGGER_NETDEV_TX, rules); -+ if (val & QCA8K_LED_RX_BLINK_MASK) -+ set_bit(TRIGGER_NETDEV_RX, rules); -+ -+ return 0; -+} -+ -+static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { - struct fwnode_handle *led = NULL, *leds = NULL; -@@ -224,6 +374,10 @@ qca8k_parse_port_leds(struct qca8k_priv - port_led->cdev.max_brightness = 1; - port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; - port_led->cdev.blink_set = qca8k_cled_blink_set; -+ port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; -+ port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; -+ port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; -+ port_led->cdev.hw_control_trigger = "netdev"; - init_data.default_label = ":port"; - init_data.fwnode = led; - init_data.devname_mandatory = true; diff --git a/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch b/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch deleted file mode 100644 index feb6b9e1e4..0000000000 --- a/target/linux/generic/backport-6.6/804-v6.5-13-net-dsa-qca8k-add-op-to-get-ports-netdev.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 4f53c27f772e27e4cf4e5507d6f4d5980002cb6a Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Mon, 29 May 2023 18:32:43 +0200 -Subject: [PATCH 13/13] net: dsa: qca8k: add op to get ports netdev - -In order that the LED trigger can blink the switch MAC ports LED, it -needs to know the netdev associated to the port. Add the callback to -return the struct device of the netdev. - -Add an helper function qca8k_phy_to_port() to convert the phy back to -dsa_port index, as we reference LED port based on the internal PHY -index and needs to be converted back. - -Signed-off-by: Andrew Lunn -Signed-off-by: Christian Marangi -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca/qca8k-leds.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -5,6 +5,18 @@ - #include "qca8k.h" - #include "qca8k_leds.h" - -+static u32 qca8k_phy_to_port(int phy) -+{ -+ /* Internal PHY 0 has port at index 1. -+ * Internal PHY 1 has port at index 2. -+ * Internal PHY 2 has port at index 3. -+ * Internal PHY 3 has port at index 4. -+ * Internal PHY 4 has port at index 5. -+ */ -+ -+ return phy + 1; -+} -+ - static int - qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) - { -@@ -314,6 +326,20 @@ qca8k_cled_hw_control_get(struct led_cla - return 0; - } - -+static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev) -+{ -+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); -+ struct qca8k_priv *priv = led->priv; -+ struct dsa_port *dp; -+ -+ dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num)); -+ if (!dp) -+ return NULL; -+ if (dp->slave) -+ return &dp->slave->dev; -+ return NULL; -+} -+ - static int - qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) - { -@@ -377,6 +403,7 @@ qca8k_parse_port_leds(struct qca8k_priv - port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; - port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; - port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; -+ port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device; - port_led->cdev.hw_control_trigger = "netdev"; - init_data.default_label = ":port"; - init_data.fwnode = led; diff --git a/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch b/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch deleted file mode 100644 index 1c564b3897..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-01-leds-trigger-netdev-add-additional-specific-link-spe.patch +++ /dev/null @@ -1,242 +0,0 @@ -From d5e01266e7f5fa12400d4c8aa4e86fe89dcc61e9 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:46:58 +0200 -Subject: [PATCH 1/3] leds: trigger: netdev: add additional specific link speed - mode - -Add additional modes for specific link speed. Use ethtool APIs to get the -current link speed and enable the LED accordingly. Under netdev event -handler the rtnl lock is already held and is not needed to be set to -access ethtool APIs. - -This is especially useful for PHY and Switch that supports LEDs hw -control for specific link speed. (example scenario a PHY that have 2 LED -connected one green and one orange where the green is turned on with -1000mbps speed and orange is turned on with 10mpbs speed) - -On mode set from sysfs we check if we have enabled split link speed mode -and reject enabling generic link mode to prevent wrong and redundant -configuration. - -Rework logic on the set baseline state to support these new modes to -select if we need to turn on or off the LED. - -Add additional modes: -- link_10: Turn on LED when link speed is 10mbps -- link_100: Turn on LED when link speed is 100mbps -- link_1000: Turn on LED when link speed is 1000mbps - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 80 +++++++++++++++++++++++---- - include/linux/leds.h | 3 + - 2 files changed, 73 insertions(+), 10 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -21,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include "../leds.h" - -@@ -52,6 +54,8 @@ struct led_netdev_data { - unsigned int last_activity; - - unsigned long mode; -+ int link_speed; -+ - bool carrier_link_up; - bool hw_control; - }; -@@ -77,7 +81,24 @@ static void set_baseline_state(struct le - if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); - } else { -+ bool blink_on = false; -+ - if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_10) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_100) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && -+ trigger_data->link_speed == SPEED_1000) -+ blink_on = true; -+ -+ if (blink_on) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); - else -@@ -161,6 +182,18 @@ static bool can_hw_control(struct led_ne - return true; - } - -+static void get_device_state(struct led_netdev_data *trigger_data) -+{ -+ struct ethtool_link_ksettings cmd; -+ -+ trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); -+ if (!trigger_data->carrier_link_up) -+ return; -+ -+ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) -+ trigger_data->link_speed = cmd.base.speed; -+} -+ - static ssize_t device_name_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -@@ -196,8 +229,12 @@ static int set_device_name(struct led_ne - dev_get_by_name(&init_net, trigger_data->device_name); - - trigger_data->carrier_link_up = false; -- if (trigger_data->net_dev != NULL) -- trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); -+ trigger_data->link_speed = SPEED_UNKNOWN; -+ if (trigger_data->net_dev != NULL) { -+ rtnl_lock(); -+ get_device_state(trigger_data); -+ rtnl_unlock(); -+ } - - trigger_data->last_activity = 0; - -@@ -234,6 +271,9 @@ static ssize_t netdev_led_attr_show(stru - - switch (attr) { - case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_LINK_10: -+ case TRIGGER_NETDEV_LINK_100: -+ case TRIGGER_NETDEV_LINK_1000: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -249,7 +289,7 @@ static ssize_t netdev_led_attr_store(str - size_t size, enum led_trigger_netdev_modes attr) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -- unsigned long state; -+ unsigned long state, mode = trigger_data->mode; - int ret; - int bit; - -@@ -259,6 +299,9 @@ static ssize_t netdev_led_attr_store(str - - switch (attr) { - case TRIGGER_NETDEV_LINK: -+ case TRIGGER_NETDEV_LINK_10: -+ case TRIGGER_NETDEV_LINK_100: -+ case TRIGGER_NETDEV_LINK_1000: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -267,13 +310,20 @@ static ssize_t netdev_led_attr_store(str - return -EINVAL; - } - -- cancel_delayed_work_sync(&trigger_data->work); -- - if (state) -- set_bit(bit, &trigger_data->mode); -+ set_bit(bit, &mode); - else -- clear_bit(bit, &trigger_data->mode); -+ clear_bit(bit, &mode); -+ -+ if (test_bit(TRIGGER_NETDEV_LINK, &mode) && -+ (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &mode) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) -+ return -EINVAL; -+ -+ cancel_delayed_work_sync(&trigger_data->work); - -+ trigger_data->mode = mode; - trigger_data->hw_control = can_hw_control(trigger_data); - - set_baseline_state(trigger_data); -@@ -295,6 +345,9 @@ static ssize_t netdev_led_attr_store(str - static DEVICE_ATTR_RW(trigger_name) - - DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); -+DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); -+DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); -+DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); - DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); - DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - -@@ -338,6 +391,9 @@ static DEVICE_ATTR_RW(interval); - static struct attribute *netdev_trig_attrs[] = { - &dev_attr_device_name.attr, - &dev_attr_link.attr, -+ &dev_attr_link_10.attr, -+ &dev_attr_link_100.attr, -+ &dev_attr_link_1000.attr, - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -@@ -368,9 +424,10 @@ static int netdev_trig_notify(struct not - mutex_lock(&trigger_data->lock); - - trigger_data->carrier_link_up = false; -+ trigger_data->link_speed = SPEED_UNKNOWN; - switch (evt) { - case NETDEV_CHANGENAME: -- trigger_data->carrier_link_up = netif_carrier_ok(dev); -+ get_device_state(trigger_data); - fallthrough; - case NETDEV_REGISTER: - if (trigger_data->net_dev) -@@ -384,7 +441,7 @@ static int netdev_trig_notify(struct not - break; - case NETDEV_UP: - case NETDEV_CHANGE: -- trigger_data->carrier_link_up = netif_carrier_ok(dev); -+ get_device_state(trigger_data); - break; - } - -@@ -427,7 +484,10 @@ static void netdev_trig_work(struct work - if (trigger_data->last_activity != new_activity) { - led_stop_software_blink(trigger_data->led_cdev); - -- invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); -+ invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -530,6 +530,9 @@ static inline void *led_get_trigger_data - /* Trigger specific enum */ - enum led_trigger_netdev_modes { - TRIGGER_NETDEV_LINK = 0, -+ TRIGGER_NETDEV_LINK_10, -+ TRIGGER_NETDEV_LINK_100, -+ TRIGGER_NETDEV_LINK_1000, - TRIGGER_NETDEV_TX, - TRIGGER_NETDEV_RX, - diff --git a/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch b/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch deleted file mode 100644 index a5ab461828..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-02-leds-trigger-netdev-add-additional-specific-link-dup.patch +++ /dev/null @@ -1,138 +0,0 @@ -From f22f95b9ff1551c9bab13104131929f33d51f23f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:46:59 +0200 -Subject: [PATCH 2/3] leds: trigger: netdev: add additional specific link - duplex mode - -Add additional modes for specific link duplex. Use ethtool APIs to get the -current link duplex and enable the LED accordingly. Under netdev event -handler the rtnl lock is already held and is not needed to be set to -access ethtool APIs. - -This is especially useful for PHY and Switch that supports LEDs hw -control for specific link duplex. - -Add additional modes: -- half_duplex: Turn on LED when link is half duplex -- full_duplex: Turn on LED when link is full duplex - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 27 +++++++++++++++++++++++++-- - include/linux/leds.h | 2 ++ - 2 files changed, 27 insertions(+), 2 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -55,6 +55,7 @@ struct led_netdev_data { - - unsigned long mode; - int link_speed; -+ u8 duplex; - - bool carrier_link_up; - bool hw_control; -@@ -98,6 +99,14 @@ static void set_baseline_state(struct le - trigger_data->link_speed == SPEED_1000) - blink_on = true; - -+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && -+ trigger_data->duplex == DUPLEX_HALF) -+ blink_on = true; -+ -+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && -+ trigger_data->duplex == DUPLEX_FULL) -+ blink_on = true; -+ - if (blink_on) - led_set_brightness(led_cdev, - led_cdev->blink_brightness); -@@ -190,8 +199,10 @@ static void get_device_state(struct led_ - if (!trigger_data->carrier_link_up) - return; - -- if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) -+ if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { - trigger_data->link_speed = cmd.base.speed; -+ trigger_data->duplex = cmd.base.duplex; -+ } - } - - static ssize_t device_name_show(struct device *dev, -@@ -230,6 +241,7 @@ static int set_device_name(struct led_ne - - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; -+ trigger_data->duplex = DUPLEX_UNKNOWN; - if (trigger_data->net_dev != NULL) { - rtnl_lock(); - get_device_state(trigger_data); -@@ -274,6 +286,8 @@ static ssize_t netdev_led_attr_show(stru - case TRIGGER_NETDEV_LINK_10: - case TRIGGER_NETDEV_LINK_100: - case TRIGGER_NETDEV_LINK_1000: -+ case TRIGGER_NETDEV_HALF_DUPLEX: -+ case TRIGGER_NETDEV_FULL_DUPLEX: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -302,6 +316,8 @@ static ssize_t netdev_led_attr_store(str - case TRIGGER_NETDEV_LINK_10: - case TRIGGER_NETDEV_LINK_100: - case TRIGGER_NETDEV_LINK_1000: -+ case TRIGGER_NETDEV_HALF_DUPLEX: -+ case TRIGGER_NETDEV_FULL_DUPLEX: - case TRIGGER_NETDEV_TX: - case TRIGGER_NETDEV_RX: - bit = attr; -@@ -348,6 +364,8 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD - DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); - DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); - DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); -+DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); -+DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); - DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); - DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); - -@@ -394,6 +412,8 @@ static struct attribute *netdev_trig_att - &dev_attr_link_10.attr, - &dev_attr_link_100.attr, - &dev_attr_link_1000.attr, -+ &dev_attr_full_duplex.attr, -+ &dev_attr_half_duplex.attr, - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -@@ -425,6 +445,7 @@ static int netdev_trig_notify(struct not - - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; -+ trigger_data->duplex = DUPLEX_UNKNOWN; - switch (evt) { - case NETDEV_CHANGENAME: - get_device_state(trigger_data); -@@ -487,7 +508,9 @@ static void netdev_trig_work(struct work - invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || - test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || - test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || -- test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); -+ test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || -+ test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); - interval = jiffies_to_msecs( - atomic_read(&trigger_data->interval)); - /* base state is ON (link present) */ ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -533,6 +533,8 @@ enum led_trigger_netdev_modes { - TRIGGER_NETDEV_LINK_10, - TRIGGER_NETDEV_LINK_100, - TRIGGER_NETDEV_LINK_1000, -+ TRIGGER_NETDEV_HALF_DUPLEX, -+ TRIGGER_NETDEV_FULL_DUPLEX, - TRIGGER_NETDEV_TX, - TRIGGER_NETDEV_RX, - diff --git a/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch b/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch deleted file mode 100644 index 67528cafe0..0000000000 --- a/target/linux/generic/backport-6.6/805-v6.5-03-leds-trigger-netdev-expose-hw_control-status-via-sys.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b655892ffd6d89b0c7407e099c40dbde82ee3f03 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 19 Jun 2023 22:47:00 +0200 -Subject: [PATCH 3/3] leds: trigger: netdev: expose hw_control status via sysfs - -Expose hw_control status via sysfs for the netdev trigger to give -userspace better understanding of the current state of the trigger and -the LED. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Kalesh AP -Acked-by: Lee Jones -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -406,6 +406,16 @@ static ssize_t interval_store(struct dev - - static DEVICE_ATTR_RW(interval); - -+static ssize_t hw_control_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", trigger_data->hw_control); -+} -+ -+static DEVICE_ATTR_RO(hw_control); -+ - static struct attribute *netdev_trig_attrs[] = { - &dev_attr_device_name.attr, - &dev_attr_link.attr, -@@ -417,6 +427,7 @@ static struct attribute *netdev_trig_att - &dev_attr_rx.attr, - &dev_attr_tx.attr, - &dev_attr_interval.attr, -+ &dev_attr_hw_control.attr, - NULL - }; - ATTRIBUTE_GROUPS(netdev_trig); diff --git a/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch b/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch deleted file mode 100644 index ac322e1939..0000000000 --- a/target/linux/generic/backport-6.6/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 2555f35a4f428a9bfdf09aa0459dbfdf59a24a9a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 21 Jun 2023 11:54:09 +0200 -Subject: [PATCH] net: dsa: qca8k: add support for additional modes for netdev - trigger - -The QCA8K switch supports additional modes that can be handled in -hardware for the LED netdev trigger. - -Add these additional modes to further support the Switch LEDs and -offload more blink modes. - -Add additional modes: -- link_10 -- link_100 -- link_1000 -- half_duplex -- full_duplex - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230621095409.25859-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/qca/qca8k-leds.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/net/dsa/qca/qca8k-leds.c -+++ b/drivers/net/dsa/qca/qca8k-leds.c -@@ -68,6 +68,16 @@ qca8k_parse_netdev(unsigned long rules, - *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; - if (test_bit(TRIGGER_NETDEV_RX, &rules)) - *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK; -+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) -+ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK; -+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) -+ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK; - - if (rules && !*offload_trigger) - return -EOPNOTSUPP; -@@ -322,6 +332,16 @@ qca8k_cled_hw_control_get(struct led_cla - set_bit(TRIGGER_NETDEV_TX, rules); - if (val & QCA8K_LED_RX_BLINK_MASK) - set_bit(TRIGGER_NETDEV_RX, rules); -+ if (val & QCA8K_LED_LINK_10M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_10, rules); -+ if (val & QCA8K_LED_LINK_100M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_100, rules); -+ if (val & QCA8K_LED_LINK_1000M_EN_MASK) -+ set_bit(TRIGGER_NETDEV_LINK_1000, rules); -+ if (val & QCA8K_LED_HALF_DUPLEX_MASK) -+ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); -+ if (val & QCA8K_LED_FULL_DUPLEX_MASK) -+ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch b/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch deleted file mode 100644 index 58777cd280..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 4f86eb098e18fd0f032877dfa1a7e8c1503ca409 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:41 +0200 -Subject: [PATCH 1/6] net: dsa: mv88e6xxx: pass directly chip structure to - mv88e6xxx_phy_is_internal -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since this function is a simple helper, we do not need to pass a full -dsa_switch structure, we can directly pass the mv88e6xxx_chip structure. -Doing so will allow to share this function with any other function -not manipulating dsa_switch structure but needing info about number of -internal phys - -Signed-off-by: Alexis Lothoré -Reviewed-by: Russell King (Oracle) -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -470,10 +470,8 @@ restore_link: - return err; - } - --static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) -+static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) - { -- struct mv88e6xxx_chip *chip = ds->priv; -- - return port < chip->info->num_internal_phys; - } - -@@ -591,7 +589,7 @@ static void mv88e6095_phylink_get_caps(s - - config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; - -- if (mv88e6xxx_phy_is_internal(chip->ds, port)) { -+ if (mv88e6xxx_phy_is_internal(chip, port)) { - __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); - } else { - if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && -@@ -839,7 +837,7 @@ static void mv88e6xxx_get_caps(struct ds - chip->info->ops->phylink_get_caps(chip, port, config); - mv88e6xxx_reg_unlock(chip); - -- if (mv88e6xxx_phy_is_internal(ds, port)) { -+ if (mv88e6xxx_phy_is_internal(chip, port)) { - __set_bit(PHY_INTERFACE_MODE_INTERNAL, - config->supported_interfaces); - /* Internal ports with no phy-mode need GMII for PHYLIB */ -@@ -860,7 +858,7 @@ static void mv88e6xxx_mac_config(struct - - mv88e6xxx_reg_lock(chip); - -- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { -+ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { - /* In inband mode, the link may come up at any time while the - * link is not forced down. Force the link down while we - * reconfigure the interface mode. diff --git a/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch b/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch deleted file mode 100644 index 75a21a931d..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 73cbfad9296eed004992806e056db5b48583ca41 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:42 +0200 -Subject: [PATCH 2/6] net: dsa: mv88e6xxx: use mv88e6xxx_phy_is_internal in - mv88e6xxx_port_ppu_updates -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make sure to use existing helper to get internal PHYs count instead of -redoing it manually - -Signed-off-by: Alexis Lothoré -Reviewed-by: Russell King (Oracle) -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -484,7 +484,7 @@ static int mv88e6xxx_port_ppu_updates(st - * report whether the port is internal. - */ - if (chip->info->family == MV88E6XXX_FAMILY_6250) -- return port < chip->info->num_internal_phys; -+ return mv88e6xxx_phy_is_internal(chip, port); - - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); - if (err) { diff --git a/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch b/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch deleted file mode 100644 index e24dca819b..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 1414d30660d201f515a9d877571ceea9ca190b6a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:43 +0200 -Subject: [PATCH 3/6] net: dsa: mv88e6xxx: add field to specify internal phys - layout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -mv88e6xxx currently assumes that switch equipped with internal phys have -those phys mapped contiguously starting from port 0 (see -mv88e6xxx_phy_is_internal). However, some switches have internal PHYs but -NOT starting from port 0. For example 88e6393X, 88E6193X and 88E6191X have -integrated PHYs available on ports 1 to 8 -To properly support this offset, add a new field to allow specifying an -internal PHYs layout. If field is not set, default layout is assumed (start -at port 0) - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- - drivers/net/dsa/mv88e6xxx/chip.h | 5 +++++ - drivers/net/dsa/mv88e6xxx/global2.c | 5 ++++- - 3 files changed, 12 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -472,7 +472,9 @@ restore_link: - - static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) - { -- return port < chip->info->num_internal_phys; -+ return port >= chip->info->internal_phys_offset && -+ port < chip->info->num_internal_phys + -+ chip->info->internal_phys_offset; - } - - static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -167,6 +167,11 @@ struct mv88e6xxx_info { - - /* Supports PTP */ - bool ptp_support; -+ -+ /* Internal PHY start index. 0 means that internal PHYs range starts at -+ * port 0, 1 means internal PHYs range starts at port 1, etc -+ */ -+ unsigned int internal_phys_offset; - }; - - struct mv88e6xxx_atu_entry { ---- a/drivers/net/dsa/mv88e6xxx/global2.c -+++ b/drivers/net/dsa/mv88e6xxx/global2.c -@@ -1185,8 +1185,11 @@ int mv88e6xxx_g2_irq_mdio_setup(struct m - struct mii_bus *bus) - { - int phy, irq, err, err_phy; -+ int phy_start = chip->info->internal_phys_offset; -+ int phy_end = chip->info->internal_phys_offset + -+ chip->info->num_internal_phys; - -- for (phy = 0; phy < chip->info->num_internal_phys; phy++) { -+ for (phy = phy_start; phy < phy_end; phy++) { - irq = irq_find_mapping(chip->g2_irq.domain, phy); - if (irq < 0) { - err = irq; diff --git a/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch b/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch deleted file mode 100644 index 12ea3ebda0..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch +++ /dev/null @@ -1,52 +0,0 @@ -From eb8c75f82a6711387f3b9e03e28923f3e75a761b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:44 +0200 -Subject: [PATCH 4/6] net: dsa: mv88e6xxx: fix 88E6393X family internal phys - layout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -88E6393X/88E6193X/88E6191X switches have in fact 8 internal PHYs, but those -are not present starting at port 0: supported ports go from 1 to 8 - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5944,7 +5944,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6191X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, -@@ -5967,7 +5968,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6193X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, -@@ -6286,7 +6288,8 @@ static const struct mv88e6xxx_info mv88e - .name = "Marvell 88E6393X", - .num_databases = 4096, - .num_ports = 11, /* 10 + Z80 */ -- .num_internal_phys = 9, -+ .num_internal_phys = 8, -+ .internal_phys_offset = 1, - .max_vid = 8191, - .max_sid = 63, - .port_base_addr = 0x0, diff --git a/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch b/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch deleted file mode 100644 index 72dfcee82c..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch +++ /dev/null @@ -1,110 +0,0 @@ -From cef945452c8468efce75ba0dc8420510a5b84af9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:45 +0200 -Subject: [PATCH 5/6] net: dsa: mv88e6xxx: pass mv88e6xxx_chip structure to - port_max_speed_mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some switches families have minor differences on supported link speed for -ports. Instead of redefining a new port_max_speed_mode for each different -configuration, allow to pass mv88e6xxx_chip structure to allow -differentiating those chips by known chip id - -Signed-off-by: Alexis Lothoré -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 2 +- - drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- - drivers/net/dsa/mv88e6xxx/port.c | 12 ++++++++---- - drivers/net/dsa/mv88e6xxx/port.h | 12 ++++++++---- - 4 files changed, 19 insertions(+), 10 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3328,7 +3328,7 @@ static int mv88e6xxx_setup_port(struct m - caps = pl_config.mac_capabilities; - - if (chip->info->ops->port_max_speed_mode) -- mode = chip->info->ops->port_max_speed_mode(port); -+ mode = chip->info->ops->port_max_speed_mode(chip, port); - else - mode = PHY_INTERFACE_MODE_NA; - ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -508,7 +508,8 @@ struct mv88e6xxx_ops { - int speed, int duplex); - - /* What interface mode should be used for maximum speed? */ -- phy_interface_t (*port_max_speed_mode)(int port); -+ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, -+ int port); - - int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); - ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(stru - duplex); - } - --phy_interface_t mv88e6341_port_max_speed_mode(int port) -+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 5) - return PHY_INTERFACE_MODE_2500BASEX; -@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(stru - duplex); - } - --phy_interface_t mv88e6390_port_max_speed_mode(int port) -+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 9 || port == 10) - return PHY_INTERFACE_MODE_2500BASEX; -@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(str - duplex); - } - --phy_interface_t mv88e6390x_port_max_speed_mode(int port) -+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 9 || port == 10) - return PHY_INTERFACE_MODE_XAUI; -@@ -500,7 +503,8 @@ int mv88e6393x_port_set_speed_duplex(str - return 0; - } - --phy_interface_t mv88e6393x_port_max_speed_mode(int port) -+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port) - { - if (port == 0 || port == 9 || port == 10) - return PHY_INTERFACE_MODE_10GBASER; ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -359,10 +359,14 @@ int mv88e6390x_port_set_speed_duplex(str - int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, - int speed, int duplex); - --phy_interface_t mv88e6341_port_max_speed_mode(int port); --phy_interface_t mv88e6390_port_max_speed_mode(int port); --phy_interface_t mv88e6390x_port_max_speed_mode(int port); --phy_interface_t mv88e6393x_port_max_speed_mode(int port); -+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); -+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, -+ int port); - - int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); - diff --git a/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch b/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch deleted file mode 100644 index dc6d5497f2..0000000000 --- a/target/linux/generic/backport-6.6/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 23680321789863bab2d60af507858ce50ff9f56a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= -Date: Mon, 29 May 2023 10:02:46 +0200 -Subject: [PATCH 6/6] net: dsa: mv88e6xxx: enable support for 88E6361 switch -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Marvell 88E6361 is an 8-port switch derived from the -88E6393X/88E9193X/88E6191X switches family. It can benefit from the -existing mv88e6xxx driver by simply adding the proper switch description in -the driver. Main differences with other switches from this -family are: -- 8 ports exposed (instead of 11): ports 1, 2 and 8 not available -- No 5GBase-x nor SFI/USXGMII support - -Signed-off-by: Alexis Lothoré -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++---- - drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- - drivers/net/dsa/mv88e6xxx/port.c | 14 ++++++++--- - drivers/net/dsa/mv88e6xxx/port.h | 1 + - 4 files changed, 51 insertions(+), 9 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -797,6 +797,8 @@ static void mv88e6393x_phylink_get_caps( - unsigned long *supported = config->supported_interfaces; - bool is_6191x = - chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; -+ bool is_6361 = -+ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; - - mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); - -@@ -811,13 +813,17 @@ static void mv88e6393x_phylink_get_caps( - /* 6191X supports >1G modes only on port 10 */ - if (!is_6191x || port == 10) { - __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); -- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ config->mac_capabilities |= MAC_2500FD; -+ -+ /* 6361 only supports up to 2500BaseX */ -+ if (!is_6361) { -+ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ config->mac_capabilities |= MAC_5000FD | -+ MAC_10000FD; -+ } - /* FIXME: USXGMII is not supported yet */ - /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ -- -- config->mac_capabilities |= MAC_2500FD | MAC_5000FD | -- MAC_10000FD; - } - } - -@@ -6231,6 +6237,32 @@ static const struct mv88e6xxx_info mv88e - .ptp_support = true, - .ops = &mv88e6352_ops, - }, -+ [MV88E6361] = { -+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, -+ .family = MV88E6XXX_FAMILY_6393, -+ .name = "Marvell 88E6361", -+ .num_databases = 4096, -+ .num_macs = 16384, -+ .num_ports = 11, -+ /* Ports 1, 2 and 8 are not routed */ -+ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), -+ .num_internal_phys = 5, -+ .internal_phys_offset = 3, -+ .max_vid = 4095, -+ .max_sid = 63, -+ .port_base_addr = 0x0, -+ .phy_base_addr = 0x0, -+ .global1_addr = 0x1b, -+ .global2_addr = 0x1c, -+ .age_time_coeff = 3750, -+ .g1_irqs = 10, -+ .g2_irqs = 14, -+ .atu_move_port_mask = 0x1f, -+ .pvt = true, -+ .multi_chip = true, -+ .ptp_support = true, -+ .ops = &mv88e6393x_ops, -+ }, - [MV88E6390] = { - .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, - .family = MV88E6XXX_FAMILY_6390, ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -82,6 +82,7 @@ enum mv88e6xxx_model { - MV88E6350, - MV88E6351, - MV88E6352, -+ MV88E6361, - MV88E6390, - MV88E6390X, - MV88E6393X, -@@ -100,7 +101,7 @@ enum mv88e6xxx_family { - MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ - MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ - MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ -- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ -+ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ - }; - - /** ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -424,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(str - u16 reg, ctrl; - int err; - -+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && -+ speed > 2500) -+ return -EOPNOTSUPP; -+ - if (speed == 200 && port != 0) - return -EOPNOTSUPP; - -@@ -506,10 +510,14 @@ int mv88e6393x_port_set_speed_duplex(str - phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, - int port) - { -- if (port == 0 || port == 9 || port == 10) -- return PHY_INTERFACE_MODE_10GBASER; - -- return PHY_INTERFACE_MODE_NA; -+ if (port != 0 && port != 9 && port != 10) -+ return PHY_INTERFACE_MODE_NA; -+ -+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) -+ return PHY_INTERFACE_MODE_2500BASEX; -+ -+ return PHY_INTERFACE_MODE_10GBASER; - } - - static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -133,6 +133,7 @@ - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 -+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 - #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 diff --git a/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch b/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch deleted file mode 100644 index 33759632eb..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0001-nvmem-stm32-move-STM32MP15_BSEC_NUM_LOWER-in-config.patch +++ /dev/null @@ -1,82 +0,0 @@ -From fbfc4ca465a1f8d81bf2d67d95bf7fc67c3cf0c2 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:20 +0000 -Subject: [PATCH] nvmem: stm32: move STM32MP15_BSEC_NUM_LOWER in config - -Support STM32MP15_BSEC_NUM_LOWER in stm32 romem config to prepare -the next SoC in STM32MP family. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-2-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 21 ++++++++++++++++----- - 1 file changed, 16 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -22,16 +22,15 @@ - /* shadow registers offest */ - #define STM32MP15_BSEC_DATA0 0x200 - --/* 32 (x 32-bits) lower shadow registers */ --#define STM32MP15_BSEC_NUM_LOWER 32 -- - struct stm32_romem_cfg { - int size; -+ u8 lower; - }; - - struct stm32_romem_priv { - void __iomem *base; - struct nvmem_config cfg; -+ u8 lower; - }; - - static int stm32_romem_read(void *context, unsigned int offset, void *buf, -@@ -85,7 +84,7 @@ static int stm32_bsec_read(void *context - for (i = roffset; (i < roffset + rbytes); i += 4) { - u32 otp = i >> 2; - -- if (otp < STM32MP15_BSEC_NUM_LOWER) { -+ if (otp < priv->lower) { - /* read lower data from shadow registers */ - val = readl_relaxed( - priv->base + STM32MP15_BSEC_DATA0 + i); -@@ -159,6 +158,8 @@ static int stm32_romem_probe(struct plat - priv->cfg.priv = priv; - priv->cfg.owner = THIS_MODULE; - -+ priv->lower = 0; -+ - cfg = (const struct stm32_romem_cfg *) - of_match_device(dev->driver->of_match_table, dev)->data; - if (!cfg) { -@@ -167,6 +168,7 @@ static int stm32_romem_probe(struct plat - priv->cfg.reg_read = stm32_romem_read; - } else { - priv->cfg.size = cfg->size; -+ priv->lower = cfg->lower; - priv->cfg.reg_read = stm32_bsec_read; - priv->cfg.reg_write = stm32_bsec_write; - } -@@ -174,8 +176,17 @@ static int stm32_romem_probe(struct plat - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); - } - -+/* -+ * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) -+ * => 96 x 32-bits data words -+ * - Lower: 1K bits, 2:1 redundancy, incremental bit programming -+ * => 32 (x 32-bits) lower shadow registers = words 0 to 31 -+ * - Upper: 2K bits, ECC protection, word programming only -+ * => 64 (x 32-bits) = words 32 to 95 -+ */ - static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { -- .size = 384, /* 96 x 32-bits data words */ -+ .size = 384, -+ .lower = 32, - }; - - static const struct of_device_id stm32_romem_of_match[] = { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch b/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch deleted file mode 100644 index 5791df2606..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0002-nvmem-stm32-add-warning-when-upper-OTPs-are-updated.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d61784e6410f3df2028e6eb91b06ffed37a660e0 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:21 +0000 -Subject: [PATCH] nvmem: stm32: add warning when upper OTPs are updated - -As the upper OTPs are ECC protected, they support only one 32 bits word -programming. -For a second modification of this word, these ECC become invalid and -this OTP will be no more accessible, the shadowed value is invalid. - -This patch adds a warning to indicate an upper OTP update, because this -operation is dangerous as OTP is not locked by the driver after the first -update to avoid a second update. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -132,6 +132,9 @@ static int stm32_bsec_write(void *contex - } - } - -+ if (offset + bytes >= priv->lower * 4) -+ dev_warn(dev, "Update of upper OTPs with ECC protection (word programming, only once)\n"); -+ - return 0; - } - diff --git a/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch b/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch deleted file mode 100644 index b83ad69c6b..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0003-nvmem-stm32-add-nvmem-type-attribute.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a3816a7d7c097c1da46aad5f5d1e229b607dce04 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Fri, 18 Nov 2022 06:39:22 +0000 -Subject: [PATCH] nvmem: stm32: add nvmem type attribute - -Inform NVMEM framework of type attribute for stm32-romem as NVMEM_TYPE_OTP -so userspace is able to know how the data is stored in BSEC. - -Signed-off-by: Patrick Delaunay -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -160,6 +160,7 @@ static int stm32_romem_probe(struct plat - priv->cfg.dev = dev; - priv->cfg.priv = priv; - priv->cfg.owner = THIS_MODULE; -+ priv->cfg.type = NVMEM_TYPE_OTP; - - priv->lower = 0; - diff --git a/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch b/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch deleted file mode 100644 index 52ba1e65b5..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0004-nvmem-stm32-fix-spelling-typo-in-comment.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 06aac0e11960a7ddccc1888326b5906d017e0f24 Mon Sep 17 00:00:00 2001 -From: Jiangshan Yi -Date: Fri, 18 Nov 2022 06:39:24 +0000 -Subject: [PATCH] nvmem: stm32: fix spelling typo in comment - -Fix spelling typo in comment. - -Reported-by: k2ci -Signed-off-by: Jiangshan Yi -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-6-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -19,7 +19,7 @@ - #define STM32_SMC_WRITE_SHADOW 0x03 - #define STM32_SMC_READ_OTP 0x04 - --/* shadow registers offest */ -+/* shadow registers offset */ - #define STM32MP15_BSEC_DATA0 0x200 - - struct stm32_romem_cfg { diff --git a/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch b/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch deleted file mode 100644 index 8f024f4c1a..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0005-nvmem-Kconfig-Fix-spelling-mistake-controlls-control.patch +++ /dev/null @@ -1,27 +0,0 @@ -From fb817c4ef63e8cfb6e77ae4a2875ae854c80708f Mon Sep 17 00:00:00 2001 -From: Colin Ian King -Date: Fri, 18 Nov 2022 06:39:26 +0000 -Subject: [PATCH] nvmem: Kconfig: Fix spelling mistake "controlls" -> - "controls" - -There is a spelling mistake in a Kconfig description. Fix it. - -Signed-off-by: Colin Ian King -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -164,7 +164,7 @@ config NVMEM_MICROCHIP_OTPC - depends on ARCH_AT91 || COMPILE_TEST - help - This driver enable the OTP controller available on Microchip SAMA7G5 -- SoCs. It controlls the access to the OTP memory connected to it. -+ SoCs. It controls the access to the OTP memory connected to it. - - config NVMEM_MTK_EFUSE - tristate "Mediatek SoCs EFUSE support" diff --git a/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch b/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch deleted file mode 100644 index 861386ad31..0000000000 --- a/target/linux/generic/backport-6.6/808-v6.2-0006-nvmem-u-boot-env-add-Broadcom-format-support.patch +++ /dev/null @@ -1,67 +0,0 @@ -From ada84d07af6097b2addd18262668ce6cb9e15206 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 18 Nov 2022 06:39:27 +0000 -Subject: [PATCH] nvmem: u-boot-env: add Broadcom format support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Broadcom uses U-Boot for a lot of their bcmbca familiy chipsets. They -decided to store U-Boot environment data inside U-Boot partition and to -use a custom header (with "uEnv" magic and env data length). - -Add support for Broadcom's specific binding and their custom format. - -Ref: 6b0584c19d87 ("dt-bindings: nvmem: u-boot,env: add Broadcom's variant binding") -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20221118063932.6418-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/u-boot-env.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -16,6 +16,7 @@ - enum u_boot_env_format { - U_BOOT_FORMAT_SINGLE, - U_BOOT_FORMAT_REDUNDANT, -+ U_BOOT_FORMAT_BROADCOM, - }; - - struct u_boot_env { -@@ -40,6 +41,13 @@ struct u_boot_env_image_redundant { - uint8_t data[]; - } __packed; - -+struct u_boot_env_image_broadcom { -+ __le32 magic; -+ __le32 len; -+ __le32 crc32; -+ uint8_t data[0]; -+} __packed; -+ - static int u_boot_env_read(void *context, unsigned int offset, void *val, - size_t bytes) - { -@@ -138,6 +146,11 @@ static int u_boot_env_parse(struct u_boo - crc32_data_offset = offsetof(struct u_boot_env_image_redundant, data); - data_offset = offsetof(struct u_boot_env_image_redundant, data); - break; -+ case U_BOOT_FORMAT_BROADCOM: -+ crc32_offset = offsetof(struct u_boot_env_image_broadcom, crc32); -+ crc32_data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ data_offset = offsetof(struct u_boot_env_image_broadcom, data); -+ break; - } - crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); - crc32_data_len = priv->mtd->size - crc32_data_offset; -@@ -202,6 +215,7 @@ static const struct of_device_id u_boot_ - { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, - { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, - { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, -+ { .compatible = "brcm,env", .data = (void *)U_BOOT_FORMAT_BROADCOM, }, - {}, - }; - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch b/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch deleted file mode 100644 index 01400fd490..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0001-nvmem-core-remove-spurious-white-space.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2e8dc541ae207349b51c65391be625ffe1f86e0c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Mon, 6 Feb 2023 13:43:41 +0000 -Subject: [PATCH] nvmem: core: remove spurious white space - -Remove a spurious white space in for the ida_alloc() call. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -764,7 +764,7 @@ struct nvmem_device *nvmem_register(cons - if (!nvmem) - return ERR_PTR(-ENOMEM); - -- rval = ida_alloc(&nvmem_ida, GFP_KERNEL); -+ rval = ida_alloc(&nvmem_ida, GFP_KERNEL); - if (rval < 0) { - kfree(nvmem); - return ERR_PTR(rval); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch deleted file mode 100644 index 454d3bf0ed..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0002-nvmem-core-add-an-index-parameter-to-the-cell.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:46 +0000 -Subject: [PATCH] nvmem: core: add an index parameter to the cell - -Sometimes a cell can represend multiple values. For example, a base -ethernet address stored in the NVMEM can be expanded into multiple -discreet ones by adding an offset. - -For this use case, introduce an index parameter which is then used to -distiguish between values. This parameter will then be passed to the -post process hook which can then use it to create different values -during reading. - -At the moment, there is only support for the device tree path. You can -add the index to the phandle, e.g. - - &net { - nvmem-cells = <&base_mac_address 2>; - nvmem-cell-names = "mac-address"; - }; - - &nvmem_provider { - base_mac_address: base-mac-address@0 { - #nvmem-cell-cells = <1>; - reg = <0 6>; - }; - }; - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 37 ++++++++++++++++++++++++---------- - drivers/nvmem/imx-ocotp.c | 4 ++-- - include/linux/nvmem-provider.h | 4 ++-- - 3 files changed, 30 insertions(+), 15 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -60,6 +60,7 @@ struct nvmem_cell_entry { - struct nvmem_cell { - struct nvmem_cell_entry *entry; - const char *id; -+ int index; - }; - - static DEFINE_MUTEX(nvmem_mutex); -@@ -1122,7 +1123,8 @@ struct nvmem_device *devm_nvmem_device_g - } - EXPORT_SYMBOL_GPL(devm_nvmem_device_get); - --static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id) -+static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, -+ const char *id, int index) - { - struct nvmem_cell *cell; - const char *name = NULL; -@@ -1141,6 +1143,7 @@ static struct nvmem_cell *nvmem_create_c - - cell->id = name; - cell->entry = entry; -+ cell->index = index; - - return cell; - } -@@ -1179,7 +1182,7 @@ nvmem_cell_get_from_lookup(struct device - __nvmem_device_put(nvmem); - cell = ERR_PTR(-ENOENT); - } else { -- cell = nvmem_create_cell(cell_entry, con_id); -+ cell = nvmem_create_cell(cell_entry, con_id, 0); - if (IS_ERR(cell)) - __nvmem_device_put(nvmem); - } -@@ -1227,15 +1230,27 @@ struct nvmem_cell *of_nvmem_cell_get(str - struct nvmem_device *nvmem; - struct nvmem_cell_entry *cell_entry; - struct nvmem_cell *cell; -+ struct of_phandle_args cell_spec; - int index = 0; -+ int cell_index = 0; -+ int ret; - - /* if cell name exists, find index to the name */ - if (id) - index = of_property_match_string(np, "nvmem-cell-names", id); - -- cell_np = of_parse_phandle(np, "nvmem-cells", index); -- if (!cell_np) -- return ERR_PTR(-ENOENT); -+ ret = of_parse_phandle_with_optional_args(np, "nvmem-cells", -+ "#nvmem-cell-cells", -+ index, &cell_spec); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ if (cell_spec.args_count > 1) -+ return ERR_PTR(-EINVAL); -+ -+ cell_np = cell_spec.np; -+ if (cell_spec.args_count) -+ cell_index = cell_spec.args[0]; - - nvmem_np = of_get_parent(cell_np); - if (!nvmem_np) { -@@ -1257,7 +1272,7 @@ struct nvmem_cell *of_nvmem_cell_get(str - return ERR_PTR(-ENOENT); - } - -- cell = nvmem_create_cell(cell_entry, id); -+ cell = nvmem_create_cell(cell_entry, id, cell_index); - if (IS_ERR(cell)) - __nvmem_device_put(nvmem); - -@@ -1410,8 +1425,8 @@ static void nvmem_shift_read_buffer_in_p - } - - static int __nvmem_cell_read(struct nvmem_device *nvmem, -- struct nvmem_cell_entry *cell, -- void *buf, size_t *len, const char *id) -+ struct nvmem_cell_entry *cell, -+ void *buf, size_t *len, const char *id, int index) - { - int rc; - -@@ -1425,7 +1440,7 @@ static int __nvmem_cell_read(struct nvme - nvmem_shift_read_buffer_in_place(cell, buf); - - if (nvmem->cell_post_process) { -- rc = nvmem->cell_post_process(nvmem->priv, id, -+ rc = nvmem->cell_post_process(nvmem->priv, id, index, - cell->offset, buf, cell->bytes); - if (rc) - return rc; -@@ -1460,7 +1475,7 @@ void *nvmem_cell_read(struct nvmem_cell - if (!buf) - return ERR_PTR(-ENOMEM); - -- rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id); -+ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index); - if (rc) { - kfree(buf); - return ERR_PTR(rc); -@@ -1773,7 +1788,7 @@ ssize_t nvmem_device_cell_read(struct nv - if (rc) - return rc; - -- rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL); -+ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0); - if (rc) - return rc; - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -222,8 +222,8 @@ read_end: - return ret; - } - --static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset, -- void *data, size_t bytes) -+static int imx_ocotp_cell_pp(void *context, const char *id, int index, -+ unsigned int offset, void *data, size_t bytes) - { - struct ocotp_priv *priv = context; - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr - typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, - void *val, size_t bytes); - /* used for vendor specific post processing of cell data */ --typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset, -- void *buf, size_t bytes); -+typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes); - - enum nvmem_type { - NVMEM_TYPE_UNKNOWN = 0, diff --git a/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch b/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch deleted file mode 100644 index f3829b3e17..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0003-nvmem-core-move-struct-nvmem_cell_info-to-nvmem-prov.patch +++ /dev/null @@ -1,78 +0,0 @@ -From fbd03d27776c6121a483921601418e3c8f0ff37e Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:47 +0000 -Subject: [PATCH] nvmem: core: move struct nvmem_cell_info to nvmem-provider.h - -struct nvmem_cell_info is used to describe a cell. Thus this should -really be in the nvmem-provider's header. There are two (unused) nvmem -access methods which use the nvmem_cell_info to describe the cell to be -accesses. One can argue, that they will create a cell before accessing, -thus they are both a provider and a consumer. - -struct nvmem_cell_info will get used more and more by nvmem-providers, -don't force them to also include the consumer header, although they are -not. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-14-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/nvmem-consumer.h | 10 +--------- - include/linux/nvmem-provider.h | 19 ++++++++++++++++++- - 2 files changed, 19 insertions(+), 10 deletions(-) - ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -18,15 +18,7 @@ struct device_node; - /* consumer cookie */ - struct nvmem_cell; - struct nvmem_device; -- --struct nvmem_cell_info { -- const char *name; -- unsigned int offset; -- unsigned int bytes; -- unsigned int bit_offset; -- unsigned int nbits; -- struct device_node *np; --}; -+struct nvmem_cell_info; - - /** - * struct nvmem_cell_lookup - cell lookup entry ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -14,7 +14,6 @@ - #include - - struct nvmem_device; --struct nvmem_cell_info; - typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, - void *val, size_t bytes); - typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, -@@ -48,6 +47,24 @@ struct nvmem_keepout { - }; - - /** -+ * struct nvmem_cell_info - NVMEM cell description -+ * @name: Name. -+ * @offset: Offset within the NVMEM device. -+ * @bytes: Length of the cell. -+ * @bit_offset: Bit offset if cell is smaller than a byte. -+ * @nbits: Number of bits. -+ * @np: Optional device_node pointer. -+ */ -+struct nvmem_cell_info { -+ const char *name; -+ unsigned int offset; -+ unsigned int bytes; -+ unsigned int bit_offset; -+ unsigned int nbits; -+ struct device_node *np; -+}; -+ -+/** - * struct nvmem_config - NVMEM device configuration - * - * @dev: Parent device. diff --git a/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch b/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch deleted file mode 100644 index 8f996eab34..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0004-nvmem-core-drop-the-removal-of-the-cells-in-nvmem_ad.patch +++ /dev/null @@ -1,65 +0,0 @@ -From cc5bdd323dde6494623f3ffe3a5b887fa21cd375 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:48 +0000 -Subject: [PATCH] nvmem: core: drop the removal of the cells in - nvmem_add_cells() - -If nvmem_add_cells() fails, the whole nvmem_register() will fail -and the cells will then be removed anyway. This is a preparation -to introduce a nvmem_add_one_cell() which can then be used by -nvmem_add_cells(). - -This is then the same to what nvmem_add_cells_from_table() and -nvmem_add_cells_from_of() do. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-15-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 14 ++++---------- - 1 file changed, 4 insertions(+), 10 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -515,7 +515,7 @@ static int nvmem_add_cells(struct nvmem_ - int ncells) - { - struct nvmem_cell_entry **cells; -- int i, rval; -+ int i, rval = 0; - - cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); - if (!cells) -@@ -525,28 +525,22 @@ static int nvmem_add_cells(struct nvmem_ - cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); - if (!cells[i]) { - rval = -ENOMEM; -- goto err; -+ goto out; - } - - rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); - if (rval) { - kfree(cells[i]); -- goto err; -+ goto out; - } - - nvmem_cell_entry_add(cells[i]); - } - -+out: - /* remove tmp array */ - kfree(cells); - -- return 0; --err: -- while (i--) -- nvmem_cell_entry_drop(cells[i]); -- -- kfree(cells); -- - return rval; - } - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch b/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch deleted file mode 100644 index 711ce229b2..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0005-nvmem-core-add-nvmem_add_one_cell.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 2ded6830d376d5e7bf43d59f7f7fdf1a59abc676 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:49 +0000 -Subject: [PATCH] nvmem: core: add nvmem_add_one_cell() - -Add a new function to add exactly one cell. This will be used by the -nvmem layout drivers to add custom cells. In contrast to the -nvmem_add_cells(), this has the advantage that we don't have to assemble -a list of cells on runtime. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-16-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 59 ++++++++++++++++++++-------------- - include/linux/nvmem-provider.h | 8 +++++ - 2 files changed, 43 insertions(+), 24 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -502,6 +502,36 @@ static int nvmem_cell_info_to_nvmem_cell - } - - /** -+ * nvmem_add_one_cell() - Add one cell information to an nvmem device -+ * -+ * @nvmem: nvmem device to add cells to. -+ * @info: nvmem cell info to add to the device -+ * -+ * Return: 0 or negative error code on failure. -+ */ -+int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info) -+{ -+ struct nvmem_cell_entry *cell; -+ int rval; -+ -+ cell = kzalloc(sizeof(*cell), GFP_KERNEL); -+ if (!cell) -+ return -ENOMEM; -+ -+ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell); -+ if (rval) { -+ kfree(cell); -+ return rval; -+ } -+ -+ nvmem_cell_entry_add(cell); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(nvmem_add_one_cell); -+ -+/** - * nvmem_add_cells() - Add cell information to an nvmem device - * - * @nvmem: nvmem device to add cells to. -@@ -514,34 +544,15 @@ static int nvmem_add_cells(struct nvmem_ - const struct nvmem_cell_info *info, - int ncells) - { -- struct nvmem_cell_entry **cells; -- int i, rval = 0; -- -- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL); -- if (!cells) -- return -ENOMEM; -+ int i, rval; - - for (i = 0; i < ncells; i++) { -- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL); -- if (!cells[i]) { -- rval = -ENOMEM; -- goto out; -- } -- -- rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]); -- if (rval) { -- kfree(cells[i]); -- goto out; -- } -- -- nvmem_cell_entry_add(cells[i]); -+ rval = nvmem_add_one_cell(nvmem, &info[i]); -+ if (rval) -+ return rval; - } - --out: -- /* remove tmp array */ -- kfree(cells); -- -- return rval; -+ return 0; - } - - /** ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -153,6 +153,9 @@ struct nvmem_device *devm_nvmem_register - void nvmem_add_cell_table(struct nvmem_cell_table *table); - void nvmem_del_cell_table(struct nvmem_cell_table *table); - -+int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info); -+ - #else - - static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) -@@ -170,6 +173,11 @@ devm_nvmem_register(struct device *dev, - - static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {} - static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {} -+static inline int nvmem_add_one_cell(struct nvmem_device *nvmem, -+ const struct nvmem_cell_info *info) -+{ -+ return -EOPNOTSUPP; -+} - - #endif /* CONFIG_NVMEM */ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch b/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch deleted file mode 100644 index e1791e5c83..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0006-nvmem-core-use-nvmem_add_one_cell-in-nvmem_add_cells.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 50014d659617dc58780a5d31ceb76c82779a9d8b Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:50 +0000 -Subject: [PATCH] nvmem: core: use nvmem_add_one_cell() in - nvmem_add_cells_from_of() - -Convert nvmem_add_cells_from_of() to use the new nvmem_add_one_cell(). -This will remove duplicate code and it will make it possible to add a -hook to a nvmem layout in between, which can change fields before the -cell is finally added. - -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-17-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 45 ++++++++++++++------------------------------ - 1 file changed, 14 insertions(+), 31 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -688,15 +688,14 @@ static int nvmem_validate_keepouts(struc - - static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) - { -- struct device_node *parent, *child; - struct device *dev = &nvmem->dev; -- struct nvmem_cell_entry *cell; -+ struct device_node *child; - const __be32 *addr; -- int len; -+ int len, ret; - -- parent = dev->of_node; -+ for_each_child_of_node(dev->of_node, child) { -+ struct nvmem_cell_info info = {0}; - -- for_each_child_of_node(parent, child) { - addr = of_get_property(child, "reg", &len); - if (!addr) - continue; -@@ -706,40 +705,24 @@ static int nvmem_add_cells_from_of(struc - return -EINVAL; - } - -- cell = kzalloc(sizeof(*cell), GFP_KERNEL); -- if (!cell) { -- of_node_put(child); -- return -ENOMEM; -- } -- -- cell->nvmem = nvmem; -- cell->offset = be32_to_cpup(addr++); -- cell->bytes = be32_to_cpup(addr); -- cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); -+ info.offset = be32_to_cpup(addr++); -+ info.bytes = be32_to_cpup(addr); -+ info.name = kasprintf(GFP_KERNEL, "%pOFn", child); - - addr = of_get_property(child, "bits", &len); - if (addr && len == (2 * sizeof(u32))) { -- cell->bit_offset = be32_to_cpup(addr++); -- cell->nbits = be32_to_cpup(addr); -+ info.bit_offset = be32_to_cpup(addr++); -+ info.nbits = be32_to_cpup(addr); - } - -- if (cell->nbits) -- cell->bytes = DIV_ROUND_UP( -- cell->nbits + cell->bit_offset, -- BITS_PER_BYTE); -- -- if (!IS_ALIGNED(cell->offset, nvmem->stride)) { -- dev_err(dev, "cell %s unaligned to nvmem stride %d\n", -- cell->name, nvmem->stride); -- /* Cells already added will be freed later. */ -- kfree_const(cell->name); -- kfree(cell); -+ info.np = of_node_get(child); -+ -+ ret = nvmem_add_one_cell(nvmem, &info); -+ kfree(info.name); -+ if (ret) { - of_node_put(child); -- return -EINVAL; -+ return ret; - } -- -- cell->np = of_node_get(child); -- nvmem_cell_entry_add(cell); - } - - return 0; diff --git a/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch b/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch deleted file mode 100644 index 172a78b76a..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0007-nvmem-stm32-add-OP-TEE-support-for-STM32MP13x.patch +++ /dev/null @@ -1,562 +0,0 @@ -From 6a0bc3522e746025e2d9a63ab2cb5d7062c2d39c Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Mon, 6 Feb 2023 13:43:51 +0000 -Subject: [PATCH] nvmem: stm32: add OP-TEE support for STM32MP13x - -For boot with OP-TEE on STM32MP13, the communication with the secure -world no more use STMicroelectronics SMC but communication with the -STM32MP BSEC TA, for data access (read/write) or lock operation: -- all the request are sent to OP-TEE trusted application, -- for upper OTP with ECC protection and with word programming only - each OTP are permanently locked when programmed to avoid ECC error - on the second write operation - -Signed-off-by: Patrick Delaunay -Reviewed-by: Etienne Carriere -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-18-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 11 + - drivers/nvmem/Makefile | 1 + - drivers/nvmem/stm32-bsec-optee-ta.c | 298 ++++++++++++++++++++++++++++ - drivers/nvmem/stm32-bsec-optee-ta.h | 80 ++++++++ - drivers/nvmem/stm32-romem.c | 54 ++++- - 5 files changed, 441 insertions(+), 3 deletions(-) - create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.c - create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.h - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -290,9 +290,20 @@ config NVMEM_SPRD_EFUSE - This driver can also be built as a module. If so, the module - will be called nvmem-sprd-efuse. - -+config NVMEM_STM32_BSEC_OPTEE_TA -+ bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" -+ depends on OPTEE -+ help -+ Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE -+ trusted application STM32MP BSEC. -+ -+ This library is a used by stm32-romem driver or included in the module -+ called nvmem-stm32-romem. -+ - config NVMEM_STM32_ROMEM - tristate "STMicroelectronics STM32 factory-programmed memory support" - depends on ARCH_STM32 || COMPILE_TEST -+ imply NVMEM_STM32_BSEC_OPTEE_TA - help - Say y here to enable read-only access for STMicroelectronics STM32 - factory-programmed memory area. ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -61,6 +61,7 @@ obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem - nvmem_sprd_efuse-y := sprd-efuse.o - obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o - nvmem_stm32_romem-y := stm32-romem.o -+nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o - obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o - nvmem_sunplus_ocotp-y := sunplus-ocotp.o - obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o ---- /dev/null -+++ b/drivers/nvmem/stm32-bsec-optee-ta.c -@@ -0,0 +1,298 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver -+ * -+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved -+ */ -+ -+#include -+ -+#include "stm32-bsec-optee-ta.h" -+ -+/* -+ * Read OTP memory -+ * -+ * [in] value[0].a OTP start offset in byte -+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) -+ * [out] memref[1].buffer Output buffer to store read values -+ * [out] memref[1].size Size of OTP to be read -+ * -+ * Return codes: -+ * TEE_SUCCESS - Invoke command success -+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param -+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller -+ */ -+#define PTA_BSEC_READ_MEM 0x0 -+ -+/* -+ * Write OTP memory -+ * -+ * [in] value[0].a OTP start offset in byte -+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) -+ * [in] memref[1].buffer Input buffer to read values -+ * [in] memref[1].size Size of OTP to be written -+ * -+ * Return codes: -+ * TEE_SUCCESS - Invoke command success -+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param -+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller -+ */ -+#define PTA_BSEC_WRITE_MEM 0x1 -+ -+/* value of PTA_BSEC access type = value[in] b */ -+#define SHADOW_ACCESS 0 -+#define FUSE_ACCESS 1 -+#define LOCK_ACCESS 2 -+ -+/* Bitfield definition for LOCK status */ -+#define LOCK_PERM BIT(30) -+ -+/* OP-TEE STM32MP BSEC TA UUID */ -+static const uuid_t stm32mp_bsec_ta_uuid = -+ UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5, -+ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03); -+ -+/* -+ * Check whether this driver supports the BSEC TA in the TEE instance -+ * represented by the params (ver/data) to this function. -+ */ -+static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver, -+ const void *data) -+{ -+ /* Currently this driver only supports GP compliant, OP-TEE based TA */ -+ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) && -+ (ver->gen_caps & TEE_GEN_CAP_GP)) -+ return 1; -+ else -+ return 0; -+} -+ -+/* Open a session to OP-TEE for STM32MP BSEC TA */ -+static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id) -+{ -+ struct tee_ioctl_open_session_arg sess_arg; -+ int rc; -+ -+ memset(&sess_arg, 0, sizeof(sess_arg)); -+ export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid); -+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; -+ sess_arg.num_params = 0; -+ -+ rc = tee_client_open_session(ctx, &sess_arg, NULL); -+ if ((rc < 0) || (sess_arg.ret != 0)) { -+ pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n", -+ __func__, sess_arg.ret, rc); -+ if (!rc) -+ rc = -EINVAL; -+ } else { -+ *id = sess_arg.session; -+ } -+ -+ return rc; -+} -+ -+/* close a session to OP-TEE for STM32MP BSEC TA */ -+static void stm32_bsec_ta_close_session(void *ctx, u32 id) -+{ -+ tee_client_close_session(ctx, id); -+} -+ -+/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */ -+int stm32_bsec_optee_ta_open(struct tee_context **ctx) -+{ -+ struct tee_context *tee_ctx; -+ u32 session_id; -+ int rc; -+ -+ /* Open context with TEE driver */ -+ tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL); -+ if (IS_ERR(tee_ctx)) { -+ rc = PTR_ERR(tee_ctx); -+ if (rc == -ENOENT) -+ return -EPROBE_DEFER; -+ pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc); -+ -+ return rc; -+ } -+ -+ /* Check STM32MP BSEC TA presence */ -+ rc = stm32_bsec_ta_open_session(tee_ctx, &session_id); -+ if (rc) { -+ tee_client_close_context(tee_ctx); -+ return rc; -+ } -+ -+ stm32_bsec_ta_close_session(tee_ctx, session_id); -+ -+ *ctx = tee_ctx; -+ -+ return 0; -+} -+ -+/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */ -+void stm32_bsec_optee_ta_close(void *ctx) -+{ -+ tee_client_close_context(ctx); -+} -+ -+/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */ -+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, -+ void *buf, size_t bytes) -+{ -+ struct tee_shm *shm; -+ struct tee_ioctl_invoke_arg arg; -+ struct tee_param param[2]; -+ u8 *shm_buf; -+ u32 start, num_bytes; -+ int ret; -+ u32 session_id; -+ -+ ret = stm32_bsec_ta_open_session(ctx, &session_id); -+ if (ret) -+ return ret; -+ -+ memset(&arg, 0, sizeof(arg)); -+ memset(¶m, 0, sizeof(param)); -+ -+ arg.func = PTA_BSEC_READ_MEM; -+ arg.session = session_id; -+ arg.num_params = 2; -+ -+ /* align access on 32bits */ -+ start = ALIGN_DOWN(offset, 4); -+ num_bytes = round_up(offset + bytes - start, 4); -+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; -+ param[0].u.value.a = start; -+ param[0].u.value.b = SHADOW_ACCESS; -+ -+ shm = tee_shm_alloc_kernel_buf(ctx, num_bytes); -+ if (IS_ERR(shm)) { -+ ret = PTR_ERR(shm); -+ goto out_tee_session; -+ } -+ -+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; -+ param[1].u.memref.shm = shm; -+ param[1].u.memref.size = num_bytes; -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", -+ arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ if (!ret) { -+ shm_buf = tee_shm_get_va(shm, 0); -+ if (IS_ERR(shm_buf)) { -+ ret = PTR_ERR(shm_buf); -+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); -+ } else { -+ /* read data from 32 bits aligned buffer */ -+ memcpy(buf, &shm_buf[offset % 4], bytes); -+ } -+ } -+ -+ tee_shm_free(shm); -+ -+out_tee_session: -+ stm32_bsec_ta_close_session(ctx, session_id); -+ -+ return ret; -+} -+ -+/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */ -+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, -+ unsigned int offset, void *buf, size_t bytes) -+{ struct tee_shm *shm; -+ struct tee_ioctl_invoke_arg arg; -+ struct tee_param param[2]; -+ u8 *shm_buf; -+ int ret; -+ u32 session_id; -+ -+ ret = stm32_bsec_ta_open_session(ctx, &session_id); -+ if (ret) -+ return ret; -+ -+ /* Allow only writing complete 32-bits aligned words */ -+ if ((bytes % 4) || (offset % 4)) -+ return -EINVAL; -+ -+ memset(&arg, 0, sizeof(arg)); -+ memset(¶m, 0, sizeof(param)); -+ -+ arg.func = PTA_BSEC_WRITE_MEM; -+ arg.session = session_id; -+ arg.num_params = 2; -+ -+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; -+ param[0].u.value.a = offset; -+ param[0].u.value.b = FUSE_ACCESS; -+ -+ shm = tee_shm_alloc_kernel_buf(ctx, bytes); -+ if (IS_ERR(shm)) { -+ ret = PTR_ERR(shm); -+ goto out_tee_session; -+ } -+ -+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; -+ param[1].u.memref.shm = shm; -+ param[1].u.memref.size = bytes; -+ -+ shm_buf = tee_shm_get_va(shm, 0); -+ if (IS_ERR(shm_buf)) { -+ ret = PTR_ERR(shm_buf); -+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); -+ tee_shm_free(shm); -+ -+ goto out_tee_session; -+ } -+ -+ memcpy(shm_buf, buf, bytes); -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret); -+ -+ /* Lock the upper OTPs with ECC protection, word programming only */ -+ if (!ret && ((offset + bytes) >= (lower * 4))) { -+ u32 start, nb_lock; -+ u32 *lock = (u32 *)shm_buf; -+ int i; -+ -+ /* -+ * don't lock the lower OTPs, no ECC protection and incremental -+ * bit programming, a second write is allowed -+ */ -+ start = max_t(u32, offset, lower * 4); -+ nb_lock = (offset + bytes - start) / 4; -+ -+ param[0].u.value.a = start; -+ param[0].u.value.b = LOCK_ACCESS; -+ param[1].u.memref.size = nb_lock * 4; -+ -+ for (i = 0; i < nb_lock; i++) -+ lock[i] = LOCK_PERM; -+ -+ ret = tee_client_invoke_func(ctx, &arg, param); -+ if (ret < 0 || arg.ret != 0) { -+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); -+ if (!ret) -+ ret = -EIO; -+ } -+ pr_debug("Lock upper OTPs %d to %d, ret=%d\n", -+ start / 4, start / 4 + nb_lock, ret); -+ } -+ -+ tee_shm_free(shm); -+ -+out_tee_session: -+ stm32_bsec_ta_close_session(ctx, session_id); -+ -+ return ret; -+} ---- /dev/null -+++ b/drivers/nvmem/stm32-bsec-optee-ta.h -@@ -0,0 +1,80 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver -+ * -+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved -+ */ -+ -+#if IS_ENABLED(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) -+/** -+ * stm32_bsec_optee_ta_open() - initialize the STM32 BSEC TA -+ * @ctx: the OP-TEE context on success -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_open(struct tee_context **ctx); -+ -+/** -+ * stm32_bsec_optee_ta_close() - release the STM32 BSEC TA -+ * @ctx: the OP-TEE context -+ * -+ * This function used to clean the OP-TEE resources initialized in -+ * stm32_bsec_optee_ta_open(); it can be used as callback to -+ * devm_add_action_or_reset() -+ */ -+void stm32_bsec_optee_ta_close(void *ctx); -+ -+/** -+ * stm32_bsec_optee_ta_read() - nvmem read access using TA client driver -+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open -+ * @offset: nvmem offset -+ * @buf: buffer to fill with nvem values -+ * @bytes: number of bytes to read -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, -+ void *buf, size_t bytes); -+ -+/** -+ * stm32_bsec_optee_ta_write() - nvmem write access using TA client driver -+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open -+ * @lower: number of lower OTP, not protected by ECC -+ * @offset: nvmem offset -+ * @buf: buffer with nvem values -+ * @bytes: number of bytes to write -+ * -+ * Return: -+ * On success, 0. On failure, -errno. -+ */ -+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, -+ unsigned int offset, void *buf, size_t bytes); -+ -+#else -+ -+static inline int stm32_bsec_optee_ta_open(struct tee_context **ctx) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline void stm32_bsec_optee_ta_close(void *ctx) -+{ -+} -+ -+static inline int stm32_bsec_optee_ta_read(struct tee_context *ctx, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int stm32_bsec_optee_ta_write(struct tee_context *ctx, -+ unsigned int lower, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ return -EOPNOTSUPP; -+} -+#endif /* CONFIG_NVMEM_STM32_BSEC_OPTEE_TA */ ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -11,6 +11,9 @@ - #include - #include - #include -+#include -+ -+#include "stm32-bsec-optee-ta.h" - - /* BSEC secure service access from non-secure */ - #define STM32_SMC_BSEC 0x82001003 -@@ -25,12 +28,14 @@ - struct stm32_romem_cfg { - int size; - u8 lower; -+ bool ta; - }; - - struct stm32_romem_priv { - void __iomem *base; - struct nvmem_config cfg; - u8 lower; -+ struct tee_context *ctx; - }; - - static int stm32_romem_read(void *context, unsigned int offset, void *buf, -@@ -138,12 +143,29 @@ static int stm32_bsec_write(void *contex - return 0; - } - -+static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ struct stm32_romem_priv *priv = context; -+ -+ return stm32_bsec_optee_ta_read(priv->ctx, offset, buf, bytes); -+} -+ -+static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ struct stm32_romem_priv *priv = context; -+ -+ return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); -+} -+ - static int stm32_romem_probe(struct platform_device *pdev) - { - const struct stm32_romem_cfg *cfg; - struct device *dev = &pdev->dev; - struct stm32_romem_priv *priv; - struct resource *res; -+ int rc; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -173,15 +195,31 @@ static int stm32_romem_probe(struct plat - } else { - priv->cfg.size = cfg->size; - priv->lower = cfg->lower; -- priv->cfg.reg_read = stm32_bsec_read; -- priv->cfg.reg_write = stm32_bsec_write; -+ if (cfg->ta) { -+ rc = stm32_bsec_optee_ta_open(&priv->ctx); -+ /* wait for OP-TEE client driver to be up and ready */ -+ if (rc) -+ return rc; -+ } -+ if (priv->ctx) { -+ rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); -+ if (rc) { -+ dev_err(dev, "devm_add_action_or_reset() failed (%d)\n", rc); -+ return rc; -+ } -+ priv->cfg.reg_read = stm32_bsec_pta_read; -+ priv->cfg.reg_write = stm32_bsec_pta_write; -+ } else { -+ priv->cfg.reg_read = stm32_bsec_read; -+ priv->cfg.reg_write = stm32_bsec_write; -+ } - } - - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg)); - } - - /* -- * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) -+ * STM32MP15/13 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits) - * => 96 x 32-bits data words - * - Lower: 1K bits, 2:1 redundancy, incremental bit programming - * => 32 (x 32-bits) lower shadow registers = words 0 to 31 -@@ -191,6 +229,13 @@ static int stm32_romem_probe(struct plat - static const struct stm32_romem_cfg stm32mp15_bsec_cfg = { - .size = 384, - .lower = 32, -+ .ta = false, -+}; -+ -+static const struct stm32_romem_cfg stm32mp13_bsec_cfg = { -+ .size = 384, -+ .lower = 32, -+ .ta = true, - }; - - static const struct of_device_id stm32_romem_of_match[] = { -@@ -198,7 +243,10 @@ static const struct of_device_id stm32_r - .compatible = "st,stm32mp15-bsec", - .data = (void *)&stm32mp15_bsec_cfg, - }, { -+ .compatible = "st,stm32mp13-bsec", -+ .data = (void *)&stm32mp13_bsec_cfg, - }, -+ { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, stm32_romem_of_match); - diff --git a/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch b/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch deleted file mode 100644 index cea8e93858..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0008-nvmem-stm32-detect-bsec-pta-presence-for-STM32MP15x.patch +++ /dev/null @@ -1,85 +0,0 @@ -From df2f34ef1d924125ffaf29dfdaf7cdbd3183c321 Mon Sep 17 00:00:00 2001 -From: Patrick Delaunay -Date: Mon, 6 Feb 2023 13:43:52 +0000 -Subject: [PATCH] nvmem: stm32: detect bsec pta presence for STM32MP15x - -On STM32MP15x SoC, the SMC backend is optional when OP-TEE is used; -the PTA BSEC should be used as it is done on STM32MP13x platform, -but the BSEC SMC can be also used: it is a legacy mode in OP-TEE, -not recommended but used in previous OP-TEE firmware. - -The presence of OP-TEE is dynamically detected in STM32MP15x device tree -and the supported NVMEM backend is dynamically detected: -- PTA with stm32_bsec_pta_find -- SMC with stm32_bsec_check - -With OP-TEE but without PTA and SMC detection, the probe is deferred for -STM32MP15x devices. - -On STM32MP13x platform, only the PTA is supported with cfg->ta = true -and this detection is skipped. - -Signed-off-by: Patrick Delaunay -Reviewed-by: Etienne Carriere -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-19-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 38 +++++++++++++++++++++++++++++++++---- - 1 file changed, 34 insertions(+), 4 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -159,6 +159,31 @@ static int stm32_bsec_pta_write(void *co - return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes); - } - -+static bool stm32_bsec_smc_check(void) -+{ -+ u32 val; -+ int ret; -+ -+ /* check that the OP-TEE support the BSEC SMC (legacy mode) */ -+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, 0, 0, &val); -+ -+ return !ret; -+} -+ -+static bool optee_presence_check(void) -+{ -+ struct device_node *np; -+ bool tee_detected = false; -+ -+ /* check that the OP-TEE node is present and available. */ -+ np = of_find_compatible_node(NULL, NULL, "linaro,optee-tz"); -+ if (np && of_device_is_available(np)) -+ tee_detected = true; -+ of_node_put(np); -+ -+ return tee_detected; -+} -+ - static int stm32_romem_probe(struct platform_device *pdev) - { - const struct stm32_romem_cfg *cfg; -@@ -195,11 +220,16 @@ static int stm32_romem_probe(struct plat - } else { - priv->cfg.size = cfg->size; - priv->lower = cfg->lower; -- if (cfg->ta) { -+ if (cfg->ta || optee_presence_check()) { - rc = stm32_bsec_optee_ta_open(&priv->ctx); -- /* wait for OP-TEE client driver to be up and ready */ -- if (rc) -- return rc; -+ if (rc) { -+ /* wait for OP-TEE client driver to be up and ready */ -+ if (rc == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ /* BSEC PTA is required or SMC not supported */ -+ if (cfg->ta || !stm32_bsec_smc_check()) -+ return rc; -+ } - } - if (priv->ctx) { - rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch b/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch deleted file mode 100644 index 9d6275a737..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0009-nvmem-rave-sp-eeprm-fix-kernel-doc-bad-line-warning.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 3e5ac22aa564026e99defc3a8e02082521a5b231 Mon Sep 17 00:00:00 2001 -From: Randy Dunlap -Date: Mon, 6 Feb 2023 13:43:53 +0000 -Subject: [PATCH] nvmem: rave-sp-eeprm: fix kernel-doc bad line warning - -Convert an empty line to " *" to avoid a kernel-doc warning: - -drivers/nvmem/rave-sp-eeprom.c:48: warning: bad line: - -Signed-off-by: Randy Dunlap -Cc: Srinivas Kandagatla -Cc: Andrey Vostrikov -Cc: Nikita Yushchenko -Cc: Andrey Smirnov -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-20-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rave-sp-eeprom.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/rave-sp-eeprom.c -+++ b/drivers/nvmem/rave-sp-eeprom.c -@@ -45,7 +45,7 @@ enum rave_sp_eeprom_header_size { - * @type: Access type (see enum rave_sp_eeprom_access_type) - * @success: Success flag (Success = 1, Failure = 0) - * @data: Read data -- -+ * - * Note this structure corresponds to RSP_*_EEPROM payload from RAVE - * SP ICD - */ diff --git a/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch b/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch deleted file mode 100644 index 1ab9e609d3..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0010-nvmem-qcom-spmi-sdam-register-at-device-init-time.patch +++ /dev/null @@ -1,43 +0,0 @@ -From eb7dda20f42a9137e9ee53d5ed3b743d49338cb5 Mon Sep 17 00:00:00 2001 -From: Johan Hovold -Date: Mon, 6 Feb 2023 13:43:54 +0000 -Subject: [PATCH] nvmem: qcom-spmi-sdam: register at device init time - -There are currently no in-tree users of the Qualcomm SDAM nvmem driver -and there is generally no point in registering a driver that can be -built as a module at subsys init time. - -Register the driver at the normal device init time instead and let -driver core sort out the probe order. - -Signed-off-by: Johan Hovold -Reviewed-by: Bjorn Andersson -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-21-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/qcom-spmi-sdam.c | 13 +------------ - 1 file changed, 1 insertion(+), 12 deletions(-) - ---- a/drivers/nvmem/qcom-spmi-sdam.c -+++ b/drivers/nvmem/qcom-spmi-sdam.c -@@ -175,18 +175,7 @@ static struct platform_driver sdam_drive - }, - .probe = sdam_probe, - }; -- --static int __init sdam_init(void) --{ -- return platform_driver_register(&sdam_driver); --} --subsys_initcall(sdam_init); -- --static void __exit sdam_exit(void) --{ -- return platform_driver_unregister(&sdam_driver); --} --module_exit(sdam_exit); -+module_platform_driver(sdam_driver); - - MODULE_DESCRIPTION("QCOM SPMI SDAM driver"); - MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch b/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch deleted file mode 100644 index dcf704c6ff..0000000000 --- a/target/linux/generic/backport-6.6/809-v6.3-0011-nvmem-stm32-fix-OPTEE-dependency.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1dc7e37bb0ec1c997fac82031332a38c7610352f Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Mon, 6 Feb 2023 13:43:56 +0000 -Subject: [PATCH] nvmem: stm32: fix OPTEE dependency - -The stm32 nvmem driver fails to link as built-in when OPTEE -is a loadable module: - -aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: -stm32-bsec-optee-ta.c:(.text+0xc8): undefined reference to `tee_client_open_session' -aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec: -stm32-bsec-optee-ta.c:(.text+0x1fc): undefined reference to `tee_client_open_context' - -Change the CONFIG_NVMEM_STM32_ROMEM definition so it can only -be built-in if OPTEE is either built-in or disabled, and -make NVMEM_STM32_BSEC_OPTEE_TA a hidden symbol instead. - -Signed-off-by: Arnd Bergmann -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-23-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -291,8 +291,7 @@ config NVMEM_SPRD_EFUSE - will be called nvmem-sprd-efuse. - - config NVMEM_STM32_BSEC_OPTEE_TA -- bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver" -- depends on OPTEE -+ def_bool NVMEM_STM32_ROMEM && OPTEE - help - Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE - trusted application STM32MP BSEC. -@@ -303,7 +302,7 @@ config NVMEM_STM32_BSEC_OPTEE_TA - config NVMEM_STM32_ROMEM - tristate "STMicroelectronics STM32 factory-programmed memory support" - depends on ARCH_STM32 || COMPILE_TEST -- imply NVMEM_STM32_BSEC_OPTEE_TA -+ depends on OPTEE || !OPTEE - help - Say y here to enable read-only access for STMicroelectronics STM32 - factory-programmed memory area. diff --git a/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch b/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch deleted file mode 100644 index 60a90136c9..0000000000 --- a/target/linux/generic/backport-6.6/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 4d70c74659d9746502b23d055dba03d1d28ec388 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Wed, 30 Nov 2022 15:48:35 +0200 -Subject: [PATCH] i915: Move list_count() to list.h as list_count_nodes() for - broader use - -Some of the existing users, and definitely will be new ones, want to -count existing nodes in the list. Provide a generic API for that by -moving code from i915 to list.h. - -Reviewed-by: Lucas De Marchi -Acked-by: Jani Nikula -Signed-off-by: Andy Shevchenko -Link: https://lore.kernel.org/r/20221130134838.23805-1-andriy.shevchenko@linux.intel.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/gpu/drm/i915/gt/intel_engine_cs.c | 15 ++------------- - include/linux/list.h | 15 +++++++++++++++ - 2 files changed, 17 insertions(+), 13 deletions(-) - ---- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -@@ -4154,17 +4154,6 @@ void intel_execlists_show_requests(struc - spin_unlock_irqrestore(&sched_engine->lock, flags); - } - --static unsigned long list_count(struct list_head *list) --{ -- struct list_head *pos; -- unsigned long count = 0; -- -- list_for_each(pos, list) -- count++; -- -- return count; --} -- - void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, - struct i915_request *hung_rq, - struct drm_printer *m) -@@ -4175,8 +4164,8 @@ void intel_execlists_dump_active_request - - intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); - -- drm_printf(m, "\tOn hold?: %lu\n", -- list_count(&engine->sched_engine->hold)); -+ drm_printf(m, "\tOn hold?: %zu\n", -+ list_count_nodes(&engine->sched_engine->hold)); - - spin_unlock_irqrestore(&engine->sched_engine->lock, flags); - } ---- a/include/linux/list.h -+++ b/include/linux/list.h -@@ -656,6 +656,21 @@ static inline void list_splice_tail_init - pos = n, n = pos->prev) - - /** -+ * list_count_nodes - count nodes in the list -+ * @head: the head for your list. -+ */ -+static inline size_t list_count_nodes(struct list_head *head) -+{ -+ struct list_head *pos; -+ size_t count = 0; -+ -+ list_for_each(pos, head) -+ count++; -+ -+ return count; -+} -+ -+/** - * list_entry_is_head - test if the entry points to the head of the list - * @pos: the type * to cursor - * @head: the head for your list. diff --git a/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch b/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch deleted file mode 100644 index 8328e87c0a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0001-nvmem-xilinx-zynqmp-make-modular.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bcd1fe07def0f070eb5f31594620aaee6f81d31a Mon Sep 17 00:00:00 2001 -From: Nick Alcock -Date: Tue, 4 Apr 2023 18:21:11 +0100 -Subject: [PATCH] nvmem: xilinx: zynqmp: make modular - -This driver has a MODULE_LICENSE but is not tristate so cannot be -built as a module, unlike all its peers: make it modular to match. - -Signed-off-by: Nick Alcock -Suggested-by: Michal Simek -Cc: Luis Chamberlain -Cc: linux-modules@vger.kernel.org -Cc: linux-kernel@vger.kernel.org -Cc: Hitomi Hasegawa -Cc: Srinivas Kandagatla -Cc: Michal Simek -Cc: linux-arm-kernel@lists.infradead.org -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP - be called nvmem-vf610-ocotp. - - config NVMEM_ZYNQMP -- bool "Xilinx ZYNQMP SoC nvmem firmware support" -+ tristate "Xilinx ZYNQMP SoC nvmem firmware support" - depends on ARCH_ZYNQMP - help - This is a driver to access hardware related data like diff --git a/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch deleted file mode 100644 index 94cd23c18a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0002-nvmem-core-introduce-NVMEM-layouts.patch +++ /dev/null @@ -1,387 +0,0 @@ -From 266570f496b90dea8fda893c2cf7c28d63ae2bd9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:21 +0100 -Subject: [PATCH] nvmem: core: introduce NVMEM layouts - -NVMEM layouts are used to generate NVMEM cells during runtime. Think of -an EEPROM with a well-defined conent. For now, the content can be -described by a device tree or a board file. But this only works if the -offsets and lengths are static and don't change. One could also argue -that putting the layout of the EEPROM in the device tree is the wrong -place. Instead, the device tree should just have a specific compatible -string. - -Right now there are two use cases: - (1) The NVMEM cell needs special processing. E.g. if it only specifies - a base MAC address offset and you need to add an offset, or it - needs to parse a MAC from ASCII format or some proprietary format. - (Post processing of cells is added in a later commit). - (2) u-boot environment parsing. The cells don't have a particular - offset but it needs parsing the content to determine the offsets - and length. - -Co-developed-by: Miquel Raynal -Signed-off-by: Miquel Raynal -Signed-off-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-14-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/driver-api/nvmem.rst | 15 ++++ - drivers/nvmem/Kconfig | 4 + - drivers/nvmem/Makefile | 1 + - drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++ - drivers/nvmem/layouts/Kconfig | 5 ++ - drivers/nvmem/layouts/Makefile | 4 + - include/linux/nvmem-consumer.h | 7 ++ - include/linux/nvmem-provider.h | 51 ++++++++++++ - 8 files changed, 207 insertions(+) - create mode 100644 drivers/nvmem/layouts/Kconfig - create mode 100644 drivers/nvmem/layouts/Makefile - ---- a/Documentation/driver-api/nvmem.rst -+++ b/Documentation/driver-api/nvmem.rst -@@ -185,3 +185,18 @@ ex:: - ===================== - - See Documentation/devicetree/bindings/nvmem/nvmem.txt -+ -+8. NVMEM layouts -+================ -+ -+NVMEM layouts are yet another mechanism to create cells. With the device -+tree binding it is possible to specify simple cells by using an offset -+and a length. Sometimes, the cells doesn't have a static offset, but -+the content is still well defined, e.g. tag-length-values. In this case, -+the NVMEM device content has to be first parsed and the cells need to -+be added accordingly. Layouts let you read the content of the NVMEM device -+and let you add cells dynamically. -+ -+Another use case for layouts is the post processing of cells. With layouts, -+it is possible to associate a custom post processing hook to a cell. It -+even possible to add this hook to cells not created by the layout itself. ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -21,6 +21,10 @@ config NVMEM_SYSFS - This interface is mostly used by userspace applications to - read/write directly into nvmem. - -+# Layouts -+ -+source "drivers/nvmem/layouts/Kconfig" -+ - # Devices - - config NVMEM_APPLE_EFUSES ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -5,6 +5,7 @@ - - obj-$(CONFIG_NVMEM) += nvmem_core.o - nvmem_core-y := core.o -+obj-y += layouts/ - - # Devices - obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -40,6 +40,7 @@ struct nvmem_device { - nvmem_reg_write_t reg_write; - nvmem_cell_post_process_t cell_post_process; - struct gpio_desc *wp_gpio; -+ struct nvmem_layout *layout; - void *priv; - }; - -@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list); - - static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); - -+static DEFINE_SPINLOCK(nvmem_layout_lock); -+static LIST_HEAD(nvmem_layouts); -+ - static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, - void *val, size_t bytes) - { -@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struc - return 0; - } - -+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) -+{ -+ layout->owner = owner; -+ -+ spin_lock(&nvmem_layout_lock); -+ list_add(&layout->node, &nvmem_layouts); -+ spin_unlock(&nvmem_layout_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(__nvmem_layout_register); -+ -+void nvmem_layout_unregister(struct nvmem_layout *layout) -+{ -+ spin_lock(&nvmem_layout_lock); -+ list_del(&layout->node); -+ spin_unlock(&nvmem_layout_lock); -+} -+EXPORT_SYMBOL_GPL(nvmem_layout_unregister); -+ -+static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) -+{ -+ struct device_node *layout_np, *np = nvmem->dev.of_node; -+ struct nvmem_layout *l, *layout = NULL; -+ -+ layout_np = of_get_child_by_name(np, "nvmem-layout"); -+ if (!layout_np) -+ return NULL; -+ -+ spin_lock(&nvmem_layout_lock); -+ -+ list_for_each_entry(l, &nvmem_layouts, node) { -+ if (of_match_node(l->of_match_table, layout_np)) { -+ if (try_module_get(l->owner)) -+ layout = l; -+ -+ break; -+ } -+ } -+ -+ spin_unlock(&nvmem_layout_lock); -+ of_node_put(layout_np); -+ -+ return layout; -+} -+ -+static void nvmem_layout_put(struct nvmem_layout *layout) -+{ -+ if (layout) -+ module_put(layout->owner); -+} -+ -+static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem) -+{ -+ struct nvmem_layout *layout = nvmem->layout; -+ int ret; -+ -+ if (layout && layout->add_cells) { -+ ret = layout->add_cells(&nvmem->dev, nvmem, layout); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+#if IS_ENABLED(CONFIG_OF) -+/** -+ * of_nvmem_layout_get_container() - Get OF node to layout container. -+ * -+ * @nvmem: nvmem device. -+ * -+ * Return: a node pointer with refcount incremented or NULL if no -+ * container exists. Use of_node_put() on it when done. -+ */ -+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) -+{ -+ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); -+} -+EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); -+#endif -+ -+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ struct device_node __maybe_unused *layout_np; -+ const struct of_device_id *match; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ match = of_match_node(layout->of_match_table, layout_np); -+ -+ return match ? match->data : NULL; -+} -+EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); -+ - /** - * nvmem_register() - Register a nvmem device for given nvmem_config. - * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem -@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(cons - goto err_put_device; - } - -+ /* -+ * If the driver supplied a layout by config->layout, the module -+ * pointer will be NULL and nvmem_layout_put() will be a noop. -+ */ -+ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); -+ - if (config->cells) { - rval = nvmem_add_cells(nvmem, config->cells, config->ncells); - if (rval) -@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -+ rval = nvmem_add_cells_from_layout(nvmem); -+ if (rval) -+ goto err_remove_cells; -+ - blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); - - return nvmem; - - err_remove_cells: - nvmem_device_remove_all_cells(nvmem); -+ nvmem_layout_put(nvmem->layout); - if (config->compat) - nvmem_sysfs_remove_compat(nvmem, config); - err_put_device: -@@ -881,6 +991,7 @@ static void nvmem_device_release(struct - device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); - - nvmem_device_remove_all_cells(nvmem); -+ nvmem_layout_put(nvmem->layout); - device_unregister(&nvmem->dev); - } - -@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(str - return ERR_PTR(-EINVAL); - } - -+ /* nvmem layouts produce cells within the nvmem-layout container */ -+ if (of_node_name_eq(nvmem_np, "nvmem-layout")) { -+ nvmem_np = of_get_next_parent(nvmem_np); -+ if (!nvmem_np) { -+ of_node_put(cell_np); -+ return ERR_PTR(-EINVAL); -+ } -+ } -+ - nvmem = __nvmem_device_get(nvmem_np, device_match_of_node); - of_node_put(nvmem_np); - if (IS_ERR(nvmem)) { ---- /dev/null -+++ b/drivers/nvmem/layouts/Kconfig -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+menu "Layout Types" -+ -+endmenu ---- /dev/null -+++ b/drivers/nvmem/layouts/Makefile -@@ -0,0 +1,4 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# Makefile for nvmem layouts. -+# ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(str - const char *id); - struct nvmem_device *of_nvmem_device_get(struct device_node *np, - const char *name); -+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); - #else - static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, - const char *id) -@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nv - { - return ERR_PTR(-EOPNOTSUPP); - } -+ -+static inline struct device_node * -+of_nvmem_layout_get_container(struct nvmem_device *nvmem) -+{ -+ return ERR_PTR(-EOPNOTSUPP); -+} - #endif /* CONFIG_NVMEM && CONFIG_OF */ - - #endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -88,6 +88,7 @@ struct nvmem_cell_info { - * @stride: Minimum read/write access stride. - * @priv: User context passed to read/write callbacks. - * @ignore_wp: Write Protect pin is managed by the provider. -+ * @layout: Fixed layout associated with this nvmem device. - * - * Note: A default "nvmem" name will be assigned to the device if - * no name is specified in its configuration. In such case "" is -@@ -109,6 +110,7 @@ struct nvmem_config { - bool read_only; - bool root_only; - bool ignore_wp; -+ struct nvmem_layout *layout; - struct device_node *of_node; - bool no_of_node; - nvmem_reg_read_t reg_read; -@@ -142,6 +144,33 @@ struct nvmem_cell_table { - struct list_head node; - }; - -+/** -+ * struct nvmem_layout - NVMEM layout definitions -+ * -+ * @name: Layout name. -+ * @of_match_table: Open firmware match table. -+ * @add_cells: Will be called if a nvmem device is found which -+ * has this layout. The function will add layout -+ * specific cells with nvmem_add_one_cell(). -+ * @owner: Pointer to struct module. -+ * @node: List node. -+ * -+ * A nvmem device can hold a well defined structure which can just be -+ * evaluated during runtime. For example a TLV list, or a list of "name=val" -+ * pairs. A nvmem layout can parse the nvmem device and add appropriate -+ * cells. -+ */ -+struct nvmem_layout { -+ const char *name; -+ const struct of_device_id *of_match_table; -+ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout); -+ -+ /* private */ -+ struct module *owner; -+ struct list_head node; -+}; -+ - #if IS_ENABLED(CONFIG_NVMEM) - - struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); -@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_c - int nvmem_add_one_cell(struct nvmem_device *nvmem, - const struct nvmem_cell_info *info); - -+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner); -+#define nvmem_layout_register(layout) \ -+ __nvmem_layout_register(layout, THIS_MODULE) -+void nvmem_layout_unregister(struct nvmem_layout *layout); -+ -+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout); -+ - #else - - static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) -@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(str - return -EOPNOTSUPP; - } - -+static inline int nvmem_layout_register(struct nvmem_layout *layout) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} -+ -+static inline const void * -+nvmem_layout_get_match_data(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ return NULL; -+} -+ - #endif /* CONFIG_NVMEM */ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch b/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch deleted file mode 100644 index 6fa7b6382d..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0003-nvmem-core-handle-the-absence-of-expected-layouts.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 6468a6f45148fb5e95c86b4efebf63f9abcd2137 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:22 +0100 -Subject: [PATCH] nvmem: core: handle the absence of expected layouts - -Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout -is not available. This condition cannot be triggered today as nvmem -layout drivers are initialed as part of an early init call, but soon -these drivers will be converted into modules and be initialized with a -standard priority, so the unavailability of the drivers might become a -reality that must be taken care of. - -Let's anticipate this by telling the caller the layout might not yet be -available. A probe deferral is requested in this case. - -Please note this does not affect any nvmem device not using layouts, -because an early check against the "nvmem-layout" container presence -will return NULL in this case. - -Signed-off-by: Miquel Raynal -Tested-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-15-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste - static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) - { - struct device_node *layout_np, *np = nvmem->dev.of_node; -- struct nvmem_layout *l, *layout = NULL; -+ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); - - layout_np = of_get_child_by_name(np, "nvmem-layout"); - if (!layout_np) -@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(cons - * pointer will be NULL and nvmem_layout_put() will be a noop. - */ - nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); -+ if (IS_ERR(nvmem->layout)) { -+ rval = PTR_ERR(nvmem->layout); -+ nvmem->layout = NULL; -+ -+ if (rval == -EPROBE_DEFER) -+ goto err_teardown_compat; -+ } - - if (config->cells) { - rval = nvmem_add_cells(nvmem, config->cells, config->ncells); -@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(cons - err_remove_cells: - nvmem_device_remove_all_cells(nvmem); - nvmem_layout_put(nvmem->layout); -+err_teardown_compat: - if (config->compat) - nvmem_sysfs_remove_compat(nvmem, config); - err_put_device: diff --git a/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch b/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch deleted file mode 100644 index b9341666f9..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0004-nvmem-core-request-layout-modules-loading.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b1c37bec1ccfe5ccab72bc0ddc0dfa45c43e2de2 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:23 +0100 -Subject: [PATCH] nvmem: core: request layout modules loading - -When a storage device like an eeprom or an mtd device probes, it -registers an nvmem device if the nvmem subsystem has been enabled (bool -symbol). During nvmem registration, if the device is using layouts to -expose dynamic nvmem cells, the core will first try to get a reference -over the layout driver callbacks. In practice there is not relationship -that can be described between the storage driver and the nvmem -layout. So there is no way we can enforce both drivers will be built-in -or both will be modules. If the storage device driver is built-in but -the layout is built as a module, instead of badly failing with an -endless probe deferral loop, lets just make a modprobe call in case the -driver was made available in an initramfs with -of_device_node_request_module(), and offer a fully functional system to -the user. - -Signed-off-by: Miquel Raynal -Tested-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-16-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - - struct nvmem_device { -@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout - if (!layout_np) - return NULL; - -+ /* -+ * In case the nvmem device was built-in while the layout was built as a -+ * module, we shall manually request the layout driver loading otherwise -+ * we'll never have any match. -+ */ -+ of_request_module(layout_np); -+ - spin_lock(&nvmem_layout_lock); - - list_for_each_entry(l, &nvmem_layouts, node) { diff --git a/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch b/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch deleted file mode 100644 index 53628cd4e4..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0005-nvmem-core-add-per-cell-post-processing.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 345ec382cd4b736c36e01f155d08c913b225b736 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:24 +0100 -Subject: [PATCH] nvmem: core: add per-cell post processing - -Instead of relying on the name the consumer is using for the cell, like -it is done for the nvmem .cell_post_process configuration parameter, -provide a per-cell post processing hook. This can then be populated by -the NVMEM provider (or the NVMEM layout) when adding the cell. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-17-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 17 +++++++++++++++++ - include/linux/nvmem-provider.h | 3 +++ - 2 files changed, 20 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -54,6 +54,7 @@ struct nvmem_cell_entry { - int bytes; - int bit_offset; - int nbits; -+ nvmem_cell_post_process_t read_post_process; - struct device_node *np; - struct nvmem_device *nvmem; - struct list_head node; -@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell - cell->offset = info->offset; - cell->bytes = info->bytes; - cell->name = info->name; -+ cell->read_post_process = info->read_post_process; - - cell->bit_offset = info->bit_offset; - cell->nbits = info->nbits; -@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvme - if (cell->bit_offset || cell->nbits) - nvmem_shift_read_buffer_in_place(cell, buf); - -+ if (cell->read_post_process) { -+ rc = cell->read_post_process(nvmem->priv, id, index, -+ cell->offset, buf, cell->bytes); -+ if (rc) -+ return rc; -+ } -+ - if (nvmem->cell_post_process) { - rc = nvmem->cell_post_process(nvmem->priv, id, index, - cell->offset, buf, cell->bytes); -@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(stru - (cell->bit_offset == 0 && len != cell->bytes)) - return -EINVAL; - -+ /* -+ * Any cells which have a read_post_process hook are read-only because -+ * we cannot reverse the operation and it might affect other cells, -+ * too. -+ */ -+ if (cell->read_post_process) -+ return -EINVAL; -+ - if (cell->bit_offset || cell->nbits) { - buf = nvmem_cell_prepare_write_buffer(cell, buf, len); - if (IS_ERR(buf)) ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -54,6 +54,8 @@ struct nvmem_keepout { - * @bit_offset: Bit offset if cell is smaller than a byte. - * @nbits: Number of bits. - * @np: Optional device_node pointer. -+ * @read_post_process: Callback for optional post processing of cell data -+ * on reads. - */ - struct nvmem_cell_info { - const char *name; -@@ -62,6 +64,7 @@ struct nvmem_cell_info { - unsigned int bit_offset; - unsigned int nbits; - struct device_node *np; -+ nvmem_cell_post_process_t read_post_process; - }; - - /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch b/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch deleted file mode 100644 index 32990148c8..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0006-nvmem-core-allow-to-modify-a-cell-before-adding-it.patch +++ /dev/null @@ -1,59 +0,0 @@ -From de12c9691501ccba41a154c223869f82be4c12fd Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:25 +0100 -Subject: [PATCH] nvmem: core: allow to modify a cell before adding it - -Provide a way to modify a cell before it will get added. This is useful -to attach a custom post processing hook via a layout. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-18-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 4 ++++ - include/linux/nvmem-provider.h | 5 +++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struc - - static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) - { -+ struct nvmem_layout *layout = nvmem->layout; - struct device *dev = &nvmem->dev; - struct device_node *child; - const __be32 *addr; -@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struc - - info.np = of_node_get(child); - -+ if (layout && layout->fixup_cell_info) -+ layout->fixup_cell_info(nvmem, layout, &info); -+ - ret = nvmem_add_one_cell(nvmem, &info); - kfree(info.name); - if (ret) { ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -155,6 +155,8 @@ struct nvmem_cell_table { - * @add_cells: Will be called if a nvmem device is found which - * has this layout. The function will add layout - * specific cells with nvmem_add_one_cell(). -+ * @fixup_cell_info: Will be called before a cell is added. Can be -+ * used to modify the nvmem_cell_info. - * @owner: Pointer to struct module. - * @node: List node. - * -@@ -168,6 +170,9 @@ struct nvmem_layout { - const struct of_device_id *of_match_table; - int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, - struct nvmem_layout *layout); -+ void (*fixup_cell_info)(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell); - - /* private */ - struct module *owner; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch b/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch deleted file mode 100644 index 2a5fa618ea..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0007-nvmem-imx-ocotp-replace-global-post-processing-with-.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 6c56a82d7895a213a43182a5d01a21a906a79847 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:26 +0100 -Subject: [PATCH] nvmem: imx-ocotp: replace global post processing with layouts - -In preparation of retiring the global post processing hook change this -driver to use layouts. The layout will be supplied during registration -and will be used to add the post processing hook to all added cells. - -Signed-off-by: Michael Walle -Tested-by: Michael Walle # on kontron-pitx-imx8m -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-19-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++----------- - 1 file changed, 19 insertions(+), 11 deletions(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -225,18 +225,13 @@ read_end: - static int imx_ocotp_cell_pp(void *context, const char *id, int index, - unsigned int offset, void *data, size_t bytes) - { -- struct ocotp_priv *priv = context; -+ u8 *buf = data; -+ int i; - - /* Deal with some post processing of nvmem cell data */ -- if (id && !strcmp(id, "mac-address")) { -- if (priv->params->reverse_mac_address) { -- u8 *buf = data; -- int i; -- -- for (i = 0; i < bytes/2; i++) -- swap(buf[i], buf[bytes - i - 1]); -- } -- } -+ if (id && !strcmp(id, "mac-address")) -+ for (i = 0; i < bytes / 2; i++) -+ swap(buf[i], buf[bytes - i - 1]); - - return 0; - } -@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvm - .stride = 1, - .reg_read = imx_ocotp_read, - .reg_write = imx_ocotp_write, -- .cell_post_process = imx_ocotp_cell_pp, - }; - - static const struct ocotp_params imx6q_params = { -@@ -595,6 +589,17 @@ static const struct of_device_id imx_oco - }; - MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); - -+static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell) -+{ -+ cell->read_post_process = imx_ocotp_cell_pp; -+} -+ -+struct nvmem_layout imx_ocotp_layout = { -+ .fixup_cell_info = imx_ocotp_fixup_cell_info, -+}; -+ - static int imx_ocotp_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platfo - imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; - imx_ocotp_nvmem_config.dev = dev; - imx_ocotp_nvmem_config.priv = priv; -+ if (priv->params->reverse_mac_address) -+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; -+ - priv->config = &imx_ocotp_nvmem_config; - - clk_prepare_enable(priv->clk); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch b/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch deleted file mode 100644 index eac202b882..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0008-nvmem-cell-drop-global-cell_post_process.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 011e40a166fdaa65fb9946b7cd91efec85b70dbb Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:27 +0100 -Subject: [PATCH] nvmem: cell: drop global cell_post_process - -There are no users anymore for the global cell_post_process callback -anymore. New users should use proper nvmem layouts. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-20-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 9 --------- - include/linux/nvmem-provider.h | 2 -- - 2 files changed, 11 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -39,7 +39,6 @@ struct nvmem_device { - unsigned int nkeepout; - nvmem_reg_read_t reg_read; - nvmem_reg_write_t reg_write; -- nvmem_cell_post_process_t cell_post_process; - struct gpio_desc *wp_gpio; - struct nvmem_layout *layout; - void *priv; -@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(cons - nvmem->type = config->type; - nvmem->reg_read = config->reg_read; - nvmem->reg_write = config->reg_write; -- nvmem->cell_post_process = config->cell_post_process; - nvmem->keepout = config->keepout; - nvmem->nkeepout = config->nkeepout; - if (config->of_node) -@@ -1575,13 +1573,6 @@ static int __nvmem_cell_read(struct nvme - if (rc) - return rc; - } -- -- if (nvmem->cell_post_process) { -- rc = nvmem->cell_post_process(nvmem->priv, id, index, -- cell->offset, buf, cell->bytes); -- if (rc) -- return rc; -- } - - if (len) - *len = cell->bytes; ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -85,7 +85,6 @@ struct nvmem_cell_info { - * @no_of_node: Device should not use the parent's of_node even if it's !NULL. - * @reg_read: Callback to read data. - * @reg_write: Callback to write data. -- * @cell_post_process: Callback for vendor specific post processing of cell data - * @size: Device size. - * @word_size: Minimum read/write access granularity. - * @stride: Minimum read/write access stride. -@@ -118,7 +117,6 @@ struct nvmem_config { - bool no_of_node; - nvmem_reg_read_t reg_read; - nvmem_reg_write_t reg_write; -- nvmem_cell_post_process_t cell_post_process; - int size; - int word_size; - int stride; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch b/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch deleted file mode 100644 index 46b30a2ed9..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0009-nvmem-core-provide-own-priv-pointer-in-post-process-.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 8a134fd9f9323f4c39ec27055b3d3723cfb5c1e9 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:28 +0100 -Subject: [PATCH] nvmem: core: provide own priv pointer in post process - callback - -It doesn't make any more sense to have a opaque pointer set up by the -nvmem device. Usually, the layout isn't associated with a particular -nvmem device. Instead, let the caller who set the post process callback -provide the priv pointer. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-21-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 4 +++- - include/linux/nvmem-provider.h | 5 ++++- - 2 files changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -54,6 +54,7 @@ struct nvmem_cell_entry { - int bit_offset; - int nbits; - nvmem_cell_post_process_t read_post_process; -+ void *priv; - struct device_node *np; - struct nvmem_device *nvmem; - struct list_head node; -@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell - cell->bytes = info->bytes; - cell->name = info->name; - cell->read_post_process = info->read_post_process; -+ cell->priv = info->priv; - - cell->bit_offset = info->bit_offset; - cell->nbits = info->nbits; -@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvme - nvmem_shift_read_buffer_in_place(cell, buf); - - if (cell->read_post_process) { -- rc = cell->read_post_process(nvmem->priv, id, index, -+ rc = cell->read_post_process(cell->priv, id, index, - cell->offset, buf, cell->bytes); - if (rc) - return rc; ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *p - void *val, size_t bytes); - /* used for vendor specific post processing of cell data */ - typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index, -- unsigned int offset, void *buf, size_t bytes); -+ unsigned int offset, void *buf, -+ size_t bytes); - - enum nvmem_type { - NVMEM_TYPE_UNKNOWN = 0, -@@ -56,6 +57,7 @@ struct nvmem_keepout { - * @np: Optional device_node pointer. - * @read_post_process: Callback for optional post processing of cell data - * on reads. -+ * @priv: Opaque data passed to the read_post_process hook. - */ - struct nvmem_cell_info { - const char *name; -@@ -65,6 +67,7 @@ struct nvmem_cell_info { - unsigned int nbits; - struct device_node *np; - nvmem_cell_post_process_t read_post_process; -+ void *priv; - }; - - /** diff --git a/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch deleted file mode 100644 index 7d97658b60..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0010-nvmem-layouts-sl28vpd-Add-new-layout-driver.patch +++ /dev/null @@ -1,215 +0,0 @@ -From d9fae023fe86069750092fc1c2f3a73e2fb18512 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 4 Apr 2023 18:21:29 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: Add new layout driver - -This layout applies to the VPD of the Kontron sl28 boards. The VPD only -contains a base MAC address. Therefore, we have to add an individual -offset to it. This is done by taking the second argument of the nvmem -phandle into account. Also this let us checking the VPD version and the -checksum. - -Signed-off-by: Michael Walle -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-22-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/Kconfig | 9 ++ - drivers/nvmem/layouts/Makefile | 2 + - drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++ - 3 files changed, 176 insertions(+) - create mode 100644 drivers/nvmem/layouts/sl28vpd.c - ---- a/drivers/nvmem/layouts/Kconfig -+++ b/drivers/nvmem/layouts/Kconfig -@@ -2,4 +2,13 @@ - - menu "Layout Types" - -+config NVMEM_LAYOUT_SL28_VPD -+ tristate "Kontron sl28 VPD layout support" -+ select CRC8 -+ help -+ Say Y here if you want to support the VPD layout of the Kontron -+ SMARC-sAL28 boards. -+ -+ If unsure, say N. -+ - endmenu ---- a/drivers/nvmem/layouts/Makefile -+++ b/drivers/nvmem/layouts/Makefile -@@ -2,3 +2,5 @@ - # - # Makefile for nvmem layouts. - # -+ -+obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o ---- /dev/null -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -0,0 +1,165 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SL28VPD_MAGIC 'V' -+ -+struct sl28vpd_header { -+ u8 magic; -+ u8 version; -+} __packed; -+ -+struct sl28vpd_v1 { -+ struct sl28vpd_header header; -+ char serial_number[15]; -+ u8 base_mac_address[ETH_ALEN]; -+ u8 crc8; -+} __packed; -+ -+static int sl28vpd_mac_address_pp(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ if (bytes != ETH_ALEN) -+ return -EINVAL; -+ -+ if (index < 0) -+ return -EINVAL; -+ -+ if (!is_valid_ether_addr(buf)) -+ return -EINVAL; -+ -+ eth_addr_add(buf, index); -+ -+ return 0; -+} -+ -+static const struct nvmem_cell_info sl28vpd_v1_entries[] = { -+ { -+ .name = "serial-number", -+ .offset = offsetof(struct sl28vpd_v1, serial_number), -+ .bytes = sizeof_field(struct sl28vpd_v1, serial_number), -+ }, -+ { -+ .name = "base-mac-address", -+ .offset = offsetof(struct sl28vpd_v1, base_mac_address), -+ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address), -+ .read_post_process = sl28vpd_mac_address_pp, -+ }, -+}; -+ -+static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem) -+{ -+ struct sl28vpd_v1 data_v1; -+ u8 table[CRC8_TABLE_SIZE]; -+ int ret; -+ u8 crc; -+ -+ crc8_populate_msb(table, 0x07); -+ -+ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1); -+ if (ret < 0) -+ return ret; -+ else if (ret != sizeof(data_v1)) -+ return -EIO; -+ -+ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0); -+ -+ if (crc != data_v1.crc8) { -+ dev_err(dev, -+ "Checksum is invalid (got %02x, expected %02x).\n", -+ crc, data_v1.crc8); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ const struct nvmem_cell_info *pinfo; -+ struct nvmem_cell_info info = {0}; -+ struct device_node *layout_np; -+ struct sl28vpd_header hdr; -+ int ret, i; -+ -+ /* check header */ -+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); -+ if (ret < 0) -+ return ret; -+ else if (ret != sizeof(hdr)) -+ return -EIO; -+ -+ if (hdr.magic != SL28VPD_MAGIC) { -+ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic); -+ return -EINVAL; -+ } -+ -+ if (hdr.version != 1) { -+ dev_err(dev, "Version %d is unsupported.\n", hdr.version); -+ return -EINVAL; -+ } -+ -+ ret = sl28vpd_v1_check_crc(dev, nvmem); -+ if (ret) -+ return ret; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ if (!layout_np) -+ return -ENOENT; -+ -+ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) { -+ pinfo = &sl28vpd_v1_entries[i]; -+ -+ info.name = pinfo->name; -+ info.offset = pinfo->offset; -+ info.bytes = pinfo->bytes; -+ info.read_post_process = pinfo->read_post_process; -+ info.np = of_get_child_by_name(layout_np, pinfo->name); -+ -+ ret = nvmem_add_one_cell(nvmem, &info); -+ if (ret) { -+ of_node_put(layout_np); -+ return ret; -+ } -+ } -+ -+ of_node_put(layout_np); -+ -+ return 0; -+} -+ -+static const struct of_device_id sl28vpd_of_match_table[] = { -+ { .compatible = "kontron,sl28-vpd" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); -+ -+struct nvmem_layout sl28vpd_layout = { -+ .name = "sl28-vpd", -+ .of_match_table = sl28vpd_of_match_table, -+ .add_cells = sl28vpd_add_cells, -+}; -+ -+static int __init sl28vpd_init(void) -+{ -+ return nvmem_layout_register(&sl28vpd_layout); -+} -+ -+static void __exit sl28vpd_exit(void) -+{ -+ nvmem_layout_unregister(&sl28vpd_layout); -+} -+ -+module_init(sl28vpd_init); -+module_exit(sl28vpd_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Michael Walle "); -+MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch deleted file mode 100644 index ca8b4bc069..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0011-nvmem-layouts-onie-tlv-Add-new-layout-driver.patch +++ /dev/null @@ -1,306 +0,0 @@ -From d3c0d12f6474216bf386101e2449cc73e5c5b61d Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:31 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Add new layout driver - -This layout applies on top of any non volatile storage device containing -an ONIE table factory flashed. This table follows the tlv -(type-length-value) organization described in the link below. We cannot -afford using regular parsers because the content of these tables is -manufacturer specific and must be dynamically discovered. - -Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-24-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/Kconfig | 9 ++ - drivers/nvmem/layouts/Makefile | 1 + - drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++ - 3 files changed, 267 insertions(+) - create mode 100644 drivers/nvmem/layouts/onie-tlv.c - ---- a/drivers/nvmem/layouts/Kconfig -+++ b/drivers/nvmem/layouts/Kconfig -@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD - - If unsure, say N. - -+config NVMEM_LAYOUT_ONIE_TLV -+ tristate "ONIE tlv support" -+ select CRC32 -+ help -+ Say Y here if you want to support the Open Compute Project ONIE -+ Type-Length-Value standard table. -+ -+ If unsure, say N. -+ - endmenu ---- a/drivers/nvmem/layouts/Makefile -+++ b/drivers/nvmem/layouts/Makefile -@@ -4,3 +4,4 @@ - # - - obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o -+obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o ---- /dev/null -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -0,0 +1,257 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * ONIE tlv NVMEM cells provider -+ * -+ * Copyright (C) 2022 Open Compute Group ONIE -+ * Author: Miquel Raynal -+ * Based on the nvmem driver written by: Vadym Kochan -+ * Inspired by the first layout written by: Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define ONIE_TLV_MAX_LEN 2048 -+#define ONIE_TLV_CRC_FIELD_SZ 6 -+#define ONIE_TLV_CRC_SZ 4 -+#define ONIE_TLV_HDR_ID "TlvInfo" -+ -+struct onie_tlv_hdr { -+ u8 id[8]; -+ u8 version; -+ __be16 data_len; -+} __packed; -+ -+struct onie_tlv { -+ u8 type; -+ u8 len; -+} __packed; -+ -+static const char *onie_tlv_cell_name(u8 type) -+{ -+ switch (type) { -+ case 0x21: -+ return "product-name"; -+ case 0x22: -+ return "part-number"; -+ case 0x23: -+ return "serial-number"; -+ case 0x24: -+ return "mac-address"; -+ case 0x25: -+ return "manufacture-date"; -+ case 0x26: -+ return "device-version"; -+ case 0x27: -+ return "label-revision"; -+ case 0x28: -+ return "platform-name"; -+ case 0x29: -+ return "onie-version"; -+ case 0x2A: -+ return "num-macs"; -+ case 0x2B: -+ return "manufacturer"; -+ case 0x2C: -+ return "country-code"; -+ case 0x2D: -+ return "vendor"; -+ case 0x2E: -+ return "diag-version"; -+ case 0x2F: -+ return "service-tag"; -+ case 0xFD: -+ return "vendor-extension"; -+ case 0xFE: -+ return "crc32"; -+ default: -+ break; -+ } -+ -+ return NULL; -+} -+ -+static int onie_tlv_mac_read_cb(void *priv, const char *id, int index, -+ unsigned int offset, void *buf, -+ size_t bytes) -+{ -+ eth_addr_add(buf, index); -+ -+ return 0; -+} -+ -+static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf) -+{ -+ switch (type) { -+ case 0x24: -+ return &onie_tlv_mac_read_cb; -+ default: -+ break; -+ } -+ -+ return NULL; -+} -+ -+static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem, -+ size_t data_len, u8 *data) -+{ -+ struct nvmem_cell_info cell = {}; -+ struct device_node *layout; -+ struct onie_tlv tlv; -+ unsigned int hdr_len = sizeof(struct onie_tlv_hdr); -+ unsigned int offset = 0; -+ int ret; -+ -+ layout = of_nvmem_layout_get_container(nvmem); -+ if (!layout) -+ return -ENOENT; -+ -+ while (offset < data_len) { -+ memcpy(&tlv, data + offset, sizeof(tlv)); -+ if (offset + tlv.len >= data_len) { -+ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n", -+ tlv.len, hdr_len + offset); -+ break; -+ } -+ -+ cell.name = onie_tlv_cell_name(tlv.type); -+ if (!cell.name) -+ continue; -+ -+ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len); -+ cell.bytes = tlv.len; -+ cell.np = of_get_child_by_name(layout, cell.name); -+ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv)); -+ -+ ret = nvmem_add_one_cell(nvmem, &cell); -+ if (ret) { -+ of_node_put(layout); -+ return ret; -+ } -+ -+ offset += sizeof(tlv) + tlv.len; -+ } -+ -+ of_node_put(layout); -+ -+ return 0; -+} -+ -+static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr) -+{ -+ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) { -+ dev_err(dev, "Invalid header\n"); -+ return false; -+ } -+ -+ if (hdr->version != 0x1) { -+ dev_err(dev, "Invalid version number\n"); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table) -+{ -+ struct onie_tlv crc_hdr; -+ u32 read_crc, calc_crc; -+ __be32 crc_be; -+ -+ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr)); -+ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) { -+ dev_err(dev, "Invalid CRC field\n"); -+ return false; -+ } -+ -+ /* The table contains a JAMCRC, which is XOR'ed compared to the original -+ * CRC32 implementation as known in the Ethernet world. -+ */ -+ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ); -+ read_crc = be32_to_cpu(crc_be); -+ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF; -+ if (read_crc != calc_crc) { -+ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n", -+ read_crc, calc_crc); -+ return false; -+ } -+ -+ return true; -+} -+ -+static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem, -+ struct nvmem_layout *layout) -+{ -+ struct onie_tlv_hdr hdr; -+ size_t table_len, data_len, hdr_len; -+ u8 *table, *data; -+ int ret; -+ -+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); -+ if (ret < 0) -+ return ret; -+ -+ if (!onie_tlv_hdr_is_valid(dev, &hdr)) { -+ dev_err(dev, "Invalid ONIE TLV header\n"); -+ return -EINVAL; -+ } -+ -+ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len); -+ data_len = be16_to_cpu(hdr.data_len); -+ table_len = hdr_len + data_len; -+ if (table_len > ONIE_TLV_MAX_LEN) { -+ dev_err(dev, "Invalid ONIE TLV data length\n"); -+ return -EINVAL; -+ } -+ -+ table = devm_kmalloc(dev, table_len, GFP_KERNEL); -+ if (!table) -+ return -ENOMEM; -+ -+ ret = nvmem_device_read(nvmem, 0, table_len, table); -+ if (ret != table_len) -+ return ret; -+ -+ if (!onie_tlv_crc_is_valid(dev, table_len, table)) -+ return -EINVAL; -+ -+ data = table + hdr_len; -+ ret = onie_tlv_add_cells(dev, nvmem, data_len, data); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static const struct of_device_id onie_tlv_of_match_table[] = { -+ { .compatible = "onie,tlv-layout", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table); -+ -+static struct nvmem_layout onie_tlv_layout = { -+ .name = "ONIE tlv layout", -+ .of_match_table = onie_tlv_of_match_table, -+ .add_cells = onie_tlv_parse_table, -+}; -+ -+static int __init onie_tlv_init(void) -+{ -+ return nvmem_layout_register(&onie_tlv_layout); -+} -+ -+static void __exit onie_tlv_exit(void) -+{ -+ nvmem_layout_unregister(&onie_tlv_layout); -+} -+ -+module_init(onie_tlv_init); -+module_exit(onie_tlv_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Miquel Raynal "); -+MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); -+MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch b/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch deleted file mode 100644 index 94a0911d73..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0012-nvmem-stm32-romem-mark-OF-related-data-as-maybe-unus.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a4fb434ef96ace5af758ca2c52c3a3f8f3abc87c Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 4 Apr 2023 18:21:34 +0100 -Subject: [PATCH] nvmem: stm32-romem: mark OF related data as maybe unused -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The driver can be compile tested with !CONFIG_OF making certain data -unused: - - drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=] - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-27-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm3 - .ta = true, - }; - --static const struct of_device_id stm32_romem_of_match[] = { -+static const struct of_device_id stm32_romem_of_match[] __maybe_unused = { - { .compatible = "st,stm32f4-otp", }, { - .compatible = "st,stm32mp15-bsec", - .data = (void *)&stm32mp15_bsec_cfg, diff --git a/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch b/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch deleted file mode 100644 index abda402bdd..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0013-nvmem-mtk-efuse-Support-postprocessing-for-GPU-speed.patch +++ /dev/null @@ -1,120 +0,0 @@ -From de6e05097f7db066afb0ad4c88b730949f7b7749 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Tue, 4 Apr 2023 18:21:35 +0100 -Subject: [PATCH] nvmem: mtk-efuse: Support postprocessing for GPU speed - binning data - -On some MediaTek SoCs GPU speed binning data is available for read -in the SoC's eFuse array but it has a format that is incompatible -with what the OPP API expects, as we read a number from 0 to 7 but -opp-supported-hw is expecting a bitmask to enable an OPP entry: -being what we read limited to 0-7, it's straightforward to simply -convert the value to BIT(value) as a post-processing action. - -So, introduce post-processing support and enable it by evaluating -the newly introduced platform data's `uses_post_processing` member, -currently enabled only for MT8186. - -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-28-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++-- - 1 file changed, 51 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/mtk-efuse.c -+++ b/drivers/nvmem/mtk-efuse.c -@@ -10,6 +10,11 @@ - #include - #include - #include -+#include -+ -+struct mtk_efuse_pdata { -+ bool uses_post_processing; -+}; - - struct mtk_efuse_priv { - void __iomem *base; -@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context, - return 0; - } - -+static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index, -+ unsigned int offset, void *data, size_t bytes) -+{ -+ u8 *val = data; -+ -+ if (val[0] < 8) -+ val[0] = BIT(val[0]); -+ -+ return 0; -+} -+ -+static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem, -+ struct nvmem_layout *layout, -+ struct nvmem_cell_info *cell) -+{ -+ size_t sz = strlen(cell->name); -+ -+ /* -+ * On some SoCs, the GPU speedbin is not read as bitmask but as -+ * a number with range [0-7] (max 3 bits): post process to use -+ * it in OPP tables to describe supported-hw. -+ */ -+ if (cell->nbits <= 3 && -+ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0) -+ cell->read_post_process = mtk_efuse_gpu_speedbin_pp; -+} -+ -+static struct nvmem_layout mtk_efuse_layout = { -+ .fixup_cell_info = mtk_efuse_fixup_cell_info, -+}; -+ - static int mtk_efuse_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platfo - struct nvmem_device *nvmem; - struct nvmem_config econfig = {}; - struct mtk_efuse_priv *priv; -+ const struct mtk_efuse_pdata *pdata; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platfo - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - -+ pdata = device_get_match_data(dev); - econfig.stride = 1; - econfig.word_size = 1; - econfig.reg_read = mtk_reg_read; - econfig.size = resource_size(res); - econfig.priv = priv; - econfig.dev = dev; -+ if (pdata->uses_post_processing) -+ econfig.layout = &mtk_efuse_layout; - nvmem = devm_nvmem_register(dev, &econfig); - - return PTR_ERR_OR_ZERO(nvmem); - } - -+static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { -+ .uses_post_processing = true, -+}; -+ -+static const struct mtk_efuse_pdata mtk_efuse_pdata = { -+ .uses_post_processing = false, -+}; -+ - static const struct of_device_id mtk_efuse_of_match[] = { -- { .compatible = "mediatek,mt8173-efuse",}, -- { .compatible = "mediatek,efuse",}, -+ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata }, -+ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata }, -+ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata }, - {/* sentinel */}, - }; - MODULE_DEVICE_TABLE(of, mtk_efuse_of_match); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch b/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch deleted file mode 100644 index 200eb1928f..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0014-nvmem-bcm-ocotp-Use-devm_platform_ioremap_resource.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 1dc552fa33cf98af3e784dbc0500da93cae3b24a Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:38 +0100 -Subject: [PATCH] nvmem: bcm-ocotp: Use devm_platform_ioremap_resource() - -According to commit 7945f929f1a7 ("drivers: provide -devm_platform_ioremap_resource()"), convert platform_get_resource(), -devm_ioremap_resource() to a single call to use -devm_platform_ioremap_resource(), as this is exactly what this function -does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-31-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/bcm-ocotp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/bcm-ocotp.c -+++ b/drivers/nvmem/bcm-ocotp.c -@@ -244,7 +244,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_ - static int bcm_otpc_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct resource *res; - struct otpc_priv *priv; - struct nvmem_device *nvmem; - int err; -@@ -259,8 +258,7 @@ static int bcm_otpc_probe(struct platfor - return -ENODEV; - - /* Get OTP base address register. */ -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) { - dev_err(dev, "unable to map I/O memory\n"); - return PTR_ERR(priv->base); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch b/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch deleted file mode 100644 index 890dacd08d..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0015-nvmem-nintendo-otp-Use-devm_platform_ioremap_resourc.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 649409990d2e93fac657be7c6960c28a2c601d65 Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:39 +0100 -Subject: [PATCH] nvmem: nintendo-otp: Use devm_platform_ioremap_resource() - -According to commit 7945f929f1a7 ("drivers: provide -devm_platform_ioremap_resource()"), convert platform_get_resource(), -devm_ioremap_resource() to a single call to use -devm_platform_ioremap_resource(), as this is exactly what this function -does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-32-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/nintendo-otp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/nintendo-otp.c -+++ b/drivers/nvmem/nintendo-otp.c -@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct pla - struct device *dev = &pdev->dev; - const struct of_device_id *of_id = - of_match_device(nintendo_otp_of_table, dev); -- struct resource *res; - struct nvmem_device *nvmem; - struct nintendo_otp_priv *priv; - -@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct pla - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->regs = devm_ioremap_resource(dev, res); -+ priv->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->regs)) - return PTR_ERR(priv->regs); - diff --git a/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch deleted file mode 100644 index 3f5d3c1ad4..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0016-nvmem-vf610-ocotp-Use-devm_platform_get_and_ioremap_.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c2367aa60d5e34d48582362c6de34b4131d92be7 Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Tue, 4 Apr 2023 18:21:40 +0100 -Subject: [PATCH] nvmem: vf610-ocotp: Use - devm_platform_get_and_ioremap_resource() - -According to commit 890cc39a8799 ("drivers: provide -devm_platform_get_and_ioremap_resource()"), convert -platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yang Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-33-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/vf610-ocotp.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/vf610-ocotp.c -+++ b/drivers/nvmem/vf610-ocotp.c -@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct plat - if (!ocotp_dev) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- ocotp_dev->base = devm_ioremap_resource(dev, res); -+ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(ocotp_dev->base)) - return PTR_ERR(ocotp_dev->base); - diff --git a/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch b/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch deleted file mode 100644 index eeb407e9bb..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0017-nvmem-core-support-specifying-both-cell-raw-data-pos.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Apr 2023 18:21:42 +0100 -Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post - read lengths -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Callback .read_post_process() is designed to modify raw cell content -before providing it to the consumer. So far we were dealing with -modifications that didn't affect cell size (length). In some cases -however cell content needs to be reformatted and resized. - -It's required e.g. to provide properly formatted MAC address in case -it's stored in a non-binary format (e.g. using ASCII). - -There were few discussions how to optimally handle that. Following -possible solutions were considered: -1. Allow .read_post_process() to realloc (resize) content buffer -2. Allow .read_post_process() to adjust (decrease) just buffer length -3. Register NVMEM cells using post-read sizes - -The preferred solution was the last one. The problem is that simply -adjusting "bytes" in NVMEM providers would result in core code NOT -passing whole raw data to .read_post_process() callbacks. It means -callback functions couldn't do their job without somehow manually -reading original cell content on their own. - -This patch deals with that by registering NVMEM cells with both lengths: -raw content one and post read one. It allows: -1. Core code to read whole raw cell content -2. Callbacks to return content they want - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 11 +++++++---- - include/linux/nvmem-provider.h | 2 ++ - 2 files changed, 9 insertions(+), 4 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -50,6 +50,7 @@ struct nvmem_device { - struct nvmem_cell_entry { - const char *name; - int offset; -+ size_t raw_len; - int bytes; - int bit_offset; - int nbits; -@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell - { - cell->nvmem = nvmem; - cell->offset = info->offset; -+ cell->raw_len = info->raw_len ?: info->bytes; - cell->bytes = info->bytes; - cell->name = info->name; - cell->read_post_process = info->read_post_process; -@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme - { - int rc; - -- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes); -+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len); - - if (rc) - return rc; -@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme - - if (cell->read_post_process) { - rc = cell->read_post_process(cell->priv, id, index, -- cell->offset, buf, cell->bytes); -+ cell->offset, buf, cell->raw_len); - if (rc) - return rc; - } -@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme - */ - void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) - { -- struct nvmem_device *nvmem = cell->entry->nvmem; -+ struct nvmem_cell_entry *entry = cell->entry; -+ struct nvmem_device *nvmem = entry->nvmem; - u8 *buf; - int rc; - - if (!nvmem) - return ERR_PTR(-EINVAL); - -- buf = kzalloc(cell->entry->bytes, GFP_KERNEL); -+ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL); - if (!buf) - return ERR_PTR(-ENOMEM); - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -51,6 +51,7 @@ struct nvmem_keepout { - * struct nvmem_cell_info - NVMEM cell description - * @name: Name. - * @offset: Offset within the NVMEM device. -+ * @raw_len: Length of raw data (without post processing). - * @bytes: Length of the cell. - * @bit_offset: Bit offset if cell is smaller than a byte. - * @nbits: Number of bits. -@@ -62,6 +63,7 @@ struct nvmem_keepout { - struct nvmem_cell_info { - const char *name; - unsigned int offset; -+ size_t raw_len; - unsigned int bytes; - unsigned int bit_offset; - unsigned int nbits; diff --git a/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch b/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch deleted file mode 100644 index adde0ffc4b..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0018-nvmem-u-boot-env-post-process-ethaddr-env-variable.patch +++ /dev/null @@ -1,81 +0,0 @@ -From c49f1a8af6bcf6d18576bca898f8083ca4b129e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 4 Apr 2023 18:21:43 +0100 -Subject: [PATCH] nvmem: u-boot-env: post-process "ethaddr" env variable -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -U-Boot environment variables are stored in ASCII format so "ethaddr" -requires parsing into binary to make it work with Ethernet interfaces. - -This includes support for indexes to support #nvmem-cell-cells = <1>. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-36-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 1 + - drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 27 insertions(+) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV - tristate "U-Boot environment variables support" - depends on OF && MTD - select CRC32 -+ select GENERIC_NET_UTILS - help - U-Boot stores its setup as environment variables. This driver adds - support for verifying & exporting such data. It also exposes variables ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -4,6 +4,8 @@ - */ - - #include -+#include -+#include - #include - #include - #include -@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context - return 0; - } - -+static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes) -+{ -+ u8 mac[ETH_ALEN]; -+ -+ if (bytes != 3 * ETH_ALEN - 1) -+ return -EINVAL; -+ -+ if (!mac_pton(buf, mac)) -+ return -EINVAL; -+ -+ if (index) -+ eth_addr_add(mac, index); -+ -+ ether_addr_copy(buf, mac); -+ -+ return 0; -+} -+ - static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, - size_t data_offset, size_t data_len) - { -@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u - priv->cells[idx].offset = data_offset + value - data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -+ if (!strcmp(var, "ethaddr")) { -+ priv->cells[idx].raw_len = strlen(value); -+ priv->cells[idx].bytes = ETH_ALEN; -+ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; -+ } - } - - if (WARN_ON(idx != priv->ncells)) diff --git a/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch b/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch deleted file mode 100644 index 7c6fe22b5f..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0019-nvmem-Add-macro-to-register-nvmem-layout-drivers.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 814c978f02db17f16e6aa2efa2a929372f06da09 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:44 +0100 -Subject: [PATCH] nvmem: Add macro to register nvmem layout drivers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Provide a module_nvmem_layout_driver() macro at the end of the -nvmem-provider.h header to reduce the boilerplate when registering nvmem -layout drivers. - -Suggested-by: Srinivas Kandagatla -Signed-off-by: Miquel Raynal -Acked-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-37-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/nvmem-provider.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -9,6 +9,7 @@ - #ifndef _LINUX_NVMEM_PROVIDER_H - #define _LINUX_NVMEM_PROVIDER_H - -+#include - #include - #include - #include -@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem - } - - #endif /* CONFIG_NVMEM */ -+ -+#define module_nvmem_layout_driver(__layout_driver) \ -+ module_driver(__layout_driver, nvmem_layout_register, \ -+ nvmem_layout_unregister) -+ - #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch b/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch deleted file mode 100644 index 06646dd68b..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0020-nvmem-layouts-sl28vpd-Use-module_nvmem_layout_driver.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0abdf99fe0c86252ba274703425f8d543d7e7f0d Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:45 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver() - -Stop open-coding the module init/exit functions. Use the -module_nvmem_layout_driver() instead. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-38-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/sl28vpd.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - ---- a/drivers/nvmem/layouts/sl28vpd.c -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = { - .of_match_table = sl28vpd_of_match_table, - .add_cells = sl28vpd_add_cells, - }; -- --static int __init sl28vpd_init(void) --{ -- return nvmem_layout_register(&sl28vpd_layout); --} -- --static void __exit sl28vpd_exit(void) --{ -- nvmem_layout_unregister(&sl28vpd_layout); --} -- --module_init(sl28vpd_init); --module_exit(sl28vpd_exit); -+module_nvmem_layout_driver(sl28vpd_layout); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Michael Walle "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch b/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch deleted file mode 100644 index 826f4378c2..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0021-nvmem-layouts-onie-tlv-Use-module_nvmem_layout_drive.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d119eb38faab61125aaa4f63c74eef61585cf34c Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:46 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver() - -Stop open-coding the module init/exit functions. Use the -module_nvmem_layout_driver() instead. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-39-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/onie-tlv.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - ---- a/drivers/nvmem/layouts/onie-tlv.c -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layo - .of_match_table = onie_tlv_of_match_table, - .add_cells = onie_tlv_parse_table, - }; -- --static int __init onie_tlv_init(void) --{ -- return nvmem_layout_register(&onie_tlv_layout); --} -- --static void __exit onie_tlv_exit(void) --{ -- nvmem_layout_unregister(&onie_tlv_layout); --} -- --module_init(onie_tlv_init); --module_exit(onie_tlv_exit); -+module_nvmem_layout_driver(onie_tlv_layout); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch b/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch deleted file mode 100644 index f20db85ceb..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0022-nvmem-layouts-onie-tlv-Drop-wrong-module-alias.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 6b13e4b6a9a45028ac730e550380077df1845912 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:47 +0100 -Subject: [PATCH] nvmem: layouts: onie-tlv: Drop wrong module alias - -The MODULE_ALIAS macro is misused here as it carries the -description. There is currently no relevant alias to provide so let's -just drop it. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-40-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/onie-tlv.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/nvmem/layouts/onie-tlv.c -+++ b/drivers/nvmem/layouts/onie-tlv.c -@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layo - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); - MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing"); --MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing"); diff --git a/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch b/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch deleted file mode 100644 index 5cf847b57a..0000000000 --- a/target/linux/generic/backport-6.6/811-v6.4-0023-nvmem-layouts-sl28vpd-set-varaiable-sl28vpd_layout-s.patch +++ /dev/null @@ -1,31 +0,0 @@ -From a8642cd11635a35a5f1dc31857887900d6610778 Mon Sep 17 00:00:00 2001 -From: Tom Rix -Date: Tue, 4 Apr 2023 18:21:48 +0100 -Subject: [PATCH] nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout - storage-class-specifier to static - -smatch reports -drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol - 'sl28vpd_layout' was not declared. Should it be static? - -This variable is only used in one file so it should be static. - -Signed-off-by: Tom Rix -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-41-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/layouts/sl28vpd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/layouts/sl28vpd.c -+++ b/drivers/nvmem/layouts/sl28vpd.c -@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd - }; - MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); - --struct nvmem_layout sl28vpd_layout = { -+static struct nvmem_layout sl28vpd_layout = { - .name = "sl28-vpd", - .of_match_table = sl28vpd_of_match_table, - .add_cells = sl28vpd_add_cells, diff --git a/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch b/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch deleted file mode 100644 index 13ee2d4229..0000000000 --- a/target/linux/generic/backport-6.6/812-v6.2-firmware-nvram-bcm47xx-support-init-from-IO-memory.patch +++ /dev/null @@ -1,100 +0,0 @@ -From a5be5ce0e25439fae3cd42e3d775979547926812 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 3 Nov 2022 09:25:29 +0100 -Subject: [PATCH] firmware/nvram: bcm47xx: support init from IO memory -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Provide NVMEM content to the NVRAM driver from a simple -memory resource. This is necessary to use NVRAM in a memory- -mapped flash device. Patch taken from OpenWrts development -tree. - -This patch makes it possible to use memory-mapped NVRAM -on the D-Link DWL-8610AP and the D-Link DIR-890L. - -Cc: Hauke Mehrtens -Cc: linux-mips@vger.kernel.org -Cc: Florian Fainelli -Cc: bcm-kernel-feedback-list@broadcom.com -Cc: Thomas Bogendoerfer -Signed-off-by: Rafał Miłecki -[Added an export for modules potentially using the init symbol] -Signed-off-by: Linus Walleij -Link: https://lore.kernel.org/r/20221103082529.359084-1-linus.walleij@linaro.org -Signed-off-by: Florian Fainelli ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 18 ++++++++++++++++++ - drivers/nvmem/brcm_nvram.c | 3 +++ - include/linux/bcm47xx_nvram.h | 6 ++++++ - 3 files changed, 27 insertions(+) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -110,6 +110,24 @@ found: - return 0; - } - -+int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size) -+{ -+ if (nvram_len) { -+ pr_warn("nvram already initialized\n"); -+ return -EEXIST; -+ } -+ -+ if (!bcm47xx_nvram_is_valid(nvram_start)) { -+ pr_err("No valid NVRAM found\n"); -+ return -ENOENT; -+ } -+ -+ bcm47xx_nvram_copy(nvram_start, res_size); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(bcm47xx_nvram_init_from_iomem); -+ - /* - * On bcm47xx we need access to the NVRAM very early, so we can't use mtd - * subsystem to access flash. We can't even use platform device / driver to ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -3,6 +3,7 @@ - * Copyright (C) 2021 Rafał Miłecki - */ - -+#include - #include - #include - #include -@@ -139,6 +140,8 @@ static int brcm_nvram_probe(struct platf - if (err) - return err; - -+ bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); -+ - config.dev = dev; - config.cells = priv->cells; - config.ncells = priv->ncells; ---- a/include/linux/bcm47xx_nvram.h -+++ b/include/linux/bcm47xx_nvram.h -@@ -11,6 +11,7 @@ - #include - - #ifdef CONFIG_BCM47XX_NVRAM -+int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size); - int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); - int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); - int bcm47xx_nvram_gpio_pin(const char *name); -@@ -20,6 +21,11 @@ static inline void bcm47xx_nvram_release - vfree(nvram); - }; - #else -+static inline int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, -+ size_t res_size) -+{ -+ return -ENOTSUPP; -+} - static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) - { - return -ENOTSUPP; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch b/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch deleted file mode 100644 index 38cfccd5ef..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0001-nvmem-imx-ocotp-set-varaiable-imx_ocotp_layout-stora.patch +++ /dev/null @@ -1,31 +0,0 @@ -From eebc6573ad940b62a87776db3917e912b4f52d78 Mon Sep 17 00:00:00 2001 -From: Tom Rix -Date: Sun, 11 Jun 2023 15:03:05 +0100 -Subject: [PATCH] nvmem: imx-ocotp: set varaiable imx_ocotp_layout - storage-class-specifier to static - -smatch reports -drivers/nvmem/imx-ocotp.c:599:21: warning: symbol - 'imx_ocotp_layout' was not declared. Should it be static? - -This variable is only used in one file so should be static. - -Signed-off-by: Tom Rix -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-2-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -596,7 +596,7 @@ static void imx_ocotp_fixup_cell_info(st - cell->read_post_process = imx_ocotp_cell_pp; - } - --struct nvmem_layout imx_ocotp_layout = { -+static struct nvmem_layout imx_ocotp_layout = { - .fixup_cell_info = imx_ocotp_fixup_cell_info, - }; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch b/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch deleted file mode 100644 index 7523e5ebf6..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0002-nvmem-imx-ocotp-Reverse-MAC-addresses-on-all-i.MX-de.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 8a00fc606312c68b98add8fe8e6f7a013ce29e78 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Sun, 11 Jun 2023 15:03:06 +0100 -Subject: [PATCH] nvmem: imx-ocotp: Reverse MAC addresses on all i.MX derivates - -Not just i.MX8M, but all i.MX6/7 (and subtypes) need to reverse the -MAC address read from fuses. Exceptions are i.MX6SLL and i.MX7ULP which -do not support ethernet at all. - -Fixes: d0221a780cbc ("nvmem: imx-ocotp: add support for post processing") -Signed-off-by: Alexander Stein -Tested-by: Richard Leitner # imx6q -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-3-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/imx-ocotp.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -97,7 +97,6 @@ struct ocotp_params { - unsigned int bank_address_words; - void (*set_timing)(struct ocotp_priv *priv); - struct ocotp_ctrl_reg ctrl; -- bool reverse_mac_address; - }; - - static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags) -@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mm_params = { -@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mn_params = { -@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, -- .reverse_mac_address = true, - }; - - static const struct ocotp_params imx8mp_params = { -@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_ - .bank_address_words = 0, - .set_timing = imx_ocotp_set_imx6_timing, - .ctrl = IMX_OCOTP_BM_CTRL_8MP, -- .reverse_mac_address = true, - }; - - static const struct of_device_id imx_ocotp_dt_ids[] = { -@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platfo - imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; - imx_ocotp_nvmem_config.dev = dev; - imx_ocotp_nvmem_config.priv = priv; -- if (priv->params->reverse_mac_address) -- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; -+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; - - priv->config = &imx_ocotp_nvmem_config; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch b/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch deleted file mode 100644 index fb4d346a95..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0003-nvmem-brcm_nvram-add-.read_post_process-for-MACs.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 73bcd133c910bff3b6d3b3834d0d14be9444e90a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sun, 11 Jun 2023 15:03:08 +0100 -Subject: [PATCH] nvmem: brcm_nvram: add .read_post_process() for MACs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -1. Parse ASCII MAC format into byte based -2. Calculate relative addresses based on index argument - -Signed-off-by: Rafał Miłecki -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-5-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 1 + - drivers/nvmem/brcm_nvram.c | 28 ++++++++++++++++++++++++++++ - 2 files changed, 29 insertions(+) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM - tristate "Broadcom's NVRAM support" - depends on ARCH_BCM_5301X || COMPILE_TEST - depends on HAS_IOMEM -+ select GENERIC_NET_UTILS - help - This driver provides support for Broadcom's NVRAM that can be accessed - using I/O mapping. ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -4,6 +4,8 @@ - */ - - #include -+#include -+#include - #include - #include - #include -@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context - return 0; - } - -+static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index, -+ unsigned int offset, void *buf, size_t bytes) -+{ -+ u8 mac[ETH_ALEN]; -+ -+ if (bytes != 3 * ETH_ALEN - 1) -+ return -EINVAL; -+ -+ if (!mac_pton(buf, mac)) -+ return -EINVAL; -+ -+ if (index) -+ eth_addr_add(mac, index); -+ -+ ether_addr_copy(buf, mac); -+ -+ return 0; -+} -+ - static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data, - size_t len) - { -@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct b - priv->cells[idx].offset = value - (char *)data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -+ if (!strcmp(var, "et0macaddr") || -+ !strcmp(var, "et1macaddr") || -+ !strcmp(var, "et2macaddr")) { -+ priv->cells[idx].raw_len = strlen(value); -+ priv->cells[idx].bytes = ETH_ALEN; -+ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; -+ } - } - - return 0; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch b/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch deleted file mode 100644 index 3b6e6e57f5..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0004-nvmem-rockchip-otp-Add-clks-and-reg_read-to-rockchip.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 8dc61364164e79e44c07fa2ac0a7b6939f00d5db Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:13 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data - -In preparation to support new Rockchip OTP memory devices with different -clock configurations and register layout, extend rockchip_data struct -with the related members: clks, num_clks, reg_read. - -Additionally, to avoid managing redundant driver data, drop num_clks -member from rockchip_otp struct and update all references to point to -the equivalent member in rockchip_data. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-10-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 79 ++++++++++++++++++++++-------------- - 1 file changed, 49 insertions(+), 30 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -54,21 +54,19 @@ - - #define OTPC_TIMEOUT 10000 - -+struct rockchip_data { -+ int size; -+ const char * const *clks; -+ int num_clks; -+ nvmem_reg_read_t reg_read; -+}; -+ - struct rockchip_otp { - struct device *dev; - void __iomem *base; -- struct clk_bulk_data *clks; -- int num_clks; -+ struct clk_bulk_data *clks; - struct reset_control *rst; --}; -- --/* list of required clocks */ --static const char * const rockchip_otp_clocks[] = { -- "otp", "apb_pclk", "phy", --}; -- --struct rockchip_data { -- int size; -+ const struct rockchip_data *data; - }; - - static int rockchip_otp_reset(struct rockchip_otp *otp) -@@ -132,29 +130,23 @@ static int rockchip_otp_ecc_enable(struc - return ret; - } - --static int rockchip_otp_read(void *context, unsigned int offset, -- void *val, size_t bytes) -+static int px30_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) - { - struct rockchip_otp *otp = context; - u8 *buf = val; -- int ret = 0; -- -- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks); -- if (ret < 0) { -- dev_err(otp->dev, "failed to prepare/enable clks\n"); -- return ret; -- } -+ int ret; - - ret = rockchip_otp_reset(otp); - if (ret) { - dev_err(otp->dev, "failed to reset otp phy\n"); -- goto disable_clks; -+ return ret; - } - - ret = rockchip_otp_ecc_enable(otp, false); - if (ret < 0) { - dev_err(otp->dev, "rockchip_otp_ecc_enable err\n"); -- goto disable_clks; -+ return ret; - } - - writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); -@@ -174,8 +166,28 @@ static int rockchip_otp_read(void *conte - - read_end: - writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); --disable_clks: -- clk_bulk_disable_unprepare(otp->num_clks, otp->clks); -+ -+ return ret; -+} -+ -+static int rockchip_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ struct rockchip_otp *otp = context; -+ int ret; -+ -+ if (!otp->data || !otp->data->reg_read) -+ return -EINVAL; -+ -+ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks); -+ if (ret < 0) { -+ dev_err(otp->dev, "failed to prepare/enable clks\n"); -+ return ret; -+ } -+ -+ ret = otp->data->reg_read(context, offset, val, bytes); -+ -+ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks); - - return ret; - } -@@ -189,8 +201,15 @@ static struct nvmem_config otp_config = - .reg_read = rockchip_otp_read, - }; - -+static const char * const px30_otp_clocks[] = { -+ "otp", "apb_pclk", "phy", -+}; -+ - static const struct rockchip_data px30_data = { - .size = 0x40, -+ .clks = px30_otp_clocks, -+ .num_clks = ARRAY_SIZE(px30_otp_clocks), -+ .reg_read = px30_otp_read, - }; - - static const struct of_device_id rockchip_otp_match[] = { -@@ -225,21 +244,21 @@ static int rockchip_otp_probe(struct pla - if (!otp) - return -ENOMEM; - -+ otp->data = data; - otp->dev = dev; - otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) - return PTR_ERR(otp->base); - -- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks); -- otp->clks = devm_kcalloc(dev, otp->num_clks, -- sizeof(*otp->clks), GFP_KERNEL); -+ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), -+ GFP_KERNEL); - if (!otp->clks) - return -ENOMEM; - -- for (i = 0; i < otp->num_clks; ++i) -- otp->clks[i].id = rockchip_otp_clocks[i]; -+ for (i = 0; i < data->num_clks; ++i) -+ otp->clks[i].id = data->clks[i]; - -- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks); -+ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); - if (ret) - return ret; - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch b/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch deleted file mode 100644 index b5b66cfc5a..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0005-nvmem-rockchip-otp-Generalize-rockchip_otp_wait_stat.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 30fd21cfb1e64ef20035559a8246f5fbf682c40e Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:14 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Generalize rockchip_otp_wait_status() - -In preparation to support additional Rockchip OTP memory devices with -different register layout, generalize rockchip_otp_wait_status() to -accept a new parameter for specifying the offset of the status register. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-11-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -90,18 +90,19 @@ static int rockchip_otp_reset(struct roc - return 0; - } - --static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag) -+static int rockchip_otp_wait_status(struct rockchip_otp *otp, -+ unsigned int reg, u32 flag) - { - u32 status = 0; - int ret; - -- ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status, -+ ret = readl_poll_timeout_atomic(otp->base + reg, status, - (status & flag), 1, OTPC_TIMEOUT); - if (ret) - return ret; - - /* clean int status */ -- writel(flag, otp->base + OTPC_INT_STATUS); -+ writel(flag, otp->base + reg); - - return 0; - } -@@ -123,7 +124,7 @@ static int rockchip_otp_ecc_enable(struc - - writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); - -- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); -+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE); - if (ret < 0) - dev_err(otp->dev, "timeout during ecc_enable\n"); - -@@ -156,7 +157,7 @@ static int px30_otp_read(void *context, - otp->base + OTPC_USER_ADDR); - writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, - otp->base + OTPC_USER_ENABLE); -- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); -+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE); - if (ret < 0) { - dev_err(otp->dev, "timeout during read setup\n"); - goto read_end; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch b/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch deleted file mode 100644 index 3a17479d95..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0006-nvmem-rockchip-otp-Use-devm_reset_control_array_get_.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d325c9dd2b6e94040ca722ddcadcd6af358dd2be Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:15 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Use - devm_reset_control_array_get_exclusive() - -In preparation to support new Rockchip OTP memory devices having -specific reset configurations, switch devm_reset_control_get() to -devm_reset_control_array_get_exclusive(). - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-12-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -263,7 +263,7 @@ static int rockchip_otp_probe(struct pla - if (ret) - return ret; - -- otp->rst = devm_reset_control_get(dev, "phy"); -+ otp->rst = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(otp->rst)) - return PTR_ERR(otp->rst); - diff --git a/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch b/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch deleted file mode 100644 index 37cb927b10..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0007-nvmem-rockchip-otp-Improve-probe-error-handling.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 912517345b867a69542dc9f5c2cc3e9d8beaccf5 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:16 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Improve probe error handling - -Enhance error handling in the probe function by making use of -dev_err_probe(), which ensures the error code is always printed, in -addition to the specified error message. - -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-13-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -235,10 +235,8 @@ static int rockchip_otp_probe(struct pla - int ret, i; - - data = of_device_get_match_data(dev); -- if (!data) { -- dev_err(dev, "failed to get match data\n"); -- return -EINVAL; -- } -+ if (!data) -+ return dev_err_probe(dev, -EINVAL, "failed to get match data\n"); - - otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), - GFP_KERNEL); -@@ -249,7 +247,8 @@ static int rockchip_otp_probe(struct pla - otp->dev = dev; - otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) -- return PTR_ERR(otp->base); -+ return dev_err_probe(dev, PTR_ERR(otp->base), -+ "failed to ioremap resource\n"); - - otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), - GFP_KERNEL); -@@ -261,18 +260,22 @@ static int rockchip_otp_probe(struct pla - - ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); - if (ret) -- return ret; -+ return dev_err_probe(dev, ret, "failed to get clocks\n"); - - otp->rst = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(otp->rst)) -- return PTR_ERR(otp->rst); -+ return dev_err_probe(dev, PTR_ERR(otp->rst), -+ "failed to get resets\n"); - - otp_config.size = data->size; - otp_config.priv = otp; - otp_config.dev = dev; -- nvmem = devm_nvmem_register(dev, &otp_config); - -- return PTR_ERR_OR_ZERO(nvmem); -+ nvmem = devm_nvmem_register(dev, &otp_config); -+ if (IS_ERR(nvmem)) -+ return dev_err_probe(dev, PTR_ERR(nvmem), -+ "failed to register nvmem device\n"); -+ return 0; - } - - static struct platform_driver rockchip_otp_driver = { diff --git a/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch b/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch deleted file mode 100644 index c1e2231c9e..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0008-nvmem-rockchip-otp-Add-support-for-RK3588.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 8ab099fafbbc8c9607c399d21a774784a6cb8b45 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sun, 11 Jun 2023 15:03:17 +0100 -Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3588 - -Add support for the OTP memory device found on the Rockchip RK3588 SoC. - -While here, remove the unnecessary 'void *' casts in the OF device ID -table. - -Co-developed-by: Finley Xiao -Signed-off-by: Finley Xiao -Signed-off-by: Cristian Ciocaltea -Tested-by: Vincent Legoll -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-14-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-otp.c | 78 +++++++++++++++++++++++++++++++++++- - 1 file changed, 76 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -54,6 +54,19 @@ - - #define OTPC_TIMEOUT 10000 - -+/* RK3588 Register */ -+#define RK3588_OTPC_AUTO_CTRL 0x04 -+#define RK3588_OTPC_AUTO_EN 0x08 -+#define RK3588_OTPC_INT_ST 0x84 -+#define RK3588_OTPC_DOUT0 0x20 -+#define RK3588_NO_SECURE_OFFSET 0x300 -+#define RK3588_NBYTES 4 -+#define RK3588_BURST_NUM 1 -+#define RK3588_BURST_SHIFT 8 -+#define RK3588_ADDR_SHIFT 16 -+#define RK3588_AUTO_EN BIT(0) -+#define RK3588_RD_DONE BIT(1) -+ - struct rockchip_data { - int size; - const char * const *clks; -@@ -171,6 +184,52 @@ read_end: - return ret; - } - -+static int rk3588_otp_read(void *context, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ struct rockchip_otp *otp = context; -+ unsigned int addr_start, addr_end, addr_len; -+ int ret, i = 0; -+ u32 data; -+ u8 *buf; -+ -+ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; -+ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; -+ addr_len = addr_end - addr_start; -+ addr_start += RK3588_NO_SECURE_OFFSET; -+ -+ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ while (addr_len--) { -+ writel((addr_start << RK3588_ADDR_SHIFT) | -+ (RK3588_BURST_NUM << RK3588_BURST_SHIFT), -+ otp->base + RK3588_OTPC_AUTO_CTRL); -+ writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); -+ -+ ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST, -+ RK3588_RD_DONE); -+ if (ret < 0) { -+ dev_err(otp->dev, "timeout during read setup\n"); -+ goto read_end; -+ } -+ -+ data = readl(otp->base + RK3588_OTPC_DOUT0); -+ memcpy(&buf[i], &data, RK3588_NBYTES); -+ -+ i += RK3588_NBYTES; -+ addr_start++; -+ } -+ -+ memcpy(val, buf + offset % RK3588_NBYTES, bytes); -+ -+read_end: -+ kfree(buf); -+ -+ return ret; -+} -+ - static int rockchip_otp_read(void *context, unsigned int offset, - void *val, size_t bytes) - { -@@ -213,14 +272,29 @@ static const struct rockchip_data px30_d - .reg_read = px30_otp_read, - }; - -+static const char * const rk3588_otp_clocks[] = { -+ "otp", "apb_pclk", "phy", "arb", -+}; -+ -+static const struct rockchip_data rk3588_data = { -+ .size = 0x400, -+ .clks = rk3588_otp_clocks, -+ .num_clks = ARRAY_SIZE(rk3588_otp_clocks), -+ .reg_read = rk3588_otp_read, -+}; -+ - static const struct of_device_id rockchip_otp_match[] = { - { - .compatible = "rockchip,px30-otp", -- .data = (void *)&px30_data, -+ .data = &px30_data, - }, - { - .compatible = "rockchip,rk3308-otp", -- .data = (void *)&px30_data, -+ .data = &px30_data, -+ }, -+ { -+ .compatible = "rockchip,rk3588-otp", -+ .data = &rk3588_data, - }, - { /* sentinel */ }, - }; diff --git a/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch b/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch deleted file mode 100644 index 220e3e9a05..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0009-nvmem-zynqmp-Switch-xilinx.com-emails-to-amd.com.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9734408969e978a1c0d5d752be63dd638288e374 Mon Sep 17 00:00:00 2001 -From: Michal Simek -Date: Sun, 11 Jun 2023 15:03:23 +0100 -Subject: [PATCH] nvmem: zynqmp: Switch @xilinx.com emails to @amd.com - -@xilinx.com is still working but better to switch to new amd.com after -AMD/Xilinx acquisition. - -Signed-off-by: Michal Simek -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-20-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/zynqmp_nvmem.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/zynqmp_nvmem.c -+++ b/drivers/nvmem/zynqmp_nvmem.c -@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvm - - module_platform_driver(zynqmp_nvmem_driver); - --MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); -+MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); - MODULE_DESCRIPTION("ZynqMP NVMEM driver"); - MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch b/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch deleted file mode 100644 index f8e6be4241..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0010-nvmem-imx-support-i.MX93-OCOTP.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 22e9e6fcfb5042cb6d6c7874c459b034800092f1 Mon Sep 17 00:00:00 2001 -From: Peng Fan -Date: Sun, 11 Jun 2023 15:03:25 +0100 -Subject: [PATCH] nvmem: imx: support i.MX93 OCOTP - -Add i.MX93 OCOTP support. i.MX93 OCOTP has two parts: Fuse shadow -block(fsb) and fuse managed by ELE. The FSB part could be directly -accessed with MMIO, the ELE could only be accessed with ELE API. - -Currently the ELE API is not ready, so NULL function callback is used, -but it was tested with downstream ELE API. - -Signed-off-by: Peng Fan -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-22-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/Kconfig | 9 ++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/imx-ocotp-ele.c | 175 ++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/nvmem/imx-ocotp-ele.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -83,6 +83,15 @@ config NVMEM_IMX_OCOTP - This driver can also be built as a module. If so, the module - will be called nvmem-imx-ocotp. - -+config NVMEM_IMX_OCOTP_ELE -+ tristate "i.MX On-Chip OTP Controller support" -+ depends on ARCH_MXC || COMPILE_TEST -+ depends on HAS_IOMEM -+ depends on OF -+ help -+ This is a driver for the On-Chip OTP Controller (OCOTP) -+ available on i.MX SoCs which has ELE. -+ - config NVMEM_IMX_OCOTP_SCU - tristate "i.MX8 SCU On-Chip OTP Controller support" - depends on IMX_SCU ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-im - nvmem-imx-iim-y := imx-iim.o - obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o - nvmem-imx-ocotp-y := imx-ocotp.o -+obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o -+nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o - obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o - nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o - obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o ---- /dev/null -+++ b/drivers/nvmem/imx-ocotp-ele.c -@@ -0,0 +1,175 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * i.MX9 OCOTP fusebox driver -+ * -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum fuse_type { -+ FUSE_FSB = 1, -+ FUSE_ELE = 2, -+ FUSE_INVALID = -1 -+}; -+ -+struct ocotp_map_entry { -+ u32 start; /* start word */ -+ u32 num; /* num words */ -+ enum fuse_type type; -+}; -+ -+struct ocotp_devtype_data { -+ u32 reg_off; -+ char *name; -+ u32 size; -+ u32 num_entry; -+ u32 flag; -+ nvmem_reg_read_t reg_read; -+ struct ocotp_map_entry entry[]; -+}; -+ -+struct imx_ocotp_priv { -+ struct device *dev; -+ void __iomem *base; -+ struct nvmem_config config; -+ struct mutex lock; -+ const struct ocotp_devtype_data *data; -+}; -+ -+static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index) -+{ -+ struct imx_ocotp_priv *priv = context; -+ const struct ocotp_devtype_data *data = priv->data; -+ u32 start, end; -+ int i; -+ -+ for (i = 0; i < data->num_entry; i++) { -+ start = data->entry[i].start; -+ end = data->entry[i].start + data->entry[i].num; -+ -+ if (index >= start && index < end) -+ return data->entry[i].type; -+ } -+ -+ return FUSE_INVALID; -+} -+ -+static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes) -+{ -+ struct imx_ocotp_priv *priv = context; -+ void __iomem *reg = priv->base + priv->data->reg_off; -+ u32 count, index, num_bytes; -+ enum fuse_type type; -+ u32 *buf; -+ void *p; -+ int i; -+ -+ index = offset; -+ num_bytes = round_up(bytes, 4); -+ count = num_bytes >> 2; -+ -+ if (count > ((priv->data->size >> 2) - index)) -+ count = (priv->data->size >> 2) - index; -+ -+ p = kzalloc(num_bytes, GFP_KERNEL); -+ if (!p) -+ return -ENOMEM; -+ -+ mutex_lock(&priv->lock); -+ -+ buf = p; -+ -+ for (i = index; i < (index + count); i++) { -+ type = imx_ocotp_fuse_type(context, i); -+ if (type == FUSE_INVALID || type == FUSE_ELE) { -+ *buf++ = 0; -+ continue; -+ } -+ -+ *buf++ = readl_relaxed(reg + (i << 2)); -+ } -+ -+ memcpy(val, (u8 *)p, bytes); -+ -+ mutex_unlock(&priv->lock); -+ -+ kfree(p); -+ -+ return 0; -+}; -+ -+static int imx_ele_ocotp_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct imx_ocotp_priv *priv; -+ struct nvmem_device *nvmem; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->data = of_device_get_match_data(dev); -+ -+ priv->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ priv->config.dev = dev; -+ priv->config.name = "ELE-OCOTP"; -+ priv->config.id = NVMEM_DEVID_AUTO; -+ priv->config.owner = THIS_MODULE; -+ priv->config.size = priv->data->size; -+ priv->config.reg_read = priv->data->reg_read; -+ priv->config.word_size = 4; -+ priv->config.stride = 1; -+ priv->config.priv = priv; -+ priv->config.read_only = true; -+ mutex_init(&priv->lock); -+ -+ nvmem = devm_nvmem_register(dev, &priv->config); -+ if (IS_ERR(nvmem)) -+ return PTR_ERR(nvmem); -+ -+ return 0; -+} -+ -+static const struct ocotp_devtype_data imx93_ocotp_data = { -+ .reg_off = 0x8000, -+ .reg_read = imx_ocotp_reg_read, -+ .size = 2048, -+ .num_entry = 6, -+ .entry = { -+ { 0, 52, FUSE_FSB }, -+ { 63, 1, FUSE_ELE}, -+ { 128, 16, FUSE_ELE }, -+ { 182, 1, FUSE_ELE }, -+ { 188, 1, FUSE_ELE }, -+ { 312, 200, FUSE_FSB } -+ }, -+}; -+ -+static const struct of_device_id imx_ele_ocotp_dt_ids[] = { -+ { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); -+ -+static struct platform_driver imx_ele_ocotp_driver = { -+ .driver = { -+ .name = "imx_ele_ocotp", -+ .of_match_table = imx_ele_ocotp_dt_ids, -+ }, -+ .probe = imx_ele_ocotp_probe, -+}; -+module_platform_driver(imx_ele_ocotp_driver); -+ -+MODULE_DESCRIPTION("i.MX OCOTP/ELE driver"); -+MODULE_AUTHOR("Peng Fan "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch b/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch deleted file mode 100644 index 59b2f9fa2c..0000000000 --- a/target/linux/generic/backport-6.6/813-v6.5-0011-nvmem-core-add-support-for-fixed-cells-layout.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 27f699e578b1a72df89dfa3bc42e093a01dc8d10 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Sun, 11 Jun 2023 15:03:29 +0100 -Subject: [PATCH] nvmem: core: add support for fixed cells *layout* -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds support for the "fixed-layout" NVMEM layout binding. It allows -defining NVMEM cells in a layout DT node named "nvmem-layout". - -While NVMEM subsystem supports layout drivers it has been discussed that -"fixed-layout" may actually be supperted internally. It's because: -1. It's a very basic layout -2. It allows sharing code with legacy syntax parsing -3. It's safer for soc_device_match() due to -EPROBE_DEFER -4. This will make the syntax transition easier - -Signed-off-by: Rafał Miłecki -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla -Message-ID: <20230611140330.154222-26-srinivas.kandagatla@linaro.org> -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 32 +++++++++++++++++++++++++++++--- - 1 file changed, 29 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struc - return 0; - } - --static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) -+static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) - { - struct nvmem_layout *layout = nvmem->layout; - struct device *dev = &nvmem->dev; -@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struc - const __be32 *addr; - int len, ret; - -- for_each_child_of_node(dev->of_node, child) { -+ for_each_child_of_node(np, child) { - struct nvmem_cell_info info = {0}; - - addr = of_get_property(child, "reg", &len); -@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struc - return 0; - } - -+static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem) -+{ -+ return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node); -+} -+ -+static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem) -+{ -+ struct device_node *layout_np; -+ int err = 0; -+ -+ layout_np = of_nvmem_layout_get_container(nvmem); -+ if (!layout_np) -+ return 0; -+ -+ if (of_device_is_compatible(layout_np, "fixed-layout")) -+ err = nvmem_add_cells_from_dt(nvmem, layout_np); -+ -+ of_node_put(layout_np); -+ -+ return err; -+} -+ - int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) - { - layout->owner = owner; -@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_of(nvmem); -+ rval = nvmem_add_cells_from_legacy_of(nvmem); - if (rval) - goto err_remove_cells; - -@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -+ rval = nvmem_add_cells_from_fixed_layout(nvmem); -+ if (rval) -+ goto err_remove_cells; -+ - rval = nvmem_add_cells_from_layout(nvmem); - if (rval) - goto err_remove_cells; diff --git a/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch deleted file mode 100644 index bf7a816bb2..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 9ccfcbeb8f32ff89e99b36cb9cdebaa0d1b44ed1 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:24 +0100 -Subject: [PATCH] nvmem: sunxi_sid: Convert to devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Acked-by: Jernej Skrabec -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/sunxi_sid.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/sunxi_sid.c -+++ b/drivers/nvmem/sunxi_sid.c -@@ -125,7 +125,6 @@ static int sun8i_sid_read_by_reg(void *c - static int sunxi_sid_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct resource *res; - struct nvmem_config *nvmem_cfg; - struct nvmem_device *nvmem; - struct sunxi_sid *sid; -@@ -142,8 +141,7 @@ static int sunxi_sid_probe(struct platfo - return -EINVAL; - sid->value_offset = cfg->value_offset; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- sid->base = devm_ioremap_resource(dev, res); -+ sid->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(sid->base)) - return PTR_ERR(sid->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch deleted file mode 100644 index f142d735de..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch +++ /dev/null @@ -1,30 +0,0 @@ -From cfadd0e7d9225566f320bc4dc716682be910be6c Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:25 +0100 -Subject: [PATCH] nvmem: brcm_nvram: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/brcm_nvram.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -159,8 +159,7 @@ static int brcm_nvram_probe(struct platf - return -ENOMEM; - priv->dev = dev; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch b/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch deleted file mode 100644 index 0395bbf8bc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0b49178e2b6b4aac3c7fa3ce8d8c02208a13b988 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:26 +0100 -Subject: [PATCH] nvmem: lpc18xx_otp: Convert to - devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-5-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/lpc18xx_otp.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/lpc18xx_otp.c -+++ b/drivers/nvmem/lpc18xx_otp.c -@@ -68,14 +68,12 @@ static int lpc18xx_otp_probe(struct plat - { - struct nvmem_device *nvmem; - struct lpc18xx_otp *otp; -- struct resource *res; - - otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL); - if (!otp) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- otp->base = devm_ioremap_resource(&pdev->dev, res); -+ otp->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(otp->base)) - return PTR_ERR(otp->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch b/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch deleted file mode 100644 index da077eb4b7..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0a223a097709b99a0ba738d6be5b4f52c04ffb64 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:27 +0100 -Subject: [PATCH] nvmem: meson-mx-efuse: Convert to - devm_platform_ioremap_resource() - -Use devm_platform_ioremap_resource() to simplify code. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-6-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/meson-mx-efuse.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/nvmem/meson-mx-efuse.c -+++ b/drivers/nvmem/meson-mx-efuse.c -@@ -194,7 +194,6 @@ static int meson_mx_efuse_probe(struct p - { - const struct meson_mx_efuse_platform_data *drvdata; - struct meson_mx_efuse *efuse; -- struct resource *res; - - drvdata = of_device_get_match_data(&pdev->dev); - if (!drvdata) -@@ -204,8 +203,7 @@ static int meson_mx_efuse_probe(struct p - if (!efuse) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- efuse->base = devm_ioremap_resource(&pdev->dev, res); -+ efuse->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(efuse->base)) - return PTR_ERR(efuse->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch b/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch deleted file mode 100644 index dc144ddfbd..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 94904db28db49ac8fbb2a273d25156db26a3a985 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:28 +0100 -Subject: [PATCH] nvmem: rockchip-efuse: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-7-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/rockchip-efuse.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/rockchip-efuse.c -+++ b/drivers/nvmem/rockchip-efuse.c -@@ -267,8 +267,7 @@ static int rockchip_efuse_probe(struct p - if (!efuse) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- efuse->base = devm_ioremap_resource(dev, res); -+ efuse->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(efuse->base)) - return PTR_ERR(efuse->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch b/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch deleted file mode 100644 index 99e20939cc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0a4a8c0d238fec1fa4b85591524ef42ad261cb97 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:29 +0100 -Subject: [PATCH] nvmem: stm32-romem: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/stm32-romem.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -196,8 +196,7 @@ static int stm32_romem_probe(struct plat - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch b/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch deleted file mode 100644 index 6d93752e27..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0bc0d6dc2a9a05ae6729b4622f09782d9f230815 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:30 +0100 -Subject: [PATCH] nvmem: qfprom: do some cleanup - -Use devm_platform_ioremap_resource() and -devm_platform_get_and_ioremap_resource() to simplify code. -BTW convert to use dev_err_probe() instead of open it. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/qfprom.c | 17 +++++------------ - 1 file changed, 5 insertions(+), 12 deletions(-) - ---- a/drivers/nvmem/qfprom.c -+++ b/drivers/nvmem/qfprom.c -@@ -374,8 +374,7 @@ static int qfprom_probe(struct platform_ - return -ENOMEM; - - /* The corrected section is always provided */ -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->qfpcorrected = devm_ioremap_resource(dev, res); -+ priv->qfpcorrected = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->qfpcorrected)) - return PTR_ERR(priv->qfpcorrected); - -@@ -402,12 +401,10 @@ static int qfprom_probe(struct platform_ - priv->qfpraw = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->qfpraw)) - return PTR_ERR(priv->qfpraw); -- res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -- priv->qfpconf = devm_ioremap_resource(dev, res); -+ priv->qfpconf = devm_platform_ioremap_resource(pdev, 2); - if (IS_ERR(priv->qfpconf)) - return PTR_ERR(priv->qfpconf); -- res = platform_get_resource(pdev, IORESOURCE_MEM, 3); -- priv->qfpsecurity = devm_ioremap_resource(dev, res); -+ priv->qfpsecurity = devm_platform_ioremap_resource(pdev, 3); - if (IS_ERR(priv->qfpsecurity)) - return PTR_ERR(priv->qfpsecurity); - -@@ -427,12 +424,8 @@ static int qfprom_probe(struct platform_ - return PTR_ERR(priv->vcc); - - priv->secclk = devm_clk_get(dev, "core"); -- if (IS_ERR(priv->secclk)) { -- ret = PTR_ERR(priv->secclk); -- if (ret != -EPROBE_DEFER) -- dev_err(dev, "Error getting clock: %d\n", ret); -- return ret; -- } -+ if (IS_ERR(priv->secclk)) -+ return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); - - /* Only enable writing if we have SoC data. */ - if (priv->soc_data) diff --git a/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch b/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch deleted file mode 100644 index 3e328a4c99..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6ac41c556e22a0d7d267c9b9d48681d73af4b368 Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Wed, 23 Aug 2023 14:27:31 +0100 -Subject: [PATCH] nvmem: uniphier: Use devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: Yangtao Li -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230823132744.350618-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/uniphier-efuse.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/nvmem/uniphier-efuse.c -+++ b/drivers/nvmem/uniphier-efuse.c -@@ -41,8 +41,7 @@ static int uniphier_efuse_probe(struct p - if (!priv) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- priv->base = devm_ioremap_resource(dev, res); -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch deleted file mode 100644 index acbe18e270..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch +++ /dev/null @@ -1,133 +0,0 @@ -From c8efcf7a86ebf2ff48584d270b3070a7075bc345 Mon Sep 17 00:00:00 2001 -From: Richard Alpe -Date: Mon, 10 Apr 2023 10:20:51 +0200 -Subject: [PATCH] nvmem: add new NXP QorIQ eFuse driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add SFP (Security Fuse Processor) read support for NXP (Freescale) -QorIQ series SOC's. - -This patch adds support for the T1023 SOC using the SFP offset from -the existing T1023 device tree. In theory this should also work for -T1024, T1014 and T1013 which uses the same SFP base offset. - -Signed-off-by: Richard Alpe -Reviewed-by: Niklas Söderlund -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 12 ++++++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/qoriq-efuse.c | 78 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 92 insertions(+) - create mode 100644 drivers/nvmem/qoriq-efuse.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -392,4 +392,16 @@ config NVMEM_ZYNQMP - - If sure, say yes. If unsure, say no. - -+config NVMEM_QORIQ_EFUSE -+ tristate "NXP QorIQ eFuse support" -+ depends on PPC_85xx || COMPILE_TEST -+ depends on HAS_IOMEM -+ help -+ This driver provides read support for the eFuses (SFP) on NXP QorIQ -+ series SoC's. This includes secure boot settings, the globally unique -+ NXP ID 'FUIDR' and the OEM unique ID 'OUIDR'. -+ -+ This driver can also be built as a module. If so, the module -+ will be called nvmem_qoriq_efuse. -+ - endif ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -77,3 +77,5 @@ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvme - nvmem-vf610-ocotp-y := vf610-ocotp.o - obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o - nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o -+obj-$(CONFIG_NVMEM_QORIQ_EFUSE) += nvmem-qoriq-efuse.o -+nvmem-qoriq-efuse-y := qoriq-efuse.o ---- /dev/null -+++ b/drivers/nvmem/qoriq-efuse.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2023 Westermo Network Technologies AB -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct qoriq_efuse_priv { -+ void __iomem *base; -+}; -+ -+static int qoriq_efuse_read(void *context, unsigned int offset, void *val, -+ size_t bytes) -+{ -+ struct qoriq_efuse_priv *priv = context; -+ -+ /* .stride = 4 so offset is guaranteed to be aligned */ -+ __ioread32_copy(val, priv->base + offset, bytes / 4); -+ -+ /* Ignore trailing bytes (there shouldn't be any) */ -+ -+ return 0; -+} -+ -+static int qoriq_efuse_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config config = { -+ .dev = &pdev->dev, -+ .read_only = true, -+ .reg_read = qoriq_efuse_read, -+ .stride = sizeof(u32), -+ .word_size = sizeof(u32), -+ .name = "qoriq_efuse_read", -+ .id = NVMEM_DEVID_AUTO, -+ .root_only = true, -+ }; -+ struct qoriq_efuse_priv *priv; -+ struct nvmem_device *nvmem; -+ struct resource *res; -+ -+ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ config.size = resource_size(res); -+ config.priv = priv; -+ nvmem = devm_nvmem_register(config.dev, &config); -+ -+ return PTR_ERR_OR_ZERO(nvmem); -+} -+ -+static const struct of_device_id qoriq_efuse_of_match[] = { -+ { .compatible = "fsl,t1023-sfp", }, -+ {/* sentinel */}, -+}; -+MODULE_DEVICE_TABLE(of, qoriq_efuse_of_match); -+ -+static struct platform_driver qoriq_efuse_driver = { -+ .probe = qoriq_efuse_probe, -+ .driver = { -+ .name = "qoriq-efuse", -+ .of_match_table = qoriq_efuse_of_match, -+ }, -+}; -+module_platform_driver(qoriq_efuse_driver); -+ -+MODULE_AUTHOR("Richard Alpe "); -+MODULE_DESCRIPTION("NXP QorIQ Security Fuse Processor (SFP) Reader"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch b/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch deleted file mode 100644 index 67f30e34a2..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9d53d595f688c9837e88a919229cc61a165c7b9e Mon Sep 17 00:00:00 2001 -From: Diederik de Haas -Date: Mon, 24 Jul 2023 13:36:22 +0200 -Subject: [PATCH] nvmem: Kconfig: Fix typo "drive" -> "driver" - -Fix typo where "driver" was meant instead of "drive". -While at it, also capitalize "OTP". - -Signed-off-by: Diederik de Haas -Reviewed-by: Heiko Stuebner -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -247,7 +247,7 @@ config NVMEM_ROCKCHIP_EFUSE - depends on ARCH_ROCKCHIP || COMPILE_TEST - depends on HAS_IOMEM - help -- This is a simple drive to dump specified values of Rockchip SoC -+ This is a simple driver to dump specified values of Rockchip SoC - from eFuse, such as cpu-leakage. - - This driver can also be built as a module. If so, the module -@@ -258,8 +258,8 @@ config NVMEM_ROCKCHIP_OTP - depends on ARCH_ROCKCHIP || COMPILE_TEST - depends on HAS_IOMEM - help -- This is a simple drive to dump specified values of Rockchip SoC -- from otp, such as cpu-leakage. -+ This is a simple driver to dump specified values of Rockchip SoC -+ from OTP, such as cpu-leakage. - - This driver can also be built as a module. If so, the module - will be called nvmem_rockchip_otp. diff --git a/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch b/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch deleted file mode 100644 index af4a2926dc..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0a9ec38c47c1ca4528aa058e2b9ea61901a7e632 Mon Sep 17 00:00:00 2001 -From: Komal Bajaj -Date: Tue, 1 Aug 2023 12:10:25 +0530 -Subject: [PATCH] nvmem: sec-qfprom: Add Qualcomm secure QFPROM support - -For some of the Qualcomm SoC's, it is possible that -some of the fuse regions or entire qfprom region is -protected from non-secure access. In such situations, -the OS will have to use secure calls to read the region. -With that motivation, add secure qfprom driver. - -Signed-off-by: Komal Bajaj -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/Kconfig | 13 ++++++ - drivers/nvmem/Makefile | 2 + - drivers/nvmem/sec-qfprom.c | 96 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 111 insertions(+) - create mode 100644 drivers/nvmem/sec-qfprom.c - ---- a/drivers/nvmem/Kconfig -+++ b/drivers/nvmem/Kconfig -@@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM - This driver can also be built as a module. If so, the module - will be called nvmem_qfprom. - -+config NVMEM_QCOM_SEC_QFPROM -+ tristate "QCOM SECURE QFPROM Support" -+ depends on ARCH_QCOM || COMPILE_TEST -+ depends on HAS_IOMEM -+ depends on OF -+ select QCOM_SCM -+ help -+ Say y here to enable secure QFPROM support. The secure QFPROM provides access -+ functions for QFPROM data to rest of the drivers via nvmem interface. -+ -+ This driver can also be built as a module. If so, the module will be called -+ nvmem_sec_qfprom. -+ - config NVMEM_RAVE_SP_EEPROM - tristate "Rave SP EEPROM Support" - depends on RAVE_SP_CORE ---- a/drivers/nvmem/Makefile -+++ b/drivers/nvmem/Makefile -@@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvme - nvmem-nintendo-otp-y := nintendo-otp.o - obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o - nvmem_qfprom-y := qfprom.o -+obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o -+nvmem_sec_qfprom-y := sec-qfprom.o - obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o - nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o - obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o ---- /dev/null -+++ b/drivers/nvmem/sec-qfprom.c -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * struct sec_qfprom - structure holding secure qfprom attributes -+ * -+ * @base: starting physical address for secure qfprom corrected address space. -+ * @dev: qfprom device structure. -+ */ -+struct sec_qfprom { -+ phys_addr_t base; -+ struct device *dev; -+}; -+ -+static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) -+{ -+ struct sec_qfprom *priv = context; -+ unsigned int i; -+ u8 *val = _val; -+ u32 read_val; -+ u8 *tmp; -+ -+ for (i = 0; i < bytes; i++, reg++) { -+ if (i == 0 || reg % 4 == 0) { -+ if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) { -+ dev_err(priv->dev, "Couldn't access fuse register\n"); -+ return -EINVAL; -+ } -+ tmp = (u8 *)&read_val; -+ } -+ -+ val[i] = tmp[reg & 3]; -+ } -+ -+ return 0; -+} -+ -+static int sec_qfprom_probe(struct platform_device *pdev) -+{ -+ struct nvmem_config econfig = { -+ .name = "sec-qfprom", -+ .stride = 1, -+ .word_size = 1, -+ .id = NVMEM_DEVID_AUTO, -+ .reg_read = sec_qfprom_reg_read, -+ }; -+ struct device *dev = &pdev->dev; -+ struct nvmem_device *nvmem; -+ struct sec_qfprom *priv; -+ struct resource *res; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -EINVAL; -+ -+ priv->base = res->start; -+ -+ econfig.size = resource_size(res); -+ econfig.dev = dev; -+ econfig.priv = priv; -+ -+ priv->dev = dev; -+ -+ nvmem = devm_nvmem_register(dev, &econfig); -+ -+ return PTR_ERR_OR_ZERO(nvmem); -+} -+ -+static const struct of_device_id sec_qfprom_of_match[] = { -+ { .compatible = "qcom,sec-qfprom" }, -+ {/* sentinel */}, -+}; -+MODULE_DEVICE_TABLE(of, sec_qfprom_of_match); -+ -+static struct platform_driver qfprom_driver = { -+ .probe = sec_qfprom_probe, -+ .driver = { -+ .name = "qcom_sec_qfprom", -+ .of_match_table = sec_qfprom_of_match, -+ }, -+}; -+module_platform_driver(qfprom_driver); -+MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch b/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch deleted file mode 100644 index dab8ec2c24..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c32f2186acc9abb4d766361255d7ddf07d15eeb2 Mon Sep 17 00:00:00 2001 -From: Atul Raut -Date: Sun, 30 Jul 2023 15:39:15 -0700 -Subject: [PATCH] nvmem: u-boot-env:: Replace zero-length array with - DECLARE_FLEX_ARRAY() helper - -We are moving toward replacing zero-length arrays with C99 flexible-array -members since they are deprecated. Therefore, the new DECLARE_FLEX_ARRAY() -helper macro should be used to replace the zero-length array declaration. - -This fixes warnings such as: -./drivers/nvmem/u-boot-env.c:50:9-13: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays) - -Signed-off-by: Atul Raut -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/u-boot-env.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/nvmem/u-boot-env.c -+++ b/drivers/nvmem/u-boot-env.c -@@ -47,7 +47,7 @@ struct u_boot_env_image_broadcom { - __le32 magic; - __le32 len; - __le32 crc32; -- uint8_t data[0]; -+ DECLARE_FLEX_ARRAY(uint8_t, data); - } __packed; - - static int u_boot_env_read(void *context, unsigned int offset, void *val, diff --git a/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch b/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch deleted file mode 100644 index f9532f39c3..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 104af6a5b199eb4dc7970d1304aef38ac5a6ed54 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:26 +0200 -Subject: [PATCH] nvmem: core: Create all cells before adding the nvmem device - -Let's pack all the cells creation in one place, so they are all created -before we add the nvmem device. - -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -998,17 +998,17 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -- dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); -- -- rval = device_add(&nvmem->dev); -+ rval = nvmem_add_cells_from_fixed_layout(nvmem); - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_fixed_layout(nvmem); -+ rval = nvmem_add_cells_from_layout(nvmem); - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_layout(nvmem); -+ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); -+ -+ rval = device_add(&nvmem->dev); - if (rval) - goto err_remove_cells; - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch b/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch deleted file mode 100644 index 8f64d0c28b..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6c7f48ea2e663b679aa8e60d8d8e1e6306a644f9 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:27 +0200 -Subject: [PATCH] nvmem: core: Return NULL when no nvmem layout is found - -Currently, of_nvmem_layout_get_container() returns NULL on error, or an -error pointer if either CONFIG_NVMEM or CONFIG_OF is turned off. We -should likely avoid this kind of mix for two reasons: to clarify the -intend and anyway fix the !CONFIG_OF which will likely always if we use -this helper somewhere else. Let's just return NULL when no layout is -found, we don't need an error value here. - -Link: https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/ -Fixes: 266570f496b9 ("nvmem: core: introduce NVMEM layouts") -Reported-by: kernel test robot -Reported-by: Dan Carpenter -Closes: https://lore.kernel.org/r/202308030002.DnSFOrMB-lkp@intel.com/ -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - include/linux/nvmem-consumer.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -256,7 +256,7 @@ static inline struct nvmem_device *of_nv - static inline struct device_node * - of_nvmem_layout_get_container(struct nvmem_device *nvmem) - { -- return ERR_PTR(-EOPNOTSUPP); -+ return NULL; - } - #endif /* CONFIG_NVMEM && CONFIG_OF */ - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch b/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch deleted file mode 100644 index 28d8bba194..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch +++ /dev/null @@ -1,29 +0,0 @@ -From b8257f61b4ddac6d7d0e19a5a4e8b07afb3b4ed3 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:28 +0200 -Subject: [PATCH] nvmem: core: Do not open-code existing functions - -Use of_nvmem_layout_get_container() instead of hardcoding it. - -Signed-off-by: Miquel Raynal -Reviewed-by: Michael Walle -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -786,10 +786,10 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste - - static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) - { -- struct device_node *layout_np, *np = nvmem->dev.of_node; -+ struct device_node *layout_np; - struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); - -- layout_np = of_get_child_by_name(np, "nvmem-layout"); -+ layout_np = of_nvmem_layout_get_container(nvmem); - if (!layout_np) - return NULL; - diff --git a/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch b/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch deleted file mode 100644 index b62a0e18da..0000000000 --- a/target/linux/generic/backport-6.6/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0991afbe4b1805e7f0113ef10d7c5f0698a739e4 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 8 Aug 2023 08:29:29 +0200 -Subject: [PATCH] nvmem: core: Notify when a new layout is registered - -Tell listeners a new layout was introduced and is now available. - -Signed-off-by: Miquel Raynal -Signed-off-by: Srinivas Kandagatla ---- - drivers/nvmem/core.c | 4 ++++ - include/linux/nvmem-consumer.h | 2 ++ - 2 files changed, 6 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -772,12 +772,16 @@ int __nvmem_layout_register(struct nvmem - list_add(&layout->node, &nvmem_layouts); - spin_unlock(&nvmem_layout_lock); - -+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); -+ - return 0; - } - EXPORT_SYMBOL_GPL(__nvmem_layout_register); - - void nvmem_layout_unregister(struct nvmem_layout *layout) - { -+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); -+ - spin_lock(&nvmem_layout_lock); - list_del(&layout->node); - spin_unlock(&nvmem_layout_lock); ---- a/include/linux/nvmem-consumer.h -+++ b/include/linux/nvmem-consumer.h -@@ -43,6 +43,8 @@ enum { - NVMEM_REMOVE, - NVMEM_CELL_ADD, - NVMEM_CELL_REMOVE, -+ NVMEM_LAYOUT_ADD, -+ NVMEM_LAYOUT_REMOVE, - }; - - #if IS_ENABLED(CONFIG_NVMEM) diff --git a/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch b/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch deleted file mode 100644 index e17be439b2..0000000000 --- a/target/linux/generic/backport-6.6/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch +++ /dev/null @@ -1,29 +0,0 @@ -From a75b58a46423cfd9b1f73581f4bd2ac2ae743996 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Wed, 2 Aug 2023 18:07:45 +0200 -Subject: [PATCH 1/6] leds: turris-omnia: Use sysfs_emit() instead of sprintf() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use the dedicated sysfs_emit() function instead of sprintf() in sysfs -attribute accessor brightness_show(). - -Signed-off-by: Marek Behún -Link: https://lore.kernel.org/r/20230802160748.11208-4-kabel@kernel.org -Signed-off-by: Lee Jones ---- - drivers/leds/leds-turris-omnia.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/leds/leds-turris-omnia.c -+++ b/drivers/leds/leds-turris-omnia.c -@@ -194,7 +194,7 @@ static ssize_t brightness_show(struct de - if (ret < 0) - return ret; - -- return sprintf(buf, "%d\n", ret); -+ return sysfs_emit(buf, "%d\n", ret); - } - - static ssize_t brightness_store(struct device *dev, struct device_attribute *a, diff --git a/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch b/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch deleted file mode 100644 index bd5ceaabf7..0000000000 --- a/target/linux/generic/backport-6.6/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b7c1e53751cb3990153084f31c41f25fde3b629c Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Fri, 24 Nov 2023 20:38:14 +0100 -Subject: [PATCH] nvmem: Do not expect fixed layouts to grab a layout driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Two series lived in parallel for some time, which led to this situation: -- The nvmem-layout container is used for dynamic layouts -- We now expect fixed layouts to also use the nvmem-layout container but -this does not require any additional driver, the support is built-in the -nvmem core. - -Ensure we don't refuse to probe for wrong reasons. - -Fixes: 27f699e578b1 ("nvmem: core: add support for fixed cells *layout*") -Cc: stable@vger.kernel.org -Reported-by: Luca Ceresoli -Signed-off-by: Miquel Raynal -Tested-by: Rafał Miłecki -Tested-by: Luca Ceresoli -Reviewed-by: Luca Ceresoli - -Link: https://lore.kernel.org/r/20231124193814.360552-1-miquel.raynal@bootlin.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/core.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -797,6 +797,12 @@ static struct nvmem_layout *nvmem_layout - if (!layout_np) - return NULL; - -+ /* Fixed layouts don't have a matching driver */ -+ if (of_device_is_compatible(layout_np, "fixed-layout")) { -+ of_node_put(layout_np); -+ return NULL; -+ } -+ - /* - * In case the nvmem device was built-in while the layout was built as a - * module, we shall manually request the layout driver loading otherwise diff --git a/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch b/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch deleted file mode 100644 index d49a20599d..0000000000 --- a/target/linux/generic/backport-6.6/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 1e37bf84afacd5ba17b7a13a18ca2bc78aff05c0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 15 Dec 2023 11:13:58 +0000 -Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This driver uses MMIO access for reading NVRAM from a flash device. -Underneath there is a flash controller that reads data and provides -mapping window. - -Using MMIO interface affects controller configuration and may break real -controller driver. It was reported by multiple users of devices with -NVRAM stored on NAND. - -Modify driver to read & cache NVRAM content during init and use that -copy to provide NVMEM data when requested. On NAND flashes due to their -alignment NVRAM partitions can be quite big (1 MiB and more) while -actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid -allocating so much memory check for actual data length. - -Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/ -Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM") -Cc: -Cc: Arınç ÜNAL -Cc: Florian Fainelli -Cc: Scott Branden -Signed-off-by: Rafał Miłecki -Acked-by: Arınç ÜNAL -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20231215111358.316727-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/brcm_nvram.c | 134 ++++++++++++++++++++++++++----------- - 1 file changed, 94 insertions(+), 40 deletions(-) - ---- a/drivers/nvmem/brcm_nvram.c -+++ b/drivers/nvmem/brcm_nvram.c -@@ -17,9 +17,23 @@ - - #define NVRAM_MAGIC "FLSH" - -+/** -+ * struct brcm_nvram - driver state internal struct -+ * -+ * @dev: NVMEM device pointer -+ * @nvmem_size: Size of the whole space available for NVRAM -+ * @data: NVRAM data copy stored to avoid poking underlaying flash controller -+ * @data_len: NVRAM data size -+ * @padding_byte: Padding value used to fill remaining space -+ * @cells: Array of discovered NVMEM cells -+ * @ncells: Number of elements in cells -+ */ - struct brcm_nvram { - struct device *dev; -- void __iomem *base; -+ size_t nvmem_size; -+ uint8_t *data; -+ size_t data_len; -+ uint8_t padding_byte; - struct nvmem_cell_info *cells; - int ncells; - }; -@@ -36,10 +50,47 @@ static int brcm_nvram_read(void *context - size_t bytes) - { - struct brcm_nvram *priv = context; -- u8 *dst = val; -+ size_t to_copy; -+ -+ if (offset + bytes > priv->data_len) -+ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0); -+ else -+ to_copy = bytes; -+ -+ memcpy(val, priv->data + offset, to_copy); -+ -+ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy); -+ -+ return 0; -+} -+ -+static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev) -+{ -+ struct resource *res; -+ void __iomem *base; -+ -+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ priv->nvmem_size = resource_size(res); -+ -+ priv->padding_byte = readb(base + priv->nvmem_size - 1); -+ for (priv->data_len = priv->nvmem_size; -+ priv->data_len; -+ priv->data_len--) { -+ if (readb(base + priv->data_len - 1) != priv->padding_byte) -+ break; -+ } -+ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len); - -- while (bytes--) -- *dst++ = readb(priv->base + offset++); -+ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL); -+ if (!priv->data) -+ return -ENOMEM; -+ -+ memcpy_fromio(priv->data, base, priv->data_len); -+ -+ bcm47xx_nvram_init_from_iomem(base, priv->data_len); - - return 0; - } -@@ -67,8 +118,13 @@ static int brcm_nvram_add_cells(struct b - size_t len) - { - struct device *dev = priv->dev; -- char *var, *value, *eq; -+ char *var, *value; -+ uint8_t tmp; - int idx; -+ int err = 0; -+ -+ tmp = priv->data[len - 1]; -+ priv->data[len - 1] = '\0'; - - priv->ncells = 0; - for (var = data + sizeof(struct brcm_nvram_header); -@@ -78,67 +134,68 @@ static int brcm_nvram_add_cells(struct b - } - - priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); -- if (!priv->cells) -- return -ENOMEM; -+ if (!priv->cells) { -+ err = -ENOMEM; -+ goto out; -+ } - - for (var = data + sizeof(struct brcm_nvram_header), idx = 0; - var < (char *)data + len && *var; - var = value + strlen(value) + 1, idx++) { -+ char *eq, *name; -+ - eq = strchr(var, '='); - if (!eq) - break; - *eq = '\0'; -+ name = devm_kstrdup(dev, var, GFP_KERNEL); -+ *eq = '='; -+ if (!name) { -+ err = -ENOMEM; -+ goto out; -+ } - value = eq + 1; - -- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); -- if (!priv->cells[idx].name) -- return -ENOMEM; -+ priv->cells[idx].name = name; - priv->cells[idx].offset = value - (char *)data; - priv->cells[idx].bytes = strlen(value); - priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); -- if (!strcmp(var, "et0macaddr") || -- !strcmp(var, "et1macaddr") || -- !strcmp(var, "et2macaddr")) { -+ if (!strcmp(name, "et0macaddr") || -+ !strcmp(name, "et1macaddr") || -+ !strcmp(name, "et2macaddr")) { - priv->cells[idx].raw_len = strlen(value); - priv->cells[idx].bytes = ETH_ALEN; - priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; - } - } - -- return 0; -+out: -+ priv->data[len - 1] = tmp; -+ return err; - } - - static int brcm_nvram_parse(struct brcm_nvram *priv) - { -+ struct brcm_nvram_header *header = (struct brcm_nvram_header *)priv->data; - struct device *dev = priv->dev; -- struct brcm_nvram_header header; -- uint8_t *data; - size_t len; - int err; - -- memcpy_fromio(&header, priv->base, sizeof(header)); -- -- if (memcmp(header.magic, NVRAM_MAGIC, 4)) { -+ if (memcmp(header->magic, NVRAM_MAGIC, 4)) { - dev_err(dev, "Invalid NVRAM magic\n"); - return -EINVAL; - } - -- len = le32_to_cpu(header.len); -- -- data = kzalloc(len, GFP_KERNEL); -- if (!data) -- return -ENOMEM; -- -- memcpy_fromio(data, priv->base, len); -- data[len - 1] = '\0'; -- -- err = brcm_nvram_add_cells(priv, data, len); -- if (err) { -- dev_err(dev, "Failed to add cells: %d\n", err); -- return err; -+ len = le32_to_cpu(header->len); -+ if (len > priv->nvmem_size) { -+ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, -+ priv->nvmem_size); -+ return -EINVAL; - } - -- kfree(data); -+ err = brcm_nvram_add_cells(priv, priv->data, len); -+ if (err) -+ dev_err(dev, "Failed to add cells: %d\n", err); - - return 0; - } -@@ -150,7 +207,6 @@ static int brcm_nvram_probe(struct platf - .reg_read = brcm_nvram_read, - }; - struct device *dev = &pdev->dev; -- struct resource *res; - struct brcm_nvram *priv; - int err; - -@@ -159,21 +215,19 @@ static int brcm_nvram_probe(struct platf - return -ENOMEM; - priv->dev = dev; - -- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -- if (IS_ERR(priv->base)) -- return PTR_ERR(priv->base); -+ err = brcm_nvram_copy_data(priv, pdev); -+ if (err) -+ return err; - - err = brcm_nvram_parse(priv); - if (err) - return err; - -- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); -- - config.dev = dev; - config.cells = priv->cells; - config.ncells = priv->ncells; - config.priv = priv; -- config.size = resource_size(res); -+ config.size = priv->nvmem_size; - - return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); - } diff --git a/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch b/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch deleted file mode 100644 index 3b68403690..0000000000 --- a/target/linux/generic/backport-6.6/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4bb7aac70b5d8a4bddf4ee0791b834f9f56883d2 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Thu, 20 Apr 2023 10:45:51 +0200 -Subject: [PATCH] net: phy: fix circular LEDS_CLASS dependencies - -The CONFIG_PHYLIB symbol is selected by a number of device drivers that -need PHY support, but it now has a dependency on CONFIG_LEDS_CLASS, -which may not be enabled, causing build failures. - -Avoid the risk of missing and circular dependencies by guarding the -phylib LED support itself in another Kconfig symbol that can only be -enabled if the dependency is met. - -This could be made a hidden symbol and always enabled when both CONFIG_OF -and CONFIG_LEDS_CLASS are reachable from the phylib, but there may be an -advantage in having users see this option when they have a misconfigured -kernel without built-in LED support. - -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Arnd Bergmann -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230420084624.3005701-1-arnd@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/Kconfig | 9 ++++++++- - drivers/net/phy/phy_device.c | 3 ++- - 2 files changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -18,7 +18,6 @@ menuconfig PHYLIB - depends on NETDEVICES - select MDIO_DEVICE - select MDIO_DEVRES -- depends on LEDS_CLASS || LEDS_CLASS=n - help - Ethernet controllers are usually attached to PHY - devices. This option provides infrastructure for -@@ -45,6 +44,14 @@ config LED_TRIGGER_PHY - Mbps OR Gbps OR link - for any speed known to the PHY. - -+config PHYLIB_LEDS -+ bool "Support probing LEDs from device tree" -+ depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB -+ depends on OF -+ default y -+ help -+ When LED class support is enabled, phylib can automatically -+ probe LED setting from device tree. - - config FIXED_PHY - tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs" ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3314,7 +3314,8 @@ static int phy_probe(struct device *dev) - /* Get the LEDs from the device tree, and instantiate standard - * LEDs for them. - */ -- err = of_phy_leds(phydev); -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ err = of_phy_leds(phydev); - - out: - /* Re-assert the reset signal on error */ diff --git a/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch b/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch deleted file mode 100644 index 622bb9e94a..0000000000 --- a/target/linux/generic/backport-6.6/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch +++ /dev/null @@ -1,43 +0,0 @@ -From aed8fdad2152d946add50bec00a6b07c457bdcdf Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Mon, 24 Apr 2023 16:16:48 +0200 -Subject: [PATCH] net: phy: Fix reading LED reg property - -'reg' is always encoded in 32 bits, thus it has to be read using the -function with the corresponding bit width. - -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Alexander Stein -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Link: https://lore.kernel.org/r/20230424141648.317944-1-alexander.stein@ew.tq-group.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_device.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3075,6 +3075,7 @@ static int of_phy_led(struct phy_device - struct led_init_data init_data = {}; - struct led_classdev *cdev; - struct phy_led *phyled; -+ u32 index; - int err; - - phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); -@@ -3084,10 +3085,13 @@ static int of_phy_led(struct phy_device - cdev = &phyled->led_cdev; - phyled->phydev = phydev; - -- err = of_property_read_u8(led, "reg", &phyled->index); -+ err = of_property_read_u32(led, "reg", &index); - if (err) - return err; -+ if (index > U8_MAX) -+ return -EINVAL; - -+ phyled->index = index; - if (phydev->drv->led_brightness_set) - cdev->brightness_set_blocking = phy_led_set_brightness; - if (phydev->drv->led_blink_set) diff --git a/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch b/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch deleted file mode 100644 index 80197e963b..0000000000 --- a/target/linux/generic/backport-6.6/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch +++ /dev/null @@ -1,67 +0,0 @@ -From c938ab4da0eb1620ae3243b0b24c572ddfc318fc Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Sat, 17 Jun 2023 17:55:00 +0200 -Subject: [PATCH] net: phy: Manual remove LEDs to ensure correct ordering - -If the core is left to remove the LEDs via devm_, it is performed too -late, after the PHY driver is removed from the PHY. This results in -dereferencing a NULL pointer when the LED core tries to turn the LED -off before destroying the LED. - -Manually unregister the LEDs at a safe point in phy_remove. - -Cc: stable@vger.kernel.org -Reported-by: Florian Fainelli -Suggested-by: Florian Fainelli -Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs") -Signed-off-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/phy_device.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3068,6 +3068,15 @@ static int phy_led_blink_set(struct led_ - return err; - } - -+static void phy_leds_unregister(struct phy_device *phydev) -+{ -+ struct phy_led *phyled; -+ -+ list_for_each_entry(phyled, &phydev->leds, list) { -+ led_classdev_unregister(&phyled->led_cdev); -+ } -+} -+ - static int of_phy_led(struct phy_device *phydev, - struct device_node *led) - { -@@ -3101,7 +3110,7 @@ static int of_phy_led(struct phy_device - init_data.fwnode = of_fwnode_handle(led); - init_data.devname_mandatory = true; - -- err = devm_led_classdev_register_ext(dev, cdev, &init_data); -+ err = led_classdev_register_ext(dev, cdev, &init_data); - if (err) - return err; - -@@ -3130,6 +3139,7 @@ static int of_phy_leds(struct phy_device - err = of_phy_led(phydev, led); - if (err) { - of_node_put(led); -+ phy_leds_unregister(phydev); - return err; - } - } -@@ -3335,6 +3345,9 @@ static int phy_remove(struct device *dev - - cancel_delayed_work_sync(&phydev->state_queue); - -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ phy_leds_unregister(phydev); -+ - phydev->state = PHY_DOWN; - - sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch b/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch deleted file mode 100644 index 609115b04a..0000000000 --- a/target/linux/generic/backport-6.6/824-v6.5-leds-trigger-netdev-Remove-NULL-check-before-dev_-pu.patch +++ /dev/null @@ -1,44 +0,0 @@ -From af7320ecae0ce646fd2c4a88341a3fbc243553da Mon Sep 17 00:00:00 2001 -From: Yang Li -Date: Thu, 11 May 2023 15:08:20 +0800 -Subject: [PATCH] leds: trigger: netdev: Remove NULL check before dev_{put, - hold} - -The call netdev_{put, hold} of dev_{put, hold} will check NULL, -so there is no need to check before using dev_{put, hold}, -remove it to silence the warnings: - -./drivers/leds/trigger/ledtrig-netdev.c:291:3-10: WARNING: NULL check before dev_{put, hold} functions is not needed. -./drivers/leds/trigger/ledtrig-netdev.c:401:2-9: WARNING: NULL check before dev_{put, hold} functions is not needed. - -Reported-by: Abaci Robot -Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=4929 -Signed-off-by: Yang Li -Link: https://lore.kernel.org/r/20230511070820.52731-1-yang.lee@linux.alibaba.com -Signed-off-by: Lee Jones ---- - drivers/leds/trigger/ledtrig-netdev.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -462,8 +462,7 @@ static int netdev_trig_notify(struct not - get_device_state(trigger_data); - fallthrough; - case NETDEV_REGISTER: -- if (trigger_data->net_dev) -- dev_put(trigger_data->net_dev); -+ dev_put(trigger_data->net_dev); - dev_hold(dev); - trigger_data->net_dev = dev; - break; -@@ -594,8 +593,7 @@ static void netdev_trig_deactivate(struc - - cancel_delayed_work_sync(&trigger_data->work); - -- if (trigger_data->net_dev) -- dev_put(trigger_data->net_dev); -+ dev_put(trigger_data->net_dev); - - kfree(trigger_data); - } diff --git a/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch b/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch deleted file mode 100644 index 2f7a6ced90..0000000000 --- a/target/linux/generic/backport-6.6/825-v6.5-leds-trigger-netdev-uninitialized-variable-in-netdev.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 97c5209b3d374a25ebdb4c2ea9e9c1b121768da0 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 14 Jun 2023 10:03:59 +0300 -Subject: [PATCH] leds: trigger: netdev: uninitialized variable in - netdev_trig_activate() - -The qca8k_cled_hw_control_get() function which implements ->hw_control_get -sets the appropriate bits but does not clear them. This leads to an -uninitialized variable bug. Fix this by setting mode to zero at the -start. - -Fixes: e0256648c831 ("net: dsa: qca8k: implement hw_control ops") -Signed-off-by: Dan Carpenter -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Signed-off-by: David S. Miller ---- - drivers/leds/trigger/ledtrig-netdev.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -538,7 +538,7 @@ static void netdev_trig_work(struct work - static int netdev_trig_activate(struct led_classdev *led_cdev) - { - struct led_netdev_data *trigger_data; -- unsigned long mode; -+ unsigned long mode = 0; - struct device *dev; - int rc; - diff --git a/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch b/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch deleted file mode 100644 index dedf84c64b..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-01-led-trig-netdev-Fix-requesting-offload-device.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 7df1f14c04cbb1950e79c19793420f87227c3e80 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:33 +0200 -Subject: [PATCH 1/4] led: trig: netdev: Fix requesting offload device - -When the netdev trigger is activates, it tries to determine what -device the LED blinks for, and what the current blink mode is. - -The documentation for hw_control_get() says: - - * Return 0 on success, a negative error number on failing parsing the - * initial mode. Error from this function is NOT FATAL as the device - * may be in a not supported initial state by the attached LED trigger. - */ - -For the Marvell PHY and the Armada 370-rd board, the initial LED blink -mode is not supported by the trigger, so it returns an error. This -resulted in not getting the device the LED is blinking for. As a -result, the device is unknown and offloaded is never performed. - -Change to condition to always get the device if offloading is -supported, and reduce the scope of testing for an error from -hw_control_get() to skip setting trigger internal state if there is an -error. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-2-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -564,15 +564,17 @@ static int netdev_trig_activate(struct l - /* Check if hw control is active by default on the LED. - * Init already enabled mode in hw control. - */ -- if (supports_hw_control(led_cdev) && -- !led_cdev->hw_control_get(led_cdev, &mode)) { -+ if (supports_hw_control(led_cdev)) { - dev = led_cdev->hw_control_get_device(led_cdev); - if (dev) { - const char *name = dev_name(dev); - - set_device_name(trigger_data, name, strlen(name)); - trigger_data->hw_control = true; -- trigger_data->mode = mode; -+ -+ rc = led_cdev->hw_control_get(led_cdev, &mode); -+ if (!rc) -+ trigger_data->mode = mode; - } - } - diff --git a/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch deleted file mode 100644 index 505513a53f..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:34 +0200 -Subject: [PATCH 2/4] net: phy: phy_device: Call into the PHY driver to set LED - offload - -Linux LEDs can be requested to perform hardware accelerated blinking -to indicate link, RX, TX etc. Pass the rules for blinking to the PHY -driver, if it implements the ops needed to determine if a given -pattern can be offloaded, to offload it, and what the current offload -is. Additionally implement the op needed to get what device the LED is -for. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-3-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++ - include/linux/phy.h | 33 +++++++++++++++++ - 2 files changed, 101 insertions(+) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3068,6 +3068,61 @@ static int phy_led_blink_set(struct led_ - return err; - } - -+static __maybe_unused struct device * -+phy_led_hw_control_get_device(struct led_classdev *led_cdev) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ -+ if (phydev->attached_dev) -+ return &phydev->attached_dev->dev; -+ return NULL; -+} -+ -+static int __maybe_unused -+phy_led_hw_control_get(struct led_classdev *led_cdev, -+ unsigned long *rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ -+static int __maybe_unused -+phy_led_hw_control_set(struct led_classdev *led_cdev, -+ unsigned long rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ -+static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev, -+ unsigned long rules) -+{ -+ struct phy_led *phyled = to_phy_led(led_cdev); -+ struct phy_device *phydev = phyled->phydev; -+ int err; -+ -+ mutex_lock(&phydev->lock); -+ err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ - static void phy_leds_unregister(struct phy_device *phydev) - { - struct phy_led *phyled; -@@ -3105,6 +3160,19 @@ static int of_phy_led(struct phy_device - cdev->brightness_set_blocking = phy_led_set_brightness; - if (phydev->drv->led_blink_set) - cdev->blink_set = phy_led_blink_set; -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (phydev->drv->led_hw_is_supported && -+ phydev->drv->led_hw_control_set && -+ phydev->drv->led_hw_control_get) { -+ cdev->hw_control_is_supported = phy_led_hw_is_supported; -+ cdev->hw_control_set = phy_led_hw_control_set; -+ cdev->hw_control_get = phy_led_hw_control_get; -+ cdev->hw_control_trigger = "netdev"; -+ } -+ -+ cdev->hw_control_get_device = phy_led_hw_control_get_device; -+#endif - cdev->max_brightness = 1; - init_data.devicename = dev_name(&phydev->mdio.dev); - init_data.fwnode = of_fwnode_handle(led); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1026,6 +1026,39 @@ struct phy_driver { - int (*led_blink_set)(struct phy_device *dev, u8 index, - unsigned long *delay_on, - unsigned long *delay_off); -+ /** -+ * @led_hw_is_supported: Can the HW support the given rules. -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules The core is interested in these rules -+ * -+ * Return 0 if yes, -EOPNOTSUPP if not, or an error code. -+ */ -+ int (*led_hw_is_supported)(struct phy_device *dev, u8 index, -+ unsigned long rules); -+ /** -+ * @led_hw_control_set: Set the HW to control the LED -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules The rules used to control the LED -+ * -+ * Returns 0, or a an error code. -+ */ -+ int (*led_hw_control_set)(struct phy_device *dev, u8 index, -+ unsigned long rules); -+ /** -+ * @led_hw_control_get: Get how the HW is controlling the LED -+ * @dev: PHY device which has the LED -+ * @index: Which LED of the PHY device -+ * @rules Pointer to the rules used to control the LED -+ * -+ * Set *@rules to how the HW is currently blinking. Returns 0 -+ * on success, or a error code if the current blinking cannot -+ * be represented in rules, or some other error happens. -+ */ -+ int (*led_hw_control_get)(struct phy_device *dev, u8 index, -+ unsigned long *rules); -+ - }; - #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ - struct phy_driver, mdiodrv) diff --git a/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch b/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch deleted file mode 100644 index 1300583b66..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-03-net-phy-marvell-Add-support-for-offloading-LED-blink.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 460b0b648fab24f576c481424e0de5479ffb9786 Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:35 +0200 -Subject: [PATCH 3/4] net: phy: marvell: Add support for offloading LED - blinking - -Add the code needed to indicate if a given blinking pattern can be -offloaded, to offload a pattern and to try to return the current -pattern. - -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-4-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 281 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 281 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2893,6 +2893,272 @@ static int m88e1318_led_blink_set(struct - MII_88E1318S_PHY_LED_FUNC, reg); - } - -+struct marvell_led_rules { -+ int mode; -+ unsigned long rules; -+}; -+ -+static const struct marvell_led_rules marvell_led0[] = { -+ { -+ .mode = 0, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 5, -+ .rules = BIT(TRIGGER_NETDEV_TX), -+ }, -+ { -+ .mode = 6, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static const struct marvell_led_rules marvell_led1[] = { -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 2, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 6, -+ .rules = (BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000)), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static const struct marvell_led_rules marvell_led2[] = { -+ { -+ .mode = 0, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ }, -+ { -+ .mode = 1, -+ .rules = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 3, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 4, -+ .rules = (BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)), -+ }, -+ { -+ .mode = 5, -+ .rules = BIT(TRIGGER_NETDEV_TX), -+ }, -+ { -+ .mode = 6, -+ .rules = (BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_1000)), -+ }, -+ { -+ .mode = 7, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10), -+ }, -+ { -+ .mode = 8, -+ .rules = 0, -+ }, -+}; -+ -+static int marvell_find_led_mode(unsigned long rules, -+ const struct marvell_led_rules *marvell_rules, -+ int count, -+ int *mode) -+{ -+ int i; -+ -+ for (i = 0; i < count; i++) { -+ if (marvell_rules[i].rules == rules) { -+ *mode = marvell_rules[i].mode; -+ return 0; -+ } -+ } -+ return -EOPNOTSUPP; -+} -+ -+static int marvell_get_led_mode(u8 index, unsigned long rules, int *mode) -+{ -+ int ret; -+ -+ switch (index) { -+ case 0: -+ ret = marvell_find_led_mode(rules, marvell_led0, -+ ARRAY_SIZE(marvell_led0), mode); -+ break; -+ case 1: -+ ret = marvell_find_led_mode(rules, marvell_led1, -+ ARRAY_SIZE(marvell_led1), mode); -+ break; -+ case 2: -+ ret = marvell_find_led_mode(rules, marvell_led2, -+ ARRAY_SIZE(marvell_led2), mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int marvell_find_led_rules(unsigned long *rules, -+ const struct marvell_led_rules *marvell_rules, -+ int count, -+ int mode) -+{ -+ int i; -+ -+ for (i = 0; i < count; i++) { -+ if (marvell_rules[i].mode == mode) { -+ *rules = marvell_rules[i].rules; -+ return 0; -+ } -+ } -+ return -EOPNOTSUPP; -+} -+ -+static int marvell_get_led_rules(u8 index, unsigned long *rules, int mode) -+{ -+ int ret; -+ -+ switch (index) { -+ case 0: -+ ret = marvell_find_led_rules(rules, marvell_led0, -+ ARRAY_SIZE(marvell_led0), mode); -+ break; -+ case 1: -+ ret = marvell_find_led_rules(rules, marvell_led1, -+ ARRAY_SIZE(marvell_led1), mode); -+ break; -+ case 2: -+ ret = marvell_find_led_rules(rules, marvell_led2, -+ ARRAY_SIZE(marvell_led2), mode); -+ break; -+ default: -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int m88e1318_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ int mode, ret; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ ret = marvell_get_led_mode(index, rules, &mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int m88e1318_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ int mode, ret, reg; -+ -+ switch (index) { -+ case 0: -+ case 1: -+ case 2: -+ ret = marvell_get_led_mode(index, rules, &mode); -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ if (ret < 0) -+ return ret; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ reg &= ~(0xf << (4 * index)); -+ reg |= mode << (4 * index); -+ return phy_write_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC, reg); -+} -+ -+static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int mode, reg; -+ -+ if (index > 2) -+ return -EINVAL; -+ -+ reg = phy_read_paged(phydev, MII_MARVELL_LED_PAGE, -+ MII_88E1318S_PHY_LED_FUNC); -+ if (reg < 0) -+ return reg; -+ -+ mode = (reg >> (4 * index)) & 0xf; -+ -+ return marvell_get_led_rules(index, rules, mode); -+} -+ - static int marvell_probe(struct phy_device *phydev) - { - struct marvell_priv *priv; -@@ -3144,6 +3410,9 @@ static struct phy_driver marvell_drivers - .get_stats = marvell_get_stats, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1145, -@@ -3252,6 +3521,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1540, -@@ -3280,6 +3552,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E1545, -@@ -3308,6 +3583,9 @@ static struct phy_driver marvell_drivers - .cable_test_get_status = marvell_vct7_cable_test_get_status, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - { - .phy_id = MARVELL_PHY_ID_88E3016, -@@ -3451,6 +3729,9 @@ static struct phy_driver marvell_drivers - .set_tunable = m88e1540_set_tunable, - .led_brightness_set = m88e1318_led_brightness_set, - .led_blink_set = m88e1318_led_blink_set, -+ .led_hw_is_supported = m88e1318_led_hw_is_supported, -+ .led_hw_control_set = m88e1318_led_hw_control_set, -+ .led_hw_control_get = m88e1318_led_hw_control_get, - }, - }; - diff --git a/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch b/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch deleted file mode 100644 index d6a69aa9ca..0000000000 --- a/target/linux/generic/backport-6.6/826-v6.6-04-leds-trig-netdev-Disable-offload-on-deactivation-of-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e8fbcc47a8e935f36f044d85f21a99acecbd7bfb Mon Sep 17 00:00:00 2001 -From: Andrew Lunn -Date: Tue, 8 Aug 2023 23:04:36 +0200 -Subject: [PATCH 4/4] leds: trig-netdev: Disable offload on deactivation of - trigger - -Ensure that the offloading of blinking is stopped when the trigger is -deactivated. Calling led_set_brightness() is documented as stopping -offload and setting the LED to a constant brightness. - -Suggested-by: Daniel Golle -Signed-off-by: Andrew Lunn -Reviewed-by: Simon Horman -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230808210436.838995-5-andrew@lunn.ch -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -595,6 +595,8 @@ static void netdev_trig_deactivate(struc - - cancel_delayed_work_sync(&trigger_data->work); - -+ led_set_brightness(led_cdev, LED_OFF); -+ - dev_put(trigger_data->net_dev); - - kfree(trigger_data); diff --git a/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch b/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch deleted file mode 100644 index f568c3f6ce..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0001-of-base-add-of_parse_phandle_with_optional_args.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c5d264d4b527c96ae8903376a4b195df47b05203 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:43 +0000 -Subject: [PATCH] of: base: add of_parse_phandle_with_optional_args() - -Add a new variant of the of_parse_phandle_with_args() which treats the -cells name as optional. If it's missing, it is assumed that the phandle -has no arguments. - -Up until now, a nvmem node didn't have any arguments, so all the device -trees haven't any '#*-cells' property. But there is a need for an -additional argument for the phandle, for which we need a '#*-cells' -property. Therefore, we need to support nvmem nodes with and without -this property. - -Signed-off-by: Michael Walle -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/of.h | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -1009,6 +1009,31 @@ static inline int of_parse_phandle_with_ - } - - /** -+ * of_parse_phandle_with_optional_args() - Find a node pointed by phandle in a list -+ * @np: pointer to a device tree node containing a list -+ * @list_name: property name that contains a list -+ * @cells_name: property name that specifies phandles' arguments count -+ * @index: index of a phandle to parse out -+ * @out_args: optional pointer to output arguments structure (will be filled) -+ * -+ * Same as of_parse_phandle_with_args() except that if the cells_name property -+ * is not found, cell_count of 0 is assumed. -+ * -+ * This is used to useful, if you have a phandle which didn't have arguments -+ * before and thus doesn't have a '#*-cells' property but is now migrated to -+ * having arguments while retaining backwards compatibility. -+ */ -+static inline int of_parse_phandle_with_optional_args(const struct device_node *np, -+ const char *list_name, -+ const char *cells_name, -+ int index, -+ struct of_phandle_args *out_args) -+{ -+ return __of_parse_phandle_with_args(np, list_name, cells_name, -+ 0, index, out_args); -+} -+ -+/** - * of_property_count_u8_elems - Count the number of u8 elements in a property - * - * @np: device node from which the property value is to be read. diff --git a/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch b/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch deleted file mode 100644 index 66c29126b6..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0002-of-property-make-.-cells-optional-for-simple-props.patch +++ /dev/null @@ -1,34 +0,0 @@ -From ff24fed10ba414d19579e26e60b126fad2f2bb07 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:44 +0000 -Subject: [PATCH] of: property: make #.*-cells optional for simple props - -Sometimes, future bindings for phandles will get additional arguments. -Thus the target node of the phandle will need a new #.*-cells property. -To be backwards compatible, this needs to be optional. - -Prepare the DEFINE_SIMPLE_PROPS() to handle the cells name as optional. - -Signed-off-by: Michael Walle -Tested-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-11-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/property.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -1146,8 +1146,8 @@ static struct device_node *parse_prop_ce - if (strcmp(prop_name, list_name)) - return NULL; - -- if (of_parse_phandle_with_args(np, list_name, cells_name, index, -- &sup_args)) -+ if (__of_parse_phandle_with_args(np, list_name, cells_name, 0, index, -+ &sup_args)) - return NULL; - - return sup_args.np; diff --git a/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch b/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch deleted file mode 100644 index 07354d7da7..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0003-of-property-add-nvmem-cell-cells-property.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e2d8172043d2e50df19fcd59c11e5593de8188d7 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 6 Feb 2023 13:43:45 +0000 -Subject: [PATCH] of: property: add #nvmem-cell-cells property - -Bindings describe the new '#nvmem-cell-cells' property. Now that the -arguments count property is optional, we just add this property to the -nvmem-cells. - -Signed-off-by: Michael Walle -Tested-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230206134356.839737-12-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/property.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -1251,7 +1251,7 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-c - DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") - DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") - DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) --DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) -+DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", "#nvmem-cell-cells") - DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") - DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) - DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) diff --git a/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch b/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch deleted file mode 100644 index 8dc370618e..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0004-of-device-Ignore-modalias-of-reused-nodes.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 553bd29700145e1849698985e9800f14e967da49 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Tue, 7 Feb 2023 12:05:29 +0100 -Subject: [PATCH] of: device: Ignore modalias of reused nodes - -If of_node is reused, do not use that node's modalias. This will hide -the name of the actual device. This is rather prominent in USB glue -drivers creating a platform device for the host controller. - -Signed-off-by: Alexander Stein -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/20230207110531.1060252-2-alexander.stein@ew.tq-group.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -256,7 +256,7 @@ static ssize_t of_device_get_modalias(st - ssize_t csize; - ssize_t tsize; - -- if ((!dev) || (!dev->of_node)) -+ if ((!dev) || (!dev->of_node) || dev->of_node_reused) - return -ENODEV; - - /* Name & Type */ -@@ -379,7 +379,7 @@ int of_device_uevent_modalias(struct dev - { - int sl; - -- if ((!dev) || (!dev->of_node)) -+ if ((!dev) || (!dev->of_node) || dev->of_node_reused) - return -ENODEV; - - /* Devicetree modalias is tricky, we add it in 2 steps */ diff --git a/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch b/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch deleted file mode 100644 index dcdc2313ba..0000000000 --- a/target/linux/generic/backport-6.6/827-v6.3-0005-of-device-Do-not-ignore-error-code-in-of_device_ueve.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 2295bed9bebe8d1eef276194fed5b5fbe89c5363 Mon Sep 17 00:00:00 2001 -From: Alexander Stein -Date: Tue, 7 Feb 2023 12:05:30 +0100 -Subject: [PATCH] of: device: Do not ignore error code in - of_device_uevent_modalias - -of_device_get_modalias might return an error code, propagate that one. -Otherwise the negative, signed integer is propagated to unsigned integer -for the comparison resulting in a huge 'sl' size. - -Signed-off-by: Alexander Stein -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/20230207110531.1060252-3-alexander.stein@ew.tq-group.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -388,6 +388,8 @@ int of_device_uevent_modalias(struct dev - - sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], - sizeof(env->buf) - env->buflen); -+ if (sl < 0) -+ return sl; - if (sl >= (sizeof(env->buf) - env->buflen)) - return -ENOMEM; - env->buflen += sl; diff --git a/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch b/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch deleted file mode 100644 index 280ed9085c..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0002-of-Update-of_device_get_modalias.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 5c3d15e127ebfc0754cd18def7124633b6d46672 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:15 +0100 -Subject: [PATCH] of: Update of_device_get_modalias() - -This function only needs a "struct device_node" to work, but for -convenience the author (and only user) of this helper did use a "struct -device" and put it in device.c. - -Let's convert this helper to take a "struct device node" instead. This -change asks for two additional changes: renaming it "of_modalias()" -to fit the current naming, and moving it outside of device.c which will -be done in a follow-up commit. - -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-8-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -248,7 +248,7 @@ const void *of_device_get_match_data(con - } - EXPORT_SYMBOL(of_device_get_match_data); - --static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) -+static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) - { - const char *compat; - char *c; -@@ -256,19 +256,16 @@ static ssize_t of_device_get_modalias(st - ssize_t csize; - ssize_t tsize; - -- if ((!dev) || (!dev->of_node) || dev->of_node_reused) -- return -ENODEV; -- - /* Name & Type */ - /* %p eats all alphanum characters, so %c must be used here */ -- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T', -- of_node_get_device_type(dev->of_node)); -+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -+ of_node_get_device_type(np)); - tsize = csize; - len -= csize; - if (str) - str += csize; - -- of_property_for_each_string(dev->of_node, "compatible", p, compat) { -+ of_property_for_each_string(np, "compatible", p, compat) { - csize = strlen(compat) + 1; - tsize += csize; - if (csize > len) -@@ -293,7 +290,10 @@ int of_device_request_module(struct devi - ssize_t size; - int ret; - -- size = of_device_get_modalias(dev, NULL, 0); -+ if (!dev || !dev->of_node) -+ return -ENODEV; -+ -+ size = of_modalias(dev->of_node, NULL, 0); - if (size < 0) - return size; - -@@ -304,7 +304,7 @@ int of_device_request_module(struct devi - if (!str) - return -ENOMEM; - -- of_device_get_modalias(dev, str, size); -+ of_modalias(dev->of_node, str, size); - str[size - 1] = '\0'; - ret = request_module(str); - kfree(str); -@@ -321,7 +321,12 @@ EXPORT_SYMBOL_GPL(of_device_request_modu - */ - ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) - { -- ssize_t sl = of_device_get_modalias(dev, str, len - 2); -+ ssize_t sl; -+ -+ if (!dev || !dev->of_node || dev->of_node_reused) -+ return -ENODEV; -+ -+ sl = of_modalias(dev->of_node, str, len - 2); - if (sl < 0) - return sl; - if (sl > len - 2) -@@ -386,8 +391,8 @@ int of_device_uevent_modalias(struct dev - if (add_uevent_var(env, "MODALIAS=")) - return -ENOMEM; - -- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], -- sizeof(env->buf) - env->buflen); -+ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1], -+ sizeof(env->buf) - env->buflen); - if (sl < 0) - return sl; - if (sl >= (sizeof(env->buf) - env->buflen)) diff --git a/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch deleted file mode 100644 index 671556fbaa..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 673aa1ed1c9b6710bf24e3f0957d85e2f46c77db Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:16 +0100 -Subject: [PATCH] of: Rename of_modalias_node() - -This helper does not produce a real modalias, but tries to get the -"product" compatible part of the "vendor,product" compatibles only. It -is far from creating a purely useful modalias string and does not seem -to be used like that directly anyway, so let's try to give this helper a -more meaningful name before moving there a real modalias helper (already -existing under of/device.c). - -Also update the various documentations to refer to the strings as -"aliases" rather than "modaliases" which has a real meaning in the Linux -kernel. - -There is no functional change. - -Cc: Rafael J. Wysocki -Cc: Len Brown -Cc: Maarten Lankhorst -Cc: Maxime Ripard -Cc: Thomas Zimmermann -Cc: Sebastian Reichel -Cc: Wolfram Sang -Cc: Mark Brown -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Acked-by: Mark Brown -Signed-off-by: Srinivas Kandagatla -Acked-by: Sebastian Reichel -Link: https://lore.kernel.org/r/20230404172148.82422-9-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/acpi/bus.c | 7 ++++--- - drivers/gpu/drm/drm_mipi_dsi.c | 2 +- - drivers/hsi/hsi_core.c | 2 +- - drivers/i2c/busses/i2c-powermac.c | 2 +- - drivers/i2c/i2c-core-of.c | 2 +- - drivers/of/base.c | 18 +++++++++++------- - drivers/spi/spi.c | 4 ++-- - include/linux/of.h | 3 ++- - 8 files changed, 23 insertions(+), 17 deletions(-) - ---- a/drivers/acpi/bus.c -+++ b/drivers/acpi/bus.c -@@ -806,9 +806,10 @@ static bool acpi_of_modalias(struct acpi - * @modalias: Pointer to buffer that modalias value will be copied into - * @len: Length of modalias buffer - * -- * This is a counterpart of of_modalias_node() for struct acpi_device objects. -- * If there is a compatible string for @adev, it will be copied to @modalias -- * with the vendor prefix stripped; otherwise, @default_id will be used. -+ * This is a counterpart of of_alias_from_compatible() for struct acpi_device -+ * objects. If there is a compatible string for @adev, it will be copied to -+ * @modalias with the vendor prefix stripped; otherwise, @default_id will be -+ * used. - */ - void acpi_set_modalias(struct acpi_device *adev, const char *default_id, - char *modalias, size_t len) ---- a/drivers/gpu/drm/drm_mipi_dsi.c -+++ b/drivers/gpu/drm/drm_mipi_dsi.c -@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_h - int ret; - u32 reg; - -- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { -+ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) { - drm_err(host, "modalias failure on %pOF\n", node); - return ERR_PTR(-EINVAL); - } ---- a/drivers/hsi/hsi_core.c -+++ b/drivers/hsi/hsi_core.c -@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struc - if (!cl) - return; - -- err = of_modalias_node(client, name, sizeof(name)); -+ err = of_alias_from_compatible(client, name, sizeof(name)); - if (err) - goto err; - ---- a/drivers/i2c/busses/i2c-powermac.c -+++ b/drivers/i2c/busses/i2c-powermac.c -@@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct - */ - - /* First try proper modalias */ -- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) { -+ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) { - snprintf(type, type_size, "MAC,%s", tmp); - return true; - } ---- a/drivers/i2c/i2c-core-of.c -+++ b/drivers/i2c/i2c-core-of.c -@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device - - memset(info, 0, sizeof(*info)); - -- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) { -+ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) { - dev_err(dev, "of_i2c: modalias failure on %pOF\n", node); - return -EINVAL; - } ---- a/drivers/of/base.c -+++ b/drivers/of/base.c -@@ -1208,19 +1208,23 @@ struct device_node *of_find_matching_nod - EXPORT_SYMBOL(of_find_matching_node_and_match); - - /** -- * of_modalias_node - Lookup appropriate modalias for a device node -+ * of_alias_from_compatible - Lookup appropriate alias for a device node -+ * depending on compatible - * @node: pointer to a device tree node -- * @modalias: Pointer to buffer that modalias value will be copied into -- * @len: Length of modalias value -+ * @alias: Pointer to buffer that alias value will be copied into -+ * @len: Length of alias value - * - * Based on the value of the compatible property, this routine will attempt -- * to choose an appropriate modalias value for a particular device tree node. -+ * to choose an appropriate alias value for a particular device tree node. - * It does this by stripping the manufacturer prefix (as delimited by a ',') - * from the first entry in the compatible list property. - * -+ * Note: The matching on just the "product" side of the compatible is a relic -+ * from I2C and SPI. Please do not add any new user. -+ * - * Return: This routine returns 0 on success, <0 on failure. - */ --int of_modalias_node(struct device_node *node, char *modalias, int len) -+int of_alias_from_compatible(const struct device_node *node, char *alias, int len) - { - const char *compatible, *p; - int cplen; -@@ -1229,10 +1233,10 @@ int of_modalias_node(struct device_node - if (!compatible || strlen(compatible) > cplen) - return -ENODEV; - p = strchr(compatible, ','); -- strscpy(modalias, p ? p + 1 : compatible, len); -+ strscpy(alias, p ? p + 1 : compatible, len); - return 0; - } --EXPORT_SYMBOL_GPL(of_modalias_node); -+EXPORT_SYMBOL_GPL(of_alias_from_compatible); - - /** - * of_find_node_by_phandle - Find a node given a phandle ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -2330,8 +2330,8 @@ of_register_spi_device(struct spi_contro - } - - /* Select device driver */ -- rc = of_modalias_node(nc, spi->modalias, -- sizeof(spi->modalias)); -+ rc = of_alias_from_compatible(nc, spi->modalias, -+ sizeof(spi->modalias)); - if (rc < 0) { - dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc); - goto err_out; ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -362,7 +362,8 @@ extern int of_n_addr_cells(struct device - extern int of_n_size_cells(struct device_node *np); - extern const struct of_device_id *of_match_node( - const struct of_device_id *matches, const struct device_node *node); --extern int of_modalias_node(struct device_node *node, char *modalias, int len); -+extern int of_alias_from_compatible(const struct device_node *node, char *alias, -+ int len); - extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args); - extern int __of_parse_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name, int cell_count, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch deleted file mode 100644 index 39a84161a2..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0004-of-Move-of_modalias-to-module.c.patch +++ /dev/null @@ -1,160 +0,0 @@ -From bd7a7ed774afd1a4174df34227626c95573be517 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:17 +0100 -Subject: [PATCH] of: Move of_modalias() to module.c - -Create a specific .c file for OF related module handling. -Move of_modalias() inside as a first step. - -The helper is exposed through of.h even though it is only used by core -files because the users from device.c will soon be split into an OF-only -helper in module.c as well as a device-oriented inline helper in -of_device.h. Putting this helper in of_private.h would require to -include of_private.h from of_device.h, which is not acceptable. - -Suggested-by: Rob Herring -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-10-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/Makefile | 2 +- - drivers/of/device.c | 37 ------------------------------------- - drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ - include/linux/of.h | 9 +++++++++ - 4 files changed, 54 insertions(+), 38 deletions(-) - create mode 100644 drivers/of/module.c - ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-y = base.o device.o platform.o property.o -+obj-y = base.o device.o module.o platform.o property.o - obj-$(CONFIG_OF_KOBJ) += kobj.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -1,5 +1,4 @@ - // SPDX-License-Identifier: GPL-2.0 --#include - #include - #include - #include -@@ -248,42 +247,6 @@ const void *of_device_get_match_data(con - } - EXPORT_SYMBOL(of_device_get_match_data); - --static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) --{ -- const char *compat; -- char *c; -- struct property *p; -- ssize_t csize; -- ssize_t tsize; -- -- /* Name & Type */ -- /* %p eats all alphanum characters, so %c must be used here */ -- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -- of_node_get_device_type(np)); -- tsize = csize; -- len -= csize; -- if (str) -- str += csize; -- -- of_property_for_each_string(np, "compatible", p, compat) { -- csize = strlen(compat) + 1; -- tsize += csize; -- if (csize > len) -- continue; -- -- csize = snprintf(str, len, "C%s", compat); -- for (c = str; c; ) { -- c = strchr(c, ' '); -- if (c) -- *c++ = '_'; -- } -- len -= csize; -- str += csize; -- } -- -- return tsize; --} -- - int of_device_request_module(struct device *dev) - { - char *str; ---- /dev/null -+++ b/drivers/of/module.c -@@ -0,0 +1,44 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Linux kernel module helpers. -+ */ -+ -+#include -+#include -+#include -+ -+ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) -+{ -+ const char *compat; -+ char *c; -+ struct property *p; -+ ssize_t csize; -+ ssize_t tsize; -+ -+ /* Name & Type */ -+ /* %p eats all alphanum characters, so %c must be used here */ -+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', -+ of_node_get_device_type(np)); -+ tsize = csize; -+ len -= csize; -+ if (str) -+ str += csize; -+ -+ of_property_for_each_string(np, "compatible", p, compat) { -+ csize = strlen(compat) + 1; -+ tsize += csize; -+ if (csize > len) -+ continue; -+ -+ csize = snprintf(str, len, "C%s", compat); -+ for (c = str; c; ) { -+ c = strchr(c, ' '); -+ if (c) -+ *c++ = '_'; -+ } -+ len -= csize; -+ str += csize; -+ } -+ -+ return tsize; -+} ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -374,6 +374,9 @@ extern int of_parse_phandle_with_args_ma - extern int of_count_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name); - -+/* module functions */ -+extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); -+ - /* phandle iterator functions */ - extern int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, -@@ -731,6 +734,12 @@ static inline int of_count_phandle_with_ - return -ENOSYS; - } - -+static inline ssize_t of_modalias(const struct device_node *np, char *str, -+ ssize_t len) -+{ -+ return -ENODEV; -+} -+ - static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, - const char *list_name, diff --git a/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch b/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch deleted file mode 100644 index 046c1df561..0000000000 --- a/target/linux/generic/backport-6.6/828-v6.4-0005-of-Move-the-request-module-helper-logic-to-module.c.patch +++ /dev/null @@ -1,131 +0,0 @@ -From e6506f06d5e82765666902ccf9e9162f3e31d518 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Tue, 4 Apr 2023 18:21:18 +0100 -Subject: [PATCH] of: Move the request module helper logic to module.c - -Depending on device.c for pure OF handling is considered -backwards. Let's extract the content of of_device_request_module() to -have the real logic under module.c. - -The next step will be to convert users of of_device_request_module() to -use the new helper. - -Signed-off-by: Miquel Raynal -Reviewed-by: Rob Herring -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/of/device.c | 25 ++----------------------- - drivers/of/module.c | 30 ++++++++++++++++++++++++++++++ - include/linux/of.h | 6 ++++++ - 3 files changed, 38 insertions(+), 23 deletions(-) - ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -8,7 +8,6 @@ - #include /* for bus_dma_region */ - #include - #include --#include - #include - #include - #include -@@ -249,30 +248,10 @@ EXPORT_SYMBOL(of_device_get_match_data); - - int of_device_request_module(struct device *dev) - { -- char *str; -- ssize_t size; -- int ret; -- -- if (!dev || !dev->of_node) -+ if (!dev) - return -ENODEV; - -- size = of_modalias(dev->of_node, NULL, 0); -- if (size < 0) -- return size; -- -- /* Reserve an additional byte for the trailing '\0' */ -- size++; -- -- str = kmalloc(size, GFP_KERNEL); -- if (!str) -- return -ENOMEM; -- -- of_modalias(dev->of_node, str, size); -- str[size - 1] = '\0'; -- ret = request_module(str); -- kfree(str); -- -- return ret; -+ return of_request_module(dev->of_node); - } - EXPORT_SYMBOL_GPL(of_device_request_module); - ---- a/drivers/of/module.c -+++ b/drivers/of/module.c -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - -@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_ - - return tsize; - } -+ -+int of_request_module(const struct device_node *np) -+{ -+ char *str; -+ ssize_t size; -+ int ret; -+ -+ if (!np) -+ return -ENODEV; -+ -+ size = of_modalias(np, NULL, 0); -+ if (size < 0) -+ return size; -+ -+ /* Reserve an additional byte for the trailing '\0' */ -+ size++; -+ -+ str = kmalloc(size, GFP_KERNEL); -+ if (!str) -+ return -ENOMEM; -+ -+ of_modalias(np, str, size); -+ str[size - 1] = '\0'; -+ ret = request_module(str); -+ kfree(str); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(of_request_module); ---- a/include/linux/of.h -+++ b/include/linux/of.h -@@ -376,6 +376,7 @@ extern int of_count_phandle_with_args(co - - /* module functions */ - extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len); -+extern int of_request_module(const struct device_node *np); - - /* phandle iterator functions */ - extern int of_phandle_iterator_init(struct of_phandle_iterator *it, -@@ -739,6 +740,11 @@ static inline ssize_t of_modalias(const - { - return -ENODEV; - } -+ -+static inline int of_request_module(const struct device_node *np) -+{ -+ return -ENODEV; -+} - - static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, - const struct device_node *np, diff --git a/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch b/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch deleted file mode 100644 index 3319f431ba..0000000000 --- a/target/linux/generic/backport-6.6/830-00-v6.2-dt-bindings-arm-qcom-document-qcom-msm-id-and-qcom-b.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 77faa07c185c969e742cbb3e6aa487a11b0b616c Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 30 Aug 2022 09:57:42 +0300 -Subject: [PATCH] dt-bindings: arm: qcom: document qcom,msm-id and - qcom,board-id - -The top level qcom,msm-id and qcom,board-id properties are utilized by -bootloaders on Qualcomm MSM platforms to determine which device tree -should be used and passed to the kernel. - -The commit b32e592d3c28 ("devicetree: bindings: Document qcom board -compatible format") from 2015 was a consensus during discussion about -upstreaming qcom,msm-id and qcom,board-id fields. There are however still -problems with that consensus: -1. It was reached 7 years ago but it turned out its implementation did - not reach all possible products. - -2. Initially additional tool (dtbTool) was needed for parsing these - fields to create a QCDT image consisting of multiple DTBs, later the - bootloaders were improved and they use these qcom,msm-id and - qcom,board-id properties directly. - -3. Extracting relevant information from the board compatible requires - this additional tool (dtbTool), which makes the build process more - complicated and not easily reproducible (DTBs are modified after the - kernel build). - -4. Some versions of Qualcomm bootloaders expect these properties even - when booting with a single DTB. The community is stuck with these - bootloaders thus they require properties in the DTBs. - -Since several upstreamed Qualcomm SoC-based boards require these -properties to properly boot and the properties are reportedly used by -bootloaders, document them along with the bindings header with constants -used by: bootloader, some DTS and socinfo driver. - -Link: https://lore.kernel.org/r/a3c932d1-a102-ce18-deea-18cbbd05ecab@linaro.org/ -Co-developed-by: Kumar Gala -Signed-off-by: Kumar Gala -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Dmitry Baryshkov -Reviewed-by: Rob Herring -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220830065744.161163-2-krzysztof.kozlowski@linaro.org ---- - include/dt-bindings/arm/qcom,ids.h | 155 +++++++++++++++++++++++++++++ - 1 file changed, 155 insertions(+) - create mode 100644 include/dt-bindings/arm/qcom,ids.h - ---- /dev/null -+++ b/include/dt-bindings/arm/qcom,ids.h -@@ -0,0 +1,155 @@ -+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ -+/* -+ * Copyright (c) 2015, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2022 Linaro Ltd -+ * Author: Krzysztof Kozlowski based on previous work of Kumar Gala. -+ */ -+#ifndef _DT_BINDINGS_ARM_QCOM_IDS_H -+#define _DT_BINDINGS_ARM_QCOM_IDS_H -+ -+/* -+ * The MSM chipset and hardware revision used by Qualcomm bootloaders, DTS for -+ * older chipsets (qcom,msm-id) and in socinfo driver: -+ */ -+#define QCOM_ID_MSM8960 87 -+#define QCOM_ID_APQ8064 109 -+#define QCOM_ID_MSM8660A 122 -+#define QCOM_ID_MSM8260A 123 -+#define QCOM_ID_APQ8060A 124 -+#define QCOM_ID_MSM8974 126 -+#define QCOM_ID_MPQ8064 130 -+#define QCOM_ID_MSM8960AB 138 -+#define QCOM_ID_APQ8060AB 139 -+#define QCOM_ID_MSM8260AB 140 -+#define QCOM_ID_MSM8660AB 141 -+#define QCOM_ID_MSM8626 145 -+#define QCOM_ID_MSM8610 147 -+#define QCOM_ID_APQ8064AB 153 -+#define QCOM_ID_MSM8226 158 -+#define QCOM_ID_MSM8526 159 -+#define QCOM_ID_MSM8110 161 -+#define QCOM_ID_MSM8210 162 -+#define QCOM_ID_MSM8810 163 -+#define QCOM_ID_MSM8212 164 -+#define QCOM_ID_MSM8612 165 -+#define QCOM_ID_MSM8112 166 -+#define QCOM_ID_MSM8225Q 168 -+#define QCOM_ID_MSM8625Q 169 -+#define QCOM_ID_MSM8125Q 170 -+#define QCOM_ID_APQ8064AA 172 -+#define QCOM_ID_APQ8084 178 -+#define QCOM_ID_APQ8074 184 -+#define QCOM_ID_MSM8274 185 -+#define QCOM_ID_MSM8674 186 -+#define QCOM_ID_MSM8974PRO_AC 194 -+#define QCOM_ID_MSM8126 198 -+#define QCOM_ID_APQ8026 199 -+#define QCOM_ID_MSM8926 200 -+#define QCOM_ID_MSM8326 205 -+#define QCOM_ID_MSM8916 206 -+#define QCOM_ID_MSM8994 207 -+#define QCOM_ID_APQ8074PRO_AA 208 -+#define QCOM_ID_APQ8074PRO_AB 209 -+#define QCOM_ID_APQ8074PRO_AC 210 -+#define QCOM_ID_MSM8274PRO_AA 211 -+#define QCOM_ID_MSM8274PRO_AB 212 -+#define QCOM_ID_MSM8274PRO_AC 213 -+#define QCOM_ID_MSM8674PRO_AA 214 -+#define QCOM_ID_MSM8674PRO_AB 215 -+#define QCOM_ID_MSM8674PRO_AC 216 -+#define QCOM_ID_MSM8974PRO_AA 217 -+#define QCOM_ID_MSM8974PRO_AB 218 -+#define QCOM_ID_APQ8028 219 -+#define QCOM_ID_MSM8128 220 -+#define QCOM_ID_MSM8228 221 -+#define QCOM_ID_MSM8528 222 -+#define QCOM_ID_MSM8628 223 -+#define QCOM_ID_MSM8928 224 -+#define QCOM_ID_MSM8510 225 -+#define QCOM_ID_MSM8512 226 -+#define QCOM_ID_MSM8936 233 -+#define QCOM_ID_MSM8939 239 -+#define QCOM_ID_APQ8036 240 -+#define QCOM_ID_APQ8039 241 -+#define QCOM_ID_MSM8996 246 -+#define QCOM_ID_APQ8016 247 -+#define QCOM_ID_MSM8216 248 -+#define QCOM_ID_MSM8116 249 -+#define QCOM_ID_MSM8616 250 -+#define QCOM_ID_MSM8992 251 -+#define QCOM_ID_APQ8094 253 -+#define QCOM_ID_MDM9607 290 -+#define QCOM_ID_APQ8096 291 -+#define QCOM_ID_MSM8998 292 -+#define QCOM_ID_MSM8953 293 -+#define QCOM_ID_MDM8207 296 -+#define QCOM_ID_MDM9207 297 -+#define QCOM_ID_MDM9307 298 -+#define QCOM_ID_MDM9628 299 -+#define QCOM_ID_APQ8053 304 -+#define QCOM_ID_MSM8996SG 305 -+#define QCOM_ID_MSM8996AU 310 -+#define QCOM_ID_APQ8096AU 311 -+#define QCOM_ID_APQ8096SG 312 -+#define QCOM_ID_SDM660 317 -+#define QCOM_ID_SDM630 318 -+#define QCOM_ID_APQ8098 319 -+#define QCOM_ID_SDM845 321 -+#define QCOM_ID_MDM9206 322 -+#define QCOM_ID_IPQ8074 323 -+#define QCOM_ID_SDA660 324 -+#define QCOM_ID_SDM658 325 -+#define QCOM_ID_SDA658 326 -+#define QCOM_ID_SDA630 327 -+#define QCOM_ID_SDM450 338 -+#define QCOM_ID_SDA845 341 -+#define QCOM_ID_IPQ8072 342 -+#define QCOM_ID_IPQ8076 343 -+#define QCOM_ID_IPQ8078 344 -+#define QCOM_ID_SDM636 345 -+#define QCOM_ID_SDA636 346 -+#define QCOM_ID_SDM632 349 -+#define QCOM_ID_SDA632 350 -+#define QCOM_ID_SDA450 351 -+#define QCOM_ID_SM8250 356 -+#define QCOM_ID_IPQ8070 375 -+#define QCOM_ID_IPQ8071 376 -+#define QCOM_ID_IPQ8072A 389 -+#define QCOM_ID_IPQ8074A 390 -+#define QCOM_ID_IPQ8076A 391 -+#define QCOM_ID_IPQ8078A 392 -+#define QCOM_ID_SM6125 394 -+#define QCOM_ID_IPQ8070A 395 -+#define QCOM_ID_IPQ8071A 396 -+#define QCOM_ID_IPQ6018 402 -+#define QCOM_ID_IPQ6028 403 -+#define QCOM_ID_IPQ6000 421 -+#define QCOM_ID_IPQ6010 422 -+#define QCOM_ID_SC7180 425 -+#define QCOM_ID_SM6350 434 -+#define QCOM_ID_SM8350 439 -+#define QCOM_ID_SC8280XP 449 -+#define QCOM_ID_IPQ6005 453 -+#define QCOM_ID_QRB5165 455 -+#define QCOM_ID_SM8450 457 -+#define QCOM_ID_SM7225 459 -+#define QCOM_ID_SA8295P 460 -+#define QCOM_ID_SA8540P 461 -+#define QCOM_ID_SM8450_2 480 -+#define QCOM_ID_SM8450_3 482 -+#define QCOM_ID_SC7280 487 -+#define QCOM_ID_SC7180P 495 -+#define QCOM_ID_SM6375 507 -+ -+/* -+ * The board type and revision information, used by Qualcomm bootloaders and -+ * DTS for older chipsets (qcom,board-id): -+ */ -+#define QCOM_BOARD_ID(a, major, minor) \ -+ (((major & 0xff) << 16) | ((minor & 0xff) << 8) | QCOM_BOARD_ID_##a) -+ -+#define QCOM_BOARD_ID_MTP 8 -+#define QCOM_BOARD_ID_DRAGONBOARD 10 -+#define QCOM_BOARD_ID_SBC 24 -+ -+#endif /* _DT_BINDINGS_ARM_QCOM_IDS_H */ diff --git a/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch b/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch deleted file mode 100644 index 394087a27a..0000000000 --- a/target/linux/generic/backport-6.6/830-01-v6.5-soc-qcom-socinfo-move-SMEM-item-struct-and-defines-t.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 7cbff3c3f867ff3b24de674f44ca03f54e416a37 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 31 Dec 2022 00:27:42 +0100 -Subject: [PATCH] soc: qcom: socinfo: move SMEM item struct and defines to a - header - -Move SMEM item struct and related defines to a header in order to be able -to reuse them in the Qualcomm NVMEM CPUFreq driver instead of duplicating -them. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-1-robimarko@gmail.com ---- - drivers/soc/qcom/socinfo.c | 58 +-------------------------- - include/linux/soc/qcom/socinfo.h | 67 ++++++++++++++++++++++++++++++++ - 2 files changed, 68 insertions(+), 57 deletions(-) - create mode 100644 include/linux/soc/qcom/socinfo.h - ---- a/drivers/soc/qcom/socinfo.c -+++ b/drivers/soc/qcom/socinfo.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -25,15 +26,6 @@ - #define SOCINFO_MINOR(ver) ((ver) & 0xffff) - #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) - --#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 --#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 -- --/* -- * SMEM item id, used to acquire handles to respective -- * SMEM region. -- */ --#define SMEM_HW_SW_BUILD_ID 137 -- - #ifdef CONFIG_DEBUG_FS - #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 - #define SMEM_IMAGE_VERSION_SIZE 4096 -@@ -116,54 +108,6 @@ static const char *const pmic_models[] = - }; - #endif /* CONFIG_DEBUG_FS */ - --/* Socinfo SMEM item structure */ --struct socinfo { -- __le32 fmt; -- __le32 id; -- __le32 ver; -- char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; -- /* Version 2 */ -- __le32 raw_id; -- __le32 raw_ver; -- /* Version 3 */ -- __le32 hw_plat; -- /* Version 4 */ -- __le32 plat_ver; -- /* Version 5 */ -- __le32 accessory_chip; -- /* Version 6 */ -- __le32 hw_plat_subtype; -- /* Version 7 */ -- __le32 pmic_model; -- __le32 pmic_die_rev; -- /* Version 8 */ -- __le32 pmic_model_1; -- __le32 pmic_die_rev_1; -- __le32 pmic_model_2; -- __le32 pmic_die_rev_2; -- /* Version 9 */ -- __le32 foundry_id; -- /* Version 10 */ -- __le32 serial_num; -- /* Version 11 */ -- __le32 num_pmics; -- __le32 pmic_array_offset; -- /* Version 12 */ -- __le32 chip_family; -- __le32 raw_device_family; -- __le32 raw_device_num; -- /* Version 13 */ -- __le32 nproduct_id; -- char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; -- /* Version 14 */ -- __le32 num_clusters; -- __le32 ncluster_array_offset; -- __le32 num_defective_parts; -- __le32 ndefective_parts_array_offset; -- /* Version 15 */ -- __le32 nmodem_supported; --}; -- - #ifdef CONFIG_DEBUG_FS - struct socinfo_params { - u32 raw_device_family; ---- /dev/null -+++ b/include/linux/soc/qcom/socinfo.h -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2017-2019, Linaro Ltd. -+ */ -+ -+#ifndef __QCOM_SOCINFO_H__ -+#define __QCOM_SOCINFO_H__ -+ -+/* -+ * SMEM item id, used to acquire handles to respective -+ * SMEM region. -+ */ -+#define SMEM_HW_SW_BUILD_ID 137 -+ -+#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 -+#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 -+ -+/* Socinfo SMEM item structure */ -+struct socinfo { -+ __le32 fmt; -+ __le32 id; -+ __le32 ver; -+ char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; -+ /* Version 2 */ -+ __le32 raw_id; -+ __le32 raw_ver; -+ /* Version 3 */ -+ __le32 hw_plat; -+ /* Version 4 */ -+ __le32 plat_ver; -+ /* Version 5 */ -+ __le32 accessory_chip; -+ /* Version 6 */ -+ __le32 hw_plat_subtype; -+ /* Version 7 */ -+ __le32 pmic_model; -+ __le32 pmic_die_rev; -+ /* Version 8 */ -+ __le32 pmic_model_1; -+ __le32 pmic_die_rev_1; -+ __le32 pmic_model_2; -+ __le32 pmic_die_rev_2; -+ /* Version 9 */ -+ __le32 foundry_id; -+ /* Version 10 */ -+ __le32 serial_num; -+ /* Version 11 */ -+ __le32 num_pmics; -+ __le32 pmic_array_offset; -+ /* Version 12 */ -+ __le32 chip_family; -+ __le32 raw_device_family; -+ __le32 raw_device_num; -+ /* Version 13 */ -+ __le32 nproduct_id; -+ char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; -+ /* Version 14 */ -+ __le32 num_clusters; -+ __le32 ncluster_array_offset; -+ __le32 num_defective_parts; -+ __le32 ndefective_parts_array_offset; -+ /* Version 15 */ -+ __le32 nmodem_supported; -+}; -+ -+#endif diff --git a/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch b/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch deleted file mode 100644 index 7c7c3f3635..0000000000 --- a/target/linux/generic/backport-6.6/830-02-v6.5-soc-qcom-smem-Switch-to-EXPORT_SYMBOL_GPL.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 9f1bbff157a69db7684f5da2f73b2325c638a90e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:47:59 +0200 -Subject: [PATCH] soc: qcom: smem: Switch to EXPORT_SYMBOL_GPL() - -SMEM has been GPL licensed from the start, and there is no reason to use -EXPORT_SYMBOL() so switch to the GPL version. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Reviewed-by: Trilok Soni -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-2-robimarko@gmail.com ---- - drivers/soc/qcom/smem.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/soc/qcom/smem.c -+++ b/drivers/soc/qcom/smem.c -@@ -500,7 +500,7 @@ int qcom_smem_alloc(unsigned host, unsig - - return ret; - } --EXPORT_SYMBOL(qcom_smem_alloc); -+EXPORT_SYMBOL_GPL(qcom_smem_alloc); - - static void *qcom_smem_get_global(struct qcom_smem *smem, - unsigned item, -@@ -674,7 +674,7 @@ void *qcom_smem_get(unsigned host, unsig - return ptr; - - } --EXPORT_SYMBOL(qcom_smem_get); -+EXPORT_SYMBOL_GPL(qcom_smem_get); - - /** - * qcom_smem_get_free_space() - retrieve amount of free space in a partition -@@ -719,7 +719,7 @@ int qcom_smem_get_free_space(unsigned ho - - return ret; - } --EXPORT_SYMBOL(qcom_smem_get_free_space); -+EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); - - static bool addr_in_range(void __iomem *base, size_t size, void *addr) - { -@@ -770,7 +770,7 @@ phys_addr_t qcom_smem_virt_to_phys(void - - return 0; - } --EXPORT_SYMBOL(qcom_smem_virt_to_phys); -+EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); - - static int qcom_smem_get_sbl_version(struct qcom_smem *smem) - { diff --git a/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch b/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch deleted file mode 100644 index 4a816bb0f9..0000000000 --- a/target/linux/generic/backport-6.6/830-03-v6.5-soc-qcom-smem-introduce-qcom_smem_get_soc_id.patch +++ /dev/null @@ -1,70 +0,0 @@ -From c3ecf2602a32d9b9e5fc997076c0d2836495c085 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:00 +0200 -Subject: [PATCH] soc: qcom: smem: introduce qcom_smem_get_soc_id() - -Introduce a helper to return the SoC SMEM ID, which is used to identify the -exact SoC model as there may be differences in the same SoC family. - -Currently, cpufreq-nvmem does this completely in the driver and there has -been more interest expresed for other drivers to use this information so -lets expose a common helper to prevent redoing it in individual drivers -since this field is present on every SMEM table version. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-3-robimarko@gmail.com ---- - drivers/soc/qcom/smem.c | 23 +++++++++++++++++++++++ - include/linux/soc/qcom/smem.h | 2 ++ - 2 files changed, 25 insertions(+) - ---- a/drivers/soc/qcom/smem.c -+++ b/drivers/soc/qcom/smem.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - /* - * The Qualcomm shared memory system is a allocate only heap structure that -@@ -772,6 +773,28 @@ phys_addr_t qcom_smem_virt_to_phys(void - } - EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); - -+/** -+ * qcom_smem_get_soc_id() - return the SoC ID -+ * @id: On success, we return the SoC ID here. -+ * -+ * Look up SoC ID from HW/SW build ID and return it. -+ * -+ * Return: 0 on success, negative errno on failure. -+ */ -+int qcom_smem_get_soc_id(u32 *id) -+{ -+ struct socinfo *info; -+ -+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); -+ if (IS_ERR(info)) -+ return PTR_ERR(info); -+ -+ *id = __le32_to_cpu(info->id); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); -+ - static int qcom_smem_get_sbl_version(struct qcom_smem *smem) - { - struct smem_header *header; ---- a/include/linux/soc/qcom/smem.h -+++ b/include/linux/soc/qcom/smem.h -@@ -11,4 +11,6 @@ int qcom_smem_get_free_space(unsigned ho - - phys_addr_t qcom_smem_virt_to_phys(void *p); - -+int qcom_smem_get_soc_id(u32 *id); -+ - #endif diff --git a/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch b/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch deleted file mode 100644 index 9560122ccd..0000000000 --- a/target/linux/generic/backport-6.6/830-04-v6.5-cpufreq-qcom-nvmem-use-SoC-ID-s-from-bindings.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 2b8634d1468ff498cc91b6adf993c27ae6fa079d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:01 +0200 -Subject: [PATCH] cpufreq: qcom-nvmem: use SoC ID-s from bindings - -SMEM SoC ID-s are now stored in DT bindings so lets use those instead of -defining them in the driver again. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Reviewed-by: Bjorn Andersson -Acked-by: Viresh Kumar -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-4-robimarko@gmail.com ---- - drivers/cpufreq/qcom-cpufreq-nvmem.c | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) - ---- a/drivers/cpufreq/qcom-cpufreq-nvmem.c -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -31,12 +31,7 @@ - - #define MSM_ID_SMEM 137 - --enum _msm_id { -- MSM8996V3 = 0xF6ul, -- APQ8096V3 = 0x123ul, -- MSM8996SG = 0x131ul, -- APQ8096SG = 0x138ul, --}; -+#include - - enum _msm8996_version { - MSM8996_V3, -@@ -154,12 +149,12 @@ static enum _msm8996_version qcom_cpufre - msm_id++; - - switch ((enum _msm_id)*msm_id) { -- case MSM8996V3: -- case APQ8096V3: -+ case QCOM_ID_MSM8996: -+ case QCOM_ID_APQ8096: - version = MSM8996_V3; - break; -- case MSM8996SG: -- case APQ8096SG: -+ case QCOM_ID_MSM8996SG: -+ case QCOM_ID_APQ8096SG: - version = MSM8996_SG; - break; - default: diff --git a/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch b/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch deleted file mode 100644 index 4f37d672ba..0000000000 --- a/target/linux/generic/backport-6.6/830-05-v6.5-cpufreq-qcom-nvmem-use-helper-to-get-SMEM-SoC-ID.patch +++ /dev/null @@ -1,109 +0,0 @@ -From e7992615acacc27baeec310197108143afc77337 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 26 May 2023 22:48:02 +0200 -Subject: [PATCH] cpufreq: qcom-nvmem: use helper to get SMEM SoC ID - -Now that SMEM exports a helper to get the SMEM SoC ID lets utilize it. -Currently qcom_cpufreq_get_msm_id() is encoding the returned SMEM SoC ID -into an enum, however there is no reason to do so and we can just match -directly on the SMEM SoC ID as returned by qcom_smem_get_soc_id(). - -Signed-off-by: Robert Marko -Acked-by: Viresh Kumar -Reviewed-by: Konrad Dybcio -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20230526204802.3081168-5-robimarko@gmail.com ---- - drivers/cpufreq/qcom-cpufreq-nvmem.c | 56 +++++----------------------- - 1 file changed, 10 insertions(+), 46 deletions(-) - ---- a/drivers/cpufreq/qcom-cpufreq-nvmem.c -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -29,16 +29,8 @@ - #include - #include - --#define MSM_ID_SMEM 137 -- - #include - --enum _msm8996_version { -- MSM8996_V3, -- MSM8996_SG, -- NUM_OF_MSM8996_VERSIONS, --}; -- - struct qcom_cpufreq_drv; - - struct qcom_cpufreq_match_data { -@@ -135,60 +127,32 @@ static void get_krait_bin_format_b(struc - dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver); - } - --static enum _msm8996_version qcom_cpufreq_get_msm_id(void) --{ -- size_t len; -- u32 *msm_id; -- enum _msm8996_version version; -- -- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -- if (IS_ERR(msm_id)) -- return NUM_OF_MSM8996_VERSIONS; -- -- /* The first 4 bytes are format, next to them is the actual msm-id */ -- msm_id++; -- -- switch ((enum _msm_id)*msm_id) { -- case QCOM_ID_MSM8996: -- case QCOM_ID_APQ8096: -- version = MSM8996_V3; -- break; -- case QCOM_ID_MSM8996SG: -- case QCOM_ID_APQ8096SG: -- version = MSM8996_SG; -- break; -- default: -- version = NUM_OF_MSM8996_VERSIONS; -- } -- -- return version; --} -- - static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, - struct nvmem_cell *speedbin_nvmem, - char **pvs_name, - struct qcom_cpufreq_drv *drv) - { - size_t len; -+ u32 msm_id; - u8 *speedbin; -- enum _msm8996_version msm8996_version; -+ int ret; - *pvs_name = NULL; - -- msm8996_version = qcom_cpufreq_get_msm_id(); -- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -- dev_err(cpu_dev, "Not Snapdragon 820/821!"); -- return -ENODEV; -- } -+ ret = qcom_smem_get_soc_id(&msm_id); -+ if (ret) -+ return ret; - - speedbin = nvmem_cell_read(speedbin_nvmem, &len); - if (IS_ERR(speedbin)) - return PTR_ERR(speedbin); - -- switch (msm8996_version) { -- case MSM8996_V3: -+ switch (msm_id) { -+ case QCOM_ID_MSM8996: -+ case QCOM_ID_APQ8096: - drv->versions = 1 << (unsigned int)(*speedbin); - break; -- case MSM8996_SG: -+ case QCOM_ID_MSM8996SG: -+ case QCOM_ID_APQ8096SG: - drv->versions = 1 << ((unsigned int)(*speedbin) + 4); - break; - default: diff --git a/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch b/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch deleted file mode 100644 index cbb9172032..0000000000 --- a/target/linux/generic/backport-6.6/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch +++ /dev/null @@ -1,170 +0,0 @@ -From fe2b1226656afae56702d1d84c6900f6b67df297 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 1 Dec 2023 11:23:22 +0100 -Subject: [PATCH] leds: trigger: netdev: fix RTNL handling to prevent potential - deadlock - -When working on LED support for r8169 I got the following lockdep -warning. Easiest way to prevent this scenario seems to be to take -the RTNL lock before the trigger_data lock in set_device_name(). - -====================================================== -WARNING: possible circular locking dependency detected -6.7.0-rc2-next-20231124+ #2 Not tainted ------------------------------------------------------- -bash/383 is trying to acquire lock: -ffff888103aa1c68 (&trigger_data->lock){+.+.}-{3:3}, at: netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - -but task is already holding lock: -ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 - -which lock already depends on the new lock. - -the existing dependency chain (in reverse order) is: - --> #1 (rtnl_mutex){+.+.}-{3:3}: - __mutex_lock+0x9b/0xb50 - mutex_lock_nested+0x16/0x20 - rtnl_lock+0x12/0x20 - set_device_name+0xa9/0x120 [ledtrig_netdev] - netdev_trig_activate+0x1a1/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - --> #0 (&trigger_data->lock){+.+.}-{3:3}: - __lock_acquire+0x1459/0x25a0 - lock_acquire+0xc8/0x2d0 - __mutex_lock+0x9b/0xb50 - mutex_lock_nested+0x16/0x20 - netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - call_netdevice_register_net_notifiers+0x5a/0x100 - register_netdevice_notifier+0x85/0x120 - netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - -other info that might help us debug this: - - Possible unsafe locking scenario: - - CPU0 CPU1 - ---- ---- - lock(rtnl_mutex); - lock(&trigger_data->lock); - lock(rtnl_mutex); - lock(&trigger_data->lock); - - *** DEADLOCK *** - -8 locks held by bash/383: - #0: ffff888103ff33f0 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x6c/0xf0 - #1: ffff888103aa1e88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x114/0x210 - #2: ffff8881036f1890 (kn->active#82){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x11d/0x210 - #3: ffff888108e2c358 (&led_cdev->led_access){+.+.}-{3:3}, at: led_trigger_write+0x30/0x140 - #4: ffffffff8cdd9e10 (triggers_list_lock){++++}-{3:3}, at: led_trigger_write+0x75/0x140 - #5: ffff888108e2c270 (&led_cdev->trigger_lock){++++}-{3:3}, at: led_trigger_write+0xe3/0x140 - #6: ffffffff8cdde3d0 (pernet_ops_rwsem){++++}-{3:3}, at: register_netdevice_notifier+0x1c/0x120 - #7: ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 - -stack backtrace: -CPU: 0 PID: 383 Comm: bash Not tainted 6.7.0-rc2-next-20231124+ #2 -Hardware name: Default string Default string/Default string, BIOS ADLN.M6.SODIMM.ZB.CY.015 08/08/2023 -Call Trace: - - dump_stack_lvl+0x5c/0xd0 - dump_stack+0x10/0x20 - print_circular_bug+0x2dd/0x410 - check_noncircular+0x131/0x150 - __lock_acquire+0x1459/0x25a0 - lock_acquire+0xc8/0x2d0 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - __mutex_lock+0x9b/0xb50 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - ? __this_cpu_preempt_check+0x13/0x20 - ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - ? __cancel_work_timer+0x11c/0x1b0 - ? __mutex_lock+0x123/0xb50 - mutex_lock_nested+0x16/0x20 - ? mutex_lock_nested+0x16/0x20 - netdev_trig_notify+0xec/0x190 [ledtrig_netdev] - call_netdevice_register_net_notifiers+0x5a/0x100 - register_netdevice_notifier+0x85/0x120 - netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] - led_trigger_set+0x172/0x2c0 - ? preempt_count_add+0x49/0xc0 - led_trigger_write+0xf1/0x140 - sysfs_kf_bin_write+0x5d/0x80 - kernfs_fop_write_iter+0x15d/0x210 - vfs_write+0x1f0/0x510 - ksys_write+0x6c/0xf0 - __x64_sys_write+0x14/0x20 - do_syscall_64+0x3f/0xf0 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 -RIP: 0033:0x7f269055d034 -Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d 35 c3 0d 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 48 89 54 24 18 48 -RSP: 002b:00007ffddb7ef748 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 -RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 00007f269055d034 -RDX: 0000000000000007 RSI: 000055bf5f4af3c0 RDI: 0000000000000001 -RBP: 000055bf5f4af3c0 R08: 0000000000000073 R09: 0000000000000001 -R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000007 -R13: 00007f26906325c0 R14: 00007f269062ff20 R15: 0000000000000000 - - -Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") -Cc: stable@vger.kernel.org -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Acked-by: Lee Jones -Link: https://lore.kernel.org/r/fb5c8294-2a10-4bf5-8f10-3d2b77d2757e@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/leds/trigger/ledtrig-netdev.c -+++ b/drivers/leds/trigger/ledtrig-netdev.c -@@ -235,6 +235,11 @@ static int set_device_name(struct led_ne - { - cancel_delayed_work_sync(&trigger_data->work); - -+ /* -+ * Take RTNL lock before trigger_data lock to prevent potential -+ * deadlock with netdev notifier registration. -+ */ -+ rtnl_lock(); - mutex_lock(&trigger_data->lock); - - if (trigger_data->net_dev) { -@@ -254,16 +259,14 @@ static int set_device_name(struct led_ne - trigger_data->carrier_link_up = false; - trigger_data->link_speed = SPEED_UNKNOWN; - trigger_data->duplex = DUPLEX_UNKNOWN; -- if (trigger_data->net_dev != NULL) { -- rtnl_lock(); -+ if (trigger_data->net_dev) - get_device_state(trigger_data); -- rtnl_unlock(); -- } - - trigger_data->last_activity = 0; - - set_baseline_state(trigger_data); - mutex_unlock(&trigger_data->lock); -+ rtnl_unlock(); - - return 0; - } diff --git a/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch b/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch deleted file mode 100644 index 51b4bbbfcb..0000000000 --- a/target/linux/generic/backport-6.6/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9b78d919632b7149d311aaad5a977e4b48b10321 Mon Sep 17 00:00:00 2001 -From: Paolo Abeni -Date: Wed, 26 Apr 2023 10:15:31 +0200 -Subject: [PATCH] net: phy: hide the PHYLIB_LEDS knob - -commit 4bb7aac70b5d ("net: phy: fix circular LEDS_CLASS dependencies") -solved a build failure, but introduces a new config knob with a default -'y' value: PHYLIB_LEDS. - -The latter is against the current new config policy. The exception -was raised to allow the user to catch bad configurations without led -support. - -Anyway the current definition of PHYLIB_LEDS does not fit the above -goal: if LEDS_CLASS is disabled, the new config will be available -only with PHYLIB disabled, too. - -Hide the mentioned config, to preserve the randconfig testing done so -far, while respecting the mentioned policy. - -Suggested-by: Andrew Lunn -Suggested-by: Arnd Bergmann -Signed-off-by: Paolo Abeni -Link: https://lore.kernel.org/r/d82489be8ed911c383c3447e9abf469995ccf39a.1682496488.git.pabeni@redhat.com -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/Kconfig | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -45,10 +45,8 @@ config LED_TRIGGER_PHY - for any speed known to the PHY. - - config PHYLIB_LEDS -- bool "Support probing LEDs from device tree" -+ def_bool OF - depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB -- depends on OF -- default y - help - When LED class support is enabled, phylib can automatically - probe LED setting from device tree. diff --git a/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch b/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch deleted file mode 100644 index 38fbc3a3d7..0000000000 --- a/target/linux/generic/backport-6.6/890-v6.2-mtd-spinand-winbond-fix-flash-detection.patch +++ /dev/null @@ -1,40 +0,0 @@ -From dbf70fc204d2fbb0d8ad8f42038a60846502efda Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Oct 2022 13:51:09 +0300 -Subject: [PATCH] mtd: spinand: winbond: fix flash identification - -Winbond uses 3 bytes to identify flash: vendor_id, dev_id_0, dev_id_1, -but current driver uses only first 2 bytes of it for devices -identification. As result Winbond W25N02KV flash (id_bytes: EF, AA, 22) -is identified as W25N01GV (id_bytes: EF, AA, 21). - -Fix this by adding missed identification bytes. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Frieder Schrempf -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-1-mikhail.kshevetskiy@iopsys.eu ---- - drivers/mtd/nand/spi/winbond.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -76,7 +76,7 @@ static int w25m02gv_select_target(struct - - static const struct spinand_info winbond_spinand_table[] = { - SPINAND_INFO("W25M02GV", -- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab), -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), - NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -@@ -86,7 +86,7 @@ static const struct spinand_info winbond - SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), - SPINAND_SELECT_TARGET(w25m02gv_select_target)), - SPINAND_INFO("W25N01GV", -- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa), -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), - NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, diff --git a/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch b/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch deleted file mode 100644 index d75a1acc57..0000000000 --- a/target/linux/generic/backport-6.6/891-v6.2-mtd-spinand-winbond-add-W25N02KV.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 6154c7a583483d7b69f53bea868efdc369edd563 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Oct 2022 13:51:10 +0300 -Subject: [PATCH] mtd: spinand: winbond: add Winbond W25N02KV flash support - -Add support of Winbond W25N02KV flash - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Frieder Schrempf -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20221010105110.446674-2-mikhail.kshevetskiy@iopsys.eu ---- - drivers/mtd/nand/spi/winbond.c | 75 ++++++++++++++++++++++++++++++++++ - 1 file changed, 75 insertions(+) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -74,6 +74,72 @@ static int w25m02gv_select_target(struct - return spi_mem_exec_op(spinand->spimem, &op); - } - -+static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = 64 + (16 * section); -+ region->length = 13; -+ -+ return 0; -+} -+ -+static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 2; -+ region->length = 14; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { -+ .ecc = w25n02kv_ooblayout_ecc, -+ .free = w25n02kv_ooblayout_free, -+}; -+ -+static int w25n02kv_ecc_get_status(struct spinand_device *spinand, -+ u8 status) -+{ -+ struct nand_device *nand = spinand_to_nand(spinand); -+ u8 mbf = 0; -+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); -+ -+ switch (status & STATUS_ECC_MASK) { -+ case STATUS_ECC_NO_BITFLIPS: -+ return 0; -+ -+ case STATUS_ECC_UNCOR_ERROR: -+ return -EBADMSG; -+ -+ case STATUS_ECC_HAS_BITFLIPS: -+ /* -+ * Let's try to retrieve the real maximum number of bitflips -+ * in order to avoid forcing the wear-leveling layer to move -+ * data around if it's not necessary. -+ */ -+ if (spi_mem_exec_op(spinand->spimem, &op)) -+ return nanddev_get_ecc_conf(nand)->strength; -+ -+ mbf >>= 4; -+ -+ if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) -+ return nanddev_get_ecc_conf(nand)->strength; -+ -+ return mbf; -+ -+ default: -+ break; -+ } -+ -+ return -EINVAL; -+} -+ - static const struct spinand_info winbond_spinand_table[] = { - SPINAND_INFO("W25M02GV", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), -@@ -94,6 +160,15 @@ static const struct spinand_info winbond - &update_cache_variants), - 0, - SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), -+ SPINAND_INFO("W25N02KV", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), -+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), -+ NAND_ECCREQ(8, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ 0, -+ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), - }; - - static int winbond_spinand_init(struct spinand_device *spinand) diff --git a/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch b/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch deleted file mode 100644 index 2f408f5a30..0000000000 --- a/target/linux/generic/backport-6.6/892-v6.5-mtd-spinand-winbond-Fix-ecc_get_status.patch +++ /dev/null @@ -1,49 +0,0 @@ -From f5a05060670a4d8d6523afc7963eb559c2e3615f Mon Sep 17 00:00:00 2001 -From: Olivier Maignial -Date: Fri, 23 Jun 2023 17:33:37 +0200 -Subject: [PATCH] mtd: spinand: winbond: Fix ecc_get_status - -Reading ECC status is failing. - -w25n02kv_ecc_get_status() is using on-stack buffer for -SPINAND_GET_FEATURE_OP() output. It is not suitable for -DMA needs of spi-mem. - -Fix this by using the spi-mem operations dedicated buffer -spinand->scratchbuf. - -See -spinand->scratchbuf: -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/mtd/spinand.h?h=v6.3#n418 -spi_mem_check_op(): -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/spi/spi-mem.c?h=v6.3#n199 - -Fixes: 6154c7a58348 ("mtd: spinand: winbond: add Winbond W25N02KV flash support") -Cc: stable@vger.kernel.org -Signed-off-by: Olivier Maignial -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/DB4P250MB1032EDB9E36B764A33769039FE23A@DB4P250MB1032.EURP250.PROD.OUTLOOK.COM ---- - drivers/mtd/nand/spi/winbond.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/winbond.c -+++ b/drivers/mtd/nand/spi/winbond.c -@@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struc - { - struct nand_device *nand = spinand_to_nand(spinand); - u8 mbf = 0; -- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); -+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); - - switch (status & STATUS_ECC_MASK) { - case STATUS_ECC_NO_BITFLIPS: -@@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struc - if (spi_mem_exec_op(spinand->spimem, &op)) - return nanddev_get_ecc_conf(nand)->strength; - -- mbf >>= 4; -+ mbf = *(spinand->scratchbuf) >> 4; - - if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) - return nanddev_get_ecc_conf(nand)->strength; From 1057d9b39d1b813705289a274982c194f8bd1a31 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 01:49:26 +0800 Subject: [PATCH 042/108] generic: 6.6: drop pending patch backported as fixes Drop pending patch backported as fixes in later kernel version. Signed-off-by: Weijie Gao --- ...ilicon-Labs-EM3581-device-compatible.patch | 32 -- ...ilicon-Labs-SI3210-device-compatible.patch | 32 -- ...able_wilink_platform_without_drivers.patch | 20 - ...ip-bcm-6345-l1-request-memory-region.patch | 113 ------ ...nand-add-support-for-ESMT-F50x1G41LB.patch | 143 -------- ..._eth_soc-fix-remaining-throughput-re.patch | 42 --- ..._eth_soc-ppe-fix-L2-offloading-with-.patch | 33 -- ..._eth_soc-set-coherent-mask-to-get-PP.patch | 46 --- ...a-b53-add-support-for-BCM63xx-RGMIIs.patch | 174 --------- ...-net-dsa-b53-mmap-add-more-63xx-SoCs.patch | 108 ------ ...dsa-b53-mmap-allow-passing-a-chip-ID.patch | 195 ---------- ...b53-add-BCM63268-RGMII-configuration.patch | 123 ------- ...sa-b53-mdio-add-support-for-BCM53134.patch | 189 ---------- ...-fix-10M-100M-speed-on-MT7988-switch.patch | 45 --- ...add-BCM63268-timer-clock-definitions.patch | 114 ------ ...add-BCM63268-timer-reset-definitions.patch | 107 ------ ...CM63268-timer-clock-and-reset-driver.patch | 345 ------------------ ...rack-busclk-state-to-avoid-bus-error.patch | 61 ---- 18 files changed, 1922 deletions(-) delete mode 100644 target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch delete mode 100644 target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch delete mode 100644 target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch delete mode 100644 target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch delete mode 100644 target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch delete mode 100644 target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch delete mode 100644 target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch delete mode 100644 target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch delete mode 100644 target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch delete mode 100644 target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch delete mode 100644 target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch delete mode 100644 target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch delete mode 100644 target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch delete mode 100644 target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch delete mode 100644 target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch delete mode 100644 target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch delete mode 100644 target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch delete mode 100644 target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch diff --git a/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch b/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch deleted file mode 100644 index ebeeae2f8f..0000000000 --- a/target/linux/generic/pending-6.6/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f7982c726e02001afc19052fe48f642dfcbc00b2 Mon Sep 17 00:00:00 2001 -From: Vincent Tremblay -Date: Mon, 26 Dec 2022 21:10:37 -0500 -Subject: [PATCH 1/2] spidev: Add Silicon Labs EM3581 device compatible - -Add compatible string for Silicon Labs EM3581 device. - -Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). - -Signed-off-by: Vincent Tremblay ---- - drivers/spi/spidev.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/spi/spidev.c -+++ b/drivers/spi/spidev.c -@@ -700,6 +700,7 @@ static const struct spi_device_id spidev - { .name = "m53cpld" }, - { .name = "spi-petra" }, - { .name = "spi-authenta" }, -+ { .name = "em3581" }, - {}, - }; - MODULE_DEVICE_TABLE(spi, spidev_spi_ids); -@@ -726,6 +727,7 @@ static const struct of_device_id spidev_ - { .compatible = "menlo,m53cpld", .data = &spidev_of_check }, - { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, - { .compatible = "micron,spi-authenta", .data = &spidev_of_check }, -+ { .compatible = "silabs,em3581", .data = &spidev_of_check }, - {}, - }; - MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch b/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch deleted file mode 100644 index db5b5800f4..0000000000 --- a/target/linux/generic/pending-6.6/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 536581825219e97fa2ae0c4de35605d2f6311416 Mon Sep 17 00:00:00 2001 -From: Vincent Tremblay -Date: Tue, 27 Dec 2022 09:00:58 -0500 -Subject: [PATCH 2/2] spidev: Add Silicon Labs SI3210 device compatible - -Add compatible string for Silicon Labs SI3210 device. - -Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). - -Signed-off-by: Vincent Tremblay ---- - drivers/spi/spidev.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/spi/spidev.c -+++ b/drivers/spi/spidev.c -@@ -701,6 +701,7 @@ static const struct spi_device_id spidev - { .name = "spi-petra" }, - { .name = "spi-authenta" }, - { .name = "em3581" }, -+ { .name = "si3210" }, - {}, - }; - MODULE_DEVICE_TABLE(spi, spidev_spi_ids); -@@ -728,6 +729,7 @@ static const struct of_device_id spidev_ - { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, - { .compatible = "micron,spi-authenta", .data = &spidev_of_check }, - { .compatible = "silabs,em3581", .data = &spidev_of_check }, -+ { .compatible = "silabs,si3210", .data = &spidev_of_check }, - {}, - }; - MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch b/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch deleted file mode 100644 index cd31f9d934..0000000000 --- a/target/linux/generic/pending-6.6/261-enable_wilink_platform_without_drivers.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Imre Kaloz -Subject: [PATCH] hack: net: wireless: make the wl12xx glue code available with - compat-wireless, too - -Signed-off-by: Imre Kaloz ---- - drivers/net/wireless/ti/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ti/Kconfig -+++ b/drivers/net/wireless/ti/Kconfig -@@ -20,7 +20,7 @@ source "drivers/net/wireless/ti/wlcore/K - - config WILINK_PLATFORM_DATA - bool "TI WiLink platform data" -- depends on WLCORE_SDIO || WL1251_SDIO -+ depends on WLCORE_SDIO || WL1251_SDIO || ARCH_OMAP2PLUS - default y - help - Small platform data bit needed to pass data to the sdio modules. diff --git a/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch b/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch deleted file mode 100644 index 2675ca4791..0000000000 --- a/target/linux/generic/pending-6.6/351-irqchip-bcm-6345-l1-request-memory-region.patch +++ /dev/null @@ -1,113 +0,0 @@ -From patchwork Thu Mar 16 19:28:33 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13178238 -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 5EF2AC6FD19 - for ; Thu, 16 Mar 2023 19:28:43 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230076AbjCPT2l (ORCPT ); - Thu, 16 Mar 2023 15:28:41 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56412 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S230039AbjCPT2k (ORCPT - ); Thu, 16 Mar 2023 15:28:40 -0400 -Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com - [IPv6:2a00:1450:4864:20::42f]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7259B7D9F; - Thu, 16 Mar 2023 12:28:38 -0700 (PDT) -Received: by mail-wr1-x42f.google.com with SMTP id y14so2539231wrq.4; - Thu, 16 Mar 2023 12:28:38 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1678994917; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=j8afldfRZftLeVmekmQfoh01jVdumsVP7nkKoPaU3Q0=; - b=FzMRr5ekh/fDiJqTlezNj6nLjzvn5z92FtYeB8MquVSMB8PuvarccnyqAzsXiccf+v - uwRFIomnTWNLGVjzc1xrB2hGiCKD3jBo5n1u8p/yEV6rpolbxVjfM7eTHXyAHXGXz7ZJ - TPeVbWfAlxiSD6+BPtXr/efehcdI64fIoL6G/U1WHNMo01Tzr/Obf3y5tug17N0fGcXg - CH6E5a2HguZUtwrm26LcK9IOV/7xEx5eIE1cOvTLMxPbGWaZwEjjP16HylJr06xRLhaf - RpiYBT3mXwwuOx0jLOhqavY/2kZ9GVbZRWMMwZrZv9xNO13SBwc1VUVgD4k3FntnSk7Z - AaOQ== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1678994917; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=j8afldfRZftLeVmekmQfoh01jVdumsVP7nkKoPaU3Q0=; - b=OaA5DMgqalrfqO5iOtmmxFPsH90MkN7l4EJpyVnzuiO1Wd6rSCpqPOR7xpxZno8OPP - tdfm4vzn9Ie4AUDbFKDTUlPG+tgkmIruo3K9C0VnY9DD2PRZMEYBbWaJKU1otqKt0NKu - IAAHNvxvQvCESKzbXFLYwWbRKFScOSMGmGBTDfgThz51A18Ff1hJy/BmnuZk7M2TLgHO - wQpy9t7oeB/Hkxl41y46emLc/nESsvwvAG/fx/zPzCe9UiaQLrdZq+BKeOwSBedktzK5 - U/ZTfgzU2UGSI67aGRqqGnI0uXq+MAJMK18qzM0VByxj6W+AXJ6BJr5P0quljeQ8upSg - bEUg== -X-Gm-Message-State: AO0yUKWnqTlccBDnqwCSRdqOBGc2FyfiLy1Tg7EjPENlISpzXuDYwW/R - lJSI06rrfq+Vel/SigfpGJI= -X-Google-Smtp-Source: - AK7set/jYfYl9ttVzIXJO+ZQVfa6cE/yOsP8fx4teiTmGNNWyVlIJRzMAlF3IUGqRAXAmY3hAabIuQ== -X-Received: by 2002:a5d:40ce:0:b0:2cd:ceab:df1a with SMTP id - b14-20020a5d40ce000000b002cdceabdf1amr381006wrq.32.1678994916642; - Thu, 16 Mar 2023 12:28:36 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - l10-20020a5d4bca000000b002cfea3c49d5sm180041wrt.52.2023.03.16.12.28.35 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Thu, 16 Mar 2023 12:28:35 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: f.fainelli@gmail.com, jonas.gorski@gmail.com, - bcm-kernel-feedback-list@broadcom.com, tglx@linutronix.de, - maz@kernel.org, linux-mips@vger.kernel.org, - linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v2] irqchip/bcm-6345-l1: request memory region -Date: Thu, 16 Mar 2023 20:28:33 +0100 -Message-Id: <20230316192833.1603149-1-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230316180701.783785-1-noltari@gmail.com> -References: <20230316180701.783785-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-mips@vger.kernel.org - -Request memory region in order to display it in /proc/iomem. -Also stop printing the MMIO address since it just displays (ptrval). - -Signed-off-by: Álvaro Fernández Rojas -Acked-by: Florian Fainelli ---- - v2: request memory region and stop displaying MMIO address. - - drivers/irqchip/irq-bcm6345-l1.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/irqchip/irq-bcm6345-l1.c -+++ b/drivers/irqchip/irq-bcm6345-l1.c -@@ -253,6 +253,9 @@ static int __init bcm6345_l1_init_one(st - if (!cpu->map_base) - return -ENOMEM; - -+ if (!request_mem_region(res.start, sz, res.name)) -+ pr_err("failed to request intc memory"); -+ - for (i = 0; i < n_words; i++) { - cpu->enable_cache[i] = 0; - __raw_writel(0, cpu->map_base + reg_enable(intc, i)); -@@ -331,8 +334,7 @@ static int __init bcm6345_l1_of_init(str - for_each_cpu(idx, &intc->cpumask) { - struct bcm6345_l1_cpu *cpu = intc->cpus[idx]; - -- pr_info(" CPU%u at MMIO 0x%p (irq = %d)\n", idx, -- cpu->map_base, cpu->parent_irq); -+ pr_info(" CPU%u (irq = %d)\n", idx, cpu->parent_irq); - } - - return 0; diff --git a/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch b/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch deleted file mode 100644 index b8116db842..0000000000 --- a/target/linux/generic/pending-6.6/486-01-mtd-spinand-add-support-for-ESMT-F50x1G41LB.patch +++ /dev/null @@ -1,143 +0,0 @@ -From a43b844cb40bf1b783055fdc81b7f991e21e7e76 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Wed, 13 Apr 2022 11:58:17 +0800 -Subject: [PATCH] mtd: spinand: add support for ESMT F50x1G41LB - -This patch adds support for ESMT F50L1G41LB and F50D1G41LB. -It seems that ESMT likes to use random JEDEC ID from other vendors. -Their 1G chips uses 0xc8 from GigaDevice and 2G/4G chips uses 0x2c from -Micron. For this reason, the ESMT entry is named esmt_c8 with explicit -JEDEC ID in variable name. - -Datasheets: -https://www.esmt.com.tw/upload/pdf/ESMT/datasheets/F50L1G41LB(2M).pdf -https://www.esmt.com.tw/upload/pdf/ESMT/datasheets/F50D1G41LB(2M).pdf - -Signed-off-by: Chuanhong Guo ---- - drivers/mtd/nand/spi/Makefile | 2 +- - drivers/mtd/nand/spi/core.c | 1 + - drivers/mtd/nand/spi/esmt.c | 89 +++++++++++++++++++++++++++++++++++ - include/linux/mtd/spinand.h | 1 + - 4 files changed, 92 insertions(+), 1 deletion(-) - create mode 100644 drivers/mtd/nand/spi/esmt.c - ---- a/drivers/mtd/nand/spi/Makefile -+++ b/drivers/mtd/nand/spi/Makefile -@@ -1,3 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o ato.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o ato.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o - obj-$(CONFIG_MTD_SPI_NAND) += spinand.o ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -938,6 +938,7 @@ static const struct nand_ops spinand_ops - - static const struct spinand_manufacturer *spinand_manufacturers[] = { - &ato_spinand_manufacturer, -+ &esmt_c8_spinand_manufacturer, - &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, - µn_spinand_manufacturer, ---- /dev/null -+++ b/drivers/mtd/nand/spi/esmt.c -@@ -0,0 +1,89 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Author: -+ * Chuanhong Guo -+ */ -+ -+#include -+#include -+#include -+ -+/* ESMT uses GigaDevice 0xc8 JECDEC ID on some SPI NANDs */ -+#define SPINAND_MFR_ESMT_C8 0xc8 -+ -+static SPINAND_OP_VARIANTS(read_cache_variants, -+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(write_cache_variants, -+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), -+ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(update_cache_variants, -+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), -+ SPINAND_PROG_LOAD(false, 0, NULL, 0)); -+ -+static int f50l1g41lb_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = 16 * section + 8; -+ region->length = 8; -+ -+ return 0; -+} -+ -+static int f50l1g41lb_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = 16 * section + 2; -+ region->length = 6; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = { -+ .ecc = f50l1g41lb_ooblayout_ecc, -+ .free = f50l1g41lb_ooblayout_free, -+}; -+ -+static const struct spinand_info esmt_c8_spinand_table[] = { -+ SPINAND_INFO("F50L1G41LB", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(1, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ 0, -+ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), -+ SPINAND_INFO("F50D1G41LB", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(1, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ 0, -+ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), -+}; -+ -+static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = { -+}; -+ -+const struct spinand_manufacturer esmt_c8_spinand_manufacturer = { -+ .id = SPINAND_MFR_ESMT_C8, -+ .name = "ESMT", -+ .chips = esmt_c8_spinand_table, -+ .nchips = ARRAY_SIZE(esmt_c8_spinand_table), -+ .ops = &esmt_spinand_manuf_ops, -+}; ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -261,6 +261,7 @@ struct spinand_manufacturer { - - /* SPI NAND manufacturers */ - extern const struct spinand_manufacturer ato_spinand_manufacturer; -+extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; - extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; - extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch b/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch deleted file mode 100644 index 0a49c75b00..0000000000 --- a/target/linux/generic/pending-6.6/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Felix Fietkau -Date: Wed, 29 Mar 2023 16:02:54 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix remaining throughput - regression - -Based on further tests, it seems that the QDMA shaper is not able to -perform shaping close to the MAC link rate without throughput loss. -This cannot be compensated by increasing the shaping rate, so it seems -to be an internal limit. - -Fix the remaining throughput regression by detecting that condition and -limiting shaping to ports with lower link speed. - -This patch intentionally ignores link speed gain from TRGMII, because -even on such links, shaping to 1000 Mbit/s incurs some throughput -degradation. - -Fixes: f63959c7eec3 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") -Reported-by: Frank Wunderlich -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -767,6 +767,7 @@ static void mtk_mac_link_up(struct phyli - MAC_MCR_FORCE_RX_FC); - - /* Configure speed */ -+ mac->speed = speed; - switch (speed) { - case SPEED_2500: - case SPEED_1000: -@@ -3348,6 +3349,9 @@ found: - if (dp->index >= MTK_QDMA_NUM_QUEUES) - return NOTIFY_DONE; - -+ if (mac->speed > 0 && mac->speed <= s.base.speed) -+ s.base.speed = 0; -+ - mtk_set_queue_speed(eth, dp->index + 3, s.base.speed); - - return NOTIFY_DONE; diff --git a/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch b/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch deleted file mode 100644 index 61042c1ad0..0000000000 --- a/target/linux/generic/pending-6.6/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Felix Fietkau -Date: Tue, 27 Dec 2022 15:02:51 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: ppe: fix L2 offloading with DSA - untagging offload enabled - -Check for skb metadata in order to detect the case where the DSA header is not -present. - -Fixes: 2d7605a72906 ("net: ethernet: mtk_eth_soc: enable hardware DSA untagging") -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include "mtk_eth_soc.h" - #include "mtk_ppe.h" -@@ -829,7 +830,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe - skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) - goto out; - -- tag += 4; -+ if (!skb_metadata_dst(skb)) -+ tag += 4; -+ - if (get_unaligned_be16(tag) != ETH_P_8021Q) - break; - diff --git a/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch b/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch deleted file mode 100644 index b598d15866..0000000000 --- a/target/linux/generic/pending-6.6/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch +++ /dev/null @@ -1,46 +0,0 @@ -From dee3f591103910c8d8b2a6d57879ccd2a4be4b10 Mon Sep 17 00:00:00 2001 -Message-ID: -From: Daniel Golle -Date: Wed, 24 Jan 2024 03:19:49 +0000 -Subject: [PATCH net] net: ethernet: mtk_eth_soc: set coherent mask to get PPE - working -To: Felix Fietkau , - Sean Wang , - Mark Lee , - Lorenzo Bianconi , - David S. Miller , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Matthias Brugger , - AngeloGioacchino Del Regno , - Daniel Golle , - netdev@vger.kernel.org, - linux-kernel@vger.kernel.org, - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org - -Set DMA coherent mask to 32-bit which makes PPE offloading engine start -working on BPi-R4 which got 4 GiB of RAM. - -Fixes: 2d75891ebc09 ("net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988") -Suggested-by: Elad Yifee -Signed-off-by: Daniel Golle ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4963,7 +4963,10 @@ static int mtk_probe(struct platform_dev - } - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { -- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); -+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); -+ if (!err) -+ err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); -+ - if (err) { - dev_err(&pdev->dev, "Wrong DMA config\n"); - return -EINVAL; diff --git a/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch b/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch deleted file mode 100644 index 23859816fa..0000000000 --- a/target/linux/generic/pending-6.6/772-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch +++ /dev/null @@ -1,174 +0,0 @@ -From patchwork Sun Mar 19 22:08:05 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13180645 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id A7A46C6FD1F - for ; Sun, 19 Mar 2023 22:08:15 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230223AbjCSWIN (ORCPT ); - Sun, 19 Mar 2023 18:08:13 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32878 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S229565AbjCSWIM (ORCPT - ); Sun, 19 Mar 2023 18:08:12 -0400 -Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com - [IPv6:2a00:1450:4864:20::42e]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 605D3E062; - Sun, 19 Mar 2023 15:08:10 -0700 (PDT) -Received: by mail-wr1-x42e.google.com with SMTP id h17so8695188wrt.8; - Sun, 19 Mar 2023 15:08:10 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679263689; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=GmPK75Q9ZD3h3IYflWYuDwS99V2e532KgDlnNucAoJg=; - b=PSdrywW48P4Lq8z9wOSPXFB/ZdO/JfuyiGlw3Gz1Iriy+Smo/cBnJ0Ve9zKkX3AKTO - Tr7/g8xhSQX8sU5WAOEPC13uVjKpO4VZsamXHTmMKL4mmfII3K/piAsQcMQkkNpgouab - Ci9yr+7ASSmqEUHIbYTM6sl6a47rPwqk3b3DcTIE2CwJsPPNXnpQ/aSVbJAcEdhcZICc - X4rAmjrYjcsl8coFIGHHPlrMH9ShekQWxB84vEb6bO1nXOORNPizOHuY1vJ3wa3WgXsx - YwlvutMFVIUXfgL2ZwCmQAKWJPiAaFk+CCk3oxSeOYoAzkjcbMyapz9VnooStfvR2aV3 - k+2g== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679263689; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=GmPK75Q9ZD3h3IYflWYuDwS99V2e532KgDlnNucAoJg=; - b=NGjqrGERyaxRwINtevHaY97h9X9W+1UY62YYwotqwv5+cfvB8myjBbD3WH2WzaqMes - o9MMER9RE8/arW3jIVlBv4ORDUuEZ7AeGgy5UbFyQZIPHlp+hJ/sxFrGvYUwamg4Qrr9 - ojargh8ORsEiMeqaf+5AkmEagNhrrV3ax0pUuWDzbJ3vXGoHjfCetHz5xyNL46dvXBfb - l/OZqjv9IYob552uUoUmCy/TbEQDqvmjkFrROFK9gtBNxgxUJkwbyiWIOVsf6RR8OarP - f7bbvSJYkvTvzx2u/g0Up7NW5ZyihMGBmDs377M3yW6AnSxW6jlfl30QmMU1aEigYXvy - v3mA== -X-Gm-Message-State: AO0yUKUm1PYmYa4xlHuVD23mZcZm83a+xbhcbs0Xryi3yF/+UnjM4Cho - GAfqSh5MZ/rlOAm3Vnpn//9hOG5Lc8vLYg== -X-Google-Smtp-Source: - AK7set+5pTahGGgk1hF/mHGkGBhsMf0//oQjZd4QFHx+HaeSgP5f6q7g0bRUcTX8kRtgHH0T7l1/hQ== -X-Received: by 2002:a5d:474f:0:b0:2d6:2ae8:70d with SMTP id - o15-20020a5d474f000000b002d62ae8070dmr2382593wrs.39.1679263688549; - Sun, 19 Mar 2023 15:08:08 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - d6-20020a5d6dc6000000b002c53f6c7599sm7354727wrz.29.2023.03.19.15.08.07 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Sun, 19 Mar 2023 15:08:07 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, - olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, - kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org, - linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v2] net: dsa: b53: add support for BCM63xx RGMIIs -Date: Sun, 19 Mar 2023 23:08:05 +0100 -Message-Id: <20230319220805.124024-1-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230319183330.761251-1-noltari@gmail.com> -References: <20230319183330.761251-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -BCM63xx RGMII ports require additional configuration in order to work. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Andrew Lunn ---- - v2: add changes suggested by Andrew: - - Use a switch statement. - - Use dev_dbg() instead of dev_info(). - - drivers/net/dsa/b53/b53_common.c | 46 ++++++++++++++++++++++++++++++++ - drivers/net/dsa/b53/b53_priv.h | 1 + - 2 files changed, 47 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1209,6 +1209,46 @@ static void b53_force_port_config(struct - b53_write8(dev, B53_CTRL_PAGE, off, reg); - } - -+static void b53_adjust_63xx_rgmii(struct dsa_switch *ds, int port, -+ phy_interface_t interface) -+{ -+ struct b53_device *dev = ds->priv; -+ u8 rgmii_ctrl = 0, off; -+ -+ if (port == dev->imp_port) -+ off = B53_RGMII_CTRL_IMP; -+ else -+ off = B53_RGMII_CTRL_P(port); -+ -+ b53_read8(dev, B53_CTRL_PAGE, off, &rgmii_ctrl); -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ rgmii_ctrl |= (RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ rgmii_ctrl &= ~(RGMII_CTRL_DLL_TXC); -+ rgmii_ctrl |= RGMII_CTRL_DLL_RXC; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC); -+ rgmii_ctrl |= RGMII_CTRL_DLL_TXC; -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ default: -+ rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); -+ break; -+ } -+ -+ if (port != dev->imp_port) -+ rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; -+ -+ b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); -+ -+ dev_dbg(ds->dev, "Configured port %d for %s\n", port, -+ phy_modes(interface)); -+} -+ - static void b53_adjust_link(struct dsa_switch *ds, int port, - struct phy_device *phydev) - { -@@ -1235,6 +1275,9 @@ static void b53_adjust_link(struct dsa_s - tx_pause, rx_pause); - b53_force_link(dev, port, phydev->link); - -+ if (is63xx(dev) && port >= B53_63XX_RGMII0) -+ b53_adjust_63xx_rgmii(ds, port, phydev->interface); -+ - if (is531x5(dev) && phy_interface_is_rgmii(phydev)) { - if (port == dev->imp_port) - off = B53_RGMII_CTRL_IMP; -@@ -1402,6 +1445,9 @@ void b53_phylink_mac_link_up(struct dsa_ - { - struct b53_device *dev = ds->priv; - -+ if (is63xx(dev) && port >= B53_63XX_RGMII0) -+ b53_adjust_63xx_rgmii(ds, port, interface); -+ - if (mode == MLO_AN_PHY) - return; - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -211,6 +211,7 @@ static inline int is58xx(struct b53_devi - dev->chip_id == BCM7278_DEVICE_ID; - } - -+#define B53_63XX_RGMII0 4 - #define B53_CPU_PORT_25 5 - #define B53_CPU_PORT 8 - diff --git a/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch b/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch deleted file mode 100644 index 8ab701ef56..0000000000 --- a/target/linux/generic/pending-6.6/773-net-dsa-b53-mmap-add-more-63xx-SoCs.patch +++ /dev/null @@ -1,108 +0,0 @@ -From patchwork Tue Mar 21 17:33:57 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13183003 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 823A1C761AF - for ; Tue, 21 Mar 2023 17:35:06 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230490AbjCURfE (ORCPT ); - Tue, 21 Mar 2023 13:35:04 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47440 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S230357AbjCURex (ORCPT - ); Tue, 21 Mar 2023 13:34:53 -0400 -Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com - [IPv6:2a00:1450:4864:20::430]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C9A45559D8; - Tue, 21 Mar 2023 10:34:26 -0700 (PDT) -Received: by mail-wr1-x430.google.com with SMTP id m2so14547588wrh.6; - Tue, 21 Mar 2023 10:34:26 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679420063; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=cUvnluVaZPzfEQB9fMRuYo+4/361t/7po7nyUBBJfxc=; - b=F0pa8JmQZ1FeXVtdpCygur8UmLrgKwxCcjaMn312u5zNvsXsEPeCAIDqP2tvNNTwv/ - UYjaNaoZ77HSvv/gSqeG808AXGyNs1PvLuHZYuUTJRNuLaMixKtkNFi4ypheCdk0WCiE - IWz0DIm6ojmdwMqafDUKQ6Qwkv5R0vo8Wh5vpjimEmCelOyMvfuLZNqubsiGqpnCguBp - uWlmKh95/VubCGgiGG2xK1IXQayL14ENuWseDds7nVpVK50NycrFgJbL17Bd6qJKYkbo - m70IC+9jM0hjwKXpyi6ipCBNcW+1E6JIwILVC04Xi+BTpOGhbUAQ59Yn2hyq7tQM7dzs - 4PLg== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679420063; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=cUvnluVaZPzfEQB9fMRuYo+4/361t/7po7nyUBBJfxc=; - b=SCX78yTuGjdnE5nuL0p7+kxGnOzsCExsigLdaV+x/JswmwxSpZvxn223i1yM95klj9 - Rk0RnXqATLF1wZA7L1YmbeZ66zxUwW/osnCjJHPeEF8AGgjK/qawtLl/HJQHN67NaRNQ - bDsRn2nWQ2GRTRFpvD+iGRy4uyQCDu9HFxLbn43fBsBmRnXWGPQP5cEb90tL83/Onp4D - Lx/XcyZOh9QRfJNhj+G1BAeRCLRA/sdA0W3Ecu5SCFs+LtS6uvLVGWDKEDfnZhYY8Xqf - Mx9evWzdW2OorEN2FI6+xTglvnEBcVhHIJ7XEGAhCG6ocgMZeck++774S8RWumWl8xpy - /K9Q== -X-Gm-Message-State: AO0yUKUORAlGfbkNwnYmQnTWcGPqW6sp4g9WfgQmRZGCV+9tCB0OebSP - ICq6v4YPmUPNRl/WNnVCbps= -X-Google-Smtp-Source: - AK7set8pFDl8fHRwGPhAguqxIfqnQ4PY+b57IHEsybIaQ/HPNwdJ1cs1+IPBGHe3TL14dTS4aVNpHA== -X-Received: by 2002:a5d:6991:0:b0:2ce:aab5:f96b with SMTP id - g17-20020a5d6991000000b002ceaab5f96bmr2965175wru.67.1679420062764; - Tue, 21 Mar 2023 10:34:22 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.21 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Tue, 21 Mar 2023 10:34:21 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, - olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, - kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v2 2/4] net: dsa: b53: mmap: add more 63xx SoCs -Date: Tue, 21 Mar 2023 18:33:57 +0100 -Message-Id: <20230321173359.251778-3-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> -References: <20230320155024.164523-1-noltari@gmail.com> - <20230321173359.251778-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -BCM6318, BCM6362 and BCM63268 are SoCs with a B53 MMAP switch. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli ---- - v2: no changes. - - drivers/net/dsa/b53/b53_mmap.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -345,8 +345,11 @@ static void b53_mmap_shutdown(struct pla - - static const struct of_device_id b53_mmap_of_table[] = { - { .compatible = "brcm,bcm3384-switch" }, -+ { .compatible = "brcm,bcm6318-switch" }, - { .compatible = "brcm,bcm6328-switch" }, -+ { .compatible = "brcm,bcm6362-switch" }, - { .compatible = "brcm,bcm6368-switch" }, -+ { .compatible = "brcm,bcm63268-switch" }, - { .compatible = "brcm,bcm63xx-switch" }, - { /* sentinel */ }, - }; diff --git a/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch b/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch deleted file mode 100644 index de237374af..0000000000 --- a/target/linux/generic/pending-6.6/774-net-dsa-b53-mmap-allow-passing-a-chip-ID.patch +++ /dev/null @@ -1,195 +0,0 @@ -From patchwork Tue Mar 21 17:33:58 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13183004 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id B2B12C74A5B - for ; Tue, 21 Mar 2023 17:35:12 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S230297AbjCURfK (ORCPT ); - Tue, 21 Mar 2023 13:35:10 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47438 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S230374AbjCURex (ORCPT - ); Tue, 21 Mar 2023 13:34:53 -0400 -Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com - [IPv6:2a00:1450:4864:20::432]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C906B5550A; - Tue, 21 Mar 2023 10:34:26 -0700 (PDT) -Received: by mail-wr1-x432.google.com with SMTP id y14so14546846wrq.4; - Tue, 21 Mar 2023 10:34:26 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679420064; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=vnvnwWc5Tmg09HBQo/m9RbRM6yM8KLx8r1VA+Abfg3k=; - b=eFv+mwe94Y2YZMiJP5gydXVrGlbIAR5HCrY0rdcoGoMPzQUHLFckZeYCgEKudI55I7 - gMLZYCtLwvDXvKeHM2AUigsq2YuJSeF5QwICPrhTnMwUGBg4yyyltrc3+J0lSd6/4kQv - h0yM1Oo4v0d8CuqjBU6bXienIk34AFVJfsPq+vWQTjAbUL7ht4WHZ2Ez2MFoTvZpkIJA - 5iWMyVoMbugZl6eqNRjvDHFmtBtrZIv8AFs10r2Ca6+Yxm+aq0v33DRkbSVVqgFPNEzy - q5QOXOeLBPL6BvyovOpmVSWGoHf1zFV7lrzcqi+uc+FuYxQ9dyN3ND73DrrhWSkLaSg9 - r8yA== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679420064; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=vnvnwWc5Tmg09HBQo/m9RbRM6yM8KLx8r1VA+Abfg3k=; - b=jIRB8pIlrLA/ovhnEoePs/6SX8fn6l7l4fY2CxX2pLrTbP1JI8AAetPavvrNVQTr2M - Vm0iLbKyL/VpTq9+bSN1SMjaoi4lAMj0pgafoHrwABMVZpFauYvtCfSYTstZ2pw4Dr1j - wYQGj3BUSpFIYHtSIDMkb5449WA3T3TONhaQLRFAUCBD6gAFyEky5fY+DIHrGaj352B6 - 9ST/tkqHgPpuFlmromr42KQWoTFU+Pj0Uhyp7ru4BsnF7tTshWroZZIHUJmSACudEadr - fBPiuurX9jgp9zNqj8Oy0HjiVUnULFCapj8yICGp5s44uDAK/XFqFXpOuJ8ptS6uPazU - xUwg== -X-Gm-Message-State: AO0yUKX2w6QZfaGDHtlZAlY/U8F8VuJa3HwlgXbxgGChgdgvIoFThawv - oDyFAhWbVfe4DxwXTwxgJ/I= -X-Google-Smtp-Source: - AK7set+sH60XiJYup7bqrZTzFJVNe1YGcX/UTfjWV9xfGwNyodc34cHvKpqNagw5J+vEpv6CKvNHaA== -X-Received: by 2002:adf:f344:0:b0:2cd:de25:1c76 with SMTP id - e4-20020adff344000000b002cdde251c76mr12989754wrp.17.1679420064464; - Tue, 21 Mar 2023 10:34:24 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.22 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Tue, 21 Mar 2023 10:34:23 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, - olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, - kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v2 3/4] net: dsa: b53: mmap: allow passing a chip ID -Date: Tue, 21 Mar 2023 18:33:58 +0100 -Message-Id: <20230321173359.251778-4-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> -References: <20230320155024.164523-1-noltari@gmail.com> - <20230321173359.251778-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -BCM6318 and BCM63268 SoCs require a special handling for their RGMIIs, so we -should be able to identify them as a special BCM63xx switch. - -Signed-off-by: Álvaro Fernández Rojas ---- - v2: - - Add missing chip to b53_switch_chips[]. - - Fix device_get_match_data() casting warning. - - Add BCM63268_DEVICE_ID to BCM6318 too. - - Add BCM6318 in commit description. - - drivers/net/dsa/b53/b53_common.c | 13 +++++++++++++ - drivers/net/dsa/b53/b53_mmap.c | 32 +++++++++++++++++++++++--------- - drivers/net/dsa/b53/b53_priv.h | 9 ++++++++- - 3 files changed, 44 insertions(+), 10 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2466,6 +2466,19 @@ static const struct b53_chip_data b53_sw - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, - }, - { -+ .chip_id = BCM63268_DEVICE_ID, -+ .dev_name = "BCM63268", -+ .vlans = 4096, -+ .enabled_ports = 0, /* pdata must provide them */ -+ .arl_bins = 4, -+ .arl_buckets = 1024, -+ .imp_port = 8, -+ .vta_regs = B53_VTA_REGS_63XX, -+ .duplex_reg = B53_DUPLEX_STAT_63XX, -+ .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, -+ .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, -+ }, -+ { - .chip_id = BCM53010_DEVICE_ID, - .dev_name = "BCM53010", - .vlans = 4096, ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -262,7 +262,7 @@ static int b53_mmap_probe_of(struct plat - return -ENOMEM; - - pdata->regs = mem; -- pdata->chip_id = BCM63XX_DEVICE_ID; -+ pdata->chip_id = (u32)(unsigned long)device_get_match_data(dev); - pdata->big_endian = of_property_read_bool(np, "big-endian"); - - of_ports = of_get_child_by_name(np, "ports"); -@@ -344,14 +344,28 @@ static void b53_mmap_shutdown(struct pla - } - - static const struct of_device_id b53_mmap_of_table[] = { -- { .compatible = "brcm,bcm3384-switch" }, -- { .compatible = "brcm,bcm6318-switch" }, -- { .compatible = "brcm,bcm6328-switch" }, -- { .compatible = "brcm,bcm6362-switch" }, -- { .compatible = "brcm,bcm6368-switch" }, -- { .compatible = "brcm,bcm63268-switch" }, -- { .compatible = "brcm,bcm63xx-switch" }, -- { /* sentinel */ }, -+ { -+ .compatible = "brcm,bcm3384-switch", -+ .data = (void *)BCM63XX_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm6318-switch", -+ .data = (void *)BCM63268_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm6328-switch", -+ .data = (void *)BCM63XX_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm6362-switch", -+ .data = (void *)BCM63XX_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm6368-switch", -+ .data = (void *)BCM63XX_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm63268-switch", -+ .data = (void *)BCM63268_DEVICE_ID, -+ }, { -+ .compatible = "brcm,bcm63xx-switch", -+ .data = (void *)BCM63XX_DEVICE_ID, -+ }, { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, b53_mmap_of_table); - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -70,6 +70,7 @@ enum { - BCM53125_DEVICE_ID = 0x53125, - BCM53128_DEVICE_ID = 0x53128, - BCM63XX_DEVICE_ID = 0x6300, -+ BCM63268_DEVICE_ID = 0x63268, - BCM53010_DEVICE_ID = 0x53010, - BCM53011_DEVICE_ID = 0x53011, - BCM53012_DEVICE_ID = 0x53012, -@@ -191,7 +192,13 @@ static inline int is531x5(struct b53_dev - - static inline int is63xx(struct b53_device *dev) - { -- return dev->chip_id == BCM63XX_DEVICE_ID; -+ return dev->chip_id == BCM63XX_DEVICE_ID || -+ dev->chip_id == BCM63268_DEVICE_ID; -+} -+ -+static inline int is63268(struct b53_device *dev) -+{ -+ return dev->chip_id == BCM63268_DEVICE_ID; - } - - static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch b/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch deleted file mode 100644 index d90d757fb2..0000000000 --- a/target/linux/generic/pending-6.6/775-net-dsa-b53-add-BCM63268-RGMII-configuration.patch +++ /dev/null @@ -1,123 +0,0 @@ -From patchwork Tue Mar 21 17:33:59 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13183005 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 31BE4C761A6 - for ; Tue, 21 Mar 2023 17:35:16 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S229674AbjCURfN (ORCPT ); - Tue, 21 Mar 2023 13:35:13 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47684 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S230327AbjCURfB (ORCPT - ); Tue, 21 Mar 2023 13:35:01 -0400 -Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com - [IPv6:2a00:1450:4864:20::436]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1D855507D; - Tue, 21 Mar 2023 10:34:27 -0700 (PDT) -Received: by mail-wr1-x436.google.com with SMTP id i9so14537769wrp.3; - Tue, 21 Mar 2023 10:34:27 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679420066; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=asmFs22xWYwR1Ql9m/IrNv+MPUNDn8hSjmwDRYvO7mE=; - b=Cqj2C6aG5vEOlhh9N3ybvDA0CV38nhQODnfdnr7utNddd323iDagoJty1Wmi3MAzj1 - 5ORmYT5fQvUnild7C4RhcCNTBn+MoYZ+wDZwZYelu6BKHkW11YFK949ax5B50by+ASR2 - z+rGI3wR5fVXd4VDgmcsT6zF5x69wKyhbhqIfrhG9BVFTctfaBgDS/l+bX1C56kSqv82 - bQkKSSAehSLGpFoCU3q62OGoZVi3jDe6HDb5M1Dp2mgHhqsW19otZpJ57DjtZ1CmtPai - o7T/ew6WoIYSl6whBmV36jeNaDJ3TItOBrKc4nMJBDWaCg4DNzUSe0ei5Xz7Oik5lb3p - y9ew== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679420066; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=asmFs22xWYwR1Ql9m/IrNv+MPUNDn8hSjmwDRYvO7mE=; - b=UdI2iQNBYwRf40ivf3ROR132t95BU/p3RUzXdZLCyz6c6JWtECQ5byyGeEwoX10n5u - HlepoNTJxMFLYrAHGvNLDPpWPuLXMa645S1mCVZ7NyWp8W96XzSynNZPeXHuJdb464QU - A7UTRSW3mlvKe9OR3EcB2CfBZv0yHWR0ldbnxcxGUFw8z78PNqpOVnITtjBdfpGesJ9c - VJw+fiM6hCcahor4nk9LLcAryPm8xmhDLxBKaLILO8wyTUiHY8G9hsXnFCtcpetnF5wS - pW13beAE+odb7ZZaXZUYpWGYhCe/hLzNjbo8YpgzHwadZthxPrT5YvNIYwyrvoViLM0n - KDRQ== -X-Gm-Message-State: AO0yUKW+9H/kqcAUyWeZhZJhiJjsBcYn1THmZaSDrPrk/pNuGXJXGtJd - NgsGZW8iSqLEv81yK+U5Os8= -X-Google-Smtp-Source: - AK7set/lzQZwCSxVaOe5dZ+7TR3xaQty/vg5xvZDpRW8TwTiPQblIbw5kJJTPLp67RySehrPIlCqSg== -X-Received: by 2002:a5d:65c9:0:b0:2ce:ac31:54ff with SMTP id - e9-20020a5d65c9000000b002ceac3154ffmr2776515wrw.2.1679420066191; - Tue, 21 Mar 2023 10:34:26 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - b13-20020a056000054d00b002da1261aa44sm184775wrf.48.2023.03.21.10.34.24 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Tue, 21 Mar 2023 10:34:25 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: f.fainelli@gmail.com, jonas.gorski@gmail.com, andrew@lunn.ch, - olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, - kuba@kernel.org, pabeni@redhat.com, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , - Simon Horman -Subject: [PATCH v2 4/4] net: dsa: b53: add BCM63268 RGMII configuration -Date: Tue, 21 Mar 2023 18:33:59 +0100 -Message-Id: <20230321173359.251778-5-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230321173359.251778-1-noltari@gmail.com> -References: <20230320155024.164523-1-noltari@gmail.com> - <20230321173359.251778-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -BCM63268 requires special RGMII configuration to work. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Reviewed-by: Simon Horman ---- - v2: no changes. - - drivers/net/dsa/b53/b53_common.c | 6 +++++- - drivers/net/dsa/b53/b53_regs.h | 1 + - 2 files changed, 6 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1240,8 +1240,12 @@ static void b53_adjust_63xx_rgmii(struct - break; - } - -- if (port != dev->imp_port) -+ if (port != dev->imp_port) { -+ if (is63268(dev)) -+ rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; -+ - rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; -+ } - - b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); - ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -138,6 +138,7 @@ - - #define B53_RGMII_CTRL_IMP 0x60 - #define RGMII_CTRL_ENABLE_GMII BIT(7) -+#define RGMII_CTRL_MII_OVERRIDE BIT(6) - #define RGMII_CTRL_TIMING_SEL BIT(2) - #define RGMII_CTRL_DLL_RXC BIT(1) - #define RGMII_CTRL_DLL_TXC BIT(0) diff --git a/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch b/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch deleted file mode 100644 index f0ae2defce..0000000000 --- a/target/linux/generic/pending-6.6/777-net-dsa-b53-mdio-add-support-for-BCM53134.patch +++ /dev/null @@ -1,189 +0,0 @@ -From patchwork Fri Mar 24 08:41:38 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13186549 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id EF744C76195 - for ; Fri, 24 Mar 2023 08:42:01 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S231807AbjCXImA (ORCPT ); - Fri, 24 Mar 2023 04:42:00 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32956 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S231272AbjCXIly (ORCPT - ); Fri, 24 Mar 2023 04:41:54 -0400 -Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com - [IPv6:2a00:1450:4864:20::535]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 113A517CF3; - Fri, 24 Mar 2023 01:41:46 -0700 (PDT) -Received: by mail-ed1-x535.google.com with SMTP id ek18so4877175edb.6; - Fri, 24 Mar 2023 01:41:45 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679647304; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=OfUWRaFIQIQw/lRivER+LHryfdLliXzvabGrcmkQVEU=; - b=JMrl6Eay1FS0JZqgPHsbcVzuNAbFELc0SLNGyzYtOVQXcI+YwKDM9Ls7I9PsQVEPoZ - CthomCTYoz5G9DU7uBuia207rnjOhssZJRu0syrCoU+O/ZiQyGLJDvq61z5oZJxC2S40 - kzRsUsC6MRjn64DKPWmxhsSTMKLzn2+P233LKNFbHtfi3NWF5Qu/85sUkxMurnfUgja0 - qQhl25qYY7ZIvmlFHYefaI5UkITQFuiybrqJW9tztCdHf/gS+f33YkkvQ8njmMQa1DW0 - ppedfOUotX+6kmHZGX1yea2V5ezEGGvRourZtYMoecTiD0E5d1J1bKhktKslVLIDm0ig - oc2g== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679647304; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=OfUWRaFIQIQw/lRivER+LHryfdLliXzvabGrcmkQVEU=; - b=b3Gmga5ZDbnmQfnw1GCz+eU2JwgsVzfciZuSmfYAiVxpW4c6cur3MHbpzDPhi99wzA - ZYAM7ryLv88rXl/tQB5g2Nte5rvMfxUeHXsT/JpsRcSSocFRbRrk0QJyiA/Xj86NiD5N - C1sKz50Im190FmrvPcBh6OHQbv/3MQyE+1fQx+9q3jW5rQiAWQaYk4Ng8GlWA7gtG3jB - fHO6Fuoenn32pgkveJbQLYL/2t2f53wGf3QLQ3IeKW7jdfIHNThwrwqBMxdHoIDaTBT9 - UWMeJuiYtylIibo/3zbORbWOgIERlWxZRf3BCOFpnzUn4eBzio4LgjtNxZ77ITRxsmbk - 3+Hg== -X-Gm-Message-State: AAQBX9dfyBfbR7Sdd5wqxMiAv3Yhk47pK1XzD87MZyAF3AxyoFyKcMaF - EbwJLyRvTGQEFdVWCGw1eMU= -X-Google-Smtp-Source: - AKy350bpDVLq7k1FxG2Mek/VIobZL4KhufiKx8qfmpxpcWmLI3bLg8wfQKEAKJRNJBleo/7CZuCL5g== -X-Received: by 2002:aa7:c711:0:b0:4a2:588f:b3c5 with SMTP id - i17-20020aa7c711000000b004a2588fb3c5mr2261236edq.21.1679647304260; - Fri, 24 Mar 2023 01:41:44 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - z21-20020a50cd15000000b004acbda55f6bsm10323728edi.27.2023.03.24.01.41.43 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Fri, 24 Mar 2023 01:41:43 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: paul.geurts@prodrive-technologies.com, f.fainelli@gmail.com, - jonas.gorski@gmail.com, andrew@lunn.ch, olteanv@gmail.com, - davem@davemloft.net, edumazet@google.com, kuba@kernel.org, - pabeni@redhat.com, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, netdev@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v2 2/2] net: dsa: b53: mdio: add support for BCM53134 -Date: Fri, 24 Mar 2023 09:41:38 +0100 -Message-Id: <20230324084138.664285-3-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230324084138.664285-1-noltari@gmail.com> -References: <20230323121804.2249605-1-noltari@gmail.com> - <20230324084138.664285-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org - -From: Paul Geurts - -Add support for the BCM53134 Ethernet switch in the existing b53 dsa driver. -BCM53134 is very similar to the BCM58XX series. - -Signed-off-by: Paul Geurts -Signed-off-by: Álvaro Fernández Rojas ---- - v2: add BCM53134 to is531x5() and remove special RGMII config - - drivers/net/dsa/b53/b53_common.c | 15 +++++++++++++++ - drivers/net/dsa/b53/b53_mdio.c | 5 ++++- - drivers/net/dsa/b53/b53_priv.h | 7 +++++-- - 3 files changed, 24 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2613,6 +2613,20 @@ static const struct b53_chip_data b53_sw - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - }, -+ { -+ .chip_id = BCM53134_DEVICE_ID, -+ .dev_name = "BCM53134", -+ .vlans = 4096, -+ .enabled_ports = 0x12f, -+ .imp_port = 8, -+ .cpu_port = B53_CPU_PORT, -+ .vta_regs = B53_VTA_REGS, -+ .arl_bins = 4, -+ .arl_buckets = 1024, -+ .duplex_reg = B53_DUPLEX_STAT_GE, -+ .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -+ .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ }, - }; - - static int b53_switch_init(struct b53_device *dev) -@@ -2790,6 +2804,7 @@ int b53_switch_detect(struct b53_device - case BCM53012_DEVICE_ID: - case BCM53018_DEVICE_ID: - case BCM53019_DEVICE_ID: -+ case BCM53134_DEVICE_ID: - dev->chip_id = id32; - break; - default: ---- a/drivers/net/dsa/b53/b53_mdio.c -+++ b/drivers/net/dsa/b53/b53_mdio.c -@@ -286,6 +286,7 @@ static const struct b53_io_ops b53_mdio_ - #define B53_BRCM_OUI_2 0x03625c00 - #define B53_BRCM_OUI_3 0x00406000 - #define B53_BRCM_OUI_4 0x01410c00 -+#define B53_BRCM_OUI_5 0xae025000 - - static int b53_mdio_probe(struct mdio_device *mdiodev) - { -@@ -313,7 +314,8 @@ static int b53_mdio_probe(struct mdio_de - if ((phy_id & 0xfffffc00) != B53_BRCM_OUI_1 && - (phy_id & 0xfffffc00) != B53_BRCM_OUI_2 && - (phy_id & 0xfffffc00) != B53_BRCM_OUI_3 && -- (phy_id & 0xfffffc00) != B53_BRCM_OUI_4) { -+ (phy_id & 0xfffffc00) != B53_BRCM_OUI_4 && -+ (phy_id & 0xfffffc00) != B53_BRCM_OUI_5) { - dev_err(&mdiodev->dev, "Unsupported device: 0x%08x\n", phy_id); - return -ENODEV; - } -@@ -375,6 +377,7 @@ static const struct of_device_id b53_of_ - { .compatible = "brcm,bcm53115" }, - { .compatible = "brcm,bcm53125" }, - { .compatible = "brcm,bcm53128" }, -+ { .compatible = "brcm,bcm53134" }, - { .compatible = "brcm,bcm5365" }, - { .compatible = "brcm,bcm5389" }, - { .compatible = "brcm,bcm5395" }, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -80,6 +80,7 @@ enum { - BCM583XX_DEVICE_ID = 0x58300, - BCM7445_DEVICE_ID = 0x7445, - BCM7278_DEVICE_ID = 0x7278, -+ BCM53134_DEVICE_ID = 0x5075, - }; - - struct b53_pcs { -@@ -187,7 +188,8 @@ static inline int is531x5(struct b53_dev - { - return dev->chip_id == BCM53115_DEVICE_ID || - dev->chip_id == BCM53125_DEVICE_ID || -- dev->chip_id == BCM53128_DEVICE_ID; -+ dev->chip_id == BCM53128_DEVICE_ID || -+ dev->chip_id == BCM53134_DEVICE_ID; - } - - static inline int is63xx(struct b53_device *dev) -@@ -215,7 +217,8 @@ static inline int is58xx(struct b53_devi - return dev->chip_id == BCM58XX_DEVICE_ID || - dev->chip_id == BCM583XX_DEVICE_ID || - dev->chip_id == BCM7445_DEVICE_ID || -- dev->chip_id == BCM7278_DEVICE_ID; -+ dev->chip_id == BCM7278_DEVICE_ID || -+ dev->chip_id == BCM53134_DEVICE_ID; - } - - #define B53_63XX_RGMII0 4 diff --git a/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch b/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch deleted file mode 100644 index 47e3b140c8..0000000000 --- a/target/linux/generic/pending-6.6/796-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch +++ /dev/null @@ -1,45 +0,0 @@ -From a444877c10a665cd8a869e6d37facdb89fd95f79 Mon Sep 17 00:00:00 2001 -Message-ID: -From: Daniel Golle -Date: Wed, 24 Jan 2024 04:17:11 +0000 -Subject: [PATCH net] net: dsa: mt7530: fix 10M/100M speed on MT7988 switch -To: Arınç ÜNAL , - Daniel Golle , - DENG Qingfang , - Sean Wang , - Andrew Lunn , - Florian Fainelli , - Vladimir Oltean , - David S. Miller , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Matthias Brugger , - AngeloGioacchino Del Regno , - netdev@vger.kernel.org, - linux-kernel@vger.kernel.org, - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org - -Setup PMCR port register for actual speed and duplex on internally -connected PHYs of the MT7988 built-in switch. This fixes links with -speeds other than 1000M. - -Fixes: ("110c18bfed414 net: dsa: mt7530: introduce driver for MT7988 built-in switch") -Signed-off-by: Daniel Golle ---- - drivers/net/dsa/mt7530.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2849,8 +2849,7 @@ 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_INTERNAL || -- interface == PHY_INTERFACE_MODE_TRGMII || -+ if (interface == PHY_INTERFACE_MODE_TRGMII || - (phy_interface_mode_is_8023z(interface))) { - speed = SPEED_1000; - duplex = DUPLEX_FULL; diff --git a/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch b/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch deleted file mode 100644 index cc6f1e0d9d..0000000000 --- a/target/linux/generic/pending-6.6/850-dt-bindings-clk-add-BCM63268-timer-clock-definitions.patch +++ /dev/null @@ -1,114 +0,0 @@ -From patchwork Wed Mar 22 17:15:12 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13184389 -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 73F2DC6FD1C - for ; Wed, 22 Mar 2023 17:15:59 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S231363AbjCVRP5 (ORCPT ); - Wed, 22 Mar 2023 13:15:57 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58824 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S231408AbjCVRPy (ORCPT - ); Wed, 22 Mar 2023 13:15:54 -0400 -Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com - [IPv6:2a00:1450:4864:20::32d]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70E4C64B28; - Wed, 22 Mar 2023 10:15:24 -0700 (PDT) -Received: by mail-wm1-x32d.google.com with SMTP id n19so1740892wms.0; - Wed, 22 Mar 2023 10:15:24 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679505322; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=dEknM98Izmc8d/crPsoJ+ejZxfl78958Ei6SPYhYDHs=; - b=LTOQ75W3s5nYo+nEfiJAKqytSopONB4jCtU3zRygzPMasugVOrYFMsUR+WrpsAjuRT - v4HgWpJxEsIWeRXrUN9W21mFXhGgJLJXSxRnrio0CsZZBNMdkebbNOphgKXIWAdm+2iM - PzqAdGm5t38wT2mmm6V/9hCy90+12raHM82tNFdhhiezfg2cukVOKP3j/TeOVCwas0gQ - iFc+CuZB6y73zYXvMUMUpTsqI5vev4xJsSMHIQJVmUxJAwqhOBhN9JCRo7Ao+wayjn2d - Fxo6AV3A8v68nVfoQ0K0I+eWXG48nMCX45iWh/lVvVTOFcR99kn4va7NY1oVnPsh+WQz - WcLA== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679505322; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=dEknM98Izmc8d/crPsoJ+ejZxfl78958Ei6SPYhYDHs=; - b=wv2NSR1B5RnsdoEE7mgJSHAfSs1JHZbQ1HPMldyaGWAk1dcucqh/uDzM3Flz+ADRi1 - 19NoaB2Ur7QaWZejbuplnIOK/nte3PnmqJ9ZNw8HejmuS4eU8mB1V1aJUSKSPGsfUi4a - LYe3HSw87l0jrAC7ptdKvdUtzBoIkX0CeFvfguTQQkDhUTyAFIG144hY6uPXY9Mga96b - gnNe2dLCzHQLbEJpaDaavT7FEEcLDxaq7jNcR2xqEEZaIwfcew+Q05t4xL/3i8GAj9Ru - 6ivQjIbBKfYQF88o7KnOW9o1wjrGsk+Nd4Iy0OLZix3JQasCJGrKV7ib5awI9J39upYV - fa4A== -X-Gm-Message-State: AO0yUKWw75I1M5Vjrd4vXq4GTruQu0H84pycgyi2CT3bczTYRJpWmEWg - +bHDhvp1n5IWW85GI9vKWpbclB13a/S0RQ== -X-Google-Smtp-Source: - AK7set9T/2oJsVetUb2L4mPEWu8YqDrnK8EzHK5bJf1ABIa1Et8f7BFJ7AA3j14ITZuf8cH0HqlRtg== -X-Received: by 2002:a05:600c:2304:b0:3ed:2949:985b with SMTP id - 4-20020a05600c230400b003ed2949985bmr206833wmo.23.1679505322457; - Wed, 22 Mar 2023 10:15:22 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.21 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Wed, 22 Mar 2023 10:15:22 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, - f.fainelli@gmail.com, jonas.gorski@gmail.com, - william.zhang@broadcom.com, linux-clk@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , - Rob Herring -Subject: [PATCH v4 1/4] dt-bindings: clk: add BCM63268 timer clock definitions -Date: Wed, 22 Mar 2023 18:15:12 +0100 -Message-Id: <20230322171515.120353-2-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> -References: <20230322171515.120353-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-clk@vger.kernel.org - -Add missing timer clock definitions for BCM63268. - -Signed-off-by: Álvaro Fernández Rojas -Acked-by: Rob Herring ---- - v4: no changes - v3: no changes - v2: change commit title, as suggested by Stephen Boyd - - include/dt-bindings/clock/bcm63268-clock.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/include/dt-bindings/clock/bcm63268-clock.h -+++ b/include/dt-bindings/clock/bcm63268-clock.h -@@ -27,4 +27,17 @@ - #define BCM63268_CLK_TBUS 27 - #define BCM63268_CLK_ROBOSW250 31 - -+#define BCM63268_TCLK_EPHY1 0 -+#define BCM63268_TCLK_EPHY2 1 -+#define BCM63268_TCLK_EPHY3 2 -+#define BCM63268_TCLK_GPHY1 3 -+#define BCM63268_TCLK_DSL 4 -+#define BCM63268_TCLK_WAKEON_EPHY 6 -+#define BCM63268_TCLK_WAKEON_DSL 7 -+#define BCM63268_TCLK_FAP1 11 -+#define BCM63268_TCLK_FAP2 15 -+#define BCM63268_TCLK_UTO_50 16 -+#define BCM63268_TCLK_UTO_EXTIN 17 -+#define BCM63268_TCLK_USB_REF 18 -+ - #endif /* __DT_BINDINGS_CLOCK_BCM63268_H */ diff --git a/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch b/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch deleted file mode 100644 index 5f1be105ac..0000000000 --- a/target/linux/generic/pending-6.6/851-dt-bindings-reset-add-BCM63268-timer-reset-definitions.patch +++ /dev/null @@ -1,107 +0,0 @@ -From patchwork Wed Mar 22 17:15:13 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13184390 -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id D0B1AC6FD1C - for ; Wed, 22 Mar 2023 17:16:08 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S231472AbjCVRQI (ORCPT ); - Wed, 22 Mar 2023 13:16:08 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58934 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S231435AbjCVRP5 (ORCPT - ); Wed, 22 Mar 2023 13:15:57 -0400 -Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com - [IPv6:2a00:1450:4864:20::329]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9655064863; - Wed, 22 Mar 2023 10:15:25 -0700 (PDT) -Received: by mail-wm1-x329.google.com with SMTP id - v4-20020a05600c470400b003ee4f06428fso2424553wmo.4; - Wed, 22 Mar 2023 10:15:25 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679505324; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=C7ykhArT1dO7P8wtmI92eo4c7KtPZI9w182/5+cB3T0=; - b=WRZRU2SM9n1LfUj4SgTPfQczADC2pfvoIrOsNpBLTym2eOfmkTetb/WbGSla5kw2Wb - SH5MIC2fFeScJg6T5FFAUOOLmRVW9xvl8Q3T3NKb3z/9wvPHO767nrdIbffRWMJFs7gW - wT/kuTpn8GYdfY0sZ/dMTkq41DVusEkxfX6GxtG85O98ZP8xMHQog8aPs9fRfUvI5ZKB - eGYcRz/Wn1cHhjey9jtWzQEEmZ/BT3b0HQTF9Tl88oofhiEgbyjFXr91+vRsLbsJpGXH - /1FjjaLG5DnonKubV9rmbuCU8KzwH331gi2KuRjvLD2V+OMewqSa5i+GvgVv8x2zC8y+ - /mLQ== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679505324; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=C7ykhArT1dO7P8wtmI92eo4c7KtPZI9w182/5+cB3T0=; - b=bhd0fNh0jDOMlGSC4F+p5igV8AUlGEPj2cXUwgdgqRfSSuUy9z+Li8cT0MbY/aWH5Z - qInRVA+R1cWV3ubrDyKag6oEc0LDU234bnMFcP9b7MRlrM8Dpit9TFSyqJU4sDUWNDs5 - KOe2k/SNIdat6munC9VOuEBDO0eB/UDMN+repKwXNdHChp/Toq9qMvW4Uy8uHxosbQlD - 8P88GbKFjynb1E8I8croGjfub7+y8PPsWB0xNUcafIv6xs3MnVOP1Mk4KwBCbqS509la - mfjsriXtIybO8XFqtn100ungjvbFWdogEplLdSPVdgAqdfF5J8gHxAoApoeYejYkL5/R - kOhQ== -X-Gm-Message-State: AO0yUKWdzr3dMmjKhD8tF+ec4Dfdq9VGZ/WCU4d85npKQvxSwhNPZZ1J - 5WYRIqivh0suFC1OqEidwenpiJYvXedYjw== -X-Google-Smtp-Source: - AK7set87ew2/mKWeShXTTW/YBbBJNR2zeGFV0CfuqLXhiJEU6tqFuyKcW+vFEoKHIbNUS8wRy1SzLA== -X-Received: by 2002:a05:600c:290:b0:3ee:6d88:774a with SMTP id - 16-20020a05600c029000b003ee6d88774amr160734wmk.14.1679505323514; - Wed, 22 Mar 2023 10:15:23 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.22 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Wed, 22 Mar 2023 10:15:23 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, - f.fainelli@gmail.com, jonas.gorski@gmail.com, - william.zhang@broadcom.com, linux-clk@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= , - Rob Herring -Subject: [PATCH v4 2/4] dt-bindings: reset: add BCM63268 timer reset - definitions -Date: Wed, 22 Mar 2023 18:15:13 +0100 -Message-Id: <20230322171515.120353-3-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> -References: <20230322171515.120353-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-clk@vger.kernel.org - -Add missing timer reset definitions for BCM63268. - -Signed-off-by: Álvaro Fernández Rojas -Acked-by: Rob Herring ---- - v4: no changes - v3: no changes - v2: change commit title, as suggested by Stephen Boyd - - include/dt-bindings/reset/bcm63268-reset.h | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/include/dt-bindings/reset/bcm63268-reset.h -+++ b/include/dt-bindings/reset/bcm63268-reset.h -@@ -23,4 +23,8 @@ - #define BCM63268_RST_PCIE_HARD 17 - #define BCM63268_RST_GPHY 18 - -+#define BCM63268_TRST_SW 29 -+#define BCM63268_TRST_HW 30 -+#define BCM63268_TRST_POR 31 -+ - #endif /* __DT_BINDINGS_RESET_BCM63268_H */ diff --git a/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch b/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch deleted file mode 100644 index 7e500cd1b5..0000000000 --- a/target/linux/generic/pending-6.6/852-clk-bcm-Add-BCM63268-timer-clock-and-reset-driver.patch +++ /dev/null @@ -1,345 +0,0 @@ -From patchwork Wed Mar 22 17:15:15 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= - -X-Patchwork-Id: 13184392 -Return-Path: -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 199D9C76196 - for ; Wed, 22 Mar 2023 17:16:11 +0000 (UTC) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S231512AbjCVRQJ (ORCPT ); - Wed, 22 Mar 2023 13:16:09 -0400 -Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58942 "EHLO - lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S231442AbjCVRP5 (ORCPT - ); Wed, 22 Mar 2023 13:15:57 -0400 -Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com - [IPv6:2a00:1450:4864:20::32c]) - by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DDB36487D; - Wed, 22 Mar 2023 10:15:27 -0700 (PDT) -Received: by mail-wm1-x32c.google.com with SMTP id - i5-20020a05600c354500b003edd24054e0so6717370wmq.4; - Wed, 22 Mar 2023 10:15:27 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; t=1679505325; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:from:to:cc:subject:date - :message-id:reply-to; - bh=rkv/eZYA1ncHp5FnV2ZWc3hgYnAx28S86QA9vmcXFCY=; - b=Y1mva2Bt3sUbKxLgEUS331CJbGxUc4z8kTQW8qiHWGhYlFKtm+d5z4sT40E5BeZAnU - zmTbCI7jbroe9NYBxGUmSli6LNVDPjND80ChbhWTqbqMQTmeQFWut9KmeBWK6Oze2lC/ - XMSOorUzowjcU2xtHNrzoq2KH2pstW573lsB8WnzFVfhMaRkE9DfRr6WNyA7zC8DyxM5 - ezxlCQtCmgPfCqlyksbIDKrgrRf3GiUR0yUd6xRU+MssyvH1FkYGDCerPctDto6lGHBz - 8Y15jT3l6OnQMT6dkekgpPF5/XrSUY93u9g0B4U8+0dhNj+K7vmDen+jqdess+tpLnq/ - gFrA== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; t=1679505325; - h=content-transfer-encoding:mime-version:references:in-reply-to - :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc - :subject:date:message-id:reply-to; - bh=rkv/eZYA1ncHp5FnV2ZWc3hgYnAx28S86QA9vmcXFCY=; - b=Ym4+u8bbTQGNkewUBrLf+89vE0EFJBQp2f1crwUxZFboKTROF9ltZonY1CGepo7b0B - fkx3TbWQy5X65g3ScuieqtClCI8WanPeNBJ48+JipJYO3ODVNBxnVaTuW/0FOIcahfqe - sG5GvggHhzRz+Yeybsbnupmzxnw8Ez0BpMl3p7zcjHL7BGZDdOOX2Zbw3zfyYa5sg2nX - UXYJT36zy2h39gxUsy9QkhQ76CG3w6omniohZpYidpojpiDjbOy0nKFky4kUe+YyA1fF - 4IBhjAm6mH+uh6wHSG1qj+NAXHs0xDDJps16PbJwAgL7Qt9K5WW+R/UAYPmHFgaRIHOw - /seA== -X-Gm-Message-State: AO0yUKXRtoYO8Nfus6Ca8lhM39P1Xn6TGkhatEfoISd1YNOkTJJN2hW+ - xRphLgxlzNfCLcVPlpGK9dk= -X-Google-Smtp-Source: - AK7set9VnMEykugk8ZYnkXuqK41bX1dzlvKsAXHEjr8i2NZBld0buKhQLcGYEcwxnBgVTtC7eRGfXw== -X-Received: by 2002:a1c:7c0b:0:b0:3e2:1dac:b071 with SMTP id - x11-20020a1c7c0b000000b003e21dacb071mr178053wmc.13.1679505325582; - Wed, 22 Mar 2023 10:15:25 -0700 (PDT) -Received: from atlantis.lan (255.red-79-146-124.dynamicip.rima-tde.net. - [79.146.124.255]) - by smtp.gmail.com with ESMTPSA id - v10-20020a05600c470a00b003ee11ac2288sm8414333wmo.21.2023.03.22.10.15.24 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Wed, 22 Mar 2023 10:15:25 -0700 (PDT) -From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, - krzysztof.kozlowski+dt@linaro.org, p.zabel@pengutronix.de, - f.fainelli@gmail.com, jonas.gorski@gmail.com, - william.zhang@broadcom.com, linux-clk@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org -Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= -Subject: [PATCH v4 4/4] clk: bcm: Add BCM63268 timer clock and reset driver -Date: Wed, 22 Mar 2023 18:15:15 +0100 -Message-Id: <20230322171515.120353-5-noltari@gmail.com> -X-Mailer: git-send-email 2.30.2 -In-Reply-To: <20230322171515.120353-1-noltari@gmail.com> -References: <20230322171515.120353-1-noltari@gmail.com> -MIME-Version: 1.0 -Precedence: bulk -List-ID: -X-Mailing-List: linux-clk@vger.kernel.org - -Add driver for BCM63268 timer clock and reset controller. - -Signed-off-by: Álvaro Fernández Rojas ---- - v4: add changes suggested by Stephen Boyd: - - Usage of of_device_get_match_data() isn't needed. - - Use devm_clk_hw_register_gate(). - - Drop clk_hw_unregister_gate(). - v3: add missing include to fix build warning - v2: add changes suggested by Stephen Boyd - - drivers/clk/bcm/Kconfig | 9 ++ - drivers/clk/bcm/Makefile | 1 + - drivers/clk/bcm/clk-bcm63268-timer.c | 215 +++++++++++++++++++++++++++ - 3 files changed, 225 insertions(+) - create mode 100644 drivers/clk/bcm/clk-bcm63268-timer.c - ---- a/drivers/clk/bcm/Kconfig -+++ b/drivers/clk/bcm/Kconfig -@@ -37,6 +37,15 @@ config CLK_BCM_63XX_GATE - Enable common clock framework support for Broadcom BCM63xx DSL SoCs - based on the MIPS architecture - -+config CLK_BCM63268_TIMER -+ bool "Broadcom BCM63268 timer clock and reset support" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ default BMIPS_GENERIC -+ select RESET_CONTROLLER -+ help -+ Enable timer clock and reset support for Broadcom BCM63268 DSL SoCs -+ based on the MIPS architecture. -+ - config CLK_BCM_KONA - bool "Broadcom Kona CCU clock support" - depends on ARCH_BCM_MOBILE || COMPILE_TEST ---- a/drivers/clk/bcm/Makefile -+++ b/drivers/clk/bcm/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o - obj-$(CONFIG_CLK_BCM_63XX_GATE) += clk-bcm63xx-gate.o -+obj-$(CONFIG_CLK_BCM63268_TIMER) += clk-bcm63268-timer.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o - obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o ---- /dev/null -+++ b/drivers/clk/bcm/clk-bcm63268-timer.c -@@ -0,0 +1,215 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * BCM63268 Timer Clock and Reset Controller Driver -+ * -+ * Copyright (C) 2023 Álvaro Fernández Rojas -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define BCM63268_TIMER_RESET_SLEEP_MIN_US 10000 -+#define BCM63268_TIMER_RESET_SLEEP_MAX_US 20000 -+ -+struct bcm63268_tclkrst_hw { -+ void __iomem *regs; -+ spinlock_t lock; -+ -+ struct reset_controller_dev rcdev; -+ struct clk_hw_onecell_data data; -+}; -+ -+struct bcm63268_tclk_table_entry { -+ const char * const name; -+ u8 bit; -+}; -+ -+static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = { -+ { -+ .name = "ephy1", -+ .bit = BCM63268_TCLK_EPHY1, -+ }, { -+ .name = "ephy2", -+ .bit = BCM63268_TCLK_EPHY2, -+ }, { -+ .name = "ephy3", -+ .bit = BCM63268_TCLK_EPHY3, -+ }, { -+ .name = "gphy1", -+ .bit = BCM63268_TCLK_GPHY1, -+ }, { -+ .name = "dsl", -+ .bit = BCM63268_TCLK_DSL, -+ }, { -+ .name = "wakeon_ephy", -+ .bit = BCM63268_TCLK_WAKEON_EPHY, -+ }, { -+ .name = "wakeon_dsl", -+ .bit = BCM63268_TCLK_WAKEON_DSL, -+ }, { -+ .name = "fap1_pll", -+ .bit = BCM63268_TCLK_FAP1, -+ }, { -+ .name = "fap2_pll", -+ .bit = BCM63268_TCLK_FAP2, -+ }, { -+ .name = "uto_50", -+ .bit = BCM63268_TCLK_UTO_50, -+ }, { -+ .name = "uto_extin", -+ .bit = BCM63268_TCLK_UTO_EXTIN, -+ }, { -+ .name = "usb_ref", -+ .bit = BCM63268_TCLK_USB_REF, -+ }, { -+ /* sentinel */ -+ } -+}; -+ -+static inline struct bcm63268_tclkrst_hw * -+to_bcm63268_timer_reset(struct reset_controller_dev *rcdev) -+{ -+ return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev); -+} -+ -+static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev, -+ unsigned long id, bool assert) -+{ -+ struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); -+ unsigned long flags; -+ uint32_t val; -+ -+ spin_lock_irqsave(&reset->lock, flags); -+ val = __raw_readl(reset->regs); -+ if (assert) -+ val &= ~BIT(id); -+ else -+ val |= BIT(id); -+ __raw_writel(val, reset->regs); -+ spin_unlock_irqrestore(&reset->lock, flags); -+ -+ return 0; -+} -+ -+static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ return bcm63268_timer_reset_update(rcdev, id, true); -+} -+ -+static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ return bcm63268_timer_reset_update(rcdev, id, false); -+} -+ -+static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ bcm63268_timer_reset_update(rcdev, id, true); -+ usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, -+ BCM63268_TIMER_RESET_SLEEP_MAX_US); -+ -+ bcm63268_timer_reset_update(rcdev, id, false); -+ /* -+ * Ensure component is taken out reset state by sleeping also after -+ * deasserting the reset. Otherwise, the component may not be ready -+ * for operation. -+ */ -+ usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, -+ BCM63268_TIMER_RESET_SLEEP_MAX_US); -+ -+ return 0; -+} -+ -+static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); -+ -+ return !(__raw_readl(reset->regs) & BIT(id)); -+} -+ -+static struct reset_control_ops bcm63268_timer_reset_ops = { -+ .assert = bcm63268_timer_reset_assert, -+ .deassert = bcm63268_timer_reset_deassert, -+ .reset = bcm63268_timer_reset_reset, -+ .status = bcm63268_timer_reset_status, -+}; -+ -+static int bcm63268_tclk_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct bcm63268_tclk_table_entry *entry; -+ struct bcm63268_tclkrst_hw *hw; -+ struct clk_hw *clk; -+ u8 maxbit = 0; -+ int i, ret; -+ -+ for (entry = bcm63268_timer_clocks; entry->name; entry++) -+ maxbit = max(maxbit, entry->bit); -+ maxbit++; -+ -+ hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit), -+ GFP_KERNEL); -+ if (!hw) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, hw); -+ -+ spin_lock_init(&hw->lock); -+ -+ hw->data.num = maxbit; -+ for (i = 0; i < maxbit; i++) -+ hw->data.hws[i] = ERR_PTR(-ENODEV); -+ -+ hw->regs = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(hw->regs)) -+ return PTR_ERR(hw->regs); -+ -+ for (entry = bcm63268_timer_clocks; entry->name; entry++) { -+ clk = devm_clk_hw_register_gate(dev, entry->name, NULL, 0, -+ hw->regs, entry->bit, -+ CLK_GATE_BIG_ENDIAN, -+ &hw->lock); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ hw->data.hws[entry->bit] = clk; -+ } -+ -+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, -+ &hw->data); -+ if (ret) -+ return ret; -+ -+ hw->rcdev.of_node = dev->of_node; -+ hw->rcdev.ops = &bcm63268_timer_reset_ops; -+ -+ ret = devm_reset_controller_register(dev, &hw->rcdev); -+ if (ret) -+ dev_err(dev, "Failed to register reset controller\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm63268_tclk_dt_ids[] = { -+ { .compatible = "brcm,bcm63268-timer-clocks" }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver bcm63268_tclk = { -+ .probe = bcm63268_tclk_probe, -+ .driver = { -+ .name = "bcm63268-timer-clock", -+ .of_match_table = bcm63268_tclk_dt_ids, -+ }, -+}; -+builtin_platform_driver(bcm63268_tclk); diff --git a/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch b/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch deleted file mode 100644 index c5db5d9491..0000000000 --- a/target/linux/generic/pending-6.6/860-serial-8250_mtk-track-busclk-state-to-avoid-bus-error.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 629c701fc39f1ada9416e0766a86729e83bde86c Mon Sep 17 00:00:00 2001 -Message-ID: <629c701fc39f1ada9416e0766a86729e83bde86c.1694465766.git.daniel@makrotopia.org> -From: Daniel Golle -Date: Mon, 11 Sep 2023 21:27:44 +0100 -Subject: [PATCH] serial: 8250_mtk: track busclk state to avoid bus error -To: Greg Kroah-Hartman , - Jiri Slaby , - Matthias Brugger , - AngeloGioacchino Del Regno , - Daniel Golle , - John Ogness , - Chen-Yu Tsai , - Changqi Hu , - linux-kernel@vger.kernel.org, - linux-serial@vger.kernel.org, - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org - -Commit e32a83c70cf9 ("serial: 8250-mtk: modify mtk uart power and -clock management") introduced polling a debug register to make sure -the UART is idle before disabling the bus clock. However, at least on -some MediaTek SoCs access to that very debug register requires the bus -clock being enabled. Hence calling the suspend function while already -in suspended state results in that register access triggering a bus -error. In order to avoid that, track the state of the bus clock and -only poll the debug register if not already in suspended state. - -Fixes: e32a83c70cf9 ("serial: 8250-mtk: modify mtk uart power and clock management") -Signed-off-by: Daniel Golle ---- - drivers/tty/serial/8250/8250_mtk.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - ---- a/drivers/tty/serial/8250/8250_mtk.c -+++ b/drivers/tty/serial/8250/8250_mtk.c -@@ -32,7 +32,7 @@ - #define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */ - #define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */ - #define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */ --#define MTK_UART_DEBUG0 0x18 -+#define MTK_UART_DEBUG0 0x18 - #define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */ - #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ - #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ -@@ -418,13 +418,12 @@ static int __maybe_unused mtk8250_runtim - struct mtk8250_data *data = dev_get_drvdata(dev); - struct uart_8250_port *up = serial8250_get_port(data->line); - -- /* wait until UART in idle status */ -- while -- (serial_in(up, MTK_UART_DEBUG0)); -- - if (data->clk_count == 0U) { - dev_dbg(dev, "%s clock count is 0\n", __func__); - } else { -+ /* wait until UART in idle status */ -+ while -+ (serial_in(up, MTK_UART_DEBUG0)); - clk_disable_unprepare(data->bus_clk); - data->clk_count--; - } From a76397cd47f838907a3087341b0e1644c86bc230 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 01:58:18 +0800 Subject: [PATCH 043/108] generic: 6.6: manually refresh backport patches Refresh backport patches that still needs to be merged for kernel 6.6. Signed-off-by: Weijie Gao --- ...-aquantia-move-to-separate-directory.patch | 92 +++++++++++++++++-- ...03x-PHY-driver-to-dedicated-director.patch | 16 ++-- ...etach-qca808x-PHY-driver-from-at803x.patch | 4 +- ...HY-package-API-to-support-multiple-g.patch | 10 +- ...ort-for-scanning-PHY-in-PHY-packages.patch | 4 +- ...-add-devm-of_phy_package_join-helper.patch | 4 +- ...iatek-fix-ppe-flow-accounting-for-L2.patch | 31 ++++--- ..._wed-rename-mtk_rxbm_desc-in-mtk_wed.patch | 8 +- ...antia-add-AQR111-and-AQR111B0-PHY-ID.patch | 10 +- ...9-net-phy-aquantia-add-AQR113-PHY-ID.patch | 10 +- ...9-net-phy-aquantia-add-AQR813-PHY-ID.patch | 4 +- ...c-move-TX-timer-arm-after-DMA-enable.patch | 32 ++++--- ...a-Add-support-for-enabling-disabling.patch | 6 +- ...Create-a-header-for-internal-sharing.patch | 4 +- 14 files changed, 160 insertions(+), 75 deletions(-) diff --git a/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch b/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch index 0cad6c53d4..be4d4ccad9 100644 --- a/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch +++ b/target/linux/generic/backport-6.6/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch @@ -26,7 +26,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -90,10 +90,7 @@ config ADIN1100_PHY +@@ -96,10 +96,7 @@ config ADIN1100_PHY Currently supports the: - ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY @@ -40,7 +40,7 @@ Signed-off-by: David S. Miller tristate "Asix PHYs" --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -33,11 +33,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) +@@ -35,11 +35,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) obj-$(CONFIG_ADIN_PHY) += adin.o obj-$(CONFIG_ADIN1100_PHY) += adin1100.o obj-$(CONFIG_AMD_PHY) += amd.o @@ -323,7 +323,7 @@ Signed-off-by: David S. Miller + .config = aqr_hwmon_temp_config, +}; + -+static const struct hwmon_channel_info *aqr_hwmon_info[] = { ++static const struct hwmon_channel_info * const aqr_hwmon_info[] = { + &aqr_hwmon_chip, + &aqr_hwmon_temp, + NULL, @@ -363,7 +363,7 @@ Signed-off-by: David S. Miller +#endif --- /dev/null +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -0,0 +1,842 @@ +@@ -0,0 +1,882 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Aquantia PHY @@ -388,6 +388,8 @@ Signed-off-by: David S. Miller +#define PHY_ID_AQR107 0x03a1b4e0 +#define PHY_ID_AQCS109 0x03a1b5c2 +#define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR412 0x03a1b712 +#define PHY_ID_AQR113C 0x31c31c12 + +#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 @@ -1167,6 +1169,42 @@ Signed-off-by: David S. Miller + .read_status = aqr_read_status, +}, +{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112), ++ .name = "Aquantia AQR112", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .read_status = aqr107_read_status, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR412), ++ .name = "Aquantia AQR412", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .read_status = aqr107_read_status, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), + .name = "Aquantia AQR113C", + .probe = aqr107_probe, @@ -1197,6 +1235,8 @@ Signed-off-by: David S. Miller + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } +}; @@ -1421,7 +1461,7 @@ Signed-off-by: David S. Miller - .config = aqr_hwmon_temp_config, -}; - --static const struct hwmon_channel_info *aqr_hwmon_info[] = { +-static const struct hwmon_channel_info * const aqr_hwmon_info[] = { - &aqr_hwmon_chip, - &aqr_hwmon_temp, - NULL, @@ -1461,7 +1501,7 @@ Signed-off-by: David S. Miller -#endif --- a/drivers/net/phy/aquantia_main.c +++ /dev/null -@@ -1,842 +0,0 @@ +@@ -1,882 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Driver for Aquantia PHY @@ -1486,6 +1526,8 @@ Signed-off-by: David S. Miller -#define PHY_ID_AQR107 0x03a1b4e0 -#define PHY_ID_AQCS109 0x03a1b5c2 -#define PHY_ID_AQR405 0x03a1b4b0 +-#define PHY_ID_AQR112 0x03a1b662 +-#define PHY_ID_AQR412 0x03a1b712 -#define PHY_ID_AQR113C 0x31c31c12 - -#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 @@ -2265,6 +2307,42 @@ Signed-off-by: David S. Miller - .read_status = aqr_read_status, -}, -{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR112), +- .name = "Aquantia AQR112", +- .probe = aqr107_probe, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .read_status = aqr107_read_status, +- .get_rate_matching = aqr107_get_rate_matching, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR412), +- .name = "Aquantia AQR412", +- .probe = aqr107_probe, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .read_status = aqr107_read_status, +- .get_rate_matching = aqr107_get_rate_matching, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), - .name = "Aquantia AQR113C", - .probe = aqr107_probe, @@ -2295,6 +2373,8 @@ Signed-off-by: David S. Miller - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { } -}; diff --git a/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch b/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch index 8c9babea7b..ba89ecdb3c 100644 --- a/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch +++ b/target/linux/generic/backport-6.6/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch @@ -25,9 +25,9 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -277,12 +277,7 @@ config NXP_TJA11XX_PHY - help - Currently supports the NXP TJA1100 and TJA1101 PHY. +@@ -318,12 +318,7 @@ config NCN26000_PHY + Currently supports the NCN26000 10BASE-T1S Industrial PHY + with MII interface. -config AT803X_PHY - tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" @@ -41,7 +41,7 @@ Signed-off-by: Jakub Kicinski tristate "Quality Semiconductor PHYs" --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -34,7 +34,6 @@ obj-$(CONFIG_ADIN_PHY) += adin.o +@@ -36,7 +36,6 @@ obj-$(CONFIG_ADIN_PHY) += adin.o obj-$(CONFIG_ADIN1100_PHY) += adin1100.o obj-$(CONFIG_AMD_PHY) += amd.o obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ @@ -49,9 +49,9 @@ Signed-off-by: Jakub Kicinski obj-$(CONFIG_AX88796B_PHY) += ax88796b.o obj-$(CONFIG_BCM54140_PHY) += bcm54140.o obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o -@@ -75,6 +74,7 @@ obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm - obj-$(CONFIG_NATIONAL_PHY) += national.o +@@ -82,6 +81,7 @@ obj-$(CONFIG_NCN26000_PHY) += ncn26000.o obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o + obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o +obj-y += qcom/ obj-$(CONFIG_QSEMI_PHY) += qsemi.o @@ -2010,7 +2010,7 @@ Signed-off-by: Jakub Kicinski - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); - -- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, - FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | @@ -4772,7 +4772,7 @@ Signed-off-by: Jakub Kicinski + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + -+ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, + FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | diff --git a/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch b/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch index 597dcea4c0..d8092a8f3c 100644 --- a/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch +++ b/target/linux/generic/backport-6.6/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch @@ -328,7 +328,7 @@ Signed-off-by: Jakub Kicinski - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); - -- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); - return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, - QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, - FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | @@ -1255,7 +1255,7 @@ Signed-off-by: Jakub Kicinski + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + -+ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ seed_value = get_random_u32_below(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, + FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | diff --git a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch index 0cf01df3d3..6e5ac8c63a 100644 --- a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch +++ b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch @@ -242,7 +242,7 @@ Signed-off-by: David S. Miller refcount_t refcnt; unsigned long flags; size_t priv_size; -@@ -1763,10 +1764,10 @@ int phy_ethtool_get_link_ksettings(struc +@@ -1969,10 +1970,10 @@ int phy_ethtool_get_link_ksettings(struc int phy_ethtool_set_link_ksettings(struct net_device *ndev, const struct ethtool_link_ksettings *cmd); int phy_ethtool_nway_reset(struct net_device *ndev); @@ -253,11 +253,11 @@ Signed-off-by: David S. Miller - int addr, size_t priv_size); + int base_addr, size_t priv_size); - #if IS_ENABLED(CONFIG_PHYLIB) int __init mdio_bus_init(void); -@@ -1778,46 +1779,65 @@ int phy_ethtool_get_sset_count(struct ph - int phy_ethtool_get_stats(struct phy_device *phydev, - struct ethtool_stats *stats, u64 *data); + void mdio_bus_exit(void); +@@ -1995,46 +1996,65 @@ int __phy_hwtstamp_set(struct phy_device + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); -static inline int phy_package_read(struct phy_device *phydev, u32 regnum) +static inline int phy_package_address(struct phy_device *phydev, diff --git a/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch index b355031aa5..50a454b2c9 100644 --- a/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch +++ b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch @@ -115,9 +115,9 @@ Signed-off-by: David S. Miller /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) { - /* Skip PHYs with reg property set */ -- if (of_find_property(child, "reg", NULL)) +- if (of_property_present(child, "reg")) + /* Skip PHYs with reg property set or ethernet-phy-package node */ -+ if (of_find_property(child, "reg", NULL) || ++ if (of_property_present(child, "reg") || + of_node_name_eq(child, "ethernet-phy-package")) continue; diff --git a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch index 3c7bf6c132..00bbd3b80b 100644 --- a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch +++ b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch @@ -170,7 +170,7 @@ Signed-off-by: David S. Miller refcount_t refcnt; unsigned long flags; size_t priv_size; -@@ -1793,9 +1796,12 @@ int phy_ethtool_set_link_ksettings(struc +@@ -1971,9 +1974,12 @@ int phy_ethtool_set_link_ksettings(struc const struct ethtool_link_ksettings *cmd); int phy_ethtool_nway_reset(struct net_device *ndev); int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size); @@ -181,5 +181,5 @@ Signed-off-by: David S. Miller +int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, + size_t priv_size); - #if IS_ENABLED(CONFIG_PHYLIB) int __init mdio_bus_init(void); + void mdio_bus_exit(void); diff --git a/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch index e20f94f1d4..e5f0c2f54d 100644 --- a/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch +++ b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -79,9 +79,9 @@ static int mtk_ppe_mib_wait_busy(struct +@@ -80,9 +80,9 @@ static int mtk_ppe_mib_wait_busy(struct int ret; u32 val; @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau if (ret) dev_err(ppe->dev, "MIB table busy"); -@@ -89,17 +89,31 @@ static int mtk_ppe_mib_wait_busy(struct +@@ -90,17 +90,31 @@ static int mtk_ppe_mib_wait_busy(struct return ret; } @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); -@@ -108,19 +122,19 @@ static int mtk_mib_entry_read(struct mtk +@@ -109,19 +123,19 @@ static int mtk_mib_entry_read(struct mtk if (mtk_is_netsys_v3_or_greater(ppe->eth)) { /* 64 bit for each counter */ u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); @@ -76,9 +76,9 @@ Signed-off-by: Felix Fietkau u32 pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); u32 pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); - *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; -- *packets = (pkt_cnt_high << 16) | pkt_cnt_low; +- *packets = ((u64)pkt_cnt_high << 16) | pkt_cnt_low; + acct->bytes += ((u64)byte_cnt_high << 32) | byte_cnt_low; -+ acct->packets += (pkt_cnt_high << 16) | pkt_cnt_low; ++ acct->packets += ((u64)pkt_cnt_high << 16) | pkt_cnt_low; } - return 0; @@ -86,10 +86,11 @@ Signed-off-by: Felix Fietkau } static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) -@@ -519,13 +533,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp +@@ -522,14 +536,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); dma_wmb(); mtk_ppe_cache_clear(ppe); +- - if (ppe->accounting) { - struct mtk_foe_accounting *acct; - @@ -100,7 +101,7 @@ Signed-off-by: Felix Fietkau } entry->hash = 0xffff; -@@ -550,11 +557,14 @@ static int __mtk_foe_entry_idle_time(str +@@ -554,11 +560,14 @@ static int __mtk_foe_entry_idle_time(str } static bool @@ -116,7 +117,7 @@ Signed-off-by: Felix Fietkau int len; if (hash == 0xffff) -@@ -565,18 +575,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp +@@ -569,18 +578,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp memcpy(&foe, hwe, len); if (!mtk_flow_entry_match(ppe->eth, entry, &foe, len) || @@ -155,7 +156,7 @@ Signed-off-by: Felix Fietkau struct mtk_flow_entry *cur; struct hlist_node *tmp; int idle; -@@ -585,7 +612,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -589,7 +615,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_list) { int cur_idle; @@ -166,7 +167,7 @@ Signed-off-by: Felix Fietkau __mtk_foe_entry_clear(ppe, entry, false); continue; } -@@ -600,10 +629,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -604,10 +632,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe } } @@ -196,7 +197,7 @@ Signed-off-by: Felix Fietkau struct mtk_eth *eth = ppe->eth; u16 timestamp = mtk_eth_timestamp(eth); struct mtk_foe_entry *hwe; -@@ -634,6 +682,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p +@@ -638,6 +685,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p dma_wmb(); @@ -209,7 +210,7 @@ Signed-off-by: Felix Fietkau mtk_ppe_cache_clear(ppe); } -@@ -796,21 +850,6 @@ out: +@@ -802,21 +855,6 @@ void __mtk_ppe_check_skb(struct mtk_ppe spin_unlock_bh(&ppe_lock); } @@ -231,7 +232,7 @@ Signed-off-by: Felix Fietkau int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) { if (!ppe) -@@ -838,32 +877,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe +@@ -844,32 +882,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe return mtk_ppe_wait_busy(ppe); } @@ -283,7 +284,7 @@ Signed-off-by: Felix Fietkau void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); -@@ -396,9 +399,8 @@ int mtk_foe_entry_set_queue(struct mtk_e +@@ -397,9 +400,8 @@ int mtk_foe_entry_set_queue(struct mtk_e unsigned int queue); int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); @@ -308,7 +309,7 @@ Signed-off-by: Felix Fietkau seq_printf(m, "%05x %s %7s", i, --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -501,24 +501,21 @@ static int +@@ -505,24 +505,21 @@ static int mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) { struct mtk_flow_entry *entry; diff --git a/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch index d83434fb2c..0a4a8ba0e1 100644 --- a/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch +++ b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch @@ -12,7 +12,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -421,7 +421,7 @@ free_pagelist: +@@ -599,7 +599,7 @@ mtk_wed_free_tx_buffer(struct mtk_wed_device static int mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) { @@ -21,7 +21,7 @@ Signed-off-by: Paolo Abeni dma_addr_t desc_phys; dev->rx_buf_ring.size = dev->wlan.rx_nbuf; -@@ -441,7 +441,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d +@@ -619,7 +619,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d static void mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) { @@ -41,10 +41,10 @@ Signed-off-by: Paolo Abeni __le32 buf0; __le32 token; } __packed __aligned(4); -@@ -105,7 +105,7 @@ struct mtk_wed_device { +@@ -109,7 +109,7 @@ struct mtk_wed_device { + struct { int size; - struct page_frag_cache rx_page; - struct mtk_rxbm_desc *desc; + struct mtk_wed_bm_desc *desc; dma_addr_t desc_phys; diff --git a/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch index 32ac37e8d0..4fc32e3e96 100644 --- a/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch @@ -26,9 +26,9 @@ Signed-off-by: Paolo Abeni #define PHY_ID_AQR405 0x03a1b4b0 +#define PHY_ID_AQR111 0x03a1b610 +#define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 #define PHY_ID_AQR113C 0x31c31c12 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 @@ -670,6 +672,16 @@ static int aqr107_probe(struct phy_devic return aqr_hwmon_probe(phydev); } @@ -91,12 +91,12 @@ Signed-off-by: Paolo Abeni PHY_ID_MATCH_MODEL(PHY_ID_AQR405), .name = "Aquantia AQR405", .config_aneg = aqr_config_aneg, -@@ -782,6 +832,8 @@ static struct mdio_device_id __maybe_unu +@@ -820,6 +870,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { } - }; diff --git a/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch index 073bbbd49d..5be82455c1 100644 --- a/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch @@ -17,15 +17,15 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -24,6 +24,7 @@ - #define PHY_ID_AQR405 0x03a1b4b0 - #define PHY_ID_AQR111 0x03a1b610 #define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 +#define PHY_ID_AQR113 0x31c31c40 #define PHY_ID_AQR113C 0x31c31c12 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 @@ -802,6 +803,25 @@ static struct phy_driver aqr_driver[] = - .read_status = aqr_read_status, + .link_change_notify = aqr107_link_change_notify, }, { + PHY_ID_MATCH_MODEL(PHY_ID_AQR113), @@ -51,9 +51,9 @@ Signed-off-by: David S. Miller .name = "Aquantia AQR113C", .probe = aqr107_probe, @@ -834,6 +854,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { } diff --git a/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch index 965b8c91b2..7dcfe7d01b 100644 --- a/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch @@ -16,7 +16,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -26,6 +26,7 @@ - #define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR412 0x03a1b712 #define PHY_ID_AQR113 0x31c31c40 #define PHY_ID_AQR113C 0x31c31c12 +#define PHY_ID_AQR813 0x31c31cb2 @@ -50,7 +50,7 @@ Signed-off-by: David S. Miller module_phy_driver(aqr_driver); @@ -856,6 +876,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, diff --git a/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch index 95dd24881b..c02e7f8888 100644 --- a/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch +++ b/target/linux/generic/backport-6.6/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -18,7 +18,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2527,9 +2527,13 @@ static void stmmac_bump_dma_threshold(st +@@ -2551,9 +2551,13 @@ static void stmmac_bump_dma_threshold(st * @priv: driver private structure * @budget: napi budget limiting this functions packet handling * @queue: TX queue index @@ -32,32 +32,34 @@ Signed-off-by: Paolo Abeni + bool *pending_packets) { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; - unsigned int bytes_compl = 0, pkts_compl = 0; -@@ -2692,7 +2696,7 @@ static int stmmac_tx_clean(struct stmmac + struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; +@@ -2713,7 +2717,7 @@ static int stmmac_tx_clean(struct stmmac /* We still have pending packets, let's call for a new scheduling */ if (tx_q->dirty_tx != tx_q->cur_tx) - stmmac_tx_timer_arm(priv, queue); + *pending_packets = true; - __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); - -@@ -5488,12 +5492,13 @@ static int stmmac_napi_poll_tx(struct na - struct stmmac_channel *ch = + u64_stats_update_begin(&txq_stats->napi_syncp); + u64_stats_add(&txq_stats->napi.tx_packets, tx_packets); +@@ -5603,6 +5607,7 @@ static int stmmac_napi_poll_tx(struct na container_of(napi, struct stmmac_channel, tx_napi); struct stmmac_priv *priv = ch->priv_data; + struct stmmac_txq_stats *txq_stats; + bool pending_packets = false; u32 chan = ch->index; int work_done; - priv->xstats.napi_poll++; +@@ -5611,7 +5616,7 @@ static int stmmac_napi_poll_tx(struct na + u64_stats_inc(&txq_stats->napi.poll); + u64_stats_update_end(&txq_stats->napi_syncp); - work_done = stmmac_tx_clean(priv, budget, chan); + work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets); work_done = min(work_done, budget); if (work_done < budget && napi_complete_done(napi, work_done)) { -@@ -5504,6 +5509,10 @@ static int stmmac_napi_poll_tx(struct na +@@ -5622,6 +5627,10 @@ static int stmmac_napi_poll_tx(struct na spin_unlock_irqrestore(&ch->lock, flags); } @@ -68,22 +70,24 @@ Signed-off-by: Paolo Abeni return work_done; } -@@ -5512,12 +5521,13 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5630,6 +5639,7 @@ static int stmmac_napi_poll_rxtx(struct struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, rxtx_napi); struct stmmac_priv *priv = ch->priv_data; + bool tx_pending_packets = false; int rx_done, tx_done, rxtx_done; - u32 chan = ch->index; - - priv->xstats.napi_poll++; + struct stmmac_rxq_stats *rxq_stats; + struct stmmac_txq_stats *txq_stats; +@@ -5645,7 +5655,7 @@ static int stmmac_napi_poll_rxtx(struct + u64_stats_inc(&txq_stats->napi.poll); + u64_stats_update_end(&txq_stats->napi_syncp); - tx_done = stmmac_tx_clean(priv, budget, chan); + tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets); tx_done = min(tx_done, budget); rx_done = stmmac_rx_zc(priv, budget, chan); -@@ -5542,6 +5552,10 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5670,6 +5680,10 @@ static int stmmac_napi_poll_rxtx(struct spin_unlock_irqrestore(&ch->lock, flags); } diff --git a/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch b/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch index e98397922d..813e6e5673 100644 --- a/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch +++ b/target/linux/generic/backport-6.6/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch @@ -217,10 +217,10 @@ Signed-off-by: Lee Jones + return le16_to_cpu(reply); +} + - static int omnia_leds_probe(struct i2c_client *client, - const struct i2c_device_id *id) + static int omnia_leds_probe(struct i2c_client *client) { -@@ -383,6 +471,21 @@ static int omnia_leds_probe(struct i2c_c + struct device *dev = &client->dev; +@@ -382,6 +470,21 @@ static int omnia_leds_probe(struct i2c_c leds->client = client; i2c_set_clientdata(client, leds); diff --git a/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch b/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch index e722109f91..b03ce68092 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch @@ -20,8 +20,8 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -20,29 +20,7 @@ - #include +@@ -19,29 +19,7 @@ + #include #include -struct nvmem_device { From 5b6bca812dee241eaa4aa13aed295926550b59c9 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 02:02:00 +0800 Subject: [PATCH 044/108] generic: 6.6: manually refresh pending patches Refresh pending patches for kernel 6.6. Signed-off-by: Daniel Golle Signed-off-by: Weijie Gao --- ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 6 +-- ...ame2-and-add-RENAME_WHITEOUT-support.patch | 32 ++++++------ ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 12 ++--- .../142-jffs2-add-splice-ops.patch | 2 +- ...t-send-arp-replies-if-src-and-target.patch | 4 +- ...he_alarm_to_be_used_as_wakeup_source.patch | 2 +- .../203-kallsyms_uncompressed.patch | 4 +- .../205-backtrace_module_info.patch | 4 +- .../302-mips_no_branch_likely.patch | 2 +- .../pending-6.6/305-mips_module_reloc.patch | 2 +- .../332-arc-add-OWRTDTB-section.patch | 2 +- ...er-NVMEM-devices-for-partitions-with.patch | 2 +- ...e-notifier-to-create-ubiblock-from-p.patch | 2 +- ...-09-block-partitions-populate-fwnode.patch | 4 +- ...50-11-block-implement-NVMEM-provider.patch | 10 ++-- ...0-13-mmc-core-set-card-fwnode_handle.patch | 2 +- ...mmc-block-set-fwnode-of-disk-devices.patch | 2 +- ...25p80-mx-disable-software-protection.patch | 10 ++-- .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 2 +- ...r-add-support-for-Gigadevice-GD25D05.patch | 2 +- ...nd-Add-support-for-Etron-EM73D044VCx.patch | 16 +++--- ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 15 +++--- ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 2 +- ...i-nor-disable-16-bit-sr-for-macronix.patch | 8 +-- .../500-fs_cdrom_dependencies.patch | 10 ++-- ...ass-device-lookup-for-dev-fit-rootfs.patch | 18 +++---- .../530-jffs2_make_lzma_available.patch | 48 +++++++++++------- .../pending-6.6/630-packet_socket_type.patch | 14 +++--- ...ng-with-source-address-failed-policy.patch | 8 +-- ...T-skip-GRO-for-foreign-MAC-addresses.patch | 10 ++-- ...83-of_net-add-mac-address-to-of-tree.patch | 6 +-- ...detach-callback-to-struct-phy_driver.patch | 6 +-- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 50 +++++++++---------- ...tek-detect-early-version-of-RTL8221B.patch | 2 +- ..._eth_soc-work-around-issue-with-send.patch | 8 +++ ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 14 +++--- ...ional-threading-for-backlog-processi.patch | 4 +- ...e-old-opp-to-config_clks-on-_set_opp.patch | 2 +- ...-support-mac-base-fixed-layout-cells.patch | 6 +-- .../811-pci_disable_usb_common_quirks.patch | 2 +- .../pending-6.6/834-ledtrig-libata.patch | 8 +-- ...-nxp-imx7d-pico-add-cpu-supply-nodes.patch | 4 +- .../pending-6.6/920-mangle_bootargs.patch | 6 +-- 43 files changed, 198 insertions(+), 177 deletions(-) diff --git a/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch index 4bf473f9a7..099b07ef7a 100644 --- a/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +++ b/target/linux/generic/pending-6.6/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -69,9 +69,9 @@ previously calculated offset is zero for the named platform it is able to boot Signed-off-by: Tobias Wolf --- ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -7897,7 +7897,7 @@ static void __init alloc_node_mem_map(st +--- a/mm/mm_init.c ++++ b/mm/mm_init.c +@@ -1673,7 +1673,7 @@ static void __init alloc_node_mem_map(st if (pgdat == NODE_DATA(0)) { mem_map = NODE_DATA(0)->node_mem_map; if (page_to_pfn(mem_map) != pgdat->node_start_pfn) diff --git a/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch index 8f40ae3ba2..b82f3d8012 100644 --- a/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch +++ b/target/linux/generic/pending-6.6/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -8,18 +8,18 @@ Signed-off-by: Felix Fietkau --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c -@@ -614,8 +614,8 @@ static int jffs2_rmdir (struct inode *di +@@ -617,8 +617,8 @@ static int jffs2_rmdir (struct inode *di return ret; } --static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, +-static int jffs2_mknod (struct mnt_idmap *idmap, struct inode *dir_i, - struct dentry *dentry, umode_t mode, dev_t rdev) -+static int __jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, -+ struct dentry *dentry, umode_t mode, dev_t rdev, bool whiteout) ++static int __jffs2_mknod (struct mnt_idmap *idmap, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev, bool whiteout) { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; -@@ -754,7 +754,11 @@ static int jffs2_mknod (struct user_name +@@ -758,7 +758,11 @@ static int jffs2_mknod (struct mnt_idmap mutex_unlock(&dir_f->sem); jffs2_complete_reservation(c); @@ -32,27 +32,27 @@ Signed-off-by: Felix Fietkau return 0; fail: -@@ -762,6 +766,19 @@ static int jffs2_mknod (struct user_name +@@ -766,6 +770,19 @@ static int jffs2_mknod (struct mnt_idmap return ret; } -+static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, -+ struct dentry *dentry, umode_t mode, dev_t rdev) ++static int jffs2_mknod (struct mnt_idmap *idmap, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev) +{ -+ return __jffs2_mknod(mnt_userns, dir_i, dentry, mode, rdev, false); ++ return __jffs2_mknod(idmap, dir_i, dentry, mode, rdev, false); +} + -+static int jffs2_whiteout (struct user_namespace *mnt_userns, struct inode *old_dir, -+ struct dentry *old_dentry) ++static int jffs2_whiteout (struct mnt_idmap *idmap, struct inode *old_dir, ++ struct dentry *old_dentry) +{ -+ return __jffs2_mknod(mnt_userns, old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, ++ return __jffs2_mknod(idmap, old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, + WHITEOUT_DEV, true); +} + - static int jffs2_rename (struct user_namespace *mnt_userns, + static int jffs2_rename (struct mnt_idmap *idmap, struct inode *old_dir_i, struct dentry *old_dentry, struct inode *new_dir_i, struct dentry *new_dentry, -@@ -773,7 +790,7 @@ static int jffs2_rename (struct user_nam +@@ -777,7 +794,7 @@ static int jffs2_rename (struct mnt_idma uint8_t type; uint32_t now; @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau return -EINVAL; /* The VFS will check for us and prevent trying to rename a -@@ -839,9 +856,14 @@ static int jffs2_rename (struct user_nam +@@ -843,9 +860,14 @@ static int jffs2_rename (struct mnt_idma if (d_is_dir(old_dentry) && !victim_f) inc_nlink(new_dir_i); @@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau - old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); + if (flags & RENAME_WHITEOUT) + /* Replace with whiteout */ -+ ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); ++ ret = jffs2_whiteout(idmap, old_dir_i, old_dentry); + else + /* Unlink the original */ + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), diff --git a/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch index f58fc791d2..c3a528ec90 100644 --- a/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch +++ b/target/linux/generic/pending-6.6/141-jffs2-add-RENAME_EXCHANGE-support.patch @@ -6,7 +6,7 @@ Signed-off-by: Felix Fietkau --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c -@@ -787,18 +787,31 @@ static int jffs2_rename (struct user_nam +@@ -791,18 +791,31 @@ static int jffs2_rename (struct mnt_idma int ret; struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); struct jffs2_inode_info *victim_f = NULL; @@ -40,7 +40,7 @@ Signed-off-by: Felix Fietkau victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); if (d_is_dir(new_dentry)) { struct jffs2_full_dirent *fd; -@@ -833,7 +846,7 @@ static int jffs2_rename (struct user_nam +@@ -837,7 +850,7 @@ static int jffs2_rename (struct mnt_idma if (ret) return ret; @@ -49,10 +49,10 @@ Signed-off-by: Felix Fietkau /* There was a victim. Kill it off nicely */ if (d_is_dir(new_dentry)) clear_nlink(d_inode(new_dentry)); -@@ -859,6 +872,12 @@ static int jffs2_rename (struct user_nam +@@ -863,6 +876,12 @@ static int jffs2_rename (struct mnt_idma if (flags & RENAME_WHITEOUT) /* Replace with whiteout */ - ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); + ret = jffs2_whiteout(idmap, old_dir_i, old_dentry); + else if (flags & RENAME_EXCHANGE) + /* Replace the original */ + ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i), @@ -62,7 +62,7 @@ Signed-off-by: Felix Fietkau else /* Unlink the original */ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), -@@ -890,7 +909,7 @@ static int jffs2_rename (struct user_nam +@@ -895,7 +914,7 @@ static int jffs2_rename (struct mnt_idma return ret; } @@ -70,4 +70,4 @@ Signed-off-by: Felix Fietkau + if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE)) drop_nlink(old_dir_i); - new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); + old_dir_i->i_mtime = inode_set_ctime_to_ts(old_dir_i, ITIME(now)); diff --git a/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch b/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch index de847a1f5c..ea57158cc2 100644 --- a/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch +++ b/target/linux/generic/pending-6.6/142-jffs2-add-splice-ops.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau .open = generic_file_open, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, -+ .splice_read = generic_file_splice_read, ++ .splice_read = filemap_splice_read, + .splice_write = iter_file_splice_write, .unlocked_ioctl=jffs2_ioctl, .mmap = generic_file_readonly_mmap, diff --git a/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch index f420d210c2..3abeacaffb 100644 --- a/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch +++ b/target/linux/generic/pending-6.6/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -17,8 +17,8 @@ Signed-off-by: Felix Fietkau +++ b/net/bridge/br_arp_nd_proxy.c @@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ if ((p && (p->flags & BR_PROXYARP)) || - (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | - BR_NEIGH_SUPPRESS)))) { + (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)) || + br_is_neigh_suppress_enabled(f->dst, vid)) { - if (!vid) + replied = true; + if (!memcmp(n->ha, sha, dev->addr_len)) diff --git a/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch index a9a5cdf8ba..85e5600847 100644 --- a/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch +++ b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch @@ -26,8 +26,8 @@ Signed-off-by: Daniel González Cabanelas dev_dbg(&client->dev, "%s\n", __func__); @@ -868,6 +869,12 @@ static int rs5c372_probe(struct i2c_clie - else rs5c372->type = id->driver_data; + } +#ifdef CONFIG_OF + if(of_property_read_bool(client->dev.of_node, diff --git a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch index 78ed262b78..5c6f620749 100644 --- a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch +++ b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch @@ -66,8 +66,8 @@ Signed-off-by: Felix Fietkau static int base_relative; static int lto_clang; @@ -608,6 +609,9 @@ static void write_src(void) - (unsigned char)(table[i]->seq >> 0)); - printf("\n"); + + free(markers); + if (uncompressed) + return; diff --git a/target/linux/generic/pending-6.6/205-backtrace_module_info.patch b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch index 27a1347981..7bbb596a5d 100644 --- a/target/linux/generic/pending-6.6/205-backtrace_module_info.patch +++ b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch @@ -32,8 +32,8 @@ Signed-off-by: Felix Fietkau + mod = __module_address(value); + if (mod) + snprintf(sym + len, sizeof(sym) - len, " [%s@%p+0x%x]", -+ mod->name, mod->core_layout.base, -+ mod->core_layout.size); ++ mod->name, mod->mem[MOD_TEXT].base, ++ mod->mem[MOD_TEXT].size); #endif + return string(buf, end, sym, spec); } diff --git a/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch b/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch index 542fba651f..669aa8143a 100644 --- a/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch +++ b/target/linux/generic/pending-6.6/302-mips_no_branch_likely.patch @@ -17,6 +17,6 @@ Signed-off-by: Felix Fietkau # -cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely - cflags-y += -msoft-float + cflags-y += -msoft-float -Wa,-msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib KBUILD_AFLAGS_MODULE += -mlong-calls diff --git a/target/linux/generic/pending-6.6/305-mips_module_reloc.patch b/target/linux/generic/pending-6.6/305-mips_module_reloc.patch index 5de9019677..6d13574b66 100644 --- a/target/linux/generic/pending-6.6/305-mips_module_reloc.patch +++ b/target/linux/generic/pending-6.6/305-mips_module_reloc.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau +++ b/arch/mips/Makefile @@ -97,8 +97,18 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely - cflags-y += -msoft-float + cflags-y += -msoft-float -Wa,-msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib +ifdef CONFIG_64BIT KBUILD_AFLAGS_MODULE += -mlong-calls diff --git a/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch index 30158cf399..4a76e216d5 100644 --- a/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch +++ b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch @@ -74,7 +74,7 @@ Signed-off-by: Evgeniy Didin + * + * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it. + */ -+ .owrt : { ++ .owrt : { + *(.owrt) + . = ALIGN(PAGE_SIZE); + } diff --git a/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch index 42b5a564b1..52acb0633b 100644 --- a/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch +++ b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch @@ -43,6 +43,6 @@ Signed-off-by: Rafał Miłecki + of_device_is_compatible(node, "brcm,env")) + return 0; + - config.id = -1; + config.id = NVMEM_DEVID_NONE; config.dev = &mtd->dev; config.name = dev_name(&mtd->dev); diff --git a/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch index eda3b108da..421daa0125 100644 --- a/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch +++ b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch @@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle +#include #include #include - #include + #include @@ -67,10 +68,10 @@ struct ubiblock_pdu { }; diff --git a/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch index 8aa5cba678..b46044f5d9 100644 --- a/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch +++ b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch @@ -21,10 +21,10 @@ Signed-off-by: Daniel Golle + #include "check.h" - static int (*check_part[])(struct parsed_partitions *) = { + static int (*const check_part[])(struct parsed_partitions *) = { @@ -298,6 +300,43 @@ static ssize_t whole_disk_show(struct de } - static DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); + static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); +static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev) +{ diff --git a/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch index e18b0c3a5c..d1972d97dc 100644 --- a/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch +++ b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch @@ -33,7 +33,7 @@ Signed-off-by: Daniel Golle + source "block/partitions/Kconfig" - config BLOCK_COMPAT + config BLK_MQ_PCI --- a/block/Makefile +++ b/block/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned @@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle + if (!bnv->bdev->bd_disk->fops->open) + return -EIO; + -+ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev, FMODE_READ); ++ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev->bd_disk, BLK_OPEN_READ); + if (ret) + return ret; + @@ -119,12 +119,12 @@ Signed-off-by: Daniel Golle + } + +err_release_bdev: -+ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk, FMODE_READ); ++ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk); + + return ret; +} + -+static int blk_nvmem_register(struct device *dev, struct class_interface *iface) ++static int blk_nvmem_register(struct device *dev) +{ + struct device_node *np = dev_of_node(dev); + struct block_device *bdev = dev_to_bdev(dev); @@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle + return 0; +} + -+static void blk_nvmem_unregister(struct device *dev, struct class_interface *iface) ++static void blk_nvmem_unregister(struct device *dev) +{ + struct block_device *bdev = dev_to_bdev(dev); + struct blk_nvmem *bnv_c, *bnv = NULL; diff --git a/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch index fada280437..cfc43318ca 100644 --- a/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch +++ b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch @@ -13,8 +13,8 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -363,6 +363,8 @@ int mmc_add_card(struct mmc_card *card) + mmc_add_card_debugfs(card); - #endif card->dev.of_node = mmc_of_find_child_device(card->host, 0); + if (card->dev.of_node && !card->dev.fwnode) + card->dev.fwnode = &card->dev.of_node->fwnode; diff --git a/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch index a9e53f1155..e645855475 100644 --- a/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch +++ b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch @@ -36,4 +36,4 @@ Signed-off-by: Daniel Golle + string_get_size((u64)size, 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); - pr_info("%s: %s %s %s %s\n", + pr_info("%s: %s %s %s%s\n", diff --git a/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch index 1e28077338..0bed77b3b5 100644 --- a/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch +++ b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch @@ -8,11 +8,11 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c -@@ -106,6 +106,7 @@ static void macronix_nor_default_init(st +@@ -115,6 +115,7 @@ static void macronix_nor_default_init(st { - nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; - nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; + if (!nor->params->set_4byte_addr_mode) + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; + nor->flags |= SNOR_F_HAS_LOCK; - } - static const struct spi_nor_fixups macronix_nor_fixups = { + return 0; + } diff --git a/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch index d2a9fb3436..371f1a7276 100644 --- a/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch +++ b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau + &spi_nor_xtx, }; - static const struct flash_info *spi_nor_match_id(struct spi_nor *nor, + static const struct flash_info spi_nor_generic_flash = { --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -633,6 +633,7 @@ extern const struct spi_nor_manufacturer diff --git a/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch index 581e06190b..3fdd354e6b 100644 --- a/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch +++ b/target/linux/generic/pending-6.6/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch @@ -15,7 +15,7 @@ Signed-off-by: Koen Vandeputte static const struct flash_info gigadevice_nor_parts[] = { + { "gd25q05", INFO(0xc84010, 0, 64 * 1024, 1) -+ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32) diff --git a/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch b/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch index 81378fba86..8fd1365952 100644 --- a/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch +++ b/target/linux/generic/pending-6.6/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch @@ -40,15 +40,17 @@ Submitted-by: Daniel Danzberger --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile -@@ -1,3 +1,3 @@ +@@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o ato.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o ato.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o +-spinand-objs := core.o alliancememory.o ato.o esmt.o gigadevice.o macronix.o +-spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o gigadevice.o ++spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -939,6 +939,7 @@ static const struct nand_ops spinand_ops - static const struct spinand_manufacturer *spinand_manufacturers[] = { +@@ -940,6 +940,7 @@ static const struct spinand_manufacturer + &alliancememory_spinand_manufacturer, &ato_spinand_manufacturer, &esmt_c8_spinand_manufacturer, + &etron_spinand_manufacturer, @@ -158,8 +160,8 @@ Submitted-by: Daniel Danzberger +}; --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h -@@ -262,6 +262,7 @@ struct spinand_manufacturer { - /* SPI NAND manufacturers */ +@@ -263,6 +263,7 @@ struct spinand_manufacturer { + extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; extern const struct spinand_manufacturer ato_spinand_manufacturer; extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +extern const struct spinand_manufacturer etron_spinand_manufacturer; diff --git a/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch index f95ec46f14..b63b333c47 100644 --- a/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +++ b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -40,14 +40,15 @@ Signed-off-by: Daniel Golle #ifdef CONFIG_ROOT_NFS #define NFSROOT_TIMEOUT_MIN 5 -@@ -579,6 +602,10 @@ void __init mount_root(void) - return; - } - #endif +@@ -408,6 +408,11 @@ void __init mount_root(void) + + void __init mount_root(char *root_device_name) + { +#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV + if (!mount_ubi_rootfs()) + return; +#endif - if (ROOT_DEV == 0 && root_device_name && root_fs_names) { - if (mount_nodev_root() == 0) - return; ++ + switch (ROOT_DEV) { + case Root_NFS: + mount_nfs_root(); diff --git a/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch index 5357c7e15d..16bdfdd4b5 100644 --- a/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +++ b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -31,4 +31,4 @@ Signed-off-by: Daniel Golle + return 0; - out_destroy_wq: + out_remove_minor: diff --git a/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch index 99e0fc72bf..e69eaf6bcc 100644 --- a/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch +++ b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch @@ -20,11 +20,11 @@ Signed-off-by: Nick Hainke --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c -@@ -107,6 +107,7 @@ static void macronix_nor_default_init(st +@@ -115,6 +115,7 @@ static void macronix_nor_default_init(st { - nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; - nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; + if (!nor->params->set_4byte_addr_mode) + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; + nor->flags &= ~SNOR_F_HAS_16BIT_SR; nor->flags |= SNOR_F_HAS_LOCK; - } + return 0; diff --git a/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch b/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch index 2053c0fbe2..7c143584a4 100644 --- a/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch +++ b/target/linux/generic/pending-6.6/500-fs_cdrom_dependencies.patch @@ -17,9 +17,9 @@ Subject: [PATCH] fs: add cdrom dependency tristate "Apple Macintosh file system support" depends on BLOCK + select CDROM + select BUFFER_HEAD select NLS - help - If you say Y here, you will be able to mount Macintosh-formatted + select LEGACY_DIRECT_IO --- a/fs/hfsplus/Kconfig +++ b/fs/hfsplus/Kconfig @@ -2,6 +2,7 @@ @@ -27,9 +27,9 @@ Subject: [PATCH] fs: add cdrom dependency tristate "Apple Extended HFS file system support" depends on BLOCK + select CDROM + select BUFFER_HEAD select NLS select NLS_UTF8 - help --- a/fs/isofs/Kconfig +++ b/fs/isofs/Kconfig @@ -1,6 +1,7 @@ @@ -37,9 +37,9 @@ Subject: [PATCH] fs: add cdrom dependency config ISO9660_FS tristate "ISO 9660 CDROM file system support" + select CDROM + select BUFFER_HEAD help This is the standard file system used on CD-ROMs. It was previously - known as "High Sierra File System" and is called "hsfs" on other --- a/fs/udf/Kconfig +++ b/fs/udf/Kconfig @@ -1,6 +1,7 @@ @@ -47,6 +47,6 @@ Subject: [PATCH] fs: add cdrom dependency config UDF_FS tristate "UDF file system support" + select CDROM + select BUFFER_HEAD select CRC_ITU_T select NLS - help diff --git a/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch index 685a5f9da5..e6ad104981 100644 --- a/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch +++ b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch @@ -13,13 +13,13 @@ Signed-off-by: Daniel Golle --- a/init/do_mounts.c +++ b/init/do_mounts.c -@@ -645,7 +645,8 @@ void __init prepare_namespace(void) +@@ -463,7 +463,8 @@ static dev_t __init parse_root_device(char + int error; + dev_t dev; - if (saved_root_name[0]) { - root_device_name = saved_root_name; -- if (!strncmp(root_device_name, "mtd", 3) || -+ if (!strncmp(root_device_name, "fit", 3) || -+ !strncmp(root_device_name, "mtd", 3) || - !strncmp(root_device_name, "ubi", 3)) { - mount_block_root(root_device_name, root_mountflags); - goto out; +- if (!strncmp(root_device_name, "mtd", 3) || ++ if (!strncmp(root_device_name, "fit", 3) || ++ !strncmp(root_device_name, "mtd", 3) || + !strncmp(root_device_name, "ubi", 3)) + return Root_Generic; + if (strcmp(root_device_name, "/dev/nfs") == 0) diff --git a/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch index 27a673399a..3e93c61839 100644 --- a/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch +++ b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch @@ -66,26 +66,33 @@ Signed-off-by: Alexandros C. Couloumbis +CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c -@@ -378,6 +378,9 @@ int __init jffs2_compressors_init(void) - #ifdef CONFIG_JFFS2_LZO - jffs2_lzo_init(); - #endif -+#ifdef CONFIG_JFFS2_LZMA -+ jffs2_lzma_init(); -+#endif +@@ -381,6 +381,9 @@ int __init jffs2_compressors_init(void) + ret = jffs2_lzo_init(); + if (ret) + goto exit_dynrubin; ++ ret = jffs2_lzma_init(); ++ if (ret) ++ goto exit_lzo; + + /* Setting default compression mode */ - #ifdef CONFIG_JFFS2_CMODE_NONE - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; -@@ -401,6 +404,9 @@ int __init jffs2_compressors_init(void) +@@ -402,6 +405,8 @@ int __init jffs2_compressors_init(void) + #endif + return 0; + ++exit_lzo: ++ jffs2_lzo_exit(); + exit_dynrubin: + jffs2_dynrubin_exit(); + exit_runinmips: +@@ -417,6 +422,7 @@ int __init jffs2_compressors_init(void) int jffs2_compressors_exit(void) { /* Unregistering compressors */ -+#ifdef CONFIG_JFFS2_LZMA + jffs2_lzma_exit(); -+#endif - #ifdef CONFIG_JFFS2_LZO jffs2_lzo_exit(); - #endif + jffs2_dynrubin_exit(); + jffs2_rubinmips_exit(); --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -29,9 +29,9 @@ @@ -101,13 +108,16 @@ Signed-off-by: Alexandros C. Couloumbis #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ #define JFFS2_DYNRUBIN_DISABLED /* for decompression */ -@@ -101,5 +101,9 @@ void jffs2_zlib_exit(void); - int jffs2_lzo_init(void); - void jffs2_lzo_exit(void); +@@ -115,5 +115,12 @@ extern void jffs2_lzo_exit(void); + static inline int jffs2_lzo_init(void) { return 0; } + static inline void jffs2_lzo_exit(void) {} #endif +#ifdef CONFIG_JFFS2_LZMA -+int jffs2_lzma_init(void); -+void jffs2_lzma_exit(void); ++extern int jffs2_lzma_init(void); ++extern void jffs2_lzma_exit(void); ++#else ++static inline int jffs2_lzma_init(void) { return 0; } ++static inline void jffs2_lzma_exit(void) {} +#endif #endif /* __JFFS2_COMPR_H__ */ diff --git a/target/linux/generic/pending-6.6/630-packet_socket_type.patch b/target/linux/generic/pending-6.6/630-packet_socket_type.patch index c40c709635..f12a09e65f 100644 --- a/target/linux/generic/pending-6.6/630-packet_socket_type.patch +++ b/target/linux/generic/pending-6.6/630-packet_socket_type.patch @@ -21,10 +21,10 @@ Signed-off-by: Felix Fietkau /* Packet socket options */ @@ -59,6 +61,7 @@ struct sockaddr_ll { - #define PACKET_ROLLOVER_STATS 21 #define PACKET_FANOUT_DATA 22 #define PACKET_IGNORE_OUTGOING 23 -+#define PACKET_RECV_TYPE 24 + #define PACKET_VNET_HDR_SZ 24 ++#define PACKET_RECV_TYPE 25 #define PACKET_FANOUT_HASH 0 #define PACKET_FANOUT_LB 1 @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; @@ -4013,6 +4016,16 @@ packet_setsockopt(struct socket *sock, i - WRITE_ONCE(po->xmit, val ? packet_direct_xmit : dev_queue_xmit); + packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val); return 0; } + case PACKET_RECV_TYPE: @@ -113,8 +113,8 @@ Signed-off-by: Felix Fietkau return -ENOPROTOOPT; } @@ -4069,6 +4082,13 @@ static int packet_getsockopt(struct sock - case PACKET_VNET_HDR: - val = po->has_vnet_hdr; + case PACKET_VNET_HDR_SZ: + val = READ_ONCE(po->vnet_hdr_sz); break; + case PACKET_RECV_TYPE: + if (len > sizeof(unsigned int)) @@ -129,10 +129,10 @@ Signed-off-by: Felix Fietkau --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -136,6 +136,7 @@ struct packet_sock { - int (*xmit)(struct sk_buff *skb); + struct net_device __rcu *cached_dev; struct packet_type prot_hook ____cacheline_aligned_in_smp; atomic_t tp_drops ____cacheline_aligned_in_smp; + unsigned int pkt_type; }; - static inline struct packet_sock *pkt_sk(struct sock *sk) + #define pkt_sk(ptr) container_of_const(ptr, struct packet_sock, sk) diff --git a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 72e8de2f1d..3ab023fdeb 100644 --- a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -125,7 +125,7 @@ Signed-off-by: Jonas Gorski +static const struct rt6_info ip6_policy_failed_entry_template = { + .dst = { -+ .__refcnt = ATOMIC_INIT(1), ++ .__rcuref = RCUREF_INIT(1), + .__use = 1, + .obsolete = DST_OBSOLETE_FORCE_CHK, + .error = -EACCES, @@ -137,7 +137,7 @@ Signed-off-by: Jonas Gorski + static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { - .__refcnt = ATOMIC_INIT(1), + .__rcuref = RCUREF_INIT(1), @@ -1039,6 +1053,7 @@ static const int fib6_prop[RTN_MAX + 1] [RTN_BLACKHOLE] = -EINVAL, [RTN_UNREACHABLE] = -EHOSTUNREACH, @@ -213,7 +213,7 @@ Signed-off-by: Jonas Gorski GFP_KERNEL); @@ -6499,11 +6535,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); - INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); + INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->dst.rt_uncached); + net->ipv6.ip6_policy_failed_entry = + kmemdup(&ip6_policy_failed_entry_template, @@ -223,7 +223,7 @@ Signed-off-by: Jonas Gorski + net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, + ip6_template_metrics, true); -+ INIT_LIST_HEAD(&net->ipv6.ip6_policy_failed_entry->rt6i_uncached); ++ INIT_LIST_HEAD(&net->ipv6.ip6_policy_failed_entry->dst.rt_uncached); + net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, sizeof(*net->ipv6.ip6_blk_hole_entry), diff --git a/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 11850c0418..26836240ee 100644 --- a/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -28,13 +28,13 @@ Signed-off-by: Felix Fietkau #endif + __u8 gro_skip:1; + #if IS_ENABLED(CONFIG_IP_VS) __u8 ipvs_property:1; - __u8 inner_protocol_type:1; --- a/net/core/gro.c +++ b/net/core/gro.c @@ -491,6 +491,9 @@ static enum gro_result dev_gro_receive(s + enum gro_result ret; int same_flow; - int grow; + if (skb->gro_skip) + goto normal; @@ -109,9 +109,9 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8824,6 +8868,7 @@ int dev_set_mac_address(struct net_devic - if (err) - return err; +@@ -8821,6 +8865,7 @@ int dev_set_mac_address(struct net_devic + return err; + } dev->addr_assign_type = NET_ADDR_SET; + netdev_update_addr_mask(dev); call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); diff --git a/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch index 03ee537fb8..9e81cb1f27 100644 --- a/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch @@ -18,8 +18,8 @@ property. This way, the MAC address can be accessed using procfs. --- a/net/core/of_net.c +++ b/net/core/of_net.c @@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct - return 0; } + EXPORT_SYMBOL(of_get_mac_address_nvmem); +static int of_add_mac_address(struct device_node *np, u8* addr) +{ @@ -62,8 +62,8 @@ property. This way, the MAC address can be accessed using procfs. - return 0; + goto found; -- return of_get_mac_addr_nvmem(np, addr); -+ ret = of_get_mac_addr_nvmem(np, addr); +- return of_get_mac_address_nvmem(np, addr); ++ ret = of_get_mac_address_nvmem(np, addr); + if (ret) + return ret; + diff --git a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch index e4937a1df1..61dd11727f 100644 --- a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,9 +11,9 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1850,6 +1850,9 @@ void phy_detach(struct phy_device *phyde - struct module *ndev_owner = NULL; - struct mii_bus *bus; +@@ -1753,6 +1753,9 @@ void phy_detach(struct phy_device *phyde + if (phydev->devlink) + device_link_del(phydev->devlink); + if (phydev->drv && phydev->drv->detach) + phydev->drv->detach(phydev); diff --git a/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index 989aca8f35..85e42d5a94 100644 --- a/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -15,18 +15,18 @@ Signed-off-by: Felix Fietkau --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -59,6 +59,7 @@ struct br_ip_list { - #define BR_MRP_LOST_IN_CONT BIT(19) - #define BR_TX_FWD_OFFLOAD BIT(20) #define BR_PORT_LOCKED BIT(21) -+#define BR_BPDU_FILTER BIT(22) + #define BR_PORT_MAB BIT(22) + #define BR_NEIGH_VLAN_SUPPRESS BIT(23) ++#define BR_BPDU_FILTER BIT(24) #define BR_DEFAULT_AGEING_TIME (300 * HZ) --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -199,6 +199,7 @@ out: - void br_flood(struct net_bridge *br, struct sk_buff *skb, - enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig, + u16 vid) { + const unsigned char *dest = eth_hdr(skb)->h_dest; struct net_bridge_port *prev = NULL; @@ -107,9 +107,9 @@ Signed-off-by: Felix Fietkau --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -561,6 +561,7 @@ enum { - IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, - IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, - IFLA_BRPORT_LOCKED, + IFLA_BRPORT_MCAST_MAX_GROUPS, + IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, + IFLA_BRPORT_BACKUP_NHID, + IFLA_BRPORT_BPDU_FILTER, __IFLA_BRPORT_MAX }; @@ -117,47 +117,47 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -188,6 +188,7 @@ static inline size_t br_port_info_size(v - + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ - + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ + nla_total_size(1) /* IFLA_BRPORT_LOCKED */ + + nla_total_size(1) /* IFLA_BRPORT_MAB */ + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_VLAN_SUPPRESS */ + + nla_total_size(1) /* IFLA_BRPORT_BPDU_FILTER */ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ @@ -274,7 +275,8 @@ static int br_port_fill_attrs(struct sk_ - nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN, - !!(p->flags & BR_MRP_LOST_IN_CONT)) || - nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) || -- nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED))) -+ nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) || + nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) || + nla_put_u8(skb, IFLA_BRPORT_MAB, !!(p->flags & BR_PORT_MAB)) || + nla_put_u8(skb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, +- !!(p->flags & BR_NEIGH_VLAN_SUPPRESS))) ++ !!(p->flags & BR_NEIGH_VLAN_SUPPRESS)) || + nla_put_u8(skb, IFLA_BRPORT_BPDU_FILTER, !!(p->flags & BR_BPDU_FILTER))) return -EMSGSIZE; timerval = br_timer_value(&p->message_age_timer); @@ -878,6 +880,7 @@ static const struct nla_policy br_port_p - [IFLA_BRPORT_LOCKED] = { .type = NLA_U8 }, - [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, - [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 }, + [IFLA_BRPORT_MCAST_MAX_GROUPS] = { .type = NLA_U32 }, + [IFLA_BRPORT_NEIGH_VLAN_SUPPRESS] = NLA_POLICY_MAX(NLA_U8, 1), + [IFLA_BRPORT_BACKUP_NHID] = { .type = NLA_U32 }, + [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, }; /* Change the state of the port and notify spanning tree */ @@ -943,6 +946,7 @@ static int br_setport(struct net_bridge_ - br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS); - br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); - br_set_port_flag(p, tb, IFLA_BRPORT_LOCKED, BR_PORT_LOCKED); + br_set_port_flag(p, tb, IFLA_BRPORT_MAB, BR_PORT_MAB); + br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, + BR_NEIGH_VLAN_SUPPRESS); + br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); - changed_mask = old_flags ^ p->flags; - + if ((p->flags & BR_PORT_MAB) && + (!(p->flags & BR_PORT_LOCKED) || !(p->flags & BR_LEARNING))) { --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -57,7 +57,7 @@ #include "dev.h" #define RTNL_MAX_TYPE 50 --#define RTNL_SLAVE_MAX_TYPE 40 -+#define RTNL_SLAVE_MAX_TYPE 41 +-#define RTNL_SLAVE_MAX_TYPE 44 ++#define RTNL_SLAVE_MAX_TYPE 45 struct rtnl_link { rtnl_doit_func doit; diff --git a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch index f5987109f6..32d81d56f8 100644 --- a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -22,7 +22,7 @@ Signed-off-by: Daniel Golle + int val; + u32 id; + -+ if (phydev->mdio.bus->probe_capabilities >= MDIOBUS_C45) { ++ if (phydev->drv->read_mmd) { + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID1); + if (val < 0) + return 0; diff --git a/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch index a1cc109050..17c7d92ce0 100644 --- a/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch +++ b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch @@ -16,6 +16,14 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" @@ -1562,12 +1562,28 @@ static void mtk_wake_queue(struct mtk_et } } diff --git a/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch index 5bd2850fec..6fe29bc6c9 100644 --- a/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch +++ b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -27,13 +27,13 @@ Signed-off-by: Daniel Golle F: include/linux/pcs/pcs-mtk-lynxi.h +F: include/linux/pcs/pcs-mtk-usxgmii.h - MEDIATEK I2C CONTROLLER DRIVER - M: Qii Wang + MEDIATEK ETHERNET PHY DRIVERS + M: Daniel Golle --- a/drivers/net/pcs/Kconfig +++ b/drivers/net/pcs/Kconfig @@ -18,6 +18,17 @@ config PCS_LYNX - This module provides helpers to phylink for managing the Lynx PCS - which is part of the Layerscape and QorIQ Ethernet SERDES. + This module provides helpers to phylink for managing the LynxI PCS + which is part of MediaTek's SoC and Ethernet switch ICs. +config PCS_MTK_USXGMII + tristate "MediaTek USXGMII PCS" @@ -51,10 +51,10 @@ Signed-off-by: Daniel Golle depends on OF && (ARCH_RZN1 || COMPILE_TEST) --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o - obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o - obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o +@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o + obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o +obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o --- /dev/null +++ b/drivers/net/pcs/pcs-mtk-usxgmii.c diff --git a/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch index 42c8519c90..bb9149a668 100644 --- a/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -20,10 +20,10 @@ Signed-off-by: Felix Fietkau /** * napi_disable - prevent NAPI from scheduling -@@ -3152,6 +3153,7 @@ struct softnet_data { +@@ -3129,6 +3130,7 @@ struct softnet_data { + /* stats */ unsigned int processed; unsigned int time_squeeze; - unsigned int received_rps; + unsigned int process_queue_empty; #ifdef CONFIG_RPS struct softnet_data *rps_ipi_list; diff --git a/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch index 2b3e4bbf71..cb5d30db27 100644 --- a/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch +++ b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch @@ -80,7 +80,7 @@ Signed-off-by: Christian Marangi -typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table, +typedef int (*config_clks_t)(struct device *dev, -+ struct opp_table *opp_table, struct dev_pm_opp *old_opp, ++ struct opp_table *opp_table, struct dev_pm_opp *old_opp, struct dev_pm_opp *opp, void *data, bool scaling_down); /** diff --git a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch index 9bb94a28b5..2f0dcd91d9 100644 --- a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch +++ b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -10,14 +10,14 @@ string. --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0-only +@@ -2,6 +2,7 @@ menuconfig NVMEM bool "NVMEM Support" -+ select GENERIC_NET_UTILS imply NVMEM_LAYOUTS ++ select GENERIC_NET_UTILS help Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... + --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -7,9 +7,12 @@ diff --git a/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch index 98ea4c06d9..eb5aa15d30 100644 --- a/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch +++ b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch @@ -111,5 +111,5 @@ Signed-off-by: Felix Fietkau +} +#endif - #ifdef CONFIG_PM extern const struct dev_pm_ops usb_hcd_pci_pm_ops; + #endif /* CONFIG_USB_PCI */ diff --git a/target/linux/generic/pending-6.6/834-ledtrig-libata.patch b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch index 050c3515f6..562f9b866c 100644 --- a/target/linux/generic/pending-6.6/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch @@ -46,7 +46,7 @@ Signed-off-by: Daniel Golle --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -663,6 +663,19 @@ u64 ata_tf_read_block(const struct ata_t - return block; + qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF; } +#ifdef CONFIG_ATA_LEDS @@ -85,10 +85,10 @@ Signed-off-by: Daniel Golle ata_sff_port_init(ap); return ap; -@@ -5473,6 +5492,12 @@ static void ata_host_release(struct kref - +@@ -5469,6 +5488,12 @@ static void ata_host_release(struct kref kfree(ap->pmp_link); kfree(ap->slave_link); + kfree(ap->ncq_sense_buf); +#ifdef CONFIG_ATA_LEDS + if (ap->ledtrig) { + led_trigger_unregister(ap->ledtrig); @@ -145,5 +145,5 @@ Signed-off-by: Daniel Golle +#endif + /* owned by EH */ + u8 *ncq_sense_buf; u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; - }; diff --git a/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch b/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch index e25389363f..1f860e9c76 100644 --- a/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch +++ b/target/linux/generic/pending-6.6/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch @@ -24,8 +24,8 @@ Signed-off-by: Lech Perczak arch/arm/boot/dts/imx7d-pico.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) ---- a/arch/arm/boot/dts/imx7d-pico.dtsi -+++ b/arch/arm/boot/dts/imx7d-pico.dtsi +--- a/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi @@ -108,6 +108,14 @@ assigned-clock-rates = <0>, <32768>; }; diff --git a/target/linux/generic/pending-6.6/920-mangle_bootargs.patch b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch index 4552b4cd66..0d690e42e8 100644 --- a/target/linux/generic/pending-6.6/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch @@ -13,9 +13,9 @@ Signed-off-by: Imre Kaloz --- a/init/Kconfig +++ b/init/Kconfig -@@ -1836,6 +1836,15 @@ config EMBEDDED - an embedded system so certain expert options are available - for configuration. +@@ -1827,6 +1827,15 @@ config EMBEDDED + + If unsure, say N. +config MANGLE_BOOTARGS + bool "Rename offending bootargs" From d9bc5c93de1412ee13acc61e3aa0a52327b44e5e Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 4 Jan 2024 02:02:53 +0800 Subject: [PATCH 045/108] generic: 6.6: manually refresh hack patches Refresh hack patches for kernel 6.6. Signed-off-by: Weijie Gao --- .../generic/hack-6.6/204-module_strip.patch | 24 ++-- .../211-darwin-uuid-typedef-clash.patch | 6 +- .../hack-6.6/212-tools_portability.patch | 34 +++--- .../hack-6.6/220-arm-gc_sections.patch | 2 +- .../generic/hack-6.6/221-module_exports.patch | 58 +++------ .../linux/generic/hack-6.6/251-kconfig.patch | 6 +- .../generic/hack-6.6/259-regmap_dynamic.patch | 44 ++++--- .../260-crypto_test_dependencies.patch | 44 +++---- .../hack-6.6/261-lib-arc4-unhide.patch | 6 +- ...upport-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch | 4 +- .../721-net-add-packet-mangeling.patch | 6 +- ...hy-aquantia-enable-AQR112-and-AQR412.patch | 71 ++++------- ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 14 +-- ...mtk-lynxi-workaround-2500BaseX-no-an.patch | 33 ++++-- ...-r8152-add-LED-configuration-from-OF.patch | 2 +- .../765-mxl-gpy-control-LED-reg-from-DT.patch | 10 +- .../790-SFP-GE-T-ignore-TX_FAULT.patch | 4 +- .../800-GPIO-add-named-gpio-exports.patch | 112 ++++++++---------- .../hack-6.6/901-debloat_sock_diag.patch | 53 +++++---- 19 files changed, 247 insertions(+), 286 deletions(-) diff --git a/target/linux/generic/hack-6.6/204-module_strip.patch b/target/linux/generic/hack-6.6/204-module_strip.patch index 9fefd0bd6e..6ff9d6a13b 100644 --- a/target/linux/generic/hack-6.6/204-module_strip.patch +++ b/target/linux/generic/hack-6.6/204-module_strip.patch @@ -102,7 +102,7 @@ Signed-off-by: Felix Fietkau endif # MODULES --- a/kernel/module/main.c +++ b/kernel/module/main.c -@@ -988,6 +988,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE( +@@ -997,6 +997,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE( static const char vermagic[] = VERMAGIC_STRING; @@ -110,15 +110,15 @@ Signed-off-by: Felix Fietkau int try_to_force_load(struct module *mod, const char *reason) { #ifdef CONFIG_MODULE_FORCE_LOAD -@@ -999,6 +1000,7 @@ int try_to_force_load(struct module *mod +@@ -1008,6 +1009,7 @@ int try_to_force_load(struct module *mod return -ENOEXEC; #endif } +#endif - static char *get_modinfo(const struct load_info *info, const char *tag); - static char *get_next_modinfo(const struct load_info *info, const char *tag, -@@ -1958,9 +1960,11 @@ static int setup_load_info(struct load_i + /* Parse tag=value strings from .modinfo section */ + char *module_next_tag_pair(char *string, unsigned long *secsize) +@@ -2075,9 +2077,11 @@ static void module_augment_kernel_taints static int check_modinfo(struct module *mod, struct load_info *info, int flags) { @@ -131,14 +131,14 @@ Signed-off-by: Felix Fietkau if (flags & MODULE_INIT_IGNORE_VERMAGIC) modmagic = NULL; -@@ -1981,6 +1985,7 @@ static int check_modinfo(struct module * - mod->name); - add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); +@@ -2091,6 +2095,7 @@ static int check_modinfo(struct module * + info->name, modmagic, vermagic); + return -ENOEXEC; } +#endif - check_modinfo_retpoline(mod, info); - + err = check_modinfo_livepatch(mod, info); + if (err) --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1785,7 +1785,9 @@ static void read_symbols(const char *mod @@ -150,8 +150,8 @@ Signed-off-by: Felix Fietkau +#endif } - for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { -@@ -1948,8 +1950,10 @@ static void add_header(struct buffer *b, + check_sec_ref(mod, &info); +@@ -1944,8 +1946,10 @@ static void add_header(struct buffer *b, buf_printf(b, "BUILD_SALT;\n"); buf_printf(b, "BUILD_LTO_INFO;\n"); buf_printf(b, "\n"); diff --git a/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch index 50a6227148..9a1905a138 100644 --- a/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch +++ b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch @@ -11,12 +11,12 @@ Signed-off-by: Kevin Darbyshire-Bryant --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -38,6 +38,9 @@ typedef struct { - __u8 b[16]; - } guid_t; + typedef uint16_t __u16; + typedef unsigned char __u8; +#ifdef __APPLE__ +#define uuid_t compat_uuid_t +#endif - /* backwards compatibility, don't use in new code */ + /* UUID types for backward compatibility, don't use in new code */ typedef struct { __u8 b[16]; diff --git a/target/linux/generic/hack-6.6/212-tools_portability.patch b/target/linux/generic/hack-6.6/212-tools_portability.patch index add281991e..4671e75128 100644 --- a/target/linux/generic/hack-6.6/212-tools_portability.patch +++ b/target/linux/generic/hack-6.6/212-tools_portability.patch @@ -74,8 +74,8 @@ Signed-off-by: Felix Fietkau struct page; struct kmem_cache; @@ -51,7 +55,9 @@ typedef __s8 s8; - #define __force #define __user + #endif #define __must_check +#ifndef __cold #define __cold @@ -108,7 +108,7 @@ Signed-off-by: Felix Fietkau --- a/tools/arch/x86/include/asm/orc_types.h +++ b/tools/arch/x86/include/asm/orc_types.h @@ -40,7 +40,6 @@ - #define ORC_REG_MAX 15 + #define ORC_TYPE_REGS_PARTIAL 4 #ifndef __ASSEMBLY__ -#include @@ -123,13 +123,13 @@ Signed-off-by: Felix Fietkau +#if __BYTE_ORDER == __LITTLE_ENDIAN unsigned sp_reg:4; unsigned bp_reg:4; - unsigned type:2; - unsigned end:1; + unsigned type:3; + unsigned signal:1; -#elif defined(__BIG_ENDIAN_BITFIELD) +#elif __BYTE_ORDER == __BIG_ENDIAN unsigned bp_reg:4; unsigned sp_reg:4; - unsigned unused:5; + unsigned unused:4; --- a/tools/arch/x86/lib/insn.c +++ b/tools/arch/x86/lib/insn.c @@ -15,7 +15,11 @@ @@ -199,15 +199,15 @@ Signed-off-by: Felix Fietkau unsigned long __rb_parent_color; --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile -@@ -4,7 +4,7 @@ include ../scripts/Makefile.arch +@@ -40,7 +40,7 @@ include ../scripts/Makefile.arch + OBJTOOL_CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED) - # always use the host compiler - AR = $(HOSTAR) --CC = $(HOSTCC) -+CC = $(HOSTCC) $(HOST_EXTRACFLAGS) - LD = $(HOSTLD) + # Always want host compilation. +-HOST_OVERRIDES := CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" ++HOST_OVERRIDES := CC="$(HOSTCC) $(HOST_EXTRACFLAGS)" LD="$(HOSTLD)" AR="$(HOSTAR)" - ifeq ($(srctree),) + AWK = awk + MKDIR = mkdir @@ -43,6 +43,7 @@ BUILD_ORC := n ifeq ($(SRCARCH),x86) @@ -252,8 +252,8 @@ Signed-off-by: Felix Fietkau } +#endif - #define NEGATIVE_RELOC ((void *)-1L) - + static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn) + { --- a/tools/objtool/include/objtool/objtool.h +++ b/tools/objtool/include/objtool/objtool.h @@ -12,7 +12,9 @@ @@ -268,10 +268,10 @@ Signed-off-by: Felix Fietkau bool clean; --- a/tools/objtool/orc_dump.c +++ b/tools/objtool/orc_dump.c -@@ -5,10 +5,10 @@ +@@ -4,10 +4,10 @@ + */ #include - #include -#include #include #include @@ -285,7 +285,7 @@ Signed-off-by: Felix Fietkau @@ -7,11 +7,11 @@ #include - #include + #include -#include #include diff --git a/target/linux/generic/hack-6.6/220-arm-gc_sections.patch b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch index a6a6c7cf2c..257796aee9 100644 --- a/target/linux/generic/hack-6.6/220-arm-gc_sections.patch +++ b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch @@ -13,7 +13,7 @@ Signed-off-by: Gabor Juhos --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -124,6 +124,7 @@ config ARM - select HAVE_VIRT_CPU_ACCOUNTING_GEN + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select IRQ_FORCED_THREADING select LOCK_MM_AND_FIND_VMA + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION diff --git a/target/linux/generic/hack-6.6/221-module_exports.patch b/target/linux/generic/hack-6.6/221-module_exports.patch index 967510bcb6..5af4eba372 100644 --- a/target/linux/generic/hack-6.6/221-module_exports.patch +++ b/target/linux/generic/hack-6.6/221-module_exports.patch @@ -27,8 +27,8 @@ Signed-off-by: Felix Fietkau +#define SYMTAB_DISCARD_GPL +#endif + - /* Align . to a 8 byte boundary equals to maximum function alignment. */ - #define ALIGN_FUNCTION() . = ALIGN(8) + /* Align . function alignment. */ + #define ALIGN_FUNCTION() . = ALIGN(CONFIG_FUNCTION_ALIGNMENT) @@ -511,14 +521,14 @@ /* Kernel symbol table: Normal symbols */ \ @@ -64,12 +64,12 @@ Signed-off-by: Felix Fietkau + SYMTAB_DISCARD_GPL \ *(.discard) \ *(.discard.*) \ - *(.modinfo) \ ---- a/include/linux/export.h -+++ b/include/linux/export.h -@@ -72,6 +72,12 @@ struct kernel_symbol { - - #else + *(.export_symbol) \ +--- a/include/linux/export-internal.h ++++ b/include/linux/export-internal.h +@@ -23,6 +23,12 @@ + #define __KSYM_REF(sym) ".long " #sym + #endif +#ifdef MODULE +#define __EXPORT_SUFFIX(sym) @@ -80,39 +80,15 @@ Signed-off-by: Felix Fietkau /* * For every exported symbol, do the following: * -@@ -87,7 +93,7 @@ struct kernel_symbol { - extern typeof(sym) sym; \ - extern const char __kstrtab_##sym[]; \ - extern const char __kstrtabns_##sym[]; \ -- asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ -+ asm(" .section \"__ksymtab_strings" __EXPORT_SUFFIX(sym) "\",\"aMS\",%progbits,1 \n" \ - "__kstrtab_" #sym ": \n" \ - " .asciz \"" #sym "\" \n" \ - "__kstrtabns_" #sym ": \n" \ ---- a/include/asm-generic/export.h -+++ b/include/asm-generic/export.h -@@ -31,6 +31,12 @@ - #endif - .endm - -+#ifdef MODULE -+#define __EXPORT_SUFFIX(name) -+#else -+#define __EXPORT_SUFFIX(name) + #name -+#endif -+ - /* - * note on .section use: we specify progbits since usage of the "M" (SHF_MERGE) - * section flag requires it. Use '%progbits' instead of '@progbits' since the -@@ -44,7 +50,7 @@ - __ksymtab_\name: - __put \val, __kstrtab_\name - .previous -- .section __ksymtab_strings,"aMS",%progbits,1 -+ .section __ksymtab_strings __EXPORT_SUFFIX(name),"aMS",%progbits,1 - __kstrtab_\name: - .asciz "\name" - .previous +@@ -35,7 +41,7 @@ + * former apparently works on all arches according to the binutils source. + */ + #define __KSYMTAB(name, sym, sec, ns) \ +- asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1" "\n" \ ++ asm(" .section \"__ksymtab_strings" __EXPORT_SUFFIX(sym) "\",\"aMS\",%progbits,1" "\n" \ + "__kstrtab_" #name ":" "\n" \ + " .asciz \"" #name "\"" "\n" \ + "__kstrtabns_" #name ":" "\n" \ --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -388,7 +388,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa diff --git a/target/linux/generic/hack-6.6/251-kconfig.patch b/target/linux/generic/hack-6.6/251-kconfig.patch index fcf4eaf6e8..0cdbe948a1 100644 --- a/target/linux/generic/hack-6.6/251-kconfig.patch +++ b/target/linux/generic/hack-6.6/251-kconfig.patch @@ -35,7 +35,7 @@ Signed-off-by: John Crispin select CRYPTO_ALGAPI @@ -75,7 +75,7 @@ config CRYPTO_AEAD2 - select CRYPTO_RNG2 + select CRYPTO_ALGAPI2 config CRYPTO_SKCIPHER - tristate @@ -44,7 +44,7 @@ Signed-off-by: John Crispin select CRYPTO_ALGAPI @@ -85,7 +85,7 @@ config CRYPTO_SKCIPHER2 - select CRYPTO_RNG2 + select CRYPTO_ALGAPI2 config CRYPTO_HASH - tristate @@ -136,7 +136,7 @@ Signed-off-by: John Crispin config SND_SEQ_DEVICE tristate @@ -27,7 +27,7 @@ config SND_RAWMIDI - select SND_SEQ_DEVICE if SND_SEQUENCER != n + The device contains 16 substreams corresponding to UMP groups. config SND_COMPRESS_OFFLOAD - tristate diff --git a/target/linux/generic/hack-6.6/259-regmap_dynamic.patch b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch index 8d25f59ce2..c62e0a6242 100644 --- a/target/linux/generic/hack-6.6/259-regmap_dynamic.patch +++ b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch @@ -14,20 +14,27 @@ Signed-off-by: Felix Fietkau --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig -@@ -4,10 +4,9 @@ +@@ -4,8 +4,7 @@ # subsystems should select the appropriate symbols. config REGMAP -- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) +- bool +- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI) ++ tristate select IRQ_DOMAIN if REGMAP_IRQ select MDIO_BUS if REGMAP_MDIO -- bool -+ tristate + help +@@ -19,7 +18,7 @@ config REGMAP - config REGCACHE_COMPRESSED - select LZO_COMPRESS -@@ -15,53 +14,67 @@ config REGCACHE_COMPRESSED - bool + config REGMAP_KUNIT + tristate "KUnit tests for regmap" +- depends on KUNIT && REGMAP ++ depends on KUNIT + default KUNIT_ALL_TESTS + select REGMAP_RAM + +@@ -34,60 +33,76 @@ config REGMAP_BUILD + normally enabled. config REGMAP_AC97 + select REGMAP @@ -70,6 +77,10 @@ Signed-off-by: Felix Fietkau + select REGMAP bool + config REGMAP_RAM ++ select REGMAP + tristate + config REGMAP_SOUNDWIRE + select REGMAP tristate @@ -94,27 +105,28 @@ Signed-off-by: Felix Fietkau + select REGMAP tristate depends on SPI + + config REGMAP_FSI ++ select REGMAP + tristate + depends on FSI --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile -@@ -2,10 +2,14 @@ +@@ -2,9 +2,11 @@ # For include/trace/define_trace.h to include trace.h CFLAGS_regmap.o := -I$(src) -obj-$(CONFIG_REGMAP) += regmap.o regcache.o --obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o --obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o +-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o regcache-maple.o -obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o -+regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o ++regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o regcache-maple.o +ifdef CONFIG_DEBUG_FS +regmap-core-objs += regmap-debugfs.o +endif -+ifdef CONFIG_REGCACHE_COMPRESSED -+regmap-core-objs += regcache-lzo.o -+endif +obj-$(CONFIG_REGMAP) += regmap-core.o + obj-$(CONFIG_REGMAP_KUNIT) += regmap-kunit.o obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o - obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -9,6 +9,7 @@ diff --git a/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch b/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch index 7ea517496e..6221d0f868 100644 --- a/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch +++ b/target/linux/generic/hack-6.6/260-crypto_test_dependencies.patch @@ -14,39 +14,41 @@ Signed-off-by: Felix Fietkau --- a/crypto/Kconfig +++ b/crypto/Kconfig -@@ -142,13 +142,13 @@ config CRYPTO_MANAGER +@@ -148,15 +148,15 @@ config CRYPTO_MANAGER cbc(aes). config CRYPTO_MANAGER2 - def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y) -- select CRYPTO_AEAD2 -- select CRYPTO_HASH2 -- select CRYPTO_SKCIPHER2 -- select CRYPTO_AKCIPHER2 -- select CRYPTO_KPP2 - select CRYPTO_ACOMP2 +- select CRYPTO_AEAD2 +- select CRYPTO_AKCIPHER2 +- select CRYPTO_SIG2 +- select CRYPTO_HASH2 +- select CRYPTO_KPP2 +- select CRYPTO_RNG2 +- select CRYPTO_SKCIPHER2 + def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS) -+ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS -+ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS -+ select CRYPTO_SKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS -+ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS -+ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS + select CRYPTO_ACOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_SIG2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_RNG2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_SKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS config CRYPTO_USER tristate "Userspace cryptographic algorithm configuration" --- a/crypto/algboss.c +++ b/crypto/algboss.c -@@ -211,8 +211,12 @@ static int cryptomgr_schedule_test(struc - type = alg->cra_flags; +@@ -204,6 +204,10 @@ static int cryptomgr_schedule_test(struc + memcpy(param->alg, alg->cra_name, sizeof(param->alg)); + param->type = alg->cra_flags; - /* Do not test internal algorithms. */ +#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS -+ type |= CRYPTO_ALG_TESTED; -+#else - if (type & CRYPTO_ALG_INTERNAL) - type |= CRYPTO_ALG_TESTED; ++ param->type |= CRYPTO_ALG_TESTED; +#endif - - param->type = type; - ++ + thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); + if (IS_ERR(thread)) + goto err_free_param; diff --git a/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch index 01829b2d51..64b4ca4521 100644 --- a/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch +++ b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch @@ -14,11 +14,11 @@ from backports. --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -9,7 +9,7 @@ config CRYPTO_LIB_AES - tristate + select CRYPTO_LIB_UTILS config CRYPTO_LIB_ARC4 - tristate + tristate "ARC4 cipher library" - config CRYPTO_ARCH_HAVE_LIB_BLAKE2S - bool + config CRYPTO_LIB_GF128MUL + tristate diff --git a/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch index 7c7e4c814e..726a2a0f18 100644 --- a/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch +++ b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch @@ -16,8 +16,8 @@ Signed-off-by: Rafał Miłecki mutex_unlock(&mtd_table_mutex); -- if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL)) { -+ if (of_find_property(mtd_get_of_node(mtd), "linux,rootfs", NULL) || +- if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { ++ if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs") || + (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && !strcmp(mtd->name, "rootfs") && ROOT_DEV == 0)) { if (IS_BUILTIN(CONFIG_MTD)) { pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); diff --git a/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch index b0be9dfdcb..64465fae2a 100644 --- a/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch @@ -19,11 +19,11 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1730,6 +1730,7 @@ enum netdev_priv_flags { - /* was IFF_LIVE_RENAME_OK */ +@@ -1707,6 +1707,7 @@ enum netdev_priv_flags { IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), -+ IFF_NO_IP_ALIGN = BIT_ULL(33), + IFF_SEE_ALL_HWTSTAMP_REQUESTS = BIT_ULL(33), ++ IFF_NO_IP_ALIGN = BIT_ULL(34), }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN diff --git a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index faaa40f9bd..1232c664ed 100644 --- a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -15,16 +15,7 @@ Signed-off-by: Alex Marginean --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -27,6 +27,8 @@ - #define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQR813 0x31c31cb2 -+#define PHY_ID_AQR112 0x03a1b662 -+#define PHY_ID_AQR412 0x03a1b712 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 - #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -99,6 +101,29 @@ +@@ -101,6 +101,29 @@ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000 @@ -54,7 +45,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -230,6 +255,51 @@ static int aqr_config_aneg(struct phy_de +@@ -232,6 +255,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -106,43 +97,21 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -860,6 +930,30 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - .link_change_notify = aqr107_link_change_notify, - }, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR112), -+ .name = "Aquantia AQR112", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR412), -+ .name = "Aquantia AQR412", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, - }; - - module_phy_driver(aqr_driver); -@@ -877,6 +971,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, - { } - }; - +@@ -809,7 +877,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR112), + .name = "Aquantia AQR112", + .probe = aqr107_probe, +- .config_aneg = aqr_config_aneg, ++ .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, + .handle_interrupt = aqr_handle_interrupt, + .get_tunable = aqr107_get_tunable, +@@ -827,7 +895,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR412), + .name = "Aquantia AQR412", + .probe = aqr107_probe, +- .config_aneg = aqr_config_aneg, ++ .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, + .handle_interrupt = aqr_handle_interrupt, + .get_tunable = aqr107_get_tunable, diff --git a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index d83cc48a33..bee48be007 100644 --- a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -13,17 +13,17 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -29,6 +29,8 @@ + #define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQR813 0x31c31cb2 - #define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR412 0x03a1b712 +#define PHY_ID_AQR112C 0x03a1b790 +#define PHY_ID_AQR112R 0x31c31d12 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -960,6 +962,30 @@ static struct phy_driver aqr_driver[] = - .get_strings = aqr107_get_strings, +@@ -898,6 +900,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), @@ -52,10 +52,10 @@ Signed-off-by: Daniel Golle }; module_phy_driver(aqr_driver); -@@ -979,6 +1005,8 @@ static struct mdio_device_id __maybe_unu +@@ -917,6 +943,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, { } diff --git a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch index a2bd3a3dbb..b50973f20b 100644 --- a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch +++ b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru +@@ -92,14 +92,23 @@ static void mtk_pcs_lynxi_get_state(struct struct phylink_link_state *state) { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); @@ -30,24 +30,35 @@ Signed-off-by: Daniel Golle + state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); + state->speed = SPEED_2500; + state->duplex = DUPLEX_FULL; ++ ++ return; ++ } - phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm), - FIELD_GET(SGMII_LPA, adv)); -+ return; -+ } -+ + regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv); + phylink_mii_c22_pcs_decode_state(state, bmsr, FIELD_GET(SGMII_LPA, adv)); } static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) -@@ -163,7 +172,8 @@ static int mtk_pcs_lynxi_config(struct p - if (neg_mode & PHYLINK_PCS_NEG_INBAND) - sgm_mode |= SGMII_REMOTE_FAULT_DIS; +@@ -109,7 +118,7 @@ static int mtk_pcs_lynxi_config(struct p + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + bool mode_changed = false, changed; +- unsigned int rgc3, sgm_mode, bmcr; ++ unsigned int rgc3, sgm_mode, bmcr = 0; + int advertise, link_timer; -- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED && -+ interface != PHY_INTERFACE_MODE_2500BASEX) { + advertise = phylink_mii_c22_pcs_encode_advertisement(interface, +@@ -132,9 +141,8 @@ static int mtk_pcs_lynxi_config(struct p + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { if (interface == PHY_INTERFACE_MODE_SGMII) sgm_mode |= SGMII_SPEED_DUPLEX_AN; - bmcr = BMCR_ANENABLE; +- bmcr = BMCR_ANENABLE; +- } else { +- bmcr = 0; ++ if (interface != PHY_INTERFACE_MODE_2500BASEX) ++ bmcr = BMCR_ANENABLE; + } + + if (mpcs->interface != interface) { diff --git a/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch index 48d4626ed6..9ef11623fc 100644 --- a/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch +++ b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch @@ -36,7 +36,7 @@ Signed-off-by: David Bauer + + if (ret) + return ret; -+ ++ + ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data); + + return 0; diff --git a/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch index 2724efa15e..dc582bba28 100644 --- a/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch +++ b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch @@ -30,7 +30,7 @@ Signed-off-by: David Bauer +#include #include #include - #include + #include @@ -33,6 +34,7 @@ #define PHY_MIISTAT 0x18 /* MII state */ #define PHY_IMASK 0x19 /* interrupt mask */ @@ -52,9 +52,9 @@ Signed-off-by: David Bauer +/* LED */ +#define VSPEC1_LED(x) (0x1 + x) + - /* SGMII */ - #define VSPEC1_SGMII_CTRL 0x08 - #define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */ + #define PHY_PMA_MGBT_POLARITY 0x82 + #define PHY_MDI_MDI_X_MASK GENMASK(1, 0) + #define PHY_MDI_MDI_X_NORMAL 0x3 @@ -241,6 +248,35 @@ out: return ret; } @@ -102,4 +102,4 @@ Signed-off-by: David Bauer + return gpy_led_write(phydev); } - static bool gpy_has_broken_mdint(struct phy_device *phydev) + static int gpy_probe(struct phy_device *phydev) diff --git a/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch index bb21bb39d3..8fb8aa84d5 100644 --- a/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch +++ b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch @@ -27,8 +27,8 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -409,6 +409,9 @@ static const struct sfp_quirk sfp_quirks - SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex, - sfp_fixup_ignore_tx_fault), + // FS 2.5G Base-T + SFP_QUIRK_M("FS", "SFP-2.5G-T", sfp_quirk_oem_2_5g), + // OEM SFP-GE-T is 1000Base-T module + SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault), diff --git a/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch index b60b428dc8..59acb9e57b 100644 --- a/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch @@ -6,18 +6,18 @@ Subject: [PATCH 30/36] GPIO: add named gpio exports Signed-off-by: John Crispin --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c -@@ -19,6 +19,8 @@ - #include - #include +@@ -21,6 +21,8 @@ + + #include #include +#include +#include #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1030,3 +1032,100 @@ void of_gpio_dev_init(struct gpio_chip * - else - gc->of_node = gdev->dev.of_node; +@@ -1111,3 +1113,74 @@ void of_gpiochip_remove(struct gpio_chip + { + of_node_put(dev_of_node(&chip->gpiodev->dev)); } + +#ifdef CONFIG_GPIO_SYSFS @@ -44,57 +44,31 @@ Signed-off-by: John Crispin + of_property_read_string(cnp, "gpio-export,name", &name); + + if (!name) -+ max_gpio = of_gpio_count(cnp); ++ max_gpio = of_gpio_named_count(cnp, "gpios"); + + for (i = 0; i < max_gpio; i++) { + struct gpio_desc *desc; + unsigned flags = 0; + enum of_gpio_flags of_flags; + -+ gpio = of_get_gpio_flags(cnp, i, &of_flags); -+ if (!gpio_is_valid(gpio)) -+ return gpio; ++ desc = of_get_named_gpiod_flags(cnp, "gpios", i, &of_flags); ++ if (IS_ERR(desc)) ++ return PTR_ERR(desc); ++ gpio = desc_to_gpio(desc); + + if (of_flags & OF_GPIO_ACTIVE_LOW) + flags |= GPIOF_ACTIVE_LOW; + -+ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) { -+ if (of_flags & OF_GPIO_SINGLE_ENDED) { -+ /* -+ * As gpiod_direction_output_raw() is used, we -+ * need to emulate open drain or open source here. -+ */ -+ if (of_flags & OF_GPIO_OPEN_DRAIN) { -+ flags |= GPIOF_OPEN_DRAIN; -+ flags |= val ? GPIOF_IN : GPIOF_OUT_INIT_LOW; -+ } else { -+ flags |= GPIOF_OPEN_SOURCE; -+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_IN; -+ } -+ } else { -+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; -+ } -+ } else { ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else + flags |= GPIOF_IN; -+ } + + if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) + continue; + -+ /* -+ * When emulating open-source or open-drain functionalities by not -+ * actively driving the line (setting mode to input) we still need to -+ * set the IS_OUT flag or otherwise we won't be able to set the line -+ * value anymore. -+ */ -+ if ((flags & GPIOF_IN) && -+ ((flags & GPIOF_OPEN_DRAIN) || (flags & GPIOF_OPEN_SOURCE))) { -+ desc = gpio_to_desc(gpio); -+ set_bit(FLAG_IS_OUT, &desc->flags); -+ } -+ + dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); -+ gpio_export_with_name(gpio, dmc, name); ++ gpio_export_with_name(gpio_to_desc(gpio), dmc, name); + nb++; + } + } @@ -116,36 +90,24 @@ Signed-off-by: John Crispin +module_platform_driver(gpio_export_driver); + +#endif ---- a/include/asm-generic/gpio.h -+++ b/include/asm-generic/gpio.h -@@ -125,6 +125,12 @@ static inline int gpio_export(unsigned g - return gpiod_export(gpio_to_desc(gpio), direction_may_change); - } - -+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); -+static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) -+{ -+ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); -+} -+ - static inline int gpio_export_link(struct device *dev, const char *name, - unsigned gpio) - { --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h -@@ -715,6 +715,7 @@ static inline struct gpio_desc *acpi_get +@@ -644,7 +644,10 @@ static inline struct gpio_desc *acpi_get #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) -+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); int gpiod_export(struct gpio_desc *desc, bool direction_may_change); ++int gpio_export_with_name(struct gpio_desc *desc, bool direction_may_change, ++ const char *name); int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); -@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de + void gpiod_unexport(struct gpio_desc *desc); +@@ -653,12 +656,26 @@ void gpiod_unexport(struct gpio_desc *de - #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + #include -+static inline int _gpiod_export(struct gpio_desc *desc, ++static inline int __gpiod_export(struct gpio_desc *desc, + bool direction_may_change, + const char *name) +{ @@ -154,10 +116,23 @@ Signed-off-by: John Crispin + static inline int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + { + return -ENOSYS; + } + ++static inline int gpio_export_with_name(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc) { --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c -@@ -547,7 +547,7 @@ static struct class gpio_class = { +@@ -557,7 +557,7 @@ static struct class gpio_class = { * * Returns zero on success, else an error. */ @@ -166,7 +141,7 @@ Signed-off-by: John Crispin { struct gpio_chip *chip; struct gpio_device *gdev; -@@ -609,6 +609,8 @@ int gpiod_export(struct gpio_desc *desc, +@@ -619,6 +619,8 @@ int gpiod_export(struct gpio_desc *desc, offset = gpio_chip_hwgpio(desc); if (chip->names && chip->names[offset]) ioname = chip->names[offset]; @@ -175,7 +150,7 @@ Signed-off-by: John Crispin dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, -@@ -630,6 +632,12 @@ err_unlock: +@@ -640,8 +642,21 @@ int gpiod_export(struct gpio_desc *desc, gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -187,4 +162,13 @@ Signed-off-by: John Crispin +} EXPORT_SYMBOL_GPL(gpiod_export); ++int gpio_export_with_name(struct gpio_desc *desc, bool direction_may_change, ++ const char *name) ++{ ++ return __gpiod_export(desc, direction_may_change, name); ++} ++EXPORT_SYMBOL_GPL(gpio_export_with_name); ++ static int match_export(struct device *dev, const void *desc) + { + struct gpiod_data *data = dev_get_drvdata(dev); diff --git a/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch index ec71f9af4b..92b35efa55 100644 --- a/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch @@ -28,13 +28,14 @@ Signed-off-by: Felix Fietkau help --- a/net/core/Makefile +++ b/net/core/Makefile -@@ -11,11 +11,12 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core. +@@ -11,12 +11,13 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core. obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ - sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ -+ dev_ioctl.o tso.o sock_reuseport.o \ - fib_notifier.o xdp.o flow_offload.o gro.o ++ dev_ioctl.o tso.o sock_reuseport.o \ + fib_notifier.o xdp.o flow_offload.o gro.o \ + netdev-genl.o netdev-genl-gen.o gso.o obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o @@ -44,15 +45,15 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_PROC_FS) += net-procfs.o --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -115,6 +115,7 @@ - #include - #include - #include +@@ -117,6 +117,7 @@ + #include + #include + #include +#include #include -@@ -146,6 +147,7 @@ +@@ -149,6 +150,7 @@ static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -60,26 +61,29 @@ Signed-off-by: Felix Fietkau static void sock_def_write_space_wfree(struct sock *sk); static void sock_def_write_space(struct sock *sk); -@@ -585,6 +587,18 @@ discard_and_relse: +@@ -588,6 +590,21 @@ int __sk_receive_skb(struct sock *sk, str } EXPORT_SYMBOL(__sk_receive_skb); +u64 __sock_gen_cookie(struct sock *sk) +{ -+ while (1) { -+ u64 res = atomic64_read(&sk->sk_cookie); ++ u64 res = atomic64_read(&sk->sk_cookie); + -+ if (res) -+ return res; -+ res = gen_cookie_next(&sock_cookie); -+ atomic64_cmpxchg(&sk->sk_cookie, 0, res); ++ if (!res) { ++ u64 new = gen_cookie_next(&sock_cookie); ++ ++ atomic64_cmpxchg(&sk->sk_cookie, res, new); ++ ++ /* Another thread might have changed sk_cookie before us. */ ++ res = atomic64_read(&sk->sk_cookie); + } ++ return res; +} + INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2188,9 +2202,11 @@ static void __sk_free(struct sock *sk) +@@ -2238,9 +2255,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); @@ -101,7 +105,7 @@ Signed-off-by: Felix Fietkau #include #include -@@ -21,20 +20,6 @@ static int (*inet_rcv_compat)(struct sk_ +@@ -21,23 +20,6 @@ static int (*inet_rcv_compat)(struct sk_ static DEFINE_MUTEX(sock_diag_table_mutex); static struct workqueue_struct *broadcast_wq; @@ -109,14 +113,17 @@ Signed-off-by: Felix Fietkau - -u64 __sock_gen_cookie(struct sock *sk) -{ -- while (1) { -- u64 res = atomic64_read(&sk->sk_cookie); +- u64 res = atomic64_read(&sk->sk_cookie); - -- if (res) -- return res; -- res = gen_cookie_next(&sock_cookie); -- atomic64_cmpxchg(&sk->sk_cookie, 0, res); +- if (!res) { +- u64 new = gen_cookie_next(&sock_cookie); +- +- atomic64_cmpxchg(&sk->sk_cookie, res, new); +- +- /* Another thread might have changed sk_cookie before us. */ +- res = atomic64_read(&sk->sk_cookie); - } +- return res; -} - int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie) From 6bac820c0f6aa804eeef022875706ada70f1360f Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 8 Mar 2024 22:03:01 +0800 Subject: [PATCH 046/108] generic: 6.6: refresh backport patches Refresh backport patches with make target/linux/refresh. Signed-off-by: Weijie Gao --- ...antia-move-MMD_VEND-define-to-header.patch | 2 +- ...y-aquantia-add-firmware-load-support.patch | 2 +- ...r-type-u8-in-phy_package_shared-stru.patch | 2 +- ...HY-package-API-to-support-multiple-g.patch | 24 ++++---- ...ure-__phy_write-read_mmd-to-helper-a.patch | 6 +- ...pport-for-PHY-package-MMD-read-write.patch | 4 +- ...ort-for-scanning-PHY-in-PHY-packages.patch | 4 +- ...-add-devm-of_phy_package_join-helper.patch | 12 ++-- ...whether-link-has-changed-in-c37_read.patch | 8 +-- ...-add-support-for-clock-frequency-pro.patch | 6 +- ..._eth_soc-improve-keeping-track-of-of.patch | 18 +++--- ...iatek-fix-ppe-flow-accounting-for-L2.patch | 20 +++---- ..._wed-do-not-assume-offload-callbacks.patch | 4 +- ..._wed-introduce-versioning-utility-ro.patch | 40 ++++++------- ..._wed-do-not-configure-rx-offload-if-.patch | 20 +++---- ..._wed-rename-mtk_rxbm_desc-in-mtk_wed.patch | 6 +- ..._wed-introduce-mtk_wed_buf-structure.patch | 8 +-- ...k_wed-add-mtk_wed_soc_data-structure.patch | 24 ++++---- ..._wed-introduce-WED-support-for-MT798.patch | 60 +++++++++---------- ..._wed-refactor-mtk_wed_check_wfdma_rx.patch | 8 +-- ..._wed-introduce-partial-AMSDU-offload.patch | 26 ++++---- ..._wed-introduce-hw_rro-support-for-MT.patch | 30 +++++----- ..._wed-debugfs-add-WED-3.0-debugfs-ent.patch | 2 +- ...et-mtk_wed-add-wed-3.0-reset-support.patch | 28 ++++----- ...antia-add-AQR111-and-AQR111B0-PHY-ID.patch | 4 +- ...9-net-phy-aquantia-add-AQR113-PHY-ID.patch | 6 +- ...9-net-phy-aquantia-add-AQR813-PHY-ID.patch | 6 +- ...t-introduce-napi_is_scheduled-helper.patch | 8 +-- ...et-stmmac-improve-TX-timer-arm-logic.patch | 2 +- ...ac-increase-TX-coalesce-timer-to-5ms.patch | 2 +- ...795-v6.7-16-r8152-use-napi_gro_frags.patch | 4 +- ...a-Support-HW-controlled-mode-via-pri.patch | 4 +- ...it-config-option-to-read-old-syntax-.patch | 14 ++--- ...4-Revert-nvmem-add-new-config-option.patch | 4 +- ...-device-Export-of_device_make_bus_id.patch | 8 +-- ...mem_layout_get_container-in-another-.patch | 2 +- ...03-nvmem-Simplify-the-add_cells-hook.patch | 2 +- ...vmem-Move-and-rename-fixup_cell_info.patch | 10 ++-- ...rk-layouts-to-become-regular-devices.patch | 22 +++---- ...vmem-core-Expose-cells-through-sysfs.patch | 10 ++-- ...factor-.add_cells-callback-arguments.patch | 2 +- ...mem-drop-nvmem_layout_get_match_data.patch | 2 +- ...nvmem-core-add-nvmem_dev_size-helper.patch | 2 +- ...t-phy-amd-Support-the-Altima-AMI101L.patch | 2 +- ...igger-netdev-Extend-speeds-up-to-10G.patch | 14 ++--- ...-support-for-PHY-LEDs-polarity-modes.patch | 8 +-- ...8-net-ethtool-implement-ethtool_puts.patch | 4 +- 47 files changed, 253 insertions(+), 253 deletions(-) diff --git a/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch b/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch index 2b94522723..66fbf2444d 100644 --- a/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch +++ b/target/linux/generic/backport-6.6/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch @@ -119,7 +119,7 @@ Signed-off-by: David S. Miller static umode_t aqr_hwmon_is_visible(const void *data, --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -89,61 +89,6 @@ +@@ -91,61 +91,6 @@ #define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a #define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b diff --git a/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch b/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch index aa52b3baa6..1ae5966df6 100644 --- a/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch +++ b/target/linux/generic/backport-6.6/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch @@ -484,7 +484,7 @@ Signed-off-by: David S. Miller +} --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -656,11 +656,17 @@ static int aqr107_resume(struct phy_devi +@@ -658,11 +658,17 @@ static int aqr107_resume(struct phy_devi static int aqr107_probe(struct phy_device *phydev) { diff --git a/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch b/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch index 6decc3430b..456259281f 100644 --- a/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch +++ b/target/linux/generic/backport-6.6/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch @@ -17,7 +17,7 @@ Signed-off-by: David S. Miller --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -330,7 +330,7 @@ struct mdio_bus_stats { +@@ -338,7 +338,7 @@ struct mdio_bus_stats { * phy_package_leave(). */ struct phy_package_shared { diff --git a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch index 6e5ac8c63a..b95f15a581 100644 --- a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch +++ b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch @@ -87,7 +87,7 @@ Signed-off-by: David S. Miller phy_unlock_mdio_bus(phydev); --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h -@@ -414,6 +414,11 @@ struct vsc8531_private { +@@ -416,6 +416,11 @@ struct vsc8531_private { * gpio_lock: used for PHC operations. Common for all PHYs as the load/save GPIO * is shared. */ @@ -101,7 +101,7 @@ Signed-off-by: David S. Miller }; --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c -@@ -700,7 +700,7 @@ int phy_base_write(struct phy_device *ph +@@ -711,7 +711,7 @@ int phy_base_write(struct phy_device *ph dump_stack(); } @@ -110,7 +110,7 @@ Signed-off-by: David S. Miller } /* phydev->bus->mdio_lock should be locked when using this function */ -@@ -711,7 +711,7 @@ int phy_base_read(struct phy_device *phy +@@ -722,7 +722,7 @@ int phy_base_read(struct phy_device *phy dump_stack(); } @@ -121,7 +121,7 @@ Signed-off-by: David S. Miller u32 vsc85xx_csr_read(struct phy_device *phydev, --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1602,20 +1602,22 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 +@@ -1650,20 +1650,22 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 /** * phy_package_join - join a common PHY group * @phydev: target phy_device struct @@ -151,7 +151,7 @@ Signed-off-by: David S. Miller * * This will set the shared pointer of the phydev to the shared storage. * If this is the first call for a this cookie the shared storage will be -@@ -1625,17 +1627,17 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 +@@ -1673,17 +1675,17 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() * with the same cookie but a different priv_size is an error. */ @@ -172,7 +172,7 @@ Signed-off-by: David S. Miller if (!shared) { ret = -ENOMEM; shared = kzalloc(sizeof(*shared), GFP_KERNEL); -@@ -1647,9 +1649,9 @@ int phy_package_join(struct phy_device * +@@ -1695,9 +1697,9 @@ int phy_package_join(struct phy_device * goto err_free; shared->priv_size = priv_size; } @@ -184,7 +184,7 @@ Signed-off-by: David S. Miller } else { ret = -EINVAL; if (priv_size && priv_size != shared->priv_size) -@@ -1687,7 +1689,7 @@ void phy_package_leave(struct phy_device +@@ -1735,7 +1737,7 @@ void phy_package_leave(struct phy_device return; if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { @@ -193,7 +193,7 @@ Signed-off-by: David S. Miller mutex_unlock(&bus->shared_lock); kfree(shared->priv); kfree(shared); -@@ -1706,7 +1708,8 @@ static void devm_phy_package_leave(struc +@@ -1754,7 +1756,8 @@ static void devm_phy_package_leave(struc * devm_phy_package_join - resource managed phy_package_join() * @dev: device that is registering this PHY package * @phydev: target phy_device struct @@ -203,7 +203,7 @@ Signed-off-by: David S. Miller * @priv_size: if non-zero allocate this amount of bytes for private data * * Managed phy_package_join(). Shared storage fetched by this function, -@@ -1714,7 +1717,7 @@ static void devm_phy_package_leave(struc +@@ -1762,7 +1765,7 @@ static void devm_phy_package_leave(struc * phy_package_join() for more information. */ int devm_phy_package_join(struct device *dev, struct phy_device *phydev, @@ -212,7 +212,7 @@ Signed-off-by: David S. Miller { struct phy_device **ptr; int ret; -@@ -1724,7 +1727,7 @@ int devm_phy_package_join(struct device +@@ -1772,7 +1775,7 @@ int devm_phy_package_join(struct device if (!ptr) return -ENOMEM; @@ -223,7 +223,7 @@ Signed-off-by: David S. Miller *ptr = phydev; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -319,7 +319,8 @@ struct mdio_bus_stats { +@@ -327,7 +327,8 @@ struct mdio_bus_stats { /** * struct phy_package_shared - Shared information in PHY packages @@ -233,7 +233,7 @@ Signed-off-by: David S. Miller * @refcnt: Number of PHYs connected to this shared data * @flags: Initialization of PHY package * @priv_size: Size of the shared private data @priv -@@ -330,7 +331,7 @@ struct mdio_bus_stats { +@@ -338,7 +339,7 @@ struct mdio_bus_stats { * phy_package_leave(). */ struct phy_package_shared { diff --git a/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch b/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch index 4a17d46453..f0ca35a1f0 100644 --- a/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch +++ b/target/linux/generic/backport-6.6/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -528,6 +528,28 @@ static void mmd_phy_indirect(struct mii_ +@@ -540,6 +540,28 @@ static void mmd_phy_indirect(struct mii_ devad | MII_MMD_CTRL_NOINCR); } @@ -49,7 +49,7 @@ Signed-off-by: David S. Miller /** * __phy_read_mmd - Convenience function for reading a register * from an MMD on a given PHY. -@@ -539,26 +561,14 @@ static void mmd_phy_indirect(struct mii_ +@@ -551,26 +573,14 @@ static void mmd_phy_indirect(struct mii_ */ int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) { @@ -81,7 +81,7 @@ Signed-off-by: David S. Miller } EXPORT_SYMBOL(__phy_read_mmd); -@@ -595,28 +605,14 @@ EXPORT_SYMBOL(phy_read_mmd); +@@ -607,28 +617,14 @@ EXPORT_SYMBOL(phy_read_mmd); */ int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) { diff --git a/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch index a628a37929..c20d2ec0c0 100644 --- a/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch +++ b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -639,6 +639,146 @@ int phy_write_mmd(struct phy_device *phy +@@ -651,6 +651,146 @@ int phy_write_mmd(struct phy_device *phy EXPORT_SYMBOL(phy_write_mmd); /** @@ -171,7 +171,7 @@ Signed-off-by: David S. Miller * @regnum: register number to modify --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1840,6 +1840,22 @@ static inline int __phy_package_write(st +@@ -2057,6 +2057,22 @@ static inline int __phy_package_write(st return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); } diff --git a/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch index 50a454b2c9..81f2d1d8e6 100644 --- a/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch +++ b/target/linux/generic/backport-6.6/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch @@ -143,7 +143,7 @@ Signed-off-by: David S. Miller } --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c -@@ -448,19 +448,34 @@ EXPORT_SYMBOL(of_mdio_find_bus); +@@ -455,19 +455,34 @@ EXPORT_SYMBOL(of_mdio_find_bus); * found, set the of_node pointer for the mdio device. This allows * auto-probed phy devices to be supplied with information passed in * via DT. @@ -185,7 +185,7 @@ Signed-off-by: David S. Miller addr = of_mdio_parse_addr(dev, child); if (addr < 0) continue; -@@ -470,9 +485,22 @@ static void of_mdiobus_link_mdiodev(stru +@@ -477,9 +492,22 @@ static void of_mdiobus_link_mdiodev(stru /* The refcount on "child" is passed to the mdio * device. Do _not_ use of_node_put(child) here. */ diff --git a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch index 00bbd3b80b..f3e814b1a0 100644 --- a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch +++ b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch @@ -27,7 +27,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1648,6 +1648,7 @@ int phy_package_join(struct phy_device * +@@ -1698,6 +1698,7 @@ int phy_package_join(struct phy_device * shared->priv_size = priv_size; } shared->base_addr = base_addr; @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller refcount_set(&shared->refcnt, 1); bus->shared[base_addr] = shared; } else { -@@ -1671,6 +1672,63 @@ err_unlock: +@@ -1721,6 +1722,63 @@ err_unlock: EXPORT_SYMBOL_GPL(phy_package_join); /** @@ -99,7 +99,7 @@ Signed-off-by: David S. Miller * phy_package_leave - leave a common PHY group * @phydev: target phy_device struct * -@@ -1686,6 +1744,10 @@ void phy_package_leave(struct phy_device +@@ -1736,6 +1794,10 @@ void phy_package_leave(struct phy_device if (!shared) return; @@ -110,7 +110,7 @@ Signed-off-by: David S. Miller if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { bus->shared[shared->base_addr] = NULL; mutex_unlock(&bus->shared_lock); -@@ -1739,6 +1801,40 @@ int devm_phy_package_join(struct device +@@ -1789,6 +1851,40 @@ int devm_phy_package_join(struct device EXPORT_SYMBOL_GPL(devm_phy_package_join); /** @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller * --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -321,6 +321,7 @@ struct mdio_bus_stats { +@@ -329,6 +329,7 @@ struct mdio_bus_stats { * struct phy_package_shared - Shared information in PHY packages * @base_addr: Base PHY address of PHY package used to combine PHYs * in one package and for offset calculation of phy_package_read/write @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @refcnt: Number of PHYs connected to this shared data * @flags: Initialization of PHY package * @priv_size: Size of the shared private data @priv -@@ -332,6 +333,8 @@ struct mdio_bus_stats { +@@ -340,6 +341,8 @@ struct mdio_bus_stats { */ struct phy_package_shared { u8 base_addr; diff --git a/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch index acaa4a644e..0441c8f60f 100644 --- a/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch +++ b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch @@ -26,7 +26,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c -@@ -609,10 +609,11 @@ static int bcm54616s_config_aneg(struct +@@ -665,10 +665,11 @@ static int bcm54616s_config_aneg(struct static int bcm54616s_read_status(struct phy_device *phydev) { struct bcm54616s_phy_priv *priv = phydev->priv; @@ -41,7 +41,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2549,12 +2549,15 @@ EXPORT_SYMBOL(genphy_read_status); +@@ -2607,12 +2607,15 @@ EXPORT_SYMBOL(genphy_read_status); /** * genphy_c37_read_status - check the link status and update current link state * @phydev: target phy_device struct @@ -58,7 +58,7 @@ Signed-off-by: David S. Miller { int lpa, err, old_link = phydev->link; -@@ -2564,9 +2567,13 @@ int genphy_c37_read_status(struct phy_de +@@ -2622,9 +2625,13 @@ int genphy_c37_read_status(struct phy_de return err; /* why bother the PHY if nothing can have changed */ @@ -89,7 +89,7 @@ Signed-off-by: David S. Miller } --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1688,7 +1688,7 @@ int genphy_write_mmd_unsupported(struct +@@ -1849,7 +1849,7 @@ int genphy_write_mmd_unsupported(struct /* Clause 37 */ int genphy_c37_config_aneg(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch b/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch index e6a240dbda..6749d7b0d9 100644 --- a/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch +++ b/target/linux/generic/backport-6.6/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch @@ -90,7 +90,7 @@ Signed-off-by: David S. Miller }; static int ipq4019_mdio_wait_busy(struct mii_bus *bus) -@@ -179,6 +191,38 @@ static int ipq4019_mdio_write(struct mii +@@ -203,6 +215,38 @@ static int ipq4019_mdio_write_c22(struct return 0; } @@ -129,7 +129,7 @@ Signed-off-by: David S. Miller static int ipq_mdio_reset(struct mii_bus *bus) { struct ipq4019_mdio_data *priv = bus->priv; -@@ -201,10 +245,58 @@ static int ipq_mdio_reset(struct mii_bus +@@ -225,10 +269,58 @@ static int ipq_mdio_reset(struct mii_bus return ret; ret = clk_prepare_enable(priv->mdio_clk); @@ -191,7 +191,7 @@ Signed-off-by: David S. Miller } static int ipq4019_mdio_probe(struct platform_device *pdev) -@@ -228,6 +320,11 @@ static int ipq4019_mdio_probe(struct pla +@@ -252,6 +344,11 @@ static int ipq4019_mdio_probe(struct pla if (IS_ERR(priv->mdio_clk)) return PTR_ERR(priv->mdio_clk); diff --git a/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch b/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch index 8b8a8e11c7..2689712228 100644 --- a/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch +++ b/target/linux/generic/backport-6.6/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -476,42 +476,43 @@ int mtk_foe_entry_set_queue(struct mtk_e +@@ -477,42 +477,43 @@ int mtk_foe_entry_set_queue(struct mtk_e return 0; } @@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, entry->hash); hwe->ib1 &= ~MTK_FOE_IB1_STATE; -@@ -531,7 +532,8 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp +@@ -533,7 +534,8 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW) return; @@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau kfree(entry); } -@@ -547,66 +549,55 @@ static int __mtk_foe_entry_idle_time(str +@@ -549,66 +551,55 @@ static int __mtk_foe_entry_idle_time(str return now - timestamp; } @@ -181,7 +181,7 @@ Signed-off-by: Felix Fietkau } static void -@@ -649,7 +640,8 @@ __mtk_foe_entry_commit(struct mtk_ppe *p +@@ -651,7 +642,8 @@ __mtk_foe_entry_commit(struct mtk_ppe *p void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) { spin_lock_bh(&ppe_lock); @@ -191,7 +191,7 @@ Signed-off-by: Felix Fietkau spin_unlock_bh(&ppe_lock); } -@@ -696,8 +688,8 @@ mtk_foe_entry_commit_subflow(struct mtk_ +@@ -698,8 +690,8 @@ mtk_foe_entry_commit_subflow(struct mtk_ { const struct mtk_soc_data *soc = ppe->eth->soc; struct mtk_flow_entry *flow_info; @@ -201,7 +201,7 @@ Signed-off-by: Felix Fietkau u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP; int type; -@@ -705,30 +697,30 @@ mtk_foe_entry_commit_subflow(struct mtk_ +@@ -707,30 +699,30 @@ mtk_foe_entry_commit_subflow(struct mtk_ if (!flow_info) return; @@ -242,7 +242,7 @@ Signed-off-by: Felix Fietkau } void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) -@@ -738,9 +730,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -740,9 +732,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, hash); struct mtk_flow_entry *entry; struct mtk_foe_bridge key = {}; @@ -254,7 +254,7 @@ Signed-off-by: Felix Fietkau u8 *tag; spin_lock_bh(&ppe_lock); -@@ -748,20 +742,14 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -750,20 +744,14 @@ void __mtk_ppe_check_skb(struct mtk_ppe if (FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == MTK_FOE_STATE_BIND) goto out; @@ -281,7 +281,7 @@ Signed-off-by: Felix Fietkau continue; } -@@ -810,9 +798,17 @@ out: +@@ -814,9 +802,17 @@ out: int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) { diff --git a/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch index e5f0c2f54d..a93f80ac79 100644 --- a/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch +++ b/target/linux/generic/backport-6.6/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau } static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) -@@ -522,14 +536,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp +@@ -520,14 +534,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); dma_wmb(); mtk_ppe_cache_clear(ppe); @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau } entry->hash = 0xffff; -@@ -554,11 +560,14 @@ static int __mtk_foe_entry_idle_time(str +@@ -552,11 +558,14 @@ static int __mtk_foe_entry_idle_time(str } static bool @@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau int len; if (hash == 0xffff) -@@ -569,18 +578,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp +@@ -567,18 +576,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp memcpy(&foe, hwe, len); if (!mtk_flow_entry_match(ppe->eth, entry, &foe, len) || @@ -156,7 +156,7 @@ Signed-off-by: Felix Fietkau struct mtk_flow_entry *cur; struct hlist_node *tmp; int idle; -@@ -589,7 +615,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -587,7 +613,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_list) { int cur_idle; @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau __mtk_foe_entry_clear(ppe, entry, false); continue; } -@@ -604,10 +632,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -602,10 +630,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe } } @@ -197,7 +197,7 @@ Signed-off-by: Felix Fietkau struct mtk_eth *eth = ppe->eth; u16 timestamp = mtk_eth_timestamp(eth); struct mtk_foe_entry *hwe; -@@ -638,6 +685,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p +@@ -636,6 +683,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p dma_wmb(); @@ -210,7 +210,7 @@ Signed-off-by: Felix Fietkau mtk_ppe_cache_clear(ppe); } -@@ -802,21 +855,6 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -800,21 +853,6 @@ out: spin_unlock_bh(&ppe_lock); } @@ -232,7 +232,7 @@ Signed-off-by: Felix Fietkau int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) { if (!ppe) -@@ -844,32 +882,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe +@@ -842,32 +880,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe return mtk_ppe_wait_busy(ppe); } @@ -284,7 +284,7 @@ Signed-off-by: Felix Fietkau void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); -@@ -397,9 +400,8 @@ int mtk_foe_entry_set_queue(struct mtk_e +@@ -396,9 +399,8 @@ int mtk_foe_entry_set_queue(struct mtk_e unsigned int queue); int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); @@ -309,7 +309,7 @@ Signed-off-by: Felix Fietkau seq_printf(m, "%05x %s %7s", i, --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -505,24 +505,21 @@ static int +@@ -501,24 +501,21 @@ static int mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) { struct mtk_flow_entry *entry; diff --git a/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch b/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch index cd7fb92e20..d6ef40cd5b 100644 --- a/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch +++ b/target/linux/generic/backport-6.6/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch @@ -14,7 +14,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1712,19 +1712,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_devi +@@ -1713,19 +1713,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_devi int mtk_wed_flow_add(int index) { struct mtk_wed_hw *hw = hw_list[index]; @@ -44,7 +44,7 @@ Signed-off-by: David S. Miller goto out; } -@@ -1743,14 +1744,15 @@ void mtk_wed_flow_remove(int index) +@@ -1744,14 +1745,15 @@ void mtk_wed_flow_remove(int index) { struct mtk_wed_hw *hw = hw_list[index]; diff --git a/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch b/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch index 2948188650..af4600a986 100644 --- a/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch +++ b/target/linux/generic/backport-6.6/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch @@ -15,7 +15,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -277,7 +277,7 @@ mtk_wed_assign(struct mtk_wed_device *de +@@ -278,7 +278,7 @@ mtk_wed_assign(struct mtk_wed_device *de if (!hw->wed_dev) goto out; @@ -24,7 +24,7 @@ Signed-off-by: Paolo Abeni return NULL; /* MT7986 WED devices do not have any pcie slot restrictions */ -@@ -358,7 +358,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d +@@ -359,7 +359,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d desc->buf0 = cpu_to_le32(buf_phys); desc->buf1 = cpu_to_le32(buf_phys + txd_size); @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, MTK_WED_BUF_SIZE - txd_size) | -@@ -497,7 +497,7 @@ mtk_wed_set_ext_int(struct mtk_wed_devic +@@ -498,7 +498,7 @@ mtk_wed_set_ext_int(struct mtk_wed_devic { u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; @@ -42,7 +42,7 @@ Signed-off-by: Paolo Abeni mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; else mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | -@@ -576,7 +576,7 @@ mtk_wed_dma_disable(struct mtk_wed_devic +@@ -577,7 +577,7 @@ mtk_wed_dma_disable(struct mtk_wed_devic MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); @@ -51,7 +51,7 @@ Signed-off-by: Paolo Abeni regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); -@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) +@@ -606,7 +606,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni return; wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); -@@ -624,7 +624,7 @@ mtk_wed_deinit(struct mtk_wed_device *de +@@ -625,7 +625,7 @@ mtk_wed_deinit(struct mtk_wed_device *de MTK_WED_CTRL_WED_TX_BM_EN | MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); @@ -69,7 +69,7 @@ Signed-off-by: Paolo Abeni return; wed_clr(dev, MTK_WED_CTRL, -@@ -730,7 +730,7 @@ mtk_wed_bus_init(struct mtk_wed_device * +@@ -731,7 +731,7 @@ mtk_wed_bus_init(struct mtk_wed_device * static void mtk_wed_set_wpdma(struct mtk_wed_device *dev) { @@ -78,7 +78,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); } else { mtk_wed_bus_init(dev); -@@ -761,7 +761,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev +@@ -762,7 +762,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); @@ -87,7 +87,7 @@ Signed-off-by: Paolo Abeni u32 offset = dev->hw->index ? 0x04000400 : 0; wdma_set(dev, MTK_WDMA_GLO_CFG, -@@ -934,7 +934,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -935,7 +935,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); @@ -96,7 +96,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_TX_BM_TKID, FIELD_PREP(MTK_WED_TX_BM_TKID_START, dev->wlan.token_start) | -@@ -967,7 +967,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -968,7 +968,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); @@ -105,7 +105,7 @@ Signed-off-by: Paolo Abeni wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN | MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); -@@ -1217,7 +1217,7 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1218,7 +1218,7 @@ mtk_wed_reset_dma(struct mtk_wed_device } dev->init_done = false; @@ -114,7 +114,7 @@ Signed-off-by: Paolo Abeni return; if (!busy) { -@@ -1343,7 +1343,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1344,7 +1344,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev MTK_WED_CTRL_WED_TX_BM_EN | MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); @@ -123,7 +123,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, MTK_WED_PCIE_INT_TRIGGER_STATUS); -@@ -1416,7 +1416,7 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1417,7 +1417,7 @@ mtk_wed_dma_enable(struct mtk_wed_device MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); @@ -132,7 +132,7 @@ Signed-off-by: Paolo Abeni wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); } else { -@@ -1465,7 +1465,7 @@ mtk_wed_start(struct mtk_wed_device *dev +@@ -1466,7 +1466,7 @@ mtk_wed_start(struct mtk_wed_device *dev mtk_wed_set_ext_int(dev, true); @@ -141,7 +141,7 @@ Signed-off-by: Paolo Abeni u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN | FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index); -@@ -1550,7 +1550,7 @@ mtk_wed_attach(struct mtk_wed_device *de +@@ -1551,7 +1551,7 @@ mtk_wed_attach(struct mtk_wed_device *de } mtk_wed_hw_init_early(dev); @@ -150,7 +150,7 @@ Signed-off-by: Paolo Abeni regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, BIT(hw->index), 0); } else { -@@ -1618,7 +1618,7 @@ static int +@@ -1619,7 +1619,7 @@ static int mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) { struct mtk_wed_ring *ring = &dev->txfree_ring; @@ -159,7 +159,7 @@ Signed-off-by: Paolo Abeni /* * For txfree event handling, the same DMA ring is shared between WED -@@ -1676,7 +1676,7 @@ mtk_wed_irq_get(struct mtk_wed_device *d +@@ -1677,7 +1677,7 @@ mtk_wed_irq_get(struct mtk_wed_device *d { u32 val, ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; @@ -168,7 +168,7 @@ Signed-off-by: Paolo Abeni ext_mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; else ext_mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | -@@ -1843,7 +1843,7 @@ mtk_wed_setup_tc(struct mtk_wed_device * +@@ -1844,7 +1844,7 @@ mtk_wed_setup_tc(struct mtk_wed_device * { struct mtk_wed_hw *hw = wed->hw; @@ -177,7 +177,7 @@ Signed-off-by: Paolo Abeni return -EOPNOTSUPP; switch (type) { -@@ -1917,9 +1917,9 @@ void mtk_wed_add_hw(struct device_node * +@@ -1918,9 +1918,9 @@ void mtk_wed_add_hw(struct device_node * hw->wdma = wdma; hw->index = index; hw->irq = irq; @@ -210,7 +210,7 @@ Signed-off-by: Paolo Abeni { --- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c -@@ -263,7 +263,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w +@@ -261,7 +261,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); diff --git a/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch b/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch index bc34aa33a9..d5bacde325 100644 --- a/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch +++ b/target/linux/generic/backport-6.6/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch @@ -15,7 +15,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) +@@ -606,7 +606,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); @@ -24,7 +24,7 @@ Signed-off-by: Paolo Abeni return; wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); -@@ -732,16 +732,21 @@ mtk_wed_set_wpdma(struct mtk_wed_device +@@ -733,16 +733,21 @@ mtk_wed_set_wpdma(struct mtk_wed_device { if (mtk_wed_is_v1(dev->hw)) { wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); @@ -55,7 +55,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -973,15 +978,17 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -974,15 +979,17 @@ mtk_wed_hw_init(struct mtk_wed_device *d MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); } else { wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); @@ -82,7 +82,7 @@ Signed-off-by: Paolo Abeni } wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); -@@ -1353,8 +1360,6 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1354,8 +1361,6 @@ mtk_wed_configure_irq(struct mtk_wed_dev wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); } else { @@ -91,7 +91,7 @@ Signed-off-by: Paolo Abeni /* initail tx interrupt trigger */ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | -@@ -1373,15 +1378,20 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1374,15 +1379,20 @@ mtk_wed_configure_irq(struct mtk_wed_dev FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, dev->wlan.txfree_tbit)); @@ -121,7 +121,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); wed_set(dev, MTK_WED_WDMA_INT_CTRL, -@@ -1400,6 +1410,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1401,6 +1411,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev static void mtk_wed_dma_enable(struct mtk_wed_device *dev) { @@ -130,7 +130,7 @@ Signed-off-by: Paolo Abeni wed_set(dev, MTK_WED_WPDMA_INT_CTRL, MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); wed_set(dev, MTK_WED_GLO_CFG, -@@ -1419,33 +1431,33 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1420,33 +1432,33 @@ mtk_wed_dma_enable(struct mtk_wed_device if (mtk_wed_is_v1(dev->hw)) { wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); @@ -186,7 +186,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -1472,7 +1484,7 @@ mtk_wed_start(struct mtk_wed_device *dev +@@ -1473,7 +1485,7 @@ mtk_wed_start(struct mtk_wed_device *dev val |= BIT(0) | (BIT(1) * !!dev->hw->index); regmap_write(dev->hw->mirror, dev->hw->index * 4, val); @@ -195,7 +195,7 @@ Signed-off-by: Paolo Abeni /* driver set mid ready and only once */ wed_w32(dev, MTK_WED_EXT_INT_MASK1, MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); -@@ -1484,7 +1496,6 @@ mtk_wed_start(struct mtk_wed_device *dev +@@ -1485,7 +1497,6 @@ mtk_wed_start(struct mtk_wed_device *dev if (mtk_wed_rro_cfg(dev)) return; @@ -203,7 +203,7 @@ Signed-off-by: Paolo Abeni } mtk_wed_set_512_support(dev, dev->wlan.wcid_512); -@@ -1550,13 +1561,14 @@ mtk_wed_attach(struct mtk_wed_device *de +@@ -1551,13 +1562,14 @@ mtk_wed_attach(struct mtk_wed_device *de } mtk_wed_hw_init_early(dev); diff --git a/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch index 0a4a8ba0e1..618624adf7 100644 --- a/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch +++ b/target/linux/generic/backport-6.6/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch @@ -12,7 +12,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -599,7 +599,7 @@ mtk_wed_free_tx_buffer(struct mtk_wed_device +@@ -422,7 +422,7 @@ free_pagelist: static int mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) { @@ -21,7 +21,7 @@ Signed-off-by: Paolo Abeni dma_addr_t desc_phys; dev->rx_buf_ring.size = dev->wlan.rx_nbuf; -@@ -619,7 +619,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d +@@ -442,7 +442,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d static void mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) { @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni __le32 buf0; __le32 token; } __packed __aligned(4); -@@ -109,7 +109,7 @@ struct mtk_wed_device { +@@ -104,7 +104,7 @@ struct mtk_wed_device { struct { int size; diff --git a/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch b/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch index 8000a8759e..15dbaf0f6f 100644 --- a/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch +++ b/target/linux/generic/backport-6.6/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch @@ -15,7 +15,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -299,9 +299,9 @@ out: +@@ -300,9 +300,9 @@ out: static int mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) { @@ -26,7 +26,7 @@ Signed-off-by: Paolo Abeni int token = dev->wlan.token_start; int ring_size; int n_pages; -@@ -342,7 +342,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d +@@ -343,7 +343,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d return -ENOMEM; } @@ -36,7 +36,7 @@ Signed-off-by: Paolo Abeni dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, DMA_BIDIRECTIONAL); -@@ -386,8 +387,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d +@@ -387,8 +388,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d static void mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) { @@ -46,7 +46,7 @@ Signed-off-by: Paolo Abeni int page_idx; int i; -@@ -399,13 +400,12 @@ mtk_wed_free_tx_buffer(struct mtk_wed_de +@@ -400,13 +401,12 @@ mtk_wed_free_tx_buffer(struct mtk_wed_de for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { diff --git a/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch b/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch index c43114fb5b..71b32c545b 100644 --- a/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch +++ b/target/linux/generic/backport-6.6/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch @@ -11,7 +11,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -48,6 +48,26 @@ struct mtk_wed_flow_block_priv { +@@ -49,6 +49,26 @@ struct mtk_wed_flow_block_priv { struct net_device *dev; }; @@ -38,7 +38,7 @@ Signed-off-by: Paolo Abeni static void wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) { -@@ -746,7 +766,7 @@ mtk_wed_set_wpdma(struct mtk_wed_device +@@ -747,7 +767,7 @@ mtk_wed_set_wpdma(struct mtk_wed_device return; wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); @@ -47,7 +47,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -940,22 +960,10 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -941,22 +961,10 @@ mtk_wed_hw_init(struct mtk_wed_device *d wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); if (mtk_wed_is_v1(dev->hw)) { @@ -70,7 +70,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_TX_BM_DYN_THR, FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | MTK_WED_TX_BM_DYN_THR_HI_V2); -@@ -970,6 +978,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -971,6 +979,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d MTK_WED_TX_TKID_DYN_THR_HI); } @@ -82,7 +82,7 @@ Signed-off-by: Paolo Abeni mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); if (mtk_wed_is_v1(dev->hw)) { -@@ -1104,13 +1117,8 @@ mtk_wed_rx_reset(struct mtk_wed_device * +@@ -1105,13 +1118,8 @@ mtk_wed_rx_reset(struct mtk_wed_device * if (ret) { mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); } else { @@ -98,7 +98,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_RESET_IDX, 0); } -@@ -1163,7 +1171,8 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1164,7 +1172,8 @@ mtk_wed_reset_dma(struct mtk_wed_device if (busy) { mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); } else { @@ -108,7 +108,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_RESET_IDX, 0); } -@@ -1255,7 +1264,6 @@ static int +@@ -1256,7 +1265,6 @@ static int mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, bool reset) { @@ -116,7 +116,7 @@ Signed-off-by: Paolo Abeni struct mtk_wed_ring *wdma; if (idx >= ARRAY_SIZE(dev->rx_wdma)) -@@ -1263,7 +1271,7 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we +@@ -1264,7 +1272,7 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we wdma = &dev->rx_wdma[idx]; if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, @@ -125,7 +125,7 @@ Signed-off-by: Paolo Abeni return -ENOMEM; wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1284,7 +1292,6 @@ static int +@@ -1285,7 +1293,6 @@ static int mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, bool reset) { @@ -133,7 +133,7 @@ Signed-off-by: Paolo Abeni struct mtk_wed_ring *wdma; if (idx >= ARRAY_SIZE(dev->tx_wdma)) -@@ -1292,7 +1299,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we +@@ -1293,7 +1300,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we wdma = &dev->tx_wdma[idx]; if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, @@ -142,7 +142,7 @@ Signed-off-by: Paolo Abeni return -ENOMEM; wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, -@@ -1931,7 +1938,12 @@ void mtk_wed_add_hw(struct device_node * +@@ -1932,7 +1939,12 @@ void mtk_wed_add_hw(struct device_node * hw->irq = irq; hw->version = eth->soc->version; @@ -156,7 +156,7 @@ Signed-off-by: Paolo Abeni hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, "mediatek,pcie-mirror"); hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, -@@ -1945,6 +1957,8 @@ void mtk_wed_add_hw(struct device_node * +@@ -1946,6 +1958,8 @@ void mtk_wed_add_hw(struct device_node * regmap_write(hw->mirror, 0, 0); regmap_write(hw->mirror, 4, 0); } diff --git a/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch b/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch index f874899c5b..12733b142f 100644 --- a/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch +++ b/target/linux/generic/backport-6.6/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch @@ -13,7 +13,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -195,6 +195,7 @@ static const struct mtk_reg_map mt7988_r +@@ -197,6 +197,7 @@ static const struct mtk_reg_map mt7988_r .wdma_base = { [0] = 0x4800, [1] = 0x4c00, @@ -46,7 +46,7 @@ Signed-off-by: Paolo Abeni } --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -16,17 +16,19 @@ +@@ -17,17 +17,19 @@ #include #include #include "mtk_eth_soc.h" @@ -68,7 +68,7 @@ Signed-off-by: Paolo Abeni #define MTK_WED_TX_RING_SIZE 2048 #define MTK_WED_WDMA_RING_SIZE 1024 -@@ -40,7 +42,10 @@ +@@ -41,7 +43,10 @@ #define MTK_WED_RRO_QUE_CNT 8192 #define MTK_WED_MIOD_ENTRY_CNT 128 @@ -80,7 +80,7 @@ Signed-off-by: Paolo Abeni static DEFINE_MUTEX(hw_lock); struct mtk_wed_flow_block_priv { -@@ -55,6 +60,7 @@ static const struct mtk_wed_soc_data mt7 +@@ -56,6 +61,7 @@ static const struct mtk_wed_soc_data mt7 .reset_idx_tx_mask = GENMASK(3, 0), .reset_idx_rx_mask = GENMASK(17, 16), }, @@ -88,7 +88,7 @@ Signed-off-by: Paolo Abeni .wdma_desc_size = sizeof(struct mtk_wdma_desc), }; -@@ -65,6 +71,18 @@ static const struct mtk_wed_soc_data mt7 +@@ -66,6 +72,18 @@ static const struct mtk_wed_soc_data mt7 .reset_idx_tx_mask = GENMASK(1, 0), .reset_idx_rx_mask = GENMASK(7, 6), }, @@ -107,7 +107,7 @@ Signed-off-by: Paolo Abeni .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), }; -@@ -319,33 +337,38 @@ out: +@@ -320,33 +338,38 @@ out: static int mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) { @@ -159,7 +159,7 @@ Signed-off-by: Paolo Abeni dma_addr_t page_phys, buf_phys; struct page *page; void *buf; -@@ -371,28 +394,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d +@@ -372,28 +395,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d buf_phys = page_phys; for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { @@ -209,7 +209,7 @@ Signed-off-by: Paolo Abeni buf += MTK_WED_BUF_SIZE; buf_phys += MTK_WED_BUF_SIZE; } -@@ -408,31 +434,31 @@ static void +@@ -409,31 +435,31 @@ static void mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) { struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages; @@ -251,7 +251,7 @@ Signed-off-by: Paolo Abeni free_pagelist: kfree(page_list); -@@ -517,13 +543,23 @@ mtk_wed_set_ext_int(struct mtk_wed_devic +@@ -518,13 +544,23 @@ mtk_wed_set_ext_int(struct mtk_wed_devic { u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; @@ -277,7 +277,7 @@ Signed-off-by: Paolo Abeni if (!dev->hw->num_flows) mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; -@@ -535,6 +571,9 @@ mtk_wed_set_ext_int(struct mtk_wed_devic +@@ -536,6 +572,9 @@ mtk_wed_set_ext_int(struct mtk_wed_devic static void mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable) { @@ -287,7 +287,7 @@ Signed-off-by: Paolo Abeni if (enable) { wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR); wed_w32(dev, MTK_WED_TXP_DW1, -@@ -609,6 +648,14 @@ mtk_wed_dma_disable(struct mtk_wed_devic +@@ -610,6 +649,14 @@ mtk_wed_dma_disable(struct mtk_wed_devic MTK_WED_WPDMA_RX_D_RX_DRV_EN); wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); @@ -302,7 +302,7 @@ Signed-off-by: Paolo Abeni } mtk_wed_set_512_support(dev, false); -@@ -651,6 +698,14 @@ mtk_wed_deinit(struct mtk_wed_device *de +@@ -652,6 +699,14 @@ mtk_wed_deinit(struct mtk_wed_device *de MTK_WED_CTRL_RX_ROUTE_QM_EN | MTK_WED_CTRL_WED_RX_BM_EN | MTK_WED_CTRL_RX_RRO_QM_EN); @@ -317,7 +317,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -700,21 +755,37 @@ mtk_wed_detach(struct mtk_wed_device *de +@@ -701,21 +756,37 @@ mtk_wed_detach(struct mtk_wed_device *de mutex_unlock(&hw_lock); } @@ -362,7 +362,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_PCIE_INT_CTRL, FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2)); -@@ -722,19 +793,9 @@ mtk_wed_bus_init(struct mtk_wed_device * +@@ -723,19 +794,9 @@ mtk_wed_bus_init(struct mtk_wed_device * /* pcie interrupt control: pola/source selection */ wed_set(dev, MTK_WED_PCIE_INT_CTRL, MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA | @@ -385,7 +385,7 @@ Signed-off-by: Paolo Abeni break; } case MTK_WED_BUS_AXI: -@@ -772,18 +833,19 @@ mtk_wed_set_wpdma(struct mtk_wed_device +@@ -773,18 +834,19 @@ mtk_wed_set_wpdma(struct mtk_wed_device static void mtk_wed_hw_init_early(struct mtk_wed_device *dev) { @@ -412,7 +412,7 @@ Signed-off-by: Paolo Abeni wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); if (mtk_wed_is_v1(dev->hw)) { -@@ -931,11 +993,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_ +@@ -932,11 +994,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_ } /* configure RX_ROUTE_QM */ @@ -436,7 +436,7 @@ Signed-off-by: Paolo Abeni /* enable RX_ROUTE_QM */ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); } -@@ -948,22 +1017,30 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -949,22 +1018,30 @@ mtk_wed_hw_init(struct mtk_wed_device *d dev->init_done = true; mtk_wed_set_ext_int(dev, false); @@ -475,7 +475,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_TX_BM_DYN_THR, FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | MTK_WED_TX_BM_DYN_THR_HI_V2); -@@ -973,9 +1050,6 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -974,9 +1051,6 @@ mtk_wed_hw_init(struct mtk_wed_device *d dev->tx_buf_ring.size / 128) | FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, dev->tx_buf_ring.size / 128)); @@ -485,7 +485,7 @@ Signed-off-by: Paolo Abeni } wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid, -@@ -985,26 +1059,62 @@ mtk_wed_hw_init(struct mtk_wed_device *d +@@ -986,26 +1060,62 @@ mtk_wed_hw_init(struct mtk_wed_device *d mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); @@ -561,7 +561,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -1302,6 +1412,24 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we +@@ -1303,6 +1413,24 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we dev->hw->soc->wdma_desc_size, true)) return -ENOMEM; @@ -586,7 +586,7 @@ Signed-off-by: Paolo Abeni wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, wdma->desc_phys); wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, -@@ -1367,6 +1495,9 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1368,6 +1496,9 @@ mtk_wed_configure_irq(struct mtk_wed_dev wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); } else { @@ -596,7 +596,7 @@ Signed-off-by: Paolo Abeni /* initail tx interrupt trigger */ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | -@@ -1419,33 +1550,60 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1420,33 +1551,60 @@ mtk_wed_dma_enable(struct mtk_wed_device { int i; @@ -668,7 +668,7 @@ Signed-off-by: Paolo Abeni wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); -@@ -1457,11 +1615,22 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1458,11 +1616,22 @@ mtk_wed_dma_enable(struct mtk_wed_device MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); @@ -693,7 +693,7 @@ Signed-off-by: Paolo Abeni for (i = 0; i < MTK_WED_RX_QUEUES; i++) mtk_wed_check_wfdma_rx_fill(dev, i); -@@ -1501,6 +1670,12 @@ mtk_wed_start(struct mtk_wed_device *dev +@@ -1502,6 +1671,12 @@ mtk_wed_start(struct mtk_wed_device *dev wed_r32(dev, MTK_WED_EXT_INT_MASK1); wed_r32(dev, MTK_WED_EXT_INT_MASK2); @@ -706,7 +706,7 @@ Signed-off-by: Paolo Abeni if (mtk_wed_rro_cfg(dev)) return; } -@@ -1552,6 +1727,7 @@ mtk_wed_attach(struct mtk_wed_device *de +@@ -1553,6 +1728,7 @@ mtk_wed_attach(struct mtk_wed_device *de dev->irq = hw->irq; dev->wdma_idx = hw->index; dev->version = hw->version; @@ -714,7 +714,7 @@ Signed-off-by: Paolo Abeni if (hw->eth->dma_dev == hw->eth->dev && of_dma_is_coherent(hw->eth->dev->of_node)) -@@ -1619,6 +1795,23 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev +@@ -1620,6 +1796,23 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev ring->reg_base = MTK_WED_RING_TX(idx); ring->wpdma = regs; @@ -738,7 +738,7 @@ Signed-off-by: Paolo Abeni /* WED -> WPDMA */ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_TX_RING_SIZE); -@@ -1693,15 +1886,13 @@ mtk_wed_rx_ring_setup(struct mtk_wed_dev +@@ -1694,15 +1887,13 @@ mtk_wed_rx_ring_setup(struct mtk_wed_dev static u32 mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) { @@ -759,7 +759,7 @@ Signed-off-by: Paolo Abeni val = wed_r32(dev, MTK_WED_EXT_INT_STATUS); wed_w32(dev, MTK_WED_EXT_INT_STATUS, val); -@@ -1942,6 +2133,9 @@ void mtk_wed_add_hw(struct device_node * +@@ -1943,6 +2134,9 @@ void mtk_wed_add_hw(struct device_node * case 2: hw->soc = &mt7986_data; break; @@ -1254,7 +1254,7 @@ Signed-off-by: Paolo Abeni #define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) --- a/include/linux/soc/mediatek/mtk_wed.h +++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -139,6 +139,8 @@ struct mtk_wed_device { +@@ -138,6 +138,8 @@ struct mtk_wed_device { u32 wpdma_rx; bool wcid_512; @@ -1263,7 +1263,7 @@ Signed-off-by: Paolo Abeni u16 token_start; unsigned int nbuf; -@@ -212,10 +214,12 @@ mtk_wed_device_attach(struct mtk_wed_dev +@@ -211,10 +213,12 @@ mtk_wed_device_attach(struct mtk_wed_dev return ret; } diff --git a/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch b/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch index e91ae69d08..5e12343de2 100644 --- a/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch +++ b/target/linux/generic/backport-6.6/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch @@ -14,7 +14,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -585,22 +585,15 @@ mtk_wed_set_512_support(struct mtk_wed_d +@@ -586,22 +586,15 @@ mtk_wed_set_512_support(struct mtk_wed_d } } @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni if (cur_idx == MTK_WED_RX_RING_SIZE - 1) break; -@@ -609,12 +602,10 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_w +@@ -610,12 +603,10 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_w if (i == 3) { dev_err(dev->hw->dev, "rx dma enable failed\n"); @@ -56,7 +56,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -1545,6 +1536,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev +@@ -1546,6 +1537,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev wed_w32(dev, MTK_WED_INT_MASK, irq_mask); } @@ -64,7 +64,7 @@ Signed-off-by: Paolo Abeni static void mtk_wed_dma_enable(struct mtk_wed_device *dev) { -@@ -1632,8 +1624,26 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1633,8 +1625,26 @@ mtk_wed_dma_enable(struct mtk_wed_device wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); } diff --git a/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch b/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch index 6534d73d8e..f70886aa0d 100644 --- a/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch +++ b/target/linux/generic/backport-6.6/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch @@ -15,7 +15,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -438,7 +438,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e +@@ -439,7 +439,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e } int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, @@ -25,7 +25,7 @@ Signed-off-by: Paolo Abeni { struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); u32 *ib2 = mtk_foe_entry_ib2(eth, entry); -@@ -450,6 +451,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et +@@ -451,6 +452,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et MTK_FOE_IB2_WDMA_WINFO_V2; l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); @@ -96,7 +96,7 @@ Signed-off-by: Paolo Abeni case 0: --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -29,6 +29,8 @@ +@@ -30,6 +30,8 @@ #define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) #define MTK_WED_RX_RING_SIZE 1536 #define MTK_WED_RX_PG_BM_CNT 8192 @@ -105,7 +105,7 @@ Signed-off-by: Paolo Abeni #define MTK_WED_TX_RING_SIZE 2048 #define MTK_WED_WDMA_RING_SIZE 1024 -@@ -172,6 +174,23 @@ mtk_wdma_rx_reset(struct mtk_wed_device +@@ -173,6 +175,23 @@ mtk_wdma_rx_reset(struct mtk_wed_device return ret; } @@ -129,7 +129,7 @@ Signed-off-by: Paolo Abeni static void mtk_wdma_tx_reset(struct mtk_wed_device *dev) { -@@ -335,6 +354,118 @@ out: +@@ -336,6 +355,118 @@ out: } static int @@ -248,7 +248,7 @@ Signed-off-by: Paolo Abeni mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) { u32 desc_size = dev->hw->soc->tx_ring_desc_size; -@@ -708,6 +839,7 @@ __mtk_wed_detach(struct mtk_wed_device * +@@ -709,6 +840,7 @@ __mtk_wed_detach(struct mtk_wed_device * mtk_wdma_rx_reset(dev); mtk_wed_reset(dev, MTK_WED_RESET_WED); @@ -256,7 +256,7 @@ Signed-off-by: Paolo Abeni mtk_wed_free_tx_buffer(dev); mtk_wed_free_tx_rings(dev); -@@ -1128,23 +1260,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring * +@@ -1129,23 +1261,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring * } } @@ -280,7 +280,7 @@ Signed-off-by: Paolo Abeni static int mtk_wed_rx_reset(struct mtk_wed_device *dev) { -@@ -1691,6 +1806,7 @@ mtk_wed_start(struct mtk_wed_device *dev +@@ -1692,6 +1807,7 @@ mtk_wed_start(struct mtk_wed_device *dev } mtk_wed_set_512_support(dev, dev->wlan.wcid_512); @@ -288,7 +288,7 @@ Signed-off-by: Paolo Abeni mtk_wed_dma_enable(dev); dev->running = true; -@@ -1747,6 +1863,10 @@ mtk_wed_attach(struct mtk_wed_device *de +@@ -1748,6 +1864,10 @@ mtk_wed_attach(struct mtk_wed_device *de if (ret) goto out; @@ -416,7 +416,7 @@ Signed-off-by: Paolo Abeni #define MTK_WED_PCIE_BASE1 0x11310000 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -928,6 +928,7 @@ struct net_device_path { +@@ -917,6 +917,7 @@ struct net_device_path { u8 queue; u16 wcid; u8 bss; @@ -426,7 +426,7 @@ Signed-off-by: Paolo Abeni }; --- a/include/linux/soc/mediatek/mtk_wed.h +++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -129,6 +129,7 @@ struct mtk_wed_device { +@@ -128,6 +128,7 @@ struct mtk_wed_device { enum mtk_wed_bus_tye bus_type; void __iomem *base; u32 phy_base; @@ -434,7 +434,7 @@ Signed-off-by: Paolo Abeni u32 wpdma_phys; u32 wpdma_int; -@@ -147,10 +148,12 @@ struct mtk_wed_device { +@@ -146,10 +147,12 @@ struct mtk_wed_device { unsigned int rx_nbuf; unsigned int rx_npkt; unsigned int rx_size; @@ -447,7 +447,7 @@ Signed-off-by: Paolo Abeni u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); int (*offload_enable)(struct mtk_wed_device *wed); -@@ -224,6 +227,15 @@ static inline bool mtk_wed_get_rx_capa(s +@@ -223,6 +226,15 @@ static inline bool mtk_wed_get_rx_capa(s #else return false; #endif diff --git a/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch b/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch index 0cf4c18875..5c3015c338 100644 --- a/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch +++ b/target/linux/generic/backport-6.6/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch @@ -13,7 +13,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -26,7 +26,7 @@ +@@ -27,7 +27,7 @@ #define MTK_WED_BUF_SIZE 2048 #define MTK_WED_PAGE_BUF_SIZE 128 #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) @@ -22,7 +22,7 @@ Signed-off-by: Paolo Abeni #define MTK_WED_RX_RING_SIZE 1536 #define MTK_WED_RX_PG_BM_CNT 8192 #define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4) -@@ -596,6 +596,68 @@ free_pagelist: +@@ -597,6 +597,68 @@ free_pagelist: } static int @@ -91,7 +91,7 @@ Signed-off-by: Paolo Abeni mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) { struct mtk_wed_bm_desc *desc; -@@ -612,7 +674,42 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d +@@ -613,7 +675,42 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d dev->rx_buf_ring.desc_phys = desc_phys; dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); @@ -135,7 +135,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -626,6 +723,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_de +@@ -627,6 +724,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_de dev->wlan.release_rx_buf(dev); dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), desc, dev->rx_buf_ring.desc_phys); @@ -164,7 +164,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -639,6 +758,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed +@@ -640,6 +759,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); @@ -173,7 +173,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -934,6 +1055,8 @@ mtk_wed_bus_init(struct mtk_wed_device * +@@ -935,6 +1056,8 @@ mtk_wed_bus_init(struct mtk_wed_device * static void mtk_wed_set_wpdma(struct mtk_wed_device *dev) { @@ -182,7 +182,7 @@ Signed-off-by: Paolo Abeni if (mtk_wed_is_v1(dev->hw)) { wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); return; -@@ -951,6 +1074,15 @@ mtk_wed_set_wpdma(struct mtk_wed_device +@@ -952,6 +1075,15 @@ mtk_wed_set_wpdma(struct mtk_wed_device wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); @@ -198,7 +198,7 @@ Signed-off-by: Paolo Abeni } static void -@@ -1762,6 +1894,165 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1763,6 +1895,165 @@ mtk_wed_dma_enable(struct mtk_wed_device } static void @@ -364,7 +364,7 @@ Signed-off-by: Paolo Abeni mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask) { int i; -@@ -2215,6 +2506,10 @@ void mtk_wed_add_hw(struct device_node * +@@ -2216,6 +2507,10 @@ void mtk_wed_add_hw(struct device_node * .detach = mtk_wed_detach, .ppe_check = mtk_wed_ppe_check, .setup_tc = mtk_wed_setup_tc, @@ -395,7 +395,7 @@ Signed-off-by: Paolo Abeni struct { int size; -@@ -120,6 +124,13 @@ struct mtk_wed_device { +@@ -119,6 +123,13 @@ struct mtk_wed_device { dma_addr_t fdbk_phys; } rro; @@ -409,7 +409,7 @@ Signed-off-by: Paolo Abeni /* filled by driver: */ struct { union { -@@ -138,6 +149,8 @@ struct mtk_wed_device { +@@ -137,6 +148,8 @@ struct mtk_wed_device { u32 wpdma_txfree; u32 wpdma_rx_glo; u32 wpdma_rx; @@ -418,7 +418,7 @@ Signed-off-by: Paolo Abeni bool wcid_512; bool hw_rro; -@@ -152,9 +165,20 @@ struct mtk_wed_device { +@@ -151,9 +164,20 @@ struct mtk_wed_device { u8 tx_tbit[MTK_WED_TX_QUEUES]; u8 rx_tbit[MTK_WED_RX_QUEUES]; @@ -439,7 +439,7 @@ Signed-off-by: Paolo Abeni u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); int (*offload_enable)(struct mtk_wed_device *wed); void (*offload_disable)(struct mtk_wed_device *wed); -@@ -193,6 +217,14 @@ struct mtk_wed_ops { +@@ -192,6 +216,14 @@ struct mtk_wed_ops { void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, enum tc_setup_type type, void *type_data); @@ -454,7 +454,7 @@ Signed-off-by: Paolo Abeni }; extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; -@@ -264,6 +296,15 @@ static inline bool mtk_wed_is_amsdu_supp +@@ -263,6 +295,15 @@ static inline bool mtk_wed_is_amsdu_supp #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) @@ -470,7 +470,7 @@ Signed-off-by: Paolo Abeni #else static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) { -@@ -283,6 +324,10 @@ static inline bool mtk_wed_device_active +@@ -282,6 +323,10 @@ static inline bool mtk_wed_device_active #define mtk_wed_device_stop(_dev) do {} while (0) #define mtk_wed_device_dma_reset(_dev) do {} while (0) #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP diff --git a/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch b/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch index f491d2fd80..9730c3042f 100644 --- a/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch +++ b/target/linux/generic/backport-6.6/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch @@ -412,7 +412,7 @@ Signed-off-by: Paolo Abeni mtk_wed_reg_set(void *data, u64 val) { struct mtk_wed_hw *hw = data; -@@ -266,7 +624,16 @@ void mtk_wed_hw_add_debugfs(struct mtk_w +@@ -264,7 +622,16 @@ void mtk_wed_hw_add_debugfs(struct mtk_w debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); diff --git a/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch b/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch index aaaabf05e8..18aa4107db 100644 --- a/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch +++ b/target/linux/generic/backport-6.6/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch @@ -13,7 +13,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -148,6 +148,90 @@ mtk_wdma_read_reset(struct mtk_wed_devic +@@ -149,6 +149,90 @@ mtk_wdma_read_reset(struct mtk_wed_devic return wdma_r32(dev, MTK_WDMA_GLO_CFG); } @@ -104,7 +104,7 @@ Signed-off-by: Paolo Abeni static int mtk_wdma_rx_reset(struct mtk_wed_device *dev) { -@@ -160,6 +244,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device +@@ -161,6 +245,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device if (ret) dev_err(dev->hw->dev, "rx reset failed\n"); @@ -112,7 +112,7 @@ Signed-off-by: Paolo Abeni wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -@@ -192,6 +277,84 @@ mtk_wed_poll_busy(struct mtk_wed_device +@@ -193,6 +278,84 @@ mtk_wed_poll_busy(struct mtk_wed_device } static void @@ -197,7 +197,7 @@ Signed-off-by: Paolo Abeni mtk_wdma_tx_reset(struct mtk_wed_device *dev) { u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; -@@ -202,6 +365,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device +@@ -203,6 +366,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device !(status & mask), 0, 10000)) dev_err(dev->hw->dev, "tx reset failed\n"); @@ -205,7 +205,7 @@ Signed-off-by: Paolo Abeni wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); -@@ -1405,13 +1569,33 @@ mtk_wed_rx_reset(struct mtk_wed_device * +@@ -1406,13 +1570,33 @@ mtk_wed_rx_reset(struct mtk_wed_device * if (ret) return ret; @@ -239,7 +239,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, MTK_WED_WPDMA_RX_D_RST_CRX_IDX | MTK_WED_WPDMA_RX_D_RST_DRV_IDX); -@@ -1439,23 +1623,52 @@ mtk_wed_rx_reset(struct mtk_wed_device * +@@ -1440,23 +1624,52 @@ mtk_wed_rx_reset(struct mtk_wed_device * wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); } @@ -298,7 +298,7 @@ Signed-off-by: Paolo Abeni mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); /* reset wed rx dma */ -@@ -1476,6 +1689,14 @@ mtk_wed_rx_reset(struct mtk_wed_device * +@@ -1477,6 +1690,14 @@ mtk_wed_rx_reset(struct mtk_wed_device * MTK_WED_CTRL_WED_RX_BM_BUSY); mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); @@ -313,7 +313,7 @@ Signed-off-by: Paolo Abeni /* wo change to enable state */ val = MTK_WED_WO_STATE_ENABLE; ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, -@@ -1493,6 +1714,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * +@@ -1494,6 +1715,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * false); } mtk_wed_free_rx_buffer(dev); @@ -321,7 +321,7 @@ Signed-off-by: Paolo Abeni return 0; } -@@ -1526,15 +1748,41 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1527,15 +1749,41 @@ mtk_wed_reset_dma(struct mtk_wed_device /* 2. reset WDMA rx DMA */ busy = !!mtk_wdma_rx_reset(dev); @@ -364,7 +364,7 @@ Signed-off-by: Paolo Abeni wed_w32(dev, MTK_WED_WDMA_RESET_IDX, MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV); wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0); -@@ -1550,8 +1798,13 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1551,8 +1799,13 @@ mtk_wed_reset_dma(struct mtk_wed_device wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); for (i = 0; i < 100; i++) { @@ -380,7 +380,7 @@ Signed-off-by: Paolo Abeni break; } -@@ -1573,6 +1826,8 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1574,6 +1827,8 @@ mtk_wed_reset_dma(struct mtk_wed_device mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV); @@ -389,7 +389,7 @@ Signed-off-by: Paolo Abeni } else { wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, MTK_WED_WPDMA_RESET_IDX_TX | -@@ -1589,7 +1844,14 @@ mtk_wed_reset_dma(struct mtk_wed_device +@@ -1590,7 +1845,14 @@ mtk_wed_reset_dma(struct mtk_wed_device wed_w32(dev, MTK_WED_RESET_IDX, 0); } @@ -405,7 +405,7 @@ Signed-off-by: Paolo Abeni } static int -@@ -1841,6 +2103,7 @@ mtk_wed_dma_enable(struct mtk_wed_device +@@ -1842,6 +2104,7 @@ mtk_wed_dma_enable(struct mtk_wed_device MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); @@ -413,7 +413,7 @@ Signed-off-by: Paolo Abeni } wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, -@@ -1904,6 +2167,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_devi +@@ -1905,6 +2168,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_devi if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) return; diff --git a/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch index 4fc32e3e96..4190a3d328 100644 --- a/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch @@ -29,7 +29,7 @@ Signed-off-by: Paolo Abeni #define PHY_ID_AQR112 0x03a1b662 #define PHY_ID_AQR412 0x03a1b712 #define PHY_ID_AQR113C 0x31c31c12 -@@ -670,6 +672,16 @@ static int aqr107_probe(struct phy_devic +@@ -672,6 +674,16 @@ static int aqr107_probe(struct phy_devic return aqr_hwmon_probe(phydev); } @@ -46,7 +46,7 @@ Signed-off-by: Paolo Abeni static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), -@@ -744,6 +756,44 @@ static struct phy_driver aqr_driver[] = +@@ -746,6 +758,44 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { diff --git a/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch index 5be82455c1..cd9161d023 100644 --- a/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch @@ -16,7 +16,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -24,6 +24,7 @@ +@@ -26,6 +26,7 @@ #define PHY_ID_AQR111B0 0x03a1b612 #define PHY_ID_AQR112 0x03a1b662 #define PHY_ID_AQR412 0x03a1b712 @@ -24,7 +24,7 @@ Signed-off-by: David S. Miller #define PHY_ID_AQR113C 0x31c31c12 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 -@@ -802,6 +803,25 @@ static struct phy_driver aqr_driver[] = +@@ -840,6 +841,25 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -50,7 +50,7 @@ Signed-off-by: David S. Miller PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), .name = "Aquantia AQR113C", .probe = aqr107_probe, -@@ -834,6 +854,7 @@ static struct mdio_device_id __maybe_unu +@@ -874,6 +894,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, diff --git a/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch index 7dcfe7d01b..fbdf810b35 100644 --- a/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch +++ b/target/linux/generic/backport-6.6/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch @@ -15,7 +15,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -26,6 +26,7 @@ +@@ -28,6 +28,7 @@ #define PHY_ID_AQR412 0x03a1b712 #define PHY_ID_AQR113 0x31c31c40 #define PHY_ID_AQR113C 0x31c31c12 @@ -23,7 +23,7 @@ Signed-off-by: David S. Miller #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -840,6 +841,25 @@ static struct phy_driver aqr_driver[] = +@@ -878,6 +879,25 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -49,7 +49,7 @@ Signed-off-by: David S. Miller }; module_phy_driver(aqr_driver); -@@ -856,6 +876,7 @@ static struct mdio_device_id __maybe_unu +@@ -896,6 +916,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, diff --git a/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch b/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch index 789b93e9f9..821fd60a2d 100644 --- a/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch +++ b/target/linux/generic/backport-6.6/770-net-introduce-napi_is_scheduled-helper.patch @@ -25,7 +25,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c -@@ -2507,14 +2507,6 @@ static int napi_rx_handler(struct napi_s +@@ -2501,14 +2501,6 @@ static int napi_rx_handler(struct napi_s return work_done; } @@ -42,7 +42,7 @@ Signed-off-by: Paolo Abeni * @adap: the adapter --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c -@@ -1479,7 +1479,7 @@ static void rtw89_core_rx_to_mac80211(st +@@ -1744,7 +1744,7 @@ static void rtw89_core_rx_to_mac80211(st struct napi_struct *napi = &rtwdev->napi; /* In low power mode, napi isn't scheduled. Receive it to netif. */ @@ -53,7 +53,7 @@ Signed-off-by: Paolo Abeni rtw89_core_hw_to_sband_rate(rx_status); --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -468,6 +468,29 @@ static inline bool napi_prefer_busy_poll +@@ -480,6 +480,29 @@ static inline bool napi_prefer_busy_poll return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state); } @@ -85,7 +85,7 @@ Signed-off-by: Paolo Abeni /** --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6533,7 +6533,7 @@ static int __napi_poll(struct napi_struc +@@ -6555,7 +6555,7 @@ static int __napi_poll(struct napi_struc * accidentally calling ->poll() when NAPI is not scheduled. */ work = 0; diff --git a/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch b/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch index aa0d730bc8..3951715fc6 100644 --- a/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch +++ b/target/linux/generic/backport-6.6/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch @@ -46,7 +46,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2974,13 +2974,25 @@ static void stmmac_tx_timer_arm(struct s +@@ -3003,13 +3003,25 @@ static void stmmac_tx_timer_arm(struct s { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; u32 tx_coal_timer = priv->tx_coal_timer[queue]; diff --git a/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch b/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch index bce54eba4f..f56c48b4b8 100644 --- a/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch +++ b/target/linux/generic/backport-6.6/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch @@ -27,7 +27,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -287,7 +287,7 @@ struct stmmac_safety_stats { +@@ -318,7 +318,7 @@ struct stmmac_safety_stats { #define MIN_DMA_RIWT 0x10 #define DEF_DMA_RIWT 0xa0 /* Tx coalesce parameters */ diff --git a/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch b/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch index 3c9680a279..85b320f15a 100644 --- a/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch +++ b/target/linux/generic/backport-6.6/795-v6.7-16-r8152-use-napi_gro_frags.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c -@@ -2583,8 +2583,9 @@ static int rx_bottom(struct r8152 *tp, i +@@ -2584,8 +2584,9 @@ static int rx_bottom(struct r8152 *tp, i while (urb->actual_length > len_used) { struct net_device *netdev = tp->netdev; struct net_device_stats *stats = &netdev->stats; @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000); -@@ -2597,45 +2598,77 @@ static int rx_bottom(struct r8152 *tp, i +@@ -2598,45 +2599,77 @@ static int rx_bottom(struct r8152 *tp, i break; pkt_len -= ETH_FCS_LEN; diff --git a/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch b/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch index 00773ab0f6..bed20f9e99 100644 --- a/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch +++ b/target/linux/generic/backport-6.6/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch @@ -49,7 +49,7 @@ Signed-off-by: Lee Jones --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig -@@ -164,6 +164,7 @@ config LEDS_TURRIS_OMNIA +@@ -188,6 +188,7 @@ config LEDS_TURRIS_OMNIA depends on I2C depends on MACH_ARMADA_38X || COMPILE_TEST depends on OF @@ -187,7 +187,7 @@ Signed-off-by: Lee Jones /* put the LED into software mode */ ret = omnia_cmd_write_u8(client, CMD_LED_MODE, -@@ -309,6 +385,12 @@ static int omnia_leds_probe(struct i2c_c +@@ -308,6 +384,12 @@ static int omnia_leds_probe(struct i2c_c mutex_init(&leds->lock); diff --git a/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch b/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch index 35b15776fb..80c9836010 100644 --- a/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch +++ b/target/linux/generic/backport-6.6/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch @@ -67,7 +67,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -523,6 +523,7 @@ static int mtd_nvmem_add(struct mtd_info +@@ -552,6 +552,7 @@ static int mtd_nvmem_add(struct mtd_info config.dev = &mtd->dev; config.name = dev_name(&mtd->dev); config.owner = THIS_MODULE; @@ -75,7 +75,7 @@ Signed-off-by: Greg Kroah-Hartman config.reg_read = mtd_nvmem_reg_read; config.size = mtd->size; config.word_size = 1; -@@ -891,6 +892,7 @@ static struct nvmem_device *mtd_otp_nvme +@@ -898,6 +899,7 @@ static struct nvmem_device *mtd_otp_nvme config.name = compatible; config.id = NVMEM_DEVID_AUTO; config.owner = THIS_MODULE; @@ -95,7 +95,7 @@ Signed-off-by: Greg Kroah-Hartman .stride = sizeof(u32), --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -998,9 +998,11 @@ struct nvmem_device *nvmem_register(cons +@@ -1003,9 +1003,11 @@ struct nvmem_device *nvmem_register(cons if (rval) goto err_remove_cells; @@ -122,7 +122,7 @@ Signed-off-by: Greg Kroah-Hartman .stride = 1, --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c -@@ -616,6 +616,7 @@ static int imx_ocotp_probe(struct platfo +@@ -615,6 +615,7 @@ static int imx_ocotp_probe(struct platfo return PTR_ERR(priv->clk); priv->params = of_device_get_match_data(&pdev->dev); @@ -142,7 +142,7 @@ Signed-off-by: Greg Kroah-Hartman econfig->reg_read = meson_efuse_read; --- a/drivers/nvmem/meson-mx-efuse.c +++ b/drivers/nvmem/meson-mx-efuse.c -@@ -211,6 +211,7 @@ static int meson_mx_efuse_probe(struct p +@@ -210,6 +210,7 @@ static int meson_mx_efuse_probe(struct p efuse->config.owner = THIS_MODULE; efuse->config.dev = &pdev->dev; efuse->config.priv = efuse; @@ -212,7 +212,7 @@ Signed-off-by: Greg Kroah-Hartman .read_only = true, --- a/drivers/nvmem/sc27xx-efuse.c +++ b/drivers/nvmem/sc27xx-efuse.c -@@ -248,6 +248,7 @@ static int sc27xx_efuse_probe(struct pla +@@ -247,6 +247,7 @@ static int sc27xx_efuse_probe(struct pla econfig.reg_read = sc27xx_efuse_read; econfig.priv = efuse; econfig.dev = &pdev->dev; @@ -262,7 +262,7 @@ Signed-off-by: Greg Kroah-Hartman .size = QAC628_OTP_SIZE, --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c -@@ -154,6 +154,7 @@ static int sunxi_sid_probe(struct platfo +@@ -153,6 +153,7 @@ static int sunxi_sid_probe(struct platfo nvmem_cfg->dev = dev; nvmem_cfg->name = "sunxi-sid"; nvmem_cfg->type = NVMEM_TYPE_OTP; diff --git a/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch b/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch index 7d80ad37f1..39be82d4bf 100644 --- a/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch +++ b/target/linux/generic/backport-6.6/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch @@ -38,7 +38,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -531,7 +531,6 @@ static int mtd_nvmem_add(struct mtd_info +@@ -560,7 +560,6 @@ static int mtd_nvmem_add(struct mtd_info config.read_only = true; config.root_only = true; config.ignore_wp = true; @@ -48,7 +48,7 @@ Signed-off-by: Greg Kroah-Hartman mtd->nvmem = nvmem_register(&config); --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -936,7 +936,7 @@ struct nvmem_device *nvmem_register(cons +@@ -941,7 +941,7 @@ struct nvmem_device *nvmem_register(cons nvmem->nkeepout = config->nkeepout; if (config->of_node) nvmem->dev.of_node = config->of_node; diff --git a/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch b/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch index 564fe9822d..95e1a7b5fc 100644 --- a/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch +++ b/target/linux/generic/backport-6.6/818-v6.8-of-device-Export-of_device_make_bus_id.patch @@ -22,7 +22,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/of/device.c +++ b/drivers/of/device.c -@@ -395,3 +395,44 @@ int of_device_uevent_modalias(struct dev +@@ -304,3 +304,44 @@ int of_device_uevent_modalias(const stru return 0; } EXPORT_SYMBOL_GPL(of_device_uevent_modalias); @@ -69,7 +69,7 @@ Signed-off-by: Greg Kroah-Hartman +EXPORT_SYMBOL_GPL(of_device_make_bus_id); --- a/drivers/of/platform.c +++ b/drivers/of/platform.c -@@ -64,46 +64,6 @@ EXPORT_SYMBOL(of_find_device_by_node); +@@ -98,46 +98,6 @@ static const struct of_device_id of_skip */ /** @@ -118,7 +118,7 @@ Signed-off-by: Greg Kroah-Hartman * @bus_id: Name to assign to the device. May be null to use default name. --- a/include/linux/of_device.h +++ b/include/linux/of_device.h -@@ -56,6 +56,9 @@ static inline int of_dma_configure(struc +@@ -40,6 +40,9 @@ static inline int of_dma_configure(struc { return of_dma_configure_id(dev, np, force_dma, NULL); } @@ -128,7 +128,7 @@ Signed-off-by: Greg Kroah-Hartman #else /* CONFIG_OF */ static inline int of_driver_match_device(struct device *dev, -@@ -113,6 +116,9 @@ static inline int of_dma_configure(struc +@@ -82,6 +85,9 @@ static inline int of_dma_configure(struc { return 0; } diff --git a/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch b/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch index 2093fac8a1..59175c8051 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch @@ -25,7 +25,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -848,14 +848,6 @@ static int nvmem_add_cells_from_layout(s +@@ -847,14 +847,6 @@ static int nvmem_add_cells_from_layout(s } #if IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch b/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch index db2d8c1b46..1f39dfea2f 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch @@ -20,7 +20,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -817,7 +817,7 @@ static int nvmem_add_cells_from_layout(s +@@ -816,7 +816,7 @@ static int nvmem_add_cells_from_layout(s int ret; if (layout && layout->add_cells) { diff --git a/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch b/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch index 65aa37f834..d2c274033e 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch @@ -25,7 +25,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -676,7 +676,6 @@ static int nvmem_validate_keepouts(struc +@@ -675,7 +675,6 @@ static int nvmem_validate_keepouts(struc static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { @@ -33,7 +33,7 @@ Signed-off-by: Greg Kroah-Hartman struct device *dev = &nvmem->dev; struct device_node *child; const __be32 *addr; -@@ -706,8 +705,8 @@ static int nvmem_add_cells_from_dt(struc +@@ -705,8 +704,8 @@ static int nvmem_add_cells_from_dt(struc info.np = of_node_get(child); @@ -44,7 +44,7 @@ Signed-off-by: Greg Kroah-Hartman ret = nvmem_add_one_cell(nvmem, &info); kfree(info.name); -@@ -896,6 +895,7 @@ struct nvmem_device *nvmem_register(cons +@@ -895,6 +894,7 @@ struct nvmem_device *nvmem_register(cons kref_init(&nvmem->refcnt); INIT_LIST_HEAD(&nvmem->cells); @@ -54,7 +54,7 @@ Signed-off-by: Greg Kroah-Hartman if (!nvmem->owner && config->dev->driver) --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c -@@ -584,17 +584,12 @@ static const struct of_device_id imx_oco +@@ -583,17 +583,12 @@ static const struct of_device_id imx_oco }; MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); @@ -74,7 +74,7 @@ Signed-off-by: Greg Kroah-Hartman static int imx_ocotp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; -@@ -620,7 +615,7 @@ static int imx_ocotp_probe(struct platfo +@@ -619,7 +614,7 @@ static int imx_ocotp_probe(struct platfo imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; imx_ocotp_nvmem_config.dev = dev; imx_ocotp_nvmem_config.priv = priv; diff --git a/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch b/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch index 1881332340..ce33b52328 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch @@ -74,7 +74,7 @@ Signed-off-by: Greg Kroah-Hartman # Devices --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -56,9 +56,6 @@ static LIST_HEAD(nvmem_lookup_list); +@@ -55,9 +55,6 @@ static LIST_HEAD(nvmem_lookup_list); static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); @@ -84,7 +84,7 @@ Signed-off-by: Greg Kroah-Hartman static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, void *val, size_t bytes) { -@@ -741,97 +738,22 @@ static int nvmem_add_cells_from_fixed_la +@@ -740,97 +737,22 @@ static int nvmem_add_cells_from_fixed_la return err; } @@ -189,7 +189,7 @@ Signed-off-by: Greg Kroah-Hartman const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, struct nvmem_layout *layout) { -@@ -839,7 +761,7 @@ const void *nvmem_layout_get_match_data( +@@ -838,7 +760,7 @@ const void *nvmem_layout_get_match_data( const struct of_device_id *match; layout_np = of_nvmem_layout_get_container(nvmem); @@ -198,7 +198,7 @@ Signed-off-by: Greg Kroah-Hartman return match ? match->data : NULL; } -@@ -951,19 +873,6 @@ struct nvmem_device *nvmem_register(cons +@@ -950,19 +872,6 @@ struct nvmem_device *nvmem_register(cons goto err_put_device; } @@ -218,7 +218,7 @@ Signed-off-by: Greg Kroah-Hartman if (config->cells) { rval = nvmem_add_cells(nvmem, config->cells, config->ncells); if (rval) -@@ -984,24 +893,24 @@ struct nvmem_device *nvmem_register(cons +@@ -983,24 +892,24 @@ struct nvmem_device *nvmem_register(cons if (rval) goto err_remove_cells; @@ -249,7 +249,7 @@ Signed-off-by: Greg Kroah-Hartman if (config->compat) nvmem_sysfs_remove_compat(nvmem, config); err_put_device: -@@ -1023,7 +932,7 @@ static void nvmem_device_release(struct +@@ -1022,7 +931,7 @@ static void nvmem_device_release(struct device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); nvmem_device_remove_all_cells(nvmem); @@ -258,7 +258,7 @@ Signed-off-by: Greg Kroah-Hartman device_unregister(&nvmem->dev); } -@@ -1325,6 +1234,12 @@ nvmem_cell_get_from_lookup(struct device +@@ -1324,6 +1233,12 @@ nvmem_cell_get_from_lookup(struct device return cell; } @@ -271,7 +271,7 @@ Signed-off-by: Greg Kroah-Hartman #if IS_ENABLED(CONFIG_OF) static struct nvmem_cell_entry * nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np) -@@ -1343,6 +1258,18 @@ nvmem_find_cell_entry_by_node(struct nvm +@@ -1342,6 +1257,18 @@ nvmem_find_cell_entry_by_node(struct nvm return cell; } @@ -290,7 +290,7 @@ Signed-off-by: Greg Kroah-Hartman /** * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id * -@@ -1405,16 +1332,29 @@ struct nvmem_cell *of_nvmem_cell_get(str +@@ -1404,16 +1331,29 @@ struct nvmem_cell *of_nvmem_cell_get(str return ERR_CAST(nvmem); } @@ -322,7 +322,7 @@ Signed-off-by: Greg Kroah-Hartman return cell; } -@@ -1528,6 +1468,7 @@ void nvmem_cell_put(struct nvmem_cell *c +@@ -1527,6 +1467,7 @@ void nvmem_cell_put(struct nvmem_cell *c kfree(cell); __nvmem_device_put(nvmem); @@ -330,7 +330,7 @@ Signed-off-by: Greg Kroah-Hartman } EXPORT_SYMBOL_GPL(nvmem_cell_put); -@@ -2105,11 +2046,22 @@ EXPORT_SYMBOL_GPL(nvmem_dev_name); +@@ -2104,11 +2045,22 @@ EXPORT_SYMBOL_GPL(nvmem_dev_name); static int __init nvmem_init(void) { diff --git a/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch b/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch index 89872bec2e..4a1f9aefc8 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch @@ -45,7 +45,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -300,6 +300,43 @@ static umode_t nvmem_bin_attr_is_visible +@@ -299,6 +299,43 @@ static umode_t nvmem_bin_attr_is_visible return nvmem_bin_attr_get_umode(nvmem); } @@ -89,7 +89,7 @@ Signed-off-by: Greg Kroah-Hartman /* default read/write permissions */ static struct bin_attribute bin_attr_rw_nvmem = { .attr = { -@@ -321,11 +358,21 @@ static const struct attribute_group nvme +@@ -320,11 +357,21 @@ static const struct attribute_group nvme .is_bin_visible = nvmem_bin_attr_is_visible, }; @@ -111,7 +111,7 @@ Signed-off-by: Greg Kroah-Hartman static struct bin_attribute bin_attr_nvmem_eeprom_compat = { .attr = { .name = "eeprom", -@@ -381,6 +428,68 @@ static void nvmem_sysfs_remove_compat(st +@@ -380,6 +427,68 @@ static void nvmem_sysfs_remove_compat(st device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); } @@ -180,7 +180,7 @@ Signed-off-by: Greg Kroah-Hartman #else /* CONFIG_NVMEM_SYSFS */ static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem, -@@ -740,11 +849,25 @@ static int nvmem_add_cells_from_fixed_la +@@ -739,11 +848,25 @@ static int nvmem_add_cells_from_fixed_la int nvmem_layout_register(struct nvmem_layout *layout) { @@ -207,7 +207,7 @@ Signed-off-by: Greg Kroah-Hartman } EXPORT_SYMBOL_GPL(nvmem_layout_register); -@@ -903,10 +1026,20 @@ struct nvmem_device *nvmem_register(cons +@@ -902,10 +1025,20 @@ struct nvmem_device *nvmem_register(cons if (rval) goto err_remove_dev; diff --git a/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch index 1bf3ba35b6..400004c617 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -44,7 +44,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l +@@ -854,7 +854,7 @@ int nvmem_layout_register(struct nvmem_l return -EINVAL; /* Populate the cells */ diff --git a/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch index 514b5f2de5..510f3dd841 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -24,7 +24,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme +@@ -876,19 +876,6 @@ void nvmem_layout_unregister(struct nvme } EXPORT_SYMBOL_GPL(nvmem_layout_unregister); diff --git a/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch index aa0bbaa0c5..ccdcc09736 100644 --- a/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch +++ b/target/linux/generic/backport-6.6/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -21,7 +21,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c -@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ +@@ -2163,6 +2163,19 @@ const char *nvmem_dev_name(struct nvmem_ } EXPORT_SYMBOL_GPL(nvmem_dev_name); diff --git a/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch b/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch index 2969462838..fa2056b69a 100644 --- a/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch +++ b/target/linux/generic/backport-6.6/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch @@ -16,7 +16,7 @@ Signed-off-by: Linus Walleij --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -72,9 +72,9 @@ config SFP +@@ -69,9 +69,9 @@ config SFP comment "MII PHY device drivers" config AMD_PHY diff --git a/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch b/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch index 1c8e014a1a..2ae209f9e1 100644 --- a/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch +++ b/target/linux/generic/backport-6.6/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch @@ -35,7 +35,7 @@ Signed-off-by: Lee Jones if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && trigger_data->duplex == DUPLEX_HALF) blink_on = true; -@@ -286,6 +298,9 @@ static ssize_t netdev_led_attr_show(stru +@@ -289,6 +301,9 @@ static ssize_t netdev_led_attr_show(stru case TRIGGER_NETDEV_LINK_10: case TRIGGER_NETDEV_LINK_100: case TRIGGER_NETDEV_LINK_1000: @@ -45,7 +45,7 @@ Signed-off-by: Lee Jones case TRIGGER_NETDEV_HALF_DUPLEX: case TRIGGER_NETDEV_FULL_DUPLEX: case TRIGGER_NETDEV_TX: -@@ -316,6 +331,9 @@ static ssize_t netdev_led_attr_store(str +@@ -319,6 +334,9 @@ static ssize_t netdev_led_attr_store(str case TRIGGER_NETDEV_LINK_10: case TRIGGER_NETDEV_LINK_100: case TRIGGER_NETDEV_LINK_1000: @@ -55,7 +55,7 @@ Signed-off-by: Lee Jones case TRIGGER_NETDEV_HALF_DUPLEX: case TRIGGER_NETDEV_FULL_DUPLEX: case TRIGGER_NETDEV_TX: -@@ -334,7 +352,10 @@ static ssize_t netdev_led_attr_store(str +@@ -337,7 +355,10 @@ static ssize_t netdev_led_attr_store(str if (test_bit(TRIGGER_NETDEV_LINK, &mode) && (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || test_bit(TRIGGER_NETDEV_LINK_100, &mode) || @@ -67,7 +67,7 @@ Signed-off-by: Lee Jones return -EINVAL; cancel_delayed_work_sync(&trigger_data->work); -@@ -364,6 +385,9 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD +@@ -367,6 +388,9 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); @@ -77,7 +77,7 @@ Signed-off-by: Lee Jones DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); -@@ -422,6 +446,9 @@ static struct attribute *netdev_trig_att +@@ -425,6 +449,9 @@ static struct attribute *netdev_trig_att &dev_attr_link_10.attr, &dev_attr_link_100.attr, &dev_attr_link_1000.attr, @@ -87,7 +87,7 @@ Signed-off-by: Lee Jones &dev_attr_full_duplex.attr, &dev_attr_half_duplex.attr, &dev_attr_rx.attr, -@@ -519,6 +546,9 @@ static void netdev_trig_work(struct work +@@ -522,6 +549,9 @@ static void netdev_trig_work(struct work test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || @@ -99,7 +99,7 @@ Signed-off-by: Lee Jones interval = jiffies_to_msecs( --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -533,6 +533,9 @@ enum led_trigger_netdev_modes { +@@ -588,6 +588,9 @@ enum led_trigger_netdev_modes { TRIGGER_NETDEV_LINK_10, TRIGGER_NETDEV_LINK_100, TRIGGER_NETDEV_LINK_1000, diff --git a/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch index 0182e6d1a2..30390299c8 100644 --- a/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch +++ b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch @@ -28,7 +28,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -3138,6 +3138,7 @@ static int of_phy_led(struct phy_device +@@ -3198,6 +3198,7 @@ static int of_phy_led(struct phy_device struct device *dev = &phydev->mdio.dev; struct led_init_data init_data = {}; struct led_classdev *cdev; @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski struct phy_led *phyled; u32 index; int err; -@@ -3155,6 +3156,21 @@ static int of_phy_led(struct phy_device +@@ -3215,6 +3216,21 @@ static int of_phy_led(struct phy_device if (index > U8_MAX) return -EINVAL; @@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski cdev->brightness_set_blocking = phy_led_set_brightness; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -791,6 +791,15 @@ struct phy_led { +@@ -870,6 +870,15 @@ struct phy_led { #define to_phy_led(d) container_of(d, struct phy_led, led_cdev) @@ -76,7 +76,7 @@ Signed-off-by: Jakub Kicinski /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -1059,6 +1068,19 @@ struct phy_driver { +@@ -1146,6 +1155,19 @@ struct phy_driver { int (*led_hw_control_get)(struct phy_device *dev, u8 index, unsigned long *rules); diff --git a/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch index 5094a6d774..9c61ff27ab 100644 --- a/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch +++ b/target/linux/generic/backport-6.6/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -103,7 +103,7 @@ Signed-off-by: Justin Stitt --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h -@@ -843,4 +843,17 @@ int ethtool_get_phc_vclocks(struct net_d +@@ -1052,4 +1052,17 @@ static inline int ethtool_mm_frag_size_m * next string. */ extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); @@ -123,7 +123,7 @@ Signed-off-by: Justin Stitt #endif /* _LINUX_ETHTOOL_H */ --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c -@@ -1974,6 +1974,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * +@@ -1991,6 +1991,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * } EXPORT_SYMBOL(ethtool_sprintf); From 293caa16a0c92b9aff367012124472f5b69aa577 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 8 Mar 2024 22:04:14 +0800 Subject: [PATCH 047/108] generic: 6.6: refresh pending patches Refresh pending patches with make target/linux/refresh. Signed-off-by: Weijie Gao --- ...include-asm-rwonce.h-for-kernel-code.patch | 2 +- .../103-kbuild-export-SUBARCH.patch | 2 +- ..._wdt-Add-support-for-specifying-WDI-.patch | 8 ++-- ...ge_allow_receiption_on_disabled_port.patch | 4 +- ...he_alarm_to_be_used_as_wakeup_source.patch | 2 +- .../203-kallsyms_uncompressed.patch | 12 +++--- .../205-backtrace_module_info.patch | 4 +- .../270-platform-mikrotik-build-bits.patch | 2 +- .../300-mips_expose_boot_raw.patch | 4 +- ...rriers-between-dcache-icache-flushes.patch | 8 ++-- .../pending-6.6/308-mips32r2_tune.patch | 2 +- .../332-arc-add-OWRTDTB-section.patch | 4 +- ...ernel-XZ-compression-option-on-PPC_8.patch | 2 +- .../400-mtd-mtdsplit-support.patch | 8 ++-- ...er-NVMEM-devices-for-partitions-with.patch | 2 +- ...support-for-minor-aligned-partitions.patch | 18 ++++---- ...e-notifier-to-create-ubiblock-from-p.patch | 12 +++--- ...0-04-mtd-ubi-attach-from-device-tree.patch | 12 +++--- ...e-pre-removal-notification-for-UBI-v.patch | 18 ++++---- ...-09-block-partitions-populate-fwnode.patch | 4 +- ...ck-add-new-genhd-flag-GENHD_FL_NVMEM.patch | 2 +- ...50-11-block-implement-NVMEM-provider.patch | 4 +- ...0-13-mmc-core-set-card-fwnode_handle.patch | 2 +- ...mmc-block-set-fwnode-of-disk-devices.patch | 4 +- .../450-15-mmc-block-set-GENHD_FL_NVMEM.patch | 2 +- ...mtd-cfi_cmdset_0002-no-erase_suspend.patch | 2 +- ...et_0002-add-buffer-write-cmd-timeout.patch | 2 +- ...25p80-mx-disable-software-protection.patch | 2 +- .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 4 +- ...mtd-device-named-ubi-or-data-on-boot.patch | 4 +- ...to-create-ubiblock-device-for-rootfs.patch | 6 +-- ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 4 +- ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 4 +- ...i-nor-disable-16-bit-sr-for-macronix.patch | 2 +- ...add-uImage.FIT-subimage-block-driver.patch | 4 +- ...ass-device-lookup-for-dev-fit-rootfs.patch | 2 +- .../530-jffs2_make_lzma_available.patch | 8 ++-- .../600-netfilter_conntrack_flush.patch | 4 +- ...etfilter_match_bypass_default_checks.patch | 12 +++--- ...netfilter_match_bypass_default_table.patch | 6 +-- ...netfilter_match_reduce_memory_access.patch | 2 +- .../pending-6.6/630-packet_socket_type.patch | 20 ++++----- .../pending-6.6/655-increase_skb_pad.patch | 2 +- ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 22 +++++----- ...ng-with-source-address-failed-policy.patch | 24 +++++------ ...T-skip-GRO-for-foreign-MAC-addresses.patch | 14 +++---- ...83-of_net-add-mac-address-to-of-tree.patch | 4 +- ...ow_offload-handle-netdevice-events-f.patch | 8 ++-- ...les-ignore-EOPNOTSUPP-on-flowtable-d.patch | 2 +- ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 4 +- ...a-tag_mtk-add-padding-for-tx-packets.patch | 2 +- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 22 +++++----- ...-qca8k-implement-lag_fdb_add-del-ops.patch | 2 +- ...a8k-enable-flooding-to-both-CPU-port.patch | 2 +- ...k-add-support-for-port_change_master.patch | 4 +- ...enable-assisted-learning-on-CPU-port.patch | 6 +-- ...pq8074-add-clock-frequency-to-MDIO-n.patch | 2 +- ...rtl8221-allow-to-configure-SERDES-mo.patch | 8 ++-- ...support-switching-between-SGMII-and-.patch | 4 +- ...e-all-MACs-are-powered-down-before-r.patch | 2 +- ...-use-genphy_soft_reset-for-2.5G-PHYs.patch | 12 +++--- ...sable-SGMII-in-band-AN-for-2-5G-PHYs.patch | 4 +- ...make-sure-paged-read-is-protected-by.patch | 2 +- ...use-inline-functions-for-10GbE-adver.patch | 6 +-- ...check-validity-of-10GbE-link-partner.patch | 2 +- ...-phy-realtek-introduce-rtl822x_probe.patch | 12 +++--- ...tek-detect-early-version-of-RTL8221B.patch | 4 +- ...0211_ptr-even-with-no-CFG82111-suppo.patch | 4 +- ..._eth_soc-work-around-issue-with-send.patch | 8 ++-- ..._eth_soc-add-paths-and-SerDes-modes-.patch | 42 +++++++++---------- ...lynxi-add-platform-driver-for-MT7988.patch | 12 +++--- ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 6 +-- ...ealtek-support-interrupt-of-RTL8221B.patch | 4 +- ...ha-Add-the-Airoha-EN8811H-PHY-driver.patch | 4 +- ...ional-threading-for-backlog-processi.patch | 28 ++++++------- ...equest-assisted-learning-on-CPU-port.patch | 2 +- ...-t-learn-non-unicast-L2-destinations.patch | 2 +- ...gister-OF-node-for-internal-MDIO-bus.patch | 4 +- ...ice-struct-copy-its-DMA-params-to-th.patch | 2 +- ...pio-cascade-add-generic-GPIO-cascade.patch | 4 +- ...e-old-opp-to-config_clks-on-_set_opp.patch | 12 +++--- ...-support-mac-base-fixed-layout-cells.patch | 4 +- .../810-pci_disable_common_quirks.patch | 10 ++--- .../811-pci_disable_usb_common_quirks.patch | 8 ++-- .../pending-6.6/834-ledtrig-libata.patch | 12 +++--- ...40-hwrng-bcm2835-set-quality-to-1000.patch | 2 +- .../pending-6.6/920-mangle_bootargs.patch | 6 +-- 88 files changed, 293 insertions(+), 293 deletions(-) diff --git a/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch index 7b342e6962..0844fcd6db 100644 --- a/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch +++ b/target/linux/generic/pending-6.6/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/compiler.h +++ b/include/linux/compiler.h -@@ -203,6 +203,8 @@ void ftrace_likely_update(struct ftrace_ +@@ -202,6 +202,8 @@ void ftrace_likely_update(struct ftrace_ __v; \ }) diff --git a/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch index c8c0efaecf..ea7a25d8a0 100644 --- a/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/pending-6.6/103-kbuild-export-SUBARCH.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -605,7 +605,7 @@ endif +@@ -599,7 +599,7 @@ endif # Allows the usage of unstable features in stable compilers. export RUSTC_BOOTSTRAP := 1 diff --git a/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch b/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch index d6b10491f8..9dd90eecdc 100644 --- a/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch +++ b/target/linux/generic/pending-6.6/111-watchdog-max63xx_wdt-Add-support-for-specifying-WDI-.patch @@ -17,7 +17,7 @@ Signed-off-by: Pali Rohár --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c -@@ -27,6 +27,7 @@ +@@ -24,6 +24,7 @@ #include #include #include @@ -25,7 +25,7 @@ Signed-off-by: Pali Rohár #define DEFAULT_HEARTBEAT 60 #define MAX_HEARTBEAT 60 -@@ -53,6 +54,9 @@ struct max63xx_wdt { +@@ -50,6 +51,9 @@ struct max63xx_wdt { void __iomem *base; spinlock_t lock; @@ -35,7 +35,7 @@ Signed-off-by: Pali Rohár /* WDI and WSET bits write access routines */ void (*ping)(struct max63xx_wdt *wdt); void (*set)(struct max63xx_wdt *wdt, u8 set); -@@ -158,6 +162,17 @@ static const struct watchdog_info max63x +@@ -155,6 +159,17 @@ static const struct watchdog_info max63x .identity = "max63xx Watchdog", }; @@ -53,7 +53,7 @@ Signed-off-by: Pali Rohár static void max63xx_mmap_ping(struct max63xx_wdt *wdt) { u8 val; -@@ -225,10 +240,19 @@ static int max63xx_wdt_probe(struct plat +@@ -222,10 +237,19 @@ static int max63xx_wdt_probe(struct plat return -EINVAL; } diff --git a/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch index 93a2d146b5..b23cae1f5e 100644 --- a/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch +++ b/target/linux/generic/pending-6.6/150-bridge_allow_receiption_on_disabled_port.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -222,6 +222,9 @@ static void __br_handle_local_finish(str +@@ -239,6 +239,9 @@ static void __br_handle_local_finish(str /* note: already called with rcu_read_lock */ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau __br_handle_local_finish(skb); /* return 1 to signal the okfn() was called so it's ok to use the skb */ -@@ -390,6 +393,17 @@ forward: +@@ -408,6 +411,17 @@ forward: goto defer_stp_filtering; switch (p->state) { diff --git a/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch index 85e5600847..a29c548bbd 100644 --- a/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch +++ b/target/linux/generic/pending-6.6/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch @@ -17,7 +17,7 @@ Signed-off-by: Daniel González Cabanelas --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c -@@ -833,6 +833,7 @@ static int rs5c372_probe(struct i2c_clie +@@ -832,6 +832,7 @@ static int rs5c372_probe(struct i2c_clie int err = 0; int smbus_mode = 0; struct rs5c372 *rs5c372; diff --git a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch index 5c6f620749..d935077c05 100644 --- a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch +++ b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/init/Kconfig +++ b/init/Kconfig -@@ -1491,6 +1491,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW +@@ -1451,6 +1451,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW the unaligned access emulation. see arch/parisc/kernel/unaligned.c for reference @@ -57,7 +57,7 @@ Signed-off-by: Felix Fietkau * and return the first char from this token. --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c -@@ -77,6 +77,7 @@ static struct addr_range percpu_range = +@@ -62,6 +62,7 @@ static struct addr_range percpu_range = static struct sym_entry **table; static unsigned int table_size, table_cnt; static int all_symbols; @@ -65,7 +65,7 @@ Signed-off-by: Felix Fietkau static int absolute_percpu; static int base_relative; static int lto_clang; -@@ -608,6 +609,9 @@ static void write_src(void) +@@ -469,6 +470,9 @@ static void write_src(void) free(markers); @@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau output_label("kallsyms_token_table"); off = 0; for (i = 0; i < 256; i++) { -@@ -659,6 +663,9 @@ static unsigned char *find_token(unsigne +@@ -582,6 +586,9 @@ static unsigned char *find_token(unsigne { int i; @@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau for (i = 0; i < len - 1; i++) { if (str[i] == token[0] && str[i+1] == token[1]) return &str[i]; -@@ -731,6 +738,9 @@ static void optimize_result(void) +@@ -654,6 +661,9 @@ static void optimize_result(void) { int i, best; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau /* using the '\0' symbol last allows compress_symbols to use standard * fast string functions */ for (i = 255; i >= 0; i--) { -@@ -892,6 +902,7 @@ int main(int argc, char **argv) +@@ -815,6 +825,7 @@ int main(int argc, char **argv) {"absolute-percpu", no_argument, &absolute_percpu, 1}, {"base-relative", no_argument, &base_relative, 1}, {"lto-clang", no_argument, <o_clang, 1}, diff --git a/target/linux/generic/pending-6.6/205-backtrace_module_info.patch b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch index 7bbb596a5d..34018e2c2f 100644 --- a/target/linux/generic/pending-6.6/205-backtrace_module_info.patch +++ b/target/linux/generic/pending-6.6/205-backtrace_module_info.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/lib/vsprintf.c +++ b/lib/vsprintf.c -@@ -985,8 +985,10 @@ char *symbol_string(char *buf, char *end +@@ -982,8 +982,10 @@ char *symbol_string(char *buf, char *end struct printf_spec spec, const char *fmt) { unsigned long value; @@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau #endif if (fmt[1] == 'R') -@@ -1007,8 +1009,14 @@ char *symbol_string(char *buf, char *end +@@ -1004,8 +1006,14 @@ char *symbol_string(char *buf, char *end return string_nocheck(buf, end, sym, spec); #else diff --git a/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch index 997e6142a7..7ca84e040d 100644 --- a/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch +++ b/target/linux/generic/pending-6.6/270-platform-mikrotik-build-bits.patch @@ -16,7 +16,7 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig -@@ -16,3 +16,5 @@ source "drivers/platform/olpc/Kconfig" +@@ -14,3 +14,5 @@ source "drivers/platform/olpc/Kconfig" source "drivers/platform/surface/Kconfig" source "drivers/platform/x86/Kconfig" diff --git a/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch b/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch index d222ec060e..ebeeb7bae7 100644 --- a/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch +++ b/target/linux/generic/pending-6.6/300-mips_expose_boot_raw.patch @@ -9,7 +9,7 @@ Acked-by: Rob Landley --- --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1035,9 +1035,6 @@ config FW_ARC +@@ -1013,9 +1013,6 @@ config FW_ARC config ARCH_MAY_HAVE_PC_FDC bool @@ -19,7 +19,7 @@ Acked-by: Rob Landley config CEVT_BCM1480 bool -@@ -3093,6 +3090,18 @@ choice +@@ -2996,6 +2993,18 @@ choice bool "Extend builtin kernel arguments with bootloader arguments" endchoice diff --git a/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch b/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch index bd56adad3a..b3cb5f0cde 100644 --- a/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch +++ b/target/linux/generic/pending-6.6/301-MIPS-Add-barriers-between-dcache-icache-flushes.patch @@ -26,7 +26,7 @@ Cc: James Hogan --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c -@@ -514,6 +514,7 @@ static inline void local_r4k___flush_cac +@@ -403,6 +403,7 @@ static inline void local_r4k___flush_cac default: r4k_blast_dcache(); @@ -34,7 +34,7 @@ Cc: James Hogan r4k_blast_icache(); break; } -@@ -594,8 +595,10 @@ static inline void local_r4k_flush_cache +@@ -483,8 +484,10 @@ static inline void local_r4k_flush_cache if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) r4k_blast_dcache(); /* If executable, blast stale lines from icache */ @@ -46,7 +46,7 @@ Cc: James Hogan } static void r4k_flush_cache_range(struct vm_area_struct *vma, -@@ -696,8 +699,13 @@ static inline void local_r4k_flush_cache +@@ -586,8 +589,13 @@ static inline void local_r4k_flush_cache if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { vaddr ? r4k_blast_dcache_page(addr) : r4k_blast_dcache_user_page(addr); @@ -61,7 +61,7 @@ Cc: James Hogan } if (exec) { if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) { -@@ -764,6 +772,7 @@ static inline void __local_r4k_flush_ica +@@ -654,6 +662,7 @@ static inline void __local_r4k_flush_ica else blast_dcache_range(start, end); } diff --git a/target/linux/generic/pending-6.6/308-mips32r2_tune.patch b/target/linux/generic/pending-6.6/308-mips32r2_tune.patch index db410a6bc0..b12058053b 100644 --- a/target/linux/generic/pending-6.6/308-mips32r2_tune.patch +++ b/target/linux/generic/pending-6.6/308-mips32r2_tune.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/arch/mips/Makefile +++ b/arch/mips/Makefile -@@ -172,7 +172,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43 +@@ -163,7 +163,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43 cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap diff --git a/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch index 4a76e216d5..5b943f3734 100644 --- a/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch +++ b/target/linux/generic/pending-6.6/332-arc-add-OWRTDTB-section.patch @@ -42,7 +42,7 @@ Signed-off-by: Evgeniy Didin ;---------------------------------------------------------------- --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c -@@ -495,6 +495,8 @@ static inline bool uboot_arg_invalid(uns +@@ -450,6 +450,8 @@ static inline bool uboot_arg_invalid(uns /* We always pass 0 as magic from U-boot */ #define UBOOT_MAGIC_VALUE 0 @@ -51,7 +51,7 @@ Signed-off-by: Evgeniy Didin void __init handle_uboot_args(void) { bool use_embedded_dtb = true; -@@ -533,7 +535,7 @@ void __init handle_uboot_args(void) +@@ -488,7 +490,7 @@ void __init handle_uboot_args(void) ignore_uboot_args: if (use_embedded_dtb) { diff --git a/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch index e9b47d185d..71173b081c 100644 --- a/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch +++ b/target/linux/generic/pending-6.6/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch @@ -14,7 +14,7 @@ Signed-off-by: Pawel Dembicki --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig -@@ -229,7 +229,7 @@ config PPC +@@ -251,7 +251,7 @@ config PPC select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE select HAVE_KERNEL_LZO if DEFAULT_UIMAGE diff --git a/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch index c619d12ce5..bd1c3a123f 100644 --- a/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch +++ b/target/linux/generic/pending-6.6/400-mtd-mtdsplit-support.patch @@ -66,7 +66,7 @@ Subject: [PATCH] mtd: mtdsplit support /* * MTD methods which simply translate the effective address and pass through -@@ -236,6 +238,147 @@ static int mtd_add_partition_attrs(struc +@@ -242,6 +244,147 @@ static int mtd_add_partition_attrs(struc return ret; } @@ -214,7 +214,7 @@ Subject: [PATCH] mtd: mtdsplit support int mtd_add_partition(struct mtd_info *parent, const char *name, long long offset, long long length) { -@@ -274,6 +417,7 @@ int mtd_add_partition(struct mtd_info *p +@@ -280,6 +423,7 @@ int mtd_add_partition(struct mtd_info *p if (ret) goto err_remove_part; @@ -222,7 +222,7 @@ Subject: [PATCH] mtd: mtdsplit support mtd_add_partition_attrs(child); return 0; -@@ -422,6 +566,7 @@ int add_mtd_partitions(struct mtd_info * +@@ -423,6 +567,7 @@ int add_mtd_partitions(struct mtd_info * goto err_del_partitions; } @@ -230,7 +230,7 @@ Subject: [PATCH] mtd: mtdsplit support mtd_add_partition_attrs(child); /* Look for subpartitions */ -@@ -438,31 +583,6 @@ err_del_partitions: +@@ -439,31 +584,6 @@ err_del_partitions: return ret; } diff --git a/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch index 52acb0633b..54a02d8ecd 100644 --- a/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch +++ b/target/linux/generic/pending-6.6/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch @@ -16,7 +16,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -519,6 +519,29 @@ static int mtd_nvmem_add(struct mtd_info +@@ -548,6 +548,29 @@ static int mtd_nvmem_add(struct mtd_info struct device_node *node = mtd_get_of_node(mtd); struct nvmem_config config = {}; diff --git a/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch index c7da2f8834..5a812b86bf 100644 --- a/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch +++ b/target/linux/generic/pending-6.6/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -80,7 +80,7 @@ Reported-by: Dan Carpenter --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -169,6 +169,15 @@ static ssize_t mtd_erasesize_show(struct +@@ -198,6 +198,15 @@ static ssize_t mtd_erasesize_show(struct } MTD_DEVICE_ATTR_RO(erasesize); @@ -96,7 +96,7 @@ Reported-by: Dan Carpenter static ssize_t mtd_writesize_show(struct device *dev, struct device_attribute *attr, char *buf) { -@@ -314,6 +323,7 @@ static struct attribute *mtd_attrs[] = { +@@ -343,6 +352,7 @@ static struct attribute *mtd_attrs[] = { &dev_attr_flags.attr, &dev_attr_size.attr, &dev_attr_erasesize.attr, @@ -106,7 +106,7 @@ Reported-by: Dan Carpenter &dev_attr_oobsize.attr, --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -41,6 +41,7 @@ static struct mtd_info *allocate_partiti +@@ -47,6 +47,7 @@ static struct mtd_info *allocate_partiti struct mtd_info *master = mtd_get_master(parent); int wr_alignment = (parent->flags & MTD_NO_ERASE) ? master->writesize : master->erasesize; @@ -114,7 +114,7 @@ Reported-by: Dan Carpenter u64 parent_size = mtd_is_partition(parent) ? parent->part.size : parent->size; struct mtd_info *child; -@@ -165,6 +166,7 @@ static struct mtd_info *allocate_partiti +@@ -171,6 +172,7 @@ static struct mtd_info *allocate_partiti } else { /* Single erase size */ child->erasesize = master->erasesize; @@ -122,7 +122,7 @@ Reported-by: Dan Carpenter } /* -@@ -172,26 +174,39 @@ static struct mtd_info *allocate_partiti +@@ -178,26 +180,39 @@ static struct mtd_info *allocate_partiti * exposes several regions with different erasesize. Adjust * wr_alignment accordingly. */ @@ -193,7 +193,7 @@ Reported-by: Dan Carpenter default y --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -1050,6 +1050,8 @@ static u8 spi_nor_convert_3to4_erase(u8 +@@ -1150,6 +1150,8 @@ static u8 spi_nor_convert_3to4_erase(u8 static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) { @@ -202,7 +202,7 @@ Reported-by: Dan Carpenter return !!nor->params->erase_map.uniform_erase_type; } -@@ -2158,6 +2160,7 @@ static int spi_nor_select_erase(struct s +@@ -2582,6 +2584,7 @@ static int spi_nor_select_erase(struct s { struct spi_nor_erase_map *map = &nor->params->erase_map; const struct spi_nor_erase_type *erase = NULL; @@ -210,7 +210,7 @@ Reported-by: Dan Carpenter struct mtd_info *mtd = &nor->mtd; u32 wanted_size = nor->info->sector_size; int i; -@@ -2190,8 +2193,9 @@ static int spi_nor_select_erase(struct s +@@ -2614,8 +2617,9 @@ static int spi_nor_select_erase(struct s */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { if (map->erase_type[i].size) { @@ -222,7 +222,7 @@ Reported-by: Dan Carpenter } } -@@ -2199,6 +2203,9 @@ static int spi_nor_select_erase(struct s +@@ -2623,6 +2627,9 @@ static int spi_nor_select_erase(struct s return -EINVAL; mtd->erasesize = erase->size; diff --git a/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch index 421daa0125..a1e1d6fa9d 100644 --- a/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch +++ b/target/linux/generic/pending-6.6/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch @@ -26,7 +26,7 @@ Signed-off-by: Daniel Golle #include #include #include -@@ -67,10 +68,10 @@ struct ubiblock_pdu { +@@ -65,10 +66,10 @@ struct ubiblock_pdu { }; /* Numbers of elements set in the @ubiblock_param array */ @@ -39,7 +39,7 @@ Signed-off-by: Daniel Golle struct ubiblock { struct ubi_volume_desc *desc; -@@ -504,7 +505,7 @@ int ubiblock_remove(struct ubi_volume_in +@@ -469,7 +470,7 @@ int ubiblock_remove(struct ubi_volume_in } /* Found a device, let's lock it so we can check if it's busy */ @@ -48,7 +48,7 @@ Signed-off-by: Daniel Golle if (dev->refcnt > 0) { ret = -EBUSY; goto out_unlock_dev; -@@ -567,6 +568,85 @@ static int ubiblock_resize(struct ubi_vo +@@ -532,6 +533,85 @@ static int ubiblock_resize(struct ubi_vo return 0; } @@ -134,7 +134,7 @@ Signed-off-by: Daniel Golle static int ubiblock_notify(struct notifier_block *nb, unsigned long notification_type, void *ns_ptr) { -@@ -574,10 +654,7 @@ static int ubiblock_notify(struct notifi +@@ -539,10 +619,7 @@ static int ubiblock_notify(struct notifi switch (notification_type) { case UBI_VOLUME_ADDED: @@ -146,7 +146,7 @@ Signed-off-by: Daniel Golle break; case UBI_VOLUME_REMOVED: ubiblock_remove(&nt->vi); -@@ -603,56 +680,6 @@ static struct notifier_block ubiblock_no +@@ -568,56 +645,6 @@ static struct notifier_block ubiblock_no .notifier_call = ubiblock_notify, }; @@ -203,7 +203,7 @@ Signed-off-by: Daniel Golle static void ubiblock_remove_all(void) { struct ubiblock *next; -@@ -678,18 +705,7 @@ int __init ubiblock_init(void) +@@ -643,18 +670,7 @@ int __init ubiblock_init(void) if (ubiblock_major < 0) return ubiblock_major; diff --git a/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch b/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch index 6e10e5ebed..a295146aee 100644 --- a/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch +++ b/target/linux/generic/pending-6.6/450-04-mtd-ubi-attach-from-device-tree.patch @@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle #include #include #include "ubi.h" -@@ -1071,6 +1072,7 @@ out_free: +@@ -1072,6 +1073,7 @@ out_free: * ubi_detach_mtd_dev - detach an MTD device. * @ubi_num: UBI device number to detach from * @anyway: detach MTD even if device reference count is not zero @@ -33,7 +33,7 @@ Signed-off-by: Daniel Golle * * This function destroys an UBI device number @ubi_num and detaches the * underlying MTD device. Returns zero in case of success and %-EBUSY if the -@@ -1080,7 +1082,7 @@ out_free: +@@ -1081,7 +1083,7 @@ out_free: * Note, the invocations of this function has to be serialized by the * @ubi_devices_mutex. */ @@ -42,7 +42,7 @@ Signed-off-by: Daniel Golle { struct ubi_device *ubi; -@@ -1136,7 +1138,11 @@ int ubi_detach_mtd_dev(int ubi_num, int +@@ -1137,7 +1139,11 @@ int ubi_detach_mtd_dev(int ubi_num, int vfree(ubi->peb_buf); vfree(ubi->fm_buf); ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index); @@ -55,7 +55,7 @@ Signed-off-by: Daniel Golle put_device(&ubi->dev); return 0; } -@@ -1213,43 +1219,43 @@ static struct mtd_info * __init open_mtd +@@ -1214,43 +1220,43 @@ static struct mtd_info * __init open_mtd return mtd; } @@ -128,7 +128,7 @@ Signed-off-by: Daniel Golle /* Attach MTD devices */ for (i = 0; i < mtd_devs; i++) { -@@ -1297,25 +1303,79 @@ static int __init ubi_init(void) +@@ -1298,25 +1304,79 @@ static int __init ubi_init(void) } } @@ -217,7 +217,7 @@ Signed-off-by: Daniel Golle out_slab: kmem_cache_destroy(ubi_wl_entry_slab); out_dev_unreg: -@@ -1325,18 +1385,20 @@ out: +@@ -1326,18 +1386,20 @@ out: pr_err("UBI error: cannot initialize UBI, error %d\n", err); return err; } diff --git a/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch b/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch index d5da37b856..c7c058f8f4 100644 --- a/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch +++ b/target/linux/generic/pending-6.6/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -568,6 +568,29 @@ static int ubiblock_resize(struct ubi_vo +@@ -533,6 +533,29 @@ static int ubiblock_resize(struct ubi_vo return 0; } @@ -53,7 +53,7 @@ Signed-off-by: Daniel Golle static bool match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) { -@@ -659,6 +682,9 @@ static int ubiblock_notify(struct notifi +@@ -624,6 +647,9 @@ static int ubiblock_notify(struct notifi case UBI_VOLUME_REMOVED: ubiblock_remove(&nt->vi); break; @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle break; --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c -@@ -89,7 +89,7 @@ static struct ubi_device *ubi_devices[UB +@@ -91,7 +91,7 @@ static struct ubi_device *ubi_devices[UB /* Serializes UBI devices creations and removals */ DEFINE_MUTEX(ubi_devices_mutex); @@ -74,7 +74,7 @@ Signed-off-by: Daniel Golle static DEFINE_SPINLOCK(ubi_devices_lock); /* "Show" method for files in '//class/ubi/' */ -@@ -258,6 +258,9 @@ struct ubi_device *ubi_get_device(int ub +@@ -259,6 +259,9 @@ struct ubi_device *ubi_get_device(int ub spin_lock(&ubi_devices_lock); ubi = ubi_devices[ubi_num]; @@ -84,7 +84,7 @@ Signed-off-by: Daniel Golle if (ubi) { ubi_assert(ubi->ref_count >= 0); ubi->ref_count += 1; -@@ -295,7 +298,7 @@ struct ubi_device *ubi_get_by_major(int +@@ -296,7 +299,7 @@ struct ubi_device *ubi_get_by_major(int spin_lock(&ubi_devices_lock); for (i = 0; i < UBI_MAX_DEVICES; i++) { ubi = ubi_devices[i]; @@ -93,7 +93,7 @@ Signed-off-by: Daniel Golle ubi_assert(ubi->ref_count >= 0); ubi->ref_count += 1; get_device(&ubi->dev); -@@ -324,7 +327,7 @@ int ubi_major2num(int major) +@@ -325,7 +328,7 @@ int ubi_major2num(int major) for (i = 0; i < UBI_MAX_DEVICES; i++) { struct ubi_device *ubi = ubi_devices[i]; @@ -102,7 +102,7 @@ Signed-off-by: Daniel Golle ubi_num = ubi->ubi_num; break; } -@@ -511,7 +514,7 @@ static void ubi_free_volumes_from(struct +@@ -512,7 +515,7 @@ static void ubi_free_volumes_from(struct int i; for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { @@ -111,7 +111,7 @@ Signed-off-by: Daniel Golle continue; ubi_eba_replace_table(ubi->volumes[i], NULL); ubi_fastmap_destroy_checkmap(ubi->volumes[i]); -@@ -1094,10 +1097,10 @@ int ubi_detach_mtd_dev(int ubi_num, int +@@ -1095,10 +1098,10 @@ int ubi_detach_mtd_dev(int ubi_num, int return -EINVAL; spin_lock(&ubi_devices_lock); @@ -123,7 +123,7 @@ Signed-off-by: Daniel Golle spin_unlock(&ubi_devices_lock); return -EBUSY; } -@@ -1105,6 +1108,13 @@ int ubi_detach_mtd_dev(int ubi_num, int +@@ -1106,6 +1109,13 @@ int ubi_detach_mtd_dev(int ubi_num, int ubi_err(ubi, "%s reference count %d, destroy anyway", ubi->ubi_name, ubi->ref_count); } diff --git a/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch index b46044f5d9..2e5bcac653 100644 --- a/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch +++ b/target/linux/generic/pending-6.6/450-09-block-partitions-populate-fwnode.patch @@ -22,7 +22,7 @@ Signed-off-by: Daniel Golle #include "check.h" static int (*const check_part[])(struct parsed_partitions *) = { -@@ -298,6 +300,43 @@ static ssize_t whole_disk_show(struct de +@@ -292,6 +294,43 @@ static ssize_t whole_disk_show(struct de } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); @@ -66,7 +66,7 @@ Signed-off-by: Daniel Golle /* * Must be called either with open_mutex held, before a disk can be opened or * after all disk users are gone. -@@ -380,6 +419,8 @@ static struct block_device *add_partitio +@@ -374,6 +413,8 @@ static struct block_device *add_partitio goto out_put; } diff --git a/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch index 4cbec14f5c..8fc5cd636c 100644 --- a/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch +++ b/target/linux/generic/pending-6.6/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h -@@ -87,11 +87,13 @@ struct partition_meta_info { +@@ -80,11 +80,13 @@ struct partition_meta_info { * ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not * scan for partitions from add_disk, and users can't add partitions manually. * diff --git a/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch index d1972d97dc..d96477111c 100644 --- a/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch +++ b/target/linux/generic/pending-6.6/450-11-block-implement-NVMEM-provider.patch @@ -18,7 +18,7 @@ Signed-off-by: Daniel Golle --- a/block/Kconfig +++ b/block/Kconfig -@@ -203,6 +203,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK +@@ -208,6 +208,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK by falling back to the kernel crypto API when inline encryption hardware is not present. @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle config BLK_MQ_PCI --- a/block/Makefile +++ b/block/Makefile -@@ -35,6 +35,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned +@@ -34,6 +34,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned obj-$(CONFIG_BLK_WBT) += blk-wbt.o obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o diff --git a/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch index cfc43318ca..ff0d9c395c 100644 --- a/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch +++ b/target/linux/generic/pending-6.6/450-13-mmc-core-set-card-fwnode_handle.patch @@ -12,7 +12,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c -@@ -363,6 +363,8 @@ int mmc_add_card(struct mmc_card *card) +@@ -364,6 +364,8 @@ int mmc_add_card(struct mmc_card *card) mmc_add_card_debugfs(card); card->dev.of_node = mmc_of_find_child_device(card->host, 0); diff --git a/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch index e645855475..27875b8c2c 100644 --- a/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch +++ b/target/linux/generic/pending-6.6/450-14-mmc-block-set-fwnode-of-disk-devices.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -2484,6 +2484,8 @@ static struct mmc_blk_data *mmc_blk_allo +@@ -2461,6 +2461,8 @@ static struct mmc_blk_data *mmc_blk_allo int area_type, unsigned int part_type) { @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle struct mmc_blk_data *md; int devidx, ret; char cap_str[10]; -@@ -2580,6 +2582,13 @@ static struct mmc_blk_data *mmc_blk_allo +@@ -2557,6 +2559,13 @@ static struct mmc_blk_data *mmc_blk_allo blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled); diff --git a/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch index d76e7b2fe5..308910859b 100644 --- a/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch +++ b/target/linux/generic/pending-6.6/450-15-mmc-block-set-GENHD_FL_NVMEM.patch @@ -12,7 +12,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -2538,6 +2538,7 @@ static struct mmc_blk_data *mmc_blk_allo +@@ -2515,6 +2515,7 @@ static struct mmc_blk_data *mmc_blk_allo md->disk->major = MMC_BLOCK_MAJOR; md->disk->minors = perdev_minors; md->disk->first_minor = devidx * perdev_minors; diff --git a/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch index 1b653fb735..2435133fa0 100644 --- a/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch +++ b/target/linux/generic/pending-6.6/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -908,7 +908,7 @@ static int get_chip(struct map_info *map +@@ -906,7 +906,7 @@ static int get_chip(struct map_info *map return 0; case FL_ERASING: diff --git a/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch index f2788c5214..059d9673dc 100644 --- a/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch +++ b/target/linux/generic/pending-6.6/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch @@ -7,7 +7,7 @@ Signed-off-by: George Kashperko 1 file changed, 1 insertion(+) --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -2052,6 +2052,7 @@ static int __xipram do_write_buffer(stru +@@ -2050,6 +2050,7 @@ static int __xipram do_write_buffer(stru /* Write Buffer Load */ map_write(map, CMD(0x25), cmd_adr); diff --git a/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch index 0bed77b3b5..09a508b29e 100644 --- a/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch +++ b/target/linux/generic/pending-6.6/465-m25p80-mx-disable-software-protection.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c -@@ -115,6 +115,7 @@ static void macronix_nor_default_init(st +@@ -114,6 +114,7 @@ static int macronix_nor_late_init(struct { if (!nor->params->set_4byte_addr_mode) nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; diff --git a/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch index 371f1a7276..945f5baf10 100644 --- a/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch +++ b/target/linux/generic/pending-6.6/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau +}; --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -1636,6 +1636,7 @@ static const struct spi_nor_manufacturer +@@ -2017,6 +2017,7 @@ static const struct spi_nor_manufacturer &spi_nor_winbond, &spi_nor_xilinx, &spi_nor_xmc, @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau static const struct flash_info spi_nor_generic_flash = { --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h -@@ -633,6 +633,7 @@ extern const struct spi_nor_manufacturer +@@ -647,6 +647,7 @@ extern const struct spi_nor_manufacturer extern const struct spi_nor_manufacturer spi_nor_winbond; extern const struct spi_nor_manufacturer spi_nor_xilinx; extern const struct spi_nor_manufacturer spi_nor_xmc; diff --git a/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch index 2eccb9d3bb..5a897d5d6f 100644 --- a/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +++ b/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c -@@ -1263,6 +1263,74 @@ static struct mtd_notifier ubi_mtd_notif +@@ -1264,6 +1264,74 @@ static struct mtd_notifier ubi_mtd_notif .remove = ubi_notify_remove, }; @@ -83,7 +83,7 @@ Signed-off-by: Daniel Golle static int __init ubi_init_attach(void) { int err, i, k; -@@ -1313,6 +1381,12 @@ static int __init ubi_init_attach(void) +@@ -1314,6 +1382,12 @@ static int __init ubi_init_attach(void) } } diff --git a/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch index a43da2a572..e0134e876a 100644 --- a/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +++ b/target/linux/generic/pending-6.6/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -644,10 +644,47 @@ match_volume_desc(struct ubi_volume_info +@@ -609,10 +609,47 @@ match_volume_desc(struct ubi_volume_info return true; } @@ -56,7 +56,7 @@ Signed-off-by: Daniel Golle struct ubiblock_param *p; /* -@@ -660,6 +697,7 @@ ubiblock_create_from_param(struct ubi_vo +@@ -625,6 +662,7 @@ ubiblock_create_from_param(struct ubi_vo if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) continue; @@ -64,7 +64,7 @@ Signed-off-by: Daniel Golle ret = ubiblock_create(vi); if (ret) { pr_err( -@@ -668,6 +706,10 @@ ubiblock_create_from_param(struct ubi_vo +@@ -633,6 +671,10 @@ ubiblock_create_from_param(struct ubi_vo } break; } diff --git a/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch index b63b333c47..297789e539 100644 --- a/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +++ b/target/linux/generic/pending-6.6/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/init/do_mounts.c +++ b/init/do_mounts.c -@@ -446,7 +446,30 @@ retry: +@@ -248,7 +248,30 @@ retry: out: put_page(page); } @@ -40,7 +40,7 @@ Signed-off-by: Daniel Golle #ifdef CONFIG_ROOT_NFS #define NFSROOT_TIMEOUT_MIN 5 -@@ -408,6 +408,11 @@ void __init mount_root(void) +@@ -385,6 +408,11 @@ static inline void mount_block_root(char void __init mount_root(char *root_device_name) { diff --git a/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch index 16bdfdd4b5..788690088a 100644 --- a/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +++ b/target/linux/generic/pending-6.6/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -43,6 +43,7 @@ +@@ -42,6 +42,7 @@ #include #include #include @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle #include "ubi-media.h" #include "ubi.h" -@@ -460,6 +461,15 @@ int ubiblock_create(struct ubi_volume_in +@@ -429,6 +430,15 @@ int ubiblock_create(struct ubi_volume_in dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", dev->ubi_num, dev->vol_id, vi->name); mutex_unlock(&devices_mutex); diff --git a/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch index e69eaf6bcc..ea580a90a0 100644 --- a/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch +++ b/target/linux/generic/pending-6.6/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch @@ -20,7 +20,7 @@ Signed-off-by: Nick Hainke --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c -@@ -115,6 +115,7 @@ static void macronix_nor_default_init(st +@@ -115,6 +115,7 @@ static int macronix_nor_late_init(struct { if (!nor->params->set_4byte_addr_mode) nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b; diff --git a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch index 54234caf94..c565350dc0 100644 --- a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21052,6 +21052,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -22006,6 +22006,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ @@ -51,7 +51,7 @@ Signed-off-by: Daniel Golle L: linux-block@vger.kernel.org --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig -@@ -383,6 +383,18 @@ config VIRTIO_BLK +@@ -354,6 +354,18 @@ config VIRTIO_BLK This is the virtual block driver for virtio. It can be used with QEMU based VMMs (like KVM or Xen). Say Y or M. diff --git a/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch index e6ad104981..b2b7f5eb0c 100644 --- a/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch +++ b/target/linux/generic/pending-6.6/511-init-bypass-device-lookup-for-dev-fit-rootfs.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/init/do_mounts.c +++ b/init/do_mounts.c -@@ -463,7 +463,8 @@ static dev_t __init parse_root_device(char +@@ -463,7 +463,8 @@ static dev_t __init parse_root_device(ch int error; dev_t dev; diff --git a/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch index 3e93c61839..3be6c8eb9d 100644 --- a/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch +++ b/target/linux/generic/pending-6.6/530-jffs2_make_lzma_available.patch @@ -85,7 +85,7 @@ Signed-off-by: Alexandros C. Couloumbis exit_dynrubin: jffs2_dynrubin_exit(); exit_runinmips: -@@ -417,6 +422,7 @@ int __init jffs2_compressors_init(void) +@@ -417,6 +422,7 @@ exit: int jffs2_compressors_exit(void) { /* Unregistering compressors */ @@ -1097,7 +1097,7 @@ Signed-off-by: Alexandros C. Couloumbis #define JFFS2_NODE_ACCURATE 0x2000 --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -354,6 +354,12 @@ config ZSTD_DECOMPRESS +@@ -356,6 +356,12 @@ config ZSTD_DECOMPRESS source "lib/xz/Kconfig" @@ -1112,7 +1112,7 @@ Signed-off-by: Alexandros C. Couloumbis # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) --- a/lib/Makefile +++ b/lib/Makefile -@@ -140,6 +140,16 @@ CFLAGS_kobject.o += -DDEBUG +@@ -145,6 +145,16 @@ CFLAGS_kobject.o += -DDEBUG CFLAGS_kobject_uevent.o += -DDEBUG endif @@ -1129,7 +1129,7 @@ Signed-off-by: Alexandros C. Couloumbis obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any) -@@ -200,6 +210,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ +@@ -205,6 +215,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ obj-$(CONFIG_XZ_DEC) += xz/ obj-$(CONFIG_RAID6_PQ) += raid6/ diff --git a/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch index d7548c1419..f6c3783219 100644 --- a/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch +++ b/target/linux/generic/pending-6.6/600-netfilter_conntrack_flush.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau #include #ifdef CONFIG_SYSCTL #include -@@ -465,6 +466,58 @@ static int ct_cpu_seq_show(struct seq_fi +@@ -461,6 +462,58 @@ static int ct_cpu_seq_show(struct seq_fi return 0; } @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau static const struct seq_operations ct_cpu_seq_ops = { .start = ct_cpu_seq_start, .next = ct_cpu_seq_next, -@@ -478,8 +531,9 @@ static int nf_conntrack_standalone_init_ +@@ -474,8 +527,9 @@ static int nf_conntrack_standalone_init_ kuid_t root_uid; kgid_t root_gid; diff --git a/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch index 7e34ef3713..67dcf25a0d 100644 --- a/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch +++ b/target/linux/generic/pending-6.6/610-netfilter_match_bypass_default_checks.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c -@@ -50,6 +50,9 @@ ip_packet_match(const struct iphdr *ip, +@@ -48,6 +48,9 @@ ip_packet_match(const struct iphdr *ip, { unsigned long ret; @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau if (NF_INVF(ipinfo, IPT_INV_SRCIP, (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || NF_INVF(ipinfo, IPT_INV_DSTIP, -@@ -80,6 +83,29 @@ ip_packet_match(const struct iphdr *ip, +@@ -78,6 +81,29 @@ ip_packet_match(const struct iphdr *ip, return true; } @@ -59,7 +59,7 @@ Signed-off-by: Felix Fietkau static bool ip_checkentry(const struct ipt_ip *ip) { -@@ -525,6 +551,8 @@ find_check_entry(struct ipt_entry *e, st +@@ -523,6 +549,8 @@ find_check_entry(struct ipt_entry *e, st struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; @@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) return -ENOMEM; -@@ -819,6 +847,7 @@ copy_entries_to_user(unsigned int total_ +@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ const struct xt_table_info *private = table->private; int ret = 0; const void *loc_cpu_entry; @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau counters = alloc_counters(table); if (IS_ERR(counters)) -@@ -846,6 +875,14 @@ copy_entries_to_user(unsigned int total_ +@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ goto free_counters; } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau for (i = sizeof(struct ipt_entry); i < e->target_offset; i += m->u.match_size) { -@@ -1223,12 +1260,15 @@ compat_copy_entry_to_user(struct ipt_ent +@@ -1221,12 +1258,15 @@ compat_copy_entry_to_user(struct ipt_ent compat_uint_t origsize; const struct xt_entry_match *ematch; int ret = 0; diff --git a/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch index dd557fd3ea..9f0efe4ec4 100644 --- a/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch +++ b/target/linux/generic/pending-6.6/611-netfilter_match_bypass_default_table.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c -@@ -246,6 +246,33 @@ struct ipt_entry *ipt_next_entry(const s +@@ -244,6 +244,33 @@ struct ipt_entry *ipt_next_entry(const s return (void *)entry + entry->next_offset; } @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau /* Returns one of the generic firewall policies, like NF_ACCEPT. */ unsigned int ipt_do_table(void *priv, -@@ -267,27 +294,28 @@ ipt_do_table(void *priv, +@@ -265,27 +292,28 @@ ipt_do_table(void *priv, unsigned int addend; /* Initialization */ @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; /* Switch to alternate jumpstack if we're being invoked via TEE. -@@ -300,7 +328,16 @@ ipt_do_table(void *priv, +@@ -298,7 +326,16 @@ ipt_do_table(void *priv, if (static_key_false(&xt_tee_enabled)) jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); diff --git a/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch index 79da6778b6..7f291fc008 100644 --- a/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch +++ b/target/linux/generic/pending-6.6/612-netfilter_match_reduce_memory_access.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c -@@ -53,9 +53,9 @@ ip_packet_match(const struct iphdr *ip, +@@ -51,9 +51,9 @@ ip_packet_match(const struct iphdr *ip, if (ipinfo->flags & IPT_F_NO_DEF_MATCH) return true; diff --git a/target/linux/generic/pending-6.6/630-packet_socket_type.patch b/target/linux/generic/pending-6.6/630-packet_socket_type.patch index f12a09e65f..02d6700af9 100644 --- a/target/linux/generic/pending-6.6/630-packet_socket_type.patch +++ b/target/linux/generic/pending-6.6/630-packet_socket_type.patch @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau /* Packet socket options */ -@@ -59,6 +61,7 @@ struct sockaddr_ll { +@@ -60,6 +62,7 @@ struct sockaddr_ll { #define PACKET_FANOUT_DATA 22 #define PACKET_IGNORE_OUTGOING 23 #define PACKET_VNET_HDR_SZ 24 @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #define PACKET_FANOUT_LB 1 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c -@@ -1866,6 +1866,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1864,6 +1864,7 @@ static int packet_rcv_spkt(struct sk_buf { struct sock *sk; struct sockaddr_pkt *spkt; @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* * When we registered the protocol we saved the socket in the data -@@ -1873,6 +1874,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1871,6 +1872,7 @@ static int packet_rcv_spkt(struct sk_buf */ sk = pt->af_packet_priv; @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau /* * Yank back the headers [hope the device set this -@@ -1885,7 +1887,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1883,7 +1885,7 @@ static int packet_rcv_spkt(struct sk_buf * so that this procedure is noop. */ @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau goto out; if (!net_eq(dev_net(dev), sock_net(sk))) -@@ -2131,12 +2133,12 @@ static int packet_rcv(struct sk_buff *sk +@@ -2129,12 +2131,12 @@ static int packet_rcv(struct sk_buff *sk unsigned int snaplen, res; bool is_drop_n_account = false; @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -2263,12 +2265,12 @@ static int tpacket_rcv(struct sk_buff *s +@@ -2261,12 +2263,12 @@ static int tpacket_rcv(struct sk_buff *s BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); @@ -87,7 +87,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -3378,6 +3380,7 @@ static int packet_create(struct net *net +@@ -3386,6 +3388,7 @@ static int packet_create(struct net *net mutex_init(&po->pg_vec_lock); po->rollover = NULL; po->prot_hook.func = packet_rcv; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; -@@ -4013,6 +4016,16 @@ packet_setsockopt(struct socket *sock, i +@@ -4035,6 +4038,16 @@ packet_setsockopt(struct socket *sock, i packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val); return 0; } @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau default: return -ENOPROTOOPT; } -@@ -4069,6 +4082,13 @@ static int packet_getsockopt(struct sock +@@ -4094,6 +4107,13 @@ static int packet_getsockopt(struct sock case PACKET_VNET_HDR_SZ: val = READ_ONCE(po->vnet_hdr_sz); break; @@ -128,7 +128,7 @@ Signed-off-by: Felix Fietkau break; --- a/net/packet/internal.h +++ b/net/packet/internal.h -@@ -136,6 +136,7 @@ struct packet_sock { +@@ -131,6 +131,7 @@ struct packet_sock { struct net_device __rcu *cached_dev; struct packet_type prot_hook ____cacheline_aligned_in_smp; atomic_t tp_drops ____cacheline_aligned_in_smp; diff --git a/target/linux/generic/pending-6.6/655-increase_skb_pad.patch b/target/linux/generic/pending-6.6/655-increase_skb_pad.patch index 0c47bc9d2c..3e13511e8b 100644 --- a/target/linux/generic/pending-6.6/655-increase_skb_pad.patch +++ b/target/linux/generic/pending-6.6/655-increase_skb_pad.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -3006,7 +3006,7 @@ static inline int pskb_network_may_pull( +@@ -3041,7 +3041,7 @@ static inline int pskb_network_may_pull( * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD diff --git a/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index b799c6fc9c..06126d65d3 100644 --- a/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/pending-6.6/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -311,7 +311,7 @@ Signed-off-by: Steven Barth /** * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device -@@ -1293,6 +1441,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1292,6 +1440,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str u8 protocol) { struct ip6_tnl *t = netdev_priv(dev); @@ -319,7 +319,7 @@ Signed-off-by: Steven Barth struct ipv6hdr *ipv6h; const struct iphdr *iph; int encap_limit = -1; -@@ -1392,6 +1541,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1391,6 +1540,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield); @@ -338,7 +338,7 @@ Signed-off-by: Steven Barth if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; -@@ -1545,6 +1706,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1543,6 +1704,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.link = p->link; t->parms.proto = p->proto; t->parms.fwmark = p->fwmark; @@ -353,7 +353,7 @@ Signed-off-by: Steven Barth dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); } -@@ -1579,6 +1748,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1577,6 +1746,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -361,7 +361,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1965,6 +2135,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1963,6 +2133,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -377,7 +377,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -2002,6 +2181,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -2000,6 +2179,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_FWMARK]) parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); @@ -424,7 +424,7 @@ Signed-off-by: Steven Barth } static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, -@@ -2085,6 +2304,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -2083,6 +2302,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -437,7 +437,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -2114,6 +2339,24 @@ static size_t ip6_tnl_get_size(const str +@@ -2112,6 +2337,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(0) + /* IFLA_IPTUN_FWMARK */ nla_total_size(4) + @@ -462,7 +462,7 @@ Signed-off-by: Steven Barth 0; } -@@ -2121,6 +2364,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2119,6 +2362,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -472,7 +472,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -2130,9 +2376,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2128,9 +2374,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || @@ -501,7 +501,7 @@ Signed-off-by: Steven Barth if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -@@ -2172,6 +2436,7 @@ static const struct nla_policy ip6_tnl_p +@@ -2170,6 +2434,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, diff --git a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 3ab023fdeb..e09decca56 100644 --- a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -20,7 +20,7 @@ Signed-off-by: Jonas Gorski --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h -@@ -85,6 +85,7 @@ struct netns_ipv6 { +@@ -86,6 +86,7 @@ struct netns_ipv6 { unsigned int fib6_routes_require_src; #endif struct rt6_info *ip6_prohibit_entry; @@ -138,7 +138,7 @@ Signed-off-by: Jonas Gorski static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__rcuref = RCUREF_INIT(1), -@@ -1039,6 +1053,7 @@ static const int fib6_prop[RTN_MAX + 1] +@@ -1037,6 +1051,7 @@ static const int fib6_prop[RTN_MAX + 1] [RTN_BLACKHOLE] = -EINVAL, [RTN_UNREACHABLE] = -EHOSTUNREACH, [RTN_PROHIBIT] = -EACCES, @@ -146,7 +146,7 @@ Signed-off-by: Jonas Gorski [RTN_THROW] = -EAGAIN, [RTN_NAT] = -EINVAL, [RTN_XRESOLVE] = -EINVAL, -@@ -1074,6 +1089,10 @@ static void ip6_rt_init_dst_reject(struc +@@ -1072,6 +1087,10 @@ static void ip6_rt_init_dst_reject(struc rt->dst.output = ip6_pkt_prohibit_out; rt->dst.input = ip6_pkt_prohibit; break; @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4540,6 +4559,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4539,6 +4558,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5033,7 +5063,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5030,7 +5060,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6287,6 +6318,8 @@ static int ip6_route_dev_notify(struct n +@@ -6284,6 +6315,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6298,6 +6331,7 @@ static int ip6_route_dev_notify(struct n +@@ -6295,6 +6328,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6489,6 +6523,8 @@ static int __net_init ip6_route_net_init +@@ -6495,6 +6529,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6499,11 +6535,21 @@ static int __net_init ip6_route_net_init +@@ -6505,11 +6541,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->dst.rt_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6530,6 +6576,8 @@ out: +@@ -6536,6 +6582,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6549,6 +6597,7 @@ static void __net_exit ip6_route_net_exi +@@ -6555,6 +6603,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6632,6 +6681,9 @@ void __init ip6_route_init_special_entri +@@ -6638,6 +6687,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 26836240ee..af38c107ee 100644 --- a/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-6.6/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2157,6 +2157,8 @@ struct net_device { +@@ -2210,6 +2210,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau #endif --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -972,6 +972,7 @@ struct sk_buff { +@@ -964,6 +964,7 @@ struct sk_buff { #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau __u8 ipvs_property:1; --- a/net/core/gro.c +++ b/net/core/gro.c -@@ -491,6 +491,9 @@ static enum gro_result dev_gro_receive(s +@@ -445,6 +445,9 @@ static enum gro_result dev_gro_receive(s enum gro_result ret; int same_flow; @@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -7625,6 +7625,48 @@ static void __netdev_adjacent_dev_unlink +@@ -7686,6 +7686,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -7676,6 +7718,7 @@ static int __netdev_upper_dev_link(struc +@@ -7737,6 +7779,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -7772,6 +7815,7 @@ static void __netdev_upper_dev_unlink(st +@@ -7833,6 +7876,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -109,7 +109,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8821,6 +8865,7 @@ int dev_set_mac_address(struct net_devic +@@ -8889,6 +8933,7 @@ int dev_set_mac_address(struct net_devic return err; } dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch index 9e81cb1f27..0fb02dbb67 100644 --- a/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-6.6/683-of_net-add-mac-address-to-of-tree.patch @@ -17,7 +17,7 @@ property. This way, the MAC address can be accessed using procfs. --- a/net/core/of_net.c +++ b/net/core/of_net.c -@@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct +@@ -97,6 +97,27 @@ int of_get_mac_address_nvmem(struct devi } EXPORT_SYMBOL(of_get_mac_address_nvmem); @@ -45,7 +45,7 @@ property. This way, the MAC address can be accessed using procfs. /** * of_get_mac_address() * @np: Caller's Device Node -@@ -130,17 +151,23 @@ int of_get_mac_address(struct device_nod +@@ -132,17 +153,23 @@ int of_get_mac_address(struct device_nod ret = of_get_mac_addr(np, "mac-address", addr); if (!ret) diff --git a/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index b335748705..6b93f47772 100644 --- a/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/pending-6.6/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -659,6 +659,23 @@ static struct pernet_operations nf_flow_ +@@ -662,6 +662,23 @@ static struct pernet_operations nf_flow_ .exit_batch = nf_flow_table_pernet_exit, }; @@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso static int __init nf_flow_table_module_init(void) { int ret; -@@ -671,8 +688,14 @@ static int __init nf_flow_table_module_i +@@ -674,8 +691,14 @@ static int __init nf_flow_table_module_i if (ret) goto out_offload; @@ -49,7 +49,7 @@ Signed-off-by: Pablo Neira Ayuso out_offload: unregister_pernet_subsys(&nf_flow_table_net_ops); return ret; -@@ -680,6 +703,7 @@ out_offload: +@@ -683,6 +706,7 @@ out_offload: static void __exit nf_flow_table_module_exit(void) { @@ -59,7 +59,7 @@ Signed-off-by: Pablo Neira Ayuso } --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -479,47 +479,14 @@ static struct nft_expr_type nft_flow_off +@@ -480,47 +480,14 @@ static struct nft_expr_type nft_flow_off .owner = THIS_MODULE, }; diff --git a/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch index 757c0b2449..cc37180277 100644 --- a/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch +++ b/target/linux/generic/pending-6.6/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -7911,7 +7911,7 @@ static int nft_register_flowtable_net_ho +@@ -8213,7 +8213,7 @@ static int nft_register_flowtable_net_ho err = flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_BIND); diff --git a/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch index 842fef3a9c..b074f546c5 100644 --- a/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch +++ b/target/linux/generic/pending-6.6/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4941,6 +4941,8 @@ static int mtk_probe(struct platform_dev +@@ -4982,6 +4982,8 @@ static int mtk_probe(struct platform_dev * for NAPI to work */ init_dummy_netdev(ð->dummy_dev); diff --git a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch index 61dd11727f..5166dd2115 100644 --- a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1753,6 +1753,9 @@ void phy_detach(struct phy_device *phyde +@@ -1900,6 +1900,9 @@ void phy_detach(struct phy_device *phyde if (phydev->devlink) device_link_del(phydev->devlink); @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -900,6 +900,12 @@ struct phy_driver { +@@ -976,6 +976,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch b/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch index d444b2027c..f7e4e77773 100644 --- a/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch +++ b/target/linux/generic/pending-6.6/705-net-dsa-tag_mtk-add-padding-for-tx-packets.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/net/dsa/tag_mtk.c +++ b/net/dsa/tag_mtk.c -@@ -27,6 +27,13 @@ static struct sk_buff *mtk_tag_xmit(stru +@@ -29,6 +29,13 @@ static struct sk_buff *mtk_tag_xmit(stru skb_set_queue_mapping(skb, dp->index); diff --git a/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index 85e42d5a94..05711780f5 100644 --- a/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/target/linux/generic/pending-6.6/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h -@@ -59,6 +59,7 @@ struct br_ip_list { +@@ -61,6 +61,7 @@ struct br_ip_list { #define BR_PORT_LOCKED BIT(21) #define BR_PORT_MAB BIT(22) #define BR_NEIGH_VLAN_SUPPRESS BIT(23) @@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c -@@ -199,6 +199,7 @@ out: +@@ -201,6 +201,7 @@ void br_flood(struct net_bridge *br, str enum br_pkt_type pkt_type, bool local_rcv, bool local_orig, u16 vid) { @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau struct net_bridge_port *prev = NULL; struct net_bridge_port *p; -@@ -214,6 +215,10 @@ void br_flood(struct net_bridge *br, str +@@ -218,6 +219,10 @@ void br_flood(struct net_bridge *br, str case BR_PKT_MULTICAST: if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) continue; @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -344,6 +344,8 @@ static rx_handler_result_t br_handle_fra +@@ -362,6 +362,8 @@ static rx_handler_result_t br_handle_fra fwd_mask |= p->group_fwd_mask; switch (dest[5]) { case 0x00: /* Bridge Group Address */ @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h -@@ -561,6 +561,7 @@ enum { +@@ -571,6 +571,7 @@ enum { IFLA_BRPORT_MCAST_MAX_GROUPS, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, IFLA_BRPORT_BACKUP_NHID, @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c -@@ -188,6 +188,7 @@ static inline size_t br_port_info_size(v +@@ -190,6 +190,7 @@ static inline size_t br_port_info_size(v + nla_total_size(1) /* IFLA_BRPORT_LOCKED */ + nla_total_size(1) /* IFLA_BRPORT_MAB */ + nla_total_size(1) /* IFLA_BRPORT_NEIGH_VLAN_SUPPRESS */ @@ -124,7 +124,7 @@ Signed-off-by: Felix Fietkau + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ -@@ -274,7 +275,8 @@ static int br_port_fill_attrs(struct sk_ +@@ -282,7 +283,8 @@ static int br_port_fill_attrs(struct sk_ nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) || nla_put_u8(skb, IFLA_BRPORT_MAB, !!(p->flags & BR_PORT_MAB)) || nla_put_u8(skb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, @@ -134,7 +134,7 @@ Signed-off-by: Felix Fietkau return -EMSGSIZE; timerval = br_timer_value(&p->message_age_timer); -@@ -878,6 +880,7 @@ static const struct nla_policy br_port_p +@@ -901,6 +903,7 @@ static const struct nla_policy br_port_p [IFLA_BRPORT_MCAST_MAX_GROUPS] = { .type = NLA_U32 }, [IFLA_BRPORT_NEIGH_VLAN_SUPPRESS] = NLA_POLICY_MAX(NLA_U8, 1), [IFLA_BRPORT_BACKUP_NHID] = { .type = NLA_U32 }, @@ -142,7 +142,7 @@ Signed-off-by: Felix Fietkau }; /* Change the state of the port and notify spanning tree */ -@@ -943,6 +946,7 @@ static int br_setport(struct net_bridge_ +@@ -969,6 +972,7 @@ static int br_setport(struct net_bridge_ br_set_port_flag(p, tb, IFLA_BRPORT_MAB, BR_PORT_MAB); br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS, BR_NEIGH_VLAN_SUPPRESS); @@ -152,7 +152,7 @@ Signed-off-by: Felix Fietkau (!(p->flags & BR_PORT_LOCKED) || !(p->flags & BR_LEARNING))) { --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c -@@ -57,7 +57,7 @@ +@@ -61,7 +61,7 @@ #include "dev.h" #define RTNL_MAX_TYPE 50 @@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau struct rtnl_link { rtnl_doit_func doit; -@@ -4840,7 +4840,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu +@@ -4949,7 +4949,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || brport_nla_put_flag(skb, flags, mask, diff --git a/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch index 629b141572..3197aea091 100644 --- a/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch +++ b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch @@ -16,7 +16,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -2015,6 +2015,8 @@ static const struct dsa_switch_ops qca8k +@@ -2012,6 +2012,8 @@ static const struct dsa_switch_ops qca8k .port_fdb_add = qca8k_port_fdb_add, .port_fdb_del = qca8k_port_fdb_del, .port_fdb_dump = qca8k_port_fdb_dump, diff --git a/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch b/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch index 24243468a8..b1d9f84cfe 100644 --- a/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch +++ b/target/linux/generic/pending-6.6/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch @@ -14,7 +14,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1904,15 +1904,12 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1901,15 +1901,12 @@ qca8k_setup(struct dsa_switch *ds) } } diff --git a/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch b/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch index 8a58e0f76e..9b553e77cd 100644 --- a/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch +++ b/target/linux/generic/pending-6.6/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch @@ -26,7 +26,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -1741,6 +1741,117 @@ qca8k_get_tag_protocol(struct dsa_switch +@@ -1738,6 +1738,117 @@ qca8k_get_tag_protocol(struct dsa_switch return DSA_TAG_PROTO_QCA; } @@ -144,7 +144,7 @@ Signed-off-by: Christian Marangi static void qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, bool operational) -@@ -2027,8 +2138,9 @@ static const struct dsa_switch_ops qca8k +@@ -2024,8 +2135,9 @@ static const struct dsa_switch_ops qca8k .phylink_mac_link_down = qca8k_phylink_mac_link_down, .phylink_mac_link_up = qca8k_phylink_mac_link_up, .get_phy_flags = qca8k_get_phy_flags, diff --git a/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch index 23816fe366..18afa1c072 100644 --- a/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch +++ b/target/linux/generic/pending-6.6/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch @@ -20,7 +20,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -2013,6 +2013,12 @@ qca8k_setup(struct dsa_switch *ds) +@@ -2010,6 +2010,12 @@ qca8k_setup(struct dsa_switch *ds) dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); return ret; } @@ -33,7 +33,7 @@ Signed-off-by: Christian Marangi } /* Forward all unknown frames to CPU port for Linux processing */ -@@ -2042,11 +2048,6 @@ qca8k_setup(struct dsa_switch *ds) +@@ -2039,11 +2045,6 @@ qca8k_setup(struct dsa_switch *ds) if (ret) return ret; @@ -45,7 +45,7 @@ Signed-off-by: Christian Marangi /* For port based vlans to work we need to set the * default egress vid */ -@@ -2098,6 +2099,9 @@ qca8k_setup(struct dsa_switch *ds) +@@ -2095,6 +2096,9 @@ qca8k_setup(struct dsa_switch *ds) /* Set max number of LAGs supported */ ds->num_lag_ids = QCA8K_NUM_LAGS; diff --git a/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch b/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch index 55f116ec5f..74cce98381 100644 --- a/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch +++ b/target/linux/generic/pending-6.6/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch @@ -14,7 +14,7 @@ Signed-off-by: Christian Marangi --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -263,6 +263,8 @@ +@@ -275,6 +275,8 @@ clocks = <&gcc GCC_MDIO_AHB_CLK>; clock-names = "gcc_mdio_ahb_clk"; diff --git a/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch b/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch index ed13b004e4..7e9b3660d5 100644 --- a/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch +++ b/target/linux/generic/pending-6.6/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch @@ -23,7 +23,7 @@ Signed-off-by: Alexander Couzens --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -53,6 +53,15 @@ +@@ -54,6 +54,15 @@ RTL8201F_ISR_LINK) #define RTL8201F_IER 0x13 @@ -39,7 +39,7 @@ Signed-off-by: Alexander Couzens #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -851,6 +860,48 @@ static irqreturn_t rtl9000a_handle_inter +@@ -879,6 +888,48 @@ static irqreturn_t rtl9000a_handle_inter return IRQ_HANDLED; } @@ -88,7 +88,7 @@ Signed-off-by: Alexander Couzens static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1003,6 +1054,7 @@ static struct phy_driver realtek_drvs[] +@@ -1033,6 +1084,7 @@ static struct phy_driver realtek_drvs[] PHY_ID_MATCH_EXACT(0x001cc849), .name = "RTL8221B-VB-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, @@ -96,7 +96,7 @@ Signed-off-by: Alexander Couzens .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, .suspend = genphy_suspend, -@@ -1014,6 +1066,7 @@ static struct phy_driver realtek_drvs[] +@@ -1044,6 +1096,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8221B-VM-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, diff --git a/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch b/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch index abe31e66af..58bd259198 100644 --- a/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch +++ b/target/linux/generic/pending-6.6/722-net-phy-realtek-support-switching-between-SGMII-and-.patch @@ -16,7 +16,7 @@ Signed-off-by: Chukun Pan --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -686,6 +686,25 @@ static int rtl822x_config_aneg(struct ph +@@ -714,6 +714,25 @@ static int rtl822x_config_aneg(struct ph return __genphy_config_aneg(phydev, ret); } @@ -42,7 +42,7 @@ Signed-off-by: Chukun Pan static int rtl822x_read_status(struct phy_device *phydev) { int ret; -@@ -704,11 +723,14 @@ static int rtl822x_read_status(struct ph +@@ -732,11 +751,14 @@ static int rtl822x_read_status(struct ph phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); } diff --git a/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch index a18d1ad717..4ab8e24f99 100644 --- a/target/linux/generic/pending-6.6/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch +++ b/target/linux/generic/pending-6.6/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 -@@ -2252,6 +2252,10 @@ mt7530_setup(struct dsa_switch *ds) +@@ -2268,6 +2268,10 @@ mt7530_setup(struct dsa_switch *ds) return -ENODEV; } diff --git a/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch b/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch index 8e0e4b1fdd..8efedd3a11 100644 --- a/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch +++ b/target/linux/generic/pending-6.6/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch @@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -1040,6 +1040,7 @@ static struct phy_driver realtek_drvs[] +@@ -1070,6 +1070,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc840), .name = "RTL8226B_RTL8221B 2.5Gbps PHY", -@@ -1052,6 +1053,7 @@ static struct phy_driver realtek_drvs[] +@@ -1082,6 +1083,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, @@ -31,7 +31,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", -@@ -1062,6 +1064,7 @@ static struct phy_driver realtek_drvs[] +@@ -1092,6 +1094,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -39,7 +39,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", -@@ -1072,6 +1075,7 @@ static struct phy_driver realtek_drvs[] +@@ -1102,6 +1105,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -47,7 +47,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc849), .name = "RTL8221B-VB-CG 2.5Gbps PHY", -@@ -1083,6 +1087,7 @@ static struct phy_driver realtek_drvs[] +@@ -1113,6 +1117,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -55,7 +55,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc84a), .name = "RTL8221B-VM-CG 2.5Gbps PHY", -@@ -1094,6 +1099,7 @@ static struct phy_driver realtek_drvs[] +@@ -1124,6 +1129,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, diff --git a/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch index babaa47aed..43cf35ab77 100644 --- a/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch +++ b/target/linux/generic/pending-6.6/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -885,6 +885,7 @@ static irqreturn_t rtl9000a_handle_inter +@@ -913,6 +913,7 @@ static irqreturn_t rtl9000a_handle_inter static int rtl8221b_config_init(struct phy_device *phydev) { u16 option_mode; @@ -27,7 +27,7 @@ Signed-off-by: Daniel Golle switch (phydev->interface) { case PHY_INTERFACE_MODE_2500BASEX: -@@ -921,6 +922,13 @@ static int rtl8221b_config_init(struct p +@@ -949,6 +950,13 @@ static int rtl8221b_config_init(struct p break; } diff --git a/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch b/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch index 6e338d9474..be86a774ea 100644 --- a/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch +++ b/target/linux/generic/pending-6.6/726-net-phy-realtek-make-sure-paged-read-is-protected-by.patch @@ -18,7 +18,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -737,9 +737,11 @@ static bool rtlgen_supports_2_5gbps(stru +@@ -765,9 +765,11 @@ static bool rtlgen_supports_2_5gbps(stru { int val; diff --git a/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch b/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch index cafaefd3bf..e6cbfbe649 100644 --- a/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch +++ b/target/linux/generic/pending-6.6/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -68,10 +68,6 @@ +@@ -69,10 +69,6 @@ #define RTL_SUPPORTS_5000FULL BIT(14) #define RTL_SUPPORTS_2500FULL BIT(13) #define RTL_SUPPORTS_10000FULL BIT(0) @@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle #define RTL9000A_GINMR 0x14 #define RTL9000A_GINMR_LINK_STATUS BIT(4) -@@ -671,14 +667,11 @@ static int rtl822x_config_aneg(struct ph +@@ -699,14 +695,11 @@ static int rtl822x_config_aneg(struct ph int ret = 0; if (phydev->autoneg == AUTONEG_ENABLE) { @@ -44,7 +44,7 @@ Signed-off-by: Daniel Golle if (ret < 0) return ret; } -@@ -715,12 +708,7 @@ static int rtl822x_read_status(struct ph +@@ -743,12 +736,7 @@ static int rtl822x_read_status(struct ph if (lpadv < 0) return lpadv; diff --git a/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch b/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch index 8be1af6e50..329415bab5 100644 --- a/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch +++ b/target/linux/generic/pending-6.6/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch @@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -708,6 +708,10 @@ static int rtl822x_read_status(struct ph +@@ -736,6 +736,10 @@ static int rtl822x_read_status(struct ph if (lpadv < 0) return lpadv; diff --git a/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch b/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch index 92e7a8742a..7098fa6b28 100644 --- a/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch +++ b/target/linux/generic/pending-6.6/729-net-phy-realtek-introduce-rtl822x_probe.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -62,6 +62,10 @@ +@@ -63,6 +63,10 @@ #define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 #define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 @@ -24,7 +24,7 @@ Signed-off-by: Daniel Golle #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -750,6 +754,25 @@ static int rtl8226_match_phy_device(stru +@@ -778,6 +782,25 @@ static int rtl8226_match_phy_device(stru rtlgen_supports_2_5gbps(phydev); } @@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle static int rtlgen_resume(struct phy_device *phydev) { int ret = genphy_resume(phydev); -@@ -1061,6 +1084,7 @@ static struct phy_driver realtek_drvs[] +@@ -1091,6 +1114,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8226-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, @@ -58,7 +58,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1072,6 +1096,7 @@ static struct phy_driver realtek_drvs[] +@@ -1102,6 +1126,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, @@ -66,7 +66,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1084,6 +1109,7 @@ static struct phy_driver realtek_drvs[] +@@ -1114,6 +1139,7 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, @@ -74,7 +74,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1096,6 +1122,7 @@ static struct phy_driver realtek_drvs[] +@@ -1126,6 +1152,7 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl8221b_config_init, diff --git a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch index 32d81d56f8..2a8e742a74 100644 --- a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -754,6 +754,38 @@ static int rtl8226_match_phy_device(stru +@@ -782,6 +782,38 @@ static int rtl8226_match_phy_device(stru rtlgen_supports_2_5gbps(phydev); } @@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle static int rtl822x_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; -@@ -1104,7 +1136,7 @@ static struct phy_driver realtek_drvs[] +@@ -1134,7 +1166,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .soft_reset = genphy_soft_reset, }, { diff --git a/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch b/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch index a7a4bafbb6..f92f60f349 100644 --- a/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch +++ b/target/linux/generic/pending-6.6/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch @@ -17,7 +17,7 @@ Signed-off-by: Christian Marangi --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2192,7 +2192,7 @@ struct net_device { +@@ -2245,7 +2245,7 @@ struct net_device { #if IS_ENABLED(CONFIG_AX25) void *ax25_ptr; #endif @@ -28,7 +28,7 @@ Signed-off-by: Christian Marangi #if IS_ENABLED(CONFIG_IEEE802154) || IS_ENABLED(CONFIG_6LOWPAN) --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c -@@ -308,7 +308,7 @@ static bool batadv_is_cfg80211_netdev(st +@@ -309,7 +309,7 @@ static bool batadv_is_cfg80211_netdev(st if (!net_device) return false; diff --git a/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch index 17c7d92ce0..e4b7070cbe 100644 --- a/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch +++ b/target/linux/generic/pending-6.6/732-01-net-ethernet-mtk_eth_soc-work-around-issue-with-send.patch @@ -22,9 +22,9 @@ Signed-off-by: Felix Fietkau #include +#include #include - + #include "mtk_eth_soc.h" -@@ -1562,12 +1562,28 @@ static void mtk_wake_queue(struct mtk_et +@@ -1579,12 +1580,28 @@ static void mtk_wake_queue(struct mtk_et } } @@ -53,7 +53,7 @@ Signed-off-by: Felix Fietkau bool gso = false; int tx_num; -@@ -1589,6 +1605,18 @@ static netdev_tx_t mtk_start_xmit(struct +@@ -1606,6 +1623,18 @@ static netdev_tx_t mtk_start_xmit(struct return NETDEV_TX_BUSY; } @@ -72,7 +72,7 @@ Signed-off-by: Felix Fietkau /* TSO: fill MSS info in tcp checksum field */ if (skb_is_gso(skb)) { if (skb_cow_head(skb, 0)) { -@@ -1604,8 +1632,14 @@ static netdev_tx_t mtk_start_xmit(struct +@@ -1621,8 +1650,14 @@ static netdev_tx_t mtk_start_xmit(struct } } diff --git a/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index afe561ab31..c9cd726aca 100644 --- a/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -205,7 +205,7 @@ Signed-off-by: Daniel Golle 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 -@@ -21,6 +21,8 @@ +@@ -22,6 +22,8 @@ #include #include #include @@ -214,7 +214,7 @@ Signed-off-by: Daniel Golle #include #include #include -@@ -258,12 +260,8 @@ static const char * const mtk_clks_sourc +@@ -261,12 +263,8 @@ static const char * const mtk_clks_sourc "ethwarp_wocpu2", "ethwarp_wocpu1", "ethwarp_wocpu0", @@ -227,7 +227,7 @@ Signed-off-by: Daniel Golle "top_eth_gmii_sel", "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", -@@ -475,6 +473,30 @@ static void mtk_setup_bridge_switch(stru +@@ -509,6 +507,30 @@ static void mtk_setup_bridge_switch(stru MTK_GSW_CFG); } @@ -258,7 +258,7 @@ Signed-off-by: Daniel Golle static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { -@@ -483,6 +505,21 @@ static struct phylink_pcs *mtk_mac_selec +@@ -517,6 +539,21 @@ static struct phylink_pcs *mtk_mac_selec struct mtk_eth *eth = mac->hw; unsigned int sid; @@ -280,7 +280,7 @@ Signed-off-by: Daniel Golle if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) { sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? -@@ -544,7 +581,22 @@ static void mtk_mac_config(struct phylin +@@ -568,7 +605,22 @@ static void mtk_mac_config(struct phylin goto init_err; } break; @@ -303,7 +303,7 @@ Signed-off-by: Daniel Golle break; default: goto err_phy; -@@ -599,8 +651,6 @@ static void mtk_mac_config(struct phylin +@@ -615,8 +667,6 @@ static void mtk_mac_config(struct phylin val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id); val |= SYSCFG0_GE_MODE(ge_mode, mac->id); regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); @@ -312,7 +312,7 @@ Signed-off-by: Daniel Golle } /* SGMII */ -@@ -617,21 +667,40 @@ static void mtk_mac_config(struct phylin +@@ -633,21 +683,40 @@ static void mtk_mac_config(struct phylin /* Save the syscfg0 value for mac_finish */ mac->syscfg0 = val; @@ -360,7 +360,7 @@ Signed-off-by: Daniel Golle return; err_phy: -@@ -644,6 +713,18 @@ init_err: +@@ -660,6 +729,18 @@ init_err: mac->id, phy_modes(state->interface), err); } @@ -379,7 +379,7 @@ Signed-off-by: Daniel Golle static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, phy_interface_t interface) { -@@ -652,6 +733,10 @@ static int mtk_mac_finish(struct phylink +@@ -668,6 +749,10 @@ static int mtk_mac_finish(struct phylink struct mtk_eth *eth = mac->hw; u32 mcr_cur, mcr_new; @@ -390,7 +390,7 @@ Signed-off-by: Daniel Golle /* Enable SGMII */ if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) -@@ -677,10 +762,13 @@ static void mtk_mac_link_down(struct phy +@@ -693,10 +778,13 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); @@ -407,7 +407,7 @@ Signed-off-by: Daniel Golle } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -752,13 +840,11 @@ static void mtk_set_queue_speed(struct m +@@ -768,13 +856,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -425,7 +425,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -792,9 +878,63 @@ static void mtk_mac_link_up(struct phyli +@@ -808,9 +894,63 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -489,7 +489,7 @@ Signed-off-by: Daniel Golle .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, .mac_link_up = mtk_mac_link_up, -@@ -3373,6 +3513,9 @@ static int mtk_open(struct net_device *d +@@ -3391,6 +3531,9 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -499,7 +499,7 @@ Signed-off-by: Daniel Golle err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3501,6 +3644,9 @@ static int mtk_stop(struct net_device *d +@@ -3520,6 +3663,9 @@ static int mtk_stop(struct net_device *d for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) mtk_ppe_stop(eth->ppe[i]); @@ -509,7 +509,7 @@ Signed-off-by: Daniel Golle return 0; } -@@ -4498,6 +4644,7 @@ static const struct net_device_ops mtk_n +@@ -4517,6 +4663,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { const __be32 *_id = of_get_property(np, "reg", NULL); @@ -517,7 +517,7 @@ Signed-off-by: Daniel Golle phy_interface_t phy_mode; struct phylink *phylink; struct mtk_mac *mac; -@@ -4533,16 +4680,41 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4553,16 +4700,41 @@ static int mtk_add_mac(struct mtk_eth *e mac->id = id; mac->hw = eth; mac->of_node = np; @@ -567,7 +567,7 @@ Signed-off-by: Daniel Golle } memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); -@@ -4616,8 +4788,21 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4645,8 +4817,21 @@ static int mtk_add_mac(struct mtk_eth *e phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); @@ -589,7 +589,7 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4662,6 +4847,26 @@ free_netdev: +@@ -4697,6 +4882,26 @@ free_netdev: return err; } @@ -616,7 +616,7 @@ Signed-off-by: Daniel Golle void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) { struct net_device *dev, *tmp; -@@ -4805,7 +5010,8 @@ static int mtk_probe(struct platform_dev +@@ -4843,7 +5048,8 @@ static int mtk_probe(struct platform_dev regmap_write(cci, 0, 3); } @@ -626,7 +626,7 @@ Signed-off-by: Daniel Golle err = mtk_sgmii_init(eth); if (err) -@@ -4916,6 +5122,24 @@ static int mtk_probe(struct platform_dev +@@ -4954,6 +5160,24 @@ static int mtk_probe(struct platform_dev } } @@ -651,7 +651,7 @@ Signed-off-by: Daniel Golle if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, -@@ -5018,6 +5242,11 @@ static int mtk_remove(struct platform_de +@@ -5056,6 +5280,11 @@ static int mtk_remove(struct platform_de mtk_stop(eth->netdev[i]); mac = netdev_priv(eth->netdev[i]); phylink_disconnect_phy(mac->phylink); diff --git a/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch index adb95e9587..b67c8a0ea0 100644 --- a/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch +++ b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch @@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, -@@ -148,6 +181,7 @@ static int mtk_pcs_lynxi_config(struct p +@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p SGMII_PHYA_PWD); /* Reset SGMII PCS state */ @@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, SGMII_SW_RESET); -@@ -234,10 +268,29 @@ static void mtk_pcs_lynxi_link_up(struct +@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct } } @@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle mpcs->interface = PHY_INTERFACE_MODE_NA; } -@@ -247,11 +300,12 @@ static const struct phylink_pcs_ops mtk_ +@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_ .pcs_an_restart = mtk_pcs_lynxi_restart_an, .pcs_link_up = mtk_pcs_lynxi_link_up, .pcs_disable = mtk_pcs_lynxi_disable, @@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle { struct mtk_pcs_lynxi *mpcs; u32 id, ver; -@@ -259,29 +313,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create +@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); if (ret < 0) @@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle mpcs->ana_rgc3 = ana_rgc3; mpcs->regmap = regmap; -@@ -292,6 +350,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create +@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create mpcs->interface = PHY_INTERFACE_MODE_NA; return &mpcs->pcs; @@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle } EXPORT_SYMBOL(mtk_pcs_lynxi_create); -@@ -304,4 +369,144 @@ void mtk_pcs_lynxi_destroy(struct phylin +@@ -303,4 +368,144 @@ void mtk_pcs_lynxi_destroy(struct phylin } EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); diff --git a/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch index 6fe29bc6c9..73ec05464a 100644 --- a/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch +++ b/target/linux/generic/pending-6.6/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12934,7 +12934,9 @@ M: Daniel Golle +@@ -13348,7 +13348,9 @@ M: Daniel Golle L: netdev@vger.kernel.org S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c @@ -31,7 +31,7 @@ Signed-off-by: Daniel Golle M: Daniel Golle --- a/drivers/net/pcs/Kconfig +++ b/drivers/net/pcs/Kconfig -@@ -18,6 +18,17 @@ config PCS_LYNX +@@ -25,6 +25,17 @@ config PCS_MTK_LYNXI This module provides helpers to phylink for managing the LynxI PCS which is part of MediaTek's SoC and Ethernet switch ICs. @@ -51,7 +51,7 @@ Signed-off-by: Daniel Golle depends on OF && (ARCH_RZN1 || COMPILE_TEST) --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o +@@ -7,3 +7,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o diff --git a/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch index 51cd98c883..3c68bf8bbd 100644 --- a/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -981,6 +981,51 @@ static int rtl8221b_config_init(struct p +@@ -1009,6 +1009,51 @@ static int rtl8221b_config_init(struct p return 0; } @@ -52,7 +52,7 @@ static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1141,6 +1186,8 @@ static struct phy_driver realtek_drvs[] +@@ -1171,6 +1216,8 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, diff --git a/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch b/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch index 1dfa1366eb..c811e40d49 100644 --- a/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch +++ b/target/linux/generic/pending-6.6/750-net-phy-airoha-Add-the-Airoha-EN8811H-PHY-driver.patch @@ -82,7 +82,7 @@ Signed-off-by: Eric Woudstra --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -69,6 +69,11 @@ config SFP +@@ -68,6 +68,11 @@ config SFP comment "MII PHY device drivers" @@ -96,7 +96,7 @@ Signed-off-by: Eric Woudstra help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -32,6 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) +@@ -34,6 +34,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) obj-$(CONFIG_ADIN_PHY) += adin.o obj-$(CONFIG_ADIN1100_PHY) += adin1100.o diff --git a/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch index bb9149a668..013005f053 100644 --- a/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-6.6/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -543,6 +543,7 @@ static inline bool napi_complete(struct +@@ -558,6 +558,7 @@ static inline bool napi_complete(struct } int dev_set_threaded(struct net_device *dev, bool threaded); @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau /** * napi_disable - prevent NAPI from scheduling -@@ -3129,6 +3130,7 @@ struct softnet_data { +@@ -3238,6 +3239,7 @@ struct softnet_data { /* stats */ unsigned int processed; unsigned int time_squeeze; @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4625,7 +4625,7 @@ static int napi_schedule_rps(struct soft +@@ -4729,7 +4729,7 @@ static void napi_schedule_rps(struct sof struct softnet_data *mysd = this_cpu_ptr(&softnet_data); #ifdef CONFIG_RPS @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5806,6 +5806,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5848,6 +5848,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5820,8 +5822,17 @@ static void flush_backlog(struct work_st +@@ -5862,8 +5864,17 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5829,7 +5840,16 @@ static void flush_backlog(struct work_st +@@ -5871,7 +5882,16 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -5961,6 +5981,7 @@ static int process_backlog(struct napi_s +@@ -6003,6 +6023,7 @@ static int process_backlog(struct napi_s } rps_lock_irq_disable(sd); @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -5970,7 +5991,8 @@ static int process_backlog(struct napi_s +@@ -6012,7 +6033,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6386,6 +6408,55 @@ int dev_set_threaded(struct net_device * +@@ -6426,6 +6448,55 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11168,6 +11239,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11348,6 +11419,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11480,6 +11554,7 @@ static int __init net_dev_init(void) +@@ -11663,6 +11737,7 @@ static int __init net_dev_init(void) INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); spin_lock_init(&sd->defer_lock); @@ -177,7 +177,7 @@ Signed-off-by: Felix Fietkau sd->backlog.weight = weight_p; --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c -@@ -29,6 +29,7 @@ static int int_3600 = 3600; +@@ -30,6 +30,7 @@ static int int_3600 = 3600; static int min_sndbuf = SOCK_MIN_SNDBUF; static int min_rcvbuf = SOCK_MIN_RCVBUF; static int max_skb_frags = MAX_SKB_FRAGS; @@ -185,7 +185,7 @@ Signed-off-by: Felix Fietkau static int net_msg_warn; /* Unused, but still a sysctl */ -@@ -112,6 +113,23 @@ static int rps_sock_flow_sysctl(struct c +@@ -188,6 +189,23 @@ static int rps_sock_flow_sysctl(struct c } #endif /* CONFIG_RPS */ @@ -209,7 +209,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_NET_FLOW_LIMIT static DEFINE_MUTEX(flow_limit_update_mutex); -@@ -473,6 +491,15 @@ static struct ctl_table net_core_table[] +@@ -532,6 +550,15 @@ static struct ctl_table net_core_table[] .proc_handler = rps_sock_flow_sysctl }, #endif diff --git a/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index 9556c90b57..332d7e721a 100644 --- a/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -7025,6 +7025,7 @@ static int mv88e6xxx_register_switch(str +@@ -6883,6 +6883,7 @@ static int mv88e6xxx_register_switch(str ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; diff --git a/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch b/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch index 6c1f596759..551855a229 100644 --- a/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch +++ b/target/linux/generic/pending-6.6/779-net-vxlan-don-t-learn-non-unicast-L2-destinations.patch @@ -17,7 +17,7 @@ Signed-off-by: David Bauer --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c -@@ -1493,6 +1493,10 @@ static bool vxlan_snoop(struct net_devic +@@ -1446,6 +1446,10 @@ static bool vxlan_snoop(struct net_devic struct vxlan_fdb *f; u32 ifindex = 0; diff --git a/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch b/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch index d333f3f489..4b5eb767fd 100644 --- a/target/linux/generic/pending-6.6/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch +++ b/target/linux/generic/pending-6.6/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 -@@ -2142,10 +2142,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr +@@ -2156,10 +2156,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; -@@ -2162,7 +2165,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr +@@ -2178,7 +2181,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr if (priv->irq) mt7530_setup_mdio_irq(priv); diff --git a/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch index 478a2cb27d..4a9c188d17 100644 --- a/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch +++ b/target/linux/generic/pending-6.6/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch @@ -50,7 +50,7 @@ Signed-off-by: Rafał Miłecki if (err) --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -236,13 +236,17 @@ EXPORT_SYMBOL(bcma_core_irq); +@@ -237,13 +237,17 @@ EXPORT_SYMBOL(bcma_core_irq); void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) { diff --git a/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch index a13d405e64..ca4101f148 100644 --- a/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch +++ b/target/linux/generic/pending-6.6/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch @@ -70,7 +70,7 @@ v1 -> v2: --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -1711,4 +1711,19 @@ config GPIO_SIM +@@ -1819,4 +1819,19 @@ config GPIO_SIM endmenu @@ -92,7 +92,7 @@ v1 -> v2: endif --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -43,6 +43,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd +@@ -44,6 +44,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o diff --git a/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch index cb5d30db27..7f67091478 100644 --- a/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch +++ b/target/linux/generic/pending-6.6/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch @@ -33,7 +33,7 @@ Signed-off-by: Christian Marangi return 0; --- a/drivers/opp/core.c +++ b/drivers/opp/core.c -@@ -816,7 +816,8 @@ static int _set_opp_voltage(struct devic +@@ -902,7 +902,8 @@ static int _set_opp_voltage(struct devic static int _opp_config_clk_single(struct device *dev, struct opp_table *opp_table, @@ -43,7 +43,7 @@ Signed-off-by: Christian Marangi { unsigned long *target = data; unsigned long freq; -@@ -848,8 +849,8 @@ _opp_config_clk_single(struct device *de +@@ -934,8 +935,8 @@ _opp_config_clk_single(struct device *de * the order in which they are present in the array while scaling up. */ int dev_pm_opp_config_clks_simple(struct device *dev, @@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi { int ret, i; -@@ -1121,7 +1122,7 @@ static int _set_opp(struct device *dev, +@@ -1217,7 +1218,7 @@ static int _set_opp(struct device *dev, } if (opp_table->config_clks) { @@ -63,7 +63,7 @@ Signed-off-by: Christian Marangi if (ret) return ret; } -@@ -1196,7 +1197,7 @@ int dev_pm_opp_set_rate(struct device *d +@@ -1292,7 +1293,7 @@ int dev_pm_opp_set_rate(struct device *d * equivalent to a clk_set_rate() */ if (!_get_opp_count(opp_table)) { @@ -84,7 +84,7 @@ Signed-off-by: Christian Marangi struct dev_pm_opp *opp, void *data, bool scaling_down); /** -@@ -160,8 +161,8 @@ int dev_pm_opp_set_config(struct device +@@ -172,8 +173,8 @@ int dev_pm_opp_set_config(struct device int devm_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config); void dev_pm_opp_clear_config(int token); int dev_pm_opp_config_clks_simple(struct device *dev, @@ -95,7 +95,7 @@ Signed-off-by: Christian Marangi struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp); int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate); -@@ -346,8 +347,8 @@ static inline int devm_pm_opp_set_config +@@ -377,8 +378,8 @@ static inline int devm_pm_opp_set_config static inline void dev_pm_opp_clear_config(int token) {} static inline int dev_pm_opp_config_clks_simple(struct device *dev, diff --git a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch index 2f0dcd91d9..d08ed63eaa 100644 --- a/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch +++ b/target/linux/generic/pending-6.6/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -33,7 +33,7 @@ string. #include #include #include -@@ -780,6 +783,62 @@ static int nvmem_validate_keepouts(struc +@@ -779,6 +782,62 @@ static int nvmem_validate_keepouts(struc return 0; } @@ -96,7 +96,7 @@ string. static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct device *dev = &nvmem->dev; -@@ -814,6 +873,25 @@ static int nvmem_add_cells_from_dt(struc +@@ -813,6 +872,25 @@ static int nvmem_add_cells_from_dt(struc if (nvmem->fixup_dt_cell_info) nvmem->fixup_dt_cell_info(nvmem, &info); diff --git a/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch index ba06196f7c..9bdfcc7486 100644 --- a/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch +++ b/target/linux/generic/pending-6.6/810-pci_disable_common_quirks.patch @@ -9,7 +9,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig -@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND +@@ -113,6 +113,13 @@ config XEN_PCIDEV_FRONTEND The PCI device frontend driver allows the kernel to import arbitrary PCI devices from a PCI backend to support PCI driver domains. @@ -25,7 +25,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -207,6 +207,7 @@ static void quirk_mmio_always_on(struct +@@ -300,6 +300,7 @@ static void quirk_mmio_always_on(struct DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); @@ -33,7 +33,7 @@ Signed-off-by: Gabor Juhos /* * The Mellanox Tavor device gives false positive parity errors. Disable * parity error reporting. -@@ -3393,6 +3394,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I +@@ -3488,6 +3489,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); @@ -42,7 +42,7 @@ Signed-off-by: Gabor Juhos /* * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. * To work around this, query the size it should be configured to by the -@@ -3418,6 +3421,8 @@ static void quirk_intel_ntb(struct pci_d +@@ -3513,6 +3516,8 @@ static void quirk_intel_ntb(struct pci_d DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); @@ -51,7 +51,7 @@ Signed-off-by: Gabor Juhos /* * Some BIOS implementations leave the Intel GPU interrupts enabled, even * though no one is handling them (e.g., if the i915 driver is never -@@ -3456,6 +3461,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN +@@ -3551,6 +3556,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); diff --git a/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch index eb5aa15d30..4c271a7bd8 100644 --- a/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch +++ b/target/linux/generic/pending-6.6/811-pci_disable_usb_common_quirks.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau static struct amd_chipset_info { struct pci_dev *nb_dev; struct pci_dev *smbus_dev; -@@ -633,6 +635,10 @@ bool usb_amd_pt_check_port(struct device +@@ -631,6 +633,10 @@ bool usb_amd_pt_check_port(struct device } EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau /* * Make sure the controller is completely inactive, unable to * generate interrupts or do DMA. -@@ -712,8 +718,17 @@ reset_needed: +@@ -710,8 +716,17 @@ reset_needed: uhci_reset_hc(pdev, base); return 1; } @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) { u16 cmd; -@@ -1285,3 +1300,4 @@ static void quirk_usb_early_handoff(stru +@@ -1283,3 +1298,4 @@ static void quirk_usb_early_handoff(stru } DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau #endif /* __LINUX_USB_PCI_QUIRKS_H */ --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h -@@ -483,7 +483,14 @@ extern int usb_hcd_pci_probe(struct pci_ +@@ -484,7 +484,14 @@ extern int usb_hcd_pci_probe(struct pci_ extern void usb_hcd_pci_remove(struct pci_dev *dev); extern void usb_hcd_pci_shutdown(struct pci_dev *dev); diff --git a/target/linux/generic/pending-6.6/834-ledtrig-libata.patch b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch index 562f9b866c..0282e337e0 100644 --- a/target/linux/generic/pending-6.6/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-6.6/834-ledtrig-libata.patch @@ -45,7 +45,7 @@ Signed-off-by: Daniel Golle depends on ACPI --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c -@@ -663,6 +663,19 @@ u64 ata_tf_read_block(const struct ata_t +@@ -685,6 +685,19 @@ static inline void ata_set_tf_cdl(struct qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF; } @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @qc: Metadata associated with the taskfile to build -@@ -4716,6 +4729,9 @@ void __ata_qc_complete(struct ata_queued +@@ -4771,6 +4784,9 @@ void __ata_qc_complete(struct ata_queued link->active_tag = ATA_TAG_POISON; ap->nr_active_links--; } @@ -75,7 +75,7 @@ Signed-off-by: Daniel Golle /* clear exclusive status */ if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL && -@@ -5438,6 +5454,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -5494,6 +5510,9 @@ struct ata_port *ata_port_alloc(struct a ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; #endif @@ -85,7 +85,7 @@ Signed-off-by: Daniel Golle ata_sff_port_init(ap); return ap; -@@ -5469,6 +5488,12 @@ static void ata_host_release(struct kref +@@ -5530,6 +5549,12 @@ static void ata_host_release(struct kref kfree(ap->pmp_link); kfree(ap->slave_link); kfree(ap->ncq_sense_buf); @@ -98,7 +98,7 @@ Signed-off-by: Daniel Golle kfree(ap); host->ports[i] = NULL; } -@@ -5875,7 +5900,23 @@ int ata_host_register(struct ata_host *h +@@ -5920,7 +5945,23 @@ int ata_host_register(struct ata_host *h host->ports[i]->print_id = atomic_inc_return(&ata_print_id); host->ports[i]->local_port_no = i + 1; } @@ -134,7 +134,7 @@ Signed-off-by: Daniel Golle /* * Define if arch has non-standard setup. This is a _PCI_ standard -@@ -864,6 +867,12 @@ struct ata_port { +@@ -874,6 +877,12 @@ struct ata_port { #ifdef CONFIG_ATA_ACPI struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ #endif diff --git a/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch index 5ca8933d6f..3172ad5a16 100644 --- a/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch +++ b/target/linux/generic/pending-6.6/840-hwrng-bcm2835-set-quality-to-1000.patch @@ -16,7 +16,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c -@@ -170,6 +170,7 @@ static int bcm2835_rng_probe(struct plat +@@ -169,6 +169,7 @@ static int bcm2835_rng_probe(struct plat priv->rng.init = bcm2835_rng_init; priv->rng.read = bcm2835_rng_read; priv->rng.cleanup = bcm2835_rng_cleanup; diff --git a/target/linux/generic/pending-6.6/920-mangle_bootargs.patch b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch index 0d690e42e8..2ce1b9ccb5 100644 --- a/target/linux/generic/pending-6.6/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.6/920-mangle_bootargs.patch @@ -13,7 +13,7 @@ Signed-off-by: Imre Kaloz --- a/init/Kconfig +++ b/init/Kconfig -@@ -1827,6 +1827,15 @@ config EMBEDDED +@@ -1811,6 +1811,15 @@ config DEBUG_RSEQ If unsure, say N. @@ -31,7 +31,7 @@ Signed-off-by: Imre Kaloz help --- a/init/main.c +++ b/init/main.c -@@ -611,6 +611,29 @@ static inline void setup_nr_cpu_ids(void +@@ -608,6 +608,29 @@ static inline void setup_nr_cpu_ids(void static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif @@ -61,7 +61,7 @@ Signed-off-by: Imre Kaloz /* * We need to store the untouched command line for future reference. * We also need to store the touched command line since the parameter -@@ -958,6 +981,7 @@ asmlinkage __visible void __init __no_sa +@@ -895,6 +918,7 @@ void start_kernel(void) pr_notice("%s", linux_banner); early_security_init(); setup_arch(&command_line); From 9a673642a28ca0f42c3c7ac666d5d4f85d7c3978 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 8 Mar 2024 22:04:26 +0800 Subject: [PATCH 048/108] generic: 6.6: refresh hack patches Refresh hack patches with make target/linux/refresh. Signed-off-by: Weijie Gao --- .../generic/hack-6.6/204-module_strip.patch | 22 +++++++++---------- .../211-darwin-uuid-typedef-clash.patch | 2 +- .../hack-6.6/212-tools_portability.patch | 20 ++++++++--------- .../hack-6.6/220-arm-gc_sections.patch | 14 ++++++------ .../generic/hack-6.6/221-module_exports.patch | 12 +++++----- .../hack-6.6/230-openwrt_lzma_options.patch | 2 +- .../hack-6.6/250-netfilter_depends.patch | 4 ++-- .../linux/generic/hack-6.6/251-kconfig.patch | 12 +++++----- .../generic/hack-6.6/253-ksmbd-config.patch | 4 ++-- .../generic/hack-6.6/259-regmap_dynamic.patch | 4 ++-- .../hack-6.6/261-lib-arc4-unhide.patch | 2 +- ...rans-call-add-disks-after-mtd-device.patch | 4 ++-- ...upport-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch | 2 +- ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 8 +++---- .../hack-6.6/651-wireless_mesh_header.patch | 2 +- ...t-size-the-hashtable-more-adequately.patch | 2 +- .../700-swconfig_switch_drivers.patch | 4 ++-- ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 2 +- .../721-net-add-packet-mangeling.patch | 18 +++++++-------- ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 4 ++-- ...mtk-lynxi-workaround-2500BaseX-no-an.patch | 6 ++--- ...-r8152-add-LED-configuration-from-OF.patch | 8 +++---- .../765-mxl-gpy-control-LED-reg-from-DT.patch | 8 +++---- .../780-usb-net-MeigLink_modem_support.patch | 2 +- .../790-SFP-GE-T-ignore-TX_FAULT.patch | 6 ++--- .../800-GPIO-add-named-gpio-exports.patch | 9 ++++---- .../810-bcma-ssb-fallback-sprom.patch | 2 +- .../hack-6.6/901-debloat_sock_diag.patch | 12 +++++----- .../generic/hack-6.6/902-debloat_proc.patch | 20 ++++++++--------- .../hack-6.6/904-debloat_dma_buf.patch | 6 ++--- .../911-kobject_add_broadcast_uevent.patch | 2 +- .../hack-6.6/920-device_tree_cmdline.patch | 2 +- ...vert-driver-core-Set-fw_devlink-on-b.patch | 2 +- 33 files changed, 114 insertions(+), 115 deletions(-) diff --git a/target/linux/generic/hack-6.6/204-module_strip.patch b/target/linux/generic/hack-6.6/204-module_strip.patch index 6ff9d6a13b..32a83ece9f 100644 --- a/target/linux/generic/hack-6.6/204-module_strip.patch +++ b/target/linux/generic/hack-6.6/204-module_strip.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/module.h +++ b/include/linux/module.h -@@ -163,6 +163,7 @@ extern void cleanup_module(void); +@@ -164,6 +164,7 @@ extern void cleanup_module(void); /* Generic info of form tag = "info" */ #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info) @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau /* For userspace: you can also call me... */ #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) -@@ -232,12 +233,12 @@ extern void cleanup_module(void); +@@ -233,12 +234,12 @@ extern void cleanup_module(void); * Author(s), use "Name " or just "Name", for multiple * authors use multiple MODULE_AUTHOR() statements/lines. */ @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* Creates an alias so file2alias.c can find device table. */ #define MODULE_DEVICE_TABLE(type, name) \ extern typeof(name) __mod_##type##__##name##_device_table \ -@@ -264,7 +265,9 @@ extern typeof(name) __mod_##type##__##na +@@ -265,7 +266,9 @@ extern typeof(name) __mod_##type##__##na */ #if defined(MODULE) || !defined(CONFIG_SYSFS) @@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau #else #define MODULE_VERSION(_version) \ MODULE_INFO(version, _version); \ -@@ -287,7 +290,7 @@ extern typeof(name) __mod_##type##__##na +@@ -288,7 +291,7 @@ extern typeof(name) __mod_##type##__##na /* Optional firmware file (or files) needed by the module * format is simply firmware file name. Multiple firmware * files require multiple MODULE_FIRMWARE() specifiers */ @@ -88,7 +88,7 @@ Signed-off-by: Felix Fietkau --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig -@@ -290,4 +290,11 @@ config MODULES_TREE_LOOKUP +@@ -389,4 +389,11 @@ config MODULES_TREE_LOOKUP def_bool y depends on PERF_EVENTS || TRACING || CFI_CLANG @@ -141,7 +141,7 @@ Signed-off-by: Felix Fietkau if (err) --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c -@@ -1785,7 +1785,9 @@ static void read_symbols(const char *mod +@@ -1745,7 +1745,9 @@ static void read_symbols(const char *mod symname = remove_dot(info.strtab + sym->st_name); handle_symbol(mod, &info, sym, symname); @@ -151,7 +151,7 @@ Signed-off-by: Felix Fietkau } check_sec_ref(mod, &info); -@@ -1944,8 +1946,10 @@ static void add_header(struct buffer *b, +@@ -1918,8 +1920,10 @@ static void add_header(struct buffer *b, buf_printf(b, "BUILD_SALT;\n"); buf_printf(b, "BUILD_LTO_INFO;\n"); buf_printf(b, "\n"); @@ -162,7 +162,7 @@ Signed-off-by: Felix Fietkau buf_printf(b, "\n"); buf_printf(b, "__visible struct module __this_module\n"); buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n"); -@@ -1963,8 +1967,10 @@ static void add_header(struct buffer *b, +@@ -1933,8 +1937,10 @@ static void add_header(struct buffer *b, buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n"); buf_printf(b, "};\n"); @@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau buf_printf(b, "\n" -@@ -1972,8 +1978,10 @@ static void add_header(struct buffer *b, +@@ -1942,8 +1948,10 @@ static void add_header(struct buffer *b, "MODULE_INFO(retpoline, \"Y\");\n" "#endif\n"); @@ -184,7 +184,7 @@ Signed-off-by: Felix Fietkau if (strstarts(mod->name, "tools/testing")) buf_printf(b, "\nMODULE_INFO(test, \"Y\");\n"); -@@ -2069,11 +2077,13 @@ static void add_depends(struct buffer *b +@@ -2053,11 +2061,13 @@ static void add_depends(struct buffer *b static void add_srcversion(struct buffer *b, struct module *mod) { @@ -198,7 +198,7 @@ Signed-off-by: Felix Fietkau } static void write_buf(struct buffer *b, const char *fname) -@@ -2159,7 +2169,9 @@ static void write_mod_c_file(struct modu +@@ -2140,7 +2150,9 @@ static void write_mod_c_file(struct modu add_exported_symbols(&buf, mod); add_versions(&buf, mod); add_depends(&buf, mod); diff --git a/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch index 9a1905a138..c0e0b24e3c 100644 --- a/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch +++ b/target/linux/generic/hack-6.6/211-darwin-uuid-typedef-clash.patch @@ -10,7 +10,7 @@ Signed-off-by: Kevin Darbyshire-Bryant --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c -@@ -38,6 +38,9 @@ typedef struct { +@@ -35,6 +35,9 @@ typedef uint32_t __u32; typedef uint16_t __u16; typedef unsigned char __u8; diff --git a/target/linux/generic/hack-6.6/212-tools_portability.patch b/target/linux/generic/hack-6.6/212-tools_portability.patch index 4671e75128..ec10f4b966 100644 --- a/target/linux/generic/hack-6.6/212-tools_portability.patch +++ b/target/linux/generic/hack-6.6/212-tools_portability.patch @@ -73,7 +73,7 @@ Signed-off-by: Felix Fietkau struct page; struct kmem_cache; -@@ -51,7 +55,9 @@ typedef __s8 s8; +@@ -56,7 +60,9 @@ typedef __s8 s8; #define __user #endif #define __must_check @@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau typedef __u16 __bitwise __be16; --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py -@@ -684,6 +684,7 @@ def main() -> None: +@@ -1197,6 +1197,7 @@ such as "arm/cortex-a34".''', #include "util/header.h" #include "util/pmu.h" #include @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN) --- a/tools/arch/x86/include/asm/orc_types.h +++ b/tools/arch/x86/include/asm/orc_types.h -@@ -40,7 +40,6 @@ +@@ -46,7 +46,6 @@ #define ORC_TYPE_REGS_PARTIAL 4 #ifndef __ASSEMBLY__ @@ -115,7 +115,7 @@ Signed-off-by: Felix Fietkau /* * This struct is more or less a vastly simplified version of the DWARF Call -@@ -53,12 +52,12 @@ +@@ -59,12 +58,12 @@ struct orc_entry { s16 sp_offset; s16 bp_offset; @@ -199,7 +199,7 @@ Signed-off-by: Felix Fietkau unsigned long __rb_parent_color; --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile -@@ -40,7 +40,7 @@ include ../scripts/Makefile.arch +@@ -40,7 +40,7 @@ elfshdr := $(shell echo '$(pound)include OBJTOOL_CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED) # Always want host compilation. @@ -208,7 +208,7 @@ Signed-off-by: Felix Fietkau AWK = awk MKDIR = mkdir -@@ -43,6 +43,7 @@ BUILD_ORC := n +@@ -55,6 +55,7 @@ BUILD_ORC := n ifeq ($(SRCARCH),x86) BUILD_ORC := y @@ -218,7 +218,7 @@ Signed-off-by: Felix Fietkau export BUILD_ORC --- a/tools/objtool/check.c +++ b/tools/objtool/check.c -@@ -1164,11 +1164,12 @@ static int add_ignore_alternatives(struc +@@ -1288,11 +1288,12 @@ static int add_ignore_alternatives(struc return 0; } @@ -232,7 +232,7 @@ Signed-off-by: Felix Fietkau { return false; } -@@ -1177,7 +1178,7 @@ __weak bool arch_is_retpoline(struct sym +@@ -1301,7 +1302,7 @@ __weak bool arch_is_retpoline(struct sym * Symbols that replace INSN_RETURN, every (tail) call to such a symbol * will be added to the .return_sites section. */ @@ -241,7 +241,7 @@ Signed-off-by: Felix Fietkau { return false; } -@@ -1186,10 +1187,11 @@ __weak bool arch_is_rethunk(struct symbo +@@ -1310,10 +1311,11 @@ __weak bool arch_is_rethunk(struct symbo * Symbols that are embedded inside other instructions, because sometimes crazy * code exists. These are mostly ignored for validation purposes. */ @@ -297,7 +297,7 @@ Signed-off-by: Felix Fietkau struct instruction *insn) --- a/tools/objtool/special.c +++ b/tools/objtool/special.c -@@ -54,9 +54,11 @@ struct special_entry entries[] = { +@@ -54,9 +54,11 @@ static const struct special_entry entrie {}, }; diff --git a/target/linux/generic/hack-6.6/220-arm-gc_sections.patch b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch index 257796aee9..eb49704ff7 100644 --- a/target/linux/generic/hack-6.6/220-arm-gc_sections.patch +++ b/target/linux/generic/hack-6.6/220-arm-gc_sections.patch @@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos --- --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -124,6 +124,7 @@ config ARM +@@ -128,6 +128,7 @@ config ARM select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select IRQ_FORCED_THREADING select LOCK_MM_AND_FIND_VMA @@ -22,7 +22,7 @@ Signed-off-by: Gabor Juhos select OF_EARLY_FLATTREE if OF --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile -@@ -91,6 +91,7 @@ endif +@@ -92,6 +92,7 @@ endif ifeq ($(CONFIG_USE_OF),y) OBJS += $(libfdt_objs) fdt_check_mem_start.o endif @@ -32,7 +32,7 @@ Signed-off-by: Gabor Juhos --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S -@@ -75,7 +75,7 @@ SECTIONS +@@ -74,7 +74,7 @@ SECTIONS . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; @@ -41,7 +41,7 @@ Signed-off-by: Gabor Juhos __stop___ex_table = .; } -@@ -100,24 +100,24 @@ SECTIONS +@@ -99,24 +99,24 @@ SECTIONS } .init.arch.info : { __arch_info_begin = .; @@ -88,7 +88,7 @@ Signed-off-by: Gabor Juhos __idmap_text_end = .; \ #define ARM_DISCARD \ -@@ -109,12 +109,12 @@ +@@ -108,12 +108,12 @@ . = ALIGN(8); \ .ARM.unwind_idx : { \ __start_unwind_idx = .; \ @@ -103,7 +103,7 @@ Signed-off-by: Gabor Juhos __stop_unwind_tab = .; \ } -@@ -126,7 +126,7 @@ +@@ -125,7 +125,7 @@ __vectors_lma = .; \ OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \ .vectors { \ @@ -112,7 +112,7 @@ Signed-off-by: Gabor Juhos } \ .vectors.bhb.loop8 { \ *(.vectors.bhb.loop8) \ -@@ -144,7 +144,7 @@ +@@ -143,7 +143,7 @@ \ __stubs_lma = .; \ .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) { \ diff --git a/target/linux/generic/hack-6.6/221-module_exports.patch b/target/linux/generic/hack-6.6/221-module_exports.patch index 5af4eba372..294944a34b 100644 --- a/target/linux/generic/hack-6.6/221-module_exports.patch +++ b/target/linux/generic/hack-6.6/221-module_exports.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau /* Align . function alignment. */ #define ALIGN_FUNCTION() . = ALIGN(CONFIG_FUNCTION_ALIGNMENT) -@@ -511,14 +521,14 @@ +@@ -486,14 +496,14 @@ /* Kernel symbol table: Normal symbols */ \ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ __start___ksymtab = .; \ @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau __stop___ksymtab_gpl = .; \ } \ \ -@@ -538,7 +548,7 @@ +@@ -513,7 +523,7 @@ \ /* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau } \ \ /* __*init sections */ \ -@@ -1042,6 +1052,8 @@ +@@ -1000,6 +1010,8 @@ #define COMMON_DISCARDS \ SANITIZER_DISCARDS \ PATCHABLE_DISCARDS \ @@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau *(.export_symbol) \ --- a/include/linux/export-internal.h +++ b/include/linux/export-internal.h -@@ -23,6 +23,12 @@ +@@ -26,6 +26,12 @@ #define __KSYM_REF(sym) ".long " #sym #endif @@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau /* * For every exported symbol, do the following: * -@@ -35,7 +41,7 @@ +@@ -38,7 +44,7 @@ * former apparently works on all arches according to the binutils source. */ #define __KSYMTAB(name, sym, sec, ns) \ @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau "__kstrtabns_" #name ":" "\n" \ --- a/scripts/Makefile.build +++ b/scripts/Makefile.build -@@ -388,7 +388,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa +@@ -366,7 +366,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa # Linker scripts preprocessor (.lds.S -> .lds) # --------------------------------------------------------------------------- quiet_cmd_cpp_lds_S = LDS $@ diff --git a/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch index 55530c5c7e..a22acafea1 100644 --- a/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch +++ b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch @@ -23,7 +23,7 @@ Signed-off-by: Imre Kaloz { {0x02, 0x21}, "lz4", unlz4 }, --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -443,10 +443,10 @@ quiet_cmd_bzip2_with_size = BZIP2 $@ +@@ -456,10 +456,10 @@ quiet_cmd_bzip2_with_size = BZIP2 $@ # --------------------------------------------------------------------------- quiet_cmd_lzma = LZMA $@ diff --git a/target/linux/generic/hack-6.6/250-netfilter_depends.patch b/target/linux/generic/hack-6.6/250-netfilter_depends.patch index fbb5a61157..43faa9959e 100644 --- a/target/linux/generic/hack-6.6/250-netfilter_depends.patch +++ b/target/linux/generic/hack-6.6/250-netfilter_depends.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -253,7 +253,6 @@ config NF_CONNTRACK_FTP +@@ -259,7 +259,6 @@ config NF_CONNTRACK_FTP config NF_CONNTRACK_H323 tristate "H.323 protocol support" @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau depends on NETFILTER_ADVANCED help H.323 is a VoIP signalling protocol from ITU-T. As one of the most -@@ -1118,7 +1117,6 @@ config NETFILTER_XT_TARGET_SECMARK +@@ -1120,7 +1119,6 @@ config NETFILTER_XT_TARGET_SECMARK config NETFILTER_XT_TARGET_TCPMSS tristate '"TCPMSS" target support' diff --git a/target/linux/generic/hack-6.6/251-kconfig.patch b/target/linux/generic/hack-6.6/251-kconfig.patch index 0cdbe948a1..845cfbfcc8 100644 --- a/target/linux/generic/hack-6.6/251-kconfig.patch +++ b/target/linux/generic/hack-6.6/251-kconfig.patch @@ -34,7 +34,7 @@ Signed-off-by: John Crispin select CRYPTO_AEAD2 select CRYPTO_ALGAPI -@@ -75,7 +75,7 @@ config CRYPTO_AEAD2 +@@ -82,7 +82,7 @@ config CRYPTO_SIG2 select CRYPTO_ALGAPI2 config CRYPTO_SKCIPHER @@ -43,7 +43,7 @@ Signed-off-by: John Crispin select CRYPTO_SKCIPHER2 select CRYPTO_ALGAPI -@@ -85,7 +85,7 @@ config CRYPTO_SKCIPHER2 +@@ -91,7 +91,7 @@ config CRYPTO_SKCIPHER2 select CRYPTO_ALGAPI2 config CRYPTO_HASH @@ -52,7 +52,7 @@ Signed-off-by: John Crispin select CRYPTO_HASH2 select CRYPTO_ALGAPI -@@ -94,7 +94,7 @@ config CRYPTO_HASH2 +@@ -100,7 +100,7 @@ config CRYPTO_HASH2 select CRYPTO_ALGAPI2 config CRYPTO_RNG @@ -92,7 +92,7 @@ Signed-off-by: John Crispin bool --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -457,16 +457,16 @@ config BCH_CONST_T +@@ -460,16 +460,16 @@ config BCH_CONST_T # Textsearch support is select'ed if needed # config TEXTSEARCH @@ -135,7 +135,7 @@ Signed-off-by: John Crispin config SND_SEQ_DEVICE tristate -@@ -27,7 +27,7 @@ config SND_RAWMIDI +@@ -40,7 +40,7 @@ config SND_UMP_LEGACY_RAWMIDI The device contains 16 substreams corresponding to UMP groups. config SND_COMPRESS_OFFLOAD @@ -146,7 +146,7 @@ Signed-off-by: John Crispin bool --- a/net/Kconfig +++ b/net/Kconfig -@@ -430,7 +430,7 @@ config NET_DEVLINK +@@ -467,7 +467,7 @@ config NET_DEVLINK default n config PAGE_POOL diff --git a/target/linux/generic/hack-6.6/253-ksmbd-config.patch b/target/linux/generic/hack-6.6/253-ksmbd-config.patch index a57c914180..298a0787b7 100644 --- a/target/linux/generic/hack-6.6/253-ksmbd-config.patch +++ b/target/linux/generic/hack-6.6/253-ksmbd-config.patch @@ -10,7 +10,7 @@ Subject: [PATCH] Kconfig: add tristate for OID and ASNI string --- a/init/Kconfig +++ b/init/Kconfig -@@ -2013,7 +2013,7 @@ config PADATA +@@ -1989,7 +1989,7 @@ config PADATA bool config ASN1 @@ -21,7 +21,7 @@ Subject: [PATCH] Kconfig: add tristate for OID and ASNI string that can be interpreted by the ASN.1 stream decoder and used to --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -637,7 +637,7 @@ config LIBFDT +@@ -647,7 +647,7 @@ config LIBFDT bool config OID_REGISTRY diff --git a/target/linux/generic/hack-6.6/259-regmap_dynamic.patch b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch index c62e0a6242..8a799679bf 100644 --- a/target/linux/generic/hack-6.6/259-regmap_dynamic.patch +++ b/target/linux/generic/hack-6.6/259-regmap_dynamic.patch @@ -137,7 +137,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -3513,3 +3514,5 @@ static int __init regmap_initcall(void) +@@ -3433,3 +3434,5 @@ static int __init regmap_initcall(void) return 0; } postcore_initcall(regmap_initcall); @@ -145,7 +145,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/include/linux/regmap.h +++ b/include/linux/regmap.h -@@ -180,7 +180,7 @@ struct reg_sequence { +@@ -197,7 +197,7 @@ struct reg_sequence { __ret ?: __tmp; \ }) diff --git a/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch index 64b4ca4521..af1d286208 100644 --- a/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch +++ b/target/linux/generic/hack-6.6/261-lib-arc4-unhide.patch @@ -13,7 +13,7 @@ from backports. --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig -@@ -9,7 +9,7 @@ config CRYPTO_LIB_AES +@@ -15,7 +15,7 @@ config CRYPTO_LIB_AESGCM select CRYPTO_LIB_UTILS config CRYPTO_LIB_ARC4 diff --git a/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index c82ca3edd8..29607b155d 100644 --- a/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/target/linux/generic/hack-6.6/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -83,7 +83,7 @@ Signed-off-by: Daniel Golle unsigned long flags; --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -32,6 +32,7 @@ +@@ -33,6 +33,7 @@ #include #include @@ -91,7 +91,7 @@ Signed-off-by: Daniel Golle #include "mtdcore.h" -@@ -1098,6 +1099,8 @@ int mtd_device_parse_register(struct mtd +@@ -1125,6 +1126,8 @@ int mtd_device_parse_register(struct mtd register_reboot_notifier(&mtd->reboot_notifier); } diff --git a/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch index 726a2a0f18..c32d8ec184 100644 --- a/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch +++ b/target/linux/generic/hack-6.6/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch @@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -773,7 +773,8 @@ int add_mtd_device(struct mtd_info *mtd) +@@ -801,7 +801,8 @@ int add_mtd_device(struct mtd_info *mtd) mutex_unlock(&mtd_table_mutex); diff --git a/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index 59a5fb4d91..cb7ac007b1 100644 --- a/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-6.6/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -1023,6 +1023,15 @@ config NETFILTER_XT_TARGET_NOTRACK +@@ -1025,6 +1025,15 @@ config NETFILTER_XT_TARGET_NOTRACK depends on NETFILTER_ADVANCED select NETFILTER_XT_TARGET_CT @@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau depends on NETFILTER_ADVANCED --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile -@@ -154,6 +154,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF +@@ -163,6 +163,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o @@ -749,7 +749,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -374,8 +373,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -377,8 +376,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -759,7 +759,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct nf_flowtable *flowtable, struct flow_offload *flow, void *data), void *data) -@@ -436,6 +434,7 @@ static void nf_flow_offload_gc_step(stru +@@ -439,6 +437,7 @@ static void nf_flow_offload_gc_step(stru nf_flow_offload_stats(flow_table, flow); } } diff --git a/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch b/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch index fd7d5346ad..3a2a9970bd 100644 --- a/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch +++ b/target/linux/generic/hack-6.6/651-wireless_mesh_header.patch @@ -11,7 +11,7 @@ Signed-off-by: Imre Kaloz --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -149,8 +149,8 @@ static inline bool dev_xmit_complete(int +@@ -157,8 +157,8 @@ static inline bool dev_xmit_complete(int #if defined(CONFIG_HYPERV_NET) # define LL_MAX_HEADER 128 diff --git a/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch b/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch index fe94a9da0c..020f3f3a11 100644 --- a/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch +++ b/target/linux/generic/hack-6.6/661-kernel-ct-size-the-hashtable-more-adequately.patch @@ -14,7 +14,7 @@ Signed-off-by: Rui Salvaterra --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c -@@ -2705,7 +2705,7 @@ int nf_conntrack_init_start(void) +@@ -2682,7 +2682,7 @@ int nf_conntrack_init_start(void) if (!nf_conntrack_htable_size) { nf_conntrack_htable_size diff --git a/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch index 673082d840..4428ebbb5a 100644 --- a/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch +++ b/target/linux/generic/hack-6.6/700-swconfig_switch_drivers.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -67,6 +67,80 @@ config SFP +@@ -66,6 +66,80 @@ config SFP depends on HWMON || HWMON=n select MDIO_I2C @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau config AIR_EN8811H_PHY --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -24,6 +24,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ +@@ -26,6 +26,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ obj-$(CONFIG_PHYLINK) += phylink.o obj-$(CONFIG_PHYLIB) += libphy.o diff --git a/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch index f09ad117b0..6a2c60107b 100644 --- a/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch +++ b/target/linux/generic/hack-6.6/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -9,7 +9,7 @@ Subject: [PATCH] net/dsa/mv88e6xxx: disable ATU violation --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3488,6 +3488,9 @@ static int mv88e6xxx_setup_port(struct m +@@ -3305,6 +3305,9 @@ static int mv88e6xxx_setup_port(struct m else reg = 1 << port; diff --git a/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch index 64465fae2a..2fd8aef2b5 100644 --- a/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.6/721-net-add-packet-mangeling.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1707,6 +1707,7 @@ enum netdev_priv_flags { +@@ -1759,6 +1759,7 @@ enum netdev_priv_flags { IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), IFF_SEE_ALL_HWTSTAMP_REQUESTS = BIT_ULL(33), @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN -@@ -1763,6 +1764,7 @@ enum netdev_priv_flags { +@@ -1792,6 +1793,7 @@ enum netdev_priv_flags { #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -2131,6 +2133,11 @@ struct net_device { +@@ -2184,6 +2186,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned char operstate; -@@ -2206,6 +2213,10 @@ struct net_device { +@@ -2259,6 +2266,10 @@ struct net_device { struct mctp_dev __rcu *mctp_ptr; #endif @@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau */ --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -3040,6 +3040,10 @@ static inline int pskb_trim(struct sk_bu +@@ -3075,6 +3075,10 @@ static inline int pskb_trim(struct sk_bu return (len < skb->len) ? __pskb_trim(skb, len) : 0; } @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau /** * pskb_trim_unique - remove end from a paged unique (not cloned) buffer * @skb: buffer to alter -@@ -3189,16 +3193,6 @@ static inline struct sk_buff *dev_alloc_ +@@ -3240,16 +3244,6 @@ static inline struct sk_buff *dev_alloc_ } @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3607,6 +3607,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3571,6 +3571,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); @@ -119,7 +119,7 @@ Signed-off-by: Felix Fietkau rc = netdev_start_xmit(skb, dev, txq, more); --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -61,6 +61,7 @@ +@@ -62,6 +62,7 @@ #include #include #include @@ -127,7 +127,7 @@ Signed-off-by: Felix Fietkau #include #include -@@ -709,6 +710,22 @@ skb_fail: +@@ -844,6 +845,22 @@ skb_fail: } EXPORT_SYMBOL(__napi_alloc_skb); diff --git a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index bee48be007..ee7d0c57b0 100644 --- a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -898,6 +900,30 @@ static struct phy_driver aqr_driver[] = +@@ -972,6 +974,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle }; module_phy_driver(aqr_driver); -@@ -917,6 +943,8 @@ static struct mdio_device_id __maybe_unu +@@ -991,6 +1017,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, diff --git a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch index b50973f20b..30a502a237 100644 --- a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch +++ b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -92,14 +92,23 @@ static void mtk_pcs_lynxi_get_state(struct +@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru struct phylink_link_state *state) { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); @@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle } static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) -@@ -109,7 +118,7 @@ static int mtk_pcs_lynxi_config(struct p +@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); bool mode_changed = false, changed; @@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle int advertise, link_timer; advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -@@ -132,9 +141,8 @@ static int mtk_pcs_lynxi_config(struct p +@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { if (interface == PHY_INTERFACE_MODE_SGMII) sgm_mode |= SGMII_SPEED_DUPLEX_AN; diff --git a/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch index 9ef11623fc..190dd3507c 100644 --- a/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch +++ b/target/linux/generic/hack-6.6/760-net-usb-r8152-add-LED-configuration-from-OF.patch @@ -22,7 +22,7 @@ Signed-off-by: David Bauer #include #include #include -@@ -7034,6 +7035,22 @@ static void rtl_tally_reset(struct r8152 +@@ -7035,6 +7036,22 @@ static void rtl_tally_reset(struct r8152 ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); } @@ -45,7 +45,7 @@ Signed-off-by: David Bauer static void r8152b_init(struct r8152 *tp) { u32 ocp_data; -@@ -7075,6 +7092,8 @@ static void r8152b_init(struct r8152 *tp +@@ -7076,6 +7093,8 @@ static void r8152b_init(struct r8152 *tp ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); @@ -54,7 +54,7 @@ Signed-off-by: David Bauer } static void r8153_init(struct r8152 *tp) -@@ -7215,6 +7234,8 @@ static void r8153_init(struct r8152 *tp) +@@ -7216,6 +7235,8 @@ static void r8153_init(struct r8152 *tp) tp->coalesce = COALESCE_SLOW; break; } @@ -63,7 +63,7 @@ Signed-off-by: David Bauer } static void r8153b_init(struct r8152 *tp) -@@ -7297,6 +7318,8 @@ static void r8153b_init(struct r8152 *tp +@@ -7298,6 +7319,8 @@ static void r8153b_init(struct r8152 *tp rtl_tally_reset(tp); tp->coalesce = 15000; /* 15 us */ diff --git a/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch index dc582bba28..51a03be2ad 100644 --- a/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch +++ b/target/linux/generic/hack-6.6/765-mxl-gpy-control-LED-reg-from-DT.patch @@ -31,7 +31,7 @@ Signed-off-by: David Bauer #include #include #include -@@ -33,6 +34,7 @@ +@@ -38,6 +39,7 @@ #define PHY_MIISTAT 0x18 /* MII state */ #define PHY_IMASK 0x19 /* interrupt mask */ #define PHY_ISTAT 0x1A /* interrupt status */ @@ -39,7 +39,7 @@ Signed-off-by: David Bauer #define PHY_FWV 0x1E /* firmware version */ #define PHY_MIISTAT_SPD_MASK GENMASK(2, 0) -@@ -56,10 +58,15 @@ +@@ -61,10 +63,15 @@ PHY_IMASK_ADSC | \ PHY_IMASK_ANC) @@ -55,7 +55,7 @@ Signed-off-by: David Bauer #define PHY_PMA_MGBT_POLARITY 0x82 #define PHY_MDI_MDI_X_MASK GENMASK(1, 0) #define PHY_MDI_MDI_X_NORMAL 0x3 -@@ -241,6 +248,35 @@ out: +@@ -260,6 +267,35 @@ out: return ret; } @@ -91,7 +91,7 @@ Signed-off-by: David Bauer static int gpy_config_init(struct phy_device *phydev) { int ret; -@@ -252,7 +288,10 @@ static int gpy_config_init(struct phy_de +@@ -271,7 +307,10 @@ static int gpy_config_init(struct phy_de /* Clear all pending interrupts */ ret = phy_read(phydev, PHY_ISTAT); diff --git a/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch index 51f939356f..794a28b716 100644 --- a/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch @@ -10,7 +10,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c -@@ -1082,12 +1082,18 @@ static const struct usb_device_id produc +@@ -1083,12 +1083,18 @@ static const struct usb_device_id produc USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, }, diff --git a/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch index 8fb8aa84d5..d48f382ce5 100644 --- a/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch +++ b/target/linux/generic/hack-6.6/790-SFP-GE-T-ignore-TX_FAULT.patch @@ -26,7 +26,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -409,6 +409,9 @@ static const struct sfp_quirk sfp_quirks +@@ -471,6 +471,9 @@ static const struct sfp_quirk sfp_quirks // FS 2.5G Base-T SFP_QUIRK_M("FS", "SFP-2.5G-T", sfp_quirk_oem_2_5g), @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle // Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report // 2500MBd NRZ in their EEPROM SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex), -@@ -2344,7 +2347,8 @@ static void sfp_sm_main(struct sfp *sfp, +@@ -2587,7 +2590,8 @@ static void sfp_sm_main(struct sfp *sfp, * or t_start_up, so assume there is a fault. */ sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, @@ -46,7 +46,7 @@ Signed-off-by: Daniel Golle } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) { init_done: /* Create mdiobus and start trying for PHY */ -@@ -2578,10 +2582,12 @@ static void sfp_check_state(struct sfp * +@@ -2841,10 +2845,12 @@ static void sfp_check_state(struct sfp * mutex_lock(&sfp->st_mutex); state = sfp_get_state(sfp); changed = state ^ sfp->state; diff --git a/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch index 59acb9e57b..666dcfad4d 100644 --- a/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.6/800-GPIO-add-named-gpio-exports.patch @@ -103,7 +103,7 @@ Signed-off-by: John Crispin int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); void gpiod_unexport(struct gpio_desc *desc); -@@ -653,12 +656,26 @@ void gpiod_unexport(struct gpio_desc *de +@@ -653,11 +656,25 @@ void gpiod_unexport(struct gpio_desc *de #include @@ -119,17 +119,16 @@ Signed-off-by: John Crispin { return -ENOSYS; } - ++ +static inline int gpio_export_with_name(struct gpio_desc *desc, + bool direction_may_change, + const char *name) +{ + return -ENOSYS; +} -+ + static inline int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc) - { --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -557,7 +557,7 @@ static struct class gpio_class = { @@ -150,7 +149,7 @@ Signed-off-by: John Crispin dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, -@@ -640,8 +642,21 @@ int gpiod_export(struct gpio_desc *desc, +@@ -640,8 +642,21 @@ err_unlock: gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } diff --git a/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch b/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch index c581a512cb..9375a721b5 100644 --- a/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch +++ b/target/linux/generic/hack-6.6/810-bcma-ssb-fallback-sprom.patch @@ -54,7 +54,7 @@ Subject: [PATCH] ssb_sprom: add generic kernel support for Broadcom Fallback SP --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -668,6 +668,14 @@ static int __init bcma_modinit(void) +@@ -671,6 +671,14 @@ static int __init bcma_modinit(void) { int err; diff --git a/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch index 92b35efa55..b0054da2eb 100644 --- a/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.6/901-debloat_sock_diag.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau --- a/net/Kconfig +++ b/net/Kconfig -@@ -104,6 +104,9 @@ source "net/mptcp/Kconfig" +@@ -129,6 +129,9 @@ source "net/mptcp/Kconfig" endif # if INET @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_PROC_FS) += net-procfs.o --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -117,6 +117,7 @@ +@@ -118,6 +118,7 @@ #include #include #include @@ -53,7 +53,7 @@ Signed-off-by: Felix Fietkau #include -@@ -149,6 +150,7 @@ +@@ -150,6 +151,7 @@ static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau static void sock_def_write_space_wfree(struct sock *sk); static void sock_def_write_space(struct sock *sk); -@@ -588,6 +590,21 @@ int __sk_receive_skb(struct sock *sk, str +@@ -589,6 +591,21 @@ discard_and_relse: } EXPORT_SYMBOL(__sk_receive_skb); @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2238,9 +2255,11 @@ static void __sk_free(struct sock *sk) +@@ -2246,9 +2263,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); @@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau Support for PF_PACKET sockets monitoring interface used by the ss tool. --- a/net/unix/Kconfig +++ b/net/unix/Kconfig -@@ -33,6 +33,7 @@ config AF_UNIX_OOB +@@ -29,6 +29,7 @@ config AF_UNIX_OOB config UNIX_DIAG tristate "UNIX: socket monitoring interface" depends on UNIX diff --git a/target/linux/generic/hack-6.6/902-debloat_proc.patch b/target/linux/generic/hack-6.6/902-debloat_proc.patch index a90169efc9..ea9c20c1ab 100644 --- a/target/linux/generic/hack-6.6/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.6/902-debloat_proc.patch @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau --- a/fs/locks.c +++ b/fs/locks.c -@@ -2909,6 +2909,8 @@ static const struct seq_operations locks +@@ -2897,6 +2897,8 @@ static const struct seq_operations locks static int __init proc_locks_init(void) { @@ -54,7 +54,7 @@ Signed-off-by: Felix Fietkau depends on PROC_FS --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c -@@ -92,6 +92,9 @@ static const struct seq_operations conso +@@ -107,6 +107,9 @@ static const struct seq_operations conso static int __init proc_consoles_init(void) { @@ -235,7 +235,7 @@ Signed-off-by: Felix Fietkau if (!pe) --- a/mm/vmalloc.c +++ b/mm/vmalloc.c -@@ -4205,6 +4205,8 @@ static const struct seq_operations vmall +@@ -4439,6 +4439,8 @@ static const struct seq_operations vmall static int __init proc_vmalloc_init(void) { @@ -246,7 +246,7 @@ Signed-off-by: Felix Fietkau &vmalloc_op, --- a/mm/vmstat.c +++ b/mm/vmstat.c -@@ -2109,10 +2109,12 @@ void __init init_mm_internals(void) +@@ -2135,10 +2135,12 @@ void __init init_mm_internals(void) start_shepherd_timer(); #endif #ifdef CONFIG_PROC_FS @@ -286,7 +286,7 @@ Signed-off-by: Felix Fietkau goto err; --- a/net/core/net-procfs.c +++ b/net/core/net-procfs.c -@@ -319,10 +319,12 @@ static int __net_init dev_proc_net_init( +@@ -327,10 +327,12 @@ static int __net_init dev_proc_net_init( if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops, sizeof(struct seq_net_private))) goto out; @@ -301,7 +301,7 @@ Signed-off-by: Felix Fietkau sizeof(struct seq_net_private))) goto out_softnet; -@@ -332,9 +334,11 @@ static int __net_init dev_proc_net_init( +@@ -340,9 +342,11 @@ static int __net_init dev_proc_net_init( out: return rc; out_ptype: @@ -315,7 +315,7 @@ Signed-off-by: Felix Fietkau out_dev: remove_proc_entry("dev", net->proc_net); goto out; -@@ -344,8 +348,10 @@ static void __net_exit dev_proc_net_exit +@@ -352,8 +356,10 @@ static void __net_exit dev_proc_net_exit { wext_proc_exit(net); @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4114,6 +4114,8 @@ static __net_initdata struct pernet_oper +@@ -4144,6 +4144,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { @@ -385,7 +385,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c -@@ -553,5 +553,8 @@ static __net_initdata struct pernet_oper +@@ -556,5 +556,8 @@ static __net_initdata struct pernet_oper int __init ip_misc_proc_init(void) { @@ -408,7 +408,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c -@@ -269,7 +269,7 @@ void __inet_twsk_schedule(struct inet_ti +@@ -266,7 +266,7 @@ void __inet_twsk_schedule(struct inet_ti */ if (!rearm) { diff --git a/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch index 105eb3da4b..8fdaab5ad6 100644 --- a/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch @@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau +dma-shared-buffer-objs := $(dma-buf-objs-y) --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c -@@ -1636,4 +1636,5 @@ static void __exit dma_buf_deinit(void) +@@ -1731,4 +1731,5 @@ static void __exit dma_buf_deinit(void) kern_unmount(dma_buf_mnt); dma_buf_uninit_sysfs_statistics(); } @@ -73,7 +73,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -4367,6 +4367,7 @@ int wake_up_state(struct task_struct *p, +@@ -4487,6 +4487,7 @@ int wake_up_state(struct task_struct *p, { return try_to_wake_up(p, state, 0); } @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau * Perform scheduler related setup for a newly forked process p. --- a/fs/d_path.c +++ b/fs/d_path.c -@@ -313,6 +313,7 @@ char *dynamic_dname(char *buffer, int bu +@@ -314,6 +314,7 @@ char *dynamic_dname(char *buffer, int bu buffer += buflen - sz; return memcpy(buffer, temp, sz); } diff --git a/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch index 9854585d25..7a21e73dae 100644 --- a/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch +++ b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_UEVENT_HELPER /* path to the userspace helper executed on an event */ extern char uevent_helper[]; -@@ -224,4 +226,7 @@ int kobject_synth_uevent(struct kobject +@@ -219,4 +221,7 @@ int kobject_synth_uevent(struct kobject __printf(2, 3) int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...); diff --git a/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch index cc384bb553..2a43ffb7ad 100644 --- a/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-6.6/920-device_tree_cmdline.patch @@ -9,7 +9,7 @@ Subject: [PATCH] of/ftd: add device tree cmdline --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c -@@ -1183,6 +1183,9 @@ int __init early_init_dt_scan_chosen(cha +@@ -1185,6 +1185,9 @@ int __init early_init_dt_scan_chosen(cha p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); diff --git a/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch b/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch index 04aaab7adf..2cec82bb01 100644 --- a/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch +++ b/target/linux/generic/hack-6.6/930-Revert-Revert-Revert-driver-core-Set-fw_devlink-on-b.patch @@ -19,7 +19,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/base/core.c +++ b/drivers/base/core.c -@@ -1702,7 +1702,7 @@ static void device_links_purge(struct de +@@ -1642,7 +1642,7 @@ static void device_links_purge(struct de #define FW_DEVLINK_FLAGS_RPM (FW_DEVLINK_FLAGS_ON | \ DL_FLAG_PM_RUNTIME) From 7f356a7bd37eacb7446af5e707de9567a7cfd9a3 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 5 Jan 2024 16:31:24 +0800 Subject: [PATCH 049/108] generic: 6.6: add missing symbols Add missing symbols to config for 6.6. Signed-off-by: Robert Marko Signed-off-by: Daniel Golle Signed-off-by: Weijie Gao --- target/linux/generic/config-6.6 | 204 ++++++++++++++++++++++++++++++-- 1 file changed, 196 insertions(+), 8 deletions(-) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 34a6503ce0..0d010a7b03 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -32,6 +32,7 @@ CONFIG_64BIT_TIME=y # CONFIG_AD2S1210 is not set # CONFIG_AD2S90 is not set # CONFIG_AD3552R is not set +# CONFIG_AD4130 is not set # CONFIG_AD5064 is not set # CONFIG_AD5110 is not set # CONFIG_AD525X_DPOT is not set @@ -68,6 +69,7 @@ CONFIG_64BIT_TIME=y # CONFIG_AD7293 is not set # CONFIG_AD7298 is not set # CONFIG_AD7303 is not set +# CONFIG_AD74115 is not set # CONFIG_AD74413R is not set # CONFIG_AD7476 is not set # CONFIG_AD7606 is not set @@ -95,6 +97,7 @@ CONFIG_64BIT_TIME=y # CONFIG_ADE7854 is not set # CONFIG_ADF4350 is not set # CONFIG_ADF4371 is not set +# CONFIG_ADF4377 is not set # CONFIG_ADFS_FS is not set # CONFIG_ADIN1100_PHY is not set # CONFIG_ADIN1110 is not set @@ -144,6 +147,7 @@ CONFIG_AEABI=y # CONFIG_AF_KCM is not set # CONFIG_AF_RXRPC is not set # CONFIG_AF_RXRPC_INJECT_LOSS is not set +# CONFIG_AF_RXRPC_INJECT_RX_DELAY is not set # CONFIG_AF_RXRPC_IPV6 is not set CONFIG_AF_UNIX_OOB=y # CONFIG_AGP is not set @@ -151,6 +155,7 @@ CONFIG_AF_UNIX_OOB=y # CONFIG_AHCI_CEVA is not set # CONFIG_AHCI_DWC is not set # CONFIG_AHCI_IMX is not set +# CONFIG_ARCH_MA35 is not set # CONFIG_AHCI_MVEBU is not set # CONFIG_AHCI_QORIQ is not set # CONFIG_AHCI_XGENE is not set @@ -366,7 +371,10 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_2077057 is not set # CONFIG_ARM64_ERRATUM_2441007 is not set # CONFIG_ARM64_ERRATUM_2441009 is not set +# CONFIG_ARM64_ERRATUM_2645198 is not set # CONFIG_ARM64_ERRATUM_2658417 is not set +# CONFIG_ARM64_ERRATUM_2966298 is not set +# CONFIG_ARM64_ERRATUM_3117295 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set @@ -376,7 +384,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_843419 is not set # CONFIG_ARM64_ERRATUM_845719 is not set # CONFIG_ARM64_ERRATUM_858921 is not set -# CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set CONFIG_ARM64_MODULE_PLTS=y @@ -566,6 +573,7 @@ CONFIG_ATM_CLIP_NO_ICMP=y # CONFIG_BACKLIGHT_GENERIC is not set # CONFIG_BACKLIGHT_GPIO is not set # CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTZ8866 is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_BACKLIGHT_LED is not set # CONFIG_BACKLIGHT_LM3630A is not set @@ -773,6 +781,7 @@ CONFIG_BPF=y CONFIG_BPF_JIT=y # CONFIG_BPF_JIT_ALWAYS_ON is not set CONFIG_BPF_JIT_DEFAULT_ON=y +# CONFIG_BPF_LSM is not set # CONFIG_BPF_PRELOAD is not set # CONFIG_BPF_STREAM_PARSER is not set CONFIG_BPF_SYSCALL=y @@ -832,6 +841,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y # CONFIG_BT_CMTP is not set # CONFIG_BT_FEATURE_DEBUG is not set # CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBCM4377 is not set # CONFIG_BT_HCIBFUSB is not set # CONFIG_BT_HCIBLUECARD is not set # CONFIG_BT_HCIBPA10X is not set @@ -840,6 +850,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y # CONFIG_BT_HCIBTUSB is not set # CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set # CONFIG_BT_HCIBTUSB_MTK is not set +CONFIG_BT_HCIBTUSB_POLL_SYNC=y # CONFIG_BT_HCIBTUSB_RTL is not set # CONFIG_BT_HCIDTL1 is not set # CONFIG_BT_HCIUART is not set @@ -857,10 +868,12 @@ CONFIG_BT_HCIUART_H4=y # CONFIG_BT_HS is not set # CONFIG_BT_LE is not set # CONFIG_BT_LEDS is not set +CONFIG_BT_LE_L2CAP_ECRED=y # CONFIG_BT_MRVL is not set # CONFIG_BT_MSFTEXT is not set # CONFIG_BT_MTKSDIO is not set # CONFIG_BT_MTKUART is not set +# CONFIG_BT_NXPUART is not set # CONFIG_BT_RFCOMM is not set CONFIG_BT_RFCOMM_TTY=y # CONFIG_BT_SELFTEST is not set @@ -873,6 +886,7 @@ CONFIG_BUILDTIME_TABLE_SORT=y CONFIG_BUILD_SALT="" # CONFIG_C2PORT is not set CONFIG_CACHE_L2X0_PMU=y +# CONFIG_CACHESTAT_SYSCALL is not set # CONFIG_CADENCE_WATCHDOG is not set # CONFIG_CAIF is not set # CONFIG_CAN is not set @@ -928,6 +942,7 @@ CONFIG_CC_CAN_LINK=y CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CDROM_PKTCDVD is not set +# CONFIG_CDX_BUS is not set # CONFIG_CEPH_FS is not set # CONFIG_CEPH_LIB is not set # CONFIG_CFG80211 is not set @@ -957,7 +972,10 @@ CONFIG_CFG80211_HEADERS=y # CONFIG_CHARGER_MAX77976 is not set # CONFIG_CHARGER_MAX8903 is not set # CONFIG_CHARGER_QCOM_SMBB is not set +# CONFIG_CHARGER_QCOM_SMB2 is not set # CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_RT9467 is not set +# CONFIG_CHARGER_RT9471 is not set # CONFIG_CHARGER_SBS is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_CHARGER_TWL4030 is not set @@ -1025,6 +1043,7 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_FIXED_MMIO is not set # CONFIG_COMMON_CLK_IPROC is not set # CONFIG_COMMON_CLK_MAX9485 is not set +# CONFIG_COMMON_CLK_MEDIATEK_FHCTL is not set # CONFIG_COMMON_CLK_MT6765 is not set # CONFIG_COMMON_CLK_MT8167 is not set # CONFIG_COMMON_CLK_MT8167_AUDSYS is not set @@ -1032,6 +1051,7 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_MT8167_MFGCFG is not set # CONFIG_COMMON_CLK_MT8167_MMSYS is not set # CONFIG_COMMON_CLK_MT8167_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8188 is not set # CONFIG_COMMON_CLK_MT8192 is not set # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PIC32 is not set @@ -1043,10 +1063,12 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_RP1_SDIO is not set # CONFIG_COMMON_CLK_RS9_PCIE is not set # CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI521XX is not set # CONFIG_COMMON_CLK_SI5341 is not set # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI544 is not set # CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_VC3 is not set # CONFIG_COMMON_CLK_VC5 is not set # CONFIG_COMMON_CLK_VC7 is not set # CONFIG_COMMON_CLK_XGENE is not set @@ -1095,6 +1117,8 @@ CONFIG_CONSTRUCTORS=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set CONFIG_CPU_SW_DOMAIN_PAN=y # CONFIG_CPU_THERMAL is not set +# CONFIG_CPUFREQ_DT is not set +# CONFIG_CPUFREQ_DT_PLATDEV is not set # CONFIG_CRAMFS is not set CONFIG_CRAMFS_BLOCKDEV=y # CONFIG_CRAMFS_MTD is not set @@ -1244,6 +1268,7 @@ CONFIG_CRYPTO_HASH2=y # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_HW is not set # CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE is not set # CONFIG_CRYPTO_KEYWRAP is not set # CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_KPP=y @@ -1368,6 +1393,7 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_CGROUP_REF is not set # CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_DEBUG_DRIVER is not set @@ -1384,7 +1410,8 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_ICEDCC is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_INFO_BTF is not set -# CONFIG_DEBUG_INFO_COMPRESSED is not set +CONFIG_DEBUG_INFO_COMPRESSED_NONE=y +# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set # CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y @@ -1442,6 +1469,7 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_MAPLE_TREE is not set # CONFIG_DEBUG_VM_PGFLAGS is not set # CONFIG_DEBUG_VM_PGTABLE is not set # CONFIG_DEBUG_VM_RB is not set @@ -1515,6 +1543,7 @@ CONFIG_DEVPORT=y # CONFIG_DMARD09 is not set # CONFIG_DMARD10 is not set # CONFIG_DMASCC is not set +# CONFIG_DMAPOOL_TEST is not set # CONFIG_DMATEST is not set # CONFIG_DMA_API_DEBUG is not set CONFIG_DMA_COHERENT_POOL=y @@ -1550,6 +1579,7 @@ CONFIG_DMA_NONCOHERENT_MMAP=y # CONFIG_DM_VERITY is not set # CONFIG_DM_WRITECACHE is not set # CONFIG_DM_ZERO is not set +# CONFIG_DM_ZONED is not set # CONFIG_DNET is not set # CONFIG_DNOTIFY is not set # CONFIG_DNS_RESOLVER is not set @@ -1561,16 +1591,19 @@ CONFIG_DOUBLEFAULT=y # CONFIG_DP83869_PHY is not set # CONFIG_DP83TC811_PHY is not set # CONFIG_DP83TD510_PHY is not set +# CONFIG_DPM_WATCHDOG is not set # CONFIG_DPOT_DAC is not set # CONFIG_DPS310 is not set CONFIG_DQL=y # CONFIG_DRAGONRISE_FF is not set # CONFIG_DRM is not set +# CONFIG_DRM_ACCEL is not set # CONFIG_DRM_AMDGPU is not set # CONFIG_DRM_AMDGPU_CIK is not set # CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set # CONFIG_DRM_AMDGPU_SI is not set # CONFIG_DRM_AMDGPU_USERPTR is not set +# CONFIG_DRM_AMDGPU_WERROR is not set # CONFIG_DRM_AMD_ACP is not set # CONFIG_DRM_AMD_DC_DCN2_0 is not set # CONFIG_DRM_AMD_DC_DCN3_0 is not set @@ -1625,6 +1658,7 @@ CONFIG_DQL=y # CONFIG_DRM_LIMA is not set # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set # CONFIG_DRM_LOGICVC is not set +# CONFIG_DRM_LOONGSON is not set # CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9211 is not set # CONFIG_DRM_LONTIUM_LT9611 is not set @@ -1643,6 +1677,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_ABT_Y030XX067A is not set # CONFIG_DRM_PANEL_ARM_VERSATILE is not set # CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_AUO_A030JTN01 is not set # CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set # CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set # CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set @@ -1677,6 +1712,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +# CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set # CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set # CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set # CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set @@ -1690,6 +1726,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set @@ -1733,6 +1770,7 @@ CONFIG_DQL=y # CONFIG_DRM_RP1_DPI is not set # CONFIG_DRM_RP1_DSI is not set # CONFIG_DRM_RP1_VEC is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set # CONFIG_DRM_SII902X is not set # CONFIG_DRM_SII9234 is not set # CONFIG_DRM_SIL_SII8620 is not set @@ -2060,6 +2098,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_DA8XX is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_DEVICE is not set # CONFIG_FB_FLEX is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_FSL_DIU is not set @@ -2221,6 +2260,7 @@ CONFIG_FSNOTIFY=y # CONFIG_FUJITSU_LAPTOP is not set # CONFIG_FUJITSU_TABLET is not set # CONFIG_FUNCTION_ERROR_INJECTION is not set +# CONFIG_FUNCTION_GRAPH_RETVAL is not set # CONFIG_FUNCTION_TRACER is not set # CONFIG_FUN_ETH is not set # CONFIG_FUSE_FS is not set @@ -2231,8 +2271,10 @@ CONFIG_FSNOTIFY=y CONFIG_FUTEX=y CONFIG_FUTEX_PI=y # CONFIG_FW_CFG_SYSFS is not set +# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER=y # CONFIG_FW_LOADER_COMPRESS is not set +# CONFIG_FW_LOADER_DEBUG is not set CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_UPLOAD is not set @@ -2271,6 +2313,7 @@ CONFIG_GENERIC_VDSO_TIME_NS=y # CONFIG_GLOB_SELFTEST is not set # CONFIG_GNSS is not set # CONFIG_GOLDFISH is not set +# CONFIG_GOOGLE_CBMEM is not set # CONFIG_GOOGLE_FIRMWARE is not set # CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT is not set # CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set @@ -2301,17 +2344,21 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_CDEV_V1 is not set # CONFIG_GPIO_CS5535 is not set # CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_DS4520 is not set # CONFIG_GPIO_EM is not set # CONFIG_GPIO_EXAR is not set # CONFIG_GPIO_F7188X is not set # CONFIG_GPIO_FTGPIO010 is not set +# CONFIG_GPIO_FXL6408 is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GPIO_MM is not set # CONFIG_GPIO_GRGPIO is not set # CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_HISI is not set # CONFIG_GPIO_HLWD is not set # CONFIG_GPIO_ICH is not set # CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LATCH is not set # CONFIG_GPIO_LOGICVC is not set # CONFIG_GPIO_LYNXPOINT is not set # CONFIG_GPIO_MAX3191X is not set @@ -2412,6 +2459,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_BELKIN is not set # CONFIG_HID_BETOP_FF is not set # CONFIG_HID_BIGBEN_FF is not set +# CONFIG_HID_BPF is not set # CONFIG_HID_CHERRY is not set # CONFIG_HID_CHICONY is not set # CONFIG_HID_CMEDIA is not set @@ -2425,6 +2473,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_ELECOM is not set # CONFIG_HID_ELO is not set # CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EVISION is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_FT260 is not set # CONFIG_HID_GEMBIRD is not set @@ -2432,6 +2481,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_GFRM is not set # CONFIG_HID_GLORIOUS is not set # CONFIG_HID_GOOGLE_HAMMER is not set +# CONFIG_HID_GOOGLE_STADIA_FF is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_GT683R is not set # CONFIG_HID_GYRATION is not set @@ -2461,6 +2511,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_NINTENDO is not set # CONFIG_HID_NTI is not set # CONFIG_HID_NTRIG is not set +# CONFIG_HID_NVIDIA_SHIELD is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PENMOUNT is not set @@ -2553,6 +2604,7 @@ CONFIG_HPET_MMAP_DEFAULT=y # CONFIG_HTU21 is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set +# CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON is not set # CONFIG_HVC_DCC is not set # CONFIG_HVC_UDBG is not set # CONFIG_HWLAT_TRACER is not set @@ -2638,6 +2690,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_HID_OF is not set # CONFIG_I2C_HID_OF_ELAN is not set # CONFIG_I2C_HID_OF_GOODIX is not set +# CONFIG_I2C_HISI is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_IBM_IIC is not set # CONFIG_I2C_IMG is not set @@ -2740,6 +2793,8 @@ CONFIG_HZ_100=y CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IIO_CROS_EC_ACCEL_LEGACY is not set # CONFIG_IIO_INTERRUPT_TRIGGER is not set +# CONFIG_IIO_KX022A_I2C is not set +# CONFIG_IIO_KX022A_SPI is not set # CONFIG_IIO_MUX is not set # CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set # CONFIG_IIO_RESCALE is not set @@ -2792,6 +2847,7 @@ CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INGENIC_ADC is not set # CONFIG_INGENIC_CGU_JZ4725B is not set # CONFIG_INGENIC_CGU_JZ4740 is not set +# CONFIG_INGENIC_CGU_JZ4755 is not set # CONFIG_INGENIC_CGU_JZ4760 is not set # CONFIG_INGENIC_CGU_JZ4770 is not set # CONFIG_INGENIC_CGU_JZ4780 is not set @@ -2947,6 +3003,7 @@ CONFIG_IO_WQ=y # CONFIG_IPC_NS is not set # CONFIG_IPMB_DEVICE_INTERFACE is not set # CONFIG_IPMI_HANDLER is not set +# CONFIG_IPU_BRIDGE is not set # CONFIG_IPV6 is not set # CONFIG_IPV6_FOU is not set # CONFIG_IPV6_FOU_TUNNEL is not set @@ -3025,6 +3082,7 @@ CONFIG_IP_VS_MH_TAB_INDEX=10 # CONFIG_IRQ_DOMAIN_DEBUG is not set # CONFIG_IRQ_POLL is not set # CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_IRSD200 is not set # CONFIG_IR_GPIO_CIR is not set # CONFIG_IR_HIX5HD2 is not set # CONFIG_IR_IGORPLUGUSB is not set @@ -3108,6 +3166,7 @@ CONFIG_JOLIET=y # CONFIG_KALLSYMS is not set # CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_SELFTEST is not set CONFIG_KALLSYMS_BASE_RELATIVE=y # CONFIG_KALLSYMS_UNCOMPRESSED is not set # CONFIG_KARMA_PARTITION is not set @@ -3231,9 +3290,11 @@ CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y # CONFIG_LD_HEAD_STUB_CATCH is not set # CONFIG_LEDS_AN30259A is not set # CONFIG_LEDS_APU is not set +# CONFIG_LEDS_AW200XX is not set # CONFIG_LEDS_AW2013 is not set # CONFIG_LEDS_BCM6328 is not set # CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_BD2606MVV is not set # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_BLINKM is not set CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y @@ -3244,6 +3305,7 @@ CONFIG_LEDS_CLASS_MULTICOLOR=y # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_EL15203000 is not set # CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_GROUP_MULTICOLOR is not set # CONFIG_LEDS_INTEL_SS4200 is not set # CONFIG_LEDS_IS31FL319X is not set # CONFIG_LEDS_IS31FL32XX is not set @@ -3252,6 +3314,7 @@ CONFIG_LEDS_CLASS_MULTICOLOR=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_LM3642 is not set # CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_LM3697 is not set # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP3952 is not set # CONFIG_LEDS_LP50XX is not set @@ -3270,6 +3333,7 @@ CONFIG_LEDS_CLASS_MULTICOLOR=y # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set # CONFIG_LEDS_PWM is not set # CONFIG_LEDS_PWM_MULTICOLOR is not set # CONFIG_LEDS_REGULATOR is not set @@ -3300,6 +3364,7 @@ CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_USER is not set # CONFIG_LED_TRIGGER_PHY is not set # CONFIG_LEGACY_PTYS is not set +# CONFIG_LEGACY_TIOCSTI is not set # CONFIG_LGUEST is not set # CONFIG_LIB80211 is not set # CONFIG_LIB80211_CRYPT_CCMP is not set @@ -3321,6 +3386,7 @@ CONFIG_LINEAR_RANGES=y # CONFIG_LIQUIDIO_VF is not set # CONFIG_LIRC is not set # CONFIG_LIS3L02DQ is not set +# CONFIG_LIST_HARDENED is not set # CONFIG_LITEX_LITEETH is not set # CONFIG_LITEX_SOC_CONTROLLER is not set # CONFIG_LIVEPATCH is not set @@ -3425,16 +3491,20 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MANDATORY_FILE_LOCKING is not set # CONFIG_MANGLE_BOOTARGS is not set # CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88Q2XXX_PHY is not set # CONFIG_MARVELL_88X2222_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set # CONFIG_MAX1118 is not set # CONFIG_MAX11205 is not set +# CONFIG_MAX11410 is not set # CONFIG_MAX1241 is not set # CONFIG_MAX1363 is not set # CONFIG_MAX30100 is not set # CONFIG_MAX30102 is not set +# CONFIG_MAX30208 is not set +# CONFIG_MAX31827 is not set # CONFIG_MAX31856 is not set # CONFIG_MAX31865 is not set # CONFIG_MAX44000 is not set @@ -3443,11 +3513,13 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MAX5432 is not set # CONFIG_MAX5481 is not set # CONFIG_MAX5487 is not set +# CONFIG_MAX5522 is not set # CONFIG_MAX5821 is not set # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_MAX9611 is not set # CONFIG_MAXIM_THERMOCOUPLE is not set # CONFIG_MAXLINEAR_GPHY is not set +CONFIG_MAX_SKB_FRAGS=17 CONFIG_MAY_USE_DEVLINK=y # CONFIG_MB1232 is not set # CONFIG_MC3230 is not set @@ -3460,6 +3532,7 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MCP4131 is not set # CONFIG_MCP4531 is not set # CONFIG_MCP4725 is not set +# CONFIG_MCP4728 is not set # CONFIG_MCP4922 is not set # CONFIG_MCPM is not set # CONFIG_MCTP is not set @@ -3480,6 +3553,7 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MDIO_THUNDER is not set # CONFIG_MDIO_XPCS is not set # CONFIG_MDM_GCC_9607 is not set +# CONFIG_MD_BITMAP_FILE is not set # CONFIG_MD_FAULTY is not set # CONFIG_MEDIATEK_GE_PHY is not set # CONFIG_MEDIATEK_MT6577_AUXADC is not set @@ -3543,6 +3617,7 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MEGARAID_SAS is not set # CONFIG_MELLANOX_PLATFORM is not set CONFIG_MEMBARRIER=y +CONFIG_MEMFD_CREATE=y # CONFIG_MEMORY is not set # CONFIG_MEMORY_FAILURE is not set # CONFIG_MEMORY_HOTPLUG is not set @@ -3572,6 +3647,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_CORE is not set # CONFIG_MFD_CPCAP is not set # CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_CS42L43_I2C is not set # CONFIG_MFD_CS5535 is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9052_SPI is not set @@ -3583,7 +3659,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_EXYNOS_LPASS is not set # CONFIG_MFD_GATEWORKS_GSC is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_INTEL_M10_BMC_SPI is not set # CONFIG_MFD_INTEL_PMT is not set # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_MFD_IQS62X is not set @@ -3595,6 +3671,8 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_LP8788 is not set # CONFIG_MFD_MADERA is not set # CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX5970 is not set +# CONFIG_MFD_MAX77541 is not set # CONFIG_MFD_MAX77620 is not set # CONFIG_MFD_MAX77650 is not set # CONFIG_MFD_MAX77686 is not set @@ -3626,6 +3704,8 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RETU is not set # CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RK8XX_I2C is not set +# CONFIG_MFD_RK8XX_SPI is not set # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_ROHM_BD70528 is not set # CONFIG_MFD_ROHM_BD71828 is not set @@ -3645,6 +3725,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SL28CPLD is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMPRO is not set # CONFIG_MFD_SMSC is not set # CONFIG_MFD_STMFX is not set # CONFIG_MFD_STMPE is not set @@ -3665,11 +3746,14 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS65219 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS6594_I2C is not set +# CONFIG_MFD_TPS6594_SPI is not set # CONFIG_MFD_TPS68470 is not set # CONFIG_MFD_TPS80031 is not set # CONFIG_MFD_TQMX86 is not set @@ -3695,6 +3779,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MICROCHIP_KSZ is not set # CONFIG_MICROCHIP_PHY is not set # CONFIG_MICROCHIP_PIT64B is not set +# CONFIG_MICROCHIP_T1S_PHY is not set # CONFIG_MICROCHIP_T1_PHY is not set # CONFIG_MICROSEMI_PHY is not set # CONFIG_MIGRATION is not set @@ -3744,6 +3829,7 @@ CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y # CONFIG_MLX4_EN is not set # CONFIG_MLX5_CORE is not set # CONFIG_MLX5_EN_MACSEC is not set +# CONFIG_MLX5_MACSEC is not set # CONFIG_MLX5_SF is not set # CONFIG_MLX5_VFIO_PCI is not set # CONFIG_MLX90614 is not set @@ -3818,6 +3904,7 @@ CONFIG_MODULES=y CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_COMPRESS_XZ is not set # CONFIG_MODULE_COMPRESS_ZSTD is not set +# CONFIG_MODULE_DEBUG is not set # CONFIG_MODULE_FORCE_LOAD is not set # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODULE_SIG is not set @@ -3846,6 +3933,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MPLS is not set # CONFIG_MPLS_IPTUNNEL is not set # CONFIG_MPLS_ROUTING is not set +# CONFIG_MPRLS0025PA is not set # CONFIG_MPTCP is not set # CONFIG_MPU3050_I2C is not set # CONFIG_MQ_IOSCHED_DEADLINE is not set @@ -4070,12 +4158,14 @@ CONFIG_MULTIUSER=y # CONFIG_NATSEMI is not set # CONFIG_NAU7802 is not set # CONFIG_NBPFAXI_DMA is not set +# CONFIG_NCN26000_PHY is not set # CONFIG_NCP_FS is not set # CONFIG_NE2000 is not set # CONFIG_NE2K_PCI is not set # CONFIG_NEC_MARKEINS is not set CONFIG_NET=y # CONFIG_NETCONSOLE is not set +# CONFIG_NETCONSOLE_EXTENDED_LOG is not set CONFIG_NETDEVICES=y # CONFIG_NETDEVSIM is not set # CONFIG_NETFILTER is not set @@ -4221,6 +4311,7 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set # CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON is not set # CONFIG_NET_DSA_MSCC_FELIX is not set +# CONFIG_NET_DSA_MSCC_OCELOT_EXT is not set # CONFIG_NET_DSA_MSCC_SEVILLE is not set # CONFIG_NET_DSA_MT7530 is not set # CONFIG_NET_DSA_MV88E6060 is not set @@ -4250,6 +4341,7 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_TAG_KSZ is not set # CONFIG_NET_DSA_TAG_LAN9303 is not set # CONFIG_NET_DSA_TAG_MTK is not set +# CONFIG_NET_DSA_TAG_NONE is not set # CONFIG_NET_DSA_TAG_OCELOT is not set # CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set # CONFIG_NET_DSA_TAG_QCA is not set @@ -4426,6 +4518,7 @@ CONFIG_NEW_LEDS=y # CONFIG_NFC is not set # CONFIG_NFP is not set # CONFIG_NFSD is not set +# CONFIG_NFSD_V2 is not set # CONFIG_NFSD_V2_ACL is not set CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set @@ -4585,6 +4678,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_MAC_ROMAN is not set # CONFIG_NLS_MAC_ROMANIAN is not set # CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UCS2_UTILS is not set # CONFIG_NLS_UTF8 is not set CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NOA1305 is not set @@ -4628,6 +4722,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NVRAM is not set # CONFIG_NV_TCO is not set # CONFIG_NXP_C45_TJA11XX_PHY is not set +# CONFIG_NXP_CBTX_PHY is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set # CONFIG_NXP_TJA11XX_PHY is not set @@ -4653,12 +4748,14 @@ CONFIG_OF_RESERVED_MEM=y # CONFIG_OPROFILE is not set # CONFIG_OPROFILE_EVENT_MULTIPLEX is not set # CONFIG_OPT3001 is not set +# CONFIG_OPT4001 is not set CONFIG_OPTIMIZE_INLINING=y # CONFIG_ORANGEFS_FS is not set # CONFIG_ORION_WATCHDOG is not set # CONFIG_OSF_PARTITION is not set # CONFIG_OSNOISE_TRACER is not set CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_DEBUG is not set # CONFIG_OVERLAY_FS_INDEX is not set # CONFIG_OVERLAY_FS_METACOPY is not set CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y @@ -4697,6 +4794,7 @@ CONFIG_PANIC_TIMEOUT=1 # CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_PC is not set CONFIG_PARTITION_ADVANCED=y +# CONFIG_PATA_ACPI is not set # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ARASAN_CF is not set @@ -4732,6 +4830,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PARPORT is not set # CONFIG_PATA_PCMCIA is not set # CONFIG_PATA_PDC2027X is not set # CONFIG_PATA_PDC_OLD is not set @@ -4789,6 +4888,7 @@ CONFIG_PCIE_BUS_DEFAULT=y # CONFIG_PCI_CNB20LE_QUIRK is not set # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set +# CONFIG_PCI_DYNAMIC_OF_NODES is not set # CONFIG_PCI_ENDPOINT is not set # CONFIG_PCI_ENDPOINT_TEST is not set # CONFIG_PCI_FTPCI100 is not set @@ -4842,12 +4942,14 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PD6729 is not set # CONFIG_PDA_POWER is not set # CONFIG_PDC_ADMA is not set +# CONFIG_PDS_CORE is not set # CONFIG_PECI is not set # CONFIG_PERCPU_STATS is not set # CONFIG_PERCPU_TEST is not set # CONFIG_PERF_EVENTS is not set # CONFIG_PERF_EVENTS_AMD_POWER is not set # CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_PER_VMA_LOCK_STATS is not set # CONFIG_PHANTOM is not set # CONFIG_PHONET is not set # CONFIG_PHYLIB is not set @@ -4981,6 +5083,10 @@ CONFIG_PPC_4K_PAGES=y # CONFIG_PPP is not set # CONFIG_PPPOATM is not set # CONFIG_PPPOE is not set +# CONFIG_PPPOE_HASH_BITS_1 is not set +# CONFIG_PPPOE_HASH_BITS_2 is not set +CONFIG_PPPOE_HASH_BITS_4=y +# CONFIG_PPPOE_HASH_BITS_8 is not set # CONFIG_PPPOL2TP is not set # CONFIG_PPP_ASYNC is not set # CONFIG_PPP_BSDCOMP is not set @@ -5055,6 +5161,7 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PTP_1588_CLOCK_IDTCM is not set # CONFIG_PTP_1588_CLOCK_IXP46X is not set # CONFIG_PTP_1588_CLOCK_KVM is not set +# CONFIG_PTP_1588_CLOCK_MOCK is not set # CONFIG_PTP_1588_CLOCK_OCP is not set # CONFIG_PTP_1588_CLOCK_PCH is not set # CONFIG_PTP_1588_CLOCK_VMW is not set @@ -5144,6 +5251,7 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_RANDOMIZE_BASE is not set CONFIG_RANDOMIZE_KSTACK_OFFSET=y # CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set +# CONFIG_RANDOM_KMALLOC_CACHES is not set CONFIG_RANDOM_TRUST_BOOTLOADER=y CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDSTRUCT_NONE is not set @@ -5152,6 +5260,7 @@ CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RASPBERRYPI_GPIOMEM is not set # CONFIG_RBTREE_TEST is not set # CONFIG_RCU_BOOST is not set +# CONFIG_RCU_CPU_STALL_CPUTIME is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_EQS_DEBUG is not set # CONFIG_RCU_EXPEDITE_BOOT is not set @@ -5198,6 +5307,7 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_AW37503 is not set # CONFIG_REGULATOR_DA9121 is not set # CONFIG_REGULATOR_DA9210 is not set # CONFIG_REGULATOR_DA9211 is not set @@ -5216,8 +5326,10 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_LTC3676 is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX20086 is not set +# CONFIG_REGULATOR_MAX20411 is not set # CONFIG_REGULATOR_MAX77620 is not set # CONFIG_REGULATOR_MAX77826 is not set +# CONFIG_REGULATOR_MAX77857 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8893 is not set @@ -5238,14 +5350,19 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_PV88080 is not set # CONFIG_REGULATOR_PV88090 is not set # CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_RAA215300 is not set # CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set # CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT4803 is not set # CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_RT5739 is not set # CONFIG_REGULATOR_RT5759 is not set # CONFIG_REGULATOR_RT6160 is not set +# CONFIG_REGULATOR_RT6190 is not set # CONFIG_REGULATOR_RT6245 is not set # CONFIG_REGULATOR_RTMV20 is not set # CONFIG_REGULATOR_RTQ2134 is not set +# CONFIG_REGULATOR_RTQ2208 is not set # CONFIG_REGULATOR_RTQ6752 is not set # CONFIG_REGULATOR_SLG51000 is not set # CONFIG_REGULATOR_SY8106A is not set @@ -5255,6 +5372,7 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS6286X is not set +# CONFIG_REGULATOR_TPS6287X is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_TPS65132 is not set @@ -5305,11 +5423,17 @@ CONFIG_RFKILL=y # CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set # CONFIG_RMI4_CORE is not set # CONFIG_RMNET is not set +# CONFIG_ROCKCHIP_ERRATUM_3588001 is not set # CONFIG_ROCKCHIP_PHY is not set # CONFIG_ROCKER is not set +# CONFIG_ROHM_BU27008 is not set +# CONFIG_ROHM_BU27034 is not set # CONFIG_ROMFS_FS is not set # CONFIG_ROSE is not set # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 is not set +# CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2 is not set +# CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA is not set # CONFIG_RPMSG_QCOM_GLINK_RPM is not set # CONFIG_RPMSG_VIRTIO is not set # CONFIG_RPMSG_WWAN_CTRL is not set @@ -5442,6 +5566,7 @@ CONFIG_RUNTIME_TESTING_MENU=y # CONFIG_RV is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_RXKAD=y +# CONFIG_RXPERF is not set # CONFIG_S2IO is not set # CONFIG_SAMPLES is not set # CONFIG_SAMSUNG_LAPTOP is not set @@ -5596,6 +5721,7 @@ CONFIG_SCSI_PROC_FS=y # CONFIG_SD_ADC_MODULATOR is not set # CONFIG_SECCOMP is not set # CONFIG_SECCOMP_CACHE_DEBUG is not set +# CONFIG_SECRETMEM is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set @@ -5610,6 +5736,7 @@ CONFIG_SECURITY_DMESG_RESTRICT=y # CONFIG_SECURITY_SELINUX_AVC_STATS is not set # CONFIG_SECURITY_SELINUX_BOOTPARAM is not set CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 +# CONFIG_SECURITY_SELINUX_DEBUG is not set # CONFIG_SECURITY_SELINUX_DEVELOP is not set # CONFIG_SECURITY_SELINUX_DISABLE is not set # CONFIG_SECURITY_SMACK is not set @@ -5621,6 +5748,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSIRION_SGP40 is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_ACBEL_FSG032 is not set # CONFIG_SENSORS_ACPI_POWER is not set # CONFIG_SENSORS_AD7314 is not set # CONFIG_SENSORS_AD7414 is not set @@ -5693,6 +5821,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_HMC5843 is not set # CONFIG_SENSORS_HMC5843_I2C is not set # CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_HS3001 is not set # CONFIG_SENSORS_HTU21 is not set # CONFIG_SENSORS_I5500 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -5774,10 +5903,12 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX8688 is not set +# CONFIG_SENSORS_MC34VR500 is not set # CONFIG_SENSORS_MCP3021 is not set # CONFIG_SENSORS_MP2888 is not set # CONFIG_SENSORS_MP2975 is not set # CONFIG_SENSORS_MP5023 is not set +# CONFIG_SENSORS_MPQ7932 is not set # CONFIG_SENSORS_MR75203 is not set # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set @@ -5823,6 +5954,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_STTS751 is not set # CONFIG_SENSORS_TC654 is not set # CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_TDA38640 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP102 is not set # CONFIG_SENSORS_TMP103 is not set @@ -5883,6 +6015,7 @@ CONFIG_SERIAL_8250_DMA=y # CONFIG_SERIAL_8250_MOXA is not set CONFIG_SERIAL_8250_NR_UARTS=2 # CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_PCI1XXXX is not set # CONFIG_SERIAL_8250_PERICOM is not set # CONFIG_SERIAL_8250_RSA is not set # CONFIG_SERIAL_8250_RT288X is not set @@ -5898,7 +6031,7 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_DEV_BUS is not set CONFIG_SERIAL_EARLYCON=y -# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_EARLYCON_SEMIHOST is not set # CONFIG_SERIAL_FSL_LINFLEXUART is not set # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set @@ -5983,7 +6116,7 @@ CONFIG_SIGNALFD=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SKY2_DEBUG is not set -# CONFIG_SLAB is not set +# CONFIG_SLAB_DEPRECATED is not set CONFIG_SLABINFO=y CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_SLAB_FREELIST_RANDOM=y @@ -5999,6 +6132,7 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_MEMCG_SYSFS_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_SLUB_TINY is not set # CONFIG_SMARTJOYPLUS_FF is not set # CONFIG_SMB_SERVER is not set # CONFIG_SMC911X is not set @@ -6140,6 +6274,7 @@ CONFIG_SND_OSSEMUL=y CONFIG_SND_PCI=y # CONFIG_SND_PCM is not set # CONFIG_SND_PCMCIA is not set +# CONFIG_SND_PCMTEST is not set # CONFIG_SND_PCM_OSS is not set CONFIG_SND_PCM_OSS_PLUGINS=y # CONFIG_SND_PCM_TIMER is not set @@ -6163,6 +6298,7 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SBAWE_SEQ is not set # CONFIG_SND_SE6X is not set # CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_SEQ_UMP is not set # CONFIG_SND_SERIAL_GENERIC is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_SIMPLE_CARD is not set @@ -6197,9 +6333,14 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_AMD_RENOIR is not set # CONFIG_SND_SOC_AU1XAUDIO is not set # CONFIG_SND_SOC_AU1XPSC is not set +# CONFIG_SND_SOC_AUDIO_IIO_AUX is not set # CONFIG_SND_SOC_AW8738 is not set +# CONFIG_SND_SOC_AW88261 is not set +# CONFIG_SND_SOC_AW88395 is not set # CONFIG_SND_SOC_BD28623 is not set # CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CHV3_CODEC is not set +# CONFIG_SND_SOC_CHV3_I2S is not set # CONFIG_SND_SOC_CS35L32 is not set # CONFIG_SND_SOC_CS35L33 is not set # CONFIG_SND_SOC_CS35L34 is not set @@ -6209,6 +6350,8 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_CS35L41_SPI is not set # CONFIG_SND_SOC_CS35L45_I2C is not set # CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS35L56_I2C is not set +# CONFIG_SND_SOC_CS35L56_SPI is not set # CONFIG_SND_SOC_CS4234 is not set # CONFIG_SND_SOC_CS4265 is not set # CONFIG_SND_SOC_CS4270 is not set @@ -6252,6 +6395,7 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_GTM601 is not set # CONFIG_SND_SOC_HDA is not set # CONFIG_SND_SOC_ICS43432 is not set +# CONFIG_SND_SOC_IDT821034 is not set # CONFIG_SND_SOC_IMG is not set # CONFIG_SND_SOC_IMX_AUDMIX is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set @@ -6300,6 +6444,8 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_JZ4725B_CODEC is not set # CONFIG_SND_SOC_JZ4740_CODEC is not set # CONFIG_SND_SOC_JZ4770_CODEC is not set +# CONFIG_SND_SOC_LOONGSON_CARD is not set +# CONFIG_SND_SOC_LOONGSON_I2S_PCI is not set # CONFIG_SND_SOC_LPASS_RX_MACRO is not set # CONFIG_SND_SOC_LPASS_TX_MACRO is not set # CONFIG_SND_SOC_LPASS_VA_MACRO is not set @@ -6307,9 +6453,11 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_MA120X0P is not set # CONFIG_SND_SOC_MAX9759 is not set # CONFIG_SND_SOC_MAX98088 is not set +# CONFIG_SND_SOC_MAX98090 is not set # CONFIG_SND_SOC_MAX98357A is not set # CONFIG_SND_SOC_MAX98373 is not set # CONFIG_SND_SOC_MAX98373_I2C is not set +# CONFIG_SND_SOC_MAX98388 is not set # CONFIG_SND_SOC_MAX98390 is not set # CONFIG_SND_SOC_MAX98396 is not set # CONFIG_SND_SOC_MAX98504 is not set @@ -6332,6 +6480,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_MT8173 is not set # CONFIG_SND_SOC_MT8183 is not set # CONFIG_SND_SOC_MT8186 is not set +# CONFIG_SND_SOC_MT8188 is not set # CONFIG_SND_SOC_MT8192 is not set # CONFIG_SND_SOC_MT8195 is not set # CONFIG_SND_SOC_MTK_BTCVSD is not set @@ -6355,6 +6504,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_PCM5102A is not set # CONFIG_SND_SOC_PCM512x_I2C is not set # CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_PEB2466 is not set # CONFIG_SND_SOC_QCOM is not set # CONFIG_SND_SOC_RK3328 is not set # CONFIG_SND_SOC_RK817 is not set @@ -6369,6 +6519,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set # CONFIG_SND_SOC_SIMPLE_MUX is not set # CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SMA1303 is not set # CONFIG_SND_SOC_SOF_TOPLEVEL is not set # CONFIG_SND_SOC_SPDIF is not set # CONFIG_SND_SOC_SRC4XXX_I2C is not set @@ -6376,6 +6527,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_SSM2518 is not set # CONFIG_SND_SOC_SSM2602_I2C is not set # CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM3515 is not set # CONFIG_SND_SOC_SSM4567 is not set # CONFIG_SND_SOC_STA32X is not set # CONFIG_SND_SOC_STA350 is not set @@ -6385,6 +6537,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_TAS2764 is not set # CONFIG_SND_SOC_TAS2770 is not set # CONFIG_SND_SOC_TAS2780 is not set +# CONFIG_SND_SOC_TAS2781_I2C is not set # CONFIG_SND_SOC_TAS5086 is not set # CONFIG_SND_SOC_TAS571X is not set # CONFIG_SND_SOC_TAS5720 is not set @@ -6430,6 +6583,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_WM8904 is not set # CONFIG_SND_SOC_WM8940 is not set # CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8961 is not set # CONFIG_SND_SOC_WM8962 is not set # CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set @@ -6453,6 +6607,7 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y CONFIG_SND_USB=y # CONFIG_SND_USB_6FIRE is not set # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_AUDIO_MIDI_V2 is not set # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_USB_HIFACE is not set # CONFIG_SND_USB_POD is not set @@ -6541,6 +6696,7 @@ CONFIG_SND_X86=y # CONFIG_SPI_OCTEON is not set # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_ORION is not set +# CONFIG_SPI_PCI1XXXX is not set # CONFIG_SPI_PL022 is not set # CONFIG_SPI_PPC4xx is not set # CONFIG_SPI_PXA2XX is not set @@ -6551,6 +6707,7 @@ CONFIG_SND_X86=y # CONFIG_SPI_SC18IS602 is not set # CONFIG_SPI_SIFIVE is not set # CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SN_F_OSPI is not set # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_THUNDERX is not set # CONFIG_SPI_TI_QSPI is not set @@ -6567,9 +6724,10 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SPS30_SERIAL is not set CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -# CONFIG_SQUASHFS_DECOMP_MULTI is not set -CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y -# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set +CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE is not set CONFIG_SQUASHFS_EMBEDDED=y # CONFIG_SQUASHFS_FILE_CACHE is not set CONFIG_SQUASHFS_FILE_DIRECT=y @@ -6647,6 +6805,8 @@ CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y # CONFIG_SUSPEND is not set # CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_SWAP=y +# CONFIG_SWIOTLB is not set +# CONFIG_SWIOTLB_DYNAMIC is not set # CONFIG_SWCONFIG is not set # CONFIG_SWCONFIG_B53 is not set # CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set @@ -6742,6 +6902,7 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set # CONFIG_TEST_DEBUG_VIRTUAL is not set +# CONFIG_TEST_DHRY is not set # CONFIG_TEST_DIV64 is not set # CONFIG_TEST_DYNAMIC_DEBUG is not set # CONFIG_TEST_FIRMWARE is not set @@ -6783,6 +6944,7 @@ CONFIG_TEXTSEARCH=y # CONFIG_TEXTSEARCH_FSM is not set # CONFIG_TEXTSEARCH_KMP is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set @@ -6833,8 +6995,10 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ADC128S052 is not set # CONFIG_TI_ADC161S626 is not set # CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS1100 is not set # CONFIG_TI_ADS124S08 is not set # CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7924 is not set # CONFIG_TI_ADS7950 is not set # CONFIG_TI_ADS8344 is not set # CONFIG_TI_ADS8688 is not set @@ -6850,9 +7014,11 @@ CONFIG_TINY_RCU=y # CONFIG_TI_DAC7612 is not set # CONFIG_TI_DAVINCI_CPDMA is not set # CONFIG_TI_DAVINCI_MDIO is not set +# CONFIG_TI_LMP92064 is not set # CONFIG_TI_ST is not set # CONFIG_TI_SYSCON_RESET is not set # CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TMAG5273 is not set # CONFIG_TI_TSC2046 is not set # CONFIG_TLAN is not set # CONFIG_TLS is not set @@ -6865,6 +7031,7 @@ CONFIG_TINY_RCU=y CONFIG_TMPFS=y # CONFIG_TMPFS_INODE64 is not set # CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_QUOTA is not set CONFIG_TMPFS_XATTR=y # CONFIG_TOPSTAR_LAPTOP is not set # CONFIG_TORTURE_TEST is not set @@ -6890,6 +7057,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set # CONFIG_TOUCHSCREEN_CYTTSP4_I2C is not set # CONFIG_TOUCHSCREEN_CYTTSP4_SPI is not set +# CONFIG_TOUCHSCREEN_CYTTSP5 is not set # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set # CONFIG_TOUCHSCREEN_CYTTSP_I2C is not set # CONFIG_TOUCHSCREEN_CYTTSP_SPI is not set @@ -6909,10 +7077,12 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set # CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set # CONFIG_TOUCHSCREEN_HP600 is not set # CONFIG_TOUCHSCREEN_HP7XX is not set # CONFIG_TOUCHSCREEN_HTCPEN is not set # CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_ILITEK is not set # CONFIG_TOUCHSCREEN_IMAGIS is not set @@ -6921,6 +7091,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set # CONFIG_TOUCHSCREEN_IPROC is not set # CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_IQS7211 is not set # CONFIG_TOUCHSCREEN_LPC32XX is not set # CONFIG_TOUCHSCREEN_MAX11801 is not set # CONFIG_TOUCHSCREEN_MC13783 is not set @@ -6933,6 +7104,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_MX25 is not set # CONFIG_TOUCHSCREEN_MXS_LRADC is not set +# CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set # CONFIG_TOUCHSCREEN_PCAP is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set # CONFIG_TOUCHSCREEN_PIXCIR is not set @@ -7476,6 +7648,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_USERFAULTFD is not set # CONFIG_USERIO is not set # CONFIG_USER_DECRYPTED_DATA is not set +# CONFIG_USER_EVENTS is not set # CONFIG_USE_OF is not set # CONFIG_UTS_NS is not set # CONFIG_UWB is not set @@ -7485,6 +7658,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_V4L_TEST_DRIVERS is not set # CONFIG_VALIDATE_FS_PARSER is not set # CONFIG_VBOXGUEST is not set +# CONFIG_VCAP is not set # CONFIG_VCNL3020 is not set # CONFIG_VCNL4000 is not set # CONFIG_VCNL4035 is not set @@ -7562,8 +7736,12 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_CX88 is not set # CONFIG_VIDEO_DEV is not set # CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_VIDEO_DS90UB913 is not set +# CONFIG_VIDEO_DS90UB953 is not set +# CONFIG_VIDEO_DS90UB960 is not set # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_DW9719 is not set # CONFIG_VIDEO_DW9768 is not set # CONFIG_VIDEO_DW9807_VCM is not set # CONFIG_VIDEO_EM28XX is not set @@ -7688,9 +7866,11 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_SUN6I_CSI is not set # CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2 is not set # CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_STK1160 is not set # CONFIG_VIDEO_STK1160_COMMON is not set # CONFIG_VIDEO_ST_MIPID02 is not set # CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC358746 is not set # CONFIG_VIDEO_TDA1997X is not set # CONFIG_VIDEO_TDA7432 is not set # CONFIG_VIDEO_TDA9840 is not set @@ -7846,6 +8026,8 @@ CONFIG_WLAN=y # CONFIG_WLAN_VENDOR_TI is not set # CONFIG_WLAN_VENDOR_ZYDAS is not set # CONFIG_WLCORE is not set +# CONFIG_WPCM450_SOC is not set +# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y # CONFIG_WQ_WATCHDOG is not set # CONFIG_WWAN is not set @@ -7855,6 +8037,7 @@ CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y # CONFIG_X509_CERTIFICATE_PARSER is not set # CONFIG_X86_PKG_TEMP_THERMAL is not set CONFIG_X86_SYSFB=y +# CONFIG_X9250 is not set # CONFIG_XDP_SOCKETS is not set # CONFIG_XEN is not set # CONFIG_XEN_GRANT_DMA_ALLOC is not set @@ -7873,6 +8056,7 @@ CONFIG_XFRM=y # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_SUPPORT_ASCII_CI is not set # CONFIG_XFS_SUPPORT_V4 is not set # CONFIG_XFS_WARN is not set # CONFIG_XILINX_AXI_EMAC is not set @@ -7884,7 +8068,9 @@ CONFIG_XFRM=y # CONFIG_XILINX_SDFEC is not set # CONFIG_XILINX_VCU is not set # CONFIG_XILINX_WATCHDOG is not set +# CONFIG_XILINX_WINDOW_WATCHDOG is not set # CONFIG_XILINX_XADC is not set +# CONFIG_XILINX_XDMA is not set # CONFIG_XILINX_ZYNQMP_DMA is not set # CONFIG_XILINX_ZYNQMP_DPDMA is not set # CONFIG_XILLYBUS is not set @@ -7931,6 +8117,8 @@ CONFIG_ZONE_DMA=y # CONFIG_ZRAM_DEF_COMP_LZORLE is not set # CONFIG_ZRAM_DEF_COMP_ZSTD is not set # CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_ZRAM_MULTI_COMP is not set # CONFIG_ZSMALLOC is not set +CONFIG_ZSMALLOC_CHAIN_SIZE=8 # CONFIG_ZSWAP is not set # CONFIG_ZX_TDM is not set From 6be4e487da8ca2c5e318e57f5d75efc4b7bbfacb Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 5 Jan 2024 16:49:18 +0800 Subject: [PATCH 050/108] generic: 6.6: refresh config symbols Sort generic config for 6.6. The sort commands: $ ./scripts/kconfig.pl '+' target/linux/generic/config-6.6 /dev/null > target/linux/generic/config-6.6-new $ mv target/linux/generic/config-6.6-new target/linux/generic/config-6.6 Signed-off-by: Weijie Gao --- target/linux/generic/config-6.6 | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 0d010a7b03..319f56fe01 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -155,14 +155,13 @@ CONFIG_AF_UNIX_OOB=y # CONFIG_AHCI_CEVA is not set # CONFIG_AHCI_DWC is not set # CONFIG_AHCI_IMX is not set -# CONFIG_ARCH_MA35 is not set # CONFIG_AHCI_MVEBU is not set # CONFIG_AHCI_QORIQ is not set # CONFIG_AHCI_XGENE is not set CONFIG_AIO=y -# CONFIG_AIR_EN8811H_PHY is not set # CONFIG_AIRO is not set # CONFIG_AIRO_CS is not set +# CONFIG_AIR_EN8811H_PHY is not set # CONFIG_AIX_PARTITION is not set # CONFIG_AK09911 is not set # CONFIG_AK8974 is not set @@ -265,6 +264,7 @@ CONFIG_ARCH_FORCE_MAX_ORDER=11 # CONFIG_ARCH_LAYERSCAPE is not set # CONFIG_ARCH_LG1K is not set # CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MA35 is not set # CONFIG_ARCH_MEDIATEK is not set # CONFIG_ARCH_MESON is not set # CONFIG_ARCH_MILBEAUT is not set @@ -885,8 +885,8 @@ CONFIG_BUILDTIME_TABLE_SORT=y # CONFIG_BUILD_BIN2C is not set CONFIG_BUILD_SALT="" # CONFIG_C2PORT is not set -CONFIG_CACHE_L2X0_PMU=y # CONFIG_CACHESTAT_SYSCALL is not set +CONFIG_CACHE_L2X0_PMU=y # CONFIG_CADENCE_WATCHDOG is not set # CONFIG_CAIF is not set # CONFIG_CAN is not set @@ -971,8 +971,8 @@ CONFIG_CFG80211_HEADERS=y # CONFIG_CHARGER_MANAGER is not set # CONFIG_CHARGER_MAX77976 is not set # CONFIG_CHARGER_MAX8903 is not set -# CONFIG_CHARGER_QCOM_SMBB is not set # CONFIG_CHARGER_QCOM_SMB2 is not set +# CONFIG_CHARGER_QCOM_SMBB is not set # CONFIG_CHARGER_RT9455 is not set # CONFIG_CHARGER_RT9467 is not set # CONFIG_CHARGER_RT9471 is not set @@ -1092,6 +1092,8 @@ CONFIG_CONSTRUCTORS=y # CONFIG_CORTINA_PHY is not set # CONFIG_COUNTER is not set # CONFIG_CPA_DEBUG is not set +# CONFIG_CPUFREQ_DT is not set +# CONFIG_CPUFREQ_DT_PLATDEV is not set # CONFIG_CPU_BIG_ENDIAN is not set # CONFIG_CPU_BPREDICT_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set @@ -1117,8 +1119,6 @@ CONFIG_CONSTRUCTORS=y # CONFIG_CPU_NO_EFFICIENT_FFS is not set CONFIG_CPU_SW_DOMAIN_PAN=y # CONFIG_CPU_THERMAL is not set -# CONFIG_CPUFREQ_DT is not set -# CONFIG_CPUFREQ_DT_PLATDEV is not set # CONFIG_CRAMFS is not set CONFIG_CRAMFS_BLOCKDEV=y # CONFIG_CRAMFS_MTD is not set @@ -1539,11 +1539,11 @@ CONFIG_DEVPORT=y # CONFIG_DMABUF_SYSFS_STATS is not set # CONFIG_DMADEVICES is not set # CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMAPOOL_TEST is not set # CONFIG_DMARD06 is not set # CONFIG_DMARD09 is not set # CONFIG_DMARD10 is not set # CONFIG_DMASCC is not set -# CONFIG_DMAPOOL_TEST is not set # CONFIG_DMATEST is not set # CONFIG_DMA_API_DEBUG is not set CONFIG_DMA_COHERENT_POOL=y @@ -1658,11 +1658,11 @@ CONFIG_DQL=y # CONFIG_DRM_LIMA is not set # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set # CONFIG_DRM_LOGICVC is not set -# CONFIG_DRM_LOONGSON is not set # CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9211 is not set # CONFIG_DRM_LONTIUM_LT9611 is not set # CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_LOONGSON is not set # CONFIG_DRM_LVDS_CODEC is not set # CONFIG_DRM_LVDS_ENCODER is not set # CONFIG_DRM_MALI_DISPLAY is not set @@ -2343,8 +2343,8 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_CDEV is not set # CONFIG_GPIO_CDEV_V1 is not set # CONFIG_GPIO_CS5535 is not set -# CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_DS4520 is not set +# CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_EM is not set # CONFIG_GPIO_EXAR is not set # CONFIG_GPIO_F7188X is not set @@ -3166,8 +3166,8 @@ CONFIG_JOLIET=y # CONFIG_KALLSYMS is not set # CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set # CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_SELFTEST is not set CONFIG_KALLSYMS_BASE_RELATIVE=y +# CONFIG_KALLSYMS_SELFTEST is not set # CONFIG_KALLSYMS_UNCOMPRESSED is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_KASAN is not set @@ -3406,9 +3406,9 @@ CONFIG_LOCKDEP_STACK_TRACE_BITS=19 CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14 CONFIG_LOCKDEP_SUPPORT=y CONFIG_LOCKD_V4=y -CONFIG_LOCK_MM_AND_FIND_VMA=y # CONFIG_LOCKUP_DETECTOR is not set # CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_LOCK_MM_AND_FIND_VMA=y # CONFIG_LOCK_STAT is not set # CONFIG_LOCK_TORTURE_TEST is not set # CONFIG_LOGFS is not set @@ -5186,9 +5186,9 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QCA7000 is not set # CONFIG_QCA7000_SPI is not set # CONFIG_QCA7000_UART is not set -# CONFIG_QCA83XX_PHY is not set # CONFIG_QCA807X_PHY is not set # CONFIG_QCA808X_PHY is not set +# CONFIG_QCA83XX_PHY is not set # CONFIG_QCOM_A7PLL is not set # CONFIG_QCOM_BAM_DMUX is not set # CONFIG_QCOM_EMAC is not set @@ -6116,8 +6116,8 @@ CONFIG_SIGNALFD=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SKY2_DEBUG is not set -# CONFIG_SLAB_DEPRECATED is not set CONFIG_SLABINFO=y +# CONFIG_SLAB_DEPRECATED is not set CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_MERGE_DEFAULT=y @@ -6805,8 +6805,6 @@ CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y # CONFIG_SUSPEND is not set # CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_SWAP=y -# CONFIG_SWIOTLB is not set -# CONFIG_SWIOTLB_DYNAMIC is not set # CONFIG_SWCONFIG is not set # CONFIG_SWCONFIG_B53 is not set # CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set @@ -6814,6 +6812,8 @@ CONFIG_SWAP=y # CONFIG_SWCONFIG_B53_SPI_DRIVER is not set # CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set # CONFIG_SWCONFIG_LEDS is not set +# CONFIG_SWIOTLB is not set +# CONFIG_SWIOTLB_DYNAMIC is not set # CONFIG_SW_SYNC is not set # CONFIG_SX9310 is not set # CONFIG_SX9324 is not set @@ -7193,8 +7193,8 @@ CONFIG_TRAD_SIGNALS=y # CONFIG_TRUSTED_FOUNDATIONS is not set # CONFIG_TRUSTED_KEYS is not set # CONFIG_TRUSTED_KEYS_CAAM is not set -# CONFIG_TRUSTED_KEYS_TPM is not set # CONFIG_TRUSTED_KEYS_TEE is not set +# CONFIG_TRUSTED_KEYS_TPM is not set # CONFIG_TSL2583 is not set # CONFIG_TSL2591 is not set # CONFIG_TSL2772 is not set @@ -7245,8 +7245,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_UFS_FS is not set # CONFIG_UHID is not set CONFIG_UID16=y -# CONFIG_UIO is not set # CONFIG_UIMAGE_FIT_BLK is not set +# CONFIG_UIO is not set # CONFIG_ULTRA is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_UNICODE is not set @@ -7862,13 +7862,13 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_SMIAPP is not set # CONFIG_VIDEO_SOLO6X10 is not set # CONFIG_VIDEO_SONY_BTF_MPX is not set -# CONFIG_VIDEO_SUN4I_CSI is not set -# CONFIG_VIDEO_SUN6I_CSI is not set -# CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2 is not set # CONFIG_VIDEO_SR030PC30 is not set # CONFIG_VIDEO_STK1160 is not set # CONFIG_VIDEO_STK1160_COMMON is not set # CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_SUN4I_CSI is not set +# CONFIG_VIDEO_SUN6I_CSI is not set +# CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2 is not set # CONFIG_VIDEO_TC358743 is not set # CONFIG_VIDEO_TC358746 is not set # CONFIG_VIDEO_TDA1997X is not set From d356fb33c311a8f37d676aac5bb554715d1d19d2 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 00:08:35 +0000 Subject: [PATCH 051/108] generic: v6.6: update fitblk driver to work with Linux 6.6 Update fitblk driver which has previously been backported to Linux 6.1 so it can build and work with Linux 6.6. Signed-off-by: Daniel Golle --- ...add-uImage.FIT-subimage-block-driver.patch | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch index c565350dc0..117edbcef2 100644 --- a/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/target/linux/generic/pending-6.6/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -81,7 +81,7 @@ Signed-off-by: Daniel Golle swim_mod-y := swim.o swim_asm.o --- /dev/null +++ b/drivers/block/fitblk.c -@@ -0,0 +1,636 @@ +@@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * uImage.FIT virtual block device driver. @@ -199,9 +199,9 @@ Signed-off-by: Daniel Golle + bool dead; +}; + -+static int fitblk_open(struct block_device *bdev, fmode_t mode) ++static int fitblk_open(struct gendisk *disk, fmode_t mode) +{ -+ struct fitblk *fitblk = bdev->bd_disk->private_data; ++ struct fitblk *fitblk = disk->private_data; + + if (fitblk->dead) + return -ENOENT; @@ -209,7 +209,7 @@ Signed-off-by: Daniel Golle + return 0; +} + -+static void fitblk_release(struct gendisk *disk, fmode_t mode) ++static void fitblk_release(struct gendisk *disk) +{ + return; +} @@ -283,7 +283,7 @@ Signed-off-by: Daniel Golle + + if (refcount_dec_if_one(&num_devs)) { + sysfs_remove_link(&pdev->dev.kobj, "lower_dev"); -+ blkdev_put(fitblk->lower_bdev, FMODE_READ | FMODE_EXCL); ++ blkdev_put(fitblk->lower_bdev, &_fitblk_claim_ptr); + } + + kfree(fitblk); @@ -373,6 +373,29 @@ Signed-off-by: Daniel Golle + return err; +} + ++static void fitblk_mark_dead(struct block_device *bdev, bool surprise) ++{ ++ struct list_head *n, *tmp; ++ struct fitblk *fitblk; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_safe(n, tmp, &fitblk_devices) { ++ fitblk = list_entry(n, struct fitblk, list); ++ if (fitblk->lower_bdev != bdev) ++ continue; ++ ++ fitblk->dead = true; ++ list_del(&fitblk->list); ++ /* removal needs to be deferred to avoid deadlock */ ++ schedule_work(&fitblk->remove_work); ++ } ++ mutex_unlock(&devices_mutex); ++} ++ ++static const struct blk_holder_ops fitblk_hops = { ++ .mark_dead = fitblk_mark_dead, ++}; ++ +static int parse_fit_on_dev(struct device *dev) +{ + struct block_device *bdev; @@ -401,7 +424,7 @@ Signed-off-by: Daniel Golle + unsigned int slot = 0; + + /* Exclusive open the block device to receive holder notifications */ -+ bdev = blkdev_get_by_dev(dev->devt, FMODE_READ | FMODE_EXCL, &_fitblk_claim_ptr); ++ bdev = blkdev_get_by_dev(dev->devt, BLK_OPEN_READ, &_fitblk_claim_ptr, &fitblk_hops); + if (!bdev) + return -ENODEV; + @@ -653,7 +676,7 @@ Signed-off-by: Daniel Golle + kfree(fit); +out_blkdev: + if (!found || ret) -+ blkdev_put(bdev, FMODE_READ | FMODE_EXCL); ++ blkdev_put(bdev, &_fitblk_claim_ptr); + + return ret; +} From 7acb8203c2e61d045c5129bb2c3df0b3a99d0f0b Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 1 Mar 2024 14:15:15 +0100 Subject: [PATCH 052/108] generic: 6.6: fix uncompressed kallsyms Currently, the existing uncompressed kallsym support is causing qualcommax boards to hang on boot, and only after earlycon and verbose BUG() prints are enabled the trace is visible: [ 0.000000] ------------[ cut here ]------------ [ 0.000000] kernel BUG at kernel/kallsyms.c:340! [ 0.000000] Internal error: Oops - BUG: 00000000f2000800 [#1] SMP Felix has fixed up the uncompressed kallsyms support so modify the current patch with the fix. All credits for the code go to Felix. Signed-off-by: Robert Marko --- .../203-kallsyms_uncompressed.patch | 69 ++++++++++++++++--- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch index d935077c05..c23811ed39 100644 --- a/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch +++ b/target/linux/generic/pending-6.6/203-kallsyms_uncompressed.patch @@ -65,17 +65,66 @@ Signed-off-by: Felix Fietkau static int absolute_percpu; static int base_relative; static int lto_clang; -@@ -469,6 +470,9 @@ static void write_src(void) +@@ -453,13 +454,15 @@ static void write_src(void) + } + printf("\n"); + +- /* +- * Now that we wrote out the compressed symbol names, restore the +- * original names, which are needed in some of the later steps. +- */ +- for (i = 0; i < table_cnt; i++) { +- expand_symbol(table[i]->sym, table[i]->len, buf); +- strcpy((char *)table[i]->sym, buf); ++ if (!uncompressed) { ++ /* ++ * Now that we wrote out the compressed symbol names, restore the ++ * original names, which are needed in some of the later steps. ++ */ ++ for (i = 0; i < table_cnt; i++) { ++ expand_symbol(table[i]->sym, table[i]->len, buf); ++ strcpy((char *)table[i]->sym, buf); ++ } + } + + output_label("kallsyms_markers"); +@@ -469,20 +472,22 @@ static void write_src(void) free(markers); -+ if (uncompressed) -+ return; -+ - output_label("kallsyms_token_table"); - off = 0; - for (i = 0; i < 256; i++) { -@@ -582,6 +586,9 @@ static unsigned char *find_token(unsigne +- output_label("kallsyms_token_table"); +- off = 0; +- for (i = 0; i < 256; i++) { +- best_idx[i] = off; +- expand_symbol(best_table[i], best_table_len[i], buf); +- printf("\t.asciz\t\"%s\"\n", buf); +- off += strlen(buf) + 1; +- } +- printf("\n"); ++ if (!uncompressed) { ++ output_label("kallsyms_token_table"); ++ off = 0; ++ for (i = 0; i < 256; i++) { ++ best_idx[i] = off; ++ expand_symbol(best_table[i], best_table_len[i], buf); ++ printf("\t.asciz\t\"%s\"\n", buf); ++ off += strlen(buf) + 1; ++ } ++ printf("\n"); + +- output_label("kallsyms_token_index"); +- for (i = 0; i < 256; i++) +- printf("\t.short\t%d\n", best_idx[i]); +- printf("\n"); ++ output_label("kallsyms_token_index"); ++ for (i = 0; i < 256; i++) ++ printf("\t.short\t%d\n", best_idx[i]); ++ printf("\n"); ++ } + + if (!base_relative) + output_label("kallsyms_addresses"); +@@ -582,6 +587,9 @@ static unsigned char *find_token(unsigne { int i; @@ -85,7 +134,7 @@ Signed-off-by: Felix Fietkau for (i = 0; i < len - 1; i++) { if (str[i] == token[0] && str[i+1] == token[1]) return &str[i]; -@@ -654,6 +661,9 @@ static void optimize_result(void) +@@ -654,6 +662,9 @@ static void optimize_result(void) { int i, best; @@ -95,7 +144,7 @@ Signed-off-by: Felix Fietkau /* using the '\0' symbol last allows compress_symbols to use standard * fast string functions */ for (i = 255; i >= 0; i--) { -@@ -815,6 +825,7 @@ int main(int argc, char **argv) +@@ -815,6 +826,7 @@ int main(int argc, char **argv) {"absolute-percpu", no_argument, &absolute_percpu, 1}, {"base-relative", no_argument, &base_relative, 1}, {"lto-clang", no_argument, <o_clang, 1}, From f6c27b22f6f84b13ad230dcf3afa7f11efe7a8bc Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:48:08 +0000 Subject: [PATCH 053/108] generic: 6.6: fix realtek PHY detection patch Avoid crashing the kernel when trying to detect early versions of RealTek RTL8221B 2.5G Ethernet PHY. Signed-off-by: Daniel Golle --- ...tek-detect-early-version-of-RTL8221B.patch | 43 +++++++++++++++---- ...ealtek-support-interrupt-of-RTL8221B.patch | 4 +- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch index 2a8e742a74..1d30a19654 100644 --- a/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -1,4 +1,4 @@ -From 0de82310d2b32e78ff79d42c08b1122a6ede3778 Mon Sep 17 00:00:00 2001 +From e52faf1564a8bcaf866f9a6c7bf0e8a8748afb15 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 00:15:41 +0100 Subject: [PATCH] net: phy: realtek: detect early version of RTL8221B @@ -10,11 +10,22 @@ Implement custom identify function using the PKGID instead of iterating over the implemented MMDs. Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 50 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 49 insertions(+), 1 deletion(-) --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -782,6 +782,38 @@ static int rtl8226_match_phy_device(stru - rtlgen_supports_2_5gbps(phydev); +@@ -81,6 +81,7 @@ + + #define RTL_GENERIC_PHYID 0x001cc800 + #define RTL_8211FVD_PHYID 0x001cc878 ++#define RTL_8221B_VB_CG 0x001cc849 + + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); +@@ -801,6 +802,54 @@ static int rtl822x_probe(struct phy_devi + return 0; } +static int rtl8221b_vb_cg_match_phy_device(struct phy_device *phydev) @@ -22,7 +33,15 @@ Signed-off-by: Daniel Golle + int val; + u32 id; + -+ if (phydev->drv->read_mmd) { ++ if (phydev->is_c45) { ++ if (phydev->c45_ids.device_ids[1]) ++ return phydev->c45_ids.device_ids[1] == RTL_8221B_VB_CG; ++ } else { ++ if (phydev->phy_id) ++ return phydev->phy_id == RTL_8221B_VB_CG; ++ } ++ ++ if (phydev->mdio.bus->read_c45) { + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID1); + if (val < 0) + return 0; @@ -46,13 +65,21 @@ Signed-off-by: Daniel Golle + id |= val; + } + -+ return (id == 0x001cc849); ++ if (id != RTL_8221B_VB_CG) ++ return 0; ++ ++ if (phydev->is_c45) ++ phydev->c45_ids.device_ids[1] = id; ++ else ++ phydev->phy_id = id; ++ ++ return 1; +} + - static int rtl822x_probe(struct phy_device *phydev) + static int rtlgen_resume(struct phy_device *phydev) { - struct device *dev = &phydev->mdio.dev; -@@ -1134,7 +1166,7 @@ static struct phy_driver realtek_drvs[] + int ret = genphy_resume(phydev); +@@ -1134,7 +1183,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .soft_reset = genphy_soft_reset, }, { diff --git a/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch index 3c68bf8bbd..aab0d3f7d5 100644 --- a/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -1009,6 +1009,51 @@ static int rtl8221b_config_init(struct p +@@ -1026,6 +1026,51 @@ static int rtl8221b_config_init(struct p return 0; } @@ -52,7 +52,7 @@ static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1171,6 +1216,8 @@ static struct phy_driver realtek_drvs[] +@@ -1188,6 +1233,8 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, From 8d83b9ee2dd4e22a1bf08d117c9b508ff5c66709 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 13:15:41 +0800 Subject: [PATCH 054/108] kernel: modules: iio: adapt for kernel 6.6 Adapt iio kmods for building under kernel 6.6: * kmod-iio-lsm6dsx depends on kmod-kmod-industrialio-triggered-buffer from 6.2 Signed-off-by: Weijie Gao --- package/kernel/linux/modules/iio.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/iio.mk b/package/kernel/linux/modules/iio.mk index f901f87ddd..7cf0952db3 100644 --- a/package/kernel/linux/modules/iio.mk +++ b/package/kernel/linux/modules/iio.mk @@ -383,7 +383,7 @@ $(eval $(call KernelPackage,iio-st_accel-spi)) define KernelPackage/iio-lsm6dsx - DEPENDS:=+kmod-iio-kfifo-buf +kmod-regmap-core + DEPENDS:=+kmod-iio-kfifo-buf +kmod-regmap-core +LINUX_6_6:kmod-industrialio-triggered-buffer TITLE:=ST LSM6DSx driver for IMU MEMS sensors KCONFIG:=CONFIG_IIO_ST_LSM6DSX FILES:=$(LINUX_DIR)/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.ko From 0c98d99c5e8178ee8e578e67afa7bee7da9e4a14 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 15:08:41 +0800 Subject: [PATCH 055/108] kernel: modules: input: adapt for kernel 6.6 Adapt input kmods for building under kernel 6.6: * kmod-input-touchscreen-edt-ft5x06 depends on kmod-regmap-i2c from 6.3 as it starts to use regmap to access registers * CONFIG_HID_SUPPORT needs to be set in addition to CONFIG_HID. Signed-off-by: Daniel Golle Signed-off-by: Weijie Gao --- package/kernel/linux/modules/input.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/linux/modules/input.mk b/package/kernel/linux/modules/input.mk index 92587b1874..89fba29005 100644 --- a/package/kernel/linux/modules/input.mk +++ b/package/kernel/linux/modules/input.mk @@ -11,7 +11,7 @@ define KernelPackage/hid SUBMENU:=$(INPUT_MODULES_MENU) TITLE:=HID Devices DEPENDS:=+kmod-input-core +kmod-input-evdev - KCONFIG:=CONFIG_HID CONFIG_HIDRAW=y CONFIG_HID_BATTERY_STRENGTH=y + KCONFIG:=CONFIG_HID CONFIG_HID_SUPPORT=y CONFIG_HIDRAW=y CONFIG_HID_BATTERY_STRENGTH=y FILES:=$(LINUX_DIR)/drivers/hid/hid.ko AUTOLOAD:=$(call AutoLoad,61,hid) endef @@ -179,7 +179,7 @@ $(eval $(call KernelPackage,input-touchscreen-ads7846)) define KernelPackage/input-touchscreen-edt-ft5x06 SUBMENU:=$(INPUT_MODULES_MENU) TITLE:=EDT FT5x06 and Focaltech FT6236 based touchscreens - DEPENDS:=+kmod-i2c-core +kmod-input-core + DEPENDS:=+kmod-i2c-core +kmod-input-core +LINUX_6_6:kmod-regmap-i2c KCONFIG:= \ CONFIG_INPUT_TOUCHSCREEN=y \ CONFIG_TOUCHSCREEN_EDT_FT5X06 From 48b52d51dcb976a57875435786562987d5b8d2f7 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 15:09:12 +0800 Subject: [PATCH 056/108] kernel: modules: netsupport: adapt for kernel 6.6 Adapt netsupport kmods for building under kernel 6.6: * common part of mqprio was split into a new Kconfig since 6.3. Add new kmod-sched-mqprio-common as dependency for kmod-sched-mqprio. Signed-off-by: Weijie Gao --- package/kernel/linux/modules/netsupport.mk | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk index 535c087dec..0ee58fada4 100644 --- a/package/kernel/linux/modules/netsupport.mk +++ b/package/kernel/linux/modules/netsupport.mk @@ -907,10 +907,26 @@ endef $(eval $(call KernelPackage,sched-ipset)) +define KernelPackage/sched-mqprio-common + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=mqprio queue common dependencies support + DEPENDS:=@LINUX_6_6 + HIDDEN:=1 + KCONFIG:=CONFIG_NET_SCH_MQPRIO_LIB + FILES:=$(LINUX_DIR)/net/sched/sch_mqprio_lib.ko +endef + +define KernelPackage/sched-mqprio-common/description + Common library for manipulating mqprio queue configurations +endef + +$(eval $(call KernelPackage,sched-mqprio-common)) + + define KernelPackage/sched-mqprio SUBMENU:=$(NETWORK_SUPPORT_MENU) TITLE:=Multi-queue priority scheduler (MQPRIO) - DEPENDS:=+kmod-sched-core + DEPENDS:=+kmod-sched-core +LINUX_6_6:kmod-sched-mqprio-common KCONFIG:=CONFIG_NET_SCH_MQPRIO FILES:=$(LINUX_DIR)/net/sched/sch_mqprio.ko AUTOLOAD:=$(call AutoProbe, sch_mqprio) From ad2906b40573b35d01d5de636fd41edcc9b6a26d Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:21:29 +0000 Subject: [PATCH 057/108] kernel: modules: netdevices: adapt for kernel 6.6 Adapt netdevices kmods for building under kernel 6.6: * Add missing module dependency for kmod-stmmac-core on kmod-of-mdio. * Invert criteria to allow Airoha EN8811H PHY driver to build with Linux 6.1 as well as Linux 6.6. * Mellanox mlx5 driver started exposing thermal sensors and now it requires hwmon Signed-off-by: Robert Marko Signed-off-by: Daniel Golle --- package/kernel/linux/modules/netdevices.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index 72504d8de7..d43866ed9b 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -378,7 +378,7 @@ $(eval $(call KernelPackage,phy-smsc)) define KernelPackage/phy-airoha-en8811h SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Airoha EN8811H 2.5G Ethernet PHY - DEPENDS:=+airoha-en8811h-firmware +kmod-libphy @LINUX_6_1 + DEPENDS:=+airoha-en8811h-firmware +kmod-libphy @!LINUX_5_15 KCONFIG:=CONFIG_AIR_EN8811H_PHY FILES:= \ $(LINUX_DIR)/drivers/net/phy/air_en8811h.ko @@ -1360,7 +1360,7 @@ $(eval $(call KernelPackage,mlx4-core)) define KernelPackage/mlx5-core SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Mellanox ConnectX(R) mlx5 core Network Driver - DEPENDS:=@PCI_SUPPORT +kmod-ptp +kmod-mlxfw + DEPENDS:=@PCI_SUPPORT +kmod-ptp +kmod-mlxfw +LINUX_6_6:kmod-hwmon-core FILES:=$(LINUX_DIR)/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko KCONFIG:= CONFIG_MLX5_CORE \ CONFIG_MLX5_CORE_EN=y \ @@ -1573,7 +1573,7 @@ $(eval $(call KernelPackage,pcs-xpcs)) define KernelPackage/stmmac-core SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Synopsis Ethernet Controller core (NXP,STMMicro,others) - DEPENDS:=@TARGET_x86_64||TARGET_armsr_armv8 +kmod-pcs-xpcs +kmod-ptp + DEPENDS:=@TARGET_x86_64||TARGET_armsr_armv8 +kmod-pcs-xpcs +LINUX_6_6:kmod-of-mdio +kmod-ptp KCONFIG:=CONFIG_STMMAC_ETH \ CONFIG_STMMAC_SELFTESTS=n \ CONFIG_STMMAC_PLATFORM \ From ef523fdb075b2fd0cd96d1a209693f120ab7369c Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 15:17:17 +0800 Subject: [PATCH 058/108] kernel: modules: usb: adapt for kernel 6.6 Adapt usb kmods for building under kernel 6.6: * Add kmod-phylink as dependency for usb-net-asix * Add kmod-net-selftests as dependency for usb-net-smsc95xx * Add kmod-iio-core as dependency for usb-hid-mcp2221 as ADC/DAC support was added since 6.2 which requires IIO. Signed-off-by: Weijie Gao --- package/kernel/linux/modules/usb.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk index f4a2113e17..7b680288b9 100644 --- a/package/kernel/linux/modules/usb.mk +++ b/package/kernel/linux/modules/usb.mk @@ -1184,7 +1184,7 @@ define KernelPackage/usb-net-asix TITLE:=Kernel module for USB-to-Ethernet Asix convertors DEPENDS:= \ +kmod-libphy +kmod-net-selftests +kmod-mdio-devres +kmod-phy-ax88796b \ - +LINUX_6_1:kmod-phylink + +LINUX_6_1:kmod-phylink +LINUX_6_6:kmod-phylink KCONFIG:=CONFIG_USB_NET_AX8817X FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/asix.ko AUTOLOAD:=$(call AutoProbe,asix) @@ -1312,7 +1312,7 @@ $(eval $(call KernelPackage,usb-net-smsc75xx)) define KernelPackage/usb-net-smsc95xx TITLE:=SMSC LAN95XX based USB 2.0 10/100 ethernet devices - DEPENDS:=+kmod-libphy +kmod-phy-smsc +LINUX_6_1:kmod-net-selftests + DEPENDS:=+kmod-libphy +kmod-phy-smsc +!LINUX_5_15:kmod-net-selftests KCONFIG:=CONFIG_USB_NET_SMSC95XX FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/smsc95xx.ko AUTOLOAD:=$(call AutoProbe,smsc95xx) @@ -1605,7 +1605,7 @@ define KernelPackage/usb-hid-mcp2221 SUBMENU:=$(USB_MENU) TITLE:=Microchip USB 2.0 to I2C/UART Protocol Converter with GPIO KCONFIG:=CONFIG_HID_MCP2221 - DEPENDS:=@GPIO_SUPPORT +kmod-usb-hid +kmod-i2c-core + DEPENDS:=@GPIO_SUPPORT +kmod-usb-hid +kmod-i2c-core +LINUX_6_6:kmod-iio-core FILES:=$(LINUX_DIR)/drivers/hid/hid-mcp2221.ko AUTOLOAD:=$(call AutoProbe,hid-mcp2221) endef From f9198480da262d379dc1604e2c5338a213aef6d0 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 15:56:26 +0800 Subject: [PATCH 059/108] kernel: modules: fs: adapt for kernel 6.6 Adapt fs kmods for building under kernel 6.6: * Add kmod-fs-netfs as dependency for kmod-fs-9p * Add kmod-fs-netfs as dependency for fs-smbfs-common as netfs is required for cifs since 6.3 * Add new kmod-nls-ucs2-utils as dependency for smbfs/jfs as UCS2 support was split as new module since 6.6. * Add kmod-lib-zlib-deflate and kmod-lib-zlib-inflate as dependencies for kmod-pstore due to crypto API compression was replaced with zlib_deflate library calls since 6.6 * Remove nfs_ssc.ko from kmod-fs-nfs-common. The nfs_ssc was no longer a kernel module described by NFS_V4_2_SSC_HELPER since 5.13 [1] Link: [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/fs/Kconfig?id=d9092b4bb2109502eb8972021a3f74febc931a63 Signed-off-by: Weijie Gao --- package/kernel/linux/modules/fs.mk | 8 +++++--- package/kernel/linux/modules/nls.mk | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index 58af180c28..8f1ed41484 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -10,7 +10,7 @@ FS_MENU:=Filesystems define KernelPackage/fs-9p SUBMENU:=$(FS_MENU) TITLE:=Plan 9 Resource Sharing Support - DEPENDS:=+kmod-9pnet +LINUX_6_1:kmod-fs-netfs + DEPENDS:=+kmod-9pnet +LINUX_6_1:kmod-fs-netfs +LINUX_6_6:kmod-fs-netfs KCONFIG:=\ CONFIG_9P_FS \ CONFIG_9P_FS_POSIX_ACL=n \ @@ -87,6 +87,7 @@ define KernelPackage/fs-smbfs-common SUBMENU:=$(FS_MENU) TITLE:=SMBFS common dependencies support HIDDEN:=1 + DEPENDS:=+LINUX_6_6:kmod-fs-netfs +LINUX_6_6:kmod-nls-ucs2-utils KCONFIG:=\ CONFIG_SMBFS_COMMON@lt6.1 \ CONFIG_SMBFS@ge6.1 @@ -344,6 +345,7 @@ define KernelPackage/fs-jfs FILES:=$(LINUX_DIR)/fs/jfs/jfs.ko AUTOLOAD:=$(call AutoLoad,30,jfs,1) $(call AddDepends/nls) + DEPENDS:=+LINUX_6_6:kmod-nls-ucs2-utils endef define KernelPackage/fs-jfs/description @@ -470,8 +472,7 @@ define KernelPackage/fs-nfs-common FILES:= \ $(LINUX_DIR)/fs/lockd/lockd.ko \ $(LINUX_DIR)/net/sunrpc/sunrpc.ko \ - $(LINUX_DIR)/fs/nfs_common/grace.ko \ - $(LINUX_DIR)/fs/nfs_common/nfs_ssc.ko + $(LINUX_DIR)/fs/nfs_common/grace.ko AUTOLOAD:=$(call AutoLoad,30,grace sunrpc lockd) endef @@ -712,6 +713,7 @@ define KernelPackage/pstore CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y FILES:= $(LINUX_DIR)/fs/pstore/pstore.ko AUTOLOAD:=$(call AutoLoad,30,pstore,1) + DEPENDS:=+LINUX_6_6:kmod-lib-zlib-deflate +LINUX_6_6:kmod-lib-zlib-inflate endef define KernelPackage/pstore/description diff --git a/package/kernel/linux/modules/nls.mk b/package/kernel/linux/modules/nls.mk index 7450ed1ce5..893ec9c23a 100644 --- a/package/kernel/linux/modules/nls.mk +++ b/package/kernel/linux/modules/nls.mk @@ -339,3 +339,20 @@ define KernelPackage/nls-utf8/description endef $(eval $(call KernelPackage,nls-utf8)) + + +define KernelPackage/nls-ucs2-utils + SUBMENU:=Native Language Support + TITLE:=UCS-2 common library + DEPENDS+=@LINUX_6_6 + HIDDEN:=1 + KCONFIG:=CONFIG_NLS_UCS2_UTILS + FILES:=$(LINUX_DIR)/fs/nls/nls_ucs2_utils.ko + $(call AddDepends/nls) +endef + +define KernelPackage/nls-ucs2-utils/description + UCS-2 common library +endef + +$(eval $(call KernelPackage,nls-ucs2-utils)) From 85ede9291bfa204982d35c5e036d42024575ae99 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 16:12:06 +0800 Subject: [PATCH 060/108] kernel: modules: block: adapt for kernel 6.6 Adapt block kmods for building under kernel 6.6: * To build scsi_transport_iscsi.ko, change CONFIG_SCSI_ISCSI_ATTRS from =y to =m as this config is always tristate since 2.6. Signed-off-by: Weijie Gao --- package/kernel/linux/modules/block.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/block.mk b/package/kernel/linux/modules/block.mk index 5e6eefa76a..49a1b6fce1 100644 --- a/package/kernel/linux/modules/block.mk +++ b/package/kernel/linux/modules/block.mk @@ -263,7 +263,7 @@ define KernelPackage/iscsi-initiator CONFIG_INET \ CONFIG_SCSI_LOWLEVEL=y \ CONFIG_ISCSI_TCP \ - CONFIG_SCSI_ISCSI_ATTRS=y + CONFIG_SCSI_ISCSI_ATTRS FILES:= \ $(LINUX_DIR)/drivers/scsi/iscsi_tcp.ko \ $(LINUX_DIR)/drivers/scsi/libiscsi.ko \ From 5b08b56007205b9703f207c8f6235ca83ba359af Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sat, 6 Jan 2024 16:19:10 +0800 Subject: [PATCH 061/108] kernel: modules: video: adapt for kernel 6.6 Adapt video kmods for building under kernel 6.6: * Add drm_exec.ko and drm_suballoc_helper.ko for kmod-drm as they are added since 6.6 and 6.4 * Add uvc.ko for kmod-video-uvc as related contents was split as a new module since 6.3 Signed-off-by: Tan Zien Signed-off-by: Weijie Gao --- package/kernel/linux/modules/video.mk | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/package/kernel/linux/modules/video.mk b/package/kernel/linux/modules/video.mk index 982bcb1db0..e3a350e781 100644 --- a/package/kernel/linux/modules/video.mk +++ b/package/kernel/linux/modules/video.mk @@ -246,11 +246,15 @@ define KernelPackage/drm HIDDEN:=1 DEPENDS:=+kmod-dma-buf +kmod-i2c-core +PACKAGE_kmod-backlight:kmod-backlight \ +kmod-fb - KCONFIG:=CONFIG_DRM + KCONFIG:=CONFIG_DRM \ + CONFIG_DRM_EXEC@ge6.6 \ + CONFIG_DRM_SUBALLOC_HELPER@ge6.4 FILES:= \ $(LINUX_DIR)/drivers/gpu/drm/drm.ko \ - $(LINUX_DIR)/drivers/gpu/drm/drm_panel_orientation_quirks.ko - AUTOLOAD:=$(call AutoLoad,05,drm) + $(LINUX_DIR)/drivers/gpu/drm/drm_panel_orientation_quirks.ko \ + $(LINUX_DIR)/drivers/gpu/drm/drm_exec.ko@ge6.6 \ + $(LINUX_DIR)/drivers/gpu/drm/drm_suballoc_helper.ko@ge6.4 + AUTOLOAD:=$(call AutoLoad,05,drm_exec@ge6.6 drm_suballoc_helper@ge6.4 drm) endef define KernelPackage/drm/description @@ -262,7 +266,7 @@ $(eval $(call KernelPackage,drm)) define KernelPackage/drm-buddy SUBMENU:=$(VIDEO_MENU) TITLE:=A page based buddy allocator - DEPENDS:=@DISPLAY_SUPPORT +kmod-drm @LINUX_6_1 + DEPENDS:=@DISPLAY_SUPPORT +kmod-drm @LINUX_6_1||LINUX_6_6 KCONFIG:=CONFIG_DRM_BUDDY FILES:= $(LINUX_DIR)/drivers/gpu/drm/drm_buddy.ko AUTOLOAD:=$(call AutoProbe,drm_buddy) @@ -277,7 +281,7 @@ $(eval $(call KernelPackage,drm-buddy)) define KernelPackage/drm-display-helper SUBMENU:=$(VIDEO_MENU) TITLE:=DRM helpers for display adapters drivers - DEPENDS:=@DISPLAY_SUPPORT +kmod-drm-kms-helper @LINUX_6_1 + DEPENDS:=@DISPLAY_SUPPORT +kmod-drm-kms-helper @LINUX_6_1||LINUX_6_6 KCONFIG:=CONFIG_DRM_DISPLAY_HELPER FILES:=$(LINUX_DIR)/drivers/gpu/drm/display/drm_display_helper.ko AUTOLOAD:=$(call AutoProbe,drm_display_helper) @@ -349,7 +353,8 @@ define KernelPackage/drm-amdgpu CONFIG_DRM_AMD_DC=y \ CONFIG_DEBUG_KERNEL_DC=n FILES:=$(LINUX_DIR)/drivers/gpu/drm/amd/amdgpu/amdgpu.ko \ - $(LINUX_DIR)/drivers/gpu/drm/scheduler/gpu-sched.ko + $(LINUX_DIR)/drivers/gpu/drm/scheduler/gpu-sched.ko \ + $(LINUX_DIR)/drivers/gpu/drm/amd/amdxcp/amdxcp.ko@ge6.5 AUTOLOAD:=$(call AutoProbe,amdgpu) endef @@ -557,9 +562,10 @@ $(eval $(call KernelPackage,video-pwc)) define KernelPackage/video-uvc TITLE:=USB Video Class (UVC) support DEPENDS:=@USB_SUPPORT +kmod-usb-core +kmod-video-videobuf2 +kmod-input-core - KCONFIG:= CONFIG_USB_VIDEO_CLASS - FILES:=$(LINUX_DIR)/drivers/media/$(V4L2_USB_DIR)/uvc/uvcvideo.ko - AUTOLOAD:=$(call AutoProbe,uvcvideo) + KCONFIG:= CONFIG_USB_VIDEO_CLASS CONFIG_UVC_COMMON@ge6.3 + FILES:=$(LINUX_DIR)/drivers/media/$(V4L2_USB_DIR)/uvc/uvcvideo.ko \ + $(LINUX_DIR)/drivers/media/common/uvc.ko@ge6.3 + AUTOLOAD:=$(call AutoProbe,uvc@ge6.3 uvcvideo) $(call AddDepends/camera) endef From 35b04bafa187a99044ced7df9eb9148bc771be64 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sun, 3 Mar 2024 22:07:29 +0800 Subject: [PATCH 062/108] kernel: modules: crypto: adapt for kernel 6.6 Adapt crypto kmods for building under kernel 6.6: * mpi.ko moved from lib/mpi/mpi.ko to lib/crypto/mpi/mpi.ko * jitterentropy_rng requires SHA3 support for kernel 6.6 Signed-off-by: Robert Marko Signed-off-by: Tan Zien Signed-off-by: Weijie Gao --- package/kernel/linux/modules/crypto.mk | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index b7cecb8919..f61f258603 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -39,7 +39,8 @@ define KernelPackage/crypto-aead TITLE:=CryptoAPI AEAD support KCONFIG:= \ CONFIG_CRYPTO_AEAD \ - CONFIG_CRYPTO_AEAD2 + CONFIG_CRYPTO_AEAD2 \ + CONFIG_CRYPTO_GENIV FILES:= \ $(LINUX_DIR)/crypto/aead.ko \ $(LINUX_DIR)/crypto/geniv.ko @@ -216,7 +217,7 @@ $(eval $(call KernelPackage,crypto-ecb)) define KernelPackage/crypto-ecdh TITLE:=ECDH algorithm - DEPENDS:=+kmod-crypto-kpp + DEPENDS:=+kmod-crypto-kpp +kmod-crypto-rng KCONFIG:= CONFIG_CRYPTO_ECDH FILES:= \ $(LINUX_DIR)/crypto/ecdh_generic.ko \ @@ -846,7 +847,8 @@ define KernelPackage/crypto-rsa KCONFIG:= CONFIG_CRYPTO_RSA HIDDEN:=1 FILES:= \ - $(LINUX_DIR)/lib/mpi/mpi.ko \ + $(LINUX_DIR)/lib/mpi/mpi.ko@lt6.5 \ + $(LINUX_DIR)/lib/crypto/mpi/mpi.ko@ge6.5 \ $(LINUX_DIR)/crypto/akcipher.ko \ $(LINUX_DIR)/crypto/rsa_generic.ko AUTOLOAD:=$(call AutoLoad,10,rsa_generic) @@ -870,7 +872,7 @@ $(eval $(call KernelPackage,crypto-rmd160)) define KernelPackage/crypto-rng TITLE:=CryptoAPI random number generation - DEPENDS:=+kmod-crypto-hash +kmod-crypto-hmac +kmod-crypto-sha512 + DEPENDS:=+kmod-crypto-hash +kmod-crypto-hmac +kmod-crypto-sha512 +LINUX_6_6:kmod-crypto-sha3 KCONFIG:= \ CONFIG_CRYPTO_DRBG \ CONFIG_CRYPTO_DRBG_HMAC=y \ From faf3d80bf1751e457af73fa22f2d2f3517f2d93f Mon Sep 17 00:00:00 2001 From: Tan Zien Date: Mon, 4 Mar 2024 00:57:03 +0800 Subject: [PATCH 063/108] kernel: modules: hwmon: adapt for kernel 6.6 Adapt hwmon kmods for building under kernel 6.6: * ad7418 now requires regmap * Invert criteria to allow adt7410 be built with Linux 6.1 as well as Linux 6.6. Signed-off-by: Tan Zien --- package/kernel/linux/modules/hwmon.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/linux/modules/hwmon.mk b/package/kernel/linux/modules/hwmon.mk index 8afe315344..0d105dcc9e 100644 --- a/package/kernel/linux/modules/hwmon.mk +++ b/package/kernel/linux/modules/hwmon.mk @@ -34,7 +34,7 @@ define KernelPackage/hwmon-ad7418 KCONFIG:=CONFIG_SENSORS_AD7418 FILES:=$(LINUX_DIR)/drivers/hwmon/ad7418.ko AUTOLOAD:=$(call AutoLoad,60,ad7418 ad7418) - $(call AddDepends/hwmon,+kmod-i2c-core) + $(call AddDepends/hwmon,+kmod-i2c-core +LINUX_6_6:kmod-regmap-core) endef define KernelPackage/hwmon-ad7418/description @@ -52,7 +52,7 @@ define KernelPackage/hwmon-adt7410 $(LINUX_DIR)/drivers/hwmon/adt7x10.ko \ $(LINUX_DIR)/drivers/hwmon/adt7410.ko AUTOLOAD:=$(call AutoLoad,60,adt7x10 adt7410) - $(call AddDepends/hwmon,+kmod-i2c-core +LINUX_6_1:kmod-regmap-core) + $(call AddDepends/hwmon,+kmod-i2c-core +!LINUX_5_15:kmod-regmap-core) endef define KernelPackage/hwmon-adt7410/description From b065981e15d454351e04e2c27ad2c13745a1bf7a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 7 Mar 2024 14:47:13 +0100 Subject: [PATCH 064/108] kernel: crypto: package geniv as a separate module for 6.6 In kernel 6.5 geniv was split from AEAD config symbol, in order to manage its dependencies on other code. So, lets do the same in OpenWrt and split it from aead module so others can depend on geniv directly. Signed-off-by: Robert Marko --- package/kernel/linux/modules/crypto.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index f61f258603..335930cfaa 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -891,6 +891,19 @@ endef $(eval $(call KernelPackage,crypto-rng)) +define KernelPackage/crypto-geniv + TITLE:=CryptoAPI Shared IV generator + HIDDEN:=1 + DEPENDS:=+kmod-crypto-rng +kmod-crypto-aead @LINUX_6_6 + KCONFIG:=CONFIG_CRYPTO_GENIV + FILES:=$(LINUX_DIR)/crypto/geniv.ko + AUTOLOAD:=$(call AutoLoad,09,geniv) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-geniv)) + + define KernelPackage/crypto-seqiv TITLE:=CryptoAPI Sequence Number IV Generator DEPENDS:=+kmod-crypto-aead +kmod-crypto-rng From e12945032149eb3da7f62b516f0a249711ec7275 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 7 Mar 2024 15:04:59 +0100 Subject: [PATCH 065/108] kernel: crypto: remove geniv from aead with kernel 6.6 geniv was separated intentionally from aead in kernel 6.5, and since we now have it packaged separately as well remove it from kmod-aead in 6.6. Signed-off-by: Robert Marko --- package/kernel/linux/modules/crypto.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 335930cfaa..36b03bcdef 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -40,10 +40,10 @@ define KernelPackage/crypto-aead KCONFIG:= \ CONFIG_CRYPTO_AEAD \ CONFIG_CRYPTO_AEAD2 \ - CONFIG_CRYPTO_GENIV + CONFIG_CRYPTO_GENIV@lt6.6 FILES:= \ $(LINUX_DIR)/crypto/aead.ko \ - $(LINUX_DIR)/crypto/geniv.ko + $(LINUX_DIR)/crypto/geniv.ko@lt6.6 AUTOLOAD:=$(call AutoLoad,09,aead,1) $(call AddDepends/crypto, +kmod-crypto-null) endef From 729ad2feb32b70e9060073c29e3feedc5f6c418a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 7 Mar 2024 15:08:27 +0100 Subject: [PATCH 066/108] kernel: crypto: add kmod-crypto-geniv as dependency to modules that use it Now that geniv is packaged separately for kernel 6.6, we need to add it as a dependency to kmod-crypto-seqiv and kmod-crypto-echainiv that require it under kernel 6.6. Signed-off-by: Robert Marko --- package/kernel/linux/modules/crypto.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 36b03bcdef..49882c58df 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -231,7 +231,7 @@ $(eval $(call KernelPackage,crypto-ecdh)) define KernelPackage/crypto-echainiv TITLE:=Encrypted Chain IV Generator - DEPENDS:=+kmod-crypto-aead + DEPENDS:=+kmod-crypto-aead +LINUX_6_6:kmod-crypto-geniv KCONFIG:=CONFIG_CRYPTO_ECHAINIV FILES:=$(LINUX_DIR)/crypto/echainiv.ko AUTOLOAD:=$(call AutoLoad,09,echainiv) @@ -906,7 +906,7 @@ $(eval $(call KernelPackage,crypto-geniv)) define KernelPackage/crypto-seqiv TITLE:=CryptoAPI Sequence Number IV Generator - DEPENDS:=+kmod-crypto-aead +kmod-crypto-rng + DEPENDS:=+kmod-crypto-aead +kmod-crypto-rng +LINUX_6_6:kmod-crypto-geniv KCONFIG:=CONFIG_CRYPTO_SEQIV FILES:=$(LINUX_DIR)/crypto/seqiv.ko AUTOLOAD:=$(call AutoLoad,09,seqiv) From 7fcbcea75120fbab5adb87b6c63029dfd8812a39 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Sun, 7 Jan 2024 03:31:28 +0800 Subject: [PATCH 067/108] gpio-button-hotplug: fix 6.2 build failure devm_gpiod_get_from_of_node() was removed since linux 6.2. devm_fwnode_gpiod_get() is the recommended replacement. Link: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/gpio/gpiolib-devres.c?id=650f2dc970539b3344a98c4bd18efa309e66623b Signed-off-by: Robert Marko Signed-off-by: Weijie Gao --- package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c index 522085bb2f..e36494c2fe 100644 --- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c +++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c @@ -538,8 +538,9 @@ static int gpio_keys_button_probe(struct platform_device *pdev, struct device_node *child = of_get_next_child(dev->of_node, prev); - bdata->gpiod = devm_gpiod_get_from_of_node(dev, - child, "gpios", 0, GPIOD_IN, desc); + bdata->gpiod = devm_fwnode_gpiod_get(dev, + of_fwnode_handle(child), NULL, GPIOD_IN, + desc); prev = child; } From a325c5fa014c534a3daf69f3cec99f0fc7b9b7e9 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 29 Feb 2024 23:56:40 +0800 Subject: [PATCH 068/108] mac80211: fix build with linux kernel 6.6 Fix build failure with linux kernel 6.6 Related kernel commits: 20b0b53aca43 (genetlink: introduce split op representation) bffcc6882a1b (genetlink: remove userhdr from struct genl_info) e9a688bcb193 (random: use rejection sampling for uniform bounded random integers) 3c202d14a9d7 (prandom: remove prandom_u32_max()) 3d2f20ad46f8 (wifi: iwlwifi: Use generic thermal_zone_get_trip() function) Signed-off-by: Weijie Gao --- .../230-backport_genl_info_userhdr.patch | 32 ++++ .../build/240-backport_genl_split_ops.patch | 32 ++++ .../build/250-backport_iwlwifi_thermal.patch | 160 ++++++++++++++++++ ...domize-BA-session-dialog-token-alloc.patch | 6 +- 4 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 package/kernel/mac80211/patches/build/230-backport_genl_info_userhdr.patch create mode 100644 package/kernel/mac80211/patches/build/240-backport_genl_split_ops.patch create mode 100644 package/kernel/mac80211/patches/build/250-backport_iwlwifi_thermal.patch diff --git a/package/kernel/mac80211/patches/build/230-backport_genl_info_userhdr.patch b/package/kernel/mac80211/patches/build/230-backport_genl_info_userhdr.patch new file mode 100644 index 0000000000..38f86dc37a --- /dev/null +++ b/package/kernel/mac80211/patches/build/230-backport_genl_info_userhdr.patch @@ -0,0 +1,32 @@ +--- a/backport-include/net/genetlink.h ++++ b/backport-include/net/genetlink.h +@@ -3,6 +3,7 @@ + #include_next + #include + ++#if LINUX_VERSION_IS_LESS(4,12,0) + static inline void __bp_genl_info_userhdr_set(struct genl_info *info, + void *userhdr) + { +@@ -14,7 +15,6 @@ static inline void *__bp_genl_info_userh + return info->userhdr; + } + +-#if LINUX_VERSION_IS_LESS(4,12,0) + #define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG(genl_info_extack(info), msg) + + static inline int genl_err_attr(struct genl_info *info, int err, +@@ -44,11 +44,13 @@ static inline struct netlink_ext_ack *ge + #endif + } + ++#if LINUX_VERSION_IS_LESS(6,6,0) + /* this gets put in place of info->userhdr, since we use that above */ + static inline void *genl_info_userhdr(struct genl_info *info) + { + return (u8 *)info->genlhdr + GENL_HDRLEN; + } ++#endif + + #if LINUX_VERSION_IS_LESS(4,10,0) + #define __genl_ro_after_init diff --git a/package/kernel/mac80211/patches/build/240-backport_genl_split_ops.patch b/package/kernel/mac80211/patches/build/240-backport_genl_split_ops.patch new file mode 100644 index 0000000000..b22804cf92 --- /dev/null +++ b/package/kernel/mac80211/patches/build/240-backport_genl_split_ops.patch @@ -0,0 +1,32 @@ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -16442,8 +16442,14 @@ static u32 nl80211_internal_flags[] = { + #undef SELECTOR + }; + ++#if LINUX_VERSION_IS_LESS(6,2,0) + static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) ++#else ++static int nl80211_pre_doit(const struct genl_split_ops *ops, ++ struct sk_buff *skb, ++ struct genl_info *info) ++#endif + { + struct cfg80211_registered_device *rdev = NULL; + struct wireless_dev *wdev = NULL; +@@ -16543,8 +16549,14 @@ out_unlock: + return err; + } + ++#if LINUX_VERSION_IS_LESS(6,2,0) + static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) ++#else ++static void nl80211_post_doit(const struct genl_split_ops *ops, ++ struct sk_buff *skb, ++ struct genl_info *info) ++#endif + { + u32 internal_flags = nl80211_internal_flags[ops->internal_flags]; + diff --git a/package/kernel/mac80211/patches/build/250-backport_iwlwifi_thermal.patch b/package/kernel/mac80211/patches/build/250-backport_iwlwifi_thermal.patch new file mode 100644 index 0000000000..631fdd710d --- /dev/null +++ b/package/kernel/mac80211/patches/build/250-backport_iwlwifi_thermal.patch @@ -0,0 +1,160 @@ +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -531,7 +531,11 @@ struct iwl_mvm_tt_mgmt { + * @tzone: thermal zone device data + */ + struct iwl_mvm_thermal_device { ++#if LINUX_VERSION_IS_LESS(6,6,0) + s16 temp_trips[IWL_MAX_DTS_TRIPS]; ++#else ++ struct thermal_trip trips[IWL_MAX_DTS_TRIPS]; ++#endif + u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; + struct thermal_zone_device *tzone; + }; +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +@@ -573,6 +573,7 @@ int iwl_mvm_send_temp_report_ths_cmd(str + * and uncompressed, the FW should get it compressed and sorted + */ + ++#if LINUX_VERSION_IS_LESS(6,6,0) + /* compress temp_trips to cmd array, remove uninitialized values*/ + for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { + if (mvm->tz_device.temp_trips[i] != S16_MIN) { +@@ -580,6 +581,15 @@ int iwl_mvm_send_temp_report_ths_cmd(str + cpu_to_le16(mvm->tz_device.temp_trips[i]); + } + } ++#else ++ /* compress trips to cmd array, remove uninitialized values*/ ++ for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { ++ if (mvm->tz_device.trips[i].temperature != INT_MIN) { ++ cmd.thresholds[idx++] = ++ cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000)); ++ } ++ } ++#endif + cmd.num_temps = cpu_to_le32(idx); + + if (!idx) +@@ -593,8 +603,13 @@ int iwl_mvm_send_temp_report_ths_cmd(str + */ + for (i = 0; i < idx; i++) { + for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) { ++#if LINUX_VERSION_IS_LESS(6,6,0) + if (le16_to_cpu(cmd.thresholds[i]) == + mvm->tz_device.temp_trips[j]) ++#else ++ if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) == ++ mvm->tz_device.trips[j].temperature) ++#endif + mvm->tz_device.fw_trips_index[i] = j; + } + } +@@ -638,6 +653,7 @@ out: + return ret; + } + ++#if LINUX_VERSION_IS_LESS(6,6,0) + static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device, + int trip, int *temp) + { +@@ -661,14 +677,19 @@ static int iwl_mvm_tzone_get_trip_type(s + + return 0; + } ++#endif + + static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, + int trip, int temp) + { + struct iwl_mvm *mvm = thermal_zone_device_priv(device); + struct iwl_mvm_thermal_device *tzone; ++#if LINUX_VERSION_IS_LESS(6,6,0) + int i, ret; + s16 temperature; ++#else ++ int ret; ++#endif + + mutex_lock(&mvm->mutex); + +@@ -678,17 +699,21 @@ static int iwl_mvm_tzone_set_trip_temp(s + goto out; + } + ++#if LINUX_VERSION_IS_LESS(6,6,0) + if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) { + ret = -EINVAL; + goto out; + } ++#endif + + if ((temp / 1000) > S16_MAX) { + ret = -EINVAL; + goto out; + } + ++#if LINUX_VERSION_IS_LESS(6,6,0) + temperature = (s16)(temp / 1000); ++#endif + tzone = &mvm->tz_device; + + if (!tzone) { +@@ -696,6 +721,7 @@ static int iwl_mvm_tzone_set_trip_temp(s + goto out; + } + ++#if LINUX_VERSION_IS_LESS(6,6,0) + /* no updates*/ + if (tzone->temp_trips[trip] == temperature) { + ret = 0; +@@ -711,6 +737,7 @@ static int iwl_mvm_tzone_set_trip_temp(s + } + + tzone->temp_trips[trip] = temperature; ++#endif + + ret = iwl_mvm_send_temp_report_ths_cmd(mvm); + out: +@@ -720,8 +747,10 @@ out: + + static struct thermal_zone_device_ops tzone_ops = { + .get_temp = iwl_mvm_tzone_get_temp, ++#if LINUX_VERSION_IS_LESS(6,6,0) + .get_trip_temp = iwl_mvm_tzone_get_trip_temp, + .get_trip_type = iwl_mvm_tzone_get_trip_type, ++#endif + .set_trip_temp = iwl_mvm_tzone_set_trip_temp, + }; + +@@ -743,7 +772,12 @@ static void iwl_mvm_thermal_zone_registe + BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); + + sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); ++#if LINUX_VERSION_IS_LESS(6,6,0) + mvm->tz_device.tzone = thermal_zone_device_register(name, ++#else ++ mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, ++ mvm->tz_device.trips, ++#endif + IWL_MAX_DTS_TRIPS, + IWL_WRITABLE_TRIPS_MSK, + mvm, &tzone_ops, +@@ -766,8 +800,15 @@ static void iwl_mvm_thermal_zone_registe + /* 0 is a valid temperature, + * so initialize the array with S16_MIN which invalid temperature + */ ++#if LINUX_VERSION_IS_LESS(6,6,0) + for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) + mvm->tz_device.temp_trips[i] = S16_MIN; ++#else ++ for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) { ++ mvm->tz_device.trips[i].temperature = INT_MIN; ++ mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE; ++ } ++#endif + } + + static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev, diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch index ec1e1d12eb..1034e2c928 100644 --- a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch +++ b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch @@ -28,11 +28,15 @@ Signed-off-by: Johannes Berg --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -561,6 +561,7 @@ __sta_info_alloc(struct ieee80211_sub_if +@@ -561,6 +561,11 @@ __sta_info_alloc(struct ieee80211_sub_if INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); ++#if LINUX_VERSION_IS_LESS(6,2,0) + sta->ampdu_mlme.dialog_token_allocator = prandom_u32_max(U8_MAX); ++#else ++ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX); ++#endif #ifdef CPTCFG_MAC80211_MESH if (ieee80211_vif_is_mesh(&sdata->vif)) { sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); From 504cf50eea5a8f56b114cd985e7dc7af6cf64bfa Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 1 Mar 2024 15:49:13 +0800 Subject: [PATCH 069/108] mt76: fix build failure on linux kernel 6.6 A commit introduced in kernel 6.6 has splitted page_pool.h into several headers. Thus the included header must be modified for a successful build. Ref: a9ca9f9ceff3 (page_pool: split types and declarations from page_pool.h) Signed-off-by: Weijie Gao --- .../100-fix-build-on-linux-kernel-6.6.patch | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 package/kernel/mt76/patches/100-fix-build-on-linux-kernel-6.6.patch diff --git a/package/kernel/mt76/patches/100-fix-build-on-linux-kernel-6.6.patch b/package/kernel/mt76/patches/100-fix-build-on-linux-kernel-6.6.patch new file mode 100644 index 0000000000..4fdba0c472 --- /dev/null +++ b/package/kernel/mt76/patches/100-fix-build-on-linux-kernel-6.6.patch @@ -0,0 +1,24 @@ +--- a/mac80211.c ++++ b/mac80211.c +@@ -4,7 +4,9 @@ + */ + #include + #include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0) + #include ++#endif + #include "mt76.h" + + #define CHAN2G(_idx, _freq) { \ +--- a/mt76.h ++++ b/mt76.h +@@ -13,6 +13,9 @@ + #include + #include + #include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,6,0) ++#include ++#endif + #include + #include + #include "util.h" From 01f04539701c6a08bee3f648ec40dade7aba46cc Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 1 Mar 2024 00:46:12 +0800 Subject: [PATCH 070/108] rtl8812au-ct: fix build failure on linux kernel 6.6 Use the correct return status code to avoid incompatible type error Signed-off-by: Weijie Gao --- .../patches/008-fix-ret-status-code-type.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 package/kernel/rtl8812au-ct/patches/008-fix-ret-status-code-type.patch diff --git a/package/kernel/rtl8812au-ct/patches/008-fix-ret-status-code-type.patch b/package/kernel/rtl8812au-ct/patches/008-fix-ret-status-code-type.patch new file mode 100644 index 0000000000..2c776288bf --- /dev/null +++ b/package/kernel/rtl8812au-ct/patches/008-fix-ret-status-code-type.patch @@ -0,0 +1,11 @@ +--- a/core/rtw_bt_mp.c ++++ b/core/rtw_bt_mp.c +@@ -169,7 +169,7 @@ mptbt_CheckBtRspStatus( + PBT_EXT_C2H pExtC2h + ) + { +- BT_CTRL_STATUS retStatus=BT_OP_STATUS_SUCCESS; ++ BT_CTRL_STATUS retStatus=BT_STATUS_SUCCESS; + + switch(pExtC2h->statusCode) { + case BT_OP_STATUS_SUCCESS: From ba521e5cf29815aa0c1f2258c6e3ecf42d28c237 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Fri, 1 Mar 2024 00:47:56 +0800 Subject: [PATCH 071/108] ath10k-ct: fix build error on linux kernel 6.6 Fix a build error caused by fortify checking memcpy data range. Signed-off-by: Weijie Gao --- .../patches/300-fix-fortify-checking-error.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 package/kernel/ath10k-ct/patches/300-fix-fortify-checking-error.patch diff --git a/package/kernel/ath10k-ct/patches/300-fix-fortify-checking-error.patch b/package/kernel/ath10k-ct/patches/300-fix-fortify-checking-error.patch new file mode 100644 index 0000000000..6966a5a487 --- /dev/null +++ b/package/kernel/ath10k-ct/patches/300-fix-fortify-checking-error.patch @@ -0,0 +1,11 @@ +--- a/ath10k-6.4/wmi.h ++++ b/ath10k-6.4/wmi.h +@@ -6341,7 +6341,7 @@ struct qca9880_set_ctl_table_cmd { + __le32 ctl_len; /* in bytes. This may be ignored in firmware, + * make sure ctl_info data is sizeof(qca9880_power_ctl) */ + /** ctl array (len adjusted to number of words) */ +- __le32 ctl_info[1]; /* data would be the qca9880_power_ctl table above */ ++ __le32 ctl_info[]; /* data would be the qca9880_power_ctl table above */ + }; + + /* Used by: WMI_PDEV_SET_MIMOGAIN_TABLE_CMDID */ From b72a7bf186ef86f8a805b94b1b244fd9393b4af9 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 16:09:29 +0000 Subject: [PATCH 072/108] fitblk: invert kernel version dependency Allow building fitblk with Linux 6.6 by depending on !LINUX_5_15 instead of LINUX_6_1. Signed-off-by: Daniel Golle --- package/utils/fitblk/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/utils/fitblk/Makefile b/package/utils/fitblk/Makefile index cb9e7ebb40..4da4dc46f1 100644 --- a/package/utils/fitblk/Makefile +++ b/package/utils/fitblk/Makefile @@ -16,7 +16,7 @@ define Package/fitblk SECTION:=base CATEGORY:=Base system TITLE:=fitblk firmware release tool - DEPENDS:=@LINUX_6_1 + DEPENDS:=@!LINUX_5_15 endef define Package/fitblk/description From dd02da54e9c4c25258107ad8681acf0ab70c98f5 Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 6 Mar 2024 16:29:01 -0500 Subject: [PATCH 073/108] kernel: bump 6.1 to 6.1.81 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.81 All patches automatically rebased. Build system: x86/64 Build-tested: x86/64/AMD Cezanne, ramips/tplink_archer-a6-v3, flogic/xiaomi_redmi-router-ax6000-ubootmod Run-tested: x86/64/AMD Cezanne, ramips/tplink_archer-a6-v3, flogic/xiaomi_redmi-router-ax6000-ubootmod Signed-off-by: John Audia --- include/kernel-6.1 | 4 ++-- ...50-0100-lan78xx-Enable-LEDs-and-auto-negotiation.patch | 6 +++--- ...950-0137-lan78xx-Read-initial-EEE-status-from-DT.patch | 2 +- ...net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch | 2 +- ...-lan78xx-Move-enabling-of-EEE-into-PHY-init-code.patch | 4 ++-- ...78xx-Debounce-link-events-to-minimize-poll-storm.patch | 2 +- ...0-0153-lan78xx-EEE-support-is-now-a-PHY-property.patch | 2 +- ...ia-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch | 2 +- ...ia-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch | 2 +- ...mentation-devicetree-Add-documentation-for-imx37.patch | 2 +- ...hing-lan78xx-for-SOF_TIMESTAMPING_TX_SOFTWARE-su.patch | 2 +- ...indings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch | 2 +- ...indings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch | 2 +- .../950-0594-media-i2c-IMX296-camera-sensor-driver.patch | 2 +- ...649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch | 2 +- ...indings-media-i2c-Replace-IMX708-sensor-binding-.patch | 2 +- ...-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch | 2 +- ...1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch | 2 +- .../714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch | 2 +- ...02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch | 8 ++++---- ...10-net-dsa-mt7530-introduce-separate-MDIO-driver.patch | 2 +- ...dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch | 2 +- ...Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch | 2 +- .../510-block-add-uImage.FIT-subimage-block-driver.patch | 2 +- ...ilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch | 2 +- ...9-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch | 2 +- ...-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch | 2 +- .../701-net-dsa-add-out-of-band-tagging-protocol.patch | 2 +- ...phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch | 2 +- ...MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch | 2 +- target/linux/ramips/patches-6.1/200-add-ralink-eth.patch | 2 +- 31 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index d00860a68c..1d3d508822 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .80 -LINUX_KERNEL_HASH-6.1.80 = 568ecaaebb8b87c7c8246bba67bc83402972bf34f5811651a2d3cd548ff7b671 +LINUX_VERSION-6.1 = .81 +LINUX_KERNEL_HASH-6.1.81 = 0ebd861c6fd47bb0a9d3a09664d704833d1a54750c7bf9c4ad8b5e9cbd49342b diff --git a/target/linux/bcm27xx/patches-6.1/950-0100-lan78xx-Enable-LEDs-and-auto-negotiation.patch b/target/linux/bcm27xx/patches-6.1/950-0100-lan78xx-Enable-LEDs-and-auto-negotiation.patch index 9c5a7333c4..b0c577587a 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0100-lan78xx-Enable-LEDs-and-auto-negotiation.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0100-lan78xx-Enable-LEDs-and-auto-negotiation.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -2881,6 +2881,11 @@ static int lan78xx_reset(struct lan78xx_ +@@ -2883,6 +2883,11 @@ static int lan78xx_reset(struct lan78xx_ int ret; u32 buf; u8 sig; @@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell ret = lan78xx_read_reg(dev, HW_CFG, &buf); if (ret < 0) -@@ -2945,6 +2950,10 @@ static int lan78xx_reset(struct lan78xx_ +@@ -2947,6 +2952,10 @@ static int lan78xx_reset(struct lan78xx_ buf |= HW_CFG_MEF_; @@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell ret = lan78xx_write_reg(dev, HW_CFG, buf); if (ret < 0) return ret; -@@ -3043,6 +3052,9 @@ static int lan78xx_reset(struct lan78xx_ +@@ -3046,6 +3055,9 @@ static int lan78xx_reset(struct lan78xx_ buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; } } diff --git a/target/linux/bcm27xx/patches-6.1/950-0137-lan78xx-Read-initial-EEE-status-from-DT.patch b/target/linux/bcm27xx/patches-6.1/950-0137-lan78xx-Read-initial-EEE-status-from-DT.patch index 8d097c1ea9..7c9268289c 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0137-lan78xx-Read-initial-EEE-status-from-DT.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0137-lan78xx-Read-initial-EEE-status-from-DT.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -3108,6 +3108,22 @@ static int lan78xx_open(struct net_devic +@@ -3111,6 +3111,22 @@ static int lan78xx_open(struct net_devic netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0142-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch b/target/linux/bcm27xx/patches-6.1/950-0142-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch index 22a67a0eb1..ad16a61cbc 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0142-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0142-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch @@ -37,7 +37,7 @@ Signed-off-by: Dave Stevenson static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf; -@@ -3467,8 +3476,14 @@ static int lan78xx_bind(struct lan78xx_n +@@ -3470,8 +3479,14 @@ static int lan78xx_bind(struct lan78xx_n if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; diff --git a/target/linux/bcm27xx/patches-6.1/950-0143-lan78xx-Move-enabling-of-EEE-into-PHY-init-code.patch b/target/linux/bcm27xx/patches-6.1/950-0143-lan78xx-Move-enabling-of-EEE-into-PHY-init-code.patch index 66acf38301..f8016c66d2 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0143-lan78xx-Move-enabling-of-EEE-into-PHY-init-code.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0143-lan78xx-Move-enabling-of-EEE-into-PHY-init-code.patch @@ -16,7 +16,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -2417,6 +2417,22 @@ static int lan78xx_phy_init(struct lan78 +@@ -2419,6 +2419,22 @@ static int lan78xx_phy_init(struct lan78 mii_adv_to_linkmode_adv_t(fc, mii_adv); linkmode_or(phydev->advertising, fc, phydev->advertising); @@ -39,7 +39,7 @@ Signed-off-by: Phil Elwell if (phydev->mdio.dev.of_node) { u32 reg; int len; -@@ -3117,22 +3133,6 @@ static int lan78xx_open(struct net_devic +@@ -3120,22 +3136,6 @@ static int lan78xx_open(struct net_devic netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0152-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch b/target/linux/bcm27xx/patches-6.1/950-0152-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch index 127ddbc537..85514feac4 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0152-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0152-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch @@ -28,7 +28,7 @@ See: https://github.com/raspberrypi/linux/issues/2447 static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf; -@@ -4454,7 +4459,13 @@ static int lan78xx_probe(struct usb_inte +@@ -4457,7 +4462,13 @@ static int lan78xx_probe(struct usb_inte if (ret < 0) goto out4; diff --git a/target/linux/bcm27xx/patches-6.1/950-0153-lan78xx-EEE-support-is-now-a-PHY-property.patch b/target/linux/bcm27xx/patches-6.1/950-0153-lan78xx-EEE-support-is-now-a-PHY-property.patch index b38c62273e..38510a6fd5 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0153-lan78xx-EEE-support-is-now-a-PHY-property.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0153-lan78xx-EEE-support-is-now-a-PHY-property.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -2422,7 +2422,7 @@ static int lan78xx_phy_init(struct lan78 +@@ -2424,7 +2424,7 @@ static int lan78xx_phy_init(struct lan78 mii_adv_to_linkmode_adv_t(fc, mii_adv); linkmode_or(phydev->advertising, fc, phydev->advertising); diff --git a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch index 102b1e2309..4860bae933 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch @@ -343,7 +343,7 @@ Signed-off-by: Naushir Patuck +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19283,6 +19283,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19290,6 +19290,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-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch index bae8b88490..662c057e9a 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch @@ -177,7 +177,7 @@ Signed-off-by: Phil Elwell +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19291,6 +19291,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19298,6 +19298,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch index 2a42b1feac..e1115b80bb 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch @@ -132,7 +132,7 @@ Signed-off-by: David Plowman +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19288,6 +19288,7 @@ M: Raspberry Pi Kernel Maintenance +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19332,6 +19332,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19339,6 +19339,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx519.yaml F: drivers/media/i2c/imx519.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch index ece309fc06..003e0d4ccb 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch @@ -128,7 +128,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19274,6 +19274,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19281,6 +19281,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx290.txt F: drivers/media/i2c/imx290.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch index 9c084cc80f..853b2c757a 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Sakari Ailus --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19281,6 +19281,7 @@ L: linux-media@vger.kernel.org +@@ -19288,6 +19288,7 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml diff --git a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch index db0e89b166..b2417364c6 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch @@ -219,7 +219,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19271,7 +19271,7 @@ M: Manivannan Sadhasivam +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19346,7 +19346,7 @@ M: Raspberry Pi Kernel Maintenance +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17897,6 +17897,13 @@ S: Maintained +@@ -17904,6 +17904,13 @@ S: Maintained F: Documentation/devicetree/bindings/iio/light/bh1750.yaml F: drivers/iio/light/bh1750.c diff --git a/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch index 9888ad8ade..01940e18e3 100644 --- a/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch +++ b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch @@ -16,7 +16,7 @@ Signed-off-by: Jacopo Mondi --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -15323,6 +15323,14 @@ S: Maintained +@@ -15330,6 +15330,14 @@ S: Maintained T: git git://linuxtv.org/media_tree.git F: drivers/media/i2c/ov5695.c diff --git a/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch index d56a142451..80c870159b 100644 --- a/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch +++ b/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org +@@ -12935,6 +12935,14 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/mediatek/ diff --git a/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch index 95dd24881b..8736120654 100644 --- a/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -42,7 +42,7 @@ Signed-off-by: Paolo Abeni __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); -@@ -5488,12 +5492,13 @@ static int stmmac_napi_poll_tx(struct na +@@ -5490,12 +5494,13 @@ static int stmmac_napi_poll_tx(struct na struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, tx_napi); struct stmmac_priv *priv = ch->priv_data; @@ -57,7 +57,7 @@ Signed-off-by: Paolo Abeni work_done = min(work_done, budget); if (work_done < budget && napi_complete_done(napi, work_done)) { -@@ -5504,6 +5509,10 @@ static int stmmac_napi_poll_tx(struct na +@@ -5506,6 +5511,10 @@ static int stmmac_napi_poll_tx(struct na spin_unlock_irqrestore(&ch->lock, flags); } @@ -68,7 +68,7 @@ Signed-off-by: Paolo Abeni return work_done; } -@@ -5512,12 +5521,13 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5514,12 +5523,13 @@ static int stmmac_napi_poll_rxtx(struct struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, rxtx_napi); struct stmmac_priv *priv = ch->priv_data; @@ -83,7 +83,7 @@ Signed-off-by: Paolo Abeni tx_done = min(tx_done, budget); rx_done = stmmac_rx_zc(priv, budget, chan); -@@ -5542,6 +5552,10 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5544,6 +5554,10 @@ static int stmmac_napi_poll_rxtx(struct spin_unlock_irqrestore(&ch->lock, flags); } diff --git a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch index d203711884..f57a1bf06a 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13062,6 +13062,7 @@ M: Landen Chao L: netdev@vger.kernel.org S: Maintained diff --git a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch index 63bf0e77fa..05adccf517 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -28,7 +28,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13060,9 +13060,11 @@ MEDIATEK SWITCH DRIVER +@@ -13067,9 +13067,11 @@ MEDIATEK SWITCH DRIVER M: Sean Wang M: Landen Chao M: DENG Qingfang diff --git a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 4cdd67cdcc..3cf98acc85 100644 --- a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-6.1/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 -@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h +@@ -13971,6 +13971,7 @@ F: include/uapi/linux/meye.h MOTORCOMM PHY DRIVER M: Peter Geis diff --git a/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch b/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch index 54234caf94..f88136541f 100644 --- a/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21052,6 +21052,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -21059,6 +21059,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ diff --git a/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch index 757c0b2449..4c3ac8ee07 100644 --- a/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch +++ b/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -7911,7 +7911,7 @@ static int nft_register_flowtable_net_ho +@@ -7918,7 +7918,7 @@ static int nft_register_flowtable_net_ho err = flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_BIND); diff --git a/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch index 5bd2850fec..fd1bba3089 100644 --- a/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch +++ b/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12934,7 +12934,9 @@ M: Daniel Golle +@@ -12941,7 +12941,9 @@ M: Daniel Golle L: netdev@vger.kernel.org S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c diff --git a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch index 4b1a43259f..be12bfcd21 100644 --- a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch @@ -32,7 +32,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17068,6 +17068,13 @@ L: netdev@vger.kernel.org +@@ -17075,6 +17075,13 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/qualcomm/emac/ diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch index ab01e6704a..68d1a2e23b 100644 --- a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch +++ b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch @@ -64,7 +64,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17074,6 +17074,7 @@ L: netdev@vger.kernel.org +@@ -17081,6 +17081,7 @@ L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml F: drivers/net/ethernet/qualcomm/ipqess/ diff --git a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 0bbf9ac773..4022b2a842 100644 --- a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -24,7 +24,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12938,6 +12938,15 @@ F: drivers/net/pcs/pcs-mtk-usxgmii.c +@@ -12945,6 +12945,15 @@ F: drivers/net/pcs/pcs-mtk-usxgmii.c F: include/linux/pcs/pcs-mtk-lynxi.h F: include/linux/pcs/pcs-mtk-usxgmii.h diff --git a/target/linux/ramips/patches-6.1/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch b/target/linux/ramips/patches-6.1/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch index 361dc81df7..f7ab99bc76 100644 --- a/target/linux/ramips/patches-6.1/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch +++ b/target/linux/ramips/patches-6.1/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch @@ -13,7 +13,7 @@ Signed-off-by: Thomas Bogendoerfer --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13014,6 +13014,12 @@ S: Maintained +@@ -13021,6 +13021,12 @@ S: Maintained F: Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml F: drivers/clk/ralink/clk-mt7621.c diff --git a/target/linux/ramips/patches-6.1/200-add-ralink-eth.patch b/target/linux/ramips/patches-6.1/200-add-ralink-eth.patch index cd18fe7dd4..c52c12526b 100644 --- a/target/linux/ramips/patches-6.1/200-add-ralink-eth.patch +++ b/target/linux/ramips/patches-6.1/200-add-ralink-eth.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig -@@ -167,6 +167,7 @@ source "drivers/net/ethernet/pensando/Kc +@@ -166,6 +166,7 @@ source "drivers/net/ethernet/pensando/Kc source "drivers/net/ethernet/qlogic/Kconfig" source "drivers/net/ethernet/brocade/Kconfig" source "drivers/net/ethernet/qualcomm/Kconfig" From d84128658b46f28a2f01fd5aa15d001cf59fcb9f Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 6 Mar 2024 16:19:12 -0500 Subject: [PATCH 074/108] kernel: config: add symbol introduced with 6.1.81 Add CONFIG_EFI_HANDOVER_PROTOCOL=y to the default config[1] and disable CONFIG_NFSD_V2 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/diff/arch/x86/Kconfig?id=v6.1.81&id2=v6.1.80 Signed-off-by: John Audia --- target/linux/generic/config-6.1 | 1 + target/linux/x86/config-6.1 | 1 + 2 files changed, 2 insertions(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index deecb62ba8..fabe7029c5 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -4437,6 +4437,7 @@ CONFIG_NFS_COMMON=y # CONFIG_NFS_FSCACHE is not set # CONFIG_NFS_SWAP is not set # CONFIG_NFS_V2 is not set +# CONFIG_NFSD_V2 is not set CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set diff --git a/target/linux/x86/config-6.1 b/target/linux/x86/config-6.1 index af3676f371..6580969faf 100644 --- a/target/linux/x86/config-6.1 +++ b/target/linux/x86/config-6.1 @@ -106,6 +106,7 @@ CONFIG_EARLY_PRINTK=y CONFIG_EDAC_ATOMIC_SCRUB=y CONFIG_EDAC_SUPPORT=y # CONFIG_EDD is not set +CONFIG_EFI_HANDOVER_PROTOCOL=y # CONFIG_EISA is not set # CONFIG_EUROTECH_WDT is not set # CONFIG_EXAR_WDT is not set From c0e1e7542cfd19c7bc62c6b0a9406352f9fc46f8 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 11 Mar 2024 19:10:49 +0000 Subject: [PATCH 075/108] generic: 6.6: fix copy & refresh A new patch was added meanwhile which will go as fix via netdev tree. Copy & refresh it for Linux 6.6 as well. Signed-off-by: Daniel Golle --- ..._eth_soc-release-MAC_MCR_FORCE_LINK-.patch | 50 +++++++++++++++++++ ..._eth_soc-add-paths-and-SerDes-modes-.patch | 41 +++++++-------- 2 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 target/linux/generic/pending-6.6/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch diff --git a/target/linux/generic/pending-6.6/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch b/target/linux/generic/pending-6.6/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch new file mode 100644 index 0000000000..dedd084545 --- /dev/null +++ b/target/linux/generic/pending-6.6/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch @@ -0,0 +1,50 @@ +From ef5976ae4e117fae9a61bb3c0f8319a917a425ea Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 11 Mar 2024 17:43:28 +0000 +Subject: [PATCH] net: mediatek: mtk_eth_soc: release MAC_MCR_FORCE_LINK only when MAC is up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Clearing bit MAC_MCR_FORCE_LINK which forces the link down too early +can result in MAC ending up in a broken/blocked state. + +Fix this by handling this bit in the .mac_link_up and .mac_link_down +calls instead of in .mac_finish. + +Fixes: b8fc9f30821ec ("net: ethernet: mediatek: Add basic PHYLINK support") +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -678,8 +678,7 @@ static int mtk_mac_finish(struct phylink + mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr_new = mcr_cur; + mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | +- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK | +- MAC_MCR_RX_FIFO_CLR_DIS; ++ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_RX_FIFO_CLR_DIS; + + /* Only update control register when needed! */ + if (mcr_new != mcr_cur) +@@ -695,7 +694,7 @@ static void mtk_mac_link_down(struct phy + phylink_config); + u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); ++ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + +@@ -804,7 +803,7 @@ static void mtk_mac_link_up(struct phyli + if (rx_pause) + mcr |= MAC_MCR_FORCE_RX_FC; + +- mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN; ++ mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + diff --git a/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index c9cd726aca..aedeedece9 100644 --- a/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/target/linux/generic/pending-6.6/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -1,4 +1,4 @@ -From 91bda2f441f9e37273922028ffc48ce8e91bf5bd Mon Sep 17 00:00:00 2001 +From d5e337e7aecc2e1cc9e96768062610adb95f8f72 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 12 Dec 2023 03:51:14 +0000 Subject: [PATCH] net: ethernet: mtk_eth_soc: add paths and SerDes modes for @@ -19,9 +19,9 @@ modes. Signed-off-by: Daniel Golle --- drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 291 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 292 +++++++++++++++++-- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++- - 3 files changed, 469 insertions(+), 51 deletions(-) + 3 files changed, 470 insertions(+), 51 deletions(-) --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -390,24 +390,25 @@ Signed-off-by: Daniel Golle /* Enable SGMII */ if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) -@@ -693,10 +778,13 @@ static void mtk_mac_link_down(struct phy +@@ -692,10 +777,14 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); - u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + if (!mtk_interface_mode_is_xgmii(interface)) { -+ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); -+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); -+ } else if (mac->id != MTK_GMAC1_ID) { ++ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, MTK_MAC_MCR(mac->id)); ++ if (mtk_is_netsys_v3_or_greater(mac->hw)) ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); ++ } else if (mtk_is_netsys_v3_or_greater(mac->hw) && mac->id != MTK_GMAC1_ID) { + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id)); + } } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -768,13 +856,11 @@ static void mtk_set_queue_speed(struct m +@@ -767,13 +856,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -425,7 +426,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -808,9 +894,63 @@ static void mtk_mac_link_up(struct phyli +@@ -807,9 +894,63 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -470,7 +471,7 @@ Signed-off-by: Daniel Golle + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); + -+ if (mtk_interface_mode_is_xgmii(interface)) ++ if (mtk_is_netsys_v3_or_greater(mac->hw) && mtk_interface_mode_is_xgmii(interface)) + mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); + else @@ -489,7 +490,7 @@ Signed-off-by: Daniel Golle .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, .mac_link_up = mtk_mac_link_up, -@@ -3391,6 +3531,9 @@ static int mtk_open(struct net_device *d +@@ -3390,6 +3531,9 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -499,7 +500,7 @@ Signed-off-by: Daniel Golle err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3520,6 +3663,9 @@ static int mtk_stop(struct net_device *d +@@ -3519,6 +3663,9 @@ static int mtk_stop(struct net_device *d for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) mtk_ppe_stop(eth->ppe[i]); @@ -509,7 +510,7 @@ Signed-off-by: Daniel Golle return 0; } -@@ -4517,6 +4663,7 @@ static const struct net_device_ops mtk_n +@@ -4516,6 +4663,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { const __be32 *_id = of_get_property(np, "reg", NULL); @@ -517,7 +518,7 @@ Signed-off-by: Daniel Golle phy_interface_t phy_mode; struct phylink *phylink; struct mtk_mac *mac; -@@ -4553,16 +4700,41 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4552,16 +4700,41 @@ static int mtk_add_mac(struct mtk_eth *e mac->id = id; mac->hw = eth; mac->of_node = np; @@ -567,7 +568,7 @@ Signed-off-by: Daniel Golle } memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); -@@ -4645,8 +4817,21 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4644,8 +4817,21 @@ static int mtk_add_mac(struct mtk_eth *e phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); @@ -589,7 +590,7 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4697,6 +4882,26 @@ free_netdev: +@@ -4696,6 +4882,26 @@ free_netdev: return err; } @@ -616,7 +617,7 @@ Signed-off-by: Daniel Golle void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) { struct net_device *dev, *tmp; -@@ -4843,7 +5048,8 @@ static int mtk_probe(struct platform_dev +@@ -4842,7 +5048,8 @@ static int mtk_probe(struct platform_dev regmap_write(cci, 0, 3); } @@ -626,7 +627,7 @@ Signed-off-by: Daniel Golle err = mtk_sgmii_init(eth); if (err) -@@ -4954,6 +5160,24 @@ static int mtk_probe(struct platform_dev +@@ -4953,6 +5160,24 @@ static int mtk_probe(struct platform_dev } } @@ -651,7 +652,7 @@ Signed-off-by: Daniel Golle if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, -@@ -5056,6 +5280,11 @@ static int mtk_remove(struct platform_de +@@ -5055,6 +5280,11 @@ static int mtk_remove(struct platform_de mtk_stop(eth->netdev[i]); mac = netdev_priv(eth->netdev[i]); phylink_disconnect_phy(mac->phylink); From 9cb70f399caa14102032dcd5305dcfb3b444f8b4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 01:56:31 +0000 Subject: [PATCH 076/108] mediatek: copy files-6.1 to files-6.6 Copy files from files-6.1 to files-6.6. No changes. Signed-off-by: Daniel Golle --- .../mt7981-rfb-mxl-2p5g-phy-eth1.dtso | 32 + .../mt7981-rfb-mxl-2p5g-phy-swp5.dtso | 33 + .../dts/mediatek/mt7981-rfb-spim-nand.dtso | 66 + .../arm64/boot/dts/mediatek/mt7981-rfb.dts | 188 ++ .../arch/arm64/boot/dts/mediatek/mt7981.dtsi | 822 +++++++++ .../dts/mediatek/mt7986a-rfb-spim-nand.dts | 52 + .../dts/mediatek/mt7986a-rfb-spim-nor.dts | 51 + .../arm64/boot/dts/mediatek/mt7986a-rfb.dtsi | 389 ++++ .../mt7988a-bananapi-bpi-r4-emmc.dtso | 62 + .../mediatek/mt7988a-bananapi-bpi-r4-rtc.dtso | 19 + .../mediatek/mt7988a-bananapi-bpi-r4-sd.dtso | 60 + .../mt7988a-bananapi-bpi-r4-wifi-mt7996a.dtso | 99 ++ .../dts/mediatek/mt7988a-bananapi-bpi-r4.dts | 407 +++++ .../boot/dts/mediatek/mt7988a-rfb-emmc.dtso | 33 + .../dts/mediatek/mt7988a-rfb-eth1-aqr.dtso | 41 + .../mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso | 30 + .../dts/mediatek/mt7988a-rfb-eth1-mxl.dtso | 39 + .../dts/mediatek/mt7988a-rfb-eth1-sfp.dtso | 47 + .../dts/mediatek/mt7988a-rfb-eth2-aqr.dtso | 41 + .../dts/mediatek/mt7988a-rfb-eth2-mxl.dtso | 39 + .../dts/mediatek/mt7988a-rfb-eth2-sfp.dtso | 47 + .../boot/dts/mediatek/mt7988a-rfb-sd.dtso | 31 + .../dts/mediatek/mt7988a-rfb-snfi-nand.dtso | 69 + .../dts/mediatek/mt7988a-rfb-spim-nand.dtso | 64 + .../dts/mediatek/mt7988a-rfb-spim-nor.dtso | 59 + .../arm64/boot/dts/mediatek/mt7988a-rfb.dts | 200 +++ .../arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 1569 +++++++++++++++++ .../drivers/net/phy/mediatek-2p5ge.c | 316 ++++ .../drivers/pinctrl/mediatek/pinctrl-mt7988.c | 1517 ++++++++++++++++ 29 files changed, 6422 insertions(+) create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-eth1.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-swp5.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-spim-nand.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb.dts create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981.dtsi create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-rtc.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-wifi-mt7996a.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts create mode 100644 target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi create mode 100644 target/linux/mediatek/files-6.6/drivers/net/phy/mediatek-2p5ge.c create mode 100644 target/linux/mediatek/files-6.6/drivers/pinctrl/mediatek/pinctrl-mt7988.c diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-eth1.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-eth1.dtso new file mode 100644 index 0000000000..4d0e5c0406 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-eth1.dtso @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7981-rfb", "mediatek,mt7981"; + + fragment@0 { + target = <&gmac1>; + __overlay__ { + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + }; + + fragment@1 { + target = <&mdio_bus>; + __overlay__ { + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + reset-delay-us = <600>; + reset-post-delay-us = <20000>; + + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-swp5.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-swp5.dtso new file mode 100644 index 0000000000..710e6c0bcf --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-mxl-2p5g-phy-swp5.dtso @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7981-rfb", "mediatek,mt7981"; + + fragment@0 { + target = <&sw_p5>; + __overlay__ { + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&mdio_bus>; + __overlay__ { + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + reset-delay-us = <600>; + reset-post-delay-us = <20000>; + + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-spim-nand.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-spim-nand.dtso new file mode 100644 index 0000000000..5b51dfd671 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb-spim-nand.dtso @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7981-rfb", "mediatek,mt7981"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <10000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + 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 0x0200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; + }; + }; + + fragment@1 { + target = <&wifi>; + __overlay__ { + mediatek,mtd-eeprom = <&factory 0x0>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb.dts b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb.dts new file mode 100644 index 0000000000..b2bb692956 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981-rfb.dts @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7981.dtsi" + +/ { + model = "MediaTek MT7981 RFB"; + compatible = "mediatek,mt7981-rfb", "mediatek,mt7981"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; +}; + +&crypto { + status = "okay"; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + sw_p5: port@5 { + reg = <5>; + label = "lan5"; + status = "disabled"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&xhci { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981.dtsi new file mode 100644 index 0000000000..54cfd0b4b9 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7981.dtsi @@ -0,0 +1,822 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (c) 2020 MediaTek Inc. + * Author: Sam.Shih + * Author: Jianhui Zhao + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + compatible = "mediatek,mt7981"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a53"; + reg = <0x0>; + device_type = "cpu"; + enable-method = "psci"; + }; + + cpu@1 { + compatible = "arm,cortex-a53"; + reg = <0x1>; + device_type = "cpu"; + enable-method = "psci"; + }; + }; + + ice: ice_debug { + compatible = "mediatek,mt7981-ice_debug", "mediatek,mt2701-ice_debug"; + clocks = <&infracfg CLK_INFRA_DBG_CK>; + clock-names = "ice_dbg"; + }; + + clk40m: oscillator-40m { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + clock-output-names = "clkxtal"; + #clock-cells = <0>; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + /* cooling level (0, 1, 2, 3, 4, 5, 6, 7) : (0%/25%/37.5%/50%/62.5%/75%/87.5%/100% duty) */ + cooling-levels = <0 63 95 127 159 191 223 255>; + #cooling-cells = <2>; + status = "disabled"; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + /* 64 KiB reserved for ramoops/pstore */ + ramoops@42ff0000 { + compatible = "ramoops"; + reg = <0 0x42ff0000 0 0x10000>; + record-size = <0x1000>; + }; + + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; + no-map; + }; + + wmcpu_emi: wmcpu-reserved@47c80000 { + reg = <0 0x47c80000 0 0x100000>; + no-map; + }; + + wo_emi0: wo-emi@47d80000 { + reg = <0 0x47d80000 0 0x40000>; + no-map; + }; + + wo_data: wo-data@47dc0000 { + reg = <0 0x47dc0000 0 0x240000>; + no-map; + }; + }; + + soc { + compatible = "simple-bus"; + ranges; + #address-cells = <2>; + #size-cells = <2>; + + gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + reg = <0 0x0c000000 0 0x40000>, /* GICD */ + <0 0x0c080000 0 0x200000>; /* GICR */ + interrupt-parent = <&gic>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + }; + + consys: consys@10000000 { + compatible = "mediatek,mt7981-consys"; + reg = <0 0x10000000 0 0x8600000>; + memory-region = <&wmcpu_emi>; + }; + + infracfg: clock-controller@10001000 { + compatible = "mediatek,mt7981-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + }; + + wed_pcie: wed_pcie@10003000 { + compatible = "mediatek,wed_pcie"; + reg = <0 0x10003000 0 0x10>; + }; + + topckgen: clock-controller@1001b000 { + compatible = "mediatek,mt7981-topckgen", "syscon"; + reg = <0 0x1001b000 0 0x1000>; + #clock-cells = <1>; + }; + + watchdog: watchdog@1001c000 { + compatible = "mediatek,mt7986-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x1001c000 0 0x1000>; + interrupts = ; + #reset-cells = <1>; + status = "disabled"; + }; + + apmixedsys: clock-controller@1001e000 { + compatible = "mediatek,mt7981-apmixedsys", "syscon"; + reg = <0 0x1001e000 0 0x1000>; + #clock-cells = <1>; + }; + + pwm: pwm@10048000 { + compatible = "mediatek,mt7981-pwm"; + reg = <0 0x10048000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_PWM_STA>, + <&infracfg CLK_INFRA_PWM_HCK>, + <&infracfg CLK_INFRA_PWM1_CK>, + <&infracfg CLK_INFRA_PWM2_CK>, + <&infracfg CLK_INFRA_PWM3_CK>; + clock-names = "top", "main", "pwm1", "pwm2", "pwm3"; + #pwm-cells = <2>; + }; + + sgmiisys0: syscon@10060000 { + compatible = "mediatek,mt7981-sgmiisys_0", "syscon"; + reg = <0 0x10060000 0 0x1000>; + mediatek,pnswap; + #clock-cells = <1>; + }; + + sgmiisys1: syscon@10070000 { + compatible = "mediatek,mt7981-sgmiisys_1", "syscon"; + reg = <0 0x10070000 0 0x1000>; + #clock-cells = <1>; + }; + + crypto: crypto@10320000 { + compatible = "inside-secure,safexcel-eip97"; + reg = <0 0x10320000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "ring0", "ring1", "ring2", "ring3"; + clocks = <&topckgen CLK_TOP_EIP97B>; + clock-names = "top_eip97_ck"; + assigned-clocks = <&topckgen CLK_TOP_EIP97B_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_NET1_D5>; + }; + + uart0: serial@11002000 { + compatible = "mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART0_SEL>, + <&infracfg CLK_INFRA_UART0_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_UART0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, + <&topckgen CLK_TOP_UART_SEL>; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; + status = "disabled"; + }; + + uart1: serial@11003000 { + compatible = "mediatek,mt6577-uart"; + reg = <0 0x11003000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART1_SEL>, + <&infracfg CLK_INFRA_UART1_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_UART1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + uart2: serial@11004000 { + compatible = "mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART2_SEL>, + <&infracfg CLK_INFRA_UART2_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_UART2_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + snand: snfi@11005000 { + compatible = "mediatek,mt7986-snand"; + reg = <0 0x11005000 0 0x1000>, <0 0x11006000 0 0x1000>; + reg-names = "nfi", "ecc"; + interrupts = ; + clocks = <&infracfg CLK_INFRA_SPINFI1_CK>, + <&infracfg CLK_INFRA_NFI1_CK>, + <&infracfg CLK_INFRA_NFI_HCK_CK>; + clock-names = "pad_clk", "nfi_clk", "nfi_hclk"; + assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, + <&topckgen CLK_TOP_NFI1X_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D8>, + <&topckgen CLK_TOP_CB_M_D8>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c0: i2c@11007000 { + compatible = "mediatek,mt7981-i2c"; + reg = <0 0x11007000 0 0x1000>, + <0 0x10217080 0 0x80>; + interrupts = ; + clock-div = <1>; + clocks = <&infracfg CLK_INFRA_I2C0_CK>, + <&infracfg CLK_INFRA_AP_DMA_CK>, + <&infracfg CLK_INFRA_I2C_MCK_CK>, + <&infracfg CLK_INFRA_I2C_PCK_CK>; + clock-names = "main", "dma", "arb", "pmic"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@11009000 { + compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x11009000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI2_CK>, + <&infracfg CLK_INFRA_SPI2_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi0: spi@1100a000 { + compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100a000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI0_CK>, + <&infracfg CLK_INFRA_SPI0_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@1100b000 { + compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100b000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPIM_MST_SEL>, + <&infracfg CLK_INFRA_SPI1_CK>, + <&infracfg CLK_INFRA_SPI1_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + thermal: thermal@1100c800 { + compatible = "mediatek,mt7981-thermal", "mediatek,mt7986-thermal"; + reg = <0 0x1100c800 0 0x800>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_THERM_CK>, + <&infracfg CLK_INFRA_ADC_26M_CK>; + clock-names = "therm", "auxadc"; + nvmem-cells = <&thermal_calibration>; + nvmem-cell-names = "calibration-data"; + #thermal-sensor-cells = <1>; + mediatek,auxadc = <&auxadc>; + mediatek,apmixedsys = <&apmixedsys>; + }; + + auxadc: adc@1100d000 { + compatible = "mediatek,mt7981-auxadc", + "mediatek,mt7986-auxadc", + "mediatek,mt7622-auxadc"; + reg = <0 0x1100d000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_ADC_26M_CK>, + <&infracfg CLK_INFRA_ADC_FRC_CK>; + clock-names = "main", "32k"; + #io-channel-cells = <1>; + }; + + xhci: usb@11200000 { + compatible = "mediatek,mt7986-xhci", + "mediatek,mtk-xhci"; + reg = <0 0x11200000 0 0x2e00>, + <0 0x11203e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts = ; + clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, + <&infracfg CLK_INFRA_IUSB_CK>, + <&infracfg CLK_INFRA_IUSB_133_CK>, + <&infracfg CLK_INFRA_IUSB_66M_CK>, + <&topckgen CLK_TOP_U2U3_XHCI_SEL>; + clock-names = "sys_ck", + "ref_ck", + "mcu_ck", + "dma_ck", + "xhci_ck"; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + vusb33-supply = <®_3p3v>; + status = "disabled"; + }; + + afe: audio-controller@11210000 { + compatible = "mediatek,mt79xx-audio"; + reg = <0 0x11210000 0 0x9000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_AUD_BUS_CK>, + <&infracfg CLK_INFRA_AUD_26M_CK>, + <&infracfg CLK_INFRA_AUD_L_CK>, + <&infracfg CLK_INFRA_AUD_AUD_CK>, + <&infracfg CLK_INFRA_AUD_EG2_CK>, + <&topckgen CLK_TOP_AUD_SEL>; + clock-names = "aud_bus_ck", + "aud_26m_ck", + "aud_l_ck", + "aud_aud_ck", + "aud_eg2_ck", + "aud_sel"; + assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, + <&topckgen CLK_TOP_A1SYS_SEL>, + <&topckgen CLK_TOP_AUD_L_SEL>, + <&topckgen CLK_TOP_A_TUNER_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_APLL2_196M>, + <&topckgen CLK_TOP_APLL2_D4>, + <&topckgen CLK_TOP_CB_APLL2_196M>, + <&topckgen CLK_TOP_APLL2_D4>; + status = "disabled"; + }; + + mmc0: mmc@11230000 { + compatible = "mediatek,mt7986-mmc", "mediatek,mt7981-mmc"; + reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>; + interrupts = ; + 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", "axi_cg", "ahb_cg"; + status = "disabled"; + }; + + pcie: pcie@11280000 { + compatible = "mediatek,mt7981-pcie", + "mediatek,mt7986-pcie"; + reg = <0 0x11280000 0 0x4000>; + reg-names = "pcie-mac"; + ranges = <0x82000000 0 0x20000000 + 0x0 0x20000000 0 0x10000000>; + device_type = "pci"; + interrupts = ; + bus-range = <0x00 0xff>; + clocks = <&infracfg CLK_INFRA_IPCIE_CK>, + <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, + <&infracfg CLK_INFRA_IPCIER_CK>, + <&infracfg CLK_INFRA_IPCIEB_CK>; + phys = <&u3port0 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc 0>, + <0 0 0 2 &pcie_intc 1>, + <0 0 0 3 &pcie_intc 2>, + <0 0 0 4 &pcie_intc 3>; + #interrupt-cells = <1>; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + pcie_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <0>; + }; + }; + + pio: pinctrl@11d00000 { + compatible = "mediatek,mt7981-pinctrl"; + reg = <0 0x11d00000 0 0x1000>, + <0 0x11c00000 0 0x1000>, + <0 0x11c10000 0 0x1000>, + <0 0x11d20000 0 0x1000>, + <0 0x11e00000 0 0x1000>, + <0 0x11e20000 0 0x1000>, + <0 0x11f00000 0 0x1000>, + <0 0x11f10000 0 0x1000>, + <0 0x1000b000 0 0x1000>; + reg-names = "gpio", "iocfg_rt", "iocfg_rm", + "iocfg_rb", "iocfg_lb", "iocfg_bl", + "iocfg_tm", "iocfg_tl", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 56>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + + mdio_pins: mdc-mdio-pins { + mux { + function = "eth"; + groups = "smi_mdc_mdio"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0"; + }; + }; + + wifi_dbdc_pins: wifi-dbdc-pins { + mux { + function = "eth"; + groups = "wf0_mode1"; + }; + + conf { + pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", + "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", + "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", + "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", + "WF_CBA_RESETB", "WF_DIG_RESETB"; + drive-strength = <4>; + }; + }; + + gbe_led0_pins: gbe-led0-pins { + mux { + function = "led"; + groups = "gbe_led0"; + }; + }; + + gbe_led1_pins: gbe-led1-pins { + mux { + function = "led"; + groups = "gbe_led1"; + }; + }; + }; + + topmisc: topmisc@11d10000 { + compatible = "mediatek,mt7981-topmisc", "syscon"; + reg = <0 0x11d10000 0 0x10000>; + #clock-cells = <1>; + }; + + usb_phy: usb-phy@11e10000 { + compatible = "mediatek,mt7981", + "mediatek,generic-tphy-v2"; + ranges = <0 0 0x11e10000 0x1700>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + + u2port0: usb-phy@0 { + reg = <0x0 0x700>; + clocks = <&topckgen CLK_TOP_USB_FRMCNT_SEL>; + clock-names = "ref"; + #phy-cells = <1>; + }; + + u3port0: usb-phy@700 { + reg = <0x700 0x900>; + clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; + clock-names = "ref"; + #phy-cells = <1>; + mediatek,syscon-type = <&topmisc 0x218 0>; + status = "okay"; + }; + }; + + efuse: efuse@11f20000 { + compatible = "mediatek,mt7981-efuse", + "mediatek,efuse"; + reg = <0 0x11f20000 0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + thermal_calibration: thermal-calib@274 { + reg = <0x274 0xc>; + }; + + phy_calibration: phy-calib@8dc { + reg = <0x8dc 0x10>; + }; + + comb_rx_imp_p0: usb3-rx-imp@8c8 { + reg = <0x8c8 1>; + bits = <0 5>; + }; + + comb_tx_imp_p0: usb3-tx-imp@8c8 { + reg = <0x8c8 2>; + bits = <5 5>; + }; + + comb_intr_p0: usb3-intr@8c9 { + reg = <0x8c9 1>; + bits = <2 6>; + }; + }; + + ethsys: clock-controller@15000000 { + compatible = "mediatek,mt7981-ethsys", + "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + }; + + wed: wed@15010000 { + compatible = "mediatek,mt7981-wed", + "mediatek,mt7986-wed", + "syscon"; + reg = <0 0x15010000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; + memory-region = <&wo_emi0>, <&wo_data>; + memory-region-names = "wo-emi", "wo-data"; + mediatek,wo-ccif = <&wo_ccif0>; + mediatek,wo-ilm = <&wo_ilm0>; + mediatek,wo-dlm = <&wo_dlm0>; + mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + + eth: ethernet@15100000 { + compatible = "mediatek,mt7981-eth"; + reg = <0 0x15100000 0 0x80000>; + interrupts = , + , + , + ; + clocks = <ðsys CLK_ETH_FE_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_GP1_EN>, + <ðsys CLK_ETH_WOCPU0_EN>, + <&sgmiisys0 CLK_SGM0_TX_EN>, + <&sgmiisys0 CLK_SGM0_RX_EN>, + <&sgmiisys0 CLK_SGM0_CK0_EN>, + <&sgmiisys0 CLK_SGM0_CDR_CK0_EN>, + <&sgmiisys1 CLK_SGM1_TX_EN>, + <&sgmiisys1 CLK_SGM1_RX_EN>, + <&sgmiisys1 CLK_SGM1_CK1_EN>, + <&sgmiisys1 CLK_SGM1_CDR_CK1_EN>, + <&topckgen CLK_TOP_SGM_REG>, + <&topckgen CLK_TOP_NETSYS_SEL>, + <&topckgen CLK_TOP_NETSYS_500M_SEL>; + clock-names = "fe", "gp2", "gp1", "wocpu0", + "sgmii_tx250m", "sgmii_rx250m", + "sgmii_cdr_ref", "sgmii_cdr_fb", + "sgmii2_tx250m", "sgmii2_rx250m", + "sgmii2_cdr_ref", "sgmii2_cdr_fb", + "sgmii_ck", "netsys0", "netsys1"; + assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, + <&topckgen CLK_TOP_SGM_325M_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_CB_NET2_800M>, + <&topckgen CLK_TOP_CB_SGM_325M>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; + mediatek,infracfg = <&topmisc>; + mediatek,wed = <&wed>; + #reset-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + mdio_bus: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + int_gbe_phy: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + phy-mode = "gmii"; + phy-is-integrated; + nvmem-cells = <&phy_calibration>; + nvmem-cell-names = "phy-cal-data"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + int_gbe_phy_led0: int-gbe-phy-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + int_gbe_phy_led1: int-gbe-phy-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + }; + }; + + wdma: wdma@15104800 { + compatible = "mediatek,wed-wdma"; + reg = <0 0x15104800 0 0x400>, + <0 0x15104c00 0 0x400>; + }; + + wo_cpuboot: syscon@15194000 { + compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; + reg = <0 0x15194000 0 0x1000>; + }; + + ap2woccif: ap2woccif@151a5000 { + compatible = "mediatek,ap2woccif"; + reg = <0 0x151a5000 0 0x1000>, + <0 0x151ad000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = , + ; + }; + + wo_ccif0: syscon@151a5000 { + compatible = "mediatek,mt7986-wo-ccif", "syscon"; + reg = <0 0x151a5000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; + }; + + wo_ilm0: syscon@151e0000 { + compatible = "mediatek,mt7986-wo-ilm", "syscon"; + reg = <0 0x151e0000 0 0x8000>; + }; + + wo_dlm0: syscon@151e8000 { + compatible = "mediatek,mt7986-wo-dlm", "syscon"; + reg = <0 0x151e8000 0 0x2000>; + }; + + wifi: wifi@18000000 { + compatible = "mediatek,mt7981-wmac"; + reg = <0 0x18000000 0 0x1000000>, + <0 0x10003000 0 0x1000>, + <0 0x11d10000 0 0x1000>; + resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>; + reset-names = "consys"; + pinctrl-0 = <&wifi_dbdc_pins>; + pinctrl-names = "dbdc"; + clocks = <&topckgen CLK_TOP_NETSYS_MCU_SEL>, + <&topckgen CLK_TOP_AP2CNN_HOST_SEL>; + clock-names = "mcu", "ap2conn"; + interrupts = , + , + , + ; + memory-region = <&wmcpu_emi>; + status = "disabled"; + }; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&thermal 0>; + + trips { + cpu_trip_active_highest: active-highest { + temperature = <70000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_high: active-high { + temperature = <60000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_med: active-med { + temperature = <50000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_low: active-low { + temperature = <45000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_lowest: active-lowest { + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + cpu-active-highest { + /* active: set fan to cooling level 7 */ + cooling-device = <&fan 7 7>; + trip = <&cpu_trip_active_highest>; + }; + + cpu-active-high { + /* active: set fan to cooling level 5 */ + cooling-device = <&fan 5 5>; + trip = <&cpu_trip_active_high>; + }; + + cpu-active-med { + /* active: set fan to cooling level 3 */ + cooling-device = <&fan 3 3>; + trip = <&cpu_trip_active_med>; + }; + + cpu-active-low { + /* active: set fan to cooling level 2 */ + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_low>; + }; + + cpu-active-lowest { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_lowest>; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + clock-frequency = <13000000>; + interrupts = , + , + , + ; + + }; + + trng { + compatible = "mediatek,mt7981-rng"; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts new file mode 100644 index 0000000000..ce007099d2 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +#include "mt7986a-rfb.dtsi" + +/ { + compatible = "mediatek,mt7986a-rfb-snand"; +}; + +&spi0 { + status = "okay"; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <10000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + 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 0x0200000>; + }; + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; +}; + +&wifi { + mediatek,mtd-eeprom = <&factory 0>; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts new file mode 100644 index 0000000000..ea148315f0 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +#include "mt7986a-rfb.dtsi" + +/ { + compatible = "mediatek,mt7986a-rfb-snor"; +}; + +&spi0 { + status = "okay"; + + spi_nor: spi_nor@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x0040000>; + }; + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x0010000>; + }; + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x00B0000>; + }; + partition@100000 { + label = "FIP"; + reg = <0x100000 0x0080000>; + }; + partition@180000 { + label = "firmware"; + reg = <0x180000 0xE00000>; + }; + }; + }; +}; + +&wifi { + mediatek,mtd-eeprom = <&factory 0>; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi new file mode 100644 index 0000000000..26d560bd4b --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7986a.dtsi" + +/ { + model = "MediaTek MT7986a RFB"; + compatible = "mediatek,mt7986a-rfb"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; +}; + +&mdio { + phy5: phy@5 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <5>; + + reset-gpios = <&pio 6 1>; + reset-deassert-us = <20000>; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <6>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 0>; + }; +}; + +&crypto { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pio { + mmc0_pins_default: mmc0-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clk", "pcie_wake", "pcie_pereset"; + }; + }; + + spic_pins_g2: spic-pins-29-to-32 { + mux { + function = "spi"; + groups = "spi1_2"; + }; + }; + + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins_g2>; + status = "okay"; + + proslic_spi: proslic_spi@0 { + compatible = "silabs,proslic_spi"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-cpha = <1>; + spi-cpol = <1>; + channel_count = <1>; + debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ + reset_gpio = <&pio 7 0>; + ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ + }; +}; + +&gmac1 { + phy-mode = "2500base-x"; + phy-connection-type = "2500base-x"; + phy-handle = <&phy6>; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@4 { + reg = <4>; + label = "wan"; + }; + + port@5 { + reg = <5>; + label = "lan6"; + + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtso new file mode 100644 index 0000000000..4945185d69 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtso @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Frank Wunderlich + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + + fragment@0 { + target-path = "/soc/mmc@11230000"; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_emmc_51>; + pinctrl-1 = <&mmc0_pins_emmc_51>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x12814>; + vqmmc-supply = <®_1p8v>; + vmmc-supply = <®_3p3v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + emmc_rootfs: block-partition-production { + partname = "production"; + }; + }; + }; + }; + }; + }; + + fragment@2 { + target-path = "/chosen"; + __overlay__ { + rootdisk-emmc = <&emmc_rootfs>; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-rtc.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-rtc.dtso new file mode 100644 index 0000000000..39910b8cfe --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-rtc.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 + * Author: Daniel Golle + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + + fragment@0 { + target = <&pcf8563>; + __overlay__ { + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dtso new file mode 100644 index 0000000000..1f5e1491a4 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dtso @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Frank Wunderlich + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + + fragment@1 { + target-path = "/soc/mmc@11230000"; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_sdcard>; + pinctrl-1 = <&mmc0_pins_sdcard>; + cd-gpios = <&pio 12 GPIO_ACTIVE_LOW>; + bus-width = <4>; + max-frequency = <52000000>; + cap-sd-highspeed; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; + no-mmc; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + sd_rootfs: block-partition-production { + partname = "production"; + }; + }; + }; + }; + }; + }; + + fragment@2 { + target-path = "/chosen"; + __overlay__ { + rootdisk-sd = <&sd_rootfs>; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-wifi-mt7996a.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-wifi-mt7996a.dtso new file mode 100644 index 0000000000..8a029b149f --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-wifi-mt7996a.dtso @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + + fragment@0 { + target-path = "/"; + __overlay__ { + wifi_12v: regulator-wifi-12v { + compatible = "regulator-fixed"; + regulator-name = "wifi"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + gpio = <&pio 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + }; + }; + + fragment@1 { + target = <&i2c_wifi>; + __overlay__ { + // 5G WIFI MAC Address EEPROM + wifi_eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + address-bits = <8>; + page-size = <8>; + size = <256>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_5g: macaddr@0 { + reg = <0x0 0x6>; + }; + }; + }; + + // 6G WIFI MAC Address EEPROM + wifi_eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + address-bits = <8>; + page-size = <8>; + size = <256>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_6g: macaddr@0 { + reg = <0x0 0x6>; + }; + }; + }; + }; + }; + + fragment@2 { + target = <&pcie0>; + __overlay__ { + pcie@0,0 { + reg = <0x0000 0 0 0 0>; + + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_5g>; + }; + }; + }; + }; + + fragment@3 { + target = <&pcie1>; + __overlay__ { + pcie@0,0 { + reg = <0x0000 0 0 0 0>; + + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_6g>; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts new file mode 100644 index 0000000000..416958428f --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts @@ -0,0 +1,407 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7988a.dtsi" +#include +#include +#include +#include + +/ { + model = "Bananapi BPI-R4"; + compatible = "bananapi,bpi-r4", + "mediatek,mt7988"; + + aliases { + serial0 = &uart0; + led-boot = &led_green; + led-failsafe = &led_green; + led-running = &led_green; + led-upgrade = &led_green; + }; + + chosen { + stdout-path = &uart0; + bootargs = "console=ttyS0,115200n1 loglevel=8 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0"; + rootdisk-spim-nand = <&ubi_rootfs>; + }; + + memory { + reg = <0x00 0x40000000 0x00 0x10000000>; + }; + + /* SFP1 cage (WAN) */ + sfp1: sfp1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp1>; + los-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 82 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&pio 70 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 69 GPIO_ACTIVE_HIGH>; + rate-select0-gpios = <&pio 21 GPIO_ACTIVE_LOW>; + maximum-power-milliwatt = <3000>; + }; + + /* SFP2 cage (LAN) */ + sfp2: sfp2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp2>; + los-gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 83 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 1 GPIO_ACTIVE_HIGH>; + rate-select0-gpios = <&pio 3 GPIO_ACTIVE_LOW>; + maximum-power-milliwatt = <3000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + wps { + label = "WPS"; + linux,code = ; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led_green: led-green { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 79 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_blue: led-blue { + function = LED_FUNCTION_WPS; + color = ; + gpios = <&pio 63 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +ð { + status = "okay"; +}; + +&gmac0 { + status = "okay"; +}; + +&gmac1 { + sfp = <&sfp2>; + managed = "in-band-status"; + phy-mode = "usxgmii"; + status = "okay"; +}; + +&gmac2 { + sfp = <&sfp1>; + managed = "in-band-status"; + phy-mode = "usxgmii"; + status = "okay"; +}; + +&switch { + status = "okay"; +}; + +&gsw_phy0 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; +}; + +&gsw_port0 { + label = "wan"; +}; + +&gsw_phy0_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy1 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; +}; + +&gsw_phy1_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy2 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; +}; + +&gsw_phy2_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy3 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; +}; + +&gsw_phy3_led0 { + status = "okay"; + color = ; +}; + +&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>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + 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; + }; + }; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_1_pins>; + status = "okay"; + + pca9545: i2c-switch@70 { + reg = <0x70>; + compatible = "nxp,pca9545"; + reset-gpios = <&pio 5 GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <0>; + + i2c_rtc: i2c@0 { //eeprom,rtc,ngff + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + status = "disabled"; + }; + }; + + i2c_sfp1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + + i2c_sfp2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + + i2c_wifi: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; +}; + +/* mPCIe SIM2 */ +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +/* mPCIe SIM3 */ +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +/* M.2 key-B SIM1 */ +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + status = "okay"; +}; + +/* M.2 key-M SSD */ +&pcie3 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + status = "okay"; +}; + +&ssusb1 { + status = "okay"; +}; + +&tphy { + status = "okay"; +}; + +&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 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "ubi"; + reg = <0x200000 0x7e00000>; + compatible = "linux,ubi"; + + volumes { + ubi-volume-ubootenv { + volname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; + }; + + ubi-volume-ubootenv2 { + volname = "ubootenv2"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; + }; + + ubi_rootfs: ubi-volume-fit { + volname = "fit"; + }; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_2_lite_pins>; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_3_pins>; +}; + +&watchdog { + status = "okay"; +}; + +&xphy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso new file mode 100644 index 0000000000..3f8ac2ae38 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Frank Wunderlich + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&mmc0>; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_emmc_51>; + pinctrl-1 = <&mmc0_pins_emmc_51>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x12814>; + vqmmc-supply = <®_1p8v>; + vmmc-supply = <®_3p3v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso new file mode 100644 index 0000000000..d21a61ad19 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&mdio_bus>; + __overlay__ { + #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 GPIO_ACTIVE_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <221000>; + }; + }; + }; + + fragment@1 { + target = <&gmac1>; + __overlay__ { + phy-mode = "usxgmii"; + phy-connection-type = "usxgmii"; + phy = <&phy0>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso new file mode 100644 index 0000000000..86ab7566dc --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&gmac1>; + __overlay__ { + phy-mode = "internal"; + phy-connection-type = "internal"; + phy = <&int_2p5g_phy>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&int_2p5g_phy>; + __overlay__ { + pinctrl-names = "i2p5gbe-led"; + pinctrl-0 = <&i2p5gbe_led0_pins>; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso new file mode 100644 index 0000000000..34a23bbd7e --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&mdio_bus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + /* external Maxlinear GPY211C */ + phy13: ethernet-phy@13 { + reg = <13>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + }; + }; + + fragment@1 { + target = <&gmac1>; + __overlay__ { + phy-mode = "2500base-x"; + phy-connection-type = "2500base-x"; + phy = <&phy13>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso new file mode 100644 index 0000000000..ba40a119cb --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&i2c2>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_0_pins>; + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + sfp_esp1: sfp@1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2>; + mod-def0-gpios = <&pio 82 GPIO_ACTIVE_LOW>; + los-gpios = <&pio 81 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&pio 36 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; + }; + }; + + fragment@2 { + target = <&gmac1>; + __overlay__ { + phy-mode = "10gbase-r"; + managed = "in-band-status"; + sfp = <&sfp_esp1>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso new file mode 100644 index 0000000000..140391fc45 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&mdio_bus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + /* external Aquantia AQR113C */ + phy8: ethernet-phy@8 { + reg = <8>; + compatible = "ethernet-phy-ieee802.3-c45"; + reset-gpios = <&pio 71 GPIO_ACTIVE_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <221000>; + }; + }; + }; + + fragment@1 { + target = <&gmac2>; + __overlay__ { + phy-mode = "usxgmii"; + phy-connection-type = "usxgmii"; + phy = <&phy8>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso new file mode 100644 index 0000000000..19e0b2799f --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&mdio_bus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + /* external Maxlinear GPY211C */ + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + }; + }; + + fragment@1 { + target = <&gmac2>; + __overlay__ { + phy-mode = "2500base-x"; + phy-connection-type = "2500base-x"; + phy = <&phy5>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso new file mode 100644 index 0000000000..b9aabd2726 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&i2c1>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_sfp_pins>; + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + sfp_esp0: sfp@0 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + mod-def0-gpios = <&pio 35 GPIO_ACTIVE_LOW>; + los-gpios = <&pio 33 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&pio 29 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; + }; + }; + + fragment@2 { + target = <&gmac2>; + __overlay__ { + phy-mode = "10gbase-r"; + managed = "in-band-status"; + sfp = <&sfp_esp0>; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso new file mode 100644 index 0000000000..04472cc12d --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Frank Wunderlich + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@1 { + target-path = <&mmc0>; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_sdcard>; + pinctrl-1 = <&mmc0_pins_sdcard>; + cd-gpios = <&pio 69 GPIO_ACTIVE_LOW>; + bus-width = <4>; + max-frequency = <52000000>; + cap-sd-highspeed; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; + no-mmc; + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso new file mode 100644 index 0000000000..86b0042f64 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&snand>; + __overlay__ { + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + 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>; + }; + + partition@180000 { + label = "Factory"; + reg = <0x180000 0x0400000>; + }; + + partition@580000 { + label = "FIP"; + reg = <0x580000 0x0200000>; + }; + + partition@780000 { + label = "ubi"; + reg = <0x780000 0x7080000>; + }; + }; + }; + }; + }; + + fragment@1 { + target = <&bch>; + __overlay__ { + status = "okay"; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso new file mode 100644 index 0000000000..a9eca00d44 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + 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>; + }; + + 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-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso new file mode 100644 index 0000000000..33bd57b3fb --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; + + fragment@0 { + target = <&spi2>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 < + 0x53 0x46 0x5F 0x42 0x4F 0x4F 0x54>; /* SF_BOOT */ + spi-cal-addrlen = <1>; + spi-cal-addr = /bits/ 32 <0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x0040000>; + }; + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x0010000>; + }; + partition@50000 { + label = "Factory"; + reg = <0x50000 0x0200000>; + }; + partition@250000 { + label = "FIP"; + reg = <0x250000 0x0080000>; + }; + partition@2D0000 { + label = "firmware"; + reg = <0x2D0000 0x1D30000>; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts new file mode 100644 index 0000000000..11dbf98301 --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a-rfb.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.dtsi" +#include +#include +#include + +/ { + model = "MediaTek MT7988A Reference Board"; + compatible = "mediatek,mt7988a-rfb", + "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"; +}; + +&gmac0 { + status = "okay"; +}; + +&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"; +}; + +&switch { + status = "okay"; +}; + +&gsw_phy0 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; +}; + +&gsw_phy0_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy1 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; +}; + +&gsw_phy1_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy2 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; +}; + +&gsw_phy2_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy3 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; +}; + +&gsw_phy3_led0 { + status = "okay"; + color = ; +}; + +&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 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie2 { + status = "disabled"; +}; + +&pcie3 { + status = "okay"; +}; + +&ssusb0 { + status = "okay"; +}; + +&ssusb1 { + status = "okay"; +}; + +&tphy { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&xphy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi new file mode 100644 index 0000000000..904339335f --- /dev/null +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi @@ -0,0 +1,1569 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Sam.Shih + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* TOPRGU resets */ +#define MT7988_TOPRGU_SGMII0_GRST 1 +#define MT7988_TOPRGU_SGMII1_GRST 2 +#define MT7988_TOPRGU_XFI0_GRST 12 +#define MT7988_TOPRGU_XFI1_GRST 13 +#define MT7988_TOPRGU_XFI_PEXTP0_GRST 14 +#define MT7988_TOPRGU_XFI_PEXTP1_GRST 15 +#define MT7988_TOPRGU_XFI_PLL_GRST 16 + +/ { + compatible = "mediatek,mt7988"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + 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>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a73"; + reg = <0x0>; + device_type = "cpu"; + enable-method = "psci"; + 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 { + compatible = "arm,cortex-a73"; + reg = <0x1>; + device_type = "cpu"; + enable-method = "psci"; + 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 { + compatible = "arm,cortex-a73"; + reg = <0x2>; + device_type = "cpu"; + enable-method = "psci"; + 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 { + compatible = "arm,cortex-a73"; + reg = <0x3>; + device_type = "cpu"; + enable-method = "psci"; + 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_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>; + }; + }; + + clk40m: oscillator@0 { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + #clock-cells = <0>; + clock-output-names = "clkxtal"; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + /* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */ + cooling-levels = <0 128 255>; + #cooling-cells = <2>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; + + pmu { + compatible = "arm,cortex-a73-pmu"; + interrupt-parent = <&gic>; + interrupt = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + /* 320 KiB reserved for ARM Trusted Firmware (BL31 and BL32) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x50000>; + no-map; + }; + }; + + soc { + compatible = "simple-bus"; + ranges; + #address-cells = <2>; + #size-cells = <2>; + + gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + 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 */ + interrupt-parent = <&gic>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + }; + + phyfw: phy-firmware@f000000 { + compatible = "mediatek,2p5gphy-fw"; + reg = <0 0x0f100000 0 0x20000>, + <0 0x0f0f0018 0 0x20>; + }; + + infracfg: infracfg@10001000 { + compatible = "mediatek,mt7988-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-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", "syscon"; + 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 84>; + 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"; + }; + }; + + i2c1_sfp_pins: i2c1-sfp-pins-g0 { + mux { + function = "i2c"; + groups = "i2c1_sfp"; + }; + }; + + i2c2_pins: i2c2-pins { + mux { + function = "i2c"; + groups = "i2c2"; + }; + }; + + i2c2_0_pins: i2c2-pins-g0 { + mux { + function = "i2c"; + groups = "i2c2_0"; + }; + }; + + i2c2_1_pins: i2c2-pins-g1 { + mux { + function = "i2c"; + groups = "i2c2_1"; + }; + }; + + gbe0_led0_pins: gbe0-led0-pins { + mux { + function = "led"; + groups = "gbe0_led0"; + }; + }; + + gbe1_led0_pins: gbe1-led0-pins { + mux { + function = "led"; + groups = "gbe1_led0"; + }; + }; + + gbe2_led0_pins: gbe2-led0-pins { + mux { + function = "led"; + groups = "gbe2_led0"; + }; + }; + + gbe3_led0_pins: gbe3-led0-pins { + mux { + function = "led"; + groups = "gbe3_led0"; + }; + }; + + gbe0_led1_pins: gbe0-led1-pins { + mux { + function = "led"; + groups = "gbe0_led1"; + }; + }; + + gbe1_led1_pins: gbe1-led1-pins { + mux { + function = "led"; + groups = "gbe1_led1"; + }; + }; + + gbe2_led1_pins: gbe2-led1-pins { + mux { + function = "led"; + groups = "gbe2_led1"; + }; + }; + + gbe3_led1_pins: gbe3-led1-pins { + mux { + function = "led"; + groups = "gbe3_led1"; + }; + }; + + i2p5gbe_led0_pins: 2p5gbe-led0-pins { + mux { + function = "led"; + groups = "2p5gbe_led0"; + }; + }; + + i2p5gbe_led1_pins: 2p5gbe-led1-pins { + mux { + function = "led"; + groups = "2p5gbe_led1"; + }; + }; + + mmc0_pins_emmc_45: mmc0-pins-emmc-45 { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + + mmc0_pins_emmc_51: mmc0-pins-emmc-51 { + mux { + function = "flash"; + groups = "emmc_51"; + }; + }; + + mmc0_pins_sdcard: mmc0-pins-sdcard { + mux { + function = "flash"; + groups = "sdcard"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0"; + }; + }; + + uart1_0_pins: uart1-0-pins { + mux { + function = "uart"; + groups = "uart1_0"; + }; + }; + + uart1_1_pins: uart1-1-pins { + mux { + function = "uart"; + groups = "uart1_1"; + }; + }; + + uart1_2_pins: uart1-2-pins { + mux { + function = "uart"; + groups = "uart1_2"; + }; + }; + + uart1_2_lite_pins: uart1-2-lite-pins { + mux { + function = "uart"; + groups = "uart1_2_lite"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + uart2_0_pins: uart2-0-pins { + mux { + function = "uart"; + groups = "uart2_0"; + }; + }; + + uart2_1_pins: uart2-1-pins { + mux { + function = "uart"; + groups = "uart2_1"; + }; + }; + + uart2_2_pins: uart2-2-pins { + mux { + function = "uart"; + groups = "uart2_2"; + }; + }; + + uart2_3_pins: uart2-3-pins { + mux { + function = "uart"; + groups = "uart2_3"; + }; + }; + + snfi_pins: snfi-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + spi0_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0"; + }; + }; + + spi0_flash_pins: spi0-flash-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi1_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1"; + }; + }; + + spi2_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2"; + }; + }; + + spi2_flash_pins: spi2-flash-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + }; + + 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"; + }; + }; + }; + + pwm: pwm@10048000 { + compatible = "mediatek,mt7988-pwm"; + reg = <0 0x10048000 0 0x1000>; + #pwm-cells = <2>; + clocks = <&infracfg CLK_INFRA_66M_PWM_BCK>, + <&infracfg CLK_INFRA_66M_PWM_HCK>, + <&infracfg CLK_INFRA_66M_PWM_CK1>, + <&infracfg CLK_INFRA_66M_PWM_CK2>, + <&infracfg CLK_INFRA_66M_PWM_CK3>, + <&infracfg CLK_INFRA_66M_PWM_CK4>, + <&infracfg CLK_INFRA_66M_PWM_CK5>, + <&infracfg CLK_INFRA_66M_PWM_CK6>, + <&infracfg CLK_INFRA_66M_PWM_CK7>, + <&infracfg CLK_INFRA_66M_PWM_CK8>; + clock-names = "top", "main", "pwm1", "pwm2", "pwm3", + "pwm4","pwm5","pwm6","pwm7","pwm8"; + status = "disabled"; + }; + + sgmiisys0: syscon@10060000 { + compatible = "mediatek,mt7988-sgmiisys", + "mediatek,mt7988-sgmiisys0", + "syscon", + "simple-mfd"; + reg = <0 0x10060000 0 0x1000>; + resets = <&watchdog MT7988_TOPRGU_SGMII0_GRST>; + #clock-cells = <1>; + + sgmiipcs0: pcs { + compatible = "mediatek,mt7988-sgmii"; + clocks = <&topckgen CLK_TOP_SGM_0_SEL>, + <&sgmiisys0 CLK_SGM0_TX_EN>, + <&sgmiisys0 CLK_SGM0_RX_EN>; + clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx"; + }; + }; + + sgmiisys1: syscon@10070000 { + compatible = "mediatek,mt7988-sgmiisys", + "mediatek,mt7988-sgmiisys1", + "syscon", + "simple-mfd"; + reg = <0 0x10070000 0 0x1000>; + resets = <&watchdog MT7988_TOPRGU_SGMII1_GRST>; + #clock-cells = <1>; + + sgmiipcs1: pcs { + compatible = "mediatek,mt7988-sgmii"; + clocks = <&topckgen CLK_TOP_SGM_1_SEL>, + <&sgmiisys1 CLK_SGM1_TX_EN>, + <&sgmiisys1 CLK_SGM1_RX_EN>; + clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx"; + }; + }; + + usxgmiisys0: pcs@10080000 { + compatible = "mediatek,mt7988-usxgmiisys"; + reg = <0 0x10080000 0 0x1000>; + resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>; + clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>; + }; + + usxgmiisys1: pcs@10081000 { + compatible = "mediatek,mt7988-usxgmiisys"; + reg = <0 0x10081000 0 0x1000>; + resets = <&watchdog MT7988_TOPRGU_XFI1_GRST>; + clocks = <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>; + }; + + 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>; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "disabled"; + }; + + uart1: serial@11000100 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11000100 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_UART1_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_MUX_UART1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + uart2: serial@11000200 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11000200 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_UART2_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_MUX_UART2_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + snand: spi@11001000 { + compatible = "mediatek,mt7986-snand"; + reg = <0 0x11001000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_SPINFI>, + <&infracfg CLK_INFRA_NFI>; + clock-names = "pad_clk", "nfi_clk"; + assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, + <&topckgen CLK_TOP_NFI1X_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_MPLL_D8>, + <&topckgen CLK_TOP_MPLL_D8>; + nand-ecc-engine = <&bch>; + mediatek,quad-spi; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&snfi_pins>; + status = "disabled"; + }; + + bch: ecc@11002000 { + compatible = "mediatek,mt7686-ecc"; + reg = <0 0x11002000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_NFI1X_SEL>; + clock-names = "nfiecc_clk"; + 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"; + }; + + spi1: spi@11008000 { + compatible = "mediatek,ipm-spi-single", "mediatek,spi-ipm"; + reg = <0 0x11008000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MPLL_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_104M_SPI1>, + <&infracfg CLK_INFRA_66M_SPI1_HCK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", + "spi-hclk"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "disabled"; + }; + + spi2: spi@11009000 { + compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; + reg = <0 0x11009000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MPLL_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_104M_SPI2_BCK>, + <&infracfg CLK_INFRA_66M_SPI2_HCK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", + "spi-hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lvts: lvts@1100a000 { + compatible = "mediatek,mt7988-lvts-ap"; + reg = <0 0x1100a000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_26M_THERM_SYSTEM>; + clock-names = "lvts_clk"; + interrupts = ; + resets = <&infracfg MT7988_INFRA_RST1_THERM_CTRL_SWRST>; + nvmem-cells = <&lvts_calibration>; + nvmem-cell-names = "lvts-calib-data-1"; + #thermal-sensor-cells = <1>; + }; + + 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"; + }; + + afe: audio-controller@11210000 { + compatible = "mediatek,mt79xx-audio"; + reg = <0 0x11210000 0 0x9000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_66M_AUD_SLV_BCK>, + <&infracfg CLK_INFRA_AUD_26M>, + <&infracfg CLK_INFRA_AUD_L>, + <&infracfg CLK_INFRA_AUD_AUD>, + <&infracfg CLK_INFRA_AUD_EG2>, + <&topckgen CLK_TOP_AUD_SEL>, + <&topckgen CLK_TOP_AUD_I2S_M>; + clock-names = "aud_bus_ck", + "aud_26m_ck", + "aud_l_ck", + "aud_aud_ck", + "aud_eg2_ck", + "aud_sel", + "aud_i2s_m"; + assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, + <&topckgen CLK_TOP_A1SYS_SEL>, + <&topckgen CLK_TOP_AUD_L_SEL>, + <&topckgen CLK_TOP_A_TUNER_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_APLL2>, + <&topckgen CLK_TOP_APLL2_D4>, + <&apmixedsys CLK_APMIXED_APLL2>, + <&topckgen CLK_TOP_APLL2_D4>; + status = "disabled"; + }; + + mmc0: mmc@11230000 { + compatible = "mediatek,mt7986-mmc", + "mediatek,mt7981-mmc"; + reg = <0 0x11230000 0 0x1000>, + <0 0x11D60000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_MSDC400>, + <&infracfg CLK_INFRA_MSDC2_HCK>, + <&infracfg CLK_INFRA_66M_MSDC_0_HCK>, + <&infracfg CLK_INFRA_133M_MSDC_0_HCK>; + assigned-clocks = <&topckgen CLK_TOP_EMMC_250M_SEL>, + <&topckgen CLK_TOP_EMMC_400M_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_NET1PLL_D5_D2>, + <&apmixedsys CLK_APMIXED_MSDCPLL>; + clock-names = "source", + "hclk", + "axi_cg", + "ahb_cg"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pcie2: pcie@11280000 { + compatible = "mediatek,mt7988-pcie", + "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + reg = <0 0x11280000 0 0x2000>; + reg-names = "pcie-mac"; + ranges = <0x81000000 0x00 0x20000000 0x00 + 0x20000000 0x00 0x00200000>, + <0x82000000 0x00 0x20200000 0x00 + 0x20200000 0x00 0x07e00000>; + device_type = "pci"; + linux,pci-domain = <3>; + interrupts = ; + bus-range = <0x00 0xff>; + 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"; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + 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>; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + 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"; + reg = <0 0x11290000 0 0x2000>; + reg-names = "pcie-mac"; + ranges = <0x81000000 0x00 0x28000000 0x00 + 0x28000000 0x00 0x00200000>, + <0x82000000 0x00 0x28200000 0x00 + 0x28200000 0x00 0x07e00000>; + device_type = "pci"; + linux,pci-domain = <2>; + interrupts = ; + bus-range = <0x00 0xff>; + 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"; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + #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>; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + 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"; + reg = <0 0x11300000 0 0x2000>; + reg-names = "pcie-mac"; + ranges = <0x81000000 0x00 0x30000000 0x00 + 0x30000000 0x00 0x00200000>, + <0x82000000 0x00 0x30200000 0x00 + 0x30200000 0x00 0x07e00000>; + device_type = "pci"; + linux,pci-domain = <0>; + interrupts = ; + bus-range = <0x00 0xff>; + 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"; + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + #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>; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + 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"; + reg = <0 0x11310000 0 0x2000>; + reg-names = "pcie-mac"; + ranges = <0x81000000 0x00 0x38000000 0x00 + 0x38000000 0x00 0x00200000>, + <0x82000000 0x00 0x38200000 0x00 + 0x38200000 0x00 0x07e00000>; + device_type = "pci"; + linux,pci-domain = <1>; + interrupts = ; + bus-range = <0x00 0xff>; + 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"; + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + #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>; + #address-cells = <3>; + #size-cells = <2>; + status = "disabled"; + + pcie_intc1: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + tphy: tphy@11c50000 { + compatible = "mediatek,mt7988", + "mediatek,generic-tphy-v2"; + ranges; + #address-cells = <2>; + #size-cells = <2>; + 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"; + ranges; + #address-cells = <2>; + #size-cells = <2>; + 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>; + }; + }; + + xfi_tphy0: phy@11f20000 { + compatible = "mediatek,mt7988-xfi-tphy"; + reg = <0 0x11f20000 0 0x10000>; + resets = <&watchdog MT7988_TOPRGU_XFI_PEXTP0_GRST>; + clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>; + clock-names = "xfipll", "topxtal"; + mediatek,usxgmii-performance-errata; + #phy-cells = <0>; + }; + + xfi_tphy1: phy@11f30000 { + compatible = "mediatek,mt7988-xfi-tphy"; + reg = <0 0x11f30000 0 0x10000>; + resets = <&watchdog MT7988_TOPRGU_XFI_PEXTP1_GRST>; + clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>; + clock-names = "xfipll", "topxtal"; + #phy-cells = <0>; + }; + + xfi_pll: clock-controller@11f40000 { + compatible = "mediatek,mt7988-xfi-pll"; + reg = <0 0x11f40000 0 0x1000>; + resets = <&watchdog MT7988_TOPRGU_XFI_PLL_GRST>; + #clock-cells = <1>; + }; + + 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 { + compatible = "mediatek,mt7988-ethsys", "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + }; + + switch: switch@15020000 { + compatible = "mediatek,mt7988-switch"; + reg = <0 0x15020000 0 0x8000>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + resets = <ðwarp MT7988_ETHWARP_RST_SWITCH>; + #address-cells = <1>; + #size-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + gsw_port0: port@0 { + reg = <0>; + label = "lan0"; + phy-mode = "internal"; + phy-handle = <&gsw_phy0>; + }; + + gsw_port1: port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "internal"; + phy-handle = <&gsw_phy1>; + }; + + gsw_port2: port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "internal"; + phy-handle = <&gsw_phy2>; + }; + + gsw_port3: 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>; + mediatek,pio = <&pio>; + + gsw_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + phy-mode = "internal"; + nvmem-cells = <&phy_calibration_p0>; + nvmem-cell-names = "phy-cal-data"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy0_led0: gsw-phy0-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy0_led1: gsw-phy0-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + + gsw_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + phy-mode = "internal"; + nvmem-cells = <&phy_calibration_p1>; + nvmem-cell-names = "phy-cal-data"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy1_led0: gsw-phy1-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy1_led1: gsw-phy1-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + + gsw_phy2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + phy-mode = "internal"; + nvmem-cells = <&phy_calibration_p2>; + nvmem-cell-names = "phy-cal-data"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy2_led0: gsw-phy2-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy2_led1: gsw-phy2-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + + gsw_phy3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + phy-mode = "internal"; + nvmem-cells = <&phy_calibration_p3>; + nvmem-cell-names = "phy-cal-data"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy3_led0: gsw-phy3-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy3_led1: gsw-phy3-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + }; + }; + + ethwarp: clock-controller@15031000 { + compatible = "mediatek,mt7988-ethwarp"; + reg = <0 0x15031000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + 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>, + <ðwarp CLK_ETHWARP_WOCPU2_EN>, + <ðwarp CLK_ETHWARP_WOCPU1_EN>, + <ðwarp CLK_ETHWARP_WOCPU0_EN>, + <&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", + "ethwarp_wocpu2", "ethwarp_wocpu1", + "ethwarp_wocpu0", "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,infracfg = <&topmisc>; + #address-cells = <1>; + #size-cells = <0>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + status = "disabled"; + pcs-handle = <&sgmiipcs1>, <&usxgmiisys1>; + phys = <&xfi_tphy1>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + status = "disabled"; + pcs-handle = <&sgmiipcs0>, <&usxgmiisys0>; + phys = <&xfi_tphy0>; + }; + + mdio_bus: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + /* internal 2.5G PHY */ + int_2p5g_phy: ethernet-phy@15 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <15>; + phy-mode = "internal"; + }; + }; + }; + + crypto: crypto@15600000 { + compatible = "inside-secure,safexcel-eip197b"; + reg = <0 0x15600000 0 0x180000>; + interrupts = , + , + , + ; + interrupt-names = "ring0", "ring1", "ring2", "ring3"; + status = "okay"; + }; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&lvts 0>; + + trips { + cpu_trip_crit: crit { + temperature = <125000>; + hysteresis = <2000>; + type = "critical"; + }; + + cpu_trip_hot: hot { + temperature = <120000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_trip_active_high: active-high { + temperature = <115000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_med: active-med { + temperature = <85000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_low: active-low { + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + cpu-active-high { + /* active: set fan to cooling level 2 */ + cooling-device = <&fan 3 3>; + trip = <&cpu_trip_active_high>; + }; + + cpu-active-low { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_med>; + }; + + cpu-passive { + /* passive: set fan to cooling level 0 */ + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_low>; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; +}; diff --git a/target/linux/mediatek/files-6.6/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-6.6/drivers/net/phy/mediatek-2p5ge.c new file mode 100644 index 0000000000..e2e06d1eca --- /dev/null +++ b/target/linux/mediatek/files-6.6/drivers/net/phy/mediatek-2p5ge.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT7988_2P5GE_PMB "mediatek/mt7988/i2p5ge-phy-pmb.bin" + +#define MD32_EN BIT(0) +#define PMEM_PRIORITY BIT(8) +#define DMEM_PRIORITY BIT(16) + +#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) + +#define MTK_PHY_LPI_PCS_DSP_CTRL 0x121 +#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8) + +/* 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) + +#define MTK_EXT_PAGE_ACCESS 0x1f +#define MTK_PHY_PAGE_STANDARD 0x0000 +#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 + +struct mtk_i2p5ge_phy_priv { + bool fw_loaded; +}; + +enum { + PHY_AUX_SPD_10 = 0, + PHY_AUX_SPD_100, + PHY_AUX_SPD_1000, + PHY_AUX_SPD_2500, +}; + +static int mtk_2p5ge_phy_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); +} + +static int mtk_2p5ge_phy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); +} + +static int mt7988_2p5ge_phy_probe(struct phy_device *phydev) +{ + struct mtk_i2p5ge_phy_priv *phy_priv; + + phy_priv = devm_kzalloc(&phydev->mdio.dev, + sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL); + if (!phy_priv) + return -ENOMEM; + + phydev->priv = phy_priv; + + return 0; +} + +static int mt7988_2p5ge_phy_config_init(struct phy_device *phydev) +{ + int ret, i; + const struct firmware *fw; + struct device *dev = &phydev->mdio.dev; + struct device_node *np; + void __iomem *pmb_addr; + void __iomem *md32_en_cfg_base; + struct mtk_i2p5ge_phy_priv *phy_priv = phydev->priv; + u16 reg; + struct pinctrl *pinctrl; + + if (!phy_priv->fw_loaded) { + np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw"); + if (!np) + return -ENOENT; + pmb_addr = of_iomap(np, 0); + if (!pmb_addr) + return -ENOMEM; + md32_en_cfg_base = of_iomap(np, 1); + if (!md32_en_cfg_base) + return -ENOMEM; + + ret = request_firmware(&fw, MT7988_2P5GE_PMB, dev); + if (ret) { + dev_err(dev, "failed to load firmware: %s, ret: %d\n", + MT7988_2P5GE_PMB, ret); + return ret; + } + + reg = readw(md32_en_cfg_base); + if (reg & MD32_EN) { + phy_set_bits(phydev, 0, BIT(15)); + usleep_range(10000, 11000); + } + phy_set_bits(phydev, 0, BIT(11)); + + /* Write magic number to safely stall MCU */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df); + + for (i = 0; i < fw->size - 1; i += 4) + writel(*((uint32_t *)(fw->data + i)), pmb_addr + i); + release_firmware(fw); + + writew(reg & ~MD32_EN, md32_en_cfg_base); + writew(reg | MD32_EN, md32_en_cfg_base); + phy_set_bits(phydev, 0, BIT(15)); + dev_info(dev, "Firmware loading/trigger ok.\n"); + + phy_priv->fw_loaded = true; + } + + /* Setup LED */ + 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); + } + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL, + MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0); + + /* Enable 16-bit next page exchange bit if 1000-BT isn't advertizing */ + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + __phy_write(phydev, 0x11, 0xfbfa); + __phy_write(phydev, 0x12, 0xc3); + __phy_write(phydev, 0x10, 0x87f8); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + return 0; +} + +static int mt7988_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 mt7988_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 mt7988. + * 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 mt7988_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->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; + 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; + /* FIXME: The current firmware always enables rate adaptation mode. */ + phydev->rate_matching = RATE_MATCH_PAUSE; + + return 0; +} + +static int mt7988_2p5ge_phy_get_rate_matching(struct phy_device *phydev, + phy_interface_t iface) +{ + return RATE_MATCH_PAUSE; +} + +static struct phy_driver mtk_gephy_driver[] = { + { + PHY_ID_MATCH_MODEL(0x00339c11), + .name = "MediaTek MT798x 2.5GbE PHY", + .probe = mt7988_2p5ge_phy_probe, + .config_init = mt7988_2p5ge_phy_config_init, + .config_aneg = mt7988_2p5ge_phy_config_aneg, + .get_features = mt7988_2p5ge_phy_get_features, + .read_status = mt7988_2p5ge_phy_read_status, + .get_rate_matching = mt7988_2p5ge_phy_get_rate_matching, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_2p5ge_phy_read_page, + .write_page = mtk_2p5ge_phy_write_page, + }, +}; + +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(MT7988_2P5GE_PMB); diff --git a/target/linux/mediatek/files-6.6/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/target/linux/mediatek/files-6.6/drivers/pinctrl/mediatek/pinctrl-mt7988.c new file mode 100644 index 0000000000..9f92911245 --- /dev/null +++ b/target/linux/mediatek/files-6.6/drivers/pinctrl/mediatek/pinctrl-mt7988.c @@ -0,0 +1,1517 @@ +// 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, 0, 5, 0x30, 0x10, 13, 1), + PIN_FIELD_BASE(1, 1, 5, 0x30, 0x10, 14, 1), + PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 11, 1), + PIN_FIELD_BASE(3, 3, 5, 0x30, 0x10, 12, 1), + PIN_FIELD_BASE(4, 4, 5, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, 5, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(6, 6, 5, 0x30, 0x10, 10, 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, 13, 1, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(14, 14, 1, 0x40, 0x10, 2, 1), + + PIN_FIELD_BASE(15, 15, 5, 0x30, 0x10, 7, 1), + PIN_FIELD_BASE(16, 16, 5, 0x30, 0x10, 8, 1), + PIN_FIELD_BASE(17, 17, 5, 0x30, 0x10, 3, 1), + PIN_FIELD_BASE(18, 18, 5, 0x30, 0x10, 4, 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, 25, 3, 0x50, 0x10, 21, 1), + PIN_FIELD_BASE(26, 26, 3, 0x50, 0x10, 22, 1), + PIN_FIELD_BASE(27, 27, 3, 0x50, 0x10, 18, 1), + PIN_FIELD_BASE(28, 28, 3, 0x50, 0x10, 25, 1), + PIN_FIELD_BASE(29, 29, 3, 0x50, 0x10, 26, 1), + PIN_FIELD_BASE(30, 30, 3, 0x50, 0x10, 27, 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, 35, 3, 0x50, 0x10, 29, 1), + PIN_FIELD_BASE(36, 36, 3, 0x50, 0x10, 30, 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, 40, 3, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(41, 41, 3, 0x50, 0x10, 1, 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, 51, 3, 0x50, 0x10, 12, 1), + PIN_FIELD_BASE(52, 52, 3, 0x50, 0x10, 13, 1), + PIN_FIELD_BASE(53, 53, 3, 0x50, 0x10, 14, 1), + PIN_FIELD_BASE(54, 54, 3, 0x50, 0x10, 16, 1), + + PIN_FIELD_BASE(55, 55, 1, 0x40, 0x10, 14, 1), + PIN_FIELD_BASE(56, 56, 1, 0x40, 0x10, 15, 1), + PIN_FIELD_BASE(57, 57, 1, 0x40, 0x10, 13, 1), + PIN_FIELD_BASE(58, 58, 1, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(59, 59, 1, 0x40, 0x10, 5, 1), + PIN_FIELD_BASE(60, 60, 1, 0x40, 0x10, 6, 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, 64, 1, 0x40, 0x10, 8, 1), + PIN_FIELD_BASE(65, 65, 1, 0x40, 0x10, 9, 1), + PIN_FIELD_BASE(66, 66, 1, 0x40, 0x10, 10, 1), + PIN_FIELD_BASE(67, 67, 1, 0x40, 0x10, 11, 1), + PIN_FIELD_BASE(68, 68, 1, 0x40, 0x10, 12, 1), + + PIN_FIELD_BASE(69, 69, 5, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, 5, 0x30, 0x10, 2, 1), + PIN_FIELD_BASE(71, 71, 5, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0x30, 0x10, 6, 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, 80, 1, 0x40, 0x10, 18, 1), + PIN_FIELD_BASE(81, 81, 1, 0x40, 0x10, 19, 1), + PIN_FIELD_BASE(82, 82, 1, 0x40, 0x10, 16, 1), + PIN_FIELD_BASE(83, 83, 1, 0x40, 0x10, 17, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_smt_range[] = { + PIN_FIELD_BASE(0, 0, 5, 0xc0, 0x10, 13, 1), + PIN_FIELD_BASE(1, 1, 5, 0xc0, 0x10, 14, 1), + PIN_FIELD_BASE(2, 2, 5, 0xc0, 0x10, 11, 1), + PIN_FIELD_BASE(3, 3, 5, 0xc0, 0x10, 12, 1), + PIN_FIELD_BASE(4, 4, 5, 0xc0, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, 5, 0xc0, 0x10, 9, 1), + PIN_FIELD_BASE(6, 6, 5, 0xc0, 0x10, 10, 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, 13, 1, 0xe0, 0x10, 1, 1), + PIN_FIELD_BASE(14, 14, 1, 0xe0, 0x10, 2, 1), + + PIN_FIELD_BASE(15, 15, 5, 0xc0, 0x10, 7, 1), + PIN_FIELD_BASE(16, 16, 5, 0xc0, 0x10, 8, 1), + PIN_FIELD_BASE(17, 17, 5, 0xc0, 0x10, 3, 1), + PIN_FIELD_BASE(18, 18, 5, 0xc0, 0x10, 4, 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, 25, 3, 0x140, 0x10, 21, 1), + PIN_FIELD_BASE(26, 26, 3, 0x140, 0x10, 22, 1), + PIN_FIELD_BASE(27, 27, 3, 0x140, 0x10, 18, 1), + PIN_FIELD_BASE(28, 28, 3, 0x140, 0x10, 25, 1), + PIN_FIELD_BASE(29, 29, 3, 0x140, 0x10, 26, 1), + PIN_FIELD_BASE(30, 30, 3, 0x140, 0x10, 27, 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, 35, 3, 0x140, 0x10, 29, 1), + PIN_FIELD_BASE(36, 36, 3, 0x140, 0x10, 30, 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, 40, 3, 0x140, 0x10, 0, 1), + PIN_FIELD_BASE(41, 41, 3, 0x140, 0x10, 1, 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, 51, 3, 0x140, 0x10, 12, 1), + PIN_FIELD_BASE(52, 52, 3, 0x140, 0x10, 13, 1), + PIN_FIELD_BASE(53, 53, 3, 0x140, 0x10, 14, 1), + PIN_FIELD_BASE(54, 54, 3, 0x140, 0x10, 16, 1), + + PIN_FIELD_BASE(55, 55, 1, 0xe0, 0x10, 14, 1), + PIN_FIELD_BASE(56, 56, 1, 0xe0, 0x10, 15, 1), + PIN_FIELD_BASE(57, 57, 1, 0xe0, 0x10, 13, 1), + PIN_FIELD_BASE(58, 58, 1, 0xe0, 0x10, 4, 1), + PIN_FIELD_BASE(59, 59, 1, 0xe0, 0x10, 5, 1), + PIN_FIELD_BASE(60, 60, 1, 0xe0, 0x10, 6, 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, 64, 1, 0xe0, 0x10, 8, 1), + PIN_FIELD_BASE(65, 65, 1, 0xe0, 0x10, 9, 1), + PIN_FIELD_BASE(66, 66, 1, 0xe0, 0x10, 10, 1), + PIN_FIELD_BASE(67, 67, 1, 0xe0, 0x10, 11, 1), + PIN_FIELD_BASE(68, 68, 1, 0xe0, 0x10, 12, 1), + + PIN_FIELD_BASE(69, 69, 5, 0xc0, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, 5, 0xc0, 0x10, 2, 1), + PIN_FIELD_BASE(71, 71, 5, 0xc0, 0x10, 5, 1), + PIN_FIELD_BASE(72, 72, 5, 0xc0, 0x10, 6, 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, 80, 1, 0xe0, 0x10, 18, 1), + PIN_FIELD_BASE(81, 81, 1, 0xe0, 0x10, 19, 1), + PIN_FIELD_BASE(82, 82, 1, 0xe0, 0x10, 16, 1), + PIN_FIELD_BASE(83, 83, 1, 0xe0, 0x10, 17, 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, 13, 1, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(14, 14, 1, 0x70, 0x10, 1, 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, 13, 1, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(14, 14, 1, 0x50, 0x10, 1, 1), + + PIN_FIELD_BASE(15, 15, 5, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(16, 16, 5, 0x40, 0x10, 5, 1), + PIN_FIELD_BASE(17, 17, 5, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(18, 18, 5, 0x40, 0x10, 1, 1), + + PIN_FIELD_BASE(63, 63, 1, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(71, 71, 5, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(72, 72, 5, 0x40, 0x10, 3, 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, 0, 5, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(1, 1, 5, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(3, 3, 5, 0x00, 0x10, 18, 3), + PIN_FIELD_BASE(4, 4, 5, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(5, 5, 5, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(6, 6, 5, 0x00, 0x10, 12, 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, 13, 1, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(14, 14, 1, 0x00, 0x10, 6, 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, 25, 3, 0x20, 0x10, 3, 3), + PIN_FIELD_BASE(26, 26, 3, 0x20, 0x10, 6, 3), + PIN_FIELD_BASE(27, 27, 3, 0x10, 0x10, 24, 3), + PIN_FIELD_BASE(28, 28, 3, 0x20, 0x10, 15, 3), + PIN_FIELD_BASE(29, 29, 3, 0x20, 0x10, 18, 3), + PIN_FIELD_BASE(30, 30, 3, 0x20, 0x10, 21, 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, 40, 3, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(41, 41, 3, 0x00, 0x10, 3, 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, 51, 3, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(52, 52, 3, 0x10, 0x10, 9, 3), + PIN_FIELD_BASE(53, 53, 3, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(54, 54, 3, 0x10, 0x10, 18, 3), + + PIN_FIELD_BASE(55, 55, 1, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(56, 56, 1, 0x10, 0x10, 15, 3), + PIN_FIELD_BASE(57, 57, 1, 0x10, 0x10, 9, 3), + PIN_FIELD_BASE(58, 58, 1, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(59, 59, 1, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(60, 60, 1, 0x00, 0x10, 18, 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, 64, 1, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(65, 65, 1, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(66, 66, 1, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(67, 67, 1, 0x10, 0x10, 3, 3), + PIN_FIELD_BASE(68, 68, 1, 0x10, 0x10, 6, 3), + + PIN_FIELD_BASE(69, 69, 5, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(70, 70, 5, 0x00, 0x10, 6, 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, 80, 1, 0x10, 0x10, 24, 3), + PIN_FIELD_BASE(81, 81, 1, 0x10, 0x10, 27, 3), + PIN_FIELD_BASE(82, 82, 1, 0x10, 0x10, 18, 3), + PIN_FIELD_BASE(83, 83, 1, 0x10, 0x10, 21, 3), +}; + +static const struct mtk_pin_field_calc mt7988_pin_pupd_range[] = { + PIN_FIELD_BASE(0, 0, 5, 0x50, 0x10, 7, 1), + PIN_FIELD_BASE(1, 1, 5, 0x50, 0x10, 8, 1), + PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 5, 1), + PIN_FIELD_BASE(3, 3, 5, 0x50, 0x10, 6, 1), + PIN_FIELD_BASE(4, 4, 5, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, 5, 0x50, 0x10, 3, 1), + PIN_FIELD_BASE(6, 6, 5, 0x50, 0x10, 4, 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, 25, 3, 0x70, 0x10, 21, 1), + PIN_FIELD_BASE(26, 26, 3, 0x70, 0x10, 22, 1), + PIN_FIELD_BASE(27, 27, 3, 0x70, 0x10, 18, 1), + PIN_FIELD_BASE(28, 28, 3, 0x70, 0x10, 25, 1), + PIN_FIELD_BASE(29, 29, 3, 0x70, 0x10, 26, 1), + PIN_FIELD_BASE(30, 30, 3, 0x70, 0x10, 27, 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, 35, 3, 0x70, 0x10, 29, 1), + PIN_FIELD_BASE(36, 36, 3, 0x70, 0x10, 30, 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, 40, 3, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(41, 41, 3, 0x70, 0x10, 1, 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, 51, 3, 0x70, 0x10, 12, 1), + PIN_FIELD_BASE(52, 52, 3, 0x70, 0x10, 13, 1), + PIN_FIELD_BASE(53, 53, 3, 0x70, 0x10, 14, 1), + PIN_FIELD_BASE(54, 54, 3, 0x70, 0x10, 16, 1), + + PIN_FIELD_BASE(55, 55, 1, 0x60, 0x10, 12, 1), + PIN_FIELD_BASE(56, 56, 1, 0x60, 0x10, 13, 1), + PIN_FIELD_BASE(57, 57, 1, 0x60, 0x10, 11, 1), + PIN_FIELD_BASE(58, 58, 1, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(59, 59, 1, 0x60, 0x10, 3, 1), + PIN_FIELD_BASE(60, 60, 1, 0x60, 0x10, 4, 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, 64, 1, 0x60, 0x10, 6, 1), + PIN_FIELD_BASE(65, 65, 1, 0x60, 0x10, 7, 1), + PIN_FIELD_BASE(66, 66, 1, 0x60, 0x10, 8, 1), + PIN_FIELD_BASE(67, 67, 1, 0x60, 0x10, 9, 1), + PIN_FIELD_BASE(68, 68, 1, 0x60, 0x10, 10, 1), + + PIN_FIELD_BASE(69, 69, 5, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, 5, 0x50, 0x10, 2, 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, 80, 1, 0x60, 0x10, 16, 1), + PIN_FIELD_BASE(81, 81, 1, 0x60, 0x10, 17, 1), + PIN_FIELD_BASE(82, 82, 1, 0x60, 0x10, 14, 1), + PIN_FIELD_BASE(83, 83, 1, 0x60, 0x10, 15, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_r0_range[] = { + PIN_FIELD_BASE(0, 0, 5, 0x60, 0x10, 7, 1), + PIN_FIELD_BASE(1, 1, 5, 0x60, 0x10, 8, 1), + PIN_FIELD_BASE(2, 2, 5, 0x60, 0x10, 5, 1), + PIN_FIELD_BASE(3, 3, 5, 0x60, 0x10, 6, 1), + PIN_FIELD_BASE(4, 4, 5, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, 5, 0x60, 0x10, 3, 1), + PIN_FIELD_BASE(6, 6, 5, 0x60, 0x10, 4, 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, 25, 3, 0x90, 0x10, 21, 1), + PIN_FIELD_BASE(26, 26, 3, 0x90, 0x10, 22, 1), + PIN_FIELD_BASE(27, 27, 3, 0x90, 0x10, 18, 1), + PIN_FIELD_BASE(28, 28, 3, 0x90, 0x10, 25, 1), + PIN_FIELD_BASE(29, 29, 3, 0x90, 0x10, 26, 1), + PIN_FIELD_BASE(30, 30, 3, 0x90, 0x10, 27, 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, 35, 3, 0x90, 0x10, 29, 1), + PIN_FIELD_BASE(36, 36, 3, 0x90, 0x10, 30, 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, 40, 3, 0x90, 0x10, 0, 1), + PIN_FIELD_BASE(41, 41, 3, 0x90, 0x10, 1, 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, 51, 3, 0x90, 0x10, 12, 1), + PIN_FIELD_BASE(52, 52, 3, 0x90, 0x10, 13, 1), + PIN_FIELD_BASE(53, 53, 3, 0x90, 0x10, 14, 1), + PIN_FIELD_BASE(54, 54, 3, 0x90, 0x10, 16, 1), + + PIN_FIELD_BASE(55, 55, 1, 0x80, 0x10, 12, 1), + PIN_FIELD_BASE(56, 56, 1, 0x80, 0x10, 13, 1), + PIN_FIELD_BASE(57, 57, 1, 0x80, 0x10, 11, 1), + PIN_FIELD_BASE(58, 58, 1, 0x80, 0x10, 2, 1), + PIN_FIELD_BASE(59, 59, 1, 0x80, 0x10, 3, 1), + PIN_FIELD_BASE(60, 60, 1, 0x80, 0x10, 4, 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, 64, 1, 0x80, 0x10, 6, 1), + PIN_FIELD_BASE(65, 65, 1, 0x80, 0x10, 7, 1), + PIN_FIELD_BASE(66, 66, 1, 0x80, 0x10, 8, 1), + PIN_FIELD_BASE(67, 67, 1, 0x80, 0x10, 9, 1), + PIN_FIELD_BASE(68, 68, 1, 0x80, 0x10, 10, 1), + + PIN_FIELD_BASE(69, 69, 5, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, 5, 0x60, 0x10, 2, 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, 80, 1, 0x80, 0x10, 16, 1), + PIN_FIELD_BASE(81, 81, 1, 0x80, 0x10, 17, 1), + PIN_FIELD_BASE(82, 82, 1, 0x80, 0x10, 14, 1), + PIN_FIELD_BASE(83, 83, 1, 0x80, 0x10, 15, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_r1_range[] = { + PIN_FIELD_BASE(0, 0, 5, 0x70, 0x10, 7, 1), + PIN_FIELD_BASE(1, 1, 5, 0x70, 0x10, 8, 1), + PIN_FIELD_BASE(2, 2, 5, 0x70, 0x10, 5, 1), + PIN_FIELD_BASE(3, 3, 5, 0x70, 0x10, 6, 1), + PIN_FIELD_BASE(4, 4, 5, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, 5, 0x70, 0x10, 3, 1), + PIN_FIELD_BASE(6, 6, 5, 0x70, 0x10, 4, 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, 25, 3, 0xb0, 0x10, 21, 1), + PIN_FIELD_BASE(26, 26, 3, 0xb0, 0x10, 22, 1), + PIN_FIELD_BASE(27, 27, 3, 0xb0, 0x10, 18, 1), + PIN_FIELD_BASE(28, 28, 3, 0xb0, 0x10, 25, 1), + PIN_FIELD_BASE(29, 29, 3, 0xb0, 0x10, 26, 1), + PIN_FIELD_BASE(30, 30, 3, 0xb0, 0x10, 27, 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, 35, 3, 0xb0, 0x10, 29, 1), + PIN_FIELD_BASE(36, 36, 3, 0xb0, 0x10, 30, 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, 40, 3, 0xb0, 0x10, 0, 1), + PIN_FIELD_BASE(41, 41, 3, 0xb0, 0x10, 1, 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, 51, 3, 0xb0, 0x10, 12, 1), + PIN_FIELD_BASE(52, 52, 3, 0xb0, 0x10, 13, 1), + PIN_FIELD_BASE(53, 53, 3, 0xb0, 0x10, 14, 1), + PIN_FIELD_BASE(54, 54, 3, 0xb0, 0x10, 16, 1), + + PIN_FIELD_BASE(55, 55, 1, 0x90, 0x10, 12, 1), + PIN_FIELD_BASE(56, 56, 1, 0x90, 0x10, 13, 1), + PIN_FIELD_BASE(57, 57, 1, 0x90, 0x10, 11, 1), + PIN_FIELD_BASE(58, 58, 1, 0x90, 0x10, 2, 1), + PIN_FIELD_BASE(59, 59, 1, 0x90, 0x10, 3, 1), + PIN_FIELD_BASE(60, 60, 1, 0x90, 0x10, 4, 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, 64, 1, 0x90, 0x10, 6, 1), + PIN_FIELD_BASE(65, 65, 1, 0x90, 0x10, 7, 1), + PIN_FIELD_BASE(66, 66, 1, 0x90, 0x10, 8, 1), + PIN_FIELD_BASE(67, 67, 1, 0x90, 0x10, 9, 1), + PIN_FIELD_BASE(68, 68, 1, 0x90, 0x10, 10, 1), + + PIN_FIELD_BASE(69, 69, 5, 0x70, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, 5, 0x70, 0x10, 2, 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, 80, 1, 0x90, 0x10, 16, 1), + PIN_FIELD_BASE(81, 81, 1, 0x90, 0x10, 17, 1), + PIN_FIELD_BASE(82, 82, 1, 0x90, 0x10, 14, 1), + PIN_FIELD_BASE(83, 83, 1, 0x90, 0x10, 15, 1), +}; + +static const unsigned int mt7988_pull_type[] = { + MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ + MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ + MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ + MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PU_PD_TYPE, /*7*/ + MTK_PULL_PU_PD_TYPE, /*8*/ MTK_PULL_PU_PD_TYPE, /*9*/ + MTK_PULL_PU_PD_TYPE, /*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ + MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PU_PD_TYPE, /*13*/ + MTK_PULL_PU_PD_TYPE, /*14*/ MTK_PULL_PD_TYPE, /*15*/ + MTK_PULL_PD_TYPE, /*16*/ MTK_PULL_PD_TYPE, /*17*/ + MTK_PULL_PD_TYPE, /*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ + MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ + MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ + MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ + MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ + MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ + MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ + MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ + MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ + MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ + MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ + MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ + MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ + MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ + MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ + MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ + MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ + MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ + MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ + MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ + MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ + MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ + MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PU_PD_TYPE, /*63*/ + MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ + MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ + MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PUPD_R1R0_TYPE,/*69*/ + MTK_PULL_PUPD_R1R0_TYPE,/*70*/ MTK_PULL_PD_TYPE, /*71*/ + MTK_PULL_PD_TYPE, /*72*/ MTK_PULL_PUPD_R1R0_TYPE,/*73*/ + MTK_PULL_PUPD_R1R0_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE, /*75*/ + MTK_PULL_PU_PD_TYPE, /*76*/ MTK_PULL_PU_PD_TYPE, /*77*/ + MTK_PULL_PU_PD_TYPE, /*78*/ MTK_PULL_PU_PD_TYPE, /*79*/ + MTK_PULL_PUPD_R1R0_TYPE,/*80*/ MTK_PULL_PUPD_R1R0_TYPE,/*81*/ + MTK_PULL_PUPD_R1R0_TYPE,/*82*/ MTK_PULL_PUPD_R1R0_TYPE,/*83*/ +}; + +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_uart1_2_lite_pins[] = { 80, 81 }; +static int mt7988_uart1_2_lite_funcs[] = { 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,81) uart1_2_lite */ + PINCTRL_PIN_GROUP("uart1_2_lite", mt7988_uart1_2_lite), + /* @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 * const mt7988_jtag_groups[] = { + "tops_jtag0_0", "wo0_jtag", "wo1_jtag", + "wo2_jtag", "jtag", "tops_jtag0_1", +}; +static const char * const mt7988_int_usxgmii_groups[] = { + "int_usxgmii", +}; +static const char * const mt7988_pwm_groups[] = { + "pwm0", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7" +}; +static const char * const mt7988_dfd_groups[] = { + "dfd", +}; +static const char * const 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 * const mt7988_ethernet_groups[] = { + "mdc_mdio0", + "2p5g_ext_mdio", + "gbe_ext_mdio", + "mdc_mdio1", +}; +static const char * const 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 * const mt7988_pmic_groups[] = { + "pmic", +}; +static const char * const mt7988_wdt_groups[] = { + "watchdog", +}; +static const char * const mt7988_spi_groups[] = { + "spi0", "spi0_wp_hold", "spi1", "spi2", "spi2_wp_hold", +}; +static const char * const mt7988_flash_groups[] = { "emmc_45", "sdcard", "snfi", + "emmc_51" }; +static const char * const 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", + "uart1_2_lite", + "tops_uart1_2", + "net_wo0_uart_txd_1", + "net_wo1_uart_txd_1", + "net_wo2_uart_txd_1", +}; +static const char * const mt7988_udi_groups[] = { + "udi", +}; +static const char * const mt7988_audio_groups[] = { + "i2s", "pcm", +}; +static const char * const 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 * const 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 * const 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, + .pull_type = mt7988_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .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); From 95d3d353f84c01d20c32d0811b2159da72a11a10 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 01:56:57 +0000 Subject: [PATCH 077/108] mediatek: copy patches-6.1 to patches-6.6 Copy patches from patches-6.1 to patches-6.6. No changes. Signed-off-by: Daniel Golle --- ...-overlays-to-built-from-.dtso-named-.patch | 44 + ...ek-mt7986-add-support-for-RX-Wireles.patch | 106 + ...s-mt7986-harmonize-device-node-order.patch | 166 ++ ...7986-add-crypto-related-device-nodes.patch | 68 + ...4-v6.2-arm64-dts-mt7986-add-i2c-node.patch | 37 + ...s-mediatek-mt7986-Add-SoC-compatible.patch | 61 + ...-mt7986-add-spi-related-device-nodes.patch | 157 + ...-mt7986-add-usb-related-device-nodes.patch | 127 + ...-mt7986-add-mmc-related-device-nodes.patch | 160 + ...mt7986-add-pcie-related-device-nodes.patch | 118 + ...6.3-arm64-dts-mt7986-add-Bananapi-R3.patch | 689 +++++ ...ropagate-chassis-type-where-possible.patch | 323 ++ .../012-v6.5-arm64-dts-mt7986-add-PWM.patch | 38 + ...5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch | 43 + ...-set-Wifi-Leds-low-active-for-BPI-R3.patch | 27 + ...-use-size-of-reserved-partition-for-.patch | 46 + ...m64-dts-mt7986-add-thermal-and-efuse.patch | 80 + ...5-arm64-dts-mt7986-add-thermal-zones.patch | 51 + ...-add-pwm-fan-and-cooling-maps-to-BPI.patch | 64 + ...-increase-bl2-partition-on-NAND-of-B.patch | 41 + ...-define-3W-max-power-to-both-SFP-on-.patch | 34 + ...rm64-dts-mt7986-change-cooling-trips.patch | 59 + ...t7986-change-thermal-trips-on-BPI-R3.patch | 38 + .../041-block-fit-partition-parser.patch | 216 ++ .../100-dts-update-mt7622-rfb1.patch | 107 + .../101-dts-update-mt7629-rfb.patch | 60 + .../103-mt7623-enable-arch-timer.patch | 20 + .../patches-6.6/104-mt7622-add-snor-irq.patch | 10 + .../105-dts-mt7622-enable-pstore.patch | 16 + .../106-dts-mt7622-disable_btif.patch | 26 + .../110-dts-fix-bpi2-console.patch | 10 + .../111-dts-fix-bpi64-console.patch | 11 + .../112-dts-fix-bpi64-lan-names.patch | 37 + .../113-dts-fix-bpi64-leds-and-buttons.patch | 49 + .../114-dts-bpi64-disable-rtc.patch | 21 + ...-declare-SPI-NAND-present-on-BPI-R64.patch | 70 + .../121-hack-spi-nand-1b-bbm.patch | 20 + .../130-dts-mt7629-add-snand-support.patch | 94 + .../131-dts-mt7622-add-snand-support.patch | 68 + ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 18 + ...s-mt7623-eip97-inside-secure-support.patch | 24 + .../160-dts-mt7623-bpi-r2-earlycon.patch | 11 + ...1-dts-mt7623-bpi-r2-mmc-device-order.patch | 11 + .../162-dts-mt7623-bpi-r2-led-aliases.patch | 29 + ...163-dts-mt7623-bpi-r2-ethernet-alias.patch | 10 + ...ts-mt7623-bpi-r2-rootdisk-for-fitblk.patch | 55 + ...-handle-interrupts-from-MT7531-switc.patch | 32 + ...-dts-mediatek-mt7622-fix-GICv2-range.patch | 106 + .../193-dts-mt7623-thermal_zone_fix.patch | 48 + .../194-dts-mt7968a-add-ramoops.patch | 17 + ...i-r3-leds-port-names-and-wifi-eeprom.patch | 196 ++ ...7986a-bpi-r3-use-all-ubi-nand-layout.patch | 131 + ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 66 + ...llow-configuring-uart-rx-tx-and-rts-.patch | 88 + ...-add-pull_type-attribute-for-mediate.patch | 100 + ....3-pinctrl-add-mt7981-pinctrl-driver.patch | 1094 +++++++ ...-add-missing-options-to-PINCTRL_MT79.patch | 30 + ...diatek-fix-pull_type-data-for-MT7981.patch | 76 + ...ek-mt7981-add-additional-uart-groups.patch | 65 + ...-assign-functions-to-configure-pin-b.patch | 41 + ...-gate-Propagate-struct-device-with-m.patch | 536 ++++ ...mux-Propagate-struct-device-where-po.patch | 140 + ...-mtk-Propagate-struct-device-for-com.patch | 181 ++ ...-mux-Propagate-struct-device-for-mtk.patch | 103 + ...mediatek-clk-mtk-Add-dummy-clock-ops.patch | 74 + ...tch-to-mtk_clk_simple_probe-where-po.patch | 790 +++++ ...-clk-mtk-Extend-mtk_clk_simple_probe.patch | 189 ++ ...-mt7986-topckgen-Properly-keep-some-.patch | 97 + ...-mt7986-topckgen-Migrate-to-mtk_clk_.patch | 88 + ...986-apmixed-Use-PLL_AO-flag-to-set-c.patch | 38 + ...-clock-mediatek-add-mt7981-clock-IDs.patch | 237 ++ ...lk-mediatek-add-MT7981-clock-support.patch | 932 ++++++ ...981-topckgen-flag-SGM_REG_SEL-as-cri.patch | 30 + ...-mediatek-add-support-for-MT7988-SoC.patch | 26 + ...ngs-clock-Add-compatibles-for-MT7981.patch | 75 + ...mediatek-sgmiisys-Convert-to-DT-sche.patch | 107 + ...pcs-mediatek-sgmiisys-add-MT7981-SoC.patch | 37 + ...mediatek-move-ethsys-controller-conv.patch | 113 + ...t-mediatek-add-MT7988-ethwarp-reset-.patch | 35 + ...-clock-mediatek-add-MT7988-clock-IDs.patch | 302 ++ ...k-mediatek-add-clock-controllers-of-.patch | 260 ++ ...-pcw_chg_bit-control-for-PLLs-of-MT7.patch | 50 + ...-mediatek-add-drivers-for-MT7988-SoC.patch | 1026 +++++++ ...-infracfg-reset-controller-for-mt798.patch | 57 + ...-reset-mediatek-add-MT7988-reset-IDs.patch | 25 + ...hdog-mediatek-mt7988-add-wdt-support.patch | 125 + ...988-infracfg-fix-clocks-for-2nd-PCIe.patch | 31 + ...-mediatek-add-support-for-MT7986-SoC.patch | 47 + ...d-Inline-Crypto-Engine-clock-control.patch | 57 + ...fix-two-spelling-mistakes-in-comment.patch | 36 + ...d-open-coding-by-using-mmc_op_tuning.patch | 39 + .../330-snand-mtk-bmt-support.patch | 34 + .../331-mt7622-rfb1-enable-bmt.patch | 10 + ...Add-support-for-the-Fidelix-FM35X1GA.patch | 122 + ...freq-mediatek-Add-support-for-MT7988.patch | 41 + ...nctrl-add-mt7988-pd-pulltype-support.patch | 99 + ...ypto-add-eip97-inside-secure-support.patch | 27 + ...01-crypto-fix-eip97-cache-incoherent.patch | 26 + ...405-v6.2-mt7986-trng-add-rng-support.patch | 43 + .../patches-6.6/410-bt-mtk-serial-fix.patch | 33 + ...xx-Move-chip_config-to-driver-s-priv.patch | 130 + ...-Add-support-for-dynamic-calibration.patch | 236 ++ ...ers-spi-mem-Add-spi-calibration-hook.patch | 41 + ...xx-Add-controller-s-calibration-para.patch | 43 + ...and-Add-calibration-support-for-spin.patch | 81 + ...nor-Add-calibration-support-for-spi-.patch | 57 + .../500-gsw-rtl8367s-mt7622-support.patch | 25 + ...ert-PERST-for-100ms-for-power-and-cl.patch | 34 + ...s-mediatek-add-mt7622-pcie-slot-node.patch | 28 + ...diatek-fix-clearing-interrupt-status.patch | 23 + ...1-pcie-mediatek-gen3-PERST-for-100ms.patch | 17 + ...xsphy-support-type-switch-by-pericfg.patch | 167 ++ ...ediatek-add-support-for-coherent-DMA.patch | 82 + .../721-dts-mt7622-mediatek-fix-300mhz.patch | 27 + .../722-remove-300Hz-to-prevent-freeze.patch | 25 + ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 1204 ++++++++ ...phy-mediatek-ge-soc-support-PHY-LEDs.patch | 524 ++++ ...-don-t-use-SGMII-AN-if-using-phylink.patch | 63 + ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 39 + ...-ge-soc-sync-driver-with-MediaTek-SD.patch | 270 ++ .../804-v6.2-pwm-add-mt7986-support.patch | 23 + ...-extend-pinctrl-moore-to-support-new.patch | 129 + ...mtk_thermal-Fix-kernel-doc-function-.patch | 37 + ...mtk_thermal-Use-devm_platform_get_an.patch | 37 + ...mtk-Use-function-pointer-for-raw_to_.patch | 60 + ...mtk-Add-support-for-MT7986-and-MT798.patch | 236 ++ ...mediatek-Relocate-driver-to-mediatek.patch | 2602 +++++++++++++++++ ...mediatek-Add-the-Low-Voltage-Thermal.patch | 1298 ++++++++ ...mal-mediatek-Add-LVTS-thermal-contro.patch | 186 ++ ...mal-mediatek-Add-AP-domain-to-LVTS-t.patch | 35 + ...-Add-a-thermal-zone-devdata-accessor.patch | 65 + ...-thermal_zone_device-structure-type-.patch | 55 + ...-the-thermal-zone-devdata-accessor-i.patch | 74 + ...e-the-right-device-for-devm_thermal_.patch | 201 ++ ...e-device-internal-thermal-zone-struc.patch | 79 + ...se-thermal_zone_device_type-accessor.patch | 62 + ...mediatek-Control-buffer-enablement-t.patch | 81 + ...-mediatek-Add-support-for-MT8365-SoC.patch | 123 + ...mediatek-Add-delay-after-thermal-ban.patch | 50 + ...mediatek-lvts_thermal-Fix-sensor-1-i.patch | 46 + ...mediatek-lvts_thermal-Add-AP-domain-.patch | 149 + ...rivers-mediatek-Add-delay-after-ther.patch | 53 + ...mediatek-Add-temperature-constraints.patch | 78 + ...mediatek-Use-devm_of_iomap-to-avoid-.patch | 53 + ...mediatek-Change-clk_prepare_enable-t.patch | 100 + ...-mediatek-Use-of_address_to_resource.patch | 36 + ...rivers-mediatek-Use-devm_of_iomap-to.patch | 57 + ...mediatek-lvts_thermal-Register-therm.patch | 37 + ...mediatek-lvts_thermal-Remove-redunda.patch | 28 + ...mediatek-lvts_thermal-Handle-IRQ-on-.patch | 40 + ...mediatek-lvts_thermal-Honor-sensors-.patch | 120 + ...mediatek-lvts_thermal-Use-offset-thr.patch | 77 + ...mediatek-lvts_thermal-Disable-undesi.patch | 51 + ...mediatek-lvts_thermal-Don-t-leave-th.patch | 70 + ...mediatek-lvts_thermal-Manage-thresho.patch | 156 + ...mediatek-lvts-Fix-parameter-check-in.patch | 29 + ...mediatek-Clean-up-redundant-dev_err_.patch | 33 + ...mediatek-lvts_thermal-Make-readings-.patch | 95 + ...mediatek-auxadc_thermal-Removed-call.patch | 30 + ...vert-to-platform-remove-callback-ret.patch | 58 + ...mediatek-lvts_thermal-Make-coeff-con.patch | 198 ++ ...mal-mediatek-Add-LVTS-thermal-sensor.patch | 35 + ...mediatek-lvts_thermal-Add-mt7988-sup.patch | 91 + ...mediatek-lvts_thermal-Fix-error-chec.patch | 30 + ...rs-mediatek-Fix-probe-for-THERMAL_V2.patch | 33 + ...mediatek-lvts_thermal-Add-suspend-an.patch | 83 + ...mal-mediatek-Add-LVTS-thermal-contro.patch | 49 + ...mediatek-lvts_thermal-Add-mt8192-sup.patch | 151 + ...mediatek-lvts_thermal-Update-calibra.patch | 70 + ...-control-buffer-enablement-on-MT7896.patch | 59 + ...v6.2-i2c-mediatek-add-mt7986-support.patch | 44 + ...evm_platform_get_and_ioremap_resourc.patch | 42 + ...t65xx-drop-of_match_ptr-for-ID-table.patch | 33 + ...-mediatek-add-support-for-MT7981-SoC.patch | 47 + ...i2c-mt65xx-allow-optional-pmic-clock.patch | 45 + ...oC-mediatek-mt7986-add-common-header.patch | 269 ++ ...7986-support-etdm-in-platform-driver.patch | 430 +++ ...-mediatek-mt7986-add-platform-driver.patch | 685 +++++ ...t7986-add-machine-driver-with-wm8960.patch | 243 ++ ...-mediatek-mt7986-wm8960-add-mt7986-w.patch | 87 + ...-mediatek-mt7986-afe-add-audio-afe-d.patch | 180 ++ ...7986-drop-the-remove-callback-of-mt7.patch | 42 + ...7986-remove-the-mt7986_wm8960_priv-s.patch | 105 + ...iatek-mt7986-add-sample-rate-checker.patch | 49 + ...7986-silence-error-in-case-of-EPROBE.patch | 26 + .../862-arm64-dts-mt7986-add-afe.patch | 40 + ...63-arm64-dts-mt7986-add-sound-wm8960.patch | 61 + ...-mt7986-add-sound-overlay-for-bpi-r3.patch | 75 + ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 65 + .../901-arm-add-cmdline-override.patch | 54 + .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 31 + .../911-dts-mt7622-bpi-r64-add-rootdisk.patch | 103 + .../930-spi-mt65xx-enable-sel-clk.patch | 18 + ..._wed-rename-mtk_wed_get_memory_regio.patch | 37 + ...986-move-cpuboot-in-a-dedicated-node.patch | 66 + ..._wed-move-cpuboot-in-a-dedicated-dts.patch | 81 + ...tk_wed-move-ilm-a-dedicated-dts-node.patch | 86 + ...tk_wed-move-dlm-a-dedicated-dts-node.patch | 57 + ...-mt7986-move-ilm-in-a-dedicated-node.patch | 83 + ...-mt7986-move-dlm-in-a-dedicated-node.patch | 81 + .../950-smartrg-i2c-led-driver.patch | 34 + ...iatek-split-tx-and-rx-fields-in-mtk_.patch | 599 ++++ ...iatek-use-QDMA-instead-of-ADMAv2-on-.patch | 123 + ...ernet-mtk_eth_soc-fix-WED-wifi-reset.patch | 49 + 204 files changed, 26792 insertions(+) create mode 100644 target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch create mode 100644 target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch create mode 100644 target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch create mode 100644 target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch create mode 100644 target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch create mode 100644 target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch create mode 100644 target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch create mode 100644 target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch create mode 100644 target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch create mode 100644 target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch create mode 100644 target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch create mode 100644 target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch create mode 100644 target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch create mode 100644 target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch create mode 100644 target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch create mode 100644 target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch create mode 100644 target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch create mode 100644 target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch create mode 100644 target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch create mode 100644 target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch create mode 100644 target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch create mode 100644 target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch create mode 100644 target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch create mode 100644 target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch create mode 100644 target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch create mode 100644 target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch create mode 100644 target/linux/mediatek/patches-6.6/103-mt7623-enable-arch-timer.patch create mode 100644 target/linux/mediatek/patches-6.6/104-mt7622-add-snor-irq.patch create mode 100644 target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch create mode 100644 target/linux/mediatek/patches-6.6/106-dts-mt7622-disable_btif.patch create mode 100644 target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch create mode 100644 target/linux/mediatek/patches-6.6/111-dts-fix-bpi64-console.patch create mode 100644 target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch create mode 100644 target/linux/mediatek/patches-6.6/113-dts-fix-bpi64-leds-and-buttons.patch create mode 100644 target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch create mode 100644 target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch create mode 100644 target/linux/mediatek/patches-6.6/121-hack-spi-nand-1b-bbm.patch create mode 100644 target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch create mode 100644 target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch create mode 100644 target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch create mode 100644 target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch create mode 100644 target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch create mode 100644 target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch create mode 100644 target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch create mode 100644 target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch create mode 100644 target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch create mode 100644 target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch create mode 100644 target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch create mode 100644 target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch create mode 100644 target/linux/mediatek/patches-6.6/194-dts-mt7968a-add-ramoops.patch create mode 100644 target/linux/mediatek/patches-6.6/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch create mode 100644 target/linux/mediatek/patches-6.6/196-dts-mt7986a-bpi-r3-use-all-ubi-nand-layout.patch create mode 100644 target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch create mode 100644 target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch create mode 100644 target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch create mode 100644 target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch create mode 100644 target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch create mode 100644 target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch create mode 100644 target/linux/mediatek/patches-6.6/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch create mode 100644 target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch create mode 100644 target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch create mode 100644 target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch create mode 100644 target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch create mode 100644 target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch create mode 100644 target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch create mode 100644 target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch create mode 100644 target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch create mode 100644 target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch create mode 100644 target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch create mode 100644 target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch create mode 100644 target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch create mode 100644 target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch create mode 100644 target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch create mode 100644 target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch create mode 100644 target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch create mode 100644 target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/244-v6.8-dt-bindings-arm-mediatek-move-ethsys-controller-conv.patch create mode 100644 target/linux/mediatek/patches-6.6/245-v6.8-dt-bindings-reset-mediatek-add-MT7988-ethwarp-reset-.patch create mode 100644 target/linux/mediatek/patches-6.6/246-v6.8-dt-bindings-clock-mediatek-add-MT7988-clock-IDs.patch create mode 100644 target/linux/mediatek/patches-6.6/247-v6.8-dt-bindings-clock-mediatek-add-clock-controllers-of-.patch create mode 100644 target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch create mode 100644 target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/250-clk-mediatek-add-infracfg-reset-controller-for-mt798.patch create mode 100644 target/linux/mediatek/patches-6.6/250-dt-bindings-reset-mediatek-add-MT7988-reset-IDs.patch create mode 100644 target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch create mode 100644 target/linux/mediatek/patches-6.6/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch create mode 100644 target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch create mode 100644 target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch create mode 100644 target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch create mode 100644 target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch create mode 100644 target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch create mode 100644 target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch create mode 100644 target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch create mode 100644 target/linux/mediatek/patches-6.6/351-pinctrl-add-mt7988-pd-pulltype-support.patch create mode 100644 target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch create mode 100644 target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch create mode 100644 target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch create mode 100644 target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch create mode 100644 target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch create mode 100644 target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch create mode 100644 target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch create mode 100644 target/linux/mediatek/patches-6.6/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch create mode 100644 target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch create mode 100644 target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch create mode 100644 target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch create mode 100644 target/linux/mediatek/patches-6.6/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch create mode 100644 target/linux/mediatek/patches-6.6/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch create mode 100644 target/linux/mediatek/patches-6.6/610-pcie-mediatek-fix-clearing-interrupt-status.patch create mode 100644 target/linux/mediatek/patches-6.6/611-pcie-mediatek-gen3-PERST-for-100ms.patch create mode 100644 target/linux/mediatek/patches-6.6/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch create mode 100644 target/linux/mediatek/patches-6.6/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch create mode 100644 target/linux/mediatek/patches-6.6/721-dts-mt7622-mediatek-fix-300mhz.patch create mode 100644 target/linux/mediatek/patches-6.6/722-remove-300Hz-to-prevent-freeze.patch create mode 100644 target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch create mode 100644 target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch create mode 100644 target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch create mode 100644 target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch create mode 100644 target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch create mode 100644 target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch create mode 100644 target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch create mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch create mode 100644 target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch create mode 100644 target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch create mode 100644 target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch create mode 100644 target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch create mode 100644 target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch create mode 100644 target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.7-07-ASoC-mediatek-mt7986-drop-the-remove-callback-of-mt7.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.7-08-ASoC-mediatek-mt7986-remove-the-mt7986_wm8960_priv-s.patch create mode 100644 target/linux/mediatek/patches-6.6/860-v6.7-09-ASoC-mediatek-mt7986-add-sample-rate-checker.patch create mode 100644 target/linux/mediatek/patches-6.6/861-pending-10-ASoC-mediatek-mt7986-silence-error-in-case-of-EPROBE.patch create mode 100644 target/linux/mediatek/patches-6.6/862-arm64-dts-mt7986-add-afe.patch create mode 100644 target/linux/mediatek/patches-6.6/863-arm64-dts-mt7986-add-sound-wm8960.patch create mode 100644 target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch create mode 100644 target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch create mode 100644 target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch create mode 100644 target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch create mode 100644 target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch create mode 100644 target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch create mode 100644 target/linux/mediatek/patches-6.6/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch create mode 100644 target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch create mode 100644 target/linux/mediatek/patches-6.6/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch create mode 100644 target/linux/mediatek/patches-6.6/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch create mode 100644 target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch create mode 100644 target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch create mode 100644 target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch create mode 100644 target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch create mode 100644 target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch create mode 100644 target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch create mode 100644 target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch diff --git a/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch b/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch new file mode 100644 index 0000000000..17c5c6098a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch @@ -0,0 +1,44 @@ +From 363547d2191cbc32ca954ba75d72908712398ff2 Mon Sep 17 00:00:00 2001 +From: Andrew Davis +Date: Mon, 24 Oct 2022 12:34:28 -0500 +Subject: [PATCH] kbuild: Allow DTB overlays to built from .dtso named source + files + +Currently DTB Overlays (.dtbo) are build from source files with the same +extension (.dts) as the base DTs (.dtb). This may become confusing and +even lead to wrong results. For example, a composite DTB (created from a +base DTB and a set of overlays) might have the same name as one of the +overlays that create it. + +Different files should be generated from differently named sources. + .dtb <-> .dts + .dtbo <-> .dtso + +We do not remove the ability to compile DTBO files from .dts files here, +only add a new rule allowing the .dtso file name. The current .dts named +overlays can be renamed with time. After all have been renamed we can +remove the other rule. + +Signed-off-by: Andrew Davis +Reviewed-by: Geert Uytterhoeven +Tested-by: Geert Uytterhoeven +Reviewed-by: Frank Rowand +Tested-by: Frank Rowand +Link: https://lore.kernel.org/r/20221024173434.32518-2-afd@ti.com +Signed-off-by: Rob Herring +--- + scripts/Makefile.lib | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -408,6 +408,9 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_T + $(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE + $(call if_changed_dep,dtc) + ++$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE ++ $(call if_changed_dep,dtc) ++ + dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) + + # Bzip2 diff --git a/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch b/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch new file mode 100644 index 0000000000..970e0f92bb --- /dev/null +++ b/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch @@ -0,0 +1,106 @@ +From 2c4daed9580164522859fa100128be408cc69be2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 5 Nov 2022 23:36:16 +0100 +Subject: [PATCH 01/19] arm64: dts: mediatek: mt7986: add support for RX + Wireless Ethernet Dispatch + +Similar to TX Wireless Ethernet Dispatch, introduce RX Wireless Ethernet +Dispatch to offload traffic received by the wlan interface to lan/wan +one. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 65 +++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -76,6 +76,47 @@ + no-map; + reg = <0 0x4fc00000 0 0x00100000>; + }; ++ ++ wo_emi0: wo-emi@4fd00000 { ++ reg = <0 0x4fd00000 0 0x40000>; ++ no-map; ++ }; ++ ++ wo_emi1: wo-emi@4fd40000 { ++ reg = <0 0x4fd40000 0 0x40000>; ++ no-map; ++ }; ++ ++ wo_ilm0: wo-ilm@151e0000 { ++ reg = <0 0x151e0000 0 0x8000>; ++ no-map; ++ }; ++ ++ wo_ilm1: wo-ilm@151f0000 { ++ reg = <0 0x151f0000 0 0x8000>; ++ no-map; ++ }; ++ ++ wo_data: wo-data@4fd80000 { ++ reg = <0 0x4fd80000 0 0x240000>; ++ no-map; ++ }; ++ ++ wo_dlm0: wo-dlm@151e8000 { ++ reg = <0 0x151e8000 0 0x2000>; ++ no-map; ++ }; ++ ++ wo_dlm1: wo-dlm@151f8000 { ++ reg = <0 0x151f8000 0 0x2000>; ++ no-map; ++ }; ++ ++ wo_boot: wo-boot@15194000 { ++ reg = <0 0x15194000 0 0x1000>; ++ no-map; ++ }; ++ + }; + + timer { +@@ -239,6 +280,11 @@ + reg = <0 0x15010000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; ++ memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, ++ <&wo_data>, <&wo_boot>; ++ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", ++ "wo-data", "wo-boot"; ++ mediatek,wo-ccif = <&wo_ccif0>; + }; + + wed1: wed@15011000 { +@@ -247,6 +293,25 @@ + reg = <0 0x15011000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; ++ memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, ++ <&wo_data>, <&wo_boot>; ++ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", ++ "wo-data", "wo-boot"; ++ mediatek,wo-ccif = <&wo_ccif1>; ++ }; ++ ++ wo_ccif0: syscon@151a5000 { ++ compatible = "mediatek,mt7986-wo-ccif", "syscon"; ++ reg = <0 0x151a5000 0 0x1000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ wo_ccif1: syscon@151ad000 { ++ compatible = "mediatek,mt7986-wo-ccif", "syscon"; ++ reg = <0 0x151ad000 0 0x1000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; + }; + + eth: ethernet@15100000 { diff --git a/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch b/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch new file mode 100644 index 0000000000..b5091687a3 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch @@ -0,0 +1,166 @@ +From 438e53828c08cf0e8a65b61cf6ce1e4b6620551a Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 6 Nov 2022 09:50:24 +0100 +Subject: [PATCH 02/19] arm64: dts: mt7986: harmonize device node order + +This arrange device tree nodes in alphabetical order. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221106085034.12582-2-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 94 ++++++++++---------- + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 22 ++--- + 2 files changed, 58 insertions(+), 58 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -54,6 +54,53 @@ + }; + }; + ++&pio { ++ uart1_pins: uart1-pins { ++ mux { ++ function = "uart"; ++ groups = "uart1"; ++ }; ++ }; ++ ++ uart2_pins: uart2-pins { ++ mux { ++ function = "uart"; ++ groups = "uart2"; ++ }; ++ }; ++ ++ wf_2g_5g_pins: wf-2g-5g-pins { ++ mux { ++ function = "wifi"; ++ groups = "wf_2g", "wf_5g"; ++ }; ++ conf { ++ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", ++ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", ++ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", ++ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", ++ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", ++ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", ++ "WF1_TOP_CLK", "WF1_TOP_DATA"; ++ drive-strength = <4>; ++ }; ++ }; ++ ++ wf_dbdc_pins: wf-dbdc-pins { ++ mux { ++ function = "wifi"; ++ groups = "wf_dbdc"; ++ }; ++ conf { ++ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", ++ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", ++ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", ++ "WF0_TOP_CLK", "WF0_TOP_DATA"; ++ drive-strength = <4>; ++ }; ++ }; ++}; ++ + &switch { + ports { + #address-cells = <1>; +@@ -121,50 +168,3 @@ + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + }; +- +-&pio { +- uart1_pins: uart1-pins { +- mux { +- function = "uart"; +- groups = "uart1"; +- }; +- }; +- +- uart2_pins: uart2-pins { +- mux { +- function = "uart"; +- groups = "uart2"; +- }; +- }; +- +- wf_2g_5g_pins: wf-2g-5g-pins { +- mux { +- function = "wifi"; +- groups = "wf_2g", "wf_5g"; +- }; +- conf { +- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", +- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", +- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", +- "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", +- "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", +- "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", +- "WF1_TOP_CLK", "WF1_TOP_DATA"; +- drive-strength = <4>; +- }; +- }; +- +- wf_dbdc_pins: wf-dbdc-pins { +- mux { +- function = "wifi"; +- groups = "wf_dbdc"; +- }; +- conf { +- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", +- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", +- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", +- "WF0_TOP_CLK", "WF0_TOP_DATA"; +- drive-strength = <4>; +- }; +- }; +-}; +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -25,10 +25,6 @@ + }; + }; + +-&uart0 { +- status = "okay"; +-}; +- + ð { + status = "okay"; + +@@ -99,13 +95,6 @@ + }; + }; + +-&wifi { +- status = "okay"; +- pinctrl-names = "default", "dbdc"; +- pinctrl-0 = <&wf_2g_5g_pins>; +- pinctrl-1 = <&wf_dbdc_pins>; +-}; +- + &pio { + wf_2g_5g_pins: wf-2g-5g-pins { + mux { +@@ -138,3 +127,14 @@ + }; + }; + }; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&wifi { ++ status = "okay"; ++ pinctrl-names = "default", "dbdc"; ++ pinctrl-0 = <&wf_2g_5g_pins>; ++ pinctrl-1 = <&wf_dbdc_pins>; ++}; diff --git a/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch new file mode 100644 index 0000000000..5706531a46 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch @@ -0,0 +1,68 @@ +From ffb05357b47f06b2b4d1e14ba89169e28feb727b Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 6 Nov 2022 09:50:27 +0100 +Subject: [PATCH 03/19] arm64: dts: mt7986: add crypto related device nodes + +This patch adds crypto engine support for MT7986. + +Signed-off-by: Vic Wu +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20221106085034.12582-5-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 4 ++++ + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 4 ++++ + 3 files changed, 23 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -25,6 +25,10 @@ + }; + }; + ++&crypto { ++ status = "okay"; ++}; ++ + ð { + status = "okay"; + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -223,6 +223,21 @@ + status = "disabled"; + }; + ++ crypto: crypto@10320000 { ++ compatible = "inside-secure,safexcel-eip97"; ++ reg = <0 0x10320000 0 0x40000>; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-names = "ring0", "ring1", "ring2", "ring3"; ++ clocks = <&infracfg CLK_INFRA_EIP97_CK>; ++ clock-names = "infra_eip97_ck"; ++ assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>; ++ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>; ++ status = "disabled"; ++ }; ++ + uart0: serial@11002000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -25,6 +25,10 @@ + }; + }; + ++&crypto { ++ status = "okay"; ++}; ++ + ð { + status = "okay"; + diff --git a/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch b/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch new file mode 100644 index 0000000000..0e5b77a11b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch @@ -0,0 +1,37 @@ +From b49b7dc404ded1d89cbc568d875009a5c1ed4ef6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 6 Nov 2022 09:50:29 +0100 +Subject: [PATCH 04/19] arm64: dts: mt7986: add i2c node + +Add i2c Node to mt7986 devicetree. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20221106085034.12582-7-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -279,6 +279,20 @@ + status = "disabled"; + }; + ++ i2c0: i2c@11008000 { ++ compatible = "mediatek,mt7986-i2c"; ++ reg = <0 0x11008000 0 0x90>, ++ <0 0x10217080 0 0x80>; ++ interrupts = ; ++ clock-div = <5>; ++ clocks = <&infracfg CLK_INFRA_I2C0_CK>, ++ <&infracfg CLK_INFRA_AP_DMA_CK>; ++ clock-names = "main", "dma"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + ethsys: syscon@15000000 { + #address-cells = <1>; + #size-cells = <1>; diff --git a/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch b/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch new file mode 100644 index 0000000000..8201b47df6 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch @@ -0,0 +1,61 @@ +From 2cd6022800d6da7822e169f3e6f7f790c1431445 Mon Sep 17 00:00:00 2001 +From: Matthias Brugger +Date: Mon, 14 Nov 2022 13:16:53 +0100 +Subject: [PATCH 05/19] arm64: dts: mediatek: mt7986: Add SoC compatible + +Missing SoC compatible in the board file causes dt bindings check. + +Signed-off-by: Matthias Brugger +Link: https://lore.kernel.org/r/20221114121653.14739-1-matthias.bgg@kernel.org +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 2 +- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 1 + + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 2 +- + arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 3 +++ + 4 files changed, 6 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -9,7 +9,7 @@ + + / { + model = "MediaTek MT7986a RFB"; +- compatible = "mediatek,mt7986a-rfb"; ++ compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -10,6 +10,7 @@ + #include + + / { ++ compatible = "mediatek,mt7986a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -9,7 +9,7 @@ + + / { + model = "MediaTek MT7986b RFB"; +- compatible = "mediatek,mt7986b-rfb"; ++ compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; + + aliases { + serial0 = &uart0; +--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi +@@ -5,6 +5,9 @@ + */ + + #include "mt7986a.dtsi" ++/ { ++ compatible = "mediatek,mt7986b"; ++}; + + &pio { + compatible = "mediatek,mt7986b-pinctrl"; diff --git a/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch new file mode 100644 index 0000000000..3e5e3d880a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch @@ -0,0 +1,157 @@ +From f4029538f063a845dc9aae46cce4cf386e6253a5 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Fri, 18 Nov 2022 20:01:21 +0100 +Subject: [PATCH 06/19] arm64: dts: mt7986: add spi related device nodes + +This patch adds spi support for MT7986. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221118190126.100895-7-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 35 ++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 ++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 35 ++++++++++++++++++++ + 3 files changed, 98 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -59,6 +59,20 @@ + }; + + &pio { ++ spi_flash_pins: spi-flash-pins { ++ mux { ++ function = "spi"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ }; ++ ++ spic_pins: spic-pins { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ + uart1_pins: uart1-pins { + mux { + function = "uart"; +@@ -105,6 +119,27 @@ + }; + }; + ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++ spi_nand: spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ }; ++}; ++ ++&spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spic_pins>; ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++}; ++ + &switch { + ports { + #address-cells = <1>; +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -294,6 +294,34 @@ + status = "disabled"; + }; + ++ spi0: spi@1100a000 { ++ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0 0x1100a000 0 0x100>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_MPLL_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>, ++ <&infracfg CLK_INFRA_SPI0_CK>, ++ <&infracfg CLK_INFRA_SPI0_HCK_CK>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@1100b000 { ++ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0 0x1100b000 0 0x100>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_MPLL_D2>, ++ <&topckgen CLK_TOP_SPIM_MST_SEL>, ++ <&infracfg CLK_INFRA_SPI1_CK>, ++ <&infracfg CLK_INFRA_SPI1_HCK_CK>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; ++ status = "disabled"; ++ }; ++ + ethsys: syscon@15000000 { + #address-cells = <1>; + #size-cells = <1>; +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -100,6 +100,20 @@ + }; + + &pio { ++ spi_flash_pins: spi-flash-pins { ++ mux { ++ function = "spi"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ }; ++ ++ spic_pins: spic-pins { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; +@@ -132,6 +146,27 @@ + }; + }; + ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++ spi_nand: spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ }; ++}; ++ ++&spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spic_pins>; ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++}; ++ + &uart0 { + status = "okay"; + }; diff --git a/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch new file mode 100644 index 0000000000..53567c66a0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch @@ -0,0 +1,127 @@ +From 9e8e24ab716098e617195ce29b88e84608bf2108 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Fri, 6 Jan 2023 16:28:42 +0100 +Subject: [PATCH 07/19] arm64: dts: mt7986: add usb related device nodes + +This patch adds USB support for MT7986. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: Chunfeng Yun +Link: https://lore.kernel.org/r/20230106152845.88717-3-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 8 +++ + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 55 ++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 8 +++ + 3 files changed, 71 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -140,6 +140,10 @@ + status = "okay"; + }; + ++&ssusb { ++ status = "okay"; ++}; ++ + &switch { + ports { + #address-cells = <1>; +@@ -201,6 +205,10 @@ + status = "okay"; + }; + ++&usb_phy { ++ status = "okay"; ++}; ++ + &wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -322,6 +322,61 @@ + status = "disabled"; + }; + ++ ssusb: usb@11200000 { ++ compatible = "mediatek,mt7986-xhci", ++ "mediatek,mtk-xhci"; ++ reg = <0 0x11200000 0 0x2e00>, ++ <0 0x11203e00 0 0x0100>; ++ reg-names = "mac", "ippc"; ++ interrupts = ; ++ clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, ++ <&infracfg CLK_INFRA_IUSB_CK>, ++ <&infracfg CLK_INFRA_IUSB_133_CK>, ++ <&infracfg CLK_INFRA_IUSB_66M_CK>, ++ <&topckgen CLK_TOP_U2U3_XHCI_SEL>; ++ clock-names = "sys_ck", ++ "ref_ck", ++ "mcu_ck", ++ "dma_ck", ++ "xhci_ck"; ++ phys = <&u2port0 PHY_TYPE_USB2>, ++ <&u3port0 PHY_TYPE_USB3>, ++ <&u2port1 PHY_TYPE_USB2>; ++ status = "disabled"; ++ }; ++ ++ usb_phy: t-phy@11e10000 { ++ compatible = "mediatek,mt7986-tphy", ++ "mediatek,generic-tphy-v2"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0 0x11e10000 0x1700>; ++ status = "disabled"; ++ ++ u2port0: usb-phy@0 { ++ reg = <0x0 0x700>; ++ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, ++ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; ++ clock-names = "ref", "da_ref"; ++ #phy-cells = <1>; ++ }; ++ ++ u3port0: usb-phy@700 { ++ reg = <0x700 0x900>; ++ clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ }; ++ ++ u2port1: usb-phy@1000 { ++ reg = <0x1000 0x700>; ++ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, ++ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; ++ clock-names = "ref", "da_ref"; ++ #phy-cells = <1>; ++ }; ++ }; ++ + ethsys: syscon@15000000 { + #address-cells = <1>; + #size-cells = <1>; +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -167,10 +167,18 @@ + status = "okay"; + }; + ++&ssusb { ++ status = "okay"; ++}; ++ + &uart0 { + status = "okay"; + }; + ++&usb_phy { ++ status = "okay"; ++}; ++ + &wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; diff --git a/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch new file mode 100644 index 0000000000..9c0a48149d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch @@ -0,0 +1,160 @@ +From c1744e9e75a6a8abc7c893f349bcbf725b9c0d74 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Fri, 6 Jan 2023 16:28:43 +0100 +Subject: [PATCH 08/19] arm64: dts: mt7986: add mmc related device nodes + +This patch adds mmc support for MT7986. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20230106152845.88717-4-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 96 ++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++ + 2 files changed, 111 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -5,6 +5,8 @@ + */ + + /dts-v1/; ++#include ++ + #include "mt7986a.dtsi" + + / { +@@ -23,6 +25,24 @@ + device_type = "memory"; + reg = <0 0x40000000 0 0x40000000>; + }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; + }; + + &crypto { +@@ -58,7 +78,83 @@ + }; + }; + ++&mmc0 { ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ pinctrl-1 = <&mmc0_pins_uhs>; ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ hs400-ds-delay = <0x14014>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ non-removable; ++ no-sd; ++ no-sdio; ++ status = "okay"; ++}; ++ + &pio { ++ mmc0_pins_default: mmc0-pins { ++ mux { ++ function = "emmc"; ++ groups = "emmc_51"; ++ }; ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = <6>; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-ds { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ }; ++ ++ mmc0_pins_uhs: mmc0-uhs-pins { ++ mux { ++ function = "emmc"; ++ groups = "emmc_51"; ++ }; ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = <6>; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-ds { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ }; ++ + spi_flash_pins: spi-flash-pins { + mux { + function = "spi"; +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -345,6 +345,21 @@ + status = "disabled"; + }; + ++ mmc0: mmc@11230000 { ++ compatible = "mediatek,mt7986-mmc"; ++ reg = <0 0x11230000 0 0x1000>, ++ <0 0x11c20000 0 0x1000>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>, ++ <&infracfg CLK_INFRA_MSDC_HCK_CK>, ++ <&infracfg CLK_INFRA_MSDC_CK>, ++ <&infracfg CLK_INFRA_MSDC_133M_CK>, ++ <&infracfg CLK_INFRA_MSDC_66M_CK>; ++ clock-names = "source", "hclk", "source_cg", "bus_clk", ++ "sys_cg"; ++ status = "disabled"; ++ }; ++ + usb_phy: t-phy@11e10000 { + compatible = "mediatek,mt7986-tphy", + "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch new file mode 100644 index 0000000000..adc6394857 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch @@ -0,0 +1,118 @@ +From 87a42ef1d6cf602e4aa40555b4404cad6149a90f Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Fri, 6 Jan 2023 16:28:44 +0100 +Subject: [PATCH 09/19] arm64: dts: mt7986: add pcie related device nodes + +This patch adds PCIe support for MT7986. + +Signed-off-by: Jieyy Yang +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230106152845.88717-5-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 16 ++++++ + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 52 ++++++++++++++++++++ + 2 files changed, 68 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -93,6 +93,15 @@ + non-removable; + no-sd; + no-sdio; ++}; ++ ++&pcie { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_pins>; ++ status = "okay"; ++}; ++ ++&pcie_phy { + status = "okay"; + }; + +@@ -155,6 +164,13 @@ + }; + }; + ++ pcie_pins: pcie-pins { ++ mux { ++ function = "pcie"; ++ groups = "pcie_clk", "pcie_wake", "pcie_pereset"; ++ }; ++ }; ++ + spi_flash_pins: spi-flash-pins { + mux { + function = "spi"; +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + / { + compatible = "mediatek,mt7986a"; +@@ -360,6 +361,57 @@ + status = "disabled"; + }; + ++ pcie: pcie@11280000 { ++ compatible = "mediatek,mt7986-pcie", ++ "mediatek,mt8192-pcie"; ++ device_type = "pci"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ reg = <0x00 0x11280000 0x00 0x4000>; ++ reg-names = "pcie-mac"; ++ interrupts = ; ++ bus-range = <0x00 0xff>; ++ ranges = <0x82000000 0x00 0x20000000 0x00 ++ 0x20000000 0x00 0x10000000>; ++ clocks = <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, ++ <&infracfg CLK_INFRA_IPCIE_CK>, ++ <&infracfg CLK_INFRA_IPCIER_CK>, ++ <&infracfg CLK_INFRA_IPCIEB_CK>; ++ clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m"; ++ status = "disabled"; ++ ++ phys = <&pcie_port PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0x7>; ++ interrupt-map = <0 0 0 1 &pcie_intc 0>, ++ <0 0 0 2 &pcie_intc 1>, ++ <0 0 0 3 &pcie_intc 2>, ++ <0 0 0 4 &pcie_intc 3>; ++ pcie_intc: interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ }; ++ }; ++ ++ pcie_phy: t-phy@11c00000 { ++ compatible = "mediatek,mt7986-tphy", ++ "mediatek,generic-tphy-v2"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ pcie_port: pcie-phy@11c00000 { ++ reg = <0 0x11c00000 0 0x20000>; ++ clocks = <&clk40m>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ }; ++ }; ++ + usb_phy: t-phy@11e10000 { + compatible = "mediatek,mt7986-tphy", + "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch b/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch new file mode 100644 index 0000000000..38f159c74e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch @@ -0,0 +1,689 @@ +From a751f7412e0098801673b80bc7a4738ae7d710ce Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 6 Jan 2023 16:28:45 +0100 +Subject: [PATCH 10/19] arm64: dts: mt7986: add Bananapi R3 + +Add support for Bananapi R3 SBC. + +- SD/eMMC support (switching first 4 bits of data-bus with sw6/D) +- SPI-NAND/NOR support (switched CS by sw5/C) +- all rj45 ports and both SFP working (eth1/lan4) +- all USB-Ports + SIM-Slot tested +- i2c and all uarts tested +- wifi tested (with eeprom calibration data) + +The device can boot from all 4 storage options. Both, SPI and MMC, can +be switched using hardware switches on the board, see +https://wiki.banana-pi.org/Banana_Pi_BPI-R3#Jumper_setting + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20230106152845.88717-6-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/Makefile | 5 + + .../mt7986a-bananapi-bpi-r3-emmc.dtso | 29 ++ + .../mt7986a-bananapi-bpi-r3-nand.dtso | 55 +++ + .../mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 68 +++ + .../mediatek/mt7986a-bananapi-bpi-r3-sd.dtso | 23 + + .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 450 ++++++++++++++++++ + 6 files changed, 630 insertions(+) + create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso + create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso + create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso + create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso + create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts + +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -7,6 +7,11 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-ev + dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso +@@ -0,0 +1,29 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR MIT) ++/* ++ * Copyright (C) 2021 MediaTek Inc. ++ * Author: Sam.Shih ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ fragment@0 { ++ target-path = "/soc/mmc@11230000"; ++ __overlay__ { ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ hs400-ds-delay = <0x14014>; ++ non-removable; ++ no-sd; ++ no-sdio; ++ status = "okay"; ++ }; ++ }; ++}; ++ +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso +@@ -0,0 +1,55 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++/* ++ * Authors: Daniel Golle ++ * Frank Wunderlich ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ fragment@0 { ++ target-path = "/soc/spi@1100a000"; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi_nand: spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x80000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "reserved"; ++ reg = <0x80000 0x300000>; ++ }; ++ ++ partition@380000 { ++ label = "fip"; ++ reg = <0x380000 0x200000>; ++ read-only; ++ }; ++ ++ partition@580000 { ++ label = "ubi"; ++ reg = <0x580000 0x7a80000>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +@@ -0,0 +1,68 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++/* ++ * Authors: Daniel Golle ++ * Frank Wunderlich ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ fragment@0 { ++ target-path = "/soc/spi@1100a000"; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x20000>; ++ read-only; ++ }; ++ ++ partition@20000 { ++ label = "reserved"; ++ reg = <0x20000 0x20000>; ++ }; ++ ++ partition@40000 { ++ label = "u-boot-env"; ++ reg = <0x40000 0x40000>; ++ }; ++ ++ partition@80000 { ++ label = "reserved2"; ++ reg = <0x80000 0x80000>; ++ }; ++ ++ partition@100000 { ++ label = "fip"; ++ reg = <0x100000 0x80000>; ++ read-only; ++ }; ++ ++ partition@180000 { ++ label = "recovery"; ++ reg = <0x180000 0xa80000>; ++ }; ++ ++ partition@c00000 { ++ label = "fit"; ++ reg = <0xc00000 0x1400000>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR MIT) ++/* ++ * Copyright (C) 2021 MediaTek Inc. ++ * Author: Sam.Shih ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ fragment@0 { ++ target-path = "/soc/mmc@11230000"; ++ __overlay__ { ++ bus-width = <4>; ++ max-frequency = <52000000>; ++ cap-sd-highspeed; ++ status = "okay"; ++ }; ++ }; ++}; ++ +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -0,0 +1,450 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR MIT) ++/* ++ * Copyright (C) 2021 MediaTek Inc. ++ * Authors: Sam.Shih ++ * Frank Wunderlich ++ * Daniel Golle ++ */ ++ ++/dts-v1/; ++#include ++#include ++#include ++#include ++ ++#include "mt7986a.dtsi" ++ ++/ { ++ model = "Bananapi BPI-R3"; ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ aliases { ++ serial0 = &uart0; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ dcin: regulator-12vd { ++ compatible = "regulator-fixed"; ++ regulator-name = "12vd"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ reset-key { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&pio 9 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wps-key { ++ label = "wps"; ++ linux,code = ; ++ gpios = <&pio 10 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ /* i2c of the left SFP cage (wan) */ ++ i2c_sfp1: i2c-gpio-0 { ++ compatible = "i2c-gpio"; ++ sda-gpios = <&pio 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; ++ scl-gpios = <&pio 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; ++ i2c-gpio,delay-us = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ /* i2c of the right SFP cage (lan) */ ++ i2c_sfp2: i2c-gpio-1 { ++ compatible = "i2c-gpio"; ++ sda-gpios = <&pio 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; ++ scl-gpios = <&pio 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; ++ i2c-gpio,delay-us = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ green_led: led-0 { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&pio 69 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ blue_led: led-1 { ++ color = ; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&pio 86 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "1.8vd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ vin-supply = <&dcin>; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "3.3vd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ vin-supply = <&dcin>; ++ }; ++ ++ /* left SFP cage (wan) */ ++ sfp1: sfp-1 { ++ compatible = "sff,sfp"; ++ i2c-bus = <&i2c_sfp1>; ++ los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; ++ mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; ++ tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; ++ tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ /* right SFP cage (lan) */ ++ sfp2: sfp-2 { ++ compatible = "sff,sfp"; ++ i2c-bus = <&i2c_sfp2>; ++ los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; ++ mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; ++ tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; ++ tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&crypto { ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++ ++ gmac0: mac@0 { ++ compatible = "mediatek,eth-mac"; ++ reg = <0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ ++ gmac1: mac@1 { ++ compatible = "mediatek,eth-mac"; ++ reg = <1>; ++ phy-mode = "2500base-x"; ++ sfp = <&sfp1>; ++ managed = "in-band-status"; ++ }; ++ ++ mdio: mdio-bus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++}; ++ ++&mdio { ++ switch: switch@1f { ++ compatible = "mediatek,mt7531"; ++ reg = <31>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&pio>; ++ interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; ++ reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ pinctrl-1 = <&mmc0_pins_uhs>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c_pins>; ++ status = "okay"; ++}; ++ ++&pcie { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_pins>; ++ status = "okay"; ++}; ++ ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pio { ++ i2c_pins: i2c-pins { ++ mux { ++ function = "i2c"; ++ groups = "i2c"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0-pins { ++ mux { ++ function = "emmc"; ++ groups = "emmc_51"; ++ }; ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = <6>; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-ds { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ }; ++ ++ mmc0_pins_uhs: mmc0-uhs-pins { ++ mux { ++ function = "emmc"; ++ groups = "emmc_51"; ++ }; ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = <6>; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-ds { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; /* pull-down 50K */ ++ }; ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = <4>; ++ bias-pull-up = ; /* pull-up 10K */ ++ }; ++ }; ++ ++ pcie_pins: pcie-pins { ++ mux { ++ function = "pcie"; ++ groups = "pcie_clk", "pcie_pereset"; ++ }; ++ }; ++ ++ spi_flash_pins: spi-flash-pins { ++ mux { ++ function = "spi"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ }; ++ ++ spic_pins: spic-pins { ++ mux { ++ function = "spi"; ++ groups = "spi1_0"; ++ }; ++ }; ++ ++ uart1_pins: uart1-pins { ++ mux { ++ function = "uart"; ++ groups = "uart1_rx_tx"; ++ }; ++ }; ++ ++ uart2_pins: uart2-pins { ++ mux { ++ function = "uart"; ++ groups = "uart2_0_rx_tx"; ++ }; ++ }; ++ ++ wf_2g_5g_pins: wf-2g-5g-pins { ++ mux { ++ function = "wifi"; ++ groups = "wf_2g", "wf_5g"; ++ }; ++ conf { ++ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", ++ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", ++ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", ++ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", ++ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", ++ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", ++ "WF1_TOP_CLK", "WF1_TOP_DATA"; ++ drive-strength = <4>; ++ }; ++ }; ++ ++ wf_dbdc_pins: wf-dbdc-pins { ++ mux { ++ function = "wifi"; ++ groups = "wf_dbdc"; ++ }; ++ conf { ++ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", ++ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", ++ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", ++ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", ++ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", ++ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", ++ "WF1_TOP_CLK", "WF1_TOP_DATA"; ++ drive-strength = <4>; ++ }; ++ }; ++ ++ wf_led_pins: wf-led-pins { ++ mux { ++ function = "led"; ++ groups = "wifi_led"; ++ }; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++}; ++ ++&spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spic_pins>; ++ status = "okay"; ++}; ++ ++&ssusb { ++ status = "okay"; ++}; ++ ++&switch { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "wan"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan0"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan1"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan2"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan3"; ++ }; ++ ++ port5: port@5 { ++ reg = <5>; ++ label = "lan4"; ++ phy-mode = "2500base-x"; ++ sfp = <&sfp2>; ++ managed = "in-band-status"; ++ }; ++ ++ port@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++}; ++ ++&trng { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_pins>; ++ status = "okay"; ++}; ++ ++&usb_phy { ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "okay"; ++}; ++ ++&wifi { ++ status = "okay"; ++ pinctrl-names = "default", "dbdc"; ++ pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; ++ pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; ++}; ++ diff --git a/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch b/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch new file mode 100644 index 0000000000..79038334c4 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch @@ -0,0 +1,323 @@ +From 4c2d5411f4b101f7aa0fd74f80109e3afd6dc967 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Wed, 17 May 2023 12:11:08 +0200 +Subject: [PATCH 11/19] arm64: mediatek: Propagate chassis-type where possible + +The chassis-type string identifies the form-factor of the system: +add this property to all device trees of devices for which the form +factor is known. + +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230517101108.205654-1-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt6755-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt6779-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt6795-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts | 1 + + arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 1 + + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 1 + + arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 1 + + arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8173-elm.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts | 1 + + .../boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts | 1 + + arch/arm64/boot/dts/mediatek/mt8186-evb.dts | 1 + + 28 files changed, 28 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +@@ -11,6 +11,7 @@ + + / { + model = "MediaTek MT2712 evaluation board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt2712-evb", "mediatek,mt2712"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt6755-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt6755-evb.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek MT6755 EVB"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt6755-evb", "mediatek,mt6755"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt6779-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt6779-evb.dts +@@ -10,6 +10,7 @@ + + / { + model = "MediaTek MT6779 EVB"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt6779-evb", "mediatek,mt6779"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt6795-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt6795-evb.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek MT6795 Evaluation Board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt6795-evb", "mediatek,mt6795"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek MT6797 Evaluation Board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt6797-evb", "mediatek,mt6797"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts ++++ b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts +@@ -12,6 +12,7 @@ + + / { + model = "Mediatek X20 Development Board"; ++ chassis-type = "embedded"; + compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -15,6 +15,7 @@ + + / { + model = "Bananapi BPI-R64"; ++ chassis-type = "embedded"; + compatible = "bananapi,bpi-r64", "mediatek,mt7622"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -15,6 +15,7 @@ + + / { + model = "MediaTek MT7622 RFB1 board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -16,6 +16,7 @@ + + / { + model = "Bananapi BPI-R3"; ++ chassis-type = "embedded"; + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +@@ -11,6 +11,7 @@ + + / { + model = "MediaTek MT7986a RFB"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek MT7986b RFB"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts +@@ -11,6 +11,7 @@ + + / { + model = "Pumpkin MT8167"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt8167-pumpkin", "mediatek,mt8167"; + + memory@40000000 { +--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts +@@ -8,6 +8,7 @@ + + / { + model = "Google Hanawl"; ++ chassis-type = "laptop"; + compatible = "google,hana-rev7", "mediatek,mt8173"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts +@@ -8,6 +8,7 @@ + + / { + model = "Google Hana"; ++ chassis-type = "laptop"; + compatible = "google,hana-rev6", "google,hana-rev5", + "google,hana-rev4", "google,hana-rev3", + "google,hana", "mediatek,mt8173"; +--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dts +@@ -8,6 +8,7 @@ + + / { + model = "Google Elm"; ++ chassis-type = "laptop"; + compatible = "google,elm-rev8", "google,elm-rev7", "google,elm-rev6", + "google,elm-rev5", "google,elm-rev4", "google,elm-rev3", + "google,elm", "mediatek,mt8173"; +--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +@@ -10,6 +10,7 @@ + + / { + model = "MediaTek MT8173 evaluation board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt8173-evb", "mediatek,mt8173"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts +@@ -11,6 +11,7 @@ + + / { + model = "MediaTek MT8183 evaluation board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt8183-evb", "mediatek,mt8183"; + + aliases { +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts +@@ -9,6 +9,7 @@ + + / { + model = "Google burnet board"; ++ chassis-type = "convertible"; + compatible = "google,burnet", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts +@@ -9,6 +9,7 @@ + + / { + model = "Google damu board"; ++ chassis-type = "convertible"; + compatible = "google,damu", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts +@@ -9,6 +9,7 @@ + + / { + model = "Google juniper sku16 board"; ++ chassis-type = "convertible"; + compatible = "google,juniper-sku16", "google,juniper", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek kakadu board sku22"; ++ chassis-type = "tablet"; + compatible = "google,kakadu-rev3-sku22", "google,kakadu-rev2-sku22", + "google,kakadu", "mediatek,mt8183"; + }; +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts +@@ -9,6 +9,7 @@ + + / { + model = "MediaTek kakadu board"; ++ chassis-type = "tablet"; + compatible = "google,kakadu-rev3", "google,kakadu-rev2", + "google,kakadu", "mediatek,mt8183"; + }; +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts +@@ -12,6 +12,7 @@ + + / { + model = "MediaTek kodama sku16 board"; ++ chassis-type = "tablet"; + compatible = "google,kodama-sku16", "google,kodama", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts +@@ -12,6 +12,7 @@ + + / { + model = "MediaTek kodama sku272 board"; ++ chassis-type = "tablet"; + compatible = "google,kodama-sku272", "google,kodama", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts +@@ -12,6 +12,7 @@ + + / { + model = "MediaTek kodama sku288 board"; ++ chassis-type = "tablet"; + compatible = "google,kodama-sku288", "google,kodama", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts +@@ -14,6 +14,7 @@ + + / { + model = "MediaTek krane sku0 board"; ++ chassis-type = "tablet"; + compatible = "google,krane-sku0", "google,krane", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts +@@ -14,6 +14,7 @@ + + / { + model = "MediaTek krane sku176 board"; ++ chassis-type = "tablet"; + compatible = "google,krane-sku176", "google,krane", "mediatek,mt8183"; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt8186-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8186-evb.dts +@@ -7,6 +7,7 @@ + + / { + model = "MediaTek MT8186 evaluation board"; ++ chassis-type = "embedded"; + compatible = "mediatek,mt8186-evb", "mediatek,mt8186"; + + aliases { diff --git a/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch b/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch new file mode 100644 index 0000000000..e8c47945d6 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch @@ -0,0 +1,38 @@ +From 3b92c547e3d4a35c6214b3e7fa1103d0749d83b1 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 21 Apr 2023 15:20:44 +0200 +Subject: [PATCH 12/19] arm64: dts: mt7986: add PWM + +This adds pwm node to mt7986. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20230421132047.42166-5-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -240,6 +240,20 @@ + status = "disabled"; + }; + ++ pwm: pwm@10048000 { ++ compatible = "mediatek,mt7986-pwm"; ++ reg = <0 0x10048000 0 0x1000>; ++ #clock-cells = <1>; ++ #pwm-cells = <2>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_PWM_SEL>, ++ <&infracfg CLK_INFRA_PWM_STA>, ++ <&infracfg CLK_INFRA_PWM1_CK>, ++ <&infracfg CLK_INFRA_PWM2_CK>; ++ clock-names = "top", "main", "pwm1", "pwm2"; ++ status = "disabled"; ++ }; ++ + uart0: serial@11002000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; diff --git a/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch b/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch new file mode 100644 index 0000000000..ce908e3d31 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch @@ -0,0 +1,43 @@ +From 35e482bb599df010b4869017ff576dbb7a4d4c2e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 21 Apr 2023 15:20:45 +0200 +Subject: [PATCH 13/19] arm64: dts: mt7986: add PWM to BPI-R3 + +Add pwm node and pinctrl to BananaPi R3 devicetree. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20230421132047.42166-6-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -275,6 +275,13 @@ + }; + }; + ++ pwm_pins: pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0", "pwm1_0"; ++ }; ++ }; ++ + spi_flash_pins: spi-flash-pins { + mux { + function = "spi"; +@@ -345,6 +352,12 @@ + }; + }; + ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ + &spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; diff --git a/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch b/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch new file mode 100644 index 0000000000..c7b38484f4 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch @@ -0,0 +1,27 @@ +From ccdda5714446db8690505371442f7807f5d7c6fc Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 5 Feb 2023 18:48:33 +0100 +Subject: [PATCH 14/19] arm64: dts: mt7986: set Wifi Leds low-active for BPI-R3 + +Leds for Wifi are low-active, so add property to devicetree. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230205174833.107050-1-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -460,5 +460,9 @@ + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; + pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; ++ ++ led { ++ led-active-low; ++ }; + }; + diff --git a/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch b/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch new file mode 100644 index 0000000000..0b84f1463a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch @@ -0,0 +1,46 @@ +From 1423b4b780adcf3994e63a5988a62d5d1d509bb1 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 28 May 2023 13:33:42 +0200 +Subject: [PATCH 15/19] arm64: dts: mt7986: use size of reserved partition for + bl2 + +To store uncompressed bl2 more space is required than partition is +actually defined. + +There is currently no known usage of this reserved partition. +Openwrt uses same partition layout. + +We added same change to u-boot with commit d7bb1099 [1]. + +[1] https://source.denx.de/u-boot/u-boot/-/commit/d7bb109900c1ca754a0198b9afb50e3161ffc21e + +Cc: stable@vger.kernel.org +Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Daniel Golle +Link: https://lore.kernel.org/r/20230528113343.7649-1-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +@@ -27,15 +27,10 @@ + + partition@0 { + label = "bl2"; +- reg = <0x0 0x20000>; ++ reg = <0x0 0x40000>; + read-only; + }; + +- partition@20000 { +- label = "reserved"; +- reg = <0x20000 0x20000>; +- }; +- + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x40000>; diff --git a/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch b/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch new file mode 100644 index 0000000000..0d12079d7c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch @@ -0,0 +1,80 @@ +From 40a5a767d698ef7a71f8be851ea18b0a7a8b47bd Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 30 May 2023 22:12:33 +0200 +Subject: [PATCH 16/19] arm64: dts: mt7986: add thermal and efuse + +Add thermal related nodes to mt7986 devicetree. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230530201235.22330-3-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 36 ++++++++++++++++++++++- + 1 file changed, 35 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -337,6 +337,15 @@ + status = "disabled"; + }; + ++ auxadc: adc@1100d000 { ++ compatible = "mediatek,mt7986-auxadc"; ++ reg = <0 0x1100d000 0 0x1000>; ++ clocks = <&infracfg CLK_INFRA_ADC_26M_CK>; ++ clock-names = "main"; ++ #io-channel-cells = <1>; ++ status = "disabled"; ++ }; ++ + ssusb: usb@11200000 { + compatible = "mediatek,mt7986-xhci", + "mediatek,mtk-xhci"; +@@ -375,6 +384,21 @@ + status = "disabled"; + }; + ++ thermal: thermal@1100c800 { ++ #thermal-sensor-cells = <1>; ++ compatible = "mediatek,mt7986-thermal"; ++ reg = <0 0x1100c800 0 0x800>; ++ interrupts = ; ++ clocks = <&infracfg CLK_INFRA_THERM_CK>, ++ <&infracfg CLK_INFRA_ADC_26M_CK>, ++ <&infracfg CLK_INFRA_ADC_FRC_CK>; ++ clock-names = "therm", "auxadc", "adc_32k"; ++ mediatek,auxadc = <&auxadc>; ++ mediatek,apmixedsys = <&apmixedsys>; ++ nvmem-cells = <&thermal_calibration>; ++ nvmem-cell-names = "calibration-data"; ++ }; ++ + pcie: pcie@11280000 { + compatible = "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; +@@ -426,6 +450,17 @@ + }; + }; + ++ efuse: efuse@11d00000 { ++ compatible = "mediatek,mt7986-efuse", "mediatek,efuse"; ++ reg = <0 0x11d00000 0 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ thermal_calibration: calib@274 { ++ reg = <0x274 0xc>; ++ }; ++ }; ++ + usb_phy: t-phy@11e10000 { + compatible = "mediatek,mt7986-tphy", + "mediatek,generic-tphy-v2"; +@@ -567,5 +602,4 @@ + memory-region = <&wmcpu_emi>; + }; + }; +- + }; diff --git a/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch b/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch new file mode 100644 index 0000000000..3fe3e885eb --- /dev/null +++ b/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch @@ -0,0 +1,51 @@ +From bb78d0cf5117517f1ed296ae71048945d9107675 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 30 May 2023 22:12:34 +0200 +Subject: [PATCH 17/19] arm64: dts: mt7986: add thermal-zones + +Add thermal-zones to mt7986 devicetree. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230530201235.22330-4-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 +++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -602,4 +602,32 @@ + memory-region = <&wmcpu_emi>; + }; + }; ++ ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <1000>; ++ thermal-sensors = <&thermal 0>; ++ ++ trips { ++ cpu_trip_active_high: active-high { ++ temperature = <115000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ ++ cpu_trip_active_low: active-low { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ ++ cpu_trip_passive: passive { ++ temperature = <40000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ }; ++ }; ++ }; + }; diff --git a/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch b/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch new file mode 100644 index 0000000000..ca7d872a1b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch @@ -0,0 +1,64 @@ +From 5d90603b09e5814ffc38c47e79ccf9bc564f9296 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 30 May 2023 22:12:35 +0200 +Subject: [PATCH 18/19] arm64: dts: mt7986: add pwm-fan and cooling-maps to + BPI-R3 dts + +Add pwm-fan and cooling-maps to BananaPi-R3 devicetree. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230530201235.22330-5-linux@fw-web.de +Signed-off-by: Matthias Brugger +--- + .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -38,6 +38,15 @@ + regulator-always-on; + }; + ++ fan: pwm-fan { ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ /* cooling level (0, 1, 2) - pwm inverted */ ++ cooling-levels = <255 96 0>; ++ pwms = <&pwm 0 10000 0>; ++ status = "okay"; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + +@@ -133,6 +142,28 @@ + }; + }; + ++&cpu_thermal { ++ cooling-maps { ++ cpu-active-high { ++ /* active: set fan to cooling level 2 */ ++ cooling-device = <&fan 2 2>; ++ trip = <&cpu_trip_active_high>; ++ }; ++ ++ cpu-active-low { ++ /* active: set fan to cooling level 1 */ ++ cooling-device = <&fan 1 1>; ++ trip = <&cpu_trip_active_low>; ++ }; ++ ++ cpu-passive { ++ /* passive: set fan to cooling level 0 */ ++ cooling-device = <&fan 0 0>; ++ trip = <&cpu_trip_passive>; ++ }; ++ }; ++}; ++ + &crypto { + status = "okay"; + }; diff --git a/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch b/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch new file mode 100644 index 0000000000..9cc6cad0af --- /dev/null +++ b/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch @@ -0,0 +1,41 @@ +From 6dd3b939370094eb79529683be84500f3c757404 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 6 Jun 2023 16:43:20 +0100 +Subject: [PATCH 19/19] arm64: dts: mt7986: increase bl2 partition on NAND of + Bananapi R3 + +The bootrom burned into the MT7986 SoC will try multiple locations on +the SPI-NAND flash to load bl2 in case the bl2 image located at the the +previously attempted offset is corrupt. + +Use 0x100000 instead of 0x80000 as partition size for bl2 on SPI-NAND, +allowing for up to four redundant copies of bl2 (typically sized a +bit less than 0x40000). + +Fixes: 8e01fb15b8157 ("arm64: dts: mt7986: add Bananapi R3") +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/ZH9UGF99RgzrHZ88@makrotopia.org +Signed-off-by: Matthias Brugger +--- + .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso +@@ -29,13 +29,13 @@ + + partition@0 { + label = "bl2"; +- reg = <0x0 0x80000>; ++ reg = <0x0 0x100000>; + read-only; + }; + +- partition@80000 { ++ partition@100000 { + label = "reserved"; +- reg = <0x80000 0x300000>; ++ reg = <0x100000 0x280000>; + }; + + partition@380000 { diff --git a/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch b/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch new file mode 100644 index 0000000000..8cba3b2059 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch @@ -0,0 +1,34 @@ +From f8ed4088ed9c61ae92193da6130d04c37e7b19f2 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 20 Aug 2023 17:31:33 +0200 +Subject: [PATCH 20/22] arm64: dts: mt7986: define 3W max power to both SFP on + BPI-R3 + +All SFP power supplies are connected to the system VDD33 which is 3v3/8A. +Set 3A per SFP slot to allow SFPs work which need more power than the +default 1W. + +Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") +Signed-off-by: Frank Wunderlich +--- + arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -126,6 +126,7 @@ + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp1>; + los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; ++ maximum-power-milliwatt = <3000>; + mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; +@@ -137,6 +138,7 @@ + i2c-bus = <&i2c_sfp2>; + los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; ++ maximum-power-milliwatt = <3000>; + tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; + }; diff --git a/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch b/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch new file mode 100644 index 0000000000..20d4468cf0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch @@ -0,0 +1,59 @@ +From aa3d6df9803c267725dc72286bb91602b7579882 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 20 Aug 2023 17:31:34 +0200 +Subject: [PATCH 21/22] arm64: dts: mt7986: change cooling trips + +Add Critical and hot trips for emergency system shutdown and limiting +system load. + +Change passive trip to active to make sure fan is activated on the +lowest trip. + +Fixes: 1f5be05132f3 ("arm64: dts: mt7986: add thermal-zones") +Suggested-by: Daniel Golle +Signed-off-by: Frank Wunderlich +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -610,22 +610,34 @@ + thermal-sensors = <&thermal 0>; + + trips { ++ cpu_trip_crit: crit { ++ temperature = <125000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ ++ cpu_trip_hot: hot { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "hot"; ++ }; ++ + cpu_trip_active_high: active-high { + temperature = <115000>; + hysteresis = <2000>; + type = "active"; + }; + +- cpu_trip_active_low: active-low { ++ cpu_trip_active_med: active-med { + temperature = <85000>; + hysteresis = <2000>; + type = "active"; + }; + +- cpu_trip_passive: passive { +- temperature = <40000>; ++ cpu_trip_active_low: active-low { ++ temperature = <60000>; + hysteresis = <2000>; +- type = "passive"; ++ type = "active"; + }; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch b/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch new file mode 100644 index 0000000000..7166ab6a14 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch @@ -0,0 +1,38 @@ +From 6ddf23526955b8dbedfeaa57e691261fd73f9d4e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 20 Aug 2023 17:31:35 +0200 +Subject: [PATCH 22/22] arm64: dts: mt7986: change thermal trips on BPI-R3 + +Apply new naming after mt7986 thermal trips were changed. + +Fixes: c26f779a2295 ("arm64: dts: mt7986: add pwm-fan and cooling-maps to BPI-R3 dts") +Suggested-by: Daniel Golle +Signed-off-by: Frank Wunderlich +--- + .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -152,16 +152,16 @@ + trip = <&cpu_trip_active_high>; + }; + +- cpu-active-low { ++ cpu-active-med { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 1 1>; +- trip = <&cpu_trip_active_low>; ++ trip = <&cpu_trip_active_med>; + }; + +- cpu-passive { +- /* passive: set fan to cooling level 0 */ ++ cpu-active-low { ++ /* active: set fan to cooling level 0 */ + cooling-device = <&fan 0 0>; +- trip = <&cpu_trip_passive>; ++ trip = <&cpu_trip_active_low>; + }; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch b/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch new file mode 100644 index 0000000000..bb87c20a91 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch @@ -0,0 +1,216 @@ +From 69357074558daf6ff24c9f58714935e9e095a865 Mon Sep 17 00:00:00 2001 +From: OpenWrt community +Date: Wed, 13 Jul 2022 13:37:33 +0200 +Subject: [PATCH] kernel: add block fit partition parser + +--- + block/blk.h | 2 ++ + block/partitions/Kconfig | 7 +++++++ + block/partitions/Makefile | 1 + + block/partitions/check.h | 3 +++ + block/partitions/core.c | 17 +++++++++++++++++ + block/partitions/efi.c | 8 ++++++++ + block/partitions/efi.h | 3 +++ + block/partitions/msdos.c | 10 ++++++++++ + drivers/mtd/mtd_blkdevs.c | 2 ++ + drivers/mtd/ubi/block.c | 3 +++ + include/linux/msdos_partition.h | 1 + + 11 files changed, 57 insertions(+) + +--- a/block/blk.h ++++ b/block/blk.h +@@ -414,6 +414,8 @@ void blk_free_ext_minor(unsigned int min + #define ADDPART_FLAG_NONE 0 + #define ADDPART_FLAG_RAID 1 + #define ADDPART_FLAG_WHOLEDISK 2 ++#define ADDPART_FLAG_READONLY 4 ++#define ADDPART_FLAG_ROOTDEV 8 + int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, + sector_t length); + int bdev_del_partition(struct gendisk *disk, int partno); +--- a/block/partitions/Kconfig ++++ b/block/partitions/Kconfig +@@ -103,6 +103,13 @@ config ATARI_PARTITION + Say Y here if you would like to use hard disks under Linux which + were partitioned under the Atari OS. + ++config FIT_PARTITION ++ bool "Flattened-Image-Tree (FIT) partition support" if PARTITION_ADVANCED ++ default n ++ help ++ Say Y here if your system needs to mount the filesystem part of ++ a Flattened-Image-Tree (FIT) image commonly used with Das U-Boot. ++ + config IBM_PARTITION + bool "IBM disk label and partition support" + depends on PARTITION_ADVANCED && S390 +--- a/block/partitions/Makefile ++++ b/block/partitions/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o + obj-$(CONFIG_AMIGA_PARTITION) += amiga.o + obj-$(CONFIG_ATARI_PARTITION) += atari.o + obj-$(CONFIG_AIX_PARTITION) += aix.o ++obj-$(CONFIG_FIT_PARTITION) += fit.o + obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o + obj-$(CONFIG_MAC_PARTITION) += mac.o + obj-$(CONFIG_LDM_PARTITION) += ldm.o +--- a/block/partitions/check.h ++++ b/block/partitions/check.h +@@ -57,6 +57,7 @@ int amiga_partition(struct parsed_partit + int atari_partition(struct parsed_partitions *state); + int cmdline_partition(struct parsed_partitions *state); + int efi_partition(struct parsed_partitions *state); ++int fit_partition(struct parsed_partitions *state); + int ibm_partition(struct parsed_partitions *); + int karma_partition(struct parsed_partitions *state); + int ldm_partition(struct parsed_partitions *state); +@@ -67,3 +68,5 @@ int sgi_partition(struct parsed_partitio + int sun_partition(struct parsed_partitions *state); + int sysv68_partition(struct parsed_partitions *state); + int ultrix_partition(struct parsed_partitions *state); ++ ++int parse_fit_partitions(struct parsed_partitions *state, u64 start_sector, u64 nr_sectors, int *slot, int add_remain); +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -11,6 +11,9 @@ + #include + #include + #include ++#ifdef CONFIG_FIT_PARTITION ++#include ++#endif + + #include "check.h" + +@@ -48,6 +51,9 @@ static int (*check_part[])(struct parsed + #ifdef CONFIG_EFI_PARTITION + efi_partition, /* this must come before msdos */ + #endif ++#ifdef CONFIG_FIT_PARTITION ++ fit_partition, ++#endif + #ifdef CONFIG_SGI_PARTITION + sgi_partition, + #endif +@@ -439,6 +445,11 @@ static struct block_device *add_partitio + goto out_del; + } + ++#ifdef CONFIG_FIT_PARTITION ++ if (flags & ADDPART_FLAG_READONLY) ++ bdev->bd_read_only = true; ++#endif ++ + /* everything is up and running, commence */ + err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL); + if (err) +@@ -631,6 +642,11 @@ static bool blk_add_partition(struct gen + (state->parts[p].flags & ADDPART_FLAG_RAID)) + md_autodetect_dev(part->bd_dev); + ++#ifdef CONFIG_FIT_PARTITION ++ if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0) ++ ROOT_DEV = part->bd_dev; ++#endif ++ + return true; + } + +--- a/block/partitions/efi.c ++++ b/block/partitions/efi.c +@@ -716,6 +716,9 @@ int efi_partition(struct parsed_partitio + gpt_entry *ptes = NULL; + u32 i; + unsigned ssz = queue_logical_block_size(state->disk->queue) / 512; ++#ifdef CONFIG_FIT_PARTITION ++ u32 extra_slot = 64; ++#endif + + if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { + kfree(gpt); +@@ -749,6 +752,11 @@ int efi_partition(struct parsed_partitio + ARRAY_SIZE(ptes[i].partition_name)); + utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname); + state->parts[i + 1].has_info = true; ++#ifdef CONFIG_FIT_PARTITION ++ /* If this is a U-Boot FIT volume it may have subpartitions */ ++ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_FIT_GUID)) ++ (void) parse_fit_partitions(state, start * ssz, size * ssz, &extra_slot, 1); ++#endif + } + kfree(ptes); + kfree(gpt); +--- a/block/partitions/efi.h ++++ b/block/partitions/efi.h +@@ -51,6 +51,9 @@ + #define PARTITION_LINUX_LVM_GUID \ + EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \ + 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28) ++#define PARTITION_LINUX_FIT_GUID \ ++ EFI_GUID( 0xcae9be83, 0xb15f, 0x49cc, \ ++ 0x86, 0x3f, 0x08, 0x1b, 0x74, 0x4a, 0x2d, 0x93) + + typedef struct _gpt_header { + __le64 signature; +--- a/block/partitions/msdos.c ++++ b/block/partitions/msdos.c +@@ -564,6 +564,15 @@ static void parse_minix(struct parsed_pa + #endif /* CONFIG_MINIX_SUBPARTITION */ + } + ++static void parse_fit_mbr(struct parsed_partitions *state, ++ sector_t offset, sector_t size, int origin) ++{ ++#ifdef CONFIG_FIT_PARTITION ++ u32 extra_slot = 64; ++ (void) parse_fit_partitions(state, offset, size, &extra_slot, 1); ++#endif /* CONFIG_FIT_PARTITION */ ++} ++ + static struct { + unsigned char id; + void (*parse)(struct parsed_partitions *, sector_t, sector_t, int); +@@ -575,6 +584,7 @@ static struct { + {UNIXWARE_PARTITION, parse_unixware}, + {SOLARIS_X86_PARTITION, parse_solaris_x86}, + {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86}, ++ {FIT_PARTITION, parse_fit_mbr}, + {0, NULL}, + }; + +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -359,7 +359,9 @@ int add_mtd_blktrans_dev(struct mtd_blkt + } else { + snprintf(gd->disk_name, sizeof(gd->disk_name), + "%s%d", tr->name, new->devnum); +- gd->flags |= GENHD_FL_NO_PART; ++ ++ if (!IS_ENABLED(CONFIG_FIT_PARTITION) || mtd_type_is_nand(new->mtd)) ++ gd->flags |= GENHD_FL_NO_PART; + } + + set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -432,7 +432,9 @@ int ubiblock_create(struct ubi_volume_in + ret = -ENODEV; + goto out_cleanup_disk; + } +- gd->flags |= GENHD_FL_NO_PART; ++ if (!IS_ENABLED(CONFIG_FIT_PARTITION)) ++ gd->flags |= GENHD_FL_NO_PART; ++ + gd->private_data = dev; + sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); + set_capacity(gd, disk_capacity); +--- a/include/linux/msdos_partition.h ++++ b/include/linux/msdos_partition.h +@@ -31,6 +31,7 @@ enum msdos_sys_ind { + LINUX_LVM_PARTITION = 0x8e, + LINUX_RAID_PARTITION = 0xfd, /* autodetect RAID partition */ + ++ FIT_PARTITION = 0x2e, /* U-Boot uImage.FIT */ + SOLARIS_X86_PARTITION = 0x82, /* also Linux swap partitions */ + NEW_SOLARIS_X86_PARTITION = 0xbf, + diff --git a/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch new file mode 100644 index 0000000000..d5bd9a316b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch @@ -0,0 +1,107 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -1,7 +1,6 @@ + /* +- * Copyright (c) 2017 MediaTek Inc. +- * Author: Ming Huang +- * Sean Wang ++ * Copyright (c) 2018 MediaTek Inc. ++ * Author: Ryder Lee + * + * SPDX-License-Identifier: (GPL-2.0 OR MIT) + */ +@@ -24,7 +23,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; +- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { +@@ -45,18 +44,18 @@ + key-factory { + label = "factory"; + linux,code = ; +- gpios = <&pio 0 0>; ++ gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + + key-wps { + label = "wps"; + linux,code = ; +- gpios = <&pio 102 0>; ++ gpios = <&pio 102 GPIO_ACTIVE_LOW>; + }; + }; + + memory@40000000 { +- reg = <0 0x40000000 0 0x20000000>; ++ reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { +@@ -132,22 +131,22 @@ + + port@0 { + reg = <0>; +- label = "lan0"; ++ label = "lan1"; + }; + + port@1 { + reg = <1>; +- label = "lan1"; ++ label = "lan2"; + }; + + port@2 { + reg = <2>; +- label = "lan2"; ++ label = "lan3"; + }; + + port@3 { + reg = <3>; +- label = "lan3"; ++ label = "lan4"; + }; + + port@4 { +@@ -240,7 +239,22 @@ + status = "okay"; + }; + ++&pcie1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie1_pins>; ++ status = "okay"; ++}; ++ + &pio { ++ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and ++ * SATA functions. i.e. output-high: PCIe, output-low: SATA ++ */ ++ asm_sel { ++ gpio-hog; ++ gpios = <90 GPIO_ACTIVE_HIGH>; ++ output-high; ++ }; ++ + /* eMMC is shared pin with parallel NAND */ + emmc_pins_default: emmc-pins-default { + mux { +@@ -517,11 +531,11 @@ + }; + + &sata { +- status = "okay"; ++ status = "disabled"; + }; + + &sata_phy { +- status = "okay"; ++ status = "disabled"; + }; + + &spi0 { diff --git a/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch new file mode 100644 index 0000000000..b1770371b0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch @@ -0,0 +1,60 @@ +--- a/arch/arm/boot/dts/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mt7629-rfb.dts +@@ -18,6 +18,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; + }; + + gpio-keys { +@@ -70,6 +71,10 @@ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; ++ ++ nvmem-cells = <&macaddr_factory_2a>; ++ nvmem-cell-names = "mac-address"; ++ + fixed-link { + speed = <2500>; + full-duplex; +@@ -82,6 +87,9 @@ + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; ++ ++ nvmem-cells = <&macaddr_factory_24>; ++ nvmem-cell-names = "mac-address"; + }; + + mdio: mdio-bus { +@@ -133,8 +141,9 @@ + }; + + partition@b0000 { +- label = "kernel"; ++ label = "firmware"; + reg = <0xb0000 0xb50000>; ++ compatible = "denx,fit"; + }; + }; + }; +@@ -273,3 +282,17 @@ + pinctrl-0 = <&watchdog_pins>; + status = "okay"; + }; ++ ++&factory { ++ compatible = "nvmem-cells"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr_factory_24: macaddr@24 { ++ reg = <0x24 0x6>; ++ }; ++ ++ macaddr_factory_2a: macaddr@2a { ++ reg = <0x2a 0x6>; ++ }; ++}; diff --git a/target/linux/mediatek/patches-6.6/103-mt7623-enable-arch-timer.patch b/target/linux/mediatek/patches-6.6/103-mt7623-enable-arch-timer.patch new file mode 100644 index 0000000000..04df7b927b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/103-mt7623-enable-arch-timer.patch @@ -0,0 +1,20 @@ +From d6a596012150960f0f3a214d31bbac4b607dbd1e Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Fri, 29 Apr 2022 10:40:56 +0800 +Subject: [PATCH] arm: mediatek: select arch timer for mt7623 + +Signed-off-by: Chuanhong Guo +--- + arch/arm/mach-mediatek/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/mach-mediatek/Kconfig ++++ b/arch/arm/mach-mediatek/Kconfig +@@ -26,6 +26,7 @@ config MACH_MT6592 + config MACH_MT7623 + bool "MediaTek MT7623 SoCs support" + default ARCH_MEDIATEK ++ select HAVE_ARM_ARCH_TIMER + + config MACH_MT7629 + bool "MediaTek MT7629 SoCs support" diff --git a/target/linux/mediatek/patches-6.6/104-mt7622-add-snor-irq.patch b/target/linux/mediatek/patches-6.6/104-mt7622-add-snor-irq.patch new file mode 100644 index 0000000000..0d9c91f44d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/104-mt7622-add-snor-irq.patch @@ -0,0 +1,10 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -578,6 +578,7 @@ + compatible = "mediatek,mt7622-nor", + "mediatek,mt8173-nor"; + reg = <0 0x11014000 0 0xe0>; ++ interrupts = ; + clocks = <&pericfg CLK_PERI_FLASH_PD>, + <&topckgen CLK_TOP_FLASH_SEL>; + clock-names = "spi", "sf"; diff --git a/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch b/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch new file mode 100644 index 0000000000..93da722e72 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch @@ -0,0 +1,16 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -134,6 +134,13 @@ + #size-cells = <2>; + ranges; + ++ /* 64 KiB reserved for ramoops/pstore */ ++ ramoops@42ff0000 { ++ compatible = "ramoops"; ++ reg = <0 0x42ff0000 0 0x10000>; ++ record-size = <0x1000>; ++ }; ++ + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-6.6/106-dts-mt7622-disable_btif.patch b/target/linux/mediatek/patches-6.6/106-dts-mt7622-disable_btif.patch new file mode 100644 index 0000000000..fc6a8f35bc --- /dev/null +++ b/target/linux/mediatek/patches-6.6/106-dts-mt7622-disable_btif.patch @@ -0,0 +1,26 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -108,10 +108,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -89,10 +89,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch new file mode 100644 index 0000000000..8dc53d2985 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -19,6 +19,7 @@ + + chosen { + stdout-path = "serial2:115200n8"; ++ bootargs = "console=ttyS2,115200n8 console=tty1"; + }; + + connector { diff --git a/target/linux/mediatek/patches-6.6/111-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-6.6/111-dts-fix-bpi64-console.patch new file mode 100644 index 0000000000..f77f10cb95 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/111-dts-fix-bpi64-console.patch @@ -0,0 +1,11 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -24,7 +24,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; +- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { diff --git a/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch new file mode 100644 index 0000000000..b012a48d75 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch @@ -0,0 +1,37 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -20,6 +20,7 @@ + + aliases { + serial0 = &uart0; ++ ethernet0 = &gmac0; + }; + + chosen { +@@ -160,22 +161,22 @@ + + port@1 { + reg = <1>; +- label = "lan0"; ++ label = "lan1"; + }; + + port@2 { + reg = <2>; +- label = "lan1"; ++ label = "lan2"; + }; + + port@3 { + reg = <3>; +- label = "lan2"; ++ label = "lan3"; + }; + + port@4 { + reg = <4>; +- label = "lan3"; ++ label = "lan4"; + }; + + port@6 { diff --git a/target/linux/mediatek/patches-6.6/113-dts-fix-bpi64-leds-and-buttons.patch b/target/linux/mediatek/patches-6.6/113-dts-fix-bpi64-leds-and-buttons.patch new file mode 100644 index 0000000000..1cca6f3534 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/113-dts-fix-bpi64-leds-and-buttons.patch @@ -0,0 +1,49 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -21,6 +21,12 @@ + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; ++ led-boot = &led_system_green; ++ led-failsafe = &led_system_blue; ++ led-running = &led_system_green; ++ led-upgrade = &led_system_blue; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; + }; + + chosen { +@@ -44,8 +50,8 @@ + compatible = "gpio-keys"; + + factory-key { +- label = "factory"; +- linux,code = ; ++ label = "reset"; ++ linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + +@@ -59,17 +65,17 @@ + leds { + compatible = "gpio-leds"; + +- led-0 { ++ led_system_green: led-0 { + label = "bpi-r64:pio:green"; + color = ; + gpios = <&pio 89 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + +- led-1 { +- label = "bpi-r64:pio:red"; +- color = ; +- gpios = <&pio 88 GPIO_ACTIVE_HIGH>; ++ led_system_blue: led-1 { ++ label = "bpi-r64:pio:blue"; ++ color = ; ++ gpios = <&pio 85 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch new file mode 100644 index 0000000000..0d324084b1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch @@ -0,0 +1,21 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -556,12 +556,16 @@ + status = "okay"; + }; + ++&rtc { ++ status = "disabled"; ++}; ++ + &sata { +- status = "disable"; ++ status = "disabled"; + }; + + &sata_phy { +- status = "disable"; ++ status = "disabled"; + }; + + &spi0 { diff --git a/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch b/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch new file mode 100644 index 0000000000..5fc55314ce --- /dev/null +++ b/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch @@ -0,0 +1,70 @@ +From d278f43f25beedfd0cb784d1dd0a9e7e8c8f123f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 19 Apr 2023 20:15:53 +0100 +Subject: [PATCH] arm64: dts: mt7622: declare SPI-NAND present on BPI-R64 + +The SPI-NOR node in the device tree of the BananaPi R64 has most likely +been copied from the reference board's device tree even though the R64 +comes with an SPI-NAND chip rather than SPI-NOR. + +Setup the Serial NAND Flash Interface (SNFI) controller, enable +hardware BCH error detection and correction engine and add the SPI-NAND +chip including basic partitions, + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/ZEA96dmaXqTpk8u8@makrotopia.org +Signed-off-by: Matthias Brugger +--- + .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 38 ++++++++++++++++--- + 1 file changed, 33 insertions(+), 5 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -253,14 +253,42 @@ + status = "disabled"; + }; + +-&nor_flash { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi_nor_pins>; +- status = "disabled"; ++&bch { ++ status = "okay"; ++}; + ++&snfi { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial_nand_pins>; ++ status = "okay"; + flash@0 { +- compatible = "jedec,spi-nor"; ++ compatible = "spi-nand"; + reg = <0>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ nand-ecc-engine = <&snfi>; ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x80000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "fip"; ++ reg = <0x80000 0x200000>; ++ read-only; ++ }; ++ ++ ubi: partition@280000 { ++ label = "ubi"; ++ reg = <0x280000 0x7d80000>; ++ }; ++ }; + }; + }; + diff --git a/target/linux/mediatek/patches-6.6/121-hack-spi-nand-1b-bbm.patch b/target/linux/mediatek/patches-6.6/121-hack-spi-nand-1b-bbm.patch new file mode 100644 index 0000000000..ff5521c44e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/121-hack-spi-nand-1b-bbm.patch @@ -0,0 +1,20 @@ +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -724,7 +724,7 @@ static int spinand_mtd_write(struct mtd_ + static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) + { + struct spinand_device *spinand = nand_to_spinand(nand); +- u8 marker[2] = { }; ++ u8 marker[1] = { }; + struct nand_page_io_req req = { + .pos = *pos, + .ooblen = sizeof(marker), +@@ -735,7 +735,7 @@ static bool spinand_isbad(struct nand_de + + spinand_select_target(spinand, pos->target); + spinand_read_page(spinand, &req); +- if (marker[0] != 0xff || marker[1] != 0xff) ++ if (marker[0] != 0xff) + return true; + + return false; diff --git a/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch new file mode 100644 index 0000000000..82654e683c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch @@ -0,0 +1,94 @@ +From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001 +From: Xiangsheng Hou +Date: Thu, 6 Jun 2019 16:29:04 +0800 +Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 + +Signed-off-by: Xiangsheng Hou +--- + arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ + 3 files changed, 79 insertions(+) + +--- a/arch/arm/boot/dts/mt7629.dtsi ++++ b/arch/arm/boot/dts/mt7629.dtsi +@@ -272,6 +272,27 @@ + status = "disabled"; + }; + ++ snfi: spi@1100d000 { ++ compatible = "mediatek,mt7629-snand"; ++ reg = <0x1100d000 0x1000>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>; ++ clock-names = "nfi_clk", "pad_clk"; ++ nand-ecc-engine = <&bch>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bch: ecc@1100e000 { ++ compatible = "mediatek,mt7622-ecc"; ++ reg = <0x1100e000 0x1000>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_NFIECC_PD>; ++ clock-names = "nfiecc_clk"; ++ status = "disabled"; ++ }; ++ + spi: spi@1100a000 { + compatible = "mediatek,mt7629-spi", + "mediatek,mt7622-spi"; +--- a/arch/arm/boot/dts/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mt7629-rfb.dts +@@ -255,6 +255,50 @@ + }; + }; + ++&bch { ++ status = "okay"; ++}; ++ ++&snfi { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial_nand_pins>; ++ status = "okay"; ++ flash@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ nand-ecc-engine = <&snfi>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "Bootloader"; ++ reg = <0x00000 0x0100000>; ++ read-only; ++ }; ++ ++ partition@100000 { ++ label = "Config"; ++ reg = <0x100000 0x0040000>; ++ }; ++ ++ partition@140000 { ++ label = "factory"; ++ reg = <0x140000 0x0080000>; ++ }; ++ ++ partition@1c0000 { ++ label = "firmware"; ++ reg = <0x1c0000 0x1000000>; ++ }; ++ }; ++ }; ++}; ++ + &spi { + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; diff --git a/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch new file mode 100644 index 0000000000..d6e0ab1d41 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch @@ -0,0 +1,68 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -534,6 +534,65 @@ + status = "disabled"; + }; + ++&bch { ++ status = "okay"; ++}; ++ ++&snfi { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial_nand_pins>; ++ status = "okay"; ++ flash@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ nand-ecc-engine = <&snfi>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "Preloader"; ++ reg = <0x00000 0x0080000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "ATF"; ++ reg = <0x80000 0x0040000>; ++ }; ++ ++ partition@c0000 { ++ label = "Bootloader"; ++ reg = <0xc0000 0x0080000>; ++ }; ++ ++ partition@140000 { ++ label = "Config"; ++ reg = <0x140000 0x0080000>; ++ }; ++ ++ partition@1c0000 { ++ label = "Factory"; ++ reg = <0x1c0000 0x0100000>; ++ }; ++ ++ partition@200000 { ++ label = "firmware"; ++ reg = <0x2c0000 0x2000000>; ++ }; ++ ++ partition@2200000 { ++ label = "User_data"; ++ reg = <0x22c0000 0x4000000>; ++ }; ++ }; ++ }; ++}; ++ + &spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spic0_pins>; diff --git a/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch new file mode 100644 index 0000000000..117d5abde6 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch @@ -0,0 +1,18 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -575,7 +575,7 @@ + reg = <0x140000 0x0080000>; + }; + +- partition@1c0000 { ++ factory: partition@1c0000 { + label = "Factory"; + reg = <0x1c0000 0x0100000>; + }; +@@ -636,5 +636,6 @@ + &wmac { + pinctrl-names = "default"; + pinctrl-0 = <&wmac_pins>; ++ mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + }; diff --git a/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch new file mode 100644 index 0000000000..0860a22c37 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch @@ -0,0 +1,24 @@ +--- a/arch/arm/boot/dts/mt7623.dtsi ++++ b/arch/arm/boot/dts/mt7623.dtsi +@@ -984,17 +984,15 @@ + }; + + crypto: crypto@1b240000 { +- compatible = "mediatek,eip97-crypto"; ++ compatible = "inside-secure,safexcel-eip97"; + reg = <0 0x1b240000 0 0x20000>; + interrupts = , + , + , +- , +- ; ++ ; ++ interrupt-names = "ring0", "ring1", "ring2", "ring3"; + clocks = <ðsys CLK_ETHSYS_CRYPTO>; +- clock-names = "cryp"; +- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; +- status = "disabled"; ++ status = "okay"; + }; + + bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch b/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch new file mode 100644 index 0000000000..091cffc3c0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -19,7 +19,7 @@ + + chosen { + stdout-path = "serial2:115200n8"; +- bootargs = "console=ttyS2,115200n8 console=tty1"; ++ bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; + }; + + connector { diff --git a/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch b/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch new file mode 100644 index 0000000000..d1bafc1526 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -15,6 +15,8 @@ + + aliases { + serial2 = &uart2; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; + }; + + chosen { diff --git a/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch b/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch new file mode 100644 index 0000000000..f6745add5b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch @@ -0,0 +1,29 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -17,6 +17,10 @@ + serial2 = &uart2; + mmc0 = &mmc0; + mmc1 = &mmc1; ++ led-boot = &led_system_green; ++ led-failsafe = &led_system_blue; ++ led-running = &led_system_green; ++ led-upgrade = &led_system_blue; + }; + + chosen { +@@ -112,13 +116,13 @@ + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_a>; + +- blue { ++ led_system_blue: blue { + label = "bpi-r2:pio:blue"; + gpios = <&pio 240 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + +- green { ++ led_system_green: green { + label = "bpi-r2:pio:green"; + gpios = <&pio 241 GPIO_ACTIVE_LOW>; + default-state = "off"; diff --git a/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch b/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch new file mode 100644 index 0000000000..b1dd75a414 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -15,6 +15,7 @@ + + aliases { + serial2 = &uart2; ++ ethernet0 = &gmac0; + mmc0 = &mmc0; + mmc1 = &mmc1; + led-boot = &led_system_green; diff --git a/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch b/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch new file mode 100644 index 0000000000..2675aa2589 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch @@ -0,0 +1,55 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -26,7 +26,9 @@ + + chosen { + stdout-path = "serial2:115200n8"; +- bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; ++ bootargs = "root=/dev/fit0 earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; ++ rootdisk-emmc = <&emmc_rootdisk>; ++ rootdisk-sd = <&sd_rootdisk>; + }; + + connector { +@@ -315,6 +317,20 @@ + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ emmc_rootdisk: block-partition-fit { ++ partno = <3>; ++ }; ++ }; ++ }; ++ }; + }; + + &mmc1 { +@@ -328,6 +344,20 @@ + cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ sd_rootdisk: block-partition-fit { ++ partno = <3>; ++ }; ++ }; ++ }; ++ }; + }; + + &mt6323_leds { diff --git a/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch b/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch new file mode 100644 index 0000000000..0a971c1f45 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch @@ -0,0 +1,32 @@ +From 983f37ee08acb60435744f1b1e2afea2d2a09c48 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 19 Apr 2023 20:16:29 +0100 +Subject: [PATCH] arm64: dts: mt7622: handle interrupts from MT7531 switch on + BPI-R64 + +Since commit ba751e28d442 ("net: dsa: mt7530: add interrupt support") +the mt7530 driver can act as an interrupt controller. Wire up irq line +of the MT7531 switch on the BananaPi BPi-R64 board, so the status of +the PHYs of the five 1000Base-T ports doesn't need to be polled any +more. + +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/ZEA-DV_OsmFg5egL@makrotopia.org +Signed-off-by: Matthias Brugger +--- + arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -154,6 +154,10 @@ + switch@0 { + compatible = "mediatek,mt7531"; + reg = <0>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&pio>; ++ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 54 0>; + + ports { diff --git a/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch b/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch new file mode 100644 index 0000000000..1e04d23a0e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch @@ -0,0 +1,106 @@ +From patchwork Tue Apr 26 19:51:36 2022 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 12827872 +Return-Path: + +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +Received: from bombadil.infradead.org (bombadil.infradead.org + [198.137.202.133]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by smtp.lore.kernel.org (Postfix) with ESMTPS id BACF3C433EF + for ; + Tue, 26 Apr 2022 19:53:05 +0000 (UTC) +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=lists.infradead.org; s=bombadil.20210309; h=Sender: + Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: + List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Subject:Cc:To: + From:Date:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: + Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: + List-Owner; bh=OWGSxvlKoyPWz6b629RNINucULo6oOdFssAIiJETWRg=; b=T0HEjee0FX3hlb + x5jl7xLK5sKM0pkE2oRgwzthbFlNg8ST1j/2GkgcgT0S2Bi0vRfFxHeu/RKzS9RmiVnKJnPGL8ctg + WoBLyO5i+NcmosGoy6MmoOjGTNhj/+3q3Z1jRLBSJ4ySSP22X77YeuJTmVzySPUllQhWvDhjMVCR9 + QBRmQdc6gCAg3IYGEbWwS2TG+UHveDCeZRWxMzrwI8UPadNCRFROwugmiQ3mdU41lHCTDpnlfuRJh + o1igLKfMBLz+D8rFYvDh7FfkcKkY6lNoswA2HKUun1MEzgoyQKmITPnG2maX/BvJJuj/B3ZJShh4k + AZHmXoQxq1mrsm2FxfnQ==; +Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) + id 1njRE5-00G05D-9z; Tue, 26 Apr 2022 19:51:57 +0000 +Received: from fudo.makrotopia.org ([2a07:2ec0:3002::71]) + by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) + id 1njRE1-00G03h-9H; Tue, 26 Apr 2022 19:51:55 +0000 +Received: from local + by fudo.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) + (Exim 4.94.2) (envelope-from ) + id 1njRDu-0006aF-4F; Tue, 26 Apr 2022 21:51:46 +0200 +Date: Tue, 26 Apr 2022 20:51:36 +0100 +From: Daniel Golle +To: devicetree@vger.kernel.org, linux-mediatek@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org +Cc: Rob Herring , + Krzysztof Kozlowski , + Matthias Brugger +Subject: [PATCH] arm64: dts: mediatek: mt7622: fix GICv2 range +Message-ID: +MIME-Version: 1.0 +Content-Disposition: inline +X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 +X-CRM114-CacheID: sfid-20220426_125153_359242_EA3D452C +X-CRM114-Status: GOOD ( 12.45 ) +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.34 +Precedence: list +List-Id: +List-Unsubscribe: + , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: + , + +Sender: "linux-arm-kernel" +Errors-To: + linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org + +With the current range specified for the CPU interface there is an +error message at boot: + +GIC: GICv2 detected, but range too small and irqchip.gicv2_force_probe not set + +Setting irqchip.gicv2_force_probe=1 in bootargs results in: + +GIC: Aliased GICv2 at 0x0000000010320000, trying to find the canonical range over 128kB +GIC: Adjusting CPU interface base to 0x000000001032f000 +GIC: Using split EOI/Deactivate mode + +Using the adjusted CPU interface base and 8K size results in only the +final line remaining and fully working system as well as /proc/interrupts +showing additional IPI3,4,5,6: + +IPI3: 0 0 CPU stop (for crash dump) interrupts +IPI4: 0 0 Timer broadcast interrupts +IPI5: 0 0 IRQ work interrupts +IPI6: 0 0 CPU wake-up interrupts + +Signed-off-by: Daniel Golle +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -346,7 +346,7 @@ + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10310000 0 0x1000>, +- <0 0x10320000 0 0x1000>, ++ <0 0x1032f000 0 0x2000>, + <0 0x10340000 0 0x2000>, + <0 0x10360000 0 0x2000>; + }; diff --git a/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch b/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch new file mode 100644 index 0000000000..1cfb53d620 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch @@ -0,0 +1,48 @@ +From 824d56e753a588fcfd650db1822e34a02a48bb77 Mon Sep 17 00:00:00 2001 +From: Bruno Umuarama +Date: Thu, 13 Oct 2022 21:18:21 +0000 +Subject: [PATCH] mediatek: mt7623: fix thermal zone +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Raising the temperatures for passive and active trips. @VA1DER +proposed at issue 9396 to remove passive trip. This commit relates to +his suggestion. + +Without this patch. the CPU will be throttled all the way down to 98MHz +if the temperature rises even a degree above the trip point, and it was +further discovered that if the internal temperature of the device is +above the first trip point temperature when it boots then it will start +in a throttled state and even +$ echo disabled > /sys/class/thermal/thermal_zone0/mode +will have no effect. + +The patch increases the passive trip point and active cooling map. The +throttling temperature will then be at 77°C and 82°C, which is still a +low enough temperature for ARM devices to not be in the real danger +zone, and gives some operational headroom. + +Signed-off-by: Bruno Umuarama +--- + arch/arm/boot/dts/mt7623.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/mt7623.dtsi ++++ b/arch/arm/boot/dts/mt7623.dtsi +@@ -160,13 +160,13 @@ + + trips { + cpu_passive: cpu-passive { +- temperature = <57000>; ++ temperature = <77000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_active: cpu-active { +- temperature = <67000>; ++ temperature = <82000>; + hysteresis = <2000>; + type = "active"; + }; diff --git a/target/linux/mediatek/patches-6.6/194-dts-mt7968a-add-ramoops.patch b/target/linux/mediatek/patches-6.6/194-dts-mt7968a-add-ramoops.patch new file mode 100644 index 0000000000..161c1e7516 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/194-dts-mt7968a-add-ramoops.patch @@ -0,0 +1,17 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -68,6 +68,14 @@ + #address-cells = <2>; + #size-cells = <2>; + ranges; ++ ++ /* 64 KiB reserved for ramoops/pstore */ ++ ramoops@42ff0000 { ++ compatible = "ramoops"; ++ reg = <0 0x42ff0000 0 0x10000>; ++ record-size = <0x1000>; ++ }; ++ + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-6.6/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch b/target/linux/mediatek/patches-6.6/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch new file mode 100644 index 0000000000..336920bafe --- /dev/null +++ b/target/linux/mediatek/patches-6.6/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch @@ -0,0 +1,196 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -23,6 +23,10 @@ + serial0 = &uart0; + ethernet0 = &gmac0; + ethernet1 = &gmac1; ++ led-boot = &green_led; ++ led-failsafe = &green_led; ++ led-running = &green_led; ++ led-upgrade = &blue_led; + }; + + chosen { +@@ -419,27 +423,27 @@ + + port@1 { + reg = <1>; +- label = "lan0"; ++ label = "lan1"; + }; + + port@2 { + reg = <2>; +- label = "lan1"; ++ label = "lan2"; + }; + + port@3 { + reg = <3>; +- label = "lan2"; ++ label = "lan3"; + }; + + port@4 { + reg = <4>; +- label = "lan3"; ++ label = "lan4"; + }; + + port5: port@5 { + reg = <5>; +- label = "lan4"; ++ label = "sfp2"; + phy-mode = "2500base-x"; + sfp = <&sfp2>; + managed = "in-band-status"; +@@ -490,9 +494,137 @@ + + &wifi { + status = "okay"; +- pinctrl-names = "default", "dbdc"; ++ pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; +- pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; ++ ++ mediatek,eeprom-data = <0x86790900 0x000c4326 0x60000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x01000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000800 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x24649090 0x00280000 0x05100000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00021e00 0x021e0002 0x1e00021e 0x00022800 0x02280002 0x28000228 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00008080 0x8080fdf7 ++ 0x0903150d 0x80808080 0x80808080 0x05050d0d 0x1313c6c6 0xc3c3c200 0x00c200c2 0x00008182 ++ 0x8585c2c2 0x82828282 0x858500c2 0xc2000081 0x82858587 0x87c2c200 0x81818285 0x858787c2 ++ 0xc2000081 0x82858587 0x87c2c200 0x00818285 0x858787c2 0xc2000081 0x82858587 0x87c4c4c2 ++ 0xc100c300 0xc3c3c100 0x818383c3 0xc3c3c100 0x81838300 0xc2c2c2c0 0x81828484 0x000000c3 ++ 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x838686c2 0xc2c2c081 0x82848486 0x86c3c3c3 ++ 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x83868622 0x28002228 ++ 0x00222800 0x22280000 0xdddddddd 0xdddddddd 0xddbbbbbb 0xccccccdd 0xdddddddd 0xdddddddd ++ 0xeeeeeecc 0xccccdddd 0xdddddddd 0x004a5662 0x0000004a 0x56620000 0x004a5662 0x0000004a ++ 0x56620000 0x88888888 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 ++ 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 0x00000000 0xf0f0cc00 ++ 0x00000000 0x0000aaaa 0xaabbbbbb 0xcccccccc 0xccccbbbb 0xbbbbbbbb 0xbbbbbbaa 0xaaaabbbb ++ 0xbbaaaaaa 0x999999aa 0xaaaabbbb 0xbbcccccc 0x00000000 0x0000aaaa 0xaa000000 0xbbbbbbbb ++ 0xbbbbaaaa 0xaa999999 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb ++ 0x00000000 0x00000000 0x00000000 0x99999999 0x9999aaaa 0xaaaaaaaa 0x999999aa 0xaaaaaaaa ++ 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb 0x00000000 0x0000eeee 0xeeffffff 0xcccccccc ++ 0xccccdddd 0xddbbbbbb 0xccccccbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbcccc 0xccdddddd ++ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 ++ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 ++ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e ++ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 ++ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 ++ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e ++ 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x06000100 0x01050002 0x00ff0300 ++ 0xf900fe03 0x00000000 0x00000000 0x0000009b 0x6e370000 0x00000000 0x00fc0009 0x0a00fe00 ++ 0x060700fe 0x00070800 0x05000b0a 0x00000000 0x00000000 0x000000e2 0x96460000 0x00000000 ++ 0x000400f7 0xf8000300 0xfcfe0003 0x00fbfc00 0xee00e3f2 0x00000000 0x00000000 0x00000011 ++ 0xbb550000 0x00000000 0x000600f6 0xfc000300 0xfbfe0004 0x00fafe00 0xf600ecf2 0x00000000 ++ 0x00000000 0x0000001f 0xbf580000 0x00000000 0x000600f5 0xf6000400 0xf8f90004 0x00f7f800 ++ 0xf700f0f4 0x00000000 0x00000000 0x00000024 0xbe570000 0x00000000 0x000800f8 0xfe000600 ++ 0xf8fd0007 0x00f9fe00 0xf500f0f4 0x00000000 0x00000000 0x0000002d 0xd6610000 0x00000000 ++ 0x000400f7 0xfc000500 0xf7fc0005 0x00f7fc00 0xf900f5f8 0x00000000 0x00000000 0x00000026 ++ 0xd96e0000 0x00000000 0x000400f7 0xf9000600 0xf5f70005 0x00f5f800 0xf900f4f7 0x00000000 ++ 0x00000000 0x0000001b 0xce690000 0x00000000 0x000300f8 0xf8000600 0xf6f60004 0x00f6f700 ++ 0xf900f4f7 0x00000000 0x00000000 0x00000018 0xd8720000 0x00000000 0x00000000 0x02404002 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0xc1c2c1c2 0x41c341c3 0x3fc13fc1 0x40c13fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c13fc2 ++ 0x3fc140c0 0x41c040c0 0x3fc33fc3 0x40c23fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c23fc2 ++ 0x3fc140c1 0x41c040c0 0x00000000 0x00000000 0x41c741c7 0xc1c7c1c7 0x00000000 0x00000000 ++ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 ++ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 ++ 0x00a0ce00 0x00000000 0xb6840000 0x00000000 0x00000000 0x00000000 0x18181818 0x18181818 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x004b5763 0x0000004b 0x57630000 0x004b5763 0x0000004b 0x57630000 0x88888888 0x08474759 ++ 0x69780849 0x49596d7a 0x0849495a 0x6d790848 0x48596c78 0x08484858 0x6a780848 0x48586a78 ++ 0x08484858 0x6c78084a 0x4a5b6d79 0x08474759 0x697a0848 0x48596b79 0x08484859 0x6c7a0848 ++ 0x48586c79 0x08484857 0x68770848 0x48576877 0x08484857 0x6a77084a 0x4a5a6a77 0x08464659 ++ 0x69790848 0x48586b79 0x08484858 0x6c7a0848 0x48596c79 0x08484857 0x68770848 0x48576877 ++ 0x08494958 0x6d7a084b 0x4b5c6c77 0x0847475a 0x6a7b0849 0x495a6e7c 0x0849495a 0x6e7c0849 ++ 0x495b6e7c 0x08494959 0x6a7a0849 0x49596a7a 0x084a4a5a 0x6f7d084b 0x4b5c6e7b 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x85848484 ++ 0xc3c4c4c5 0xc4c3c33f 0xc3c3c2c2 0xc2c2c03f 0xc3c3c3c4 0xc4c4c33f 0xc2c2c2c2 0xc1c3c1c1 ++ 0xc0c08282 0x83848686 0x88880000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00001111 0x00000000 ++ 0x8080f703 0x10808080 0x80050d13 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x000000a4 0xce000000 0x0000b684 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ++ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>; + + led { + led-active-low; +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +@@ -55,6 +55,7 @@ + partition@c00000 { + label = "fit"; + reg = <0xc00000 0x1400000>; ++ compatible = "denx,fit"; + }; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/196-dts-mt7986a-bpi-r3-use-all-ubi-nand-layout.patch b/target/linux/mediatek/patches-6.6/196-dts-mt7986a-bpi-r3-use-all-ubi-nand-layout.patch new file mode 100644 index 0000000000..38510c0fc7 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/196-dts-mt7986a-bpi-r3-use-all-ubi-nand-layout.patch @@ -0,0 +1,131 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso +@@ -23,7 +23,27 @@ + no-sd; + no-sdio; + status = "okay"; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ emmc_rootdisk: block-partition-production { ++ partname = "production"; ++ }; ++ }; ++ }; ++ }; + }; + }; +-}; + ++ fragment@1 { ++ target-path = "/chosen"; ++ __overlay__ { ++ rootdisk-emmc = <&emmc_rootdisk>; ++ }; ++ }; ++}; +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso +@@ -29,27 +29,30 @@ + + partition@0 { + label = "bl2"; +- reg = <0x0 0x100000>; ++ reg = <0x0 0x200000>; + read-only; + }; + +- partition@100000 { +- label = "reserved"; +- reg = <0x100000 0x280000>; +- }; +- +- partition@380000 { +- label = "fip"; +- reg = <0x380000 0x200000>; +- read-only; +- }; +- +- partition@580000 { ++ partition@200000 { + label = "ubi"; +- reg = <0x580000 0x7a80000>; ++ reg = <0x200000 0x7e00000>; ++ compatible = "linux,ubi"; ++ ++ volumes { ++ nand_rootdisk: ubi-volume-fit { ++ volname = "fit"; ++ }; ++ }; + }; + }; + }; + }; + }; ++ ++ fragment@1 { ++ target-path = "/chosen"; ++ __overlay__ { ++ rootdisk-spim-nand = <&nand_rootdisk>; ++ }; ++ }; + }; +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +@@ -52,7 +52,7 @@ + reg = <0x180000 0xa80000>; + }; + +- partition@c00000 { ++ nor_rootdisk: partition@c00000 { + label = "fit"; + reg = <0xc00000 0x1400000>; + compatible = "denx,fit"; +@@ -61,4 +61,11 @@ + }; + }; + }; ++ ++ fragment@1 { ++ target-path = "/chosen"; ++ __overlay__ { ++ rootdisk-nor = <&nor_rootdisk>; ++ }; ++ }; + }; +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso +@@ -17,6 +17,27 @@ + max-frequency = <52000000>; + cap-sd-highspeed; + status = "okay"; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ sd_rootdisk: block-partition-production { ++ partname = "production"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/chosen"; ++ __overlay__ { ++ rootdisk-sd = <&sd_rootdisk>; + }; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch new file mode 100644 index 0000000000..6347533aa8 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch @@ -0,0 +1,66 @@ +From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001 +From: Kristian Evensen +Date: Mon, 30 Apr 2018 14:38:01 +0200 +Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support + +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -17,6 +17,8 @@ + #include + #include + #include ++#include ++#include + + #include "phy-mtk-io.h" + +@@ -264,6 +266,9 @@ + + #define TPHY_CLKS_CNT 2 + ++#define HIF_SYSCFG1 0x14 ++#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) ++ + enum mtk_phy_version { + MTK_PHY_V1 = 1, + MTK_PHY_V2, +@@ -331,6 +336,7 @@ struct mtk_tphy { + void __iomem *sif_base; /* only shared sif */ + const struct mtk_phy_pdata *pdata; + struct mtk_phy_instance **phys; ++ struct regmap *hif; + int nphys; + int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ + int src_coef; /* coefficient for slew rate calibrate */ +@@ -596,6 +602,10 @@ static void pcie_phy_instance_init(struc + if (tphy->pdata->version != MTK_PHY_V1) + return; + ++ if (tphy->hif) ++ regmap_update_bits(tphy->hif, HIF_SYSCFG1, ++ HIF_SYSCFG1_PHY2_MASK, 0); ++ + mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG0, + P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H, + FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) | +@@ -1241,6 +1251,16 @@ static int mtk_tphy_probe(struct platfor + &tphy->src_coef); + } + ++ if (of_find_property(np, "mediatek,phy-switch", NULL)) { ++ tphy->hif = syscon_regmap_lookup_by_phandle(np, ++ "mediatek,phy-switch"); ++ if (IS_ERR(tphy->hif)) { ++ dev_err(&pdev->dev, ++ "missing \"mediatek,phy-switch\" phandle\n"); ++ return PTR_ERR(tphy->hif); ++ } ++ } ++ + port = 0; + for_each_child_of_node(np, child_np) { + struct mtk_phy_instance *instance; diff --git a/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch b/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch new file mode 100644 index 0000000000..3e16a533e1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch @@ -0,0 +1,88 @@ +From f76e8bc416bebb0f7b9f57b1247eae945421c0b9 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sat, 8 Oct 2022 18:48:06 +0200 +Subject: [PATCH 1/2] pinctrl: mt7986: allow configuring uart rx/tx and rts/cts + separately + +Some mt7986 boards use uart rts/cts pins as gpio, +This patch allows to change rts/cts to gpio mode, but keep +rx/tx as UART function. + +Signed-off-by: Frank Wunderlich +Signed-off-by: Sam Shih +Link: https://lore.kernel.org/r/20221008164807.113590-1-linux@fw-web.de +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-mt7986.c | 32 ++++++++++++++++++----- + 1 file changed, 25 insertions(+), 7 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -675,11 +675,17 @@ static int mt7986_uart1_1_funcs[] = { 4, + static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; + static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; + +-static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, }; +-static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, }; ++static int mt7986_uart1_2_rx_tx_pins[] = { 29, 30, }; ++static int mt7986_uart1_2_rx_tx_funcs[] = { 3, 3, }; + +-static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, }; +-static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, }; ++static int mt7986_uart1_2_cts_rts_pins[] = { 31, 32, }; ++static int mt7986_uart1_2_cts_rts_funcs[] = { 3, 3, }; ++ ++static int mt7986_uart2_0_rx_tx_pins[] = { 29, 30, }; ++static int mt7986_uart2_0_rx_tx_funcs[] = { 4, 4, }; ++ ++static int mt7986_uart2_0_cts_rts_pins[] = { 31, 32, }; ++static int mt7986_uart2_0_cts_rts_funcs[] = { 4, 4, }; + + static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; + static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; +@@ -708,6 +714,12 @@ static int mt7986_pcie_reset_funcs[] = { + static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; + static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; + ++static int mt7986_uart1_rx_tx_pins[] = { 42, 43, }; ++static int mt7986_uart1_rx_tx_funcs[] = { 1, 1, }; ++ ++static int mt7986_uart1_cts_rts_pins[] = { 44, 45, }; ++static int mt7986_uart1_cts_rts_funcs[] = { 1, 1, }; ++ + static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; + static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; + +@@ -749,6 +761,8 @@ static const struct group_desc mt7986_gr + PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), + PINCTRL_PIN_GROUP("i2c", mt7986_i2c), + PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), ++ PINCTRL_PIN_GROUP("uart1_rx_tx", mt7986_uart1_rx_tx), ++ PINCTRL_PIN_GROUP("uart1_cts_rts", mt7986_uart1_cts_rts), + PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), + PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), + PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), +@@ -760,8 +774,10 @@ static const struct group_desc mt7986_gr + PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), + PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), + PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), +- PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2), +- PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0), ++ PINCTRL_PIN_GROUP("uart1_2_rx_tx", mt7986_uart1_2_rx_tx), ++ PINCTRL_PIN_GROUP("uart1_2_cts_rts", mt7986_uart1_2_cts_rts), ++ PINCTRL_PIN_GROUP("uart2_0_rx_tx", mt7986_uart2_0_rx_tx), ++ PINCTRL_PIN_GROUP("uart2_0_cts_rts", mt7986_uart2_0_cts_rts), + PINCTRL_PIN_GROUP("spi0", mt7986_spi0), + PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), + PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), +@@ -800,7 +816,9 @@ static const char *mt7986_pwm_groups[] = + static const char *mt7986_spi_groups[] = { + "spi0", "spi0_wp_hold", "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; + static const char *mt7986_uart_groups[] = { +- "uart1_0", "uart1_1", "uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", ++ "uart1_0", "uart1_1", "uart1_rx_tx", "uart1_cts_rts", ++ "uart1_2_rx_tx", "uart1_2_cts_rts", ++ "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0_rx_tx", "uart2_0_cts_rts", + "uart2_0", "uart2_1", "uart0", "uart1", "uart2", + }; + static const char *mt7986_wdt_groups[] = { "watchdog", }; diff --git a/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch b/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch new file mode 100644 index 0000000000..47ded1aeb5 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch @@ -0,0 +1,100 @@ +From 822d774abbcc66b811e28c68b59b40b964ba5b46 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 6 Nov 2022 09:01:13 +0100 +Subject: [PATCH 2/2] pinctrl: mediatek: add pull_type attribute for mediatek + MT7986 SoC + +Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") +add SoC specify 'pull_type' attribute for bias configuration. + +This patch add pull_type attribute to pinctrl-mt7986.c, and make +bias_set_combo and bias_get_combo available to mediatek MT7986 SoC. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221106080114.7426-7-linux@fw-web.de +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-mt7986.c | 56 +++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -407,6 +407,60 @@ static const struct mtk_pin_field_calc m + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), + }; + ++static const unsigned int mt7986_pull_type[] = { ++ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ ++ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ ++ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ ++ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ ++ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ ++ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ ++ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ ++ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ ++ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ ++ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ ++ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ ++ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ ++ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ ++ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ ++ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ ++ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ ++ MTK_PULL_PU_PD_TYPE,/*100*/ ++}; ++ + static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), +@@ -868,6 +922,7 @@ static struct mtk_pin_soc mt7986a_data = + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), ++ .pull_type = mt7986_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, +@@ -889,6 +944,7 @@ static struct mtk_pin_soc mt7986b_data = + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), ++ .pull_type = mt7986_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, diff --git a/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch b/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch new file mode 100644 index 0000000000..46dfa24b7b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch @@ -0,0 +1,1094 @@ +From 6c83b2d94fcca735cf7d8aa7a55a4957eb404a9d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 26 Jan 2023 00:34:56 +0000 +Subject: [PATCH] pinctrl: add mt7981 pinctrl driver + +Add pinctrl driver for the MediaTek MT7981 SoC, based on the driver +which can also be found the SDK. + +Signed-off-by: Daniel Golle +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/ef5112946d16cacc67e65e439ba7b52a9950c1bb.1674693008.git.daniel@makrotopia.org +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/Kconfig | 5 + + drivers/pinctrl/mediatek/Makefile | 1 + + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1048 +++++++++++++++++++++ + 3 files changed, 1054 insertions(+) + create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c + +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -127,6 +127,11 @@ config PINCTRL_MT7622 + default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_MOORE + ++config PINCTRL_MT7981 ++ bool "Mediatek MT7981 pin control" ++ depends on OF ++ select PINCTRL_MTK_MOORE ++ + config PINCTRL_MT7986 + bool "Mediatek MT7986 pin control" + depends on OF +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- + obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o + obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o ++obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o + obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o + obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o + obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o +--- /dev/null ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -0,0 +1,1048 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * The MT7981 driver based on Linux generic pinctrl binding. ++ * ++ * Copyright (C) 2020 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include "pinctrl-moore.h" ++ ++#define MT7981_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 mt7981_pin_mode_range[] = { ++ PIN_FIELD(0, 56, 0x300, 0x10, 0, 4), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = { ++ PIN_FIELD(0, 56, 0x0, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_di_range[] = { ++ PIN_FIELD(0, 56, 0x200, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_do_range[] = { ++ PIN_FIELD(0, 56, 0x100, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), ++ PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x90, 0x10, 9, 1), ++ PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = { ++ PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = { ++ PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3), ++ ++ PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), ++ ++ PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1), ++ ++ PIN_FIELD_BASE(9, 9, 5, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1), ++}; ++ ++static const unsigned int mt7981_pull_type[] = { ++ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ ++ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ ++ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ ++ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ ++ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ ++ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ ++ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ ++ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ ++ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ ++ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ ++ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ ++ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ ++ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ ++ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ ++ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ ++ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ ++ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ ++ MTK_PULL_PU_PD_TYPE,/*100*/ ++}; ++ ++static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { ++ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range), ++ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range), ++ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range), ++ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range), ++ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range), ++ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range), ++ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range), ++ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range), ++ [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range), ++ [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range), ++ [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range), ++ [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range), ++}; ++ ++static const struct mtk_pin_desc mt7981_pins[] = { ++ MT7981_PIN(0, "GPIO_WPS"), ++ MT7981_PIN(1, "GPIO_RESET"), ++ MT7981_PIN(2, "SYS_WATCHDOG"), ++ MT7981_PIN(3, "PCIE_PERESET_N"), ++ MT7981_PIN(4, "JTAG_JTDO"), ++ MT7981_PIN(5, "JTAG_JTDI"), ++ MT7981_PIN(6, "JTAG_JTMS"), ++ MT7981_PIN(7, "JTAG_JTCLK"), ++ MT7981_PIN(8, "JTAG_JTRST_N"), ++ MT7981_PIN(9, "WO_JTAG_JTDO"), ++ MT7981_PIN(10, "WO_JTAG_JTDI"), ++ MT7981_PIN(11, "WO_JTAG_JTMS"), ++ MT7981_PIN(12, "WO_JTAG_JTCLK"), ++ MT7981_PIN(13, "WO_JTAG_JTRST_N"), ++ MT7981_PIN(14, "USB_VBUS"), ++ MT7981_PIN(15, "PWM0"), ++ MT7981_PIN(16, "SPI0_CLK"), ++ MT7981_PIN(17, "SPI0_MOSI"), ++ MT7981_PIN(18, "SPI0_MISO"), ++ MT7981_PIN(19, "SPI0_CS"), ++ MT7981_PIN(20, "SPI0_HOLD"), ++ MT7981_PIN(21, "SPI0_WP"), ++ MT7981_PIN(22, "SPI1_CLK"), ++ MT7981_PIN(23, "SPI1_MOSI"), ++ MT7981_PIN(24, "SPI1_MISO"), ++ MT7981_PIN(25, "SPI1_CS"), ++ MT7981_PIN(26, "SPI2_CLK"), ++ MT7981_PIN(27, "SPI2_MOSI"), ++ MT7981_PIN(28, "SPI2_MISO"), ++ MT7981_PIN(29, "SPI2_CS"), ++ MT7981_PIN(30, "SPI2_HOLD"), ++ MT7981_PIN(31, "SPI2_WP"), ++ MT7981_PIN(32, "UART0_RXD"), ++ MT7981_PIN(33, "UART0_TXD"), ++ MT7981_PIN(34, "PCIE_CLK_REQ"), ++ MT7981_PIN(35, "PCIE_WAKE_N"), ++ MT7981_PIN(36, "SMI_MDC"), ++ MT7981_PIN(37, "SMI_MDIO"), ++ MT7981_PIN(38, "GBE_INT"), ++ MT7981_PIN(39, "GBE_RESET"), ++ MT7981_PIN(40, "WF_DIG_RESETB"), ++ MT7981_PIN(41, "WF_CBA_RESETB"), ++ MT7981_PIN(42, "WF_XO_REQ"), ++ MT7981_PIN(43, "WF_TOP_CLK"), ++ MT7981_PIN(44, "WF_TOP_DATA"), ++ MT7981_PIN(45, "WF_HB1"), ++ MT7981_PIN(46, "WF_HB2"), ++ MT7981_PIN(47, "WF_HB3"), ++ MT7981_PIN(48, "WF_HB4"), ++ MT7981_PIN(49, "WF_HB0"), ++ MT7981_PIN(50, "WF_HB0_B"), ++ MT7981_PIN(51, "WF_HB5"), ++ MT7981_PIN(52, "WF_HB6"), ++ MT7981_PIN(53, "WF_HB7"), ++ MT7981_PIN(54, "WF_HB8"), ++ MT7981_PIN(55, "WF_HB9"), ++ MT7981_PIN(56, "WF_HB10"), ++}; ++ ++/* List all groups consisting of these pins dedicated to the enablement of ++ * certain hardware block and the corresponding mode for all of the pins. ++ * The hardware probably has multiple combinations of these pinouts. ++ */ ++ ++/* WA_AICE */ ++static int mt7981_wa_aice1_pins[] = { 0, 1, }; ++static int mt7981_wa_aice1_funcs[] = { 2, 2, }; ++ ++static int mt7981_wa_aice2_pins[] = { 0, 1, }; ++static int mt7981_wa_aice2_funcs[] = { 3, 3, }; ++ ++static int mt7981_wa_aice3_pins[] = { 28, 29, }; ++static int mt7981_wa_aice3_funcs[] = { 3, 3, }; ++ ++static int mt7981_wm_aice1_pins[] = { 9, 10, }; ++static int mt7981_wm_aice1_funcs[] = { 2, 2, }; ++ ++static int mt7981_wm_aice2_pins[] = { 30, 31, }; ++static int mt7981_wm_aice2_funcs[] = { 5, 5, }; ++ ++/* WM_UART */ ++static int mt7981_wm_uart_0_pins[] = { 0, 1, }; ++static int mt7981_wm_uart_0_funcs[] = { 5, 5, }; ++ ++static int mt7981_wm_uart_1_pins[] = { 20, 21, }; ++static int mt7981_wm_uart_1_funcs[] = { 4, 4, }; ++ ++static int mt7981_wm_uart_2_pins[] = { 30, 31, }; ++static int mt7981_wm_uart_2_funcs[] = { 3, 3, }; ++ ++/* DFD */ ++static int mt7981_dfd_pins[] = { 0, 1, 4, 5, }; ++static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, }; ++ ++/* SYS_WATCHDOG */ ++static int mt7981_watchdog_pins[] = { 2, }; ++static int mt7981_watchdog_funcs[] = { 1, }; ++ ++static int mt7981_watchdog1_pins[] = { 13, }; ++static int mt7981_watchdog1_funcs[] = { 5, }; ++ ++/* PCIE_PERESET_N */ ++static int mt7981_pcie_pereset_pins[] = { 3, }; ++static int mt7981_pcie_pereset_funcs[] = { 1, }; ++ ++/* JTAG */ ++static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, }; ++static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, }; ++ ++/* WM_JTAG */ ++static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, }; ++static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, }; ++ ++static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, }; ++static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; ++ ++/* WO0_JTAG */ ++static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, }; ++static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, }; ++ ++static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, }; ++static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; ++ ++/* UART2 */ ++static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; ++static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; ++ ++/* GBE_LED0 */ ++static int mt7981_gbe_led0_pins[] = { 8, }; ++static int mt7981_gbe_led0_funcs[] = { 3, }; ++ ++/* PTA_EXT */ ++static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, }; ++static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, }; ++ ++static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, }; ++static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, }; ++ ++/* PWM2 */ ++static int mt7981_pwm2_pins[] = { 7, }; ++static int mt7981_pwm2_funcs[] = { 4, }; ++ ++/* NET_WO0_UART_TXD */ ++static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, }; ++static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, }; ++ ++static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, }; ++static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, }; ++ ++static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, }; ++static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, }; ++ ++/* SPI1 */ ++static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, }; ++static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, }; ++ ++/* I2C */ ++static int mt7981_i2c0_0_pins[] = { 6, 7, }; ++static int mt7981_i2c0_0_funcs[] = { 6, 6, }; ++ ++static int mt7981_i2c0_1_pins[] = { 30, 31, }; ++static int mt7981_i2c0_1_funcs[] = { 4, 4, }; ++ ++static int mt7981_i2c0_2_pins[] = { 36, 37, }; ++static int mt7981_i2c0_2_funcs[] = { 2, 2, }; ++ ++static int mt7981_u2_phy_i2c_pins[] = { 30, 31, }; ++static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, }; ++ ++static int mt7981_u3_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, }; ++ ++static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, }; ++ ++static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, }; ++ ++/* DFD_NTRST */ ++static int mt7981_dfd_ntrst_pins[] = { 8, }; ++static int mt7981_dfd_ntrst_funcs[] = { 6, }; ++ ++/* PWM0 */ ++static int mt7981_pwm0_0_pins[] = { 13, }; ++static int mt7981_pwm0_0_funcs[] = { 2, }; ++ ++static int mt7981_pwm0_1_pins[] = { 15, }; ++static int mt7981_pwm0_1_funcs[] = { 1, }; ++ ++/* PWM1 */ ++static int mt7981_pwm1_0_pins[] = { 14, }; ++static int mt7981_pwm1_0_funcs[] = { 2, }; ++ ++static int mt7981_pwm1_1_pins[] = { 15, }; ++static int mt7981_pwm1_1_funcs[] = { 3, }; ++ ++/* GBE_LED1 */ ++static int mt7981_gbe_led1_pins[] = { 13, }; ++static int mt7981_gbe_led1_funcs[] = { 3, }; ++ ++/* PCM */ ++static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 }; ++static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, }; ++ ++/* UDI */ ++static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, }; ++static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, }; ++ ++/* DRV_VBUS */ ++static int mt7981_drv_vbus_pins[] = { 14, }; ++static int mt7981_drv_vbus_funcs[] = { 1, }; ++ ++/* EMMC */ ++static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; ++static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ ++/* SNFI */ ++static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, }; ++static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, }; ++ ++/* SPI0 */ ++static int mt7981_spi0_pins[] = { 16, 17, 18, 19, }; ++static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI0 */ ++static int mt7981_spi0_wp_hold_pins[] = { 20, 21, }; ++static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, }; ++ ++/* SPI1 */ ++static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, }; ++static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI2 */ ++static int mt7981_spi2_pins[] = { 26, 27, 28, 29, }; ++static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI2 */ ++static int mt7981_spi2_wp_hold_pins[] = { 30, 31, }; ++static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, }; ++ ++/* UART1 */ ++static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, }; ++static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, }; ++ ++static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; ++static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; ++ ++/* UART2 */ ++static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; ++static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; ++ ++/* UART0 */ ++static int mt7981_uart0_pins[] = { 32, 33, }; ++static int mt7981_uart0_funcs[] = { 1, 1, }; ++ ++/* PCIE_CLK_REQ */ ++static int mt7981_pcie_clk_pins[] = { 34, }; ++static int mt7981_pcie_clk_funcs[] = { 2, }; ++ ++/* PCIE_WAKE_N */ ++static int mt7981_pcie_wake_pins[] = { 35, }; ++static int mt7981_pcie_wake_funcs[] = { 2, }; ++ ++/* MDC_MDIO */ ++static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, }; ++static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, }; ++ ++static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, }; ++static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, }; ++ ++/* WF0_MODE1 */ ++static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }; ++static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ++ ++/* WF0_MODE3 */ ++static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 }; ++static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 }; ++ ++/* WF2G_LED */ ++static int mt7981_wf2g_led0_pins[] = { 30, }; ++static int mt7981_wf2g_led0_funcs[] = { 2, }; ++ ++static int mt7981_wf2g_led1_pins[] = { 34, }; ++static int mt7981_wf2g_led1_funcs[] = { 1, }; ++ ++/* WF5G_LED */ ++static int mt7981_wf5g_led0_pins[] = { 31, }; ++static int mt7981_wf5g_led0_funcs[] = { 2, }; ++ ++static int mt7981_wf5g_led1_pins[] = { 35, }; ++static int mt7981_wf5g_led1_funcs[] = { 1, }; ++ ++/* MT7531_INT */ ++static int mt7981_mt7531_int_pins[] = { 38, }; ++static int mt7981_mt7531_int_funcs[] = { 1, }; ++ ++/* ANT_SEL */ ++static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 }; ++static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; ++ ++static const struct group_desc mt7981_groups[] = { ++ /* @GPIO(0,1): WA_AICE(2) */ ++ PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1), ++ /* @GPIO(0,1): WA_AICE(3) */ ++ PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2), ++ /* @GPIO(0,1): WM_UART(5) */ ++ PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0), ++ /* @GPIO(0,1,4,5): DFD(6) */ ++ PINCTRL_PIN_GROUP("dfd", mt7981_dfd), ++ /* @GPIO(2): SYS_WATCHDOG(1) */ ++ PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog), ++ /* @GPIO(3): PCIE_PERESET_N(1) */ ++ PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset), ++ /* @GPIO(4,8) JTAG(1) */ ++ PINCTRL_PIN_GROUP("jtag", mt7981_jtag), ++ /* @GPIO(4,8) WM_JTAG(2) */ ++ PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0), ++ /* @GPIO(9,13) WO0_JTAG(1) */ ++ PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), ++ /* @GPIO(4,7) WM_JTAG(3) */ ++ PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), ++ /* @GPIO(8) GBE_LED0(3) */ ++ PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), ++ /* @GPIO(4,6) PTA_EXT(4) */ ++ PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0), ++ /* @GPIO(7) PWM2(4) */ ++ PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2), ++ /* @GPIO(8) NET_WO0_UART_TXD(4) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0), ++ /* @GPIO(4,7) SPI1(5) */ ++ PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0), ++ /* @GPIO(6,7) I2C(5) */ ++ PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0), ++ /* @GPIO(0,1,4,5): DFD_NTRST(6) */ ++ PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst), ++ /* @GPIO(9,10): WM_AICE(2) */ ++ PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1), ++ /* @GPIO(13): PWM0(2) */ ++ PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0), ++ /* @GPIO(15): PWM0(1) */ ++ PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1), ++ /* @GPIO(14): PWM1(2) */ ++ PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0), ++ /* @GPIO(15): PWM1(3) */ ++ PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1), ++ /* @GPIO(14) NET_WO0_UART_TXD(3) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1), ++ /* @GPIO(15) NET_WO0_UART_TXD(4) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2), ++ /* @GPIO(13) GBE_LED0(3) */ ++ PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1), ++ /* @GPIO(9,13) PCM(4) */ ++ PINCTRL_PIN_GROUP("pcm", mt7981_pcm), ++ /* @GPIO(13): SYS_WATCHDOG1(5) */ ++ PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1), ++ /* @GPIO(9,13) UDI(4) */ ++ PINCTRL_PIN_GROUP("udi", mt7981_udi), ++ /* @GPIO(14) DRV_VBUS(1) */ ++ PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), ++ /* @GPIO(15,25): EMMC(2) */ ++ PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), ++ /* @GPIO(16,21): SNFI(3) */ ++ PINCTRL_PIN_GROUP("snfi", mt7981_snfi), ++ /* @GPIO(16,19): SPI0(1) */ ++ PINCTRL_PIN_GROUP("spi0", mt7981_spi0), ++ /* @GPIO(20,21): SPI0(1) */ ++ PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold), ++ /* @GPIO(22,25) SPI1(1) */ ++ PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1), ++ /* @GPIO(26,29): SPI2(1) */ ++ PINCTRL_PIN_GROUP("spi2", mt7981_spi2), ++ /* @GPIO(30,31): SPI0(1) */ ++ PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold), ++ /* @GPIO(16,19): UART1(4) */ ++ PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), ++ /* @GPIO(26,29): UART1(2) */ ++ PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), ++ /* @GPIO(22,25): UART1(3) */ ++ PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), ++ /* @GPIO(22,24) PTA_EXT(4) */ ++ PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1), ++ /* @GPIO(20,21): WM_UART(4) */ ++ PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1), ++ /* @GPIO(30,31): WM_UART(3) */ ++ PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2), ++ /* @GPIO(20,24) WM_JTAG(5) */ ++ PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1), ++ /* @GPIO(25,29) WO0_JTAG(5) */ ++ PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1), ++ /* @GPIO(28,29): WA_AICE(3) */ ++ PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3), ++ /* @GPIO(30,31): WM_AICE(5) */ ++ PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2), ++ /* @GPIO(30,31): I2C(4) */ ++ PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1), ++ /* @GPIO(30,31): I2C(6) */ ++ PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c), ++ /* @GPIO(32,33): I2C(1) */ ++ PINCTRL_PIN_GROUP("uart0", mt7981_uart0), ++ /* @GPIO(32,33): I2C(2) */ ++ PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c), ++ /* @GPIO(32,33): I2C(3) */ ++ PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c), ++ /* @GPIO(32,33): I2C(5) */ ++ PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c), ++ /* @GPIO(34): PCIE_CLK_REQ(2) */ ++ PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk), ++ /* @GPIO(35): PCIE_WAKE_N(2) */ ++ PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake), ++ /* @GPIO(36,37): I2C(2) */ ++ PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2), ++ /* @GPIO(36,37): MDC_MDIO(1) */ ++ PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio), ++ /* @GPIO(36,37): MDC_MDIO(3) */ ++ PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio), ++ /* @GPIO(69,85): WF0_MODE1(1) */ ++ PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1), ++ /* @GPIO(74,80): WF0_MODE3(3) */ ++ PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3), ++ /* @GPIO(30): WF2G_LED(2) */ ++ PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0), ++ /* @GPIO(34): WF2G_LED(1) */ ++ PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1), ++ /* @GPIO(31): WF5G_LED(2) */ ++ PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0), ++ /* @GPIO(35): WF5G_LED(1) */ ++ PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1), ++ /* @GPIO(38): MT7531_INT(1) */ ++ PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int), ++ /* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */ ++ PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel), ++}; ++ ++/* 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 *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", ++ "wa_aice3", "wm_aice1_2", }; ++static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", ++ "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", ++ "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; ++static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; ++static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; ++static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; ++static const char *mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", "wo0_jtag_0", ++ "wo0_jtag_1", "wm_jtag_1", }; ++static const char *mt7981_led_groups[] = { "gbe_led0", "gbe_led1", "wf2g_led0", ++ "wf2g_led1", "wf5g_led0", "wf5g_led1", }; ++static const char *mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", }; ++static const char *mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1", ++ "pwm1_0", "pwm1_1", }; ++static const char *mt7981_spi_groups[] = { "spi1_0", "spi0", "spi0_wp_hold", "spi1_1", "spi2", ++ "spi2_wp_hold", }; ++static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c", ++ "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", "i2c0_2", }; ++static const char *mt7981_pcm_groups[] = { "pcm", }; ++static const char *mt7981_udi_groups[] = { "udi", }; ++static const char *mt7981_usb_groups[] = { "drv_vbus", }; ++static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; ++static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", ++ "wf0_mode1", "wf0_mode3", "mt7531_int", }; ++static const char *mt7981_ant_groups[] = { "ant_sel", }; ++ ++static const struct function_desc mt7981_functions[] = { ++ {"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)}, ++ {"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)}, ++ {"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)}, ++ {"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)}, ++ {"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)}, ++ {"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)}, ++ {"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)}, ++ {"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)}, ++ {"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)}, ++ {"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)}, ++ {"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)}, ++ {"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)}, ++ {"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)}, ++ {"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)}, ++ {"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)}, ++ {"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)}, ++ {"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)}, ++}; ++ ++static const struct mtk_eint_hw mt7981_eint_hw = { ++ .port_mask = 7, ++ .ports = 7, ++ .ap_num = ARRAY_SIZE(mt7981_pins), ++ .db_cnt = 16, ++}; ++ ++static const char * const mt7981_pinctrl_register_base_names[] = { ++ "gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb", ++ "iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl", ++}; ++ ++static struct mtk_pin_soc mt7981_data = { ++ .reg_cal = mt7981_reg_cals, ++ .pins = mt7981_pins, ++ .npins = ARRAY_SIZE(mt7981_pins), ++ .grps = mt7981_groups, ++ .ngrps = ARRAY_SIZE(mt7981_groups), ++ .funcs = mt7981_functions, ++ .nfuncs = ARRAY_SIZE(mt7981_functions), ++ .eint_hw = &mt7981_eint_hw, ++ .gpio_m = 0, ++ .ies_present = false, ++ .base_names = mt7981_pinctrl_register_base_names, ++ .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), ++ .pull_type = mt7981_pull_type, ++ .bias_set_combo = mtk_pinconf_bias_set_combo, ++ .bias_get_combo = mtk_pinconf_bias_get_combo, ++ .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 mt7981_pinctrl_of_match[] = { ++ { .compatible = "mediatek,mt7981-pinctrl", }, ++ {} ++}; ++ ++static int mt7981_pinctrl_probe(struct platform_device *pdev) ++{ ++ return mtk_moore_pinctrl_probe(pdev, &mt7981_data); ++} ++ ++static struct platform_driver mt7981_pinctrl_driver = { ++ .driver = { ++ .name = "mt7981-pinctrl", ++ .of_match_table = mt7981_pinctrl_of_match, ++ }, ++ .probe = mt7981_pinctrl_probe, ++}; ++ ++static int __init mt7981_pinctrl_init(void) ++{ ++ return platform_driver_register(&mt7981_pinctrl_driver); ++} ++arch_initcall(mt7981_pinctrl_init); diff --git a/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch b/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch new file mode 100644 index 0000000000..995e0dc7ed --- /dev/null +++ b/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch @@ -0,0 +1,30 @@ +From c0ad453e94e5c404efbcf668648d07eaa1a71ed7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 18 Feb 2023 09:51:06 +0300 +Subject: [PATCH] pinctrl: mediatek: add missing options to PINCTRL_MT7981 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are options missing from PINCTRL_MT7981 whilst being on every other +pin controller. Add them. + +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Link: https://lore.kernel.org/r/20230218065108.8958-1-arinc.unal@arinc9.com +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -130,6 +130,8 @@ config PINCTRL_MT7622 + config PINCTRL_MT7981 + bool "Mediatek MT7981 pin control" + depends on OF ++ depends on ARM64 || COMPILE_TEST ++ default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_MOORE + + config PINCTRL_MT7986 diff --git a/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch b/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch new file mode 100644 index 0000000000..db2561695b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch @@ -0,0 +1,76 @@ +From 8f6f16fe1553ce63edfb98a39ef9d4754a0c39bf Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 18 Aug 2023 04:02:35 +0100 +Subject: [PATCH] pinctrl: mediatek: fix pull_type data for MT7981 + +MediaTek has released pull_type data for MT7981 in their SDK. +Use it and set functions to configure pin bias. + +Fixes: 6c83b2d94fcc ("pinctrl: add mt7981 pinctrl driver") +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/7bcc8ead25dbfabc7f5a85d066224a926fbb4941.1692327317.git.daniel@makrotopia.org +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 44 +++++++---------------- + 1 file changed, 13 insertions(+), 31 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -457,37 +457,15 @@ static const unsigned int mt7981_pull_ty + MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ + MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ + MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ +- MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ +- MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ +- MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ +- MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ +- MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ +- MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ +- MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ +- MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ +- MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ +- MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ +- MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ +- MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ +- MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ +- MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ +- MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ +- MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ +- MTK_PULL_PU_PD_TYPE,/*100*/ ++ MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/ ++ MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/ ++ MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PU_PD_TYPE,/*45*/ ++ MTK_PULL_PU_PD_TYPE,/*46*/ MTK_PULL_PU_PD_TYPE,/*47*/ ++ MTK_PULL_PU_PD_TYPE,/*48*/ MTK_PULL_PU_PD_TYPE,/*49*/ ++ MTK_PULL_PU_PD_TYPE,/*50*/ MTK_PULL_PU_PD_TYPE,/*51*/ ++ MTK_PULL_PU_PD_TYPE,/*52*/ MTK_PULL_PU_PD_TYPE,/*53*/ ++ MTK_PULL_PU_PD_TYPE,/*54*/ MTK_PULL_PU_PD_TYPE,/*55*/ ++ MTK_PULL_PU_PD_TYPE,/*56*/ + }; + + static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { +@@ -1014,6 +992,10 @@ static struct mtk_pin_soc mt7981_data = + .ies_present = false, + .base_names = mt7981_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7981_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, + .pull_type = mt7981_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.6/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch b/target/linux/mediatek/patches-6.6/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch new file mode 100644 index 0000000000..d2f055836b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch @@ -0,0 +1,65 @@ +From 11db447f257231e08065989100311df57b7f1f1c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 26 Aug 2023 21:06:14 +0100 +Subject: [PATCH] pinctrl: mediatek: mt7981: add additional uart groups + +Add uart2_0_tx_rx (pin 4, 5) and uart1_2 (pins 9, 10) groups. + +Signed-off-by: Daniel Golle +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -611,6 +611,9 @@ static int mt7981_wo0_jtag_1_funcs[] = { + static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; + static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; + ++static int mt7981_uart2_0_tx_rx_pins[] = { 4, 5, }; ++static int mt7981_uart2_0_tx_rx_funcs[] = { 3, 3, }; ++ + /* GBE_LED0 */ + static int mt7981_gbe_led0_pins[] = { 8, }; + static int mt7981_gbe_led0_funcs[] = { 3, }; +@@ -731,6 +734,9 @@ static int mt7981_uart1_0_funcs[] = { 4, + static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; + static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; + ++static int mt7981_uart1_2_pins[] = { 9, 10, }; ++static int mt7981_uart1_2_funcs[] = { 2, 2, }; ++ + /* UART2 */ + static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; + static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; +@@ -805,6 +811,8 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), + /* @GPIO(4,7) WM_JTAG(3) */ + PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), ++ /* @GPIO(4,5) WM_JTAG(4) */ ++ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7981_uart2_0_tx_rx), + /* @GPIO(8) GBE_LED0(3) */ + PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), + /* @GPIO(4,6) PTA_EXT(4) */ +@@ -861,6 +869,8 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), + /* @GPIO(26,29): UART1(2) */ + PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), ++ /* @GPIO(9,10): UART1(2) */ ++ PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2), + /* @GPIO(22,25): UART1(3) */ + PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), + /* @GPIO(22,24) PTA_EXT(4) */ +@@ -922,9 +932,9 @@ static const struct group_desc mt7981_gr + */ + static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", + "wa_aice3", "wm_aice1_2", }; +-static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", +- "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", +- "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; ++static const char *mt7981_uart_groups[] = { "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", ++ "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart2_0", ++ "uart2_0_tx_rx", "uart2_1", "wm_uart_0", "wm_aurt_1", "wm_aurt_2", }; + static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; + static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; + static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; diff --git a/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch b/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch new file mode 100644 index 0000000000..7992a02677 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch @@ -0,0 +1,41 @@ +From 0d8387fba9f151220e48dc3dcdc2335539708f13 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 18 Aug 2023 04:03:26 +0100 +Subject: [PATCH] pinctrl: mediatek: assign functions to configure pin bias on + MT7986 + +Assign bias_disable_get/set and bias_get/set functions to allow +configuring pin bias on MT7986. + +Fixes: 2c58d8dc9cd0 ("pinctrl: mediatek: add pull_type attribute for mediatek MT7986 SoC") +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/47f72372354312a839b9337e09476aadcc206e8b.1692327317.git.daniel@makrotopia.org +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-mt7986.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -922,6 +922,10 @@ static struct mtk_pin_soc mt7986a_data = + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_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, + .pull_type = mt7986_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, +@@ -944,6 +948,10 @@ static struct mtk_pin_soc mt7986b_data = + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_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, + .pull_type = mt7986_pull_type, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch b/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch new file mode 100644 index 0000000000..af5715e1f5 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch @@ -0,0 +1,536 @@ +From fe5c8d03f3de89ae058e365b783f8c1314f47490 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:33 +0100 +Subject: [PATCH 01/15] clk: mediatek: clk-gate: Propagate struct device with + mtk_clk_register_gates() + +Commit e4c23e19aa2a ("clk: mediatek: Register clock gate with device") +introduces a helper function for the sole purpose of propagating a +struct device pointer to the clk API when registering the mtk-gate +clocks to take advantage of Runtime PM when/where needed and where +a power domain is defined in devicetree. + +Function mtk_clk_register_gates() then becomes a wrapper around the +new mtk_clk_register_gates_with_dev() function that will simply pass +NULL as struct device: this is essential when registering drivers +with CLK_OF_DECLARE instead of as a platform device, as there will +be no struct device to pass... but we can as well simply have only +one function that always takes such pointer as a param and pass NULL +when unavoidable. + +This commit removes the mtk_clk_register_gates() wrapper and renames +mtk_clk_register_gates_with_dev() to the former and all of the calls +to either of the two functions were fixed in all drivers in order to +reflect this change; also, to improve consistency with other kernel +functions, the pointer to struct device was moved as the first param. + +Since a lot of MediaTek clock drivers are actually registering as a +platform device, but were still registering the mtk-gate clocks +without passing any struct device to the clock framework, they've +been changed to pass a valid one now, as to make all those platforms +able to use runtime power management where available. + +While at it, some much needed indentation changes were also done. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Markus Schneider-Pargmann +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-4-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd + +[daniel@makrotopia.org: dropped parts not relevant for OpenWrt] +--- + drivers/clk/mediatek/clk-gate.c | 23 +++++++--------------- + drivers/clk/mediatek/clk-gate.h | 7 +------ + drivers/clk/mediatek/clk-mt2701-aud.c | 4 ++-- + drivers/clk/mediatek/clk-mt2701-eth.c | 4 ++-- + drivers/clk/mediatek/clk-mt2701-g3d.c | 2 +- + drivers/clk/mediatek/clk-mt2701-hif.c | 4 ++-- + drivers/clk/mediatek/clk-mt2701-mm.c | 4 ++-- + drivers/clk/mediatek/clk-mt2701.c | 12 +++++------ + drivers/clk/mediatek/clk-mt2712-mm.c | 4 ++-- + drivers/clk/mediatek/clk-mt2712.c | 12 +++++------ + drivers/clk/mediatek/clk-mt7622-aud.c | 4 ++-- + drivers/clk/mediatek/clk-mt7622-eth.c | 8 ++++---- + drivers/clk/mediatek/clk-mt7622-hif.c | 8 ++++---- + drivers/clk/mediatek/clk-mt7622.c | 14 ++++++------- + drivers/clk/mediatek/clk-mt7629-eth.c | 7 ++++--- + drivers/clk/mediatek/clk-mt7629-hif.c | 8 ++++---- + drivers/clk/mediatek/clk-mt7629.c | 10 +++++----- + drivers/clk/mediatek/clk-mt7986-eth.c | 10 +++++----- + drivers/clk/mediatek/clk-mt7986-infracfg.c | 4 ++-- + 19 files changed, 68 insertions(+), 81 deletions(-) + +--- a/drivers/clk/mediatek/clk-gate.c ++++ b/drivers/clk/mediatek/clk-gate.c +@@ -152,12 +152,12 @@ const struct clk_ops mtk_clk_gate_ops_no + }; + EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv); + +-static struct clk_hw *mtk_clk_register_gate(const char *name, ++static struct clk_hw *mtk_clk_register_gate(struct device *dev, const char *name, + const char *parent_name, + struct regmap *regmap, int set_ofs, + int clr_ofs, int sta_ofs, u8 bit, + const struct clk_ops *ops, +- unsigned long flags, struct device *dev) ++ unsigned long flags) + { + struct mtk_clk_gate *cg; + int ret; +@@ -202,10 +202,9 @@ static void mtk_clk_unregister_gate(stru + kfree(cg); + } + +-int mtk_clk_register_gates_with_dev(struct device_node *node, +- const struct mtk_gate *clks, int num, +- struct clk_hw_onecell_data *clk_data, +- struct device *dev) ++int mtk_clk_register_gates(struct device *dev, struct device_node *node, ++ const struct mtk_gate *clks, int num, ++ struct clk_hw_onecell_data *clk_data) + { + int i; + struct clk_hw *hw; +@@ -229,13 +228,13 @@ int mtk_clk_register_gates_with_dev(stru + continue; + } + +- hw = mtk_clk_register_gate(gate->name, gate->parent_name, ++ hw = mtk_clk_register_gate(dev, gate->name, gate->parent_name, + regmap, + gate->regs->set_ofs, + gate->regs->clr_ofs, + gate->regs->sta_ofs, + gate->shift, gate->ops, +- gate->flags, dev); ++ gate->flags); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", gate->name, +@@ -261,14 +260,6 @@ err: + + return PTR_ERR(hw); + } +-EXPORT_SYMBOL_GPL(mtk_clk_register_gates_with_dev); +- +-int mtk_clk_register_gates(struct device_node *node, +- const struct mtk_gate *clks, int num, +- struct clk_hw_onecell_data *clk_data) +-{ +- return mtk_clk_register_gates_with_dev(node, clks, num, clk_data, NULL); +-} + EXPORT_SYMBOL_GPL(mtk_clk_register_gates); + + void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, +--- a/drivers/clk/mediatek/clk-gate.h ++++ b/drivers/clk/mediatek/clk-gate.h +@@ -50,15 +50,10 @@ struct mtk_gate { + #define GATE_MTK(_id, _name, _parent, _regs, _shift, _ops) \ + GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, _ops, 0) + +-int mtk_clk_register_gates(struct device_node *node, ++int mtk_clk_register_gates(struct device *dev, struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data); + +-int mtk_clk_register_gates_with_dev(struct device_node *node, +- const struct mtk_gate *clks, int num, +- struct clk_hw_onecell_data *clk_data, +- struct device *dev); +- + void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data); + +--- a/drivers/clk/mediatek/clk-mt2701-aud.c ++++ b/drivers/clk/mediatek/clk-mt2701-aud.c +@@ -127,8 +127,8 @@ static int clk_mt2701_aud_probe(struct p + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR); + +- mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, audio_clks, ++ ARRAY_SIZE(audio_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { +--- a/drivers/clk/mediatek/clk-mt2701-eth.c ++++ b/drivers/clk/mediatek/clk-mt2701-eth.c +@@ -51,8 +51,8 @@ static int clk_mt2701_eth_probe(struct p + + clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); + +- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, eth_clks, ++ ARRAY_SIZE(eth_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt2701-g3d.c ++++ b/drivers/clk/mediatek/clk-mt2701-g3d.c +@@ -45,7 +45,7 @@ static int clk_mt2701_g3dsys_init(struct + + clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); + +- mtk_clk_register_gates(node, g3d_clks, ARRAY_SIZE(g3d_clks), ++ mtk_clk_register_gates(&pdev->dev, node, g3d_clks, ARRAY_SIZE(g3d_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +--- a/drivers/clk/mediatek/clk-mt2701-hif.c ++++ b/drivers/clk/mediatek/clk-mt2701-hif.c +@@ -48,8 +48,8 @@ static int clk_mt2701_hif_probe(struct p + + clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); + +- mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, hif_clks, ++ ARRAY_SIZE(hif_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { +--- a/drivers/clk/mediatek/clk-mt2701-mm.c ++++ b/drivers/clk/mediatek/clk-mt2701-mm.c +@@ -76,8 +76,8 @@ static int clk_mt2701_mm_probe(struct pl + + clk_data = mtk_alloc_clk_data(CLK_MM_NR); + +- mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, mm_clks, ++ ARRAY_SIZE(mm_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt2701.c ++++ b/drivers/clk/mediatek/clk-mt2701.c +@@ -685,8 +685,8 @@ static int mtk_topckgen_init(struct plat + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt2701_clk_lock, clk_data); + +- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, top_clks, ++ ARRAY_SIZE(top_clks), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + } +@@ -789,8 +789,8 @@ static int mtk_infrasys_init(struct plat + } + } + +- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), +- infra_clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, infra_clks, ++ ARRAY_SIZE(infra_clks), infra_clk_data); + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + +@@ -902,8 +902,8 @@ static int mtk_pericfg_init(struct platf + if (!clk_data) + return -ENOMEM; + +- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, peri_clks, ++ ARRAY_SIZE(peri_clks), clk_data); + + mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, + &mt2701_clk_lock, clk_data); +--- a/drivers/clk/mediatek/clk-mt2712-mm.c ++++ b/drivers/clk/mediatek/clk-mt2712-mm.c +@@ -117,8 +117,8 @@ static int clk_mt2712_mm_probe(struct pl + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + +- mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, mm_clks, ++ ARRAY_SIZE(mm_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +--- a/drivers/clk/mediatek/clk-mt2712.c ++++ b/drivers/clk/mediatek/clk-mt2712.c +@@ -1324,8 +1324,8 @@ static int clk_mt2712_top_probe(struct p + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt2712_clk_lock, top_clk_data); +- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), +- top_clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, top_clks, ++ ARRAY_SIZE(top_clks), top_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); + +@@ -1344,8 +1344,8 @@ static int clk_mt2712_infra_probe(struct + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + +- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, infra_clks, ++ ARRAY_SIZE(infra_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +@@ -1366,8 +1366,8 @@ static int clk_mt2712_peri_probe(struct + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + +- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, peri_clks, ++ ARRAY_SIZE(peri_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +--- a/drivers/clk/mediatek/clk-mt7622-aud.c ++++ b/drivers/clk/mediatek/clk-mt7622-aud.c +@@ -114,8 +114,8 @@ static int clk_mt7622_audiosys_init(stru + + clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); + +- mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, audio_clks, ++ ARRAY_SIZE(audio_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { +--- a/drivers/clk/mediatek/clk-mt7622-eth.c ++++ b/drivers/clk/mediatek/clk-mt7622-eth.c +@@ -69,8 +69,8 @@ static int clk_mt7622_ethsys_init(struct + + clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + +- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, eth_clks, ++ ARRAY_SIZE(eth_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -91,8 +91,8 @@ static int clk_mt7622_sgmiisys_init(stru + + clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + +- mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, sgmii_clks, ++ ARRAY_SIZE(sgmii_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt7622-hif.c ++++ b/drivers/clk/mediatek/clk-mt7622-hif.c +@@ -80,8 +80,8 @@ static int clk_mt7622_ssusbsys_init(stru + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + +- mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, ++ ARRAY_SIZE(ssusb_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -102,8 +102,8 @@ static int clk_mt7622_pciesys_init(struc + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + +- mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, pcie_clks, ++ ARRAY_SIZE(pcie_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt7622.c ++++ b/drivers/clk/mediatek/clk-mt7622.c +@@ -621,8 +621,8 @@ static int mtk_topckgen_init(struct plat + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt7622_clk_lock, clk_data); + +- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, top_clks, ++ ARRAY_SIZE(top_clks), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + } +@@ -635,8 +635,8 @@ static int mtk_infrasys_init(struct plat + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + +- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, infra_clks, ++ ARRAY_SIZE(infra_clks), clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); +@@ -663,7 +663,7 @@ static int mtk_apmixedsys_init(struct pl + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + +- mtk_clk_register_gates(node, apmixed_clks, ++ mtk_clk_register_gates(&pdev->dev, node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +@@ -682,8 +682,8 @@ static int mtk_pericfg_init(struct platf + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + +- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, peri_clks, ++ ARRAY_SIZE(peri_clks), clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7622_clk_lock, clk_data); +--- a/drivers/clk/mediatek/clk-mt7629-eth.c ++++ b/drivers/clk/mediatek/clk-mt7629-eth.c +@@ -82,7 +82,8 @@ static int clk_mt7629_ethsys_init(struct + if (!clk_data) + return -ENOMEM; + +- mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, eth_clks, ++ CLK_ETH_NR_CLK, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -106,8 +107,8 @@ static int clk_mt7629_sgmiisys_init(stru + if (!clk_data) + return -ENOMEM; + +- mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK, +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, sgmii_clks[id++], ++ CLK_SGMII_NR_CLK, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt7629-hif.c ++++ b/drivers/clk/mediatek/clk-mt7629-hif.c +@@ -75,8 +75,8 @@ static int clk_mt7629_ssusbsys_init(stru + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + +- mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, ++ ARRAY_SIZE(ssusb_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -97,8 +97,8 @@ static int clk_mt7629_pciesys_init(struc + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + +- mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, pcie_clks, ++ ARRAY_SIZE(pcie_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt7629.c ++++ b/drivers/clk/mediatek/clk-mt7629.c +@@ -585,8 +585,8 @@ static int mtk_infrasys_init(struct plat + if (!clk_data) + return -ENOMEM; + +- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, infra_clks, ++ ARRAY_SIZE(infra_clks), clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); +@@ -610,8 +610,8 @@ static int mtk_pericfg_init(struct platf + if (!clk_data) + return -ENOMEM; + +- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, peri_clks, ++ ARRAY_SIZE(peri_clks), clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7629_clk_lock, clk_data); +@@ -637,7 +637,7 @@ static int mtk_apmixedsys_init(struct pl + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + +- mtk_clk_register_gates(node, apmixed_clks, ++ mtk_clk_register_gates(&pdev->dev, node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); +--- a/drivers/clk/mediatek/clk-mt7986-eth.c ++++ b/drivers/clk/mediatek/clk-mt7986-eth.c +@@ -72,8 +72,8 @@ static void __init mtk_sgmiisys_0_init(s + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); + +- mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), +- clk_data); ++ mtk_clk_register_gates(NULL, node, sgmii0_clks, ++ ARRAY_SIZE(sgmii0_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -90,8 +90,8 @@ static void __init mtk_sgmiisys_1_init(s + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); + +- mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), +- clk_data); ++ mtk_clk_register_gates(NULL, node, sgmii1_clks, ++ ARRAY_SIZE(sgmii1_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +@@ -109,7 +109,7 @@ static void __init mtk_ethsys_init(struc + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); + +- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); ++ mtk_clk_register_gates(NULL, node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +--- a/drivers/clk/mediatek/clk-mt7986-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c +@@ -180,8 +180,8 @@ static int clk_mt7986_infracfg_probe(str + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); + mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, + &mt7986_clk_lock, clk_data); +- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), +- clk_data); ++ mtk_clk_register_gates(&pdev->dev, node, infra_clks, ++ ARRAY_SIZE(infra_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -459,8 +459,8 @@ int mtk_clk_simple_probe(struct platform + if (!clk_data) + return -ENOMEM; + +- r = mtk_clk_register_gates_with_dev(node, mcd->clks, mcd->num_clks, +- clk_data, &pdev->dev); ++ r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, mcd->num_clks, ++ clk_data); + if (r) + goto free_data; + diff --git a/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch b/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch new file mode 100644 index 0000000000..223155c59b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch @@ -0,0 +1,140 @@ +From b888303c7d23d7bd0c8667cfc657669e5d153fea Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:34 +0100 +Subject: [PATCH 02/15] clk: mediatek: cpumux: Propagate struct device where + possible + +Take a pointer to a struct device in mtk_clk_register_cpumuxes() and +propagate the same to mtk_clk_register_cpumux() => clk_hw_register(). +Even though runtime pm is unlikely to be used with CPU muxes, this +helps with code consistency and possibly opens to commonization of +some mtk_clk_register_(x) functions. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Markus Schneider-Pargmann +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-5-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-cpumux.c | 8 ++++---- + drivers/clk/mediatek/clk-cpumux.h | 2 +- + drivers/clk/mediatek/clk-mt2701.c | 2 +- + drivers/clk/mediatek/clk-mt6795-infracfg.c | 3 ++- + drivers/clk/mediatek/clk-mt7622.c | 4 ++-- + drivers/clk/mediatek/clk-mt7629.c | 4 ++-- + drivers/clk/mediatek/clk-mt8173.c | 4 ++-- + 7 files changed, 14 insertions(+), 13 deletions(-) + +--- a/drivers/clk/mediatek/clk-cpumux.c ++++ b/drivers/clk/mediatek/clk-cpumux.c +@@ -58,7 +58,7 @@ static const struct clk_ops clk_cpumux_o + }; + + static struct clk_hw * +-mtk_clk_register_cpumux(const struct mtk_composite *mux, ++mtk_clk_register_cpumux(struct device *dev, const struct mtk_composite *mux, + struct regmap *regmap) + { + struct mtk_clk_cpumux *cpumux; +@@ -81,7 +81,7 @@ mtk_clk_register_cpumux(const struct mtk + cpumux->regmap = regmap; + cpumux->hw.init = &init; + +- ret = clk_hw_register(NULL, &cpumux->hw); ++ ret = clk_hw_register(dev, &cpumux->hw); + if (ret) { + kfree(cpumux); + return ERR_PTR(ret); +@@ -102,7 +102,7 @@ static void mtk_clk_unregister_cpumux(st + kfree(cpumux); + } + +-int mtk_clk_register_cpumuxes(struct device_node *node, ++int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, + const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data) + { +@@ -125,7 +125,7 @@ int mtk_clk_register_cpumuxes(struct dev + continue; + } + +- hw = mtk_clk_register_cpumux(mux, regmap); ++ hw = mtk_clk_register_cpumux(dev, mux, regmap); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, + hw); +--- a/drivers/clk/mediatek/clk-cpumux.h ++++ b/drivers/clk/mediatek/clk-cpumux.h +@@ -11,7 +11,7 @@ struct clk_hw_onecell_data; + struct device_node; + struct mtk_composite; + +-int mtk_clk_register_cpumuxes(struct device_node *node, ++int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, + const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data); + +--- a/drivers/clk/mediatek/clk-mt2701.c ++++ b/drivers/clk/mediatek/clk-mt2701.c +@@ -761,7 +761,7 @@ static void __init mtk_infrasys_init_ear + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + +- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), ++ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, ARRAY_SIZE(cpu_muxes), + infra_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, +--- a/drivers/clk/mediatek/clk-mt6795-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c +@@ -105,7 +105,8 @@ static int clk_mt6795_infracfg_probe(str + if (ret) + goto free_clk_data; + +- ret = mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); ++ ret = mtk_clk_register_cpumuxes(&pdev->dev, node, cpu_muxes, ++ ARRAY_SIZE(cpu_muxes), clk_data); + if (ret) + goto unregister_gates; + +--- a/drivers/clk/mediatek/clk-mt7622.c ++++ b/drivers/clk/mediatek/clk-mt7622.c +@@ -638,8 +638,8 @@ static int mtk_infrasys_init(struct plat + mtk_clk_register_gates(&pdev->dev, node, infra_clks, + ARRAY_SIZE(infra_clks), clk_data); + +- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), +- clk_data); ++ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, ++ ARRAY_SIZE(infra_muxes), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); +--- a/drivers/clk/mediatek/clk-mt7629.c ++++ b/drivers/clk/mediatek/clk-mt7629.c +@@ -588,8 +588,8 @@ static int mtk_infrasys_init(struct plat + mtk_clk_register_gates(&pdev->dev, node, infra_clks, + ARRAY_SIZE(infra_clks), clk_data); + +- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), +- clk_data); ++ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, ++ ARRAY_SIZE(infra_muxes), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); +--- a/drivers/clk/mediatek/clk-mt8173.c ++++ b/drivers/clk/mediatek/clk-mt8173.c +@@ -892,8 +892,8 @@ static void __init mtk_infrasys_init(str + clk_data); + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); + +- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), +- clk_data); ++ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, ++ ARRAY_SIZE(cpu_muxes), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) diff --git a/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch b/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch new file mode 100644 index 0000000000..eca1b614cd --- /dev/null +++ b/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch @@ -0,0 +1,181 @@ +From f23375db001ec0fe9f565be75eff43adde15407e Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:35 +0100 +Subject: [PATCH 03/15] clk: mediatek: clk-mtk: Propagate struct device for + composites + +Like done for cpumux clocks, propagate struct device for composite +clocks registered through clk-mtk helpers to be able to get runtime +pm support for MTK clocks. + +Signed-off-by: AngeloGioacchino Del Regno +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-6-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd + +[daniel@makrotopia.org: remove parts not relevant for OpenWrt] +--- + drivers/clk/mediatek/clk-mt2701.c | 10 ++++++---- + drivers/clk/mediatek/clk-mt2712.c | 12 ++++++++---- + drivers/clk/mediatek/clk-mt7622.c | 8 +++++--- + drivers/clk/mediatek/clk-mt7629.c | 8 +++++--- + drivers/clk/mediatek/clk-mtk.c | 11 ++++++----- + drivers/clk/mediatek/clk-mtk.h | 3 ++- + 6 files changed, 32 insertions(+), 20 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt2701.c ++++ b/drivers/clk/mediatek/clk-mt2701.c +@@ -679,8 +679,9 @@ static int mtk_topckgen_init(struct plat + mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), + clk_data); + +- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), +- base, &mt2701_clk_lock, clk_data); ++ mtk_clk_register_composites(&pdev->dev, top_muxes, ++ ARRAY_SIZE(top_muxes), base, ++ &mt2701_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt2701_clk_lock, clk_data); +@@ -905,8 +906,9 @@ static int mtk_pericfg_init(struct platf + mtk_clk_register_gates(&pdev->dev, node, peri_clks, + ARRAY_SIZE(peri_clks), clk_data); + +- mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, +- &mt2701_clk_lock, clk_data); ++ mtk_clk_register_composites(&pdev->dev, peri_muxs, ++ ARRAY_SIZE(peri_muxs), base, ++ &mt2701_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +--- a/drivers/clk/mediatek/clk-mt2712.c ++++ b/drivers/clk/mediatek/clk-mt2712.c +@@ -1320,8 +1320,9 @@ static int clk_mt2712_top_probe(struct p + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); +- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, +- &mt2712_clk_lock, top_clk_data); ++ mtk_clk_register_composites(&pdev->dev, top_muxes, ++ ARRAY_SIZE(top_muxes), base, ++ &mt2712_clk_lock, top_clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_gates(&pdev->dev, node, top_clks, +@@ -1395,8 +1396,11 @@ static int clk_mt2712_mcu_probe(struct p + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + +- mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, +- &mt2712_clk_lock, clk_data); ++ r = mtk_clk_register_composites(&pdev->dev, mcu_muxes, ++ ARRAY_SIZE(mcu_muxes), base, ++ &mt2712_clk_lock, clk_data); ++ if (r) ++ dev_err(&pdev->dev, "Could not register composites: %d\n", r); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + +--- a/drivers/clk/mediatek/clk-mt7622.c ++++ b/drivers/clk/mediatek/clk-mt7622.c +@@ -615,8 +615,9 @@ static int mtk_topckgen_init(struct plat + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + +- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), +- base, &mt7622_clk_lock, clk_data); ++ mtk_clk_register_composites(&pdev->dev, top_muxes, ++ ARRAY_SIZE(top_muxes), base, ++ &mt7622_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt7622_clk_lock, clk_data); +@@ -685,7 +686,8 @@ static int mtk_pericfg_init(struct platf + mtk_clk_register_gates(&pdev->dev, node, peri_clks, + ARRAY_SIZE(peri_clks), clk_data); + +- mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, ++ mtk_clk_register_composites(&pdev->dev, peri_muxes, ++ ARRAY_SIZE(peri_muxes), base, + &mt7622_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +--- a/drivers/clk/mediatek/clk-mt7629.c ++++ b/drivers/clk/mediatek/clk-mt7629.c +@@ -566,8 +566,9 @@ static int mtk_topckgen_init(struct plat + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + +- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), +- base, &mt7629_clk_lock, clk_data); ++ mtk_clk_register_composites(&pdev->dev, top_muxes, ++ ARRAY_SIZE(top_muxes), base, ++ &mt7629_clk_lock, clk_data); + + clk_prepare_enable(clk_data->hws[CLK_TOP_AXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_MEM_SEL]->clk); +@@ -613,7 +614,8 @@ static int mtk_pericfg_init(struct platf + mtk_clk_register_gates(&pdev->dev, node, peri_clks, + ARRAY_SIZE(peri_clks), clk_data); + +- mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, ++ mtk_clk_register_composites(&pdev->dev, peri_muxes, ++ ARRAY_SIZE(peri_muxes), base, + &mt7629_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -197,8 +197,8 @@ void mtk_clk_unregister_factors(const st + } + EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); + +-static struct clk_hw *mtk_clk_register_composite(const struct mtk_composite *mc, +- void __iomem *base, spinlock_t *lock) ++static struct clk_hw *mtk_clk_register_composite(struct device *dev, ++ const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) + { + struct clk_hw *hw; + struct clk_mux *mux = NULL; +@@ -264,7 +264,7 @@ static struct clk_hw *mtk_clk_register_c + div_ops = &clk_divider_ops; + } + +- hw = clk_hw_register_composite(NULL, mc->name, parent_names, num_parents, ++ hw = clk_hw_register_composite(dev, mc->name, parent_names, num_parents, + mux_hw, mux_ops, + div_hw, div_ops, + gate_hw, gate_ops, +@@ -308,7 +308,8 @@ static void mtk_clk_unregister_composite + kfree(mux); + } + +-int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, ++int mtk_clk_register_composites(struct device *dev, ++ const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data) + { +@@ -327,7 +328,7 @@ int mtk_clk_register_composites(const st + continue; + } + +- hw = mtk_clk_register_composite(mc, base, lock); ++ hw = mtk_clk_register_composite(dev, mc, base, lock); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mc->name, +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -149,7 +149,8 @@ struct mtk_composite { + .flags = 0, \ + } + +-int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, ++int mtk_clk_register_composites(struct device *dev, ++ const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data); + void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, diff --git a/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch b/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch new file mode 100644 index 0000000000..a50422da58 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch @@ -0,0 +1,103 @@ +From 5d911479e4c732729bfa798e4a9e3e5aec3e30a7 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:36 +0100 +Subject: [PATCH 04/15] clk: mediatek: clk-mux: Propagate struct device for + mtk-mux + +Like done for other clocks, propagate struct device for mtk mux clocks +registered through clk-mux helpers to enable runtime pm support. + +Signed-off-by: AngeloGioacchino Del Regno +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-7-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd + +[daniel@makrotopia.org: removed parts not relevant for OpenWrt] +--- + drivers/clk/mediatek/clk-mt7986-infracfg.c | 3 ++- + drivers/clk/mediatek/clk-mt7986-topckgen.c | 3 ++- + drivers/clk/mediatek/clk-mux.c | 14 ++++++++------ + drivers/clk/mediatek/clk-mux.h | 3 ++- + 4 files changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt7986-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c +@@ -178,7 +178,8 @@ static int clk_mt7986_infracfg_probe(str + return -ENOMEM; + + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); +- mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, ++ mtk_clk_register_muxes(&pdev->dev, infra_muxes, ++ ARRAY_SIZE(infra_muxes), node, + &mt7986_clk_lock, clk_data); + mtk_clk_register_gates(&pdev->dev, node, infra_clks, + ARRAY_SIZE(infra_clks), clk_data); +--- a/drivers/clk/mediatek/clk-mt7986-topckgen.c ++++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c +@@ -303,7 +303,8 @@ static int clk_mt7986_topckgen_probe(str + 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, ++ mtk_clk_register_muxes(&pdev->dev, top_muxes, ++ ARRAY_SIZE(top_muxes), node, + &mt7986_clk_lock, clk_data); + + clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); +--- a/drivers/clk/mediatek/clk-mux.c ++++ b/drivers/clk/mediatek/clk-mux.c +@@ -154,9 +154,10 @@ const struct clk_ops mtk_mux_gate_clr_se + }; + EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops); + +-static struct clk_hw *mtk_clk_register_mux(const struct mtk_mux *mux, +- struct regmap *regmap, +- spinlock_t *lock) ++static struct clk_hw *mtk_clk_register_mux(struct device *dev, ++ const struct mtk_mux *mux, ++ struct regmap *regmap, ++ spinlock_t *lock) + { + struct mtk_clk_mux *clk_mux; + struct clk_init_data init = {}; +@@ -177,7 +178,7 @@ static struct clk_hw *mtk_clk_register_m + clk_mux->lock = lock; + clk_mux->hw.init = &init; + +- ret = clk_hw_register(NULL, &clk_mux->hw); ++ ret = clk_hw_register(dev, &clk_mux->hw); + if (ret) { + kfree(clk_mux); + return ERR_PTR(ret); +@@ -198,7 +199,8 @@ static void mtk_clk_unregister_mux(struc + kfree(mux); + } + +-int mtk_clk_register_muxes(const struct mtk_mux *muxes, ++int mtk_clk_register_muxes(struct device *dev, ++ const struct mtk_mux *muxes, + int num, struct device_node *node, + spinlock_t *lock, + struct clk_hw_onecell_data *clk_data) +@@ -222,7 +224,7 @@ int mtk_clk_register_muxes(const struct + continue; + } + +- hw = mtk_clk_register_mux(mux, regmap, lock); ++ hw = mtk_clk_register_mux(dev, mux, regmap, lock); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, +--- a/drivers/clk/mediatek/clk-mux.h ++++ b/drivers/clk/mediatek/clk-mux.h +@@ -83,7 +83,8 @@ extern const struct clk_ops mtk_mux_gate + 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \ + mtk_mux_clr_set_upd_ops) + +-int mtk_clk_register_muxes(const struct mtk_mux *muxes, ++int mtk_clk_register_muxes(struct device *dev, ++ const struct mtk_mux *muxes, + int num, struct device_node *node, + spinlock_t *lock, + struct clk_hw_onecell_data *clk_data); diff --git a/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch b/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch new file mode 100644 index 0000000000..de2e6976c3 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch @@ -0,0 +1,74 @@ +From b8eb1081d267708ba976525a1fe2162901b34f3a Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:37 +0100 +Subject: [PATCH] clk: mediatek: clk-mtk: Add dummy clock ops + +In order to migrate some (few) old clock drivers to the common +mtk_clk_simple_probe() function, add dummy clock ops to be able +to insert a dummy clock with ID 0 at the beginning of the list. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Miles Chen +Reviewed-by: Chen-Yu Tsai +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-8-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-mtk.c | 16 ++++++++++++++++ + drivers/clk/mediatek/clk-mtk.h | 19 +++++++++++++++++++ + 2 files changed, 35 insertions(+) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -18,6 +18,22 @@ + #include "clk-mtk.h" + #include "clk-gate.h" + ++const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; ++EXPORT_SYMBOL_GPL(cg_regs_dummy); ++ ++static int mtk_clk_dummy_enable(struct clk_hw *hw) ++{ ++ return 0; ++} ++ ++static void mtk_clk_dummy_disable(struct clk_hw *hw) { } ++ ++const struct clk_ops mtk_clk_dummy_ops = { ++ .enable = mtk_clk_dummy_enable, ++ .disable = mtk_clk_dummy_disable, ++}; ++EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops); ++ + static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data, + unsigned int clk_num) + { +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -22,6 +22,25 @@ + + struct platform_device; + ++/* ++ * We need the clock IDs to start from zero but to maintain devicetree ++ * backwards compatibility we can't change bindings to start from zero. ++ * Only a few platforms are affected, so we solve issues given by the ++ * commonized MTK clocks probe function(s) by adding a dummy clock at ++ * the beginning where needed. ++ */ ++#define CLK_DUMMY 0 ++ ++extern const struct clk_ops mtk_clk_dummy_ops; ++extern const struct mtk_gate_regs cg_regs_dummy; ++ ++#define GATE_DUMMY(_id, _name) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .regs = &cg_regs_dummy, \ ++ .ops = &mtk_clk_dummy_ops, \ ++ } ++ + struct mtk_fixed_clk { + int id; + const char *name; diff --git a/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch b/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch new file mode 100644 index 0000000000..becfcd0ed8 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch @@ -0,0 +1,790 @@ +From c26e28015b74af73e0b299f6ad3ff22931e600b4 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:41 +0100 +Subject: [PATCH 05/15] clk: mediatek: Switch to mtk_clk_simple_probe() where + possible + +mtk_clk_simple_probe() is a function that registers mtk gate clocks +and, if reset data is present, a reset controller and across all of +the MTK clock drivers, such a function is duplicated many times: +switch to the common mtk_clk_simple_probe() function for all of the +clock drivers that are registering as platform drivers. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Miles Chen +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-12-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd + +[daniel@makrotopia.org: removed parts not relevant for OpenWrt] +--- + drivers/clk/mediatek/clk-mt2701-aud.c | 31 ++++++---- + drivers/clk/mediatek/clk-mt2701-eth.c | 36 ++++-------- + drivers/clk/mediatek/clk-mt2701-g3d.c | 56 ++++-------------- + drivers/clk/mediatek/clk-mt2701-hif.c | 38 ++++-------- + drivers/clk/mediatek/clk-mt2712.c | 83 ++++++++++---------------- + drivers/clk/mediatek/clk-mt7622-aud.c | 54 ++++++----------- + drivers/clk/mediatek/clk-mt7622-eth.c | 82 +++++--------------------- + drivers/clk/mediatek/clk-mt7622-hif.c | 85 +++++---------------------- + drivers/clk/mediatek/clk-mt7629-hif.c | 85 +++++---------------------- + 9 files changed, 144 insertions(+), 406 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt2701-aud.c ++++ b/drivers/clk/mediatek/clk-mt2701-aud.c +@@ -52,6 +52,7 @@ static const struct mtk_gate_regs audio3 + }; + + static const struct mtk_gate audio_clks[] = { ++ GATE_DUMMY(CLK_DUMMY, "aud_dummy"), + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2), + GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20), +@@ -114,29 +115,27 @@ static const struct mtk_gate audio_clks[ + GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), + }; + ++static const struct mtk_clk_desc audio_desc = { ++ .clks = audio_clks, ++ .num_clks = ARRAY_SIZE(audio_clks), ++}; ++ + static const struct of_device_id of_match_clk_mt2701_aud[] = { +- { .compatible = "mediatek,mt2701-audsys", }, +- {} ++ { .compatible = "mediatek,mt2701-audsys", .data = &audio_desc }, ++ { /* sentinel */ } + }; + + static int clk_mt2701_aud_probe(struct platform_device *pdev) + { +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; + int r; + +- clk_data = mtk_alloc_clk_data(CLK_AUD_NR); +- +- mtk_clk_register_gates(&pdev->dev, node, audio_clks, +- ARRAY_SIZE(audio_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ++ r = mtk_clk_simple_probe(pdev); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + +- goto err_clk_provider; ++ return r; + } + + r = devm_of_platform_populate(&pdev->dev); +@@ -146,13 +145,19 @@ static int clk_mt2701_aud_probe(struct p + return 0; + + err_plat_populate: +- of_clk_del_provider(node); +-err_clk_provider: ++ mtk_clk_simple_remove(pdev); + return r; + } + ++static int clk_mt2701_aud_remove(struct platform_device *pdev) ++{ ++ of_platform_depopulate(&pdev->dev); ++ return mtk_clk_simple_remove(pdev); ++} ++ + static struct platform_driver clk_mt2701_aud_drv = { + .probe = clk_mt2701_aud_probe, ++ .remove = clk_mt2701_aud_remove, + .driver = { + .name = "clk-mt2701-aud", + .of_match_table = of_match_clk_mt2701_aud, +--- a/drivers/clk/mediatek/clk-mt2701-eth.c ++++ b/drivers/clk/mediatek/clk-mt2701-eth.c +@@ -20,6 +20,7 @@ static const struct mtk_gate_regs eth_cg + GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + + static const struct mtk_gate eth_clks[] = { ++ GATE_DUMMY(CLK_DUMMY, "eth_dummy"), + GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5), + GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6), + GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7), +@@ -38,35 +39,20 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static const struct of_device_id of_match_clk_mt2701_eth[] = { +- { .compatible = "mediatek,mt2701-ethsys", }, +- {} ++static const struct mtk_clk_desc eth_desc = { ++ .clks = eth_clks, ++ .num_clks = ARRAY_SIZE(eth_clks), ++ .rst_desc = &clk_rst_desc, + }; + +-static int clk_mt2701_eth_probe(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- int r; +- struct device_node *node = pdev->dev.of_node; +- +- clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); +- +- mtk_clk_register_gates(&pdev->dev, node, eth_clks, +- ARRAY_SIZE(eth_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return r; +-} ++static const struct of_device_id of_match_clk_mt2701_eth[] = { ++ { .compatible = "mediatek,mt2701-ethsys", .data = ð_desc }, ++ { /* sentinel */ } ++}; + + static struct platform_driver clk_mt2701_eth_drv = { +- .probe = clk_mt2701_eth_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-eth", + .of_match_table = of_match_clk_mt2701_eth, +--- a/drivers/clk/mediatek/clk-mt2701-g3d.c ++++ b/drivers/clk/mediatek/clk-mt2701-g3d.c +@@ -26,6 +26,7 @@ static const struct mtk_gate_regs g3d_cg + }; + + static const struct mtk_gate g3d_clks[] = { ++ GATE_DUMMY(CLK_DUMMY, "g3d_dummy"), + GATE_G3D(CLK_G3DSYS_CORE, "g3d_core", "mfg_sel", 0), + }; + +@@ -37,57 +38,20 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static int clk_mt2701_g3dsys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); +- +- mtk_clk_register_gates(&pdev->dev, node, g3d_clks, ARRAY_SIZE(g3d_clks), +- clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return r; +-} ++static const struct mtk_clk_desc g3d_desc = { ++ .clks = g3d_clks, ++ .num_clks = ARRAY_SIZE(g3d_clks), ++ .rst_desc = &clk_rst_desc, ++}; + + static const struct of_device_id of_match_clk_mt2701_g3d[] = { +- { +- .compatible = "mediatek,mt2701-g3dsys", +- .data = clk_mt2701_g3dsys_init, +- }, { +- /* sentinel */ +- } ++ { .compatible = "mediatek,mt2701-g3dsys", .data = &g3d_desc }, ++ { /* sentinel */ } + }; + +-static int clk_mt2701_g3d_probe(struct platform_device *pdev) +-{ +- int (*clk_init)(struct platform_device *); +- int r; +- +- clk_init = of_device_get_match_data(&pdev->dev); +- if (!clk_init) +- return -EINVAL; +- +- r = clk_init(pdev); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- return r; +-} +- + static struct platform_driver clk_mt2701_g3d_drv = { +- .probe = clk_mt2701_g3d_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-g3d", + .of_match_table = of_match_clk_mt2701_g3d, +--- a/drivers/clk/mediatek/clk-mt2701-hif.c ++++ b/drivers/clk/mediatek/clk-mt2701-hif.c +@@ -20,6 +20,7 @@ static const struct mtk_gate_regs hif_cg + GATE_MTK(_id, _name, _parent, &hif_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + + static const struct mtk_gate hif_clks[] = { ++ GATE_DUMMY(CLK_DUMMY, "hif_dummy"), + GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21), + GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22), + GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24), +@@ -35,37 +36,20 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static const struct of_device_id of_match_clk_mt2701_hif[] = { +- { .compatible = "mediatek,mt2701-hifsys", }, +- {} ++static const struct mtk_clk_desc hif_desc = { ++ .clks = hif_clks, ++ .num_clks = ARRAY_SIZE(hif_clks), ++ .rst_desc = &clk_rst_desc, + }; + +-static int clk_mt2701_hif_probe(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- int r; +- struct device_node *node = pdev->dev.of_node; +- +- clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); +- +- mtk_clk_register_gates(&pdev->dev, node, hif_clks, +- ARRAY_SIZE(hif_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) { +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- return r; +- } +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return 0; +-} ++static const struct of_device_id of_match_clk_mt2701_hif[] = { ++ { .compatible = "mediatek,mt2701-hifsys", .data = &hif_desc }, ++ { /* sentinel */ } ++}; + + static struct platform_driver clk_mt2701_hif_drv = { +- .probe = clk_mt2701_hif_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-hif", + .of_match_table = of_match_clk_mt2701_hif, +--- a/drivers/clk/mediatek/clk-mt2712.c ++++ b/drivers/clk/mediatek/clk-mt2712.c +@@ -1337,50 +1337,6 @@ static int clk_mt2712_top_probe(struct p + return r; + } + +-static int clk_mt2712_infra_probe(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- int r; +- struct device_node *node = pdev->dev.of_node; +- +- clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, infra_clks, +- ARRAY_SIZE(infra_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- +- if (r != 0) +- pr_err("%s(): could not register clock provider: %d\n", +- __func__, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); +- +- return r; +-} +- +-static int clk_mt2712_peri_probe(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- int r; +- struct device_node *node = pdev->dev.of_node; +- +- clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, peri_clks, +- ARRAY_SIZE(peri_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- +- if (r != 0) +- pr_err("%s(): could not register clock provider: %d\n", +- __func__, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); +- +- return r; +-} +- + static int clk_mt2712_mcu_probe(struct platform_device *pdev) + { + struct clk_hw_onecell_data *clk_data; +@@ -1419,12 +1375,6 @@ static const struct of_device_id of_matc + .compatible = "mediatek,mt2712-topckgen", + .data = clk_mt2712_top_probe, + }, { +- .compatible = "mediatek,mt2712-infracfg", +- .data = clk_mt2712_infra_probe, +- }, { +- .compatible = "mediatek,mt2712-pericfg", +- .data = clk_mt2712_peri_probe, +- }, { + .compatible = "mediatek,mt2712-mcucfg", + .data = clk_mt2712_mcu_probe, + }, { +@@ -1450,6 +1400,33 @@ static int clk_mt2712_probe(struct platf + return r; + } + ++static const struct mtk_clk_desc infra_desc = { ++ .clks = infra_clks, ++ .num_clks = ARRAY_SIZE(infra_clks), ++ .rst_desc = &clk_rst_desc[0], ++}; ++ ++static const struct mtk_clk_desc peri_desc = { ++ .clks = peri_clks, ++ .num_clks = ARRAY_SIZE(peri_clks), ++ .rst_desc = &clk_rst_desc[1], ++}; ++ ++static const struct of_device_id of_match_clk_mt2712_simple[] = { ++ { .compatible = "mediatek,mt2712-infracfg", .data = &infra_desc }, ++ { .compatible = "mediatek,mt2712-pericfg", .data = &peri_desc, }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver clk_mt2712_simple_drv = { ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++ .driver = { ++ .name = "clk-mt2712-simple", ++ .of_match_table = of_match_clk_mt2712_simple, ++ }, ++}; ++ + static struct platform_driver clk_mt2712_drv = { + .probe = clk_mt2712_probe, + .driver = { +@@ -1460,7 +1437,11 @@ static struct platform_driver clk_mt2712 + + static int __init clk_mt2712_init(void) + { +- return platform_driver_register(&clk_mt2712_drv); ++ int ret = platform_driver_register(&clk_mt2712_drv); ++ ++ if (ret) ++ return ret; ++ return platform_driver_register(&clk_mt2712_simple_drv); + } + + arch_initcall(clk_mt2712_init); +--- a/drivers/clk/mediatek/clk-mt7622-aud.c ++++ b/drivers/clk/mediatek/clk-mt7622-aud.c +@@ -106,24 +106,22 @@ static const struct mtk_gate audio_clks[ + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), + }; + +-static int clk_mt7622_audiosys_init(struct platform_device *pdev) ++static const struct mtk_clk_desc audio_desc = { ++ .clks = audio_clks, ++ .num_clks = ARRAY_SIZE(audio_clks), ++}; ++ ++static int clk_mt7622_aud_probe(struct platform_device *pdev) + { +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; + int r; + +- clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, audio_clks, +- ARRAY_SIZE(audio_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ++ r = mtk_clk_simple_probe(pdev); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + +- goto err_clk_provider; ++ return r; + } + + r = devm_of_platform_populate(&pdev->dev); +@@ -133,40 +131,24 @@ static int clk_mt7622_audiosys_init(stru + return 0; + + err_plat_populate: +- of_clk_del_provider(node); +-err_clk_provider: ++ mtk_clk_simple_remove(pdev); + return r; + } + +-static const struct of_device_id of_match_clk_mt7622_aud[] = { +- { +- .compatible = "mediatek,mt7622-audsys", +- .data = clk_mt7622_audiosys_init, +- }, { +- /* sentinel */ +- } +-}; +- +-static int clk_mt7622_aud_probe(struct platform_device *pdev) ++static int clk_mt7622_aud_remove(struct platform_device *pdev) + { +- int (*clk_init)(struct platform_device *); +- int r; +- +- clk_init = of_device_get_match_data(&pdev->dev); +- if (!clk_init) +- return -EINVAL; +- +- r = clk_init(pdev); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- return r; ++ of_platform_depopulate(&pdev->dev); ++ return mtk_clk_simple_remove(pdev); + } + ++static const struct of_device_id of_match_clk_mt7622_aud[] = { ++ { .compatible = "mediatek,mt7622-audsys", .data = &audio_desc }, ++ { /* sentinel */ } ++}; ++ + static struct platform_driver clk_mt7622_aud_drv = { + .probe = clk_mt7622_aud_probe, ++ .remove = clk_mt7622_aud_remove, + .driver = { + .name = "clk-mt7622-aud", + .of_match_table = of_match_clk_mt7622_aud, +--- a/drivers/clk/mediatek/clk-mt7622-eth.c ++++ b/drivers/clk/mediatek/clk-mt7622-eth.c +@@ -61,80 +61,26 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static int clk_mt7622_ethsys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, eth_clks, +- ARRAY_SIZE(eth_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return r; +-} +- +-static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, sgmii_clks, +- ARRAY_SIZE(sgmii_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); ++static const struct mtk_clk_desc eth_desc = { ++ .clks = eth_clks, ++ .num_clks = ARRAY_SIZE(eth_clks), ++ .rst_desc = &clk_rst_desc, ++}; + +- return r; +-} ++static const struct mtk_clk_desc sgmii_desc = { ++ .clks = sgmii_clks, ++ .num_clks = ARRAY_SIZE(sgmii_clks), ++}; + + static const struct of_device_id of_match_clk_mt7622_eth[] = { +- { +- .compatible = "mediatek,mt7622-ethsys", +- .data = clk_mt7622_ethsys_init, +- }, { +- .compatible = "mediatek,mt7622-sgmiisys", +- .data = clk_mt7622_sgmiisys_init, +- }, { +- /* sentinel */ +- } ++ { .compatible = "mediatek,mt7622-ethsys", .data = ð_desc }, ++ { .compatible = "mediatek,mt7622-sgmiisys", .data = &sgmii_desc }, ++ { /* sentinel */ } + }; + +-static int clk_mt7622_eth_probe(struct platform_device *pdev) +-{ +- int (*clk_init)(struct platform_device *); +- int r; +- +- clk_init = of_device_get_match_data(&pdev->dev); +- if (!clk_init) +- return -EINVAL; +- +- r = clk_init(pdev); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- return r; +-} +- + static struct platform_driver clk_mt7622_eth_drv = { +- .probe = clk_mt7622_eth_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt7622-eth", + .of_match_table = of_match_clk_mt7622_eth, +--- a/drivers/clk/mediatek/clk-mt7622-hif.c ++++ b/drivers/clk/mediatek/clk-mt7622-hif.c +@@ -72,82 +72,27 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, +- ARRAY_SIZE(ssusb_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return r; +-} +- +-static int clk_mt7622_pciesys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, +- ARRAY_SIZE(pcie_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); ++static const struct mtk_clk_desc ssusb_desc = { ++ .clks = ssusb_clks, ++ .num_clks = ARRAY_SIZE(ssusb_clks), ++ .rst_desc = &clk_rst_desc, ++}; + +- return r; +-} ++static const struct mtk_clk_desc pcie_desc = { ++ .clks = pcie_clks, ++ .num_clks = ARRAY_SIZE(pcie_clks), ++ .rst_desc = &clk_rst_desc, ++}; + + static const struct of_device_id of_match_clk_mt7622_hif[] = { +- { +- .compatible = "mediatek,mt7622-pciesys", +- .data = clk_mt7622_pciesys_init, +- }, { +- .compatible = "mediatek,mt7622-ssusbsys", +- .data = clk_mt7622_ssusbsys_init, +- }, { +- /* sentinel */ +- } ++ { .compatible = "mediatek,mt7622-pciesys", .data = &pcie_desc }, ++ { .compatible = "mediatek,mt7622-ssusbsys", .data = &ssusb_desc }, ++ { /* sentinel */ } + }; + +-static int clk_mt7622_hif_probe(struct platform_device *pdev) +-{ +- int (*clk_init)(struct platform_device *); +- int r; +- +- clk_init = of_device_get_match_data(&pdev->dev); +- if (!clk_init) +- return -EINVAL; +- +- r = clk_init(pdev); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- return r; +-} +- + static struct platform_driver clk_mt7622_hif_drv = { +- .probe = clk_mt7622_hif_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt7622-hif", + .of_match_table = of_match_clk_mt7622_hif, +--- a/drivers/clk/mediatek/clk-mt7629-hif.c ++++ b/drivers/clk/mediatek/clk-mt7629-hif.c +@@ -67,82 +67,27 @@ static const struct mtk_clk_rst_desc clk + .rst_bank_nr = ARRAY_SIZE(rst_ofs), + }; + +-static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, +- ARRAY_SIZE(ssusb_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); +- +- return r; +-} +- +-static int clk_mt7629_pciesys_init(struct platform_device *pdev) +-{ +- struct clk_hw_onecell_data *clk_data; +- struct device_node *node = pdev->dev.of_node; +- int r; +- +- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); +- +- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, +- ARRAY_SIZE(pcie_clks), clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); ++static const struct mtk_clk_desc ssusb_desc = { ++ .clks = ssusb_clks, ++ .num_clks = ARRAY_SIZE(ssusb_clks), ++ .rst_desc = &clk_rst_desc, ++}; + +- return r; +-} ++static const struct mtk_clk_desc pcie_desc = { ++ .clks = pcie_clks, ++ .num_clks = ARRAY_SIZE(pcie_clks), ++ .rst_desc = &clk_rst_desc, ++}; + + static const struct of_device_id of_match_clk_mt7629_hif[] = { +- { +- .compatible = "mediatek,mt7629-pciesys", +- .data = clk_mt7629_pciesys_init, +- }, { +- .compatible = "mediatek,mt7629-ssusbsys", +- .data = clk_mt7629_ssusbsys_init, +- }, { +- /* sentinel */ +- } ++ { .compatible = "mediatek,mt7629-pciesys", .data = &pcie_desc }, ++ { .compatible = "mediatek,mt7629-ssusbsys", .data = &ssusb_desc }, ++ { /* sentinel */ } + }; + +-static int clk_mt7629_hif_probe(struct platform_device *pdev) +-{ +- int (*clk_init)(struct platform_device *); +- int r; +- +- clk_init = of_device_get_match_data(&pdev->dev); +- if (!clk_init) +- return -EINVAL; +- +- r = clk_init(pdev); +- if (r) +- dev_err(&pdev->dev, +- "could not register clock provider: %s: %d\n", +- pdev->name, r); +- +- return r; +-} +- + static struct platform_driver clk_mt7629_hif_drv = { +- .probe = clk_mt7629_hif_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt7629-hif", + .of_match_table = of_match_clk_mt7629_hif, diff --git a/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch b/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch new file mode 100644 index 0000000000..ad02df10b6 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch @@ -0,0 +1,189 @@ +From 7b6183108c8ccf0dc295f39cdf78bd8078455636 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:42 +0100 +Subject: [PATCH] clk: mediatek: clk-mtk: Extend mtk_clk_simple_probe() + +As a preparation to increase probe functions commonization across +various MediaTek SoC clock controller drivers, extend function +mtk_clk_simple_probe() to be able to register not only gates, but +also fixed clocks, factors, muxes and composites. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Miles Chen +Reviewed-by: Chen-Yu Tsai +Tested-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-13-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-mtk.c | 101 ++++++++++++++++++++++++++++++--- + drivers/clk/mediatek/clk-mtk.h | 10 ++++ + 2 files changed, 103 insertions(+), 8 deletions(-) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -11,12 +11,14 @@ + #include + #include + #include ++#include + #include + #include + #include + + #include "clk-mtk.h" + #include "clk-gate.h" ++#include "clk-mux.h" + + const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; + EXPORT_SYMBOL_GPL(cg_regs_dummy); +@@ -466,20 +468,71 @@ int mtk_clk_simple_probe(struct platform + const struct mtk_clk_desc *mcd; + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; +- int r; ++ void __iomem *base; ++ int num_clks, r; + + mcd = of_device_get_match_data(&pdev->dev); + if (!mcd) + return -EINVAL; + +- clk_data = mtk_alloc_clk_data(mcd->num_clks); ++ /* Composite clocks needs us to pass iomem pointer */ ++ if (mcd->composite_clks) { ++ if (!mcd->shared_io) ++ base = devm_platform_ioremap_resource(pdev, 0); ++ else ++ base = of_iomap(node, 0); ++ ++ if (IS_ERR_OR_NULL(base)) ++ return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM; ++ } ++ ++ /* Calculate how many clk_hw_onecell_data entries to allocate */ ++ num_clks = mcd->num_clks + mcd->num_composite_clks; ++ num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; ++ num_clks += mcd->num_mux_clks; ++ ++ clk_data = mtk_alloc_clk_data(num_clks); + if (!clk_data) + return -ENOMEM; + +- r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, mcd->num_clks, +- clk_data); +- if (r) +- goto free_data; ++ if (mcd->fixed_clks) { ++ r = mtk_clk_register_fixed_clks(mcd->fixed_clks, ++ mcd->num_fixed_clks, clk_data); ++ if (r) ++ goto free_data; ++ } ++ ++ if (mcd->factor_clks) { ++ r = mtk_clk_register_factors(mcd->factor_clks, ++ mcd->num_factor_clks, clk_data); ++ if (r) ++ goto unregister_fixed_clks; ++ } ++ ++ if (mcd->mux_clks) { ++ r = mtk_clk_register_muxes(&pdev->dev, mcd->mux_clks, ++ mcd->num_mux_clks, node, ++ mcd->clk_lock, clk_data); ++ if (r) ++ goto unregister_factors; ++ }; ++ ++ if (mcd->composite_clks) { ++ /* We don't check composite_lock because it's optional */ ++ r = mtk_clk_register_composites(&pdev->dev, ++ mcd->composite_clks, ++ mcd->num_composite_clks, ++ base, mcd->clk_lock, clk_data); ++ if (r) ++ goto unregister_muxes; ++ } ++ ++ if (mcd->clks) { ++ r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, ++ mcd->num_clks, clk_data); ++ if (r) ++ goto unregister_composites; ++ } + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -497,9 +550,28 @@ int mtk_clk_simple_probe(struct platform + return r; + + unregister_clks: +- mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); ++ if (mcd->clks) ++ mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); ++unregister_composites: ++ if (mcd->composite_clks) ++ mtk_clk_unregister_composites(mcd->composite_clks, ++ mcd->num_composite_clks, clk_data); ++unregister_muxes: ++ if (mcd->mux_clks) ++ mtk_clk_unregister_muxes(mcd->mux_clks, ++ mcd->num_mux_clks, clk_data); ++unregister_factors: ++ if (mcd->factor_clks) ++ mtk_clk_unregister_factors(mcd->factor_clks, ++ mcd->num_factor_clks, clk_data); ++unregister_fixed_clks: ++ if (mcd->fixed_clks) ++ mtk_clk_unregister_fixed_clks(mcd->fixed_clks, ++ mcd->num_fixed_clks, clk_data); + free_data: + mtk_free_clk_data(clk_data); ++ if (mcd->shared_io && base) ++ iounmap(base); + return r; + } + EXPORT_SYMBOL_GPL(mtk_clk_simple_probe); +@@ -511,7 +583,20 @@ int mtk_clk_simple_remove(struct platfor + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); +- mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); ++ if (mcd->clks) ++ mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); ++ if (mcd->composite_clks) ++ mtk_clk_unregister_composites(mcd->composite_clks, ++ mcd->num_composite_clks, clk_data); ++ if (mcd->mux_clks) ++ mtk_clk_unregister_muxes(mcd->mux_clks, ++ mcd->num_mux_clks, clk_data); ++ if (mcd->factor_clks) ++ mtk_clk_unregister_factors(mcd->factor_clks, ++ mcd->num_factor_clks, clk_data); ++ if (mcd->fixed_clks) ++ mtk_clk_unregister_fixed_clks(mcd->fixed_clks, ++ mcd->num_fixed_clks, clk_data); + mtk_free_clk_data(clk_data); + + return 0; +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -215,7 +215,17 @@ void mtk_clk_unregister_ref2usb_tx(struc + struct mtk_clk_desc { + const struct mtk_gate *clks; + size_t num_clks; ++ const struct mtk_composite *composite_clks; ++ size_t num_composite_clks; ++ const struct mtk_fixed_clk *fixed_clks; ++ size_t num_fixed_clks; ++ const struct mtk_fixed_factor *factor_clks; ++ size_t num_factor_clks; ++ const struct mtk_mux *mux_clks; ++ size_t num_mux_clks; + const struct mtk_clk_rst_desc *rst_desc; ++ spinlock_t *clk_lock; ++ bool shared_io; + }; + + int mtk_clk_simple_probe(struct platform_device *pdev); diff --git a/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch b/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch new file mode 100644 index 0000000000..bf9a172926 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch @@ -0,0 +1,97 @@ +From 3511004225ce917a4aa6e6ac61481ac60f08f401 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:52 +0100 +Subject: [PATCH 06/15] clk: mediatek: clk-mt7986-topckgen: Properly keep some + clocks enabled + +Instead of calling clk_prepare_enable() on a bunch of clocks at probe +time, set the CLK_IS_CRITICAL flag to the same as these are required +to be always on, and this is the right way of achieving that. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Miles Chen +Link: https://lore.kernel.org/r/20230120092053.182923-23-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-mt7986-topckgen.c | 46 +++++++++++----------- + 1 file changed, 24 insertions(+), 22 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt7986-topckgen.c ++++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c +@@ -202,16 +202,23 @@ static const struct mtk_mux top_muxes[] + MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", + f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, + 0x1C0, 10), +- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, +- 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", ++ f_26m_adc_parents, 0x020, 0x024, 0x028, ++ 24, 1, 31, 0x1C0, 11, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + /* CLK_CFG_3 */ +- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", +- dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, +- 0x1C0, 12), +- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, +- 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), +- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, +- 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", ++ dramc_md32_parents, 0x030, 0x034, 0x038, ++ 0, 1, 7, 0x1C0, 12, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", ++ sysaxi_parents, 0x030, 0x034, 0x038, ++ 8, 2, 15, 0x1C0, 13, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", ++ sysapb_parents, 0x030, 0x034, 0x038, ++ 16, 2, 23, 0x1C0, 14, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", + arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, + 31, 0x1C0, 15), +@@ -234,9 +241,10 @@ static const struct mtk_mux top_muxes[] + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", + sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, + 0x1C0, 21), +- MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", +- sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, +- 0x1C0, 22), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", ++ sgm_reg_parents, 0x050, 0x054, 0x058, ++ 16, 1, 23, 0x1C0, 22, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, + 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), + /* CLK_CFG_6 */ +@@ -252,9 +260,10 @@ static const struct mtk_mux top_muxes[] + f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, + 0x1C0, 27), + /* CLK_CFG_7 */ +- MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", +- f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, +- 0x1C0, 28), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", ++ f_26m_adc_parents, 0x070, 0x074, 0x078, ++ 0, 1, 7, 0x1C0, 28, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, + 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", +@@ -307,13 +316,6 @@ static int clk_mt7986_topckgen_probe(str + ARRAY_SIZE(top_muxes), node, + &mt7986_clk_lock, clk_data); + +- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); +- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAPB_SEL]->clk); +- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_SEL]->clk); +- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_MD32_SEL]->clk); +- clk_prepare_enable(clk_data->hws[CLK_TOP_F26M_SEL]->clk); +- clk_prepare_enable(clk_data->hws[CLK_TOP_SGM_REG_SEL]->clk); +- + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) { diff --git a/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch b/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch new file mode 100644 index 0000000000..d77b859f00 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch @@ -0,0 +1,88 @@ +From 9ce3b4e4719d4eec38b2c8da939c073835573d1d Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 20 Jan 2023 10:20:53 +0100 +Subject: [PATCH 07/15] clk: mediatek: clk-mt7986-topckgen: Migrate to + mtk_clk_simple_probe() + +There are no more non-common calls in clk_mt7986_topckgen_probe(): +migrate this driver to mtk_clk_simple_probe(). + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Miles Chen +Reviewed-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20230120092053.182923-24-angelogioacchino.delregno@collabora.com +Tested-by: Mingming Su +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-mt7986-topckgen.c | 55 +++++----------------- + 1 file changed, 13 insertions(+), 42 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt7986-topckgen.c ++++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c +@@ -290,53 +290,24 @@ static const struct mtk_mux top_muxes[] + 0x1C4, 5), + }; + +-static int clk_mt7986_topckgen_probe(struct platform_device *pdev) +-{ +- struct clk_hw_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); +- +- 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(&pdev->dev, top_muxes, +- ARRAY_SIZE(top_muxes), node, +- &mt7986_clk_lock, clk_data); +- +- r = of_clk_add_hw_provider(node, of_clk_hw_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 struct mtk_clk_desc topck_desc = { ++ .fixed_clks = top_fixed_clks, ++ .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), ++ .factor_clks = top_divs, ++ .num_factor_clks = ARRAY_SIZE(top_divs), ++ .mux_clks = top_muxes, ++ .num_mux_clks = ARRAY_SIZE(top_muxes), ++ .clk_lock = &mt7986_clk_lock, ++}; + + static const struct of_device_id of_match_clk_mt7986_topckgen[] = { +- { .compatible = "mediatek,mt7986-topckgen", }, +- {} ++ { .compatible = "mediatek,mt7986-topckgen", .data = &topck_desc }, ++ { /* sentinel */ } + }; + + static struct platform_driver clk_mt7986_topckgen_drv = { +- .probe = clk_mt7986_topckgen_probe, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt7986-topckgen", + .of_match_table = of_match_clk_mt7986_topckgen, diff --git a/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch b/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch new file mode 100644 index 0000000000..a47dd4b053 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch @@ -0,0 +1,38 @@ +From 06abdc84080729dc2c54946e1712c5ee1589ca1c Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Mon, 6 Mar 2023 15:05:21 +0100 +Subject: [PATCH 13/15] clk: mediatek: mt7986-apmixed: Use PLL_AO flag to set + critical clock + +Instead of calling clk_prepare_enable() at probe time, add the PLL_AO +flag to CLK_APMIXED_ARMPLL clock: this will set CLK_IS_CRITICAL. + +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Tested-by: Daniel Golle +Link: https://lore.kernel.org/r/20230306140543.1813621-33-angelogioacchino.delregno@collabora.com +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-mt7986-apmixed.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt7986-apmixed.c ++++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c +@@ -42,7 +42,7 @@ + "clkxtal") + + static const struct mtk_pll_data plls[] = { +- PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, 0, 32, ++ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, PLL_AO, 32, + 0x0200, 4, 0, 0x0204, 0), + PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x0, 0, 32, + 0x0210, 4, 0, 0x0214, 0), +@@ -77,8 +77,6 @@ static int clk_mt7986_apmixed_probe(stru + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + +- clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); +- + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", diff --git a/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch b/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch new file mode 100644 index 0000000000..ae76940e1d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch @@ -0,0 +1,237 @@ +From a6473d0f9f07b1196f3a67099826f50a2a4e84e8 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 26 Jan 2023 03:34:05 +0000 +Subject: [PATCH] dt-bindings: clock: mediatek: add mt7981 clock IDs + +Add MT7981 clock dt-bindings, include topckgen, apmixedsys, +infracfg, and ethernet subsystem clocks. + +Acked-by: Krzysztof Kozlowski +Signed-off-by: Jianhui Zhao +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/e353d32b5a4481766519a037afe1ed44e31ece1a.1674703830.git.daniel@makrotopia.org +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +--- + .../dt-bindings/clock/mediatek,mt7981-clk.h | 215 ++++++++++++++++++ + 1 file changed, 215 insertions(+) + create mode 100644 include/dt-bindings/clock/mediatek,mt7981-clk.h + +--- /dev/null ++++ b/include/dt-bindings/clock/mediatek,mt7981-clk.h +@@ -0,0 +1,215 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Wenzhen.Yu ++ * Author: Jianhui Zhao ++ * Author: Daniel Golle ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_MT7981_H ++#define _DT_BINDINGS_CLK_MT7981_H ++ ++/* TOPCKGEN */ ++#define CLK_TOP_CB_CKSQ_40M 0 ++#define CLK_TOP_CB_M_416M 1 ++#define CLK_TOP_CB_M_D2 2 ++#define CLK_TOP_CB_M_D3 3 ++#define CLK_TOP_M_D3_D2 4 ++#define CLK_TOP_CB_M_D4 5 ++#define CLK_TOP_CB_M_D8 6 ++#define CLK_TOP_M_D8_D2 7 ++#define CLK_TOP_CB_MM_720M 8 ++#define CLK_TOP_CB_MM_D2 9 ++#define CLK_TOP_CB_MM_D3 10 ++#define CLK_TOP_CB_MM_D3_D5 11 ++#define CLK_TOP_CB_MM_D4 12 ++#define CLK_TOP_CB_MM_D6 13 ++#define CLK_TOP_MM_D6_D2 14 ++#define CLK_TOP_CB_MM_D8 15 ++#define CLK_TOP_CB_APLL2_196M 16 ++#define CLK_TOP_APLL2_D2 17 ++#define CLK_TOP_APLL2_D4 18 ++#define CLK_TOP_NET1_2500M 19 ++#define CLK_TOP_CB_NET1_D4 20 ++#define CLK_TOP_CB_NET1_D5 21 ++#define CLK_TOP_NET1_D5_D2 22 ++#define CLK_TOP_NET1_D5_D4 23 ++#define CLK_TOP_CB_NET1_D8 24 ++#define CLK_TOP_NET1_D8_D2 25 ++#define CLK_TOP_NET1_D8_D4 26 ++#define CLK_TOP_CB_NET2_800M 27 ++#define CLK_TOP_CB_NET2_D2 28 ++#define CLK_TOP_CB_NET2_D4 29 ++#define CLK_TOP_NET2_D4_D2 30 ++#define CLK_TOP_NET2_D4_D4 31 ++#define CLK_TOP_CB_NET2_D6 32 ++#define CLK_TOP_CB_WEDMCU_208M 33 ++#define CLK_TOP_CB_SGM_325M 34 ++#define CLK_TOP_CKSQ_40M_D2 35 ++#define CLK_TOP_CB_RTC_32K 36 ++#define CLK_TOP_CB_RTC_32P7K 37 ++#define CLK_TOP_USB_TX250M 38 ++#define CLK_TOP_FAUD 39 ++#define CLK_TOP_NFI1X 40 ++#define CLK_TOP_USB_EQ_RX250M 41 ++#define CLK_TOP_USB_CDR_CK 42 ++#define CLK_TOP_USB_LN0_CK 43 ++#define CLK_TOP_SPINFI_BCK 44 ++#define CLK_TOP_SPI 45 ++#define CLK_TOP_SPIM_MST 46 ++#define CLK_TOP_UART_BCK 47 ++#define CLK_TOP_PWM_BCK 48 ++#define CLK_TOP_I2C_BCK 49 ++#define CLK_TOP_PEXTP_TL 50 ++#define CLK_TOP_EMMC_208M 51 ++#define CLK_TOP_EMMC_400M 52 ++#define CLK_TOP_DRAMC_REF 53 ++#define CLK_TOP_DRAMC_MD32 54 ++#define CLK_TOP_SYSAXI 55 ++#define CLK_TOP_SYSAPB 56 ++#define CLK_TOP_ARM_DB_MAIN 57 ++#define CLK_TOP_AP2CNN_HOST 58 ++#define CLK_TOP_NETSYS 59 ++#define CLK_TOP_NETSYS_500M 60 ++#define CLK_TOP_NETSYS_WED_MCU 61 ++#define CLK_TOP_NETSYS_2X 62 ++#define CLK_TOP_SGM_325M 63 ++#define CLK_TOP_SGM_REG 64 ++#define CLK_TOP_F26M 65 ++#define CLK_TOP_EIP97B 66 ++#define CLK_TOP_USB3_PHY 67 ++#define CLK_TOP_AUD 68 ++#define CLK_TOP_A1SYS 69 ++#define CLK_TOP_AUD_L 70 ++#define CLK_TOP_A_TUNER 71 ++#define CLK_TOP_U2U3_REF 72 ++#define CLK_TOP_U2U3_SYS 73 ++#define CLK_TOP_U2U3_XHCI 74 ++#define CLK_TOP_USB_FRMCNT 75 ++#define CLK_TOP_NFI1X_SEL 76 ++#define CLK_TOP_SPINFI_SEL 77 ++#define CLK_TOP_SPI_SEL 78 ++#define CLK_TOP_SPIM_MST_SEL 79 ++#define CLK_TOP_UART_SEL 80 ++#define CLK_TOP_PWM_SEL 81 ++#define CLK_TOP_I2C_SEL 82 ++#define CLK_TOP_PEXTP_TL_SEL 83 ++#define CLK_TOP_EMMC_208M_SEL 84 ++#define CLK_TOP_EMMC_400M_SEL 85 ++#define CLK_TOP_F26M_SEL 86 ++#define CLK_TOP_DRAMC_SEL 87 ++#define CLK_TOP_DRAMC_MD32_SEL 88 ++#define CLK_TOP_SYSAXI_SEL 89 ++#define CLK_TOP_SYSAPB_SEL 90 ++#define CLK_TOP_ARM_DB_MAIN_SEL 91 ++#define CLK_TOP_AP2CNN_HOST_SEL 92 ++#define CLK_TOP_NETSYS_SEL 93 ++#define CLK_TOP_NETSYS_500M_SEL 94 ++#define CLK_TOP_NETSYS_MCU_SEL 95 ++#define CLK_TOP_NETSYS_2X_SEL 96 ++#define CLK_TOP_SGM_325M_SEL 97 ++#define CLK_TOP_SGM_REG_SEL 98 ++#define CLK_TOP_EIP97B_SEL 99 ++#define CLK_TOP_USB3_PHY_SEL 100 ++#define CLK_TOP_AUD_SEL 101 ++#define CLK_TOP_A1SYS_SEL 102 ++#define CLK_TOP_AUD_L_SEL 103 ++#define CLK_TOP_A_TUNER_SEL 104 ++#define CLK_TOP_U2U3_SEL 105 ++#define CLK_TOP_U2U3_SYS_SEL 106 ++#define CLK_TOP_U2U3_XHCI_SEL 107 ++#define CLK_TOP_USB_FRMCNT_SEL 108 ++#define CLK_TOP_AUD_I2S_M 109 ++ ++/* INFRACFG */ ++#define CLK_INFRA_66M_MCK 0 ++#define CLK_INFRA_UART0_SEL 1 ++#define CLK_INFRA_UART1_SEL 2 ++#define CLK_INFRA_UART2_SEL 3 ++#define CLK_INFRA_SPI0_SEL 4 ++#define CLK_INFRA_SPI1_SEL 5 ++#define CLK_INFRA_SPI2_SEL 6 ++#define CLK_INFRA_PWM1_SEL 7 ++#define CLK_INFRA_PWM2_SEL 8 ++#define CLK_INFRA_PWM3_SEL 9 ++#define CLK_INFRA_PWM_BSEL 10 ++#define CLK_INFRA_PCIE_SEL 11 ++#define CLK_INFRA_GPT_STA 12 ++#define CLK_INFRA_PWM_HCK 13 ++#define CLK_INFRA_PWM_STA 14 ++#define CLK_INFRA_PWM1_CK 15 ++#define CLK_INFRA_PWM2_CK 16 ++#define CLK_INFRA_PWM3_CK 17 ++#define CLK_INFRA_CQ_DMA_CK 18 ++#define CLK_INFRA_AUD_BUS_CK 19 ++#define CLK_INFRA_AUD_26M_CK 20 ++#define CLK_INFRA_AUD_L_CK 21 ++#define CLK_INFRA_AUD_AUD_CK 22 ++#define CLK_INFRA_AUD_EG2_CK 23 ++#define CLK_INFRA_DRAMC_26M_CK 24 ++#define CLK_INFRA_DBG_CK 25 ++#define CLK_INFRA_AP_DMA_CK 26 ++#define CLK_INFRA_SEJ_CK 27 ++#define CLK_INFRA_SEJ_13M_CK 28 ++#define CLK_INFRA_THERM_CK 29 ++#define CLK_INFRA_I2C0_CK 30 ++#define CLK_INFRA_UART0_CK 31 ++#define CLK_INFRA_UART1_CK 32 ++#define CLK_INFRA_UART2_CK 33 ++#define CLK_INFRA_SPI2_CK 34 ++#define CLK_INFRA_SPI2_HCK_CK 35 ++#define CLK_INFRA_NFI1_CK 36 ++#define CLK_INFRA_SPINFI1_CK 37 ++#define CLK_INFRA_NFI_HCK_CK 38 ++#define CLK_INFRA_SPI0_CK 39 ++#define CLK_INFRA_SPI1_CK 40 ++#define CLK_INFRA_SPI0_HCK_CK 41 ++#define CLK_INFRA_SPI1_HCK_CK 42 ++#define CLK_INFRA_FRTC_CK 43 ++#define CLK_INFRA_MSDC_CK 44 ++#define CLK_INFRA_MSDC_HCK_CK 45 ++#define CLK_INFRA_MSDC_133M_CK 46 ++#define CLK_INFRA_MSDC_66M_CK 47 ++#define CLK_INFRA_ADC_26M_CK 48 ++#define CLK_INFRA_ADC_FRC_CK 49 ++#define CLK_INFRA_FBIST2FPC_CK 50 ++#define CLK_INFRA_I2C_MCK_CK 51 ++#define CLK_INFRA_I2C_PCK_CK 52 ++#define CLK_INFRA_IUSB_133_CK 53 ++#define CLK_INFRA_IUSB_66M_CK 54 ++#define CLK_INFRA_IUSB_SYS_CK 55 ++#define CLK_INFRA_IUSB_CK 56 ++#define CLK_INFRA_IPCIE_CK 57 ++#define CLK_INFRA_IPCIE_PIPE_CK 58 ++#define CLK_INFRA_IPCIER_CK 59 ++#define CLK_INFRA_IPCIEB_CK 60 ++ ++/* APMIXEDSYS */ ++#define CLK_APMIXED_ARMPLL 0 ++#define CLK_APMIXED_NET2PLL 1 ++#define CLK_APMIXED_MMPLL 2 ++#define CLK_APMIXED_SGMPLL 3 ++#define CLK_APMIXED_WEDMCUPLL 4 ++#define CLK_APMIXED_NET1PLL 5 ++#define CLK_APMIXED_MPLL 6 ++#define CLK_APMIXED_APLL2 7 ++ ++/* SGMIISYS_0 */ ++#define CLK_SGM0_TX_EN 0 ++#define CLK_SGM0_RX_EN 1 ++#define CLK_SGM0_CK0_EN 2 ++#define CLK_SGM0_CDR_CK0_EN 3 ++ ++/* SGMIISYS_1 */ ++#define CLK_SGM1_TX_EN 0 ++#define CLK_SGM1_RX_EN 1 ++#define CLK_SGM1_CK1_EN 2 ++#define CLK_SGM1_CDR_CK1_EN 3 ++ ++/* ETHSYS */ ++#define CLK_ETH_FE_EN 0 ++#define CLK_ETH_GP2_EN 1 ++#define CLK_ETH_GP1_EN 2 ++#define CLK_ETH_WOCPU0_EN 3 ++ ++#endif /* _DT_BINDINGS_CLK_MT7981_H */ diff --git a/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch b/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch new file mode 100644 index 0000000000..f9dd94a78a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch @@ -0,0 +1,932 @@ +From 8efeeb9c8b4ecf4fb4a74be9403aba951403bbaa Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 26 Jan 2023 03:34:24 +0000 +Subject: [PATCH] clk: mediatek: add MT7981 clock support + +Add MT7981 clock support, include topckgen, apmixedsys, infracfg and +ethernet subsystem clocks. + +The drivers are based on clk-mt7981.c which can be found in MediaTek's +SDK sources. To be fit for upstream inclusion the driver has been split +into clock domains and the infracfg part has been significantly +de-bloated by removing all the 1:1 factors (aliases). + +Signed-off-by: Jianhui Zhao +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/8136eb5b2049177bc2f6d3e0f2aefecc342d626f.1674703830.git.daniel@makrotopia.org +Reviewed-by: AngeloGioacchino Del Regno +[sboyd@kernel.org: Add module license] +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/Kconfig | 17 + + drivers/clk/mediatek/Makefile | 4 + + drivers/clk/mediatek/clk-mt7981-apmixed.c | 102 +++++ + drivers/clk/mediatek/clk-mt7981-eth.c | 118 ++++++ + drivers/clk/mediatek/clk-mt7981-infracfg.c | 207 ++++++++++ + drivers/clk/mediatek/clk-mt7981-topckgen.c | 422 +++++++++++++++++++++ + 6 files changed, 870 insertions(+) + create mode 100644 drivers/clk/mediatek/clk-mt7981-apmixed.c + create mode 100644 drivers/clk/mediatek/clk-mt7981-eth.c + create mode 100644 drivers/clk/mediatek/clk-mt7981-infracfg.c + create mode 100644 drivers/clk/mediatek/clk-mt7981-topckgen.c + +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -381,6 +381,23 @@ config COMMON_CLK_MT7629_HIFSYS + This driver supports MediaTek MT7629 HIFSYS clocks providing + to PCI-E and USB. + ++config COMMON_CLK_MT7981 ++ bool "Clock driver for MediaTek MT7981" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select COMMON_CLK_MEDIATEK ++ default ARCH_MEDIATEK ++ help ++ This driver supports MediaTek MT7981 basic clocks and clocks ++ required for various peripherals found on this SoC. ++ ++config COMMON_CLK_MT7981_ETHSYS ++ tristate "Clock driver for MediaTek MT7981 ETHSYS" ++ depends on COMMON_CLK_MT7981 ++ default COMMON_CLK_MT7981 ++ help ++ This driver adds support for clocks for Ethernet and SGMII ++ required on MediaTek MT7981 SoC. ++ + config COMMON_CLK_MT7986 + bool "Clock driver for MediaTek MT7986" + depends on ARCH_MEDIATEK || COMPILE_TEST +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -52,6 +52,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + + obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o + obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o + obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o ++obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-apmixed.o ++obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-topckgen.o ++obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-infracfg.o ++obj-$(CONFIG_COMMON_CLK_MT7981_ETHSYS) += clk-mt7981-eth.o + obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o + obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o + obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7981-apmixed.c +@@ -0,0 +1,102 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ * Author: Wenzhen Yu ++ * Author: Jianhui Zhao ++ * Author: Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-gate.h" ++#include "clk-mtk.h" ++#include "clk-mux.h" ++#include "clk-pll.h" ++ ++#include ++#include ++ ++#define MT7981_PLL_FMAX (2500UL * MHZ) ++#define CON0_MT7981_RST_BAR BIT(27) ++ ++#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ ++ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ ++ _div_table, _parent_name) \ ++ { \ ++ .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ ++ .en_mask = _en_mask, .flags = _flags, \ ++ .rst_bar_mask = CON0_MT7981_RST_BAR, .fmax = MT7981_PLL_FMAX, \ ++ .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ ++ .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ ++ .pcw_shift = _pcw_shift, .div_table = _div_table, \ ++ .parent_name = _parent_name, \ ++ } ++ ++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ ++ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ ++ PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ ++ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ ++ "clkxtal") ++ ++static const struct mtk_pll_data plls[] = { ++ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, PLL_AO, ++ 32, 0x0200, 4, 0, 0x0204, 0), ++ PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, ++ 0x0210, 4, 0, 0x0214, 0), ++ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, ++ 0x0220, 4, 0, 0x0224, 0), ++ PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023C, 0x00000001, 0, 32, ++ 0x0230, 4, 0, 0x0234, 0), ++ PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024C, 0x00000001, 0, 32, ++ 0x0240, 4, 0, 0x0244, 0), ++ PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025C, 0x00000001, 0, 32, ++ 0x0250, 4, 0, 0x0254, 0), ++ PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, ++ 0x0260, 4, 0, 0x0264, 0), ++ PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, ++ 0x0278, 4, 0, 0x027C, 0), ++}; ++ ++static const struct of_device_id of_match_clk_mt7981_apmixed[] = { ++ { .compatible = "mediatek,mt7981-apmixedsys", }, ++ { /* sentinel */ } ++}; ++ ++static int clk_mt7981_apmixed_probe(struct platform_device *pdev) ++{ ++ struct clk_hw_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_hw_provider(node, of_clk_hw_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_mt7981_apmixed_drv = { ++ .probe = clk_mt7981_apmixed_probe, ++ .driver = { ++ .name = "clk-mt7981-apmixed", ++ .of_match_table = of_match_clk_mt7981_apmixed, ++ }, ++}; ++builtin_platform_driver(clk_mt7981_apmixed_drv); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7981-eth.c +@@ -0,0 +1,118 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ * Author: Wenzhen Yu ++ * Author: Jianhui Zhao ++ * Author: Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include ++ ++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[] __initconst = { ++ GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "usb_tx250m", 2), ++ GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "usb_eq_rx250m", 3), ++ GATE_SGMII0(CLK_SGM0_CK0_EN, "sgm0_ck0_en", "usb_ln0", 4), ++ GATE_SGMII0(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", "usb_cdr", 5), ++}; ++ ++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[] __initconst = { ++ GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "usb_tx250m", 2), ++ GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "usb_eq_rx250m", 3), ++ GATE_SGMII1(CLK_SGM1_CK1_EN, "sgm1_ck1_en", "usb_ln0", 4), ++ GATE_SGMII1(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", "usb_cdr", 5), ++}; ++ ++static const struct mtk_gate_regs eth_cg_regs = { ++ .set_ofs = 0x30, ++ .clr_ofs = 0x30, ++ .sta_ofs = 0x30, ++}; ++ ++#define GATE_ETH(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = ð_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_gate eth_clks[] __initconst = { ++ GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x", 6), ++ GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m", 7), ++ GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m", 8), ++ GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_wed_mcu", 15), ++}; ++ ++static const struct mtk_clk_desc eth_desc = { ++ .clks = eth_clks, ++ .num_clks = ARRAY_SIZE(eth_clks), ++}; ++ ++static const struct mtk_clk_desc sgmii0_desc = { ++ .clks = sgmii0_clks, ++ .num_clks = ARRAY_SIZE(sgmii0_clks), ++}; ++ ++static const struct mtk_clk_desc sgmii1_desc = { ++ .clks = sgmii1_clks, ++ .num_clks = ARRAY_SIZE(sgmii1_clks), ++}; ++ ++static const struct of_device_id of_match_clk_mt7981_eth[] = { ++ { .compatible = "mediatek,mt7981-ethsys", .data = ð_desc }, ++ { .compatible = "mediatek,mt7981-sgmiisys_0", .data = &sgmii0_desc }, ++ { .compatible = "mediatek,mt7981-sgmiisys_1", .data = &sgmii1_desc }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver clk_mt7981_eth_drv = { ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++ .driver = { ++ .name = "clk-mt7981-eth", ++ .of_match_table = of_match_clk_mt7981_eth, ++ }, ++}; ++module_platform_driver(clk_mt7981_eth_drv); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7981-infracfg.c +@@ -0,0 +1,207 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ * Author: Wenzhen Yu ++ * Author: Jianhui Zhao ++ * Author: Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "clk-mtk.h" ++#include "clk-gate.h" ++#include "clk-mux.h" ++ ++#include ++#include ++ ++static DEFINE_SPINLOCK(mt7981_clk_lock); ++ ++static const struct mtk_fixed_factor infra_divs[] = { ++ FACTOR(CLK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi_sel", 1, 2), ++}; ++ ++static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", ++ "uart_sel" }; ++ ++static const char *const infra_spi0_parents[] __initconst = { "i2c_sel", ++ "spi_sel" }; ++ ++static const char *const infra_spi1_parents[] __initconst = { "i2c_sel", ++ "spim_mst_sel" }; ++ ++static const char *const infra_pwm1_parents[] __initconst = { "pwm_sel" }; ++ ++static const char *const infra_pwm_bsel_parents[] __initconst = { ++ "cb_rtc_32p7k", "csw_f26m_sel", "infra_66m_mck", "pwm_sel" ++}; ++ ++static const char *const infra_pcie_parents[] __initconst = { ++ "cb_rtc_32p7k", "csw_f26m_sel", "cb_cksq_40m", "pextp_tl_ck_sel" ++}; ++ ++static const struct mtk_mux infra_muxes[] = { ++ /* MODULE_CLK_SEL_0 */ ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", ++ infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", ++ infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", ++ infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", ++ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 4, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", ++ infra_spi1_parents, 0x0018, 0x0010, 0x0014, 5, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI2_SEL, "infra_spi2_sel", ++ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 6, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", ++ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 9, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", ++ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 11, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM3_SEL, "infra_pwm3_sel", ++ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 15, 1, ++ -1, -1, -1), ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", ++ infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, ++ 2, -1, -1, -1), ++ /* MODULE_CLK_SEL_1 */ ++ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", ++ infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, ++ -1, -1, -1), ++}; ++ ++static const struct mtk_gate_regs infra0_cg_regs = { ++ .set_ofs = 0x40, ++ .clr_ofs = 0x44, ++ .sta_ofs = 0x48, ++}; ++ ++static const struct mtk_gate_regs infra1_cg_regs = { ++ .set_ofs = 0x50, ++ .clr_ofs = 0x54, ++ .sta_ofs = 0x58, ++}; ++ ++static const struct mtk_gate_regs infra2_cg_regs = { ++ .set_ofs = 0x60, ++ .clr_ofs = 0x64, ++ .sta_ofs = 0x68, ++}; ++ ++#define GATE_INFRA0(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .name = _name, .parent_name = _parent, \ ++ .regs = &infra0_cg_regs, .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_INFRA1(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .name = _name, .parent_name = _parent, \ ++ .regs = &infra1_cg_regs, .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_INFRA2(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .name = _name, .parent_name = _parent, \ ++ .regs = &infra2_cg_regs, .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++static const struct mtk_gate infra_clks[] = { ++ /* INFRA0 */ ++ GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_66m_mck", 0), ++ GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1), ++ GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), ++ GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), ++ GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), ++ GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi", 6), ++ ++ GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi", 8), ++ GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), ++ GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l", 10), ++ GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys", 11), ++ GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner", 13), ++ GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", ++ 14), ++ GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_66m_mck", 15), ++ GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16), ++ GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24), ++ GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), ++ GATE_INFRA0(CLK_INFRA_PWM3_CK, "infra_pwm3", "infra_pwm3_sel", 27), ++ /* INFRA1 */ ++ GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), ++ GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_bck", 1), ++ GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), ++ GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), ++ GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), ++ GATE_INFRA1(CLK_INFRA_SPI2_CK, "infra_spi2", "infra_spi2_sel", 6), ++ GATE_INFRA1(CLK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", "infra_66m_mck", 7), ++ GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x", 8), ++ GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_bck", 9), ++ GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_66m_mck", 10), ++ GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), ++ GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), ++ GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_66m_mck", ++ 13), ++ GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_66m_mck", ++ 14), ++ GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "cb_rtc_32k", 15), ++ GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_400m", 16), ++ GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_208m", 17), ++ GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi", 18), ++ GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "sysaxi", 19), ++ GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), ++ GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m", 21), ++ GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x", 23), ++ GATE_INFRA1(CLK_INFRA_I2C_MCK_CK, "infra_i2c_mck", "sysaxi", 25), ++ GATE_INFRA1(CLK_INFRA_I2C_PCK_CK, "infra_i2c_pck", "infra_66m_mck", 26), ++ /* INFRA2 */ ++ GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi", 0), ++ GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "sysaxi", 1), ++ GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys", 2), ++ GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_ref", 3), ++ GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl", 12), ++ GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "cb_cksq_40m", ++ 13), ++ GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m", 14), ++ GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi", 15), ++}; ++ ++static const struct mtk_clk_desc infracfg_desc = { ++ .factor_clks = infra_divs, ++ .num_factor_clks = ARRAY_SIZE(infra_divs), ++ .mux_clks = infra_muxes, ++ .num_mux_clks = ARRAY_SIZE(infra_muxes), ++ .clks = infra_clks, ++ .num_clks = ARRAY_SIZE(infra_clks), ++ .clk_lock = &mt7981_clk_lock, ++}; ++ ++static const struct of_device_id of_match_clk_mt7981_infracfg[] = { ++ { .compatible = "mediatek,mt7981-infracfg", .data = &infracfg_desc }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver clk_mt7981_infracfg_drv = { ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++ .driver = { ++ .name = "clk-mt7981-infracfg", ++ .of_match_table = of_match_clk_mt7981_infracfg, ++ }, ++}; ++builtin_platform_driver(clk_mt7981_infracfg_drv); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c +@@ -0,0 +1,422 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ * Author: Wenzhen Yu ++ * Author: Jianhui Zhao ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include "clk-mtk.h" ++#include "clk-gate.h" ++#include "clk-mux.h" ++ ++#include ++#include ++ ++static DEFINE_SPINLOCK(mt7981_clk_lock); ++ ++static const struct mtk_fixed_factor top_divs[] = { ++ FACTOR(CLK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1), ++ FACTOR(CLK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1), ++ FACTOR(CLK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2), ++ FACTOR(CLK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3), ++ FACTOR(CLK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2), ++ FACTOR(CLK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4), ++ FACTOR(CLK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8), ++ FACTOR(CLK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16), ++ FACTOR(CLK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1), ++ FACTOR(CLK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2), ++ FACTOR(CLK_TOP_CB_MM_D3, "cb_mm_d3", "mmpll", 1, 3), ++ FACTOR(CLK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15), ++ FACTOR(CLK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4), ++ FACTOR(CLK_TOP_CB_MM_D6, "cb_mm_d6", "mmpll", 1, 6), ++ FACTOR(CLK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12), ++ FACTOR(CLK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8), ++ FACTOR(CLK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1), ++ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), ++ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), ++ FACTOR(CLK_TOP_NET1_2500M, "net1_2500m", "net1pll", 1, 1), ++ FACTOR(CLK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4), ++ FACTOR(CLK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5), ++ FACTOR(CLK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10), ++ FACTOR(CLK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20), ++ FACTOR(CLK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8), ++ FACTOR(CLK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16), ++ FACTOR(CLK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32), ++ FACTOR(CLK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1), ++ FACTOR(CLK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2), ++ FACTOR(CLK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4), ++ FACTOR(CLK_TOP_NET2_D4_D2, "net2_d4_d2", "net2pll", 1, 8), ++ FACTOR(CLK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16), ++ FACTOR(CLK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6), ++ FACTOR(CLK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1), ++ FACTOR(CLK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1), ++ FACTOR(CLK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2), ++ FACTOR(CLK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250), ++ FACTOR(CLK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220), ++ FACTOR(CLK_TOP_USB_TX250M, "usb_tx250m", "cb_cksq_40m", 1, 1), ++ FACTOR(CLK_TOP_FAUD, "faud", "aud_sel", 1, 1), ++ FACTOR(CLK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1), ++ FACTOR(CLK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", "cb_cksq_40m", 1, 1), ++ FACTOR(CLK_TOP_USB_CDR_CK, "usb_cdr", "cb_cksq_40m", 1, 1), ++ FACTOR(CLK_TOP_USB_LN0_CK, "usb_ln0", "cb_cksq_40m", 1, 1), ++ FACTOR(CLK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1), ++ FACTOR(CLK_TOP_SPI, "spi", "spi_sel", 1, 1), ++ FACTOR(CLK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1), ++ FACTOR(CLK_TOP_UART_BCK, "uart_bck", "uart_sel", 1, 1), ++ FACTOR(CLK_TOP_PWM_BCK, "pwm_bck", "pwm_sel", 1, 1), ++ FACTOR(CLK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1), ++ FACTOR(CLK_TOP_PEXTP_TL, "pextp_tl", "pextp_tl_ck_sel", 1, 1), ++ FACTOR(CLK_TOP_EMMC_208M, "emmc_208m", "emmc_208m_sel", 1, 1), ++ FACTOR(CLK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1), ++ FACTOR(CLK_TOP_DRAMC_REF, "dramc_ref", "dramc_sel", 1, 1), ++ FACTOR(CLK_TOP_DRAMC_MD32, "dramc_md32", "dramc_md32_sel", 1, 1), ++ FACTOR(CLK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1), ++ FACTOR(CLK_TOP_SYSAPB, "sysapb", "sysapb_sel", 1, 1), ++ FACTOR(CLK_TOP_ARM_DB_MAIN, "arm_db_main", "arm_db_main_sel", 1, 1), ++ FACTOR(CLK_TOP_AP2CNN_HOST, "ap2cnn_host", "ap2cnn_host_sel", 1, 1), ++ FACTOR(CLK_TOP_NETSYS, "netsys", "netsys_sel", 1, 1), ++ FACTOR(CLK_TOP_NETSYS_500M, "netsys_500m", "netsys_500m_sel", 1, 1), ++ FACTOR(CLK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1), ++ FACTOR(CLK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1), ++ FACTOR(CLK_TOP_SGM_325M, "sgm_325m", "sgm_325m_sel", 1, 1), ++ FACTOR(CLK_TOP_SGM_REG, "sgm_reg", "sgm_reg_sel", 1, 1), ++ FACTOR(CLK_TOP_F26M, "csw_f26m", "csw_f26m_sel", 1, 1), ++ FACTOR(CLK_TOP_EIP97B, "eip97b", "eip97b_sel", 1, 1), ++ FACTOR(CLK_TOP_USB3_PHY, "usb3_phy", "usb3_phy_sel", 1, 1), ++ FACTOR(CLK_TOP_AUD, "aud", "faud", 1, 1), ++ FACTOR(CLK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1), ++ FACTOR(CLK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1), ++ FACTOR(CLK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1), ++ FACTOR(CLK_TOP_U2U3_REF, "u2u3_ref", "u2u3_sel", 1, 1), ++ FACTOR(CLK_TOP_U2U3_SYS, "u2u3_sys", "u2u3_sys_sel", 1, 1), ++ FACTOR(CLK_TOP_U2U3_XHCI, "u2u3_xhci", "u2u3_xhci_sel", 1, 1), ++ FACTOR(CLK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1), ++}; ++ ++static const char * const nfi1x_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_mm_d4", ++ "net1_d8_d2", ++ "cb_net2_d6", ++ "cb_m_d4", ++ "cb_mm_d8", ++ "net1_d8_d4", ++ "cb_m_d8" ++}; ++ ++static const char * const spinfi_parents[] __initconst = { ++ "cksq_40m_d2", ++ "cb_cksq_40m", ++ "net1_d5_d4", ++ "cb_m_d4", ++ "cb_mm_d8", ++ "net1_d8_d4", ++ "mm_d6_d2", ++ "cb_m_d8" ++}; ++ ++static const char * const spi_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_m_d2", ++ "cb_mm_d4", ++ "net1_d8_d2", ++ "cb_net2_d6", ++ "net1_d5_d4", ++ "cb_m_d4", ++ "net1_d8_d4" ++}; ++ ++static const char * const uart_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_m_d8", ++ "m_d8_d2" ++}; ++ ++static const char * const pwm_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d8_d2", ++ "net1_d5_d4", ++ "cb_m_d4", ++ "m_d8_d2", ++ "cb_rtc_32k" ++}; ++ ++static const char * const i2c_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d5_d4", ++ "cb_m_d4", ++ "net1_d8_d4" ++}; ++ ++static const char * const pextp_tl_ck_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d5_d4", ++ "cb_m_d4", ++ "cb_rtc_32k" ++}; ++ ++static const char * const emmc_208m_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_m_d2", ++ "cb_net2_d4", ++ "cb_apll2_196m", ++ "cb_mm_d4", ++ "net1_d8_d2", ++ "cb_mm_d6" ++}; ++ ++static const char * const emmc_400m_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net2_d2", ++ "cb_mm_d2", ++ "cb_net2_d2" ++}; ++ ++static const char * const csw_f26m_parents[] __initconst = { ++ "cksq_40m_d2", ++ "m_d8_d2" ++}; ++ ++static const char * const dramc_md32_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_m_d2", ++ "cb_wedmcu_208m" ++}; ++ ++static const char * const sysaxi_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d8_d2" ++}; ++ ++static const char * const sysapb_parents[] __initconst = { ++ "cb_cksq_40m", ++ "m_d3_d2" ++}; ++ ++static const char * const arm_db_main_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net2_d6" ++}; ++ ++static const char * const ap2cnn_host_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d8_d4" ++}; ++ ++static const char * const netsys_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_mm_d2" ++}; ++ ++static const char * const netsys_500m_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net1_d5" ++}; ++ ++static const char * const netsys_mcu_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_mm_720m", ++ "cb_net1_d4", ++ "cb_net1_d5", ++ "cb_m_416m" ++}; ++ ++static const char * const netsys_2x_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net2_800m", ++ "cb_mm_720m" ++}; ++ ++static const char * const sgm_325m_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_sgm_325m" ++}; ++ ++static const char * const sgm_reg_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net2_d4" ++}; ++ ++static const char * const eip97b_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_net1_d5", ++ "cb_m_416m", ++ "cb_mm_d2", ++ "net1_d5_d2" ++}; ++ ++static const char * const aud_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_apll2_196m" ++}; ++ ++static const char * const a1sys_parents[] __initconst = { ++ "cb_cksq_40m", ++ "apll2_d4" ++}; ++ ++static const char * const aud_l_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_apll2_196m", ++ "m_d8_d2" ++}; ++ ++static const char * const a_tuner_parents[] __initconst = { ++ "cb_cksq_40m", ++ "apll2_d4", ++ "m_d8_d2" ++}; ++ ++static const char * const u2u3_parents[] __initconst = { ++ "cb_cksq_40m", ++ "m_d8_d2" ++}; ++ ++static const char * const u2u3_sys_parents[] __initconst = { ++ "cb_cksq_40m", ++ "net1_d5_d4" ++}; ++ ++static const char * const usb_frmcnt_parents[] __initconst = { ++ "cb_cksq_40m", ++ "cb_mm_d3_d5" ++}; ++ ++static const struct mtk_mux top_muxes[] = { ++ /* CLK_CFG_0 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, ++ 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, ++ 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, ++ 0x000, 0x004, 0x008, 16, 3, 23, 0x1C0, 2), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, ++ 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), ++ /* CLK_CFG_1 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, ++ 0x010, 0x014, 0x018, 0, 2, 7, 0x1C0, 4), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, ++ 0x010, 0x014, 0x018, 8, 3, 15, 0x1C0, 5), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, ++ 0x010, 0x014, 0x018, 16, 2, 23, 0x1C0, 6), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", ++ pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, ++ 0x1C0, 7), ++ /* CLK_CFG_2 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", ++ emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, ++ 0x1C0, 8), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", ++ emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, ++ 0x1C0, 9), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", ++ csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23, ++ 0x1C0, 10, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", ++ csw_f26m_parents, 0x020, 0x024, 0x028, 24, 1, ++ 31, 0x1C0, 11, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ /* CLK_CFG_3 */ ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", ++ dramc_md32_parents, 0x030, 0x034, 0x038, 0, 2, ++ 7, 0x1C0, 12, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", ++ sysaxi_parents, 0x030, 0x034, 0x038, 8, 1, 15, ++ 0x1C0, 13, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", ++ sysapb_parents, 0x030, 0x034, 0x038, 16, 1, ++ 23, 0x1C0, 14, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", ++ arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, 31, ++ 0x1C0, 15), ++ /* CLK_CFG_4 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", ++ ap2cnn_host_parents, 0x040, 0x044, 0x048, 0, 1, 7, ++ 0x1C0, 16), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, ++ 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", ++ netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, 23, ++ 0x1C0, 18), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", ++ netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, ++ 0x1C0, 19), ++ /* CLK_CFG_5 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", ++ netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, ++ 0x1C0, 20), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", ++ sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, ++ 0x1C0, 21), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, ++ 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, ++ 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23), ++ /* CLK_CFG_6 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", ++ csw_f26m_parents, 0x060, 0x064, 0x068, 0, 1, ++ 7, 0x1C0, 24), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x060, ++ 0x064, 0x068, 8, 1, 15, 0x1C0, 25), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, ++ 0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, ++ 0x060, 0x064, 0x068, 24, 2, 31, 0x1C0, 27), ++ /* CLK_CFG_7 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", ++ a_tuner_parents, 0x070, 0x074, 0x078, 0, 2, 7, ++ 0x1C0, 28), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x070, ++ 0x074, 0x078, 8, 1, 15, 0x1C0, 29), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", ++ u2u3_sys_parents, 0x070, 0x074, 0x078, 16, 1, 23, ++ 0x1C0, 30), ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", ++ u2u3_sys_parents, 0x070, 0x074, 0x078, 24, 1, 31, ++ 0x1C4, 0), ++ /* CLK_CFG_8 */ ++ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", ++ usb_frmcnt_parents, 0x080, 0x084, 0x088, 0, 1, 7, ++ 0x1C4, 1), ++}; ++ ++static struct mtk_composite top_aud_divs[] = { ++ DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud", ++ 0x0420, 0, 0x0420, 8, 8), ++}; ++ ++static const struct mtk_clk_desc topck_desc = { ++ .factor_clks = top_divs, ++ .num_factor_clks = ARRAY_SIZE(top_divs), ++ .mux_clks = top_muxes, ++ .num_mux_clks = ARRAY_SIZE(top_muxes), ++ .composite_clks = top_aud_divs, ++ .num_composite_clks = ARRAY_SIZE(top_aud_divs), ++ .clk_lock = &mt7981_clk_lock, ++}; ++ ++static const struct of_device_id of_match_clk_mt7981_topckgen[] = { ++ { .compatible = "mediatek,mt7981-topckgen", .data = &topck_desc }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver clk_mt7981_topckgen_drv = { ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++ .driver = { ++ .name = "clk-mt7981-topckgen", ++ .of_match_table = of_match_clk_mt7981_topckgen, ++ }, ++}; ++builtin_platform_driver(clk_mt7981_topckgen_drv); diff --git a/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch b/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch new file mode 100644 index 0000000000..8820d57f01 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch @@ -0,0 +1,30 @@ +From fc157139e6b7f8dfb6430ac7191ba754027705e8 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 18 Feb 2024 01:59:59 +0000 +Subject: [PATCH] clk: mediatek: mt7981-topckgen: flag SGM_REG_SEL as critical + +Without the SGM_REG_SEL clock enabled the system freezes if trying to +access registers used by MT7981 clock drivers itself. +Mark SGM_REG_SEL as critical to make sure it is always enabled to +prevent freezes on boot depending on probe order. + +Fixes: 813c3b53b55ba ("clk: mediatek: add MT7981 clock support") +Signed-off-by: Daniel Golle +--- + drivers/clk/mediatek/clk-mt7981-topckgen.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/clk/mediatek/clk-mt7981-topckgen.c ++++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c +@@ -359,8 +359,9 @@ static const struct mtk_mux top_muxes[] + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", + sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, + 0x1C0, 21), +- MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, +- 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22), ++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, ++ 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22, ++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, + 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23), + /* CLK_CFG_6 */ diff --git a/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch new file mode 100644 index 0000000000..a365f0860b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch @@ -0,0 +1,26 @@ +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -141,6 +141,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 +@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl- + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o + obj-$(CONFIG_PINCTRL_MT7981) += 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 diff --git a/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch b/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch new file mode 100644 index 0000000000..ad4ecdf83f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch @@ -0,0 +1,75 @@ +From cc4d9e0c77494fcf6bccbc57e23db0007cf681b7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 26 Jan 2023 03:33:46 +0000 +Subject: [PATCH] dt-bindings: clock: Add compatibles for MT7981 + +Add compatible string for MT7981 to existing bindings at + - mediatek,apmixedsys.yaml + - mediatek,topckgen.yaml + - mediatek,ethsys.txt + - mediatek,infracfg.yaml + - mediatek,sgmiisys.txt + +Signed-off-by: Jianhui Zhao +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/cc85ee470c781ff4013f6c21c92c0a21574b12b2.1674703830.git.daniel@makrotopia.org +Signed-off-by: Stephen Boyd +--- + .../devicetree/bindings/arm/mediatek/mediatek,ethsys.txt | 1 + + .../devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml | 1 + + .../devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt | 2 ++ + .../devicetree/bindings/clock/mediatek,apmixedsys.yaml | 1 + + Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml | 1 + + 5 files changed, 6 insertions(+) + +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +@@ -10,6 +10,7 @@ Required Properties: + - "mediatek,mt7622-ethsys", "syscon" + - "mediatek,mt7623-ethsys", "mediatek,mt2701-ethsys", "syscon" + - "mediatek,mt7629-ethsys", "syscon" ++ - "mediatek,mt7981-ethsys", "syscon" + - "mediatek,mt7986-ethsys", "syscon" + - #clock-cells: Must be 1 + - #reset-cells: Must be 1 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml +@@ -28,6 +28,7 @@ properties: + - mediatek,mt6797-infracfg + - mediatek,mt7622-infracfg + - mediatek,mt7629-infracfg ++ - mediatek,mt7981-infracfg + - mediatek,mt7986-infracfg + - mediatek,mt8135-infracfg + - mediatek,mt8167-infracfg +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt +@@ -8,6 +8,8 @@ Required Properties: + - compatible: Should be: + - "mediatek,mt7622-sgmiisys", "syscon" + - "mediatek,mt7629-sgmiisys", "syscon" ++ - "mediatek,mt7981-sgmiisys_0", "syscon" ++ - "mediatek,mt7981-sgmiisys_1", "syscon" + - "mediatek,mt7986-sgmiisys_0", "syscon" + - "mediatek,mt7986-sgmiisys_1", "syscon" + - #clock-cells: Must be 1 +--- a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml ++++ b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml +@@ -20,6 +20,7 @@ properties: + - enum: + - mediatek,mt6797-apmixedsys + - mediatek,mt7622-apmixedsys ++ - mediatek,mt7981-apmixedsys + - mediatek,mt7986-apmixedsys + - mediatek,mt8135-apmixedsys + - mediatek,mt8173-apmixedsys +--- a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml ++++ b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml +@@ -35,6 +35,7 @@ properties: + - mediatek,mt6779-topckgen + - mediatek,mt6795-topckgen + - mediatek,mt7629-topckgen ++ - mediatek,mt7981-topckgen + - mediatek,mt7986-topckgen + - mediatek,mt8167-topckgen + - mediatek,mt8183-topckgen diff --git a/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch b/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch new file mode 100644 index 0000000000..48d3d4e90c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch @@ -0,0 +1,107 @@ +From d4f08a703565abf47baa5a77d05365cf4598d55c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:56:52 +0000 +Subject: [PATCH 1/2] dt-bindings: arm: mediatek: sgmiisys: Convert to DT + schema + +Convert mediatek,sgmiiisys bindings to DT schema format. +Add maintainer Matthias Brugger, no maintainers were listed in the +original documentation. +As this node is also referenced by the Ethernet controller and used +as SGMII PCS add this fact to the description. +Move the file to Documentation/devicetree/bindings/net/pcs/ which seems +more appropriate given that the great majority of registers are related +to SGMII PCS functionality and only one register represents clock bits. + +Reviewed-by: Rob Herring +Signed-off-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + .../arm/mediatek/mediatek,sgmiisys.txt | 27 ---------- + .../bindings/net/pcs/mediatek,sgmiisys.yaml | 49 +++++++++++++++++++ + 2 files changed, 49 insertions(+), 27 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt + create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml + +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt ++++ /dev/null +@@ -1,27 +0,0 @@ +-MediaTek SGMIISYS controller +-============================ +- +-The MediaTek SGMIISYS controller provides various clocks to the system. +- +-Required Properties: +- +-- compatible: Should be: +- - "mediatek,mt7622-sgmiisys", "syscon" +- - "mediatek,mt7629-sgmiisys", "syscon" +- - "mediatek,mt7981-sgmiisys_0", "syscon" +- - "mediatek,mt7981-sgmiisys_1", "syscon" +- - "mediatek,mt7986-sgmiisys_0", "syscon" +- - "mediatek,mt7986-sgmiisys_1", "syscon" +-- #clock-cells: Must be 1 +- +-The SGMIISYS controller uses the common clk binding from +-Documentation/devicetree/bindings/clock/clock-bindings.txt +-The available clocks are defined in dt-bindings/clock/mt*-clk.h. +- +-Example: +- +-sgmiisys: sgmiisys@1b128000 { +- compatible = "mediatek,mt7622-sgmiisys", "syscon"; +- reg = <0 0x1b128000 0 0x1000>; +- #clock-cells = <1>; +-}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +@@ -0,0 +1,49 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/pcs/mediatek,sgmiisys.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek SGMIISYS Controller ++ ++maintainers: ++ - Matthias Brugger ++ ++description: ++ The MediaTek SGMIISYS controller provides a SGMII PCS and some clocks ++ to the ethernet subsystem to which it is attached. ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - mediatek,mt7622-sgmiisys ++ - mediatek,mt7629-sgmiisys ++ - mediatek,mt7986-sgmiisys_0 ++ - mediatek,mt7986-sgmiisys_1 ++ - const: syscon ++ ++ reg: ++ maxItems: 1 ++ ++ '#clock-cells': ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - '#clock-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ sgmiisys: syscon@1b128000 { ++ compatible = "mediatek,mt7622-sgmiisys", "syscon"; ++ reg = <0 0x1b128000 0 0x1000>; ++ #clock-cells = <1>; ++ }; ++ }; diff --git a/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch b/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch new file mode 100644 index 0000000000..62a64b9dd0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch @@ -0,0 +1,37 @@ +From 4f7eb19c4f44078100659f6ba073b0cc7191bc91 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 19 Mar 2023 12:57:04 +0000 +Subject: [PATCH 2/2] dt-bindings: net: pcs: mediatek,sgmiisys: add MT7981 SoC + +Add mediatek,pnswap boolean property needed on many boards using the +MediaTek MT7981 SoC. + +Reviewed-by: Rob Herring +Signed-off-by: Daniel Golle +Signed-off-by: Jakub Kicinski +--- + .../devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +@@ -19,6 +19,8 @@ properties: + - enum: + - mediatek,mt7622-sgmiisys + - mediatek,mt7629-sgmiisys ++ - mediatek,mt7981-sgmiisys_0 ++ - mediatek,mt7981-sgmiisys_1 + - mediatek,mt7986-sgmiisys_0 + - mediatek,mt7986-sgmiisys_1 + - const: syscon +@@ -29,6 +31,10 @@ properties: + '#clock-cells': + const: 1 + ++ mediatek,pnswap: ++ description: Invert polarity of the SGMII data lanes ++ type: boolean ++ + required: + - compatible + - reg diff --git a/target/linux/mediatek/patches-6.6/244-v6.8-dt-bindings-arm-mediatek-move-ethsys-controller-conv.patch b/target/linux/mediatek/patches-6.6/244-v6.8-dt-bindings-arm-mediatek-move-ethsys-controller-conv.patch new file mode 100644 index 0000000000..946db82235 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/244-v6.8-dt-bindings-arm-mediatek-move-ethsys-controller-conv.patch @@ -0,0 +1,113 @@ +From 94b0f301f6ee92f79a2fe2c655dfdbdfe2aec536 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sun, 19 Nov 2023 22:24:16 +0100 +Subject: [PATCH] dt-bindings: arm: mediatek: move ethsys controller & convert + to DT schema +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +DT schema helps validating DTS files. Binding was moved to clock/ as +this hardware is a clock provider. Example required a small fix for +"reg" value (1 address cell + 1 size cell). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20231119212416.2682-1-zajec5@gmail.com +Signed-off-by: Stephen Boyd +--- + .../bindings/arm/mediatek/mediatek,ethsys.txt | 29 ---------- + .../bindings/clock/mediatek,ethsys.yaml | 54 +++++++++++++++++++ + 2 files changed, 54 insertions(+), 29 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt + create mode 100644 Documentation/devicetree/bindings/clock/mediatek,ethsys.yaml + +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt ++++ /dev/null +@@ -1,29 +0,0 @@ +-Mediatek ethsys controller +-============================ +- +-The Mediatek ethsys controller provides various clocks to the system. +- +-Required Properties: +- +-- compatible: Should be: +- - "mediatek,mt2701-ethsys", "syscon" +- - "mediatek,mt7622-ethsys", "syscon" +- - "mediatek,mt7623-ethsys", "mediatek,mt2701-ethsys", "syscon" +- - "mediatek,mt7629-ethsys", "syscon" +- - "mediatek,mt7981-ethsys", "syscon" +- - "mediatek,mt7986-ethsys", "syscon" +-- #clock-cells: Must be 1 +-- #reset-cells: Must be 1 +- +-The ethsys controller uses the common clk binding from +-Documentation/devicetree/bindings/clock/clock-bindings.txt +-The available clocks are defined in dt-bindings/clock/mt*-clk.h. +- +-Example: +- +-ethsys: clock-controller@1b000000 { +- compatible = "mediatek,mt2701-ethsys", "syscon"; +- reg = <0 0x1b000000 0 0x1000>; +- #clock-cells = <1>; +- #reset-cells = <1>; +-}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/mediatek,ethsys.yaml +@@ -0,0 +1,54 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/mediatek,ethsys.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Mediatek ethsys controller ++ ++description: ++ The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++maintainers: ++ - James Liao ++ ++properties: ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - mediatek,mt2701-ethsys ++ - mediatek,mt7622-ethsys ++ - mediatek,mt7629-ethsys ++ - mediatek,mt7981-ethsys ++ - mediatek,mt7986-ethsys ++ - const: syscon ++ - items: ++ - const: mediatek,mt7623-ethsys ++ - const: mediatek,mt2701-ethsys ++ - const: syscon ++ ++ reg: ++ maxItems: 1 ++ ++ "#clock-cells": ++ const: 1 ++ ++ "#reset-cells": ++ const: 1 ++ ++required: ++ - reg ++ - "#clock-cells" ++ - "#reset-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ clock-controller@1b000000 { ++ compatible = "mediatek,mt2701-ethsys", "syscon"; ++ reg = <0x1b000000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; diff --git a/target/linux/mediatek/patches-6.6/245-v6.8-dt-bindings-reset-mediatek-add-MT7988-ethwarp-reset-.patch b/target/linux/mediatek/patches-6.6/245-v6.8-dt-bindings-reset-mediatek-add-MT7988-ethwarp-reset-.patch new file mode 100644 index 0000000000..47f05e93c6 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/245-v6.8-dt-bindings-reset-mediatek-add-MT7988-ethwarp-reset-.patch @@ -0,0 +1,35 @@ +From 5cfa3beb7761cb84be77225902e018d9d3f9b973 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 17 Dec 2023 21:49:45 +0000 +Subject: [PATCH 1/4] dt-bindings: reset: mediatek: add MT7988 ethwarp reset + IDs + +Add reset ID for ethwarp subsystem allowing to reset the built-in +Ethernet switch of the MediaTek MT7988 SoC. + +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/0c14bbacf471683af67ffa7572bfa1d5c45a0b5d.1702849494.git.daniel@makrotopia.org +Signed-off-by: Stephen Boyd +--- + include/dt-bindings/reset/mediatek,mt7988-resets.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + create mode 100644 include/dt-bindings/reset/mediatek,mt7988-resets.h + +--- /dev/null ++++ b/include/dt-bindings/reset/mediatek,mt7988-resets.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (c) 2023 Daniel Golle ++ * Author: Daniel Golle ++ */ ++ ++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7988 ++#define _DT_BINDINGS_RESET_CONTROLLER_MT7988 ++ ++/* ETHWARP resets */ ++#define MT7988_ETHWARP_RST_SWITCH 0 ++ ++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7988 */ diff --git a/target/linux/mediatek/patches-6.6/246-v6.8-dt-bindings-clock-mediatek-add-MT7988-clock-IDs.patch b/target/linux/mediatek/patches-6.6/246-v6.8-dt-bindings-clock-mediatek-add-MT7988-clock-IDs.patch new file mode 100644 index 0000000000..cf5cae6341 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/246-v6.8-dt-bindings-clock-mediatek-add-MT7988-clock-IDs.patch @@ -0,0 +1,302 @@ +From 8187e001de156e99ef95366ffd10d627ed090826 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 17 Dec 2023 21:49:33 +0000 +Subject: [PATCH] dt-bindings: clock: mediatek: add MT7988 clock IDs + +Add MT7988 clock dt-bindings for topckgen, apmixedsys, infracfg, +ethernet and xfipll subsystem clocks. + +Signed-off-by: Sam Shih +Signed-off-by: Daniel Golle +Acked-by: Krzysztof Kozlowski +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/27f99db432e9ccc804cc5b6501d7d17d72cae879.1702849494.git.daniel@makrotopia.org +Signed-off-by: Stephen Boyd +--- + .../dt-bindings/clock/mediatek,mt7988-clk.h | 280 ++++++++++++++++++ + 1 file changed, 280 insertions(+) + create mode 100644 include/dt-bindings/clock/mediatek,mt7988-clk.h + +--- /dev/null ++++ b/include/dt-bindings/clock/mediatek,mt7988-clk.h +@@ -0,0 +1,280 @@ ++/* 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 ++ ++/* XFIPLL */ ++#define CLK_XFIPLL_PLL 0 ++#define CLK_XFIPLL_PLL_EN 1 ++ ++#endif /* _DT_BINDINGS_CLK_MT7988_H */ diff --git a/target/linux/mediatek/patches-6.6/247-v6.8-dt-bindings-clock-mediatek-add-clock-controllers-of-.patch b/target/linux/mediatek/patches-6.6/247-v6.8-dt-bindings-clock-mediatek-add-clock-controllers-of-.patch new file mode 100644 index 0000000000..79088b461b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/247-v6.8-dt-bindings-clock-mediatek-add-clock-controllers-of-.patch @@ -0,0 +1,260 @@ +From afd36e9d91b0a840983b829a9e95407d8151f7e7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 17 Dec 2023 21:49:55 +0000 +Subject: [PATCH 2/4] dt-bindings: clock: mediatek: add clock controllers of + MT7988 + +Add various clock controllers found in the MT7988 SoC to existing +bindings (if applicable) and add files for the new ethwarp, mcusys +and xfi-pll clock controllers not previously present in any SoC. + +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/07e76a544ce4392bcb88e34d5480e99bb7994618.1702849494.git.daniel@makrotopia.org +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Stephen Boyd +--- + .../arm/mediatek/mediatek,infracfg.yaml | 1 + + .../bindings/clock/mediatek,apmixedsys.yaml | 1 + + .../bindings/clock/mediatek,ethsys.yaml | 1 + + .../clock/mediatek,mt7988-ethwarp.yaml | 52 +++++++++++++++ + .../clock/mediatek,mt7988-xfi-pll.yaml | 48 ++++++++++++++ + .../bindings/clock/mediatek,topckgen.yaml | 2 + + .../bindings/net/pcs/mediatek,sgmiisys.yaml | 65 ++++++++++++++++--- + 7 files changed, 161 insertions(+), 9 deletions(-) + create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt7988-ethwarp.yaml + create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mt7988-xfi-pll.yaml + +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml +@@ -30,6 +30,7 @@ properties: + - mediatek,mt7629-infracfg + - mediatek,mt7981-infracfg + - mediatek,mt7986-infracfg ++ - mediatek,mt7988-infracfg + - mediatek,mt8135-infracfg + - mediatek,mt8167-infracfg + - mediatek,mt8173-infracfg +--- a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml ++++ b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml +@@ -22,6 +22,7 @@ properties: + - mediatek,mt7622-apmixedsys + - mediatek,mt7981-apmixedsys + - mediatek,mt7986-apmixedsys ++ - mediatek,mt7988-apmixedsys + - mediatek,mt8135-apmixedsys + - mediatek,mt8173-apmixedsys + - mediatek,mt8516-apmixedsys +--- a/Documentation/devicetree/bindings/clock/mediatek,ethsys.yaml ++++ b/Documentation/devicetree/bindings/clock/mediatek,ethsys.yaml +@@ -22,6 +22,7 @@ properties: + - mediatek,mt7629-ethsys + - mediatek,mt7981-ethsys + - mediatek,mt7986-ethsys ++ - mediatek,mt7988-ethsys + - const: syscon + - items: + - const: mediatek,mt7623-ethsys +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/mediatek,mt7988-ethwarp.yaml +@@ -0,0 +1,52 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/mediatek,mt7988-ethwarp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek MT7988 ethwarp Controller ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The Mediatek MT7988 ethwarp controller provides clocks and resets for the ++ Ethernet related subsystems found the MT7988 SoC. ++ The clock values can be found in . ++ ++properties: ++ compatible: ++ items: ++ - const: mediatek,mt7988-ethwarp ++ ++ reg: ++ maxItems: 1 ++ ++ '#clock-cells': ++ const: 1 ++ ++ '#reset-cells': ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - '#clock-cells' ++ - '#reset-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ clock-controller@15031000 { ++ compatible = "mediatek,mt7988-ethwarp"; ++ reg = <0 0x15031000 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/mediatek,mt7988-xfi-pll.yaml +@@ -0,0 +1,48 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/mediatek,mt7988-xfi-pll.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek MT7988 XFI PLL Clock Controller ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek XFI PLL controller provides the 156.25MHz clock for the ++ Ethernet SerDes PHY from the 40MHz top_xtal clock. ++ ++properties: ++ compatible: ++ const: mediatek,mt7988-xfi-pll ++ ++ reg: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ '#clock-cells': ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - resets ++ - '#clock-cells' ++ ++additionalProperties: false ++ ++examples: ++ - | ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ clock-controller@11f40000 { ++ compatible = "mediatek,mt7988-xfi-pll"; ++ reg = <0 0x11f40000 0 0x1000>; ++ resets = <&watchdog 16>; ++ #clock-cells = <1>; ++ }; ++ }; +--- a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml ++++ b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml +@@ -37,6 +37,8 @@ properties: + - mediatek,mt7629-topckgen + - mediatek,mt7981-topckgen + - mediatek,mt7986-topckgen ++ - mediatek,mt7988-mcusys ++ - mediatek,mt7988-topckgen + - mediatek,mt8167-topckgen + - mediatek,mt8183-topckgen + - const: syscon +--- a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +@@ -15,15 +15,22 @@ description: + + properties: + compatible: +- items: +- - enum: +- - mediatek,mt7622-sgmiisys +- - mediatek,mt7629-sgmiisys +- - mediatek,mt7981-sgmiisys_0 +- - mediatek,mt7981-sgmiisys_1 +- - mediatek,mt7986-sgmiisys_0 +- - mediatek,mt7986-sgmiisys_1 +- - const: syscon ++ oneOf: ++ - items: ++ - enum: ++ - mediatek,mt7622-sgmiisys ++ - mediatek,mt7629-sgmiisys ++ - mediatek,mt7981-sgmiisys_0 ++ - mediatek,mt7981-sgmiisys_1 ++ - mediatek,mt7986-sgmiisys_0 ++ - mediatek,mt7986-sgmiisys_1 ++ - const: syscon ++ - items: ++ - enum: ++ - mediatek,mt7988-sgmiisys0 ++ - mediatek,mt7988-sgmiisys1 ++ - const: simple-mfd ++ - const: syscon + + reg: + maxItems: 1 +@@ -35,11 +42,51 @@ properties: + description: Invert polarity of the SGMII data lanes + type: boolean + ++ pcs: ++ type: object ++ description: MediaTek LynxI HSGMII PCS ++ properties: ++ compatible: ++ const: mediatek,mt7988-sgmii ++ ++ clocks: ++ maxItems: 3 ++ ++ clock-names: ++ items: ++ - const: sgmii_sel ++ - const: sgmii_tx ++ - const: sgmii_rx ++ ++ required: ++ - compatible ++ - clocks ++ - clock-names ++ ++ additionalProperties: false ++ + required: + - compatible + - reg + - '#clock-cells' + ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - mediatek,mt7988-sgmiisys0 ++ - mediatek,mt7988-sgmiisys1 ++ ++ then: ++ required: ++ - pcs ++ ++ else: ++ properties: ++ pcs: false ++ + additionalProperties: false + + examples: diff --git a/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch b/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch new file mode 100644 index 0000000000..ca37fc793a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch @@ -0,0 +1,50 @@ +From d9bf944beaaad1890ad3fcb755c61e1c7e4c5630 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 17 Dec 2023 21:50:07 +0000 +Subject: [PATCH 3/4] clk: mediatek: add pcw_chg_bit control for PLLs of MT7988 + +Introduce pcw_chg_bit member to struct mtk_pll_data and use it instead +of the previously hardcoded PCW_CHG_MASK macro if set. +This will needed for clocks on the MT7988 SoC. + +Signed-off-by: Sam Shih +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/3b9c65ddb08c8bedf790aacf29871af026b6f0b7.1702849494.git.daniel@makrotopia.org +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/clk-pll.c | 5 +++-- + drivers/clk/mediatek/clk-pll.h | 1 + + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/clk/mediatek/clk-pll.c ++++ b/drivers/clk/mediatek/clk-pll.c +@@ -23,7 +23,7 @@ + #define CON0_BASE_EN BIT(0) + #define CON0_PWR_ON BIT(0) + #define CON0_ISO_EN BIT(1) +-#define PCW_CHG_MASK BIT(31) ++#define PCW_CHG_BIT 31 + + #define AUDPLL_TUNER_EN BIT(31) + +@@ -141,7 +141,8 @@ 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; ++ chg = readl(pll->pcw_chg_addr) | ++ BIT(pll->data->pcw_chg_bit ? : PCW_CHG_BIT); + writel(chg, pll->pcw_chg_addr); + if (pll->tuner_addr) + writel(val + 1, pll->tuner_addr); +--- a/drivers/clk/mediatek/clk-pll.h ++++ b/drivers/clk/mediatek/clk-pll.h +@@ -46,6 +46,7 @@ struct mtk_pll_data { + const char *parent_name; + u32 en_reg; + u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ ++ u8 pcw_chg_bit; + }; + + int mtk_clk_register_plls(struct device_node *node, diff --git a/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch new file mode 100644 index 0000000000..61664b934c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch @@ -0,0 +1,1026 @@ +From 4b4719437d85f0173d344f2c76fa1a5b7f7d184b Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 17 Dec 2023 21:50:15 +0000 +Subject: [PATCH 4/4] clk: mediatek: add drivers for MT7988 SoC + +Add APMIXED, ETH, INFRACFG and TOPCKGEN clock drivers which are +typical MediaTek designs. + +Also add driver for XFIPLL clock generating the 156.25MHz clock for +the XFI SerDes. It needs an undocumented software workaround and has +an unknown internal design. + +Signed-off-by: Sam Shih +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/c7574d808e2da1a530182f0fd790c1337c336e1b.1702849494.git.daniel@makrotopia.org +[sboyd@kernel.org: Add module license to infracfg file] +Signed-off-by: Stephen Boyd +--- + drivers/clk/mediatek/Kconfig | 9 + + drivers/clk/mediatek/Makefile | 5 + + drivers/clk/mediatek/clk-mt7988-apmixed.c | 114 ++++++++ + drivers/clk/mediatek/clk-mt7988-eth.c | 150 ++++++++++ + drivers/clk/mediatek/clk-mt7988-infracfg.c | 275 +++++++++++++++++ + drivers/clk/mediatek/clk-mt7988-topckgen.c | 325 +++++++++++++++++++++ + drivers/clk/mediatek/clk-mt7988-xfipll.c | 82 ++++++ + 7 files changed, 960 insertions(+) + create mode 100644 drivers/clk/mediatek/clk-mt7988-apmixed.c + create mode 100644 drivers/clk/mediatek/clk-mt7988-eth.c + create mode 100644 drivers/clk/mediatek/clk-mt7988-infracfg.c + create mode 100644 drivers/clk/mediatek/clk-mt7988-topckgen.c + create mode 100644 drivers/clk/mediatek/clk-mt7988-xfipll.c + +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -415,6 +415,15 @@ config COMMON_CLK_MT7986_ETHSYS + This driver adds support for clocks for Ethernet and SGMII + required on MediaTek MT7986 SoC. + ++config COMMON_CLK_MT7988 ++ tristate "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 this SoC. ++ + 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 +@@ -60,6 +60,11 @@ 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_MT7988) += clk-mt7988-xfipll.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 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7988-apmixed.c +@@ -0,0 +1,114 @@ ++// 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 "clk-pll.h" ++#include ++ ++#define MT7988_PLL_FMAX (2500UL * MHZ) ++#define MT7988_PCW_CHG_BIT 2 ++ ++#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) \ ++ { \ ++ .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_bit = MT7988_PCW_CHG_BIT, \ ++ .parent_name = "clkxtal", \ ++ } ++ ++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" }, ++ { /* sentinel */ } ++}; ++ ++static int clk_mt7988_apmixed_probe(struct platform_device *pdev) ++{ ++ struct clk_hw_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; ++ ++ r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); ++ if (r) ++ goto free_apmixed_data; ++ ++ r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ++ if (r) ++ goto unregister_plls; ++ ++ return r; ++ ++unregister_plls: ++ mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); ++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); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7988-eth.c +@@ -0,0 +1,150 @@ ++// 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 "reset.h" ++#include ++#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 const struct mtk_clk_desc ethdma_desc = { ++ .clks = ethdma_clks, ++ .num_clks = ARRAY_SIZE(ethdma_clks), ++}; ++ ++static const struct mtk_gate_regs sgmii_cg_regs = { ++ .set_ofs = 0xe4, ++ .clr_ofs = 0xe4, ++ .sta_ofs = 0xe4, ++}; ++ ++#define GATE_SGMII(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &sgmii_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_gate sgmii0_clks[] = { ++ GATE_SGMII(CLK_SGM0_TX_EN, "sgm0_tx_en", "top_xtal", 2), ++ GATE_SGMII(CLK_SGM0_RX_EN, "sgm0_rx_en", "top_xtal", 3), ++}; ++ ++static const struct mtk_clk_desc sgmii0_desc = { ++ .clks = sgmii0_clks, ++ .num_clks = ARRAY_SIZE(sgmii0_clks), ++}; ++ ++static const struct mtk_gate sgmii1_clks[] = { ++ GATE_SGMII(CLK_SGM1_TX_EN, "sgm1_tx_en", "top_xtal", 2), ++ GATE_SGMII(CLK_SGM1_RX_EN, "sgm1_rx_en", "top_xtal", 3), ++}; ++ ++static const struct mtk_clk_desc sgmii1_desc = { ++ .clks = sgmii1_clks, ++ .num_clks = ARRAY_SIZE(sgmii1_clks), ++}; ++ ++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 u16 ethwarp_rst_ofs[] = { 0x8 }; ++ ++static u16 ethwarp_idx_map[] = { ++ [MT7988_ETHWARP_RST_SWITCH] = 9, ++}; ++ ++static const struct mtk_clk_rst_desc ethwarp_rst_desc = { ++ .version = MTK_RST_SIMPLE, ++ .rst_bank_ofs = ethwarp_rst_ofs, ++ .rst_bank_nr = ARRAY_SIZE(ethwarp_rst_ofs), ++ .rst_idx_map = ethwarp_idx_map, ++ .rst_idx_map_nr = ARRAY_SIZE(ethwarp_idx_map), ++}; ++ ++static const struct mtk_clk_desc ethwarp_desc = { ++ .clks = ethwarp_clks, ++ .num_clks = ARRAY_SIZE(ethwarp_clks), ++ .rst_desc = ðwarp_rst_desc, ++}; ++ ++static const struct of_device_id of_match_clk_mt7988_eth[] = { ++ { .compatible = "mediatek,mt7988-ethsys", .data = ðdma_desc }, ++ { .compatible = "mediatek,mt7988-sgmiisys0", .data = &sgmii0_desc }, ++ { .compatible = "mediatek,mt7988-sgmiisys1", .data = &sgmii1_desc }, ++ { .compatible = "mediatek,mt7988-ethwarp", .data = ðwarp_desc }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_eth); ++ ++static struct platform_driver clk_mt7988_eth_drv = { ++ .driver = { ++ .name = "clk-mt7988-eth", ++ .of_match_table = of_match_clk_mt7988_eth, ++ }, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++}; ++module_platform_driver(clk_mt7988_eth_drv); ++ ++MODULE_DESCRIPTION("MediaTek MT7988 Ethernet clocks driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c +@@ -0,0 +1,275 @@ ++// 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) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr, \ ++ _flags) ++ ++#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flags) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &infra1_cg_regs, _shift, &mtk_clk_gate_ops_setclr, \ ++ _flags) ++ ++#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flags) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr, \ ++ _flags) ++ ++#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flags) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs, _shift, &mtk_clk_gate_ops_setclr, \ ++ _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_FLAGS(CLK_INFRA_RTC, "infra_f_frtc", "top_rtc_32k", 19, CLK_IS_CRITICAL), ++ 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 const struct mtk_clk_desc infra_desc = { ++ .clks = infra_clks, ++ .num_clks = ARRAY_SIZE(infra_clks), ++ .mux_clks = infra_muxes, ++ .num_mux_clks = ARRAY_SIZE(infra_muxes), ++ .clk_lock = &mt7988_clk_lock, ++}; ++ ++static const struct of_device_id of_match_clk_mt7988_infracfg[] = { ++ { .compatible = "mediatek,mt7988-infracfg", .data = &infra_desc }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_infracfg); ++ ++static struct platform_driver clk_mt7988_infracfg_drv = { ++ .driver = { ++ .name = "clk-mt7988-infracfg", ++ .of_match_table = of_match_clk_mt7988_infracfg, ++ }, ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++}; ++module_platform_driver(clk_mt7988_infracfg_drv); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7988-topckgen.c +@@ -0,0 +1,325 @@ ++// 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 const struct mtk_clk_desc topck_desc = { ++ .fixed_clks = top_fixed_clks, ++ .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), ++ .factor_clks = top_divs, ++ .num_factor_clks = ARRAY_SIZE(top_divs), ++ .mux_clks = top_muxes, ++ .num_mux_clks = ARRAY_SIZE(top_muxes), ++ .composite_clks = top_aud_divs, ++ .num_composite_clks = ARRAY_SIZE(top_aud_divs), ++ .clk_lock = &mt7988_clk_lock, ++}; ++ ++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 const struct mtk_clk_desc mcusys_desc = { ++ .composite_clks = mcu_muxes, ++ .num_composite_clks = ARRAY_SIZE(mcu_muxes), ++}; ++ ++static const struct of_device_id of_match_clk_mt7988_topckgen[] = { ++ { .compatible = "mediatek,mt7988-topckgen", .data = &topck_desc }, ++ { .compatible = "mediatek,mt7988-mcusys", .data = &mcusys_desc }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_topckgen); ++ ++static struct platform_driver clk_mt7988_topckgen_drv = { ++ .probe = mtk_clk_simple_probe, ++ .remove = mtk_clk_simple_remove, ++ .driver = { ++ .name = "clk-mt7988-topckgen", ++ .of_match_table = of_match_clk_mt7988_topckgen, ++ }, ++}; ++module_platform_driver(clk_mt7988_topckgen_drv); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7988-xfipll.c +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2023 Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "clk-mtk.h" ++#include "clk-gate.h" ++#include ++ ++/* Register to control USXGMII XFI PLL analog */ ++#define XFI_PLL_ANA_GLB8 0x108 ++#define RG_XFI_PLL_ANA_SWWA 0x02283248 ++ ++static const struct mtk_gate_regs xfipll_cg_regs = { ++ .set_ofs = 0x8, ++ .clr_ofs = 0x8, ++ .sta_ofs = 0x8, ++}; ++ ++#define GATE_XFIPLL(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &xfipll_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_fixed_factor xfipll_divs[] = { ++ FACTOR(CLK_XFIPLL_PLL, "xfipll_pll", "top_xtal", 125, 32), ++}; ++ ++static const struct mtk_gate xfipll_clks[] = { ++ GATE_XFIPLL(CLK_XFIPLL_PLL_EN, "xfipll_pll_en", "xfipll_pll", 31), ++}; ++ ++static const struct mtk_clk_desc xfipll_desc = { ++ .clks = xfipll_clks, ++ .num_clks = ARRAY_SIZE(xfipll_clks), ++ .factor_clks = xfipll_divs, ++ .num_factor_clks = ARRAY_SIZE(xfipll_divs), ++}; ++ ++static int clk_mt7988_xfipll_probe(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ void __iomem *base = of_iomap(node, 0); ++ ++ if (!base) ++ return -ENOMEM; ++ ++ /* Apply software workaround for USXGMII PLL TCL issue */ ++ writel(RG_XFI_PLL_ANA_SWWA, base + XFI_PLL_ANA_GLB8); ++ iounmap(base); ++ ++ return mtk_clk_simple_probe(pdev); ++}; ++ ++static const struct of_device_id of_match_clk_mt7988_xfipll[] = { ++ { .compatible = "mediatek,mt7988-xfi-pll", .data = &xfipll_desc }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_xfipll); ++ ++static struct platform_driver clk_mt7988_xfipll_drv = { ++ .driver = { ++ .name = "clk-mt7988-xfipll", ++ .of_match_table = of_match_clk_mt7988_xfipll, ++ }, ++ .probe = clk_mt7988_xfipll_probe, ++ .remove = mtk_clk_simple_remove, ++}; ++module_platform_driver(clk_mt7988_xfipll_drv); ++ ++MODULE_DESCRIPTION("MediaTek MT7988 XFI PLL clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.6/250-clk-mediatek-add-infracfg-reset-controller-for-mt798.patch b/target/linux/mediatek/patches-6.6/250-clk-mediatek-add-infracfg-reset-controller-for-mt798.patch new file mode 100644 index 0000000000..cecf095e92 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/250-clk-mediatek-add-infracfg-reset-controller-for-mt798.patch @@ -0,0 +1,57 @@ +From 26ced94177b150710d94cf365002a09cc48950e9 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 17 Jan 2024 19:41:11 +0100 +Subject: [PATCH] clk: mediatek: add infracfg reset controller for mt7988 + +Infracfg can also operate as reset controller, add support for it. + +Signed-off-by: Frank Wunderlich +--- + drivers/clk/mediatek/clk-mt7988-infracfg.c | 23 ++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/clk/mediatek/clk-mt7988-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c +@@ -14,6 +14,10 @@ + #include "clk-gate.h" + #include "clk-mux.h" + #include ++#include ++ ++#define MT7988_INFRA_RST0_SET_OFFSET 0x70 ++#define MT7988_INFRA_RST1_SET_OFFSET 0x80 + + static DEFINE_SPINLOCK(mt7988_clk_lock); + +@@ -249,12 +253,31 @@ static const struct mtk_gate infra_clks[ + GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3", "sysaxi_sel", 31), + }; + ++static u16 infra_rst_ofs[] = { ++ MT7988_INFRA_RST0_SET_OFFSET, ++ MT7988_INFRA_RST1_SET_OFFSET, ++}; ++ ++static u16 infra_idx_map[] = { ++ [MT7988_INFRA_RST0_PEXTP_MAC_SWRST] = 0 * RST_NR_PER_BANK + 6, ++ [MT7988_INFRA_RST1_THERM_CTRL_SWRST] = 1 * RST_NR_PER_BANK + 9, ++}; ++ ++static struct mtk_clk_rst_desc infra_rst_desc = { ++ .version = MTK_RST_SET_CLR, ++ .rst_bank_ofs = infra_rst_ofs, ++ .rst_bank_nr = ARRAY_SIZE(infra_rst_ofs), ++ .rst_idx_map = infra_idx_map, ++ .rst_idx_map_nr = ARRAY_SIZE(infra_idx_map), ++}; ++ + static const struct mtk_clk_desc infra_desc = { + .clks = infra_clks, + .num_clks = ARRAY_SIZE(infra_clks), + .mux_clks = infra_muxes, + .num_mux_clks = ARRAY_SIZE(infra_muxes), + .clk_lock = &mt7988_clk_lock, ++ .rst_desc = &infra_rst_desc, + }; + + static const struct of_device_id of_match_clk_mt7988_infracfg[] = { diff --git a/target/linux/mediatek/patches-6.6/250-dt-bindings-reset-mediatek-add-MT7988-reset-IDs.patch b/target/linux/mediatek/patches-6.6/250-dt-bindings-reset-mediatek-add-MT7988-reset-IDs.patch new file mode 100644 index 0000000000..d353074e84 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/250-dt-bindings-reset-mediatek-add-MT7988-reset-IDs.patch @@ -0,0 +1,25 @@ +From 3c810da3206f2e52c92f9f15a87f05db4bbba734 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 17 Jan 2024 19:41:10 +0100 +Subject: [PATCH] dt-bindings: reset: mediatek: add MT7988 reset IDs + +Add reset constants for using as index in driver and dts. + +Signed-off-by: Frank Wunderlich +--- + include/dt-bindings/reset/mediatek,mt7988-resets.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/include/dt-bindings/reset/mediatek,mt7988-resets.h ++++ b/include/dt-bindings/reset/mediatek,mt7988-resets.h +@@ -10,4 +10,10 @@ + /* ETHWARP resets */ + #define MT7988_ETHWARP_RST_SWITCH 0 + ++/* INFRA resets */ ++#define MT7988_INFRA_RST0_PEXTP_MAC_SWRST 0 ++#define MT7988_INFRA_RST1_THERM_CTRL_SWRST 1 ++ ++ + #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7988 */ ++ diff --git a/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch b/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch new file mode 100644 index 0000000000..cb49ce1d25 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch @@ -0,0 +1,125 @@ +From 137c9e08e5e542d58aa606b0bb4f0990117309a0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 20 Nov 2023 18:22:31 +0000 +Subject: [PATCH] watchdog: mediatek: mt7988: add wdt support + +Add support for watchdog and reset generator unit of the MediaTek +MT7988 SoC. + +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/c0cf5f701801cce60470853fa15f1d9dced78c4f.1700504385.git.daniel@makrotopia.org +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/mtk_wdt.c | 42 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/drivers/watchdog/mtk_wdt.c ++++ b/drivers/watchdog/mtk_wdt.c +@@ -56,9 +56,13 @@ + #define WDT_SWSYSRST 0x18U + #define WDT_SWSYS_RST_KEY 0x88000000 + ++#define WDT_SWSYSRST_EN 0xfc ++ + #define DRV_NAME "mtk-wdt" + #define DRV_VERSION "1.0" + ++#define MT7988_TOPRGU_SW_RST_NUM 24 ++ + static bool nowayout = WATCHDOG_NOWAYOUT; + static unsigned int timeout; + +@@ -68,10 +72,12 @@ struct mtk_wdt_dev { + spinlock_t lock; /* protects WDT_SWSYSRST reg */ + struct reset_controller_dev rcdev; + bool disable_wdt_extrst; ++ bool has_swsysrst_en; + }; + + struct mtk_wdt_data { + int toprgu_sw_rst_num; ++ bool has_swsysrst_en; + }; + + static const struct mtk_wdt_data mt2712_data = { +@@ -82,6 +88,11 @@ static const struct mtk_wdt_data mt7986_ + .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM, + }; + ++static const struct mtk_wdt_data mt7988_data = { ++ .toprgu_sw_rst_num = MT7988_TOPRGU_SW_RST_NUM, ++ .has_swsysrst_en = true, ++}; ++ + static const struct mtk_wdt_data mt8183_data = { + .toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM, + }; +@@ -98,6 +109,28 @@ static const struct mtk_wdt_data mt8195_ + .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM, + }; + ++/** ++ * toprgu_reset_sw_en_unlocked() - enable/disable software control for reset bit ++ * @data: Pointer to instance of driver data. ++ * @id: Bit number identifying the reset to be enabled or disabled. ++ * @enable: If true, enable software control for that bit, disable otherwise. ++ * ++ * Context: The caller must hold lock of struct mtk_wdt_dev. ++ */ ++static void toprgu_reset_sw_en_unlocked(struct mtk_wdt_dev *data, ++ unsigned long id, bool enable) ++{ ++ u32 tmp; ++ ++ tmp = readl(data->wdt_base + WDT_SWSYSRST_EN); ++ if (enable) ++ tmp |= BIT(id); ++ else ++ tmp &= ~BIT(id); ++ ++ writel(tmp, data->wdt_base + WDT_SWSYSRST_EN); ++} ++ + static int toprgu_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +@@ -108,6 +141,9 @@ static int toprgu_reset_update(struct re + + spin_lock_irqsave(&data->lock, flags); + ++ if (assert && data->has_swsysrst_en) ++ toprgu_reset_sw_en_unlocked(data, id, true); ++ + tmp = readl(data->wdt_base + WDT_SWSYSRST); + if (assert) + tmp |= BIT(id); +@@ -116,6 +152,9 @@ static int toprgu_reset_update(struct re + tmp |= WDT_SWSYS_RST_KEY; + writel(tmp, data->wdt_base + WDT_SWSYSRST); + ++ if (!assert && data->has_swsysrst_en) ++ toprgu_reset_sw_en_unlocked(data, id, false); ++ + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +@@ -393,6 +432,8 @@ static int mtk_wdt_probe(struct platform + wdt_data->toprgu_sw_rst_num); + if (err) + return err; ++ ++ mtk_wdt->has_swsysrst_en = wdt_data->has_swsysrst_en; + } + + mtk_wdt->disable_wdt_extrst = +@@ -427,6 +468,7 @@ static const struct of_device_id mtk_wdt + { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, + { .compatible = "mediatek,mt6589-wdt" }, + { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, ++ { .compatible = "mediatek,mt7988-wdt", .data = &mt7988_data }, + { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, + { .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data }, + { .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data }, diff --git a/target/linux/mediatek/patches-6.6/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch b/target/linux/mediatek/patches-6.6/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch new file mode 100644 index 0000000000..c4760b9eff --- /dev/null +++ b/target/linux/mediatek/patches-6.6/252-clk-mediatek-mt7988-infracfg-fix-clocks-for-2nd-PCIe.patch @@ -0,0 +1,31 @@ +From c202f510bbaa34ab5d65a69a61e0e72761374b17 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 11 Mar 2024 17:14:19 +0000 +Subject: [PATCH] clk: mediatek: mt7988-infracfg: fix clocks for 2nd PCIe port + +Due to what seems to be an undocumented oddity in MediaTek's MT7988 +SoC design the CLK_INFRA_PCIE_PERI_26M_CK_P2 clock requires +CLK_INFRA_PCIE_PERI_26M_CK_P3 to be enabled. + +This currently leads to PCIe port 2 not working in Linux. + +Reflect the apparent relationship in the clk driver to make sure PCIe +port 2 of the MT7988 SoC works. + +Suggested-by: Sam Shih +Signed-off-by: Daniel Golle +--- + drivers/clk/mediatek/clk-mt7988-infracfg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/mediatek/clk-mt7988-infracfg.c ++++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c +@@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[ + 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), ++ "infra_pcie_peri_ck_26m_ck_p3", 9), + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3", + "csw_infra_f26m_sel", 10), + /* INFRA1 */ diff --git a/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch new file mode 100644 index 0000000000..5e3afd856f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch @@ -0,0 +1,47 @@ +From 24e961b93d292d0dd6380213d22a071a99ea787d Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Tue, 25 Oct 2022 15:29:53 +0200 +Subject: [PATCH 1/6] mmc: mediatek: add support for MT7986 SoC + +Adding mt7986 own characteristics and of_device_id to have support +of MT7986 SoC. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221025132953.81286-7-linux@fw-web.de +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/mtk-sd.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -552,6 +552,19 @@ static const struct mtk_mmc_compatible m + .support_64g = false, + }; + ++static const struct mtk_mmc_compatible mt7986_compat = { ++ .clk_div_bits = 12, ++ .recheck_sdio_irq = true, ++ .hs400_tune = false, ++ .pad_tune_reg = MSDC_PAD_TUNE0, ++ .async_fifo = true, ++ .data_tune = true, ++ .busy_check = true, ++ .stop_clk_fix = true, ++ .enhance_rx = true, ++ .support_64g = true, ++}; ++ + static const struct mtk_mmc_compatible mt8135_compat = { + .clk_div_bits = 8, + .recheck_sdio_irq = true, +@@ -609,6 +622,7 @@ static const struct of_device_id msdc_of + { .compatible = "mediatek,mt6795-mmc", .data = &mt6795_compat}, + { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, + { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, ++ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, + { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, + { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat}, diff --git a/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch b/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch new file mode 100644 index 0000000000..db2802bd0f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch @@ -0,0 +1,57 @@ +From 7b438d0377fbd520b475a68bdd9de1692393f22d Mon Sep 17 00:00:00 2001 +From: Mengqi Zhang +Date: Sun, 6 Nov 2022 11:39:24 +0800 +Subject: [PATCH 2/6] mmc: mtk-sd: add Inline Crypto Engine clock control + +Add crypto clock control and ungate it before CQHCI init. + +Signed-off-by: Mengqi Zhang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221106033924.9854-2-mengqi.zhang@mediatek.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/mtk-sd.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -452,6 +452,7 @@ struct msdc_host { + struct clk *bus_clk; /* bus clock which used to access register */ + struct clk *src_clk_cg; /* msdc source clock control gate */ + struct clk *sys_clk_cg; /* msdc subsys clock control gate */ ++ struct clk *crypto_clk; /* msdc crypto clock control gate */ + struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; + u32 mclk; /* mmc subsystem clock frequency */ + u32 src_clk_freq; /* source clock frequency */ +@@ -840,6 +841,7 @@ static void msdc_set_busy_timeout(struct + static void msdc_gate_clock(struct msdc_host *host) + { + clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); ++ clk_disable_unprepare(host->crypto_clk); + clk_disable_unprepare(host->src_clk_cg); + clk_disable_unprepare(host->src_clk); + clk_disable_unprepare(host->bus_clk); +@@ -855,6 +857,7 @@ static int msdc_ungate_clock(struct msdc + clk_prepare_enable(host->bus_clk); + clk_prepare_enable(host->src_clk); + clk_prepare_enable(host->src_clk_cg); ++ clk_prepare_enable(host->crypto_clk); + ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); + if (ret) { + dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); +@@ -2670,6 +2673,15 @@ static int msdc_drv_probe(struct platfor + goto host_free; + } + ++ /* only eMMC has crypto property */ ++ if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) { ++ host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto"); ++ if (IS_ERR(host->crypto_clk)) ++ host->crypto_clk = NULL; ++ else ++ mmc->caps2 |= MMC_CAP2_CRYPTO; ++ } ++ + host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) { + ret = host->irq; diff --git a/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch b/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch new file mode 100644 index 0000000000..921d249f8c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch @@ -0,0 +1,36 @@ +From 4b323f02b6e8df1b04292635ef829e7f723bf50e Mon Sep 17 00:00:00 2001 +From: Yu Zhe +Date: Thu, 10 Nov 2022 15:28:19 +0800 +Subject: [PATCH 3/6] mmc: mtk-sd: fix two spelling mistakes in comment + +spelling mistake fix : "alreay" -> "already" + "checksume" -> "checksum" + +Signed-off-by: Yu Zhe +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221110072819.11530-1-yuzhe@nfschina.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/mtk-sd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -750,7 +750,7 @@ static inline void msdc_dma_setup(struct + else + bd[j].bd_info &= ~BDMA_DESC_EOL; + +- /* checksume need to clear first */ ++ /* checksum need to clear first */ + bd[j].bd_info &= ~BDMA_DESC_CHECKSUM; + bd[j].bd_info |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8; + } +@@ -1229,7 +1229,7 @@ static bool msdc_cmd_done(struct msdc_ho + !host->hs400_tuning)) + /* + * should not clear fifo/interrupt as the tune data +- * may have alreay come when cmd19/cmd21 gets response ++ * may have already come when cmd19/cmd21 gets response + * CRC error. + */ + msdc_reset_hw(host); diff --git a/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch b/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch new file mode 100644 index 0000000000..8e2151e16b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch @@ -0,0 +1,39 @@ +From b98e7e8daf0ebab9dcc36812378a71e1be0b5089 Mon Sep 17 00:00:00 2001 +From: ChanWoo Lee +Date: Thu, 24 Nov 2022 17:00:31 +0900 +Subject: [PATCH 4/6] mmc: Avoid open coding by using mmc_op_tuning() + +Replace code with the already defined function. No functional changes. + +Signed-off-by: ChanWoo Lee +Reviewed-by: Adrian Hunter +Link: https://lore.kernel.org/r/20221124080031.14690-1-cw9316.lee@samsung.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/mtk-sd.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -1224,9 +1224,7 @@ static bool msdc_cmd_done(struct msdc_ho + + if (!sbc_error && !(events & MSDC_INT_CMDRDY)) { + if (events & MSDC_INT_CMDTMO || +- (cmd->opcode != MMC_SEND_TUNING_BLOCK && +- cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && +- !host->hs400_tuning)) ++ (!mmc_op_tuning(cmd->opcode) && !host->hs400_tuning)) + /* + * should not clear fifo/interrupt as the tune data + * may have already come when cmd19/cmd21 gets response +@@ -1320,9 +1318,7 @@ static void msdc_cmd_next(struct msdc_ho + { + if ((cmd->error && + !(cmd->error == -EILSEQ && +- (cmd->opcode == MMC_SEND_TUNING_BLOCK || +- cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200 || +- host->hs400_tuning))) || ++ (mmc_op_tuning(cmd->opcode) || host->hs400_tuning))) || + (mrq->sbc && mrq->sbc->error)) + msdc_request_done(host, mrq); + else if (cmd == mrq->sbc) diff --git a/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch b/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch new file mode 100644 index 0000000000..55a308e46c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch @@ -0,0 +1,34 @@ +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) + { +@@ -1344,6 +1345,7 @@ static int spinand_probe(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_attach(mtd); + ret = mtd_device_register(mtd, NULL, 0); + if (ret) + goto err_spinand_cleanup; +@@ -1351,6 +1353,7 @@ static int spinand_probe(struct spi_mem + return 0; + + err_spinand_cleanup: ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return ret; +@@ -1369,6 +1372,7 @@ static int spinand_remove(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return 0; diff --git a/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch new file mode 100644 index 0000000000..3e956701cd --- /dev/null +++ b/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch @@ -0,0 +1,10 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -548,6 +548,7 @@ + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + nand-ecc-engine = <&snfi>; ++ mediatek,bmt-v2; + + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch b/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch new file mode 100644 index 0000000000..ec66363dc9 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch @@ -0,0 +1,122 @@ +From 5f49a5c9b16330e0df8f639310e4715dcad71947 Mon Sep 17 00:00:00 2001 +From: Davide Fioravanti +Date: Fri, 8 Jan 2021 15:35:24 +0100 +Subject: [PATCH] mtd: spinand: Add support for the Fidelix FM35X1GA + +Datasheet: http://www.hobos.com.cn/upload/datasheet/DS35X1GAXXX_100_rev00.pdf + +Signed-off-by: Davide Fioravanti +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/fidelix.c | 76 ++++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 79 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/fidelix.c + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o ato.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs := core.o ato.o esmt.o etron.o fidelix.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -940,6 +940,7 @@ static const struct nand_ops spinand_ops + static const struct spinand_manufacturer *spinand_manufacturers[] = { + &ato_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, ++ &fidelix_spinand_manufacturer, + &etron_spinand_manufacturer, + &gigadevice_spinand_manufacturer, + ¯onix_spinand_manufacturer, +--- /dev/null ++++ b/drivers/mtd/nand/spi/fidelix.c +@@ -0,0 +1,76 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2020 Davide Fioravanti ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_FIDELIX 0xE5 ++#define FIDELIX_ECCSR_MASK 0x0F ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int fm35x1ga_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 8; ++ region->length = 8; ++ ++ return 0; ++} ++ ++static int fm35x1ga_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 2; ++ region->length = 6; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops fm35x1ga_ooblayout = { ++ .ecc = fm35x1ga_ooblayout_ecc, ++ .free = fm35x1ga_ooblayout_free, ++}; ++ ++static const struct spinand_info fidelix_spinand_table[] = { ++ SPINAND_INFO("FM35X1GA", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm35x1ga_ooblayout, NULL)), ++}; ++ ++static const struct spinand_manufacturer_ops fidelix_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer fidelix_spinand_manufacturer = { ++ .id = SPINAND_MFR_FIDELIX, ++ .name = "Fidelix", ++ .chips = fidelix_spinand_table, ++ .nchips = ARRAY_SIZE(fidelix_spinand_table), ++ .ops = &fidelix_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -263,6 +263,7 @@ struct spinand_manufacturer { + extern const struct spinand_manufacturer ato_spinand_manufacturer; + extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; + extern const struct spinand_manufacturer etron_spinand_manufacturer; ++extern const struct spinand_manufacturer fidelix_spinand_manufacturer; + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch new file mode 100644 index 0000000000..49cd62d0ae --- /dev/null +++ b/target/linux/mediatek/patches-6.6/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 +@@ -709,6 +709,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, +@@ -742,6 +751,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 = &mt7623_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-6.6/351-pinctrl-add-mt7988-pd-pulltype-support.patch b/target/linux/mediatek/patches-6.6/351-pinctrl-add-mt7988-pd-pulltype-support.patch new file mode 100644 index 0000000000..1fcb1e64c7 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/351-pinctrl-add-mt7988-pd-pulltype-support.patch @@ -0,0 +1,99 @@ +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +@@ -601,6 +601,30 @@ out: + return err; + } + ++static int mtk_pinconf_bias_set_pd(struct mtk_pinctrl *hw, ++ const struct mtk_pin_desc *desc, ++ u32 pullup, u32 arg) ++{ ++ int err, pd; ++ ++ if (arg == MTK_DISABLE) ++ pd = 0; ++ else if ((arg == MTK_ENABLE) && pullup) ++ pd = 0; ++ else if ((arg == MTK_ENABLE) && !pullup) ++ pd = 1; ++ else { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd); ++ ++out: ++ return err; ++ ++} ++ + static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +@@ -755,6 +779,12 @@ int mtk_pinconf_bias_set_combo(struct mt + return err; + } + ++ if (try_all_type & MTK_PULL_PD_TYPE) { ++ err = mtk_pinconf_bias_set_pd(hw, desc, pullup, arg); ++ if (!err) ++ return err; ++ } ++ + if (try_all_type & MTK_PULL_PU_PD_TYPE) { + err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); + if (!err) +@@ -875,6 +905,29 @@ out: + return err; + } + ++static int mtk_pinconf_bias_get_pd(struct mtk_pinctrl *hw, ++ const struct mtk_pin_desc *desc, ++ u32 *pullup, u32 *enable) ++{ ++ int err, pd; ++ ++ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); ++ if (err) ++ goto out; ++ ++ if (pd == 0) { ++ *pullup = 0; ++ *enable = MTK_DISABLE; ++ } else if (pd == 1) { ++ *pullup = 0; ++ *enable = MTK_ENABLE; ++ } else ++ err = -EINVAL; ++ ++out: ++ return err; ++} ++ + static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +@@ -943,6 +996,12 @@ int mtk_pinconf_bias_get_combo(struct mt + if (!err) + return err; + } ++ ++ if (try_all_type & MTK_PULL_PD_TYPE) { ++ err = mtk_pinconf_bias_get_pd(hw, desc, pullup, enable); ++ if (!err) ++ return err; ++ } + + if (try_all_type & MTK_PULL_PU_PD_TYPE) { + err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +@@ -24,6 +24,7 @@ + * turned on/off itself. But it can't be selected pull up/down + */ + #define MTK_PULL_RSEL_TYPE BIT(3) ++#define MTK_PULL_PD_TYPE BIT(4) + /* MTK_PULL_PU_PD_RSEL_TYPE is a type which is controlled by + * MTK_PULL_PU_PD_TYPE and MTK_PULL_RSEL_TYPE. + */ diff --git a/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch new file mode 100644 index 0000000000..25ca9485e4 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch @@ -0,0 +1,27 @@ +--- a/drivers/crypto/inside-secure/safexcel.c ++++ b/drivers/crypto/inside-secure/safexcel.c +@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex + val |= EIP197_MST_CTRL_TX_MAX_CMD(5); + writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); + } ++ /* ++ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3 ++ */ ++ else { ++ val = 0; ++ val |= EIP97_MST_CTRL_TX_MAX_CMD(4); ++ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); ++ } + + /* Configure wr/rd cache values */ + writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | +--- a/drivers/crypto/inside-secure/safexcel.h ++++ b/drivers/crypto/inside-secure/safexcel.h +@@ -315,6 +315,7 @@ + #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0) + #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4) + #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20) ++#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4) + #define EIP197_MST_CTRL_BYTE_SWAP BIT(24) + #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25) + #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24) diff --git a/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch new file mode 100644 index 0000000000..186c66f687 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch @@ -0,0 +1,26 @@ +--- a/drivers/crypto/inside-secure/safexcel.h ++++ b/drivers/crypto/inside-secure/safexcel.h +@@ -737,6 +737,9 @@ enum safexcel_eip_version { + /* Priority we use for advertising our algorithms */ + #define SAFEXCEL_CRA_PRIORITY 300 + ++/* System cache line size */ ++#define SYSTEM_CACHELINE_SIZE 64 ++ + /* SM3 digest result for zero length message */ + #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ + "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ +--- a/drivers/crypto/inside-secure/safexcel_hash.c ++++ b/drivers/crypto/inside-secure/safexcel_hash.c +@@ -55,9 +55,9 @@ struct safexcel_ahash_req { + u8 block_sz; /* block size, only set once */ + u8 digest_sz; /* output digest size, only set once */ + __le32 state[SHA3_512_BLOCK_SIZE / +- sizeof(__le32)] __aligned(sizeof(__le32)); ++ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE); + +- u64 len; ++ u64 len __aligned(SYSTEM_CACHELINE_SIZE); + u64 processed; + + u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); diff --git a/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch b/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch new file mode 100644 index 0000000000..615a1a1d71 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch @@ -0,0 +1,43 @@ +From f1da27b7c4191f78ed81d3dabf64c769f896296c Mon Sep 17 00:00:00 2001 +From: "Mingming.Su" +Date: Sat, 8 Oct 2022 18:45:53 +0200 +Subject: [PATCH] hwrng: mtk - add mt7986 support + +1. Add trng compatible name for MT7986 +2. Fix mtk_rng_wait_ready() function + +Signed-off-by: Mingming.Su +Signed-off-by: Frank Wunderlich +Signed-off-by: Herbert Xu +--- + drivers/char/hw_random/mtk-rng.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -22,7 +22,7 @@ + #define RNG_AUTOSUSPEND_TIMEOUT 100 + + #define USEC_POLL 2 +-#define TIMEOUT_POLL 20 ++#define TIMEOUT_POLL 60 + + #define RNG_CTRL 0x00 + #define RNG_EN BIT(0) +@@ -77,7 +77,7 @@ static bool mtk_rng_wait_ready(struct hw + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready, + ready & RNG_READY, USEC_POLL, + TIMEOUT_POLL); +- return !!ready; ++ return !!(ready & RNG_READY); + } + + static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +@@ -179,6 +179,7 @@ static const struct dev_pm_ops mtk_rng_p + #endif /* CONFIG_PM */ + + static const struct of_device_id mtk_rng_match[] = { ++ { .compatible = "mediatek,mt7986-rng" }, + { .compatible = "mediatek,mt7623-rng" }, + {}, + }; diff --git a/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch new file mode 100644 index 0000000000..5b94c9216d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch @@ -0,0 +1,33 @@ +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -86,6 +86,7 @@ struct serial8250_config { + * STOP PARITY EPAR SPAR WLEN5 WLEN6 + */ + #define UART_CAP_NOTEMT BIT(18) /* UART without interrupt on TEMT available */ ++#define UART_CAP_NMOD BIT(19) /* UART doesn't do termios */ + + #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ + #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -287,7 +287,7 @@ static const struct serial8250_config ua + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, +- .flags = UART_CAP_FIFO, ++ .flags = UART_CAP_FIFO | UART_CAP_NMOD, + }, + [PORT_NPCM] = { + .name = "Nuvoton 16550", +@@ -2773,6 +2773,11 @@ serial8250_do_set_termios(struct uart_po + unsigned long flags; + unsigned int baud, quot, frac = 0; + ++ if (up->capabilities & UART_CAP_NMOD) { ++ termios->c_cflag = 0; ++ return; ++ } ++ + if (up->capabilities & UART_CAP_MINI) { + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); + if ((termios->c_cflag & CSIZE) == CS5 || diff --git a/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch b/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch new file mode 100644 index 0000000000..8c2c80d6bf --- /dev/null +++ b/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch @@ -0,0 +1,130 @@ +From bfd3acc428085742d754a6d328d1a93ebf9451df Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:29:51 +0800 +Subject: [PATCH 1/6] drivers: spi-mt65xx: Move chip_config to driver's private + data + +Signed-off-by: SkyLake.Huang +--- + drivers/spi/spi-mt65xx.c | 29 +++++++++--------------- + include/linux/platform_data/spi-mt65xx.h | 17 -------------- + 2 files changed, 11 insertions(+), 35 deletions(-) + delete mode 100644 include/linux/platform_data/spi-mt65xx.h + +--- a/drivers/spi/spi-mt65xx.c ++++ b/drivers/spi/spi-mt65xx.c +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -171,6 +170,8 @@ struct mtk_spi { + struct device *dev; + dma_addr_t tx_dma; + dma_addr_t rx_dma; ++ u32 sample_sel; ++ u32 get_tick_dly; + }; + + static const struct mtk_spi_compatible mtk_common_compat; +@@ -216,15 +217,6 @@ static const struct mtk_spi_compatible m + .no_need_unprepare = true, + }; + +-/* +- * A piece of default chip info unless the platform +- * supplies it. +- */ +-static const struct mtk_chip_config mtk_default_chip_info = { +- .sample_sel = 0, +- .tick_delay = 0, +-}; +- + static const struct of_device_id mtk_spi_of_match[] = { + { .compatible = "mediatek,spi-ipm", + .data = (void *)&mtk_ipm_compat, +@@ -352,7 +344,6 @@ static int mtk_spi_hw_init(struct spi_ma + { + u16 cpha, cpol; + u32 reg_val; +- struct mtk_chip_config *chip_config = spi->controller_data; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + cpha = spi->mode & SPI_CPHA ? 1 : 0; +@@ -402,7 +393,7 @@ static int mtk_spi_hw_init(struct spi_ma + else + reg_val &= ~SPI_CMD_CS_POL; + +- if (chip_config->sample_sel) ++ if (mdata->sample_sel) + reg_val |= SPI_CMD_SAMPLE_SEL; + else + reg_val &= ~SPI_CMD_SAMPLE_SEL; +@@ -429,20 +420,20 @@ static int mtk_spi_hw_init(struct spi_ma + if (mdata->dev_comp->ipm_design) { + reg_val = readl(mdata->base + SPI_CMD_REG); + reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; +- reg_val |= ((chip_config->tick_delay & 0x7) ++ reg_val |= ((mdata->get_tick_dly & 0x7) + << SPI_CMD_IPM_GET_TICKDLY_OFFSET); + writel(reg_val, mdata->base + SPI_CMD_REG); + } else { + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; +- reg_val |= ((chip_config->tick_delay & 0x7) ++ reg_val |= ((mdata->get_tick_dly & 0x7) + << SPI_CFG1_GET_TICK_DLY_OFFSET); + writel(reg_val, mdata->base + SPI_CFG1_REG); + } + } else { + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; +- reg_val |= ((chip_config->tick_delay & 0x3) ++ reg_val |= ((mdata->get_tick_dly & 0x3) + << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); + writel(reg_val, mdata->base + SPI_CFG1_REG); + } +@@ -732,9 +723,6 @@ static int mtk_spi_setup(struct spi_devi + { + struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + +- if (!spi->controller_data) +- spi->controller_data = (void *)&mtk_default_chip_info; +- + if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) + /* CS de-asserted, gpiolib will handle inversion */ + gpiod_direction_output(spi->cs_gpiod, 0); +@@ -1138,6 +1126,10 @@ static int mtk_spi_probe(struct platform + mdata = spi_master_get_devdata(master); + mdata->dev_comp = device_get_match_data(dev); + ++ /* Set device configs to default first. Calibrate it later. */ ++ mdata->sample_sel = 0; ++ mdata->get_tick_dly = 2; ++ + if (mdata->dev_comp->enhance_timing) + master->mode_bits |= SPI_CS_HIGH; + +--- a/include/linux/platform_data/spi-mt65xx.h ++++ /dev/null +@@ -1,17 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * MTK SPI bus driver definitions +- * +- * Copyright (c) 2015 MediaTek Inc. +- * Author: Leilk Liu +- */ +- +-#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H +-#define ____LINUX_PLATFORM_DATA_SPI_MTK_H +- +-/* Board specific platform_data */ +-struct mtk_chip_config { +- u32 sample_sel; +- u32 tick_delay; +-}; +-#endif diff --git a/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch new file mode 100644 index 0000000000..b2c9df4386 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -0,0 +1,236 @@ +From 2ade0172154e50c8a2bfd8634c6eff943cffea29 Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:35:52 +0800 +Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration + +Signed-off-by: SkyLake.Huang +--- + drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++ + include/linux/spi/spi.h | 42 ++++++++++++ + 2 files changed, 179 insertions(+) + +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1385,6 +1385,70 @@ static int spi_transfer_wait(struct spi_ + return 0; + } + ++int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi, ++ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv) ++{ ++ int datalen = ctlr->cal_rule->datalen; ++ int addrlen = ctlr->cal_rule->addrlen; ++ u8 *buf; ++ int ret; ++ int i; ++ struct list_head *cal_head, *listptr; ++ struct spi_cal_target *target; ++ ++ /* Calculate calibration result */ ++ int hit_val, total_hit, origin; ++ bool hit; ++ ++ /* Make sure we can start calibration */ ++ if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata) ++ return 0; ++ ++ buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL); ++ if(!buf) ++ return -ENOMEM; ++ ++ ret = ctlr->append_caldata(ctlr); ++ if (ret) ++ goto cal_end; ++ ++ cal_head = ctlr->cal_target; ++ list_for_each(listptr, cal_head) { ++ target = list_entry(listptr, struct spi_cal_target, list); ++ ++ hit = false; ++ hit_val = 0; ++ total_hit = 0; ++ origin = *target->cal_item; ++ ++ for(i=target->cal_min; i<=target->cal_max; i+=target->step) { ++ *target->cal_item = i; ++ ret = (*cal_read)(drv_priv, ctlr->cal_rule->addr, addrlen, buf, datalen); ++ if(ret) ++ break; ++ dev_dbg(&spi->dev, "controller cal item value: 0x%x\n", i); ++ if(memcmp(ctlr->cal_rule->match_data, buf, datalen * sizeof(u8)) == 0) { ++ hit = true; ++ hit_val += i; ++ total_hit++; ++ dev_dbg(&spi->dev, "golden data matches data read!\n"); ++ } ++ } ++ if(hit) { ++ *target->cal_item = DIV_ROUND_CLOSEST(hit_val, total_hit); ++ dev_info(&spi->dev, "calibration result: 0x%x", *target->cal_item); ++ } else { ++ *target->cal_item = origin; ++ dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin); ++ } ++ } ++ ++cal_end: ++ kfree(buf); ++ return ret? ret: 0; ++} ++EXPORT_SYMBOL_GPL(spi_do_calibration); ++ + static void _spi_transfer_delay_ns(u32 ns) + { + if (!ns) +@@ -2223,6 +2287,75 @@ void spi_flush_queue(struct spi_controll + /*-------------------------------------------------------------------------*/ + + #if defined(CONFIG_OF) ++static inline void alloc_cal_data(struct list_head **cal_target, ++ struct spi_cal_rule **cal_rule, bool enable) ++{ ++ if(enable) { ++ *cal_target = kmalloc(sizeof(struct list_head), GFP_KERNEL); ++ INIT_LIST_HEAD(*cal_target); ++ *cal_rule = kmalloc(sizeof(struct spi_cal_rule), GFP_KERNEL); ++ } else { ++ kfree(*cal_target); ++ kfree(*cal_rule); ++ } ++} ++ ++static int of_spi_parse_cal_dt(struct spi_controller *ctlr, struct spi_device *spi, ++ struct device_node *nc) ++{ ++ u32 value; ++ int rc; ++ const char *cal_mode; ++ ++ rc = of_property_read_bool(nc, "spi-cal-enable"); ++ if (rc) ++ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, true); ++ else ++ return 0; ++ ++ rc = of_property_read_string(nc, "spi-cal-mode", &cal_mode); ++ if(!rc) { ++ if(strcmp("read-data", cal_mode) == 0){ ++ ctlr->cal_rule->mode = SPI_CAL_READ_DATA; ++ } else if(strcmp("read-pp", cal_mode) == 0) { ++ ctlr->cal_rule->mode = SPI_CAL_READ_PP; ++ return 0; ++ } else if(strcmp("read-sfdp", cal_mode) == 0){ ++ ctlr->cal_rule->mode = SPI_CAL_READ_SFDP; ++ return 0; ++ } ++ } else ++ goto err; ++ ++ ctlr->cal_rule->datalen = 0; ++ rc = of_property_read_u32(nc, "spi-cal-datalen", &value); ++ if(!rc && value > 0) { ++ ctlr->cal_rule->datalen = value; ++ ++ ctlr->cal_rule->match_data = kzalloc(value * sizeof(u8), GFP_KERNEL); ++ rc = of_property_read_u8_array(nc, "spi-cal-data", ++ ctlr->cal_rule->match_data, value); ++ if(rc) ++ kfree(ctlr->cal_rule->match_data); ++ } ++ ++ rc = of_property_read_u32(nc, "spi-cal-addrlen", &value); ++ if(!rc && value > 0) { ++ ctlr->cal_rule->addrlen = value; ++ ++ ctlr->cal_rule->addr = kzalloc(value * sizeof(u32), GFP_KERNEL); ++ rc = of_property_read_u32_array(nc, "spi-cal-addr", ++ ctlr->cal_rule->addr, value); ++ if(rc) ++ kfree(ctlr->cal_rule->addr); ++ } ++ return 0; ++ ++err: ++ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, false); ++ return 0; ++} ++ + static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, + struct device_node *nc) + { +@@ -2341,6 +2474,10 @@ of_register_spi_device(struct spi_contro + if (rc) + goto err_out; + ++ rc = of_spi_parse_cal_dt(ctlr, spi, nc); ++ if (rc) ++ goto err_out; ++ + /* Store a pointer to the node in the device structure */ + of_node_get(nc); + spi->dev.of_node = nc; +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -318,6 +318,40 @@ struct spi_driver { + struct device_driver driver; + }; + ++enum { ++ SPI_CAL_READ_DATA = 0, ++ SPI_CAL_READ_PP = 1, /* only for SPI-NAND */ ++ SPI_CAL_READ_SFDP = 2, /* only for SPI-NOR */ ++}; ++ ++struct nand_addr { ++ unsigned int lun; ++ unsigned int plane; ++ unsigned int eraseblock; ++ unsigned int page; ++ unsigned int dataoffs; ++}; ++ ++/** ++ * Read calibration rule from device dts node. ++ * Once calibration result matches the rule, we regard is as success. ++ */ ++struct spi_cal_rule { ++ int datalen; ++ u8 *match_data; ++ int addrlen; ++ u32 *addr; ++ int mode; ++}; ++ ++struct spi_cal_target { ++ u32 *cal_item; ++ int cal_min; /* min of cal_item */ ++ int cal_max; /* max of cal_item */ ++ int step; /* Increase/decrease cal_item */ ++ struct list_head list; ++}; ++ + static inline struct spi_driver *to_spi_driver(struct device_driver *drv) + { + return drv ? container_of(drv, struct spi_driver, driver) : NULL; +@@ -703,6 +737,11 @@ struct spi_controller { + void *dummy_rx; + void *dummy_tx; + ++ /* For calibration */ ++ int (*append_caldata)(struct spi_controller *ctlr); ++ struct list_head *cal_target; ++ struct spi_cal_rule *cal_rule; ++ + int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); + + /* +@@ -1510,6 +1549,9 @@ spi_register_board_info(struct spi_board + { return 0; } + #endif + ++extern int spi_do_calibration(struct spi_controller *ctlr, ++ struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv); ++ + /* If you're hotplugging an adapter with devices (parport, usb, etc) + * use spi_new_device() to describe each device. You can also call + * spi_unregister_device() to start making that device vanish, but diff --git a/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch b/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch new file mode 100644 index 0000000000..e87d63db69 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch @@ -0,0 +1,41 @@ +From 06640a5da2973318c06e516da16a5b579622e7c5 Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:37:55 +0800 +Subject: [PATCH 3/6] drivers: spi-mem: Add spi calibration hook + +Signed-off-by: SkyLake.Huang +--- + drivers/spi/spi-mem.c | 8 ++++++++ + include/linux/spi/spi-mem.h | 4 ++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -419,6 +419,14 @@ int spi_mem_exec_op(struct spi_mem *mem, + } + EXPORT_SYMBOL_GPL(spi_mem_exec_op); + ++int spi_mem_do_calibration(struct spi_mem *mem, ++ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), ++ void *priv) ++{ ++ return spi_do_calibration(mem->spi->controller, mem->spi, cal_read, priv); ++} ++EXPORT_SYMBOL_GPL(spi_mem_do_calibration); ++ + /** + * spi_mem_get_name() - Return the SPI mem device name to be used by the + * upper layer if necessary +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -366,6 +366,10 @@ bool spi_mem_supports_op(struct spi_mem + int spi_mem_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op); + ++int spi_mem_do_calibration(struct spi_mem *mem, ++ int (*cal_read)(void *, u32 *, int, u8 *, int), ++ void *priv); ++ + const char *spi_mem_get_name(struct spi_mem *mem); + + struct spi_mem_dirmap_desc * diff --git a/target/linux/mediatek/patches-6.6/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch b/target/linux/mediatek/patches-6.6/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch new file mode 100644 index 0000000000..ee3dc27860 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch @@ -0,0 +1,43 @@ +From d278c7a0bf730318a7ccf8d0a8b434c813e23fd0 Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:39:03 +0800 +Subject: [PATCH 4/6] drivers: spi-mt65xx: Add controller's calibration + paramter + +Signed-off-by: SkyLake.Huang +--- + drivers/spi/spi-mt65xx.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/spi/spi-mt65xx.c ++++ b/drivers/spi/spi-mt65xx.c +@@ -832,6 +832,21 @@ static irqreturn_t mtk_spi_interrupt(int + return IRQ_HANDLED; + } + ++static int mtk_spi_append_caldata(struct spi_controller *ctlr) ++{ ++ struct spi_cal_target *cal_target = kmalloc(sizeof(*cal_target), GFP_KERNEL); ++ struct mtk_spi *mdata = spi_master_get_devdata(ctlr); ++ ++ cal_target->cal_item = &mdata->get_tick_dly; ++ cal_target->cal_min = 0; ++ cal_target->cal_max = 7; ++ cal_target->step = 1; ++ ++ list_add(&cal_target->list, ctlr->cal_target); ++ ++ return 0; ++} ++ + static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, + struct spi_mem_op *op) + { +@@ -1122,6 +1137,7 @@ static int mtk_spi_probe(struct platform + master->setup = mtk_spi_setup; + master->set_cs_timing = mtk_spi_set_hw_cs_timing; + master->use_gpio_descriptors = true; ++ master->append_caldata = mtk_spi_append_caldata; + + mdata = spi_master_get_devdata(master); + mdata->dev_comp = device_get_match_data(dev); diff --git a/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch b/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch new file mode 100644 index 0000000000..3991d8925a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch @@ -0,0 +1,81 @@ +From 7670ec4a14891a1a182b98a9c403ffbf6b49e4b1 Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:39:56 +0800 +Subject: [PATCH 5/6] drivers: mtd: spinand: Add calibration support for + spinand + +Signed-off-by: SkyLake.Huang +--- + drivers/mtd/nand/spi/core.c | 54 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -978,6 +978,56 @@ static int spinand_manufacturer_match(st + return -ENOTSUPP; + } + ++int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) { ++ struct spinand_device *spinand = (struct spinand_device *)priv; ++ struct device *dev = &spinand->spimem->spi->dev; ++ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen); ++ struct nand_pos pos; ++ struct nand_page_io_req req; ++ u8 status; ++ int ret; ++ ++ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) { ++ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n"); ++ return -EINVAL; ++ } ++ ++ ret = spinand_reset_op(spinand); ++ if (ret) ++ return ret; ++ ++ /* We should store our golden data in first target because ++ * we can't switch target at this moment. ++ */ ++ pos = (struct nand_pos){ ++ .target = 0, ++ .lun = *addr, ++ .plane = *(addr+1), ++ .eraseblock = *(addr+2), ++ .page = *(addr+3), ++ }; ++ ++ req = (struct nand_page_io_req){ ++ .pos = pos, ++ .dataoffs = *(addr+4), ++ .datalen = readlen, ++ .databuf.in = buf, ++ .mode = MTD_OPS_AUTO_OOB, ++ }; ++ ++ ret = spinand_load_page_op(spinand, &req); ++ if (ret) ++ return ret; ++ ++ ret = spinand_wait(spinand, &status); ++ if (ret < 0) ++ return ret; ++ ++ ret = spi_mem_exec_op(spinand->spimem, &op); ++ ++ return 0; ++} ++ + static int spinand_id_detect(struct spinand_device *spinand) + { + u8 *id = spinand->id.data; +@@ -1228,6 +1278,10 @@ static int spinand_init(struct spinand_d + if (!spinand->scratchbuf) + return -ENOMEM; + ++ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand); ++ if (ret) ++ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret); ++ + ret = spinand_detect(spinand); + if (ret) + goto err_free_bufs; diff --git a/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch b/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch new file mode 100644 index 0000000000..1f747d1f4f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch @@ -0,0 +1,57 @@ +From f3fe3b15eca7908eaac57f9b8387a5dbc45ec5b2 Mon Sep 17 00:00:00 2001 +From: "SkyLake.Huang" +Date: Thu, 23 Jun 2022 18:40:59 +0800 +Subject: [PATCH 6/6] drivers: mtd: spi-nor: Add calibration support for + spi-nor + +Signed-off-by: SkyLake.Huang +--- + drivers/mtd/nand/spi/core.c | 5 ++++- + drivers/mtd/spi-nor/core.c | 15 +++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1019,7 +1019,10 @@ int spinand_cal_read(void *priv, u32 *ad + if (ret) + return ret; + +- ret = spinand_wait(spinand, &status); ++ ret = spinand_wait(spinand, ++ SPINAND_READ_INITIAL_DELAY_US, ++ SPINAND_READ_POLL_DELAY_US, ++ &status); + if (ret < 0) + return ret; + +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -2900,6 +2900,18 @@ static const struct flash_info *spi_nor_ + return NULL; + } + ++static int spi_nor_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) ++{ ++ struct spi_nor *nor = (struct spi_nor *)priv; ++ ++ nor->reg_proto = SNOR_PROTO_1_1_1; ++ nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->read_opcode = SPINOR_OP_READ; ++ nor->read_dummy = 0; ++ ++ return nor->controller_ops->read(nor, *addr, readlen, buf); ++} ++ + static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, + const char *name) + { +@@ -3003,6 +3015,9 @@ int spi_nor_scan(struct spi_nor *nor, co + if (!nor->bouncebuf) + return -ENOMEM; + ++ if(nor->spimem) ++ spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor); ++ + info = spi_nor_get_flash_info(nor, name); + if (IS_ERR(info)) + return PTR_ERR(info); diff --git a/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch new file mode 100644 index 0000000000..487990ab77 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -384,6 +384,12 @@ config ROCKCHIP_PHY + help + Currently supports the integrated Ethernet PHY. + ++config RTL8367S_GSW ++ tristate "rtl8367 Gigabit Switch support for mt7622" ++ depends on NET_VENDOR_MEDIATEK ++ help ++ This driver supports rtl8367s in mt7622 ++ + config SMSC_PHY + tristate "SMSC PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o ++obj-$(CONFIG_RTL8367S_GSW) += rtk/ + obj-$(CONFIG_SMSC_PHY) += smsc.o + obj-$(CONFIG_STE10XP) += ste10Xp.o + obj-$(CONFIG_TERANETICS_PHY) += teranetics.o diff --git a/target/linux/mediatek/patches-6.6/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch b/target/linux/mediatek/patches-6.6/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch new file mode 100644 index 0000000000..983fde707f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch @@ -0,0 +1,34 @@ +From: qizhong cheng +Date: Mon, 27 Dec 2021 21:31:10 +0800 +Subject: [PATCH] PCI: mediatek: Assert PERST# for 100ms for power and clock to + stabilize +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Described in PCIe CEM specification sections 2.2 (PERST# Signal) and +2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should +be delayed 100ms (TPVPERL) for the power and clock to become stable. + +Link: https://lore.kernel.org/r/20211227133110.14500-1-qizhong.cheng@mediatek.com +Signed-off-by: qizhong cheng +Signed-off-by: Lorenzo Pieralisi +Acked-by: Pali Rohár +--- + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -708,6 +708,13 @@ static int mtk_pcie_startup_port_v2(stru + */ + msleep(100); + ++ /* ++ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and ++ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should ++ * be delayed 100ms (TPVPERL) for the power and clock to become stable. ++ */ ++ msleep(100); ++ + /* De-assert PHY, PE, PIPE, MAC and configuration reset */ + val = readl(port->base + PCIE_RST_CTRL); + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | diff --git a/target/linux/mediatek/patches-6.6/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch b/target/linux/mediatek/patches-6.6/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch new file mode 100644 index 0000000000..bf479ab53b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch @@ -0,0 +1,28 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -849,6 +849,12 @@ + #address-cells = <0>; + #interrupt-cells = <1>; + }; ++ ++ slot0: pcie@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ }; + }; + + pcie1: pcie@1a145000 { +@@ -887,6 +893,12 @@ + #address-cells = <0>; + #interrupt-cells = <1>; + }; ++ ++ slot1: pcie@1,0 { ++ reg = <0x0800 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ }; + }; + + sata: sata@1a200000 { diff --git a/target/linux/mediatek/patches-6.6/610-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-6.6/610-pcie-mediatek-fix-clearing-interrupt-status.patch new file mode 100644 index 0000000000..2a49b2275c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/610-pcie-mediatek-fix-clearing-interrupt-status.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Fri, 4 Sep 2020 18:33:27 +0200 +Subject: [PATCH] pcie-mediatek: fix clearing interrupt status + +Clearing the status needs to happen after running the handler, otherwise +we will get an extra spurious interrupt after the cause has been cleared + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -607,9 +607,9 @@ static void mtk_pcie_intr_handler(struct + if (status & INTX_MASK) { + for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) { + /* Clear the INTx */ +- writel(1 << bit, port->base + PCIE_INT_STATUS); + generic_handle_domain_irq(port->irq_domain, + bit - INTX_SHIFT); ++ writel(1 << bit, port->base + PCIE_INT_STATUS); + } + } + diff --git a/target/linux/mediatek/patches-6.6/611-pcie-mediatek-gen3-PERST-for-100ms.patch b/target/linux/mediatek/patches-6.6/611-pcie-mediatek-gen3-PERST-for-100ms.patch new file mode 100644 index 0000000000..32b4237d82 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/611-pcie-mediatek-gen3-PERST-for-100ms.patch @@ -0,0 +1,17 @@ +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -375,7 +375,13 @@ static int mtk_pcie_startup_port(struct + msleep(100); + + /* De-assert reset signals */ +- val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB); ++ val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB); ++ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ ++ msleep(100); ++ ++ /* De-assert PERST# signals */ ++ val &= ~(PCIE_PE_RSTB); + writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + + /* Check if the link is up or not */ diff --git a/target/linux/mediatek/patches-6.6/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/target/linux/mediatek/patches-6.6/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch new file mode 100644 index 0000000000..a597f70caa --- /dev/null +++ b/target/linux/mediatek/patches-6.6/615-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch @@ -0,0 +1,167 @@ +From 50cefacc6c001eea1d9b1c78ba27304566f304f1 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 2 Jun 2023 13:06:26 +0800 +Subject: [PATCH] phy: mediatek: xsphy: support type switch by pericfg + +Patch from Sam Shih found in MediaTek SDK +released under GPL. + +Get syscon and use it to set the PHY type. +Extend support to PCIe and SGMII mode in addition to USB2 and USB3. + +Signed-off-by: Daniel Golle +--- + drivers/phy/mediatek/phy-mtk-xsphy.c | 81 +++++++++++++++++++++++++++- + 1 file changed, 80 insertions(+), 1 deletion(-) + +--- a/drivers/phy/mediatek/phy-mtk-xsphy.c ++++ b/drivers/phy/mediatek/phy-mtk-xsphy.c +@@ -11,10 +11,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + + #include "phy-mtk-io.h" + +@@ -81,12 +83,22 @@ + #define XSP_SR_COEF_DIVISOR 1000 + #define XSP_FM_DET_CYCLE_CNT 1024 + ++/* PHY switch between pcie/usb3/sgmii */ ++#define USB_PHY_SWITCH_CTRL 0x0 ++#define RG_PHY_SW_TYPE GENMASK(3, 0) ++#define RG_PHY_SW_PCIE 0x0 ++#define RG_PHY_SW_USB3 0x1 ++#define RG_PHY_SW_SGMII 0x2 ++ + struct xsphy_instance { + struct phy *phy; + void __iomem *port_base; + struct clk *ref_clk; /* reference clock of anolog phy */ + u32 index; + u32 type; ++ struct regmap *type_sw; ++ u32 type_sw_reg; ++ u32 type_sw_index; + /* only for HQA test */ + int efuse_intr; + int efuse_tx_imp; +@@ -259,6 +271,10 @@ static void phy_parse_property(struct mt + inst->efuse_intr, inst->efuse_tx_imp, + inst->efuse_rx_imp); + break; ++ case PHY_TYPE_PCIE: ++ case PHY_TYPE_SGMII: ++ /* nothing to do */ ++ break; + default: + dev_err(xsphy->dev, "incompatible phy type\n"); + return; +@@ -305,6 +321,62 @@ static void u3_phy_props_set(struct mtk_ + RG_XTP_LN0_RX_IMPSEL, inst->efuse_rx_imp); + } + ++/* type switch for usb3/pcie/sgmii */ ++static int phy_type_syscon_get(struct xsphy_instance *instance, ++ struct device_node *dn) ++{ ++ struct of_phandle_args args; ++ int ret; ++ ++ /* type switch function is optional */ ++ if (!of_property_read_bool(dn, "mediatek,syscon-type")) ++ return 0; ++ ++ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type", ++ 2, 0, &args); ++ if (ret) ++ return ret; ++ ++ instance->type_sw_reg = args.args[0]; ++ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ ++ instance->type_sw = syscon_node_to_regmap(args.np); ++ of_node_put(args.np); ++ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n", ++ instance->type_sw_reg, instance->type_sw_index); ++ ++ return PTR_ERR_OR_ZERO(instance->type_sw); ++} ++ ++static int phy_type_set(struct xsphy_instance *instance) ++{ ++ int type; ++ u32 offset; ++ ++ if (!instance->type_sw) ++ return 0; ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB3: ++ type = RG_PHY_SW_USB3; ++ break; ++ case PHY_TYPE_PCIE: ++ type = RG_PHY_SW_PCIE; ++ break; ++ case PHY_TYPE_SGMII: ++ type = RG_PHY_SW_SGMII; ++ break; ++ case PHY_TYPE_USB2: ++ default: ++ return 0; ++ } ++ ++ offset = instance->type_sw_index * BITS_PER_BYTE; ++ regmap_update_bits(instance->type_sw, instance->type_sw_reg, ++ RG_PHY_SW_TYPE << offset, type << offset); ++ ++ return 0; ++} ++ + static int mtk_phy_init(struct phy *phy) + { + struct xsphy_instance *inst = phy_get_drvdata(phy); +@@ -325,6 +397,10 @@ static int mtk_phy_init(struct phy *phy) + case PHY_TYPE_USB3: + u3_phy_props_set(xsphy, inst); + break; ++ case PHY_TYPE_PCIE: ++ case PHY_TYPE_SGMII: ++ /* nothing to do, only used to set type */ ++ break; + default: + dev_err(xsphy->dev, "incompatible phy type\n"); + clk_disable_unprepare(inst->ref_clk); +@@ -403,12 +479,15 @@ static struct phy *mtk_phy_xlate(struct + + inst->type = args->args[0]; + if (!(inst->type == PHY_TYPE_USB2 || +- inst->type == PHY_TYPE_USB3)) { ++ inst->type == PHY_TYPE_USB3 || ++ inst->type == PHY_TYPE_PCIE || ++ inst->type == PHY_TYPE_SGMII)) { + dev_err(dev, "unsupported phy type: %d\n", inst->type); + return ERR_PTR(-EINVAL); + } + + phy_parse_property(xsphy, inst); ++ phy_type_set(inst); + + return inst->phy; + } +@@ -515,6 +594,10 @@ static int mtk_xsphy_probe(struct platfo + retval = PTR_ERR(inst->ref_clk); + goto put_child; + } ++ ++ retval = phy_type_syscon_get(inst, child_np); ++ if (retval) ++ goto put_child; + } + + provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); diff --git a/target/linux/mediatek/patches-6.6/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-6.6/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch new file mode 100644 index 0000000000..76ee2fc89a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch @@ -0,0 +1,82 @@ +From: Felix Fietkau +Date: Fri, 4 Sep 2020 18:42:42 +0200 +Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA + +It improves performance by eliminating the need for a cache flush for DMA on +attached devices + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -837,6 +837,9 @@ + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; + status = "disabled"; ++ dma-coherent; ++ mediatek,hifsys = <&hifsys>; ++ mediatek,cci-control = <&cci_control2>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; +@@ -881,6 +884,9 @@ + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; + status = "disabled"; ++ dma-coherent; ++ mediatek,hifsys = <&hifsys>; ++ mediatek,cci-control = <&cci_control2>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -139,6 +140,11 @@ + #define PCIE_LINK_STATUS_V2 0x804 + #define PCIE_PORT_LINKUP_V2 BIT(10) + ++/* DMA channel mapping */ ++#define HIFSYS_DMA_AG_MAP 0x008 ++#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) ++#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) ++ + struct mtk_pcie_port; + + /** +@@ -1060,6 +1066,27 @@ static int mtk_pcie_setup(struct mtk_pci + struct mtk_pcie_port *port, *tmp; + int err, slot; + ++ if (of_dma_is_coherent(node)) { ++ struct regmap *con; ++ u32 mask; ++ ++ con = syscon_regmap_lookup_by_phandle(node, ++ "mediatek,cci-control"); ++ /* enable CPU/bus coherency */ ++ if (!IS_ERR(con)) ++ regmap_write(con, 0, 3); ++ ++ con = syscon_regmap_lookup_by_phandle(node, ++ "mediatek,hifsys"); ++ if (IS_ERR(con)) { ++ dev_err(dev, "missing hifsys node\n"); ++ return PTR_ERR(con); ++ } ++ ++ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; ++ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); ++ } ++ + slot = of_get_pci_domain_nr(dev->of_node); + if (slot < 0) { + for_each_available_child_of_node(node, child) { diff --git a/target/linux/mediatek/patches-6.6/721-dts-mt7622-mediatek-fix-300mhz.patch b/target/linux/mediatek/patches-6.6/721-dts-mt7622-mediatek-fix-300mhz.patch new file mode 100644 index 0000000000..f9a5fdbd0d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/721-dts-mt7622-mediatek-fix-300mhz.patch @@ -0,0 +1,27 @@ +From: Jip de Beer +Date: Sun, 9 Jan 2022 13:14:04 +0100 +Subject: [PATCH] mediatek mt7622: fix 300mhz typo in dts + +The lowest frequency should be 300MHz, since that is the label +assigned to the OPP in the mt7622.dtsi device tree, while there is one +missing zero in the actual value. + +To be clear, the lowest frequency should be 300MHz instead of 30MHz. + +As mentioned @dangowrt on the OpenWrt forum there is no benefit in +leaving 30MHz as the lowest frequency. + +Signed-off-by: Jip de Beer +Signed-off-by: Fritz D. Ansel +--- +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -24,7 +24,7 @@ + compatible = "operating-points-v2"; + opp-shared; + opp-300000000 { +- opp-hz = /bits/ 64 <30000000>; ++ opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <950000>; + }; + diff --git a/target/linux/mediatek/patches-6.6/722-remove-300Hz-to-prevent-freeze.patch b/target/linux/mediatek/patches-6.6/722-remove-300Hz-to-prevent-freeze.patch new file mode 100644 index 0000000000..52069496ca --- /dev/null +++ b/target/linux/mediatek/patches-6.6/722-remove-300Hz-to-prevent-freeze.patch @@ -0,0 +1,25 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -23,11 +23,17 @@ + cpu_opp_table: opp-table { + compatible = "operating-points-v2"; + opp-shared; +- opp-300000000 { +- opp-hz = /bits/ 64 <300000000>; +- opp-microvolt = <950000>; +- }; +- ++ /* Due to the bug described at the link below, remove the 300 MHz clock to avoid a low ++ * voltage condition that can cause a hang when rebooting the RT3200/E8450. ++ * ++ * https://forum.openwrt.org/t/belkin-rt3200-linksys-e8450-wifi-ax-discussion/94302/1490 ++ * ++ * opp-300000000 { ++ * opp-hz = /bits/ 64 <300000000>; ++ * opp-microvolt = <950000>; ++ * }; ++ * ++ */ + opp-437500000 { + opp-hz = /bits/ 64 <437500000>; + opp-microvolt = <1000000>; diff --git a/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch new file mode 100644 index 0000000000..0bbf9ac773 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -0,0 +1,1204 @@ +From 98c485eaf509bc0e2a85f9b58d17cd501f274c4e Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 11 Jun 2023 00:48:10 +0100 +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. +Despite the similar design the driver doesn't share any code with the +existing mediatek-ge.c. +Add support for such PHYs by introducing a new driver with basic +support for MediaTek SoCs MT7981 and MT7988 built-in 1GE PHYs. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + MAINTAINERS | 9 + + drivers/net/phy/Kconfig | 12 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mediatek-ge-soc.c | 1116 +++++++++++++++++++++++++++++ + drivers/net/phy/mediatek-ge.c | 3 +- + 5 files changed, 1140 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/mediatek-ge-soc.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -12938,6 +12938,15 @@ F: drivers/net/pcs/pcs-mtk-usxgmii.c + F: include/linux/pcs/pcs-mtk-lynxi.h + F: include/linux/pcs/pcs-mtk-usxgmii.h + ++MEDIATEK ETHERNET PHY DRIVERS ++M: Daniel Golle ++M: Qingfang Deng ++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 + M: Qii Wang + L: linux-i2c@vger.kernel.org +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -314,6 +314,18 @@ config MEDIATEK_GE_PHY + help + Supports the MediaTek Gigabit Ethernet PHYs. + ++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. ++ ++ Include support for built-in Ethernet PHYs which are present in ++ the MT7981 and MT7988 SoCs. These PHYs need calibration data ++ present in the SoCs efuse and will dynamically calibrate VCM ++ (common-mode voltage) during startup. ++ + config MICREL_PHY + tristate "Micrel PHYs" + depends on PTP_1588_CLOCK_OPTIONAL +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -80,6 +80,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 +--- /dev/null ++++ b/drivers/net/phy/mediatek-ge-soc.c +@@ -0,0 +1,1116 @@ ++// 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 ++ ++#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 ++}; ++ ++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 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 = mt798x_phy_calibration, ++ .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 = mt798x_phy_calibration, ++ .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); +--- a/drivers/net/phy/mediatek-ge.c ++++ b/drivers/net/phy/mediatek-ge.c +@@ -136,7 +136,8 @@ static struct phy_driver mtk_gephy_drive + module_phy_driver(mtk_gephy_driver); + + 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) }, + { } + }; + diff --git a/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch b/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch new file mode 100644 index 0000000000..286ce96a7d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch @@ -0,0 +1,524 @@ +From c66937b0f8dbb4c6c043663c702b1053fb47fab2 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 14 Aug 2023 02:58:14 +0100 +Subject: [PATCH] net: phy: mediatek-ge-soc: support PHY LEDs + +Implement netdev trigger and primitive bliking offloading as well as +simple set_brigthness function for both PHY LEDs of the in-SoC PHYs +found in MT7981 and MT7988. + +For MT7988, read boottrap register and apply LED polarities accordingly +to get uniform behavior from all LEDs on MT7988. +This requires syscon phandle 'mediatek,pio' present in parenting MDIO bus +which should point to the syscon holding the boottrap register. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/dc324d48c00cd7350f3a506eaa785324cae97372.1691977904.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/mediatek-ge-soc.c | 435 +++++++++++++++++++++++++++++- + 1 file changed, 426 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/mediatek-ge-soc.c ++++ b/drivers/net/phy/mediatek-ge-soc.c +@@ -1,11 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0+ + #include ++#include ++#include + #include + #include + #include + #include + #include + #include ++#include + + #define MTK_GPHY_ID_MT7981 0x03a29461 + #define MTK_GPHY_ID_MT7988 0x03a29481 +@@ -208,9 +211,42 @@ + #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_LED1_ON_CTRL 0x26 ++#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) ++#define MTK_PHY_LED_ON_LINK1000 BIT(0) ++#define MTK_PHY_LED_ON_LINK100 BIT(1) ++#define MTK_PHY_LED_ON_LINK10 BIT(2) ++#define MTK_PHY_LED_ON_LINKDOWN BIT(3) ++#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ ++#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ ++#define MTK_PHY_LED_ON_FORCE_ON BIT(6) ++#define MTK_PHY_LED_ON_POLARITY BIT(14) ++#define MTK_PHY_LED_ON_ENABLE BIT(15) ++ ++#define MTK_PHY_LED0_BLINK_CTRL 0x25 ++#define MTK_PHY_LED1_BLINK_CTRL 0x27 ++#define MTK_PHY_LED_BLINK_1000TX BIT(0) ++#define MTK_PHY_LED_BLINK_1000RX BIT(1) ++#define MTK_PHY_LED_BLINK_100TX BIT(2) ++#define MTK_PHY_LED_BLINK_100RX BIT(3) ++#define MTK_PHY_LED_BLINK_10TX BIT(4) ++#define MTK_PHY_LED_BLINK_10RX BIT(5) ++#define MTK_PHY_LED_BLINK_COLLISION BIT(6) ++#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) ++#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) ++#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) ++ ++#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) ++ + #define MTK_PHY_RG_BG_RASEL 0x115 + #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) + ++/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */ ++#define RG_GPIO_MISC_TPBANK0 0x6f0 ++#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8) ++ + /* 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)) +@@ -238,13 +274,6 @@ enum { + PAIR_D, + }; + +-enum { +- GPHY_PORT0, +- GPHY_PORT1, +- GPHY_PORT2, +- GPHY_PORT3, +-}; +- + enum calibration_mode { + EFUSE_K, + SW_K +@@ -263,6 +292,19 @@ enum CAL_MODE { + SW_M + }; + ++#define MTK_PHY_LED_STATE_FORCE_ON 0 ++#define MTK_PHY_LED_STATE_FORCE_BLINK 1 ++#define MTK_PHY_LED_STATE_NETDEV 2 ++ ++struct mtk_socphy_priv { ++ unsigned long led_state; ++}; ++ ++struct mtk_socphy_shared { ++ u32 boottrap; ++ struct mtk_socphy_priv priv[4]; ++}; ++ + static int mtk_socphy_read_page(struct phy_device *phydev) + { + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); +@@ -1073,6 +1115,371 @@ static int mt798x_phy_config_init(struct + return mt798x_phy_calibration(phydev); + } + ++static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, ++ bool on) ++{ ++ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); ++ struct mtk_socphy_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (on) ++ changed = !test_and_set_bit(bit_on, &priv->led_state); ++ else ++ changed = !!test_and_clear_bit(bit_on, &priv->led_state); ++ ++ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + ++ (index ? 16 : 0), &priv->led_state); ++ if (changed) ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? ++ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, ++ MTK_PHY_LED_ON_MASK, ++ on ? MTK_PHY_LED_ON_FORCE_ON : 0); ++ else ++ return 0; ++} ++ ++static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, ++ bool blinking) ++{ ++ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); ++ struct mtk_socphy_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (blinking) ++ changed = !test_and_set_bit(bit_blink, &priv->led_state); ++ else ++ changed = !!test_and_clear_bit(bit_blink, &priv->led_state); ++ ++ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + ++ (index ? 16 : 0), &priv->led_state); ++ if (changed) ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? ++ MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL, ++ blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0); ++ else ++ return 0; ++} ++ ++static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ bool blinking = false; ++ int err = 0; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { ++ blinking = true; ++ *delay_on = 50; ++ *delay_off = 50; ++ } ++ ++ err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); ++ if (err) ++ return err; ++ ++ return mt798x_phy_hw_led_on_set(phydev, index, false); ++} ++ ++static int mt798x_phy_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ int err; ++ ++ err = mt798x_phy_hw_led_blink_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); ++} ++ ++static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | ++ BIT(TRIGGER_NETDEV_HALF_DUPLEX) | ++ BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)); ++ ++static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ if (index > 1) ++ return -EINVAL; ++ ++ /* All combinations of the supported triggers are allowed */ ++ if (rules & ~supported_triggers) ++ return -EOPNOTSUPP; ++ ++ return 0; ++}; ++ ++static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); ++ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); ++ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); ++ struct mtk_socphy_priv *priv = phydev->priv; ++ int on, blink; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ on = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); ++ ++ if (on < 0) ++ return -EIO; ++ ++ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ index ? MTK_PHY_LED1_BLINK_CTRL : ++ MTK_PHY_LED0_BLINK_CTRL); ++ if (blink < 0) ++ return -EIO; ++ ++ if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | ++ MTK_PHY_LED_ON_LINK10)) || ++ (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | ++ MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX | ++ MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))) ++ set_bit(bit_netdev, &priv->led_state); ++ else ++ clear_bit(bit_netdev, &priv->led_state); ++ ++ if (on & MTK_PHY_LED_ON_FORCE_ON) ++ set_bit(bit_on, &priv->led_state); ++ else ++ clear_bit(bit_on, &priv->led_state); ++ ++ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) ++ set_bit(bit_blink, &priv->led_state); ++ else ++ clear_bit(bit_blink, &priv->led_state); ++ ++ if (!rules) ++ return 0; ++ ++ if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10)) ++ *rules |= BIT(TRIGGER_NETDEV_LINK); ++ ++ if (on & MTK_PHY_LED_ON_LINK10) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_10); ++ ++ if (on & MTK_PHY_LED_ON_LINK100) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_100); ++ ++ if (on & MTK_PHY_LED_ON_LINK1000) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); ++ ++ if (on & MTK_PHY_LED_ON_FDX) ++ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); ++ ++ if (on & MTK_PHY_LED_ON_HDX) ++ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); ++ ++ if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX)) ++ *rules |= BIT(TRIGGER_NETDEV_RX); ++ ++ if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)) ++ *rules |= BIT(TRIGGER_NETDEV_TX); ++ ++ return 0; ++}; ++ ++static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); ++ struct mtk_socphy_priv *priv = phydev->priv; ++ u16 on = 0, blink = 0; ++ int ret; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) ++ on |= MTK_PHY_LED_ON_FDX; ++ ++ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) ++ on |= MTK_PHY_LED_ON_HDX; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= MTK_PHY_LED_ON_LINK10; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= MTK_PHY_LED_ON_LINK100; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= MTK_PHY_LED_ON_LINK1000; ++ ++ if (rules & BIT(TRIGGER_NETDEV_RX)) { ++ blink |= MTK_PHY_LED_BLINK_10RX | ++ MTK_PHY_LED_BLINK_100RX | ++ MTK_PHY_LED_BLINK_1000RX; ++ } ++ ++ if (rules & BIT(TRIGGER_NETDEV_TX)) { ++ blink |= MTK_PHY_LED_BLINK_10TX | ++ MTK_PHY_LED_BLINK_100TX | ++ MTK_PHY_LED_BLINK_1000TX; ++ } ++ ++ if (blink || on) ++ set_bit(bit_netdev, &priv->led_state); ++ else ++ clear_bit(bit_netdev, &priv->led_state); ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? ++ MTK_PHY_LED1_ON_CTRL : ++ MTK_PHY_LED0_ON_CTRL, ++ MTK_PHY_LED_ON_FDX | ++ MTK_PHY_LED_ON_HDX | ++ MTK_PHY_LED_ON_LINK10 | ++ MTK_PHY_LED_ON_LINK100 | ++ MTK_PHY_LED_ON_LINK1000, ++ on); ++ ++ if (ret) ++ return ret; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? ++ MTK_PHY_LED1_BLINK_CTRL : ++ MTK_PHY_LED0_BLINK_CTRL, blink); ++}; ++ ++static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) ++{ ++ struct mtk_socphy_shared *priv = phydev->shared->priv; ++ u32 polarities; ++ ++ if (led_num == 0) ++ polarities = ~(priv->boottrap); ++ else ++ polarities = MTK_PHY_LED1_DEFAULT_POLARITIES; ++ ++ if (polarities & BIT(phydev->mdio.addr)) ++ return true; ++ ++ return false; ++} ++ ++static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev) ++{ ++ struct pinctrl *pinctrl; ++ int index; ++ ++ /* Setup LED polarity according to bootstrap use of LED pins */ ++ for (index = 0; index < 2; ++index) ++ phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? ++ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, ++ MTK_PHY_LED_ON_POLARITY, ++ mt7988_phy_led_get_polarity(phydev, index) ? ++ MTK_PHY_LED_ON_POLARITY : 0); ++ ++ /* Only now setup pinctrl to avoid bogus blinking */ ++ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); ++ if (IS_ERR(pinctrl)) ++ dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n"); ++ ++ return 0; ++} ++ ++static int mt7988_phy_probe_shared(struct phy_device *phydev) ++{ ++ struct device_node *np = dev_of_node(&phydev->mdio.bus->dev); ++ struct mtk_socphy_shared *shared = phydev->shared->priv; ++ struct regmap *regmap; ++ u32 reg; ++ int ret; ++ ++ /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B, ++ * LED_C and LED_D respectively. At the same time those pins are used to ++ * bootstrap configuration of the reference clock source (LED_A), ++ * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). ++ * In practise this is done using a LED and a resistor pulling the pin ++ * either to GND or to VIO. ++ * The detected value at boot time is accessible at run-time using the ++ * TPBANK0 register located in the gpio base of the pinctrl, in order ++ * to read it here it needs to be referenced by a phandle called ++ * 'mediatek,pio' in the MDIO bus hosting the PHY. ++ * The 4 bits in TPBANK0 are kept as package shared data and are used to ++ * set LED polarity for each of the LED0. ++ */ ++ regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio"); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®); ++ if (ret) ++ return ret; ++ ++ shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); ++ ++ return 0; ++} ++ ++static void mt798x_phy_leds_state_init(struct phy_device *phydev) ++{ ++ int i; ++ ++ for (i = 0; i < 2; ++i) ++ mt798x_phy_led_hw_control_get(phydev, i, NULL); ++} ++ ++static int mt7988_phy_probe(struct phy_device *phydev) ++{ ++ struct mtk_socphy_shared *shared; ++ struct mtk_socphy_priv *priv; ++ int err; ++ ++ if (phydev->mdio.addr > 3) ++ return -EINVAL; ++ ++ err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, ++ sizeof(struct mtk_socphy_shared)); ++ if (err) ++ return err; ++ ++ if (phy_package_probe_once(phydev)) { ++ err = mt7988_phy_probe_shared(phydev); ++ if (err) ++ return err; ++ } ++ ++ shared = phydev->shared->priv; ++ priv = &shared->priv[phydev->mdio.addr]; ++ ++ phydev->priv = priv; ++ ++ mt798x_phy_leds_state_init(phydev); ++ ++ err = mt7988_phy_fix_leds_polarities(phydev); ++ if (err) ++ return err; ++ ++ return mt798x_phy_calibration(phydev); ++} ++ ++static int mt7981_phy_probe(struct phy_device *phydev) ++{ ++ struct mtk_socphy_priv *priv; ++ ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ mt798x_phy_leds_state_init(phydev); ++ ++ return mt798x_phy_calibration(phydev); ++} ++ + static struct phy_driver mtk_socphy_driver[] = { + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), +@@ -1080,11 +1487,16 @@ static struct phy_driver mtk_socphy_driv + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, +- .probe = mt798x_phy_calibration, ++ .probe = mt7981_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, ++ .led_blink_set = mt798x_phy_led_blink_set, ++ .led_brightness_set = mt798x_phy_led_brightness_set, ++ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, ++ .led_hw_control_set = mt798x_phy_led_hw_control_set, ++ .led_hw_control_get = mt798x_phy_led_hw_control_get, + }, + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), +@@ -1092,11 +1504,16 @@ static struct phy_driver mtk_socphy_driv + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, +- .probe = mt798x_phy_calibration, ++ .probe = mt7988_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, ++ .led_blink_set = mt798x_phy_led_blink_set, ++ .led_brightness_set = mt798x_phy_led_brightness_set, ++ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, ++ .led_hw_control_set = mt798x_phy_led_hw_control_set, ++ .led_hw_control_get = mt798x_phy_led_hw_control_get, + }, + }; + diff --git a/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch new file mode 100644 index 0000000000..76d8b0ef00 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch @@ -0,0 +1,63 @@ +From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 6 Apr 2023 23:36:50 +0100 +Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink + +MAC drivers using phylink expect SGMII in-band-status to be switched off +when attached to a PHY. Make sure this is the case also for mxl-gpy which +keeps SGMII in-band-status in case of SGMII interface mode is used. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -371,8 +371,11 @@ static bool gpy_2500basex_chk(struct phy + + phydev->speed = SPEED_2500; + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, +- VSPEC1_SGMII_CTRL_ANEN, 0); ++ ++ if (!phydev->phylink) ++ phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, ++ VSPEC1_SGMII_CTRL_ANEN, 0); ++ + return true; + } + +@@ -396,6 +399,14 @@ static int gpy_config_aneg(struct phy_de + u32 adv; + int ret; + ++ /* Disable SGMII auto-negotiation if using phylink */ ++ if (phydev->phylink) { ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, ++ VSPEC1_SGMII_CTRL_ANEN, 0); ++ if (ret < 0) ++ return ret; ++ } ++ + if (phydev->autoneg == AUTONEG_DISABLE) { + /* Configure half duplex with genphy_setup_forced, + * because genphy_c45_pma_setup_forced does not support. +@@ -486,6 +497,8 @@ static void gpy_update_interface(struct + switch (phydev->speed) { + case SPEED_2500: + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ if (phydev->phylink) ++ break; + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, + VSPEC1_SGMII_CTRL_ANEN, 0); + if (ret < 0) +@@ -497,7 +510,7 @@ static void gpy_update_interface(struct + case SPEED_100: + case SPEED_10: + phydev->interface = PHY_INTERFACE_MODE_SGMII; +- if (gpy_sgmii_aneg_en(phydev)) ++ if (phydev->phylink || gpy_sgmii_aneg_en(phydev)) + break; + /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed + * if ANEG is disabled (in 2500-BaseX mode). diff --git a/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch new file mode 100644 index 0000000000..b4c07a4b1f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/733-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 +@@ -326,6 +326,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" + depends on PTP_1588_CLOCK_OPTIONAL +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -79,6 +79,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 diff --git a/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch b/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch new file mode 100644 index 0000000000..5daa62b6b7 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch @@ -0,0 +1,270 @@ +From f2195279c234c0f618946424b8236026126bc595 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Daniel Golle +Date: Wed, 24 Jan 2024 02:27:04 +0000 +Subject: [PATCH net] net: phy: mediatek-ge-soc: sync driver with MediaTek SDK +To: Daniel Golle , + Qingfang Deng , + SkyLake Huang , + Andrew Lunn , + Heiner Kallweit , + Russell King , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Matthias Brugger , + AngeloGioacchino Del Regno , + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org + +Sync initialization and calibration routines with MediaTek's reference +driver. Improves compliance and resolves link stability issues with +CH340 IoT devices connected to MT798x built-in PHYs. + +Fixes: 98c485eaf509 ("net: phy: add driver for MediaTek SoC built-in GE PHYs") +Signed-off-by: Daniel Golle +--- + drivers/net/phy/mediatek-ge-soc.c | 147 ++++++++++++++++-------------- + 1 file changed, 81 insertions(+), 66 deletions(-) + +--- a/drivers/net/phy/mediatek-ge-soc.c ++++ b/drivers/net/phy/mediatek-ge-soc.c +@@ -491,7 +491,7 @@ static int tx_r50_fill_result(struct phy + u16 reg, val; + + if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) +- bias = -2; ++ bias = -1; + + val = clamp_val(bias + tx_r50_cal_val, 0, 63); + +@@ -707,6 +707,11 @@ restore: + static void mt798x_phy_common_finetune(struct phy_device *phydev) + { + 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); ++ + /* EnabRandUpdTrig = 1 */ + __phy_write(phydev, 0x11, 0x2f00); + __phy_write(phydev, 0x12, 0xe); +@@ -717,15 +722,56 @@ static void mt798x_phy_common_finetune(s + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x83aa); + +- /* TrFreeze = 0 */ ++ /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ ++ __phy_write(phydev, 0x11, 0x240); ++ __phy_write(phydev, 0x12, 0x0); ++ __phy_write(phydev, 0x10, 0x9680); ++ ++ /* TrFreeze = 0 (mt7988 default) */ + __phy_write(phydev, 0x11, 0x0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9686); + ++ /* SSTrKp100 = 5 */ ++ /* SSTrKf100 = 6 */ ++ /* SSTrKp1000Mas = 5 */ ++ /* SSTrKf1000Mas = 6 */ + /* SSTrKp1000Slv = 5 */ ++ /* SSTrKf1000Slv = 6 */ + __phy_write(phydev, 0x11, 0xbaef); + __phy_write(phydev, 0x12, 0x2e); + __phy_write(phydev, 0x10, 0x968c); ++ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); ++} ++ ++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); ++ /* 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); + + /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, + * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 +@@ -740,7 +786,7 @@ static void mt798x_phy_common_finetune(s + __phy_write(phydev, 0x10, 0x8ec0); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + +- /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ ++ /* 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)); +@@ -773,48 +819,6 @@ static void mt798x_phy_common_finetune(s + 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, +@@ -829,17 +833,7 @@ static void mt7988_phy_finetune(struct p + /* 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); +@@ -847,13 +841,27 @@ static void mt7988_phy_finetune(struct p + + /* VgaDecRate is 1 at default on mt7988 */ + +- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); ++ /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, ++ * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 ++ */ ++ __phy_write(phydev, 0x11, 0xb90a); ++ __phy_write(phydev, 0x12, 0x6f); ++ __phy_write(phydev, 0x10, 0x8f82); ++ ++ /* RemAckCntLimitCtrl = 1 */ ++ __phy_write(phydev, 0x11, 0xfbba); ++ __phy_write(phydev, 0x12, 0xc3); ++ __phy_write(phydev, 0x10, 0x87f8); + +- 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 = 10 */ ++ 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, 0xa)); ++ ++ /* rg_tr_lpf_cnt_val = 1023 */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff); + } + + static void mt798x_phy_eee(struct phy_device *phydev) +@@ -886,11 +894,11 @@ static void mt798x_phy_eee(struct phy_de + 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)); ++ /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, ++ MTK_PHY_LPI_TXPCS_LOC_RCV); + ++ /* This also fixes some IoT issues, such as CH340 */ + 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) | +@@ -924,7 +932,7 @@ static void mt798x_phy_eee(struct phy_de + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9690); + +- /* REG_EEE_st2TrKf1000 = 3 */ ++ /* REG_EEE_st2TrKf1000 = 2 */ + __phy_write(phydev, 0x11, 0x114f); + __phy_write(phydev, 0x12, 0x2); + __phy_write(phydev, 0x10, 0x969a); +@@ -949,7 +957,7 @@ static void mt798x_phy_eee(struct phy_de + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96b8); + +- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ ++ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ + __phy_write(phydev, 0x11, 0x1463); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96ca); +@@ -1461,6 +1469,13 @@ static int mt7988_phy_probe(struct phy_d + if (err) + return err; + ++ /* Disable TX power saving at probing to: ++ * 1. Meet common mode compliance test criteria ++ * 2. Make sure that TX-VCM calibration works fine ++ */ ++ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, ++ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); ++ + return mt798x_phy_calibration(phydev); + } + diff --git a/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch b/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch new file mode 100644 index 0000000000..0c73d520b4 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch @@ -0,0 +1,23 @@ +--- a/drivers/pwm/pwm-mediatek.c ++++ b/drivers/pwm/pwm-mediatek.c +@@ -329,6 +329,12 @@ static const struct pwm_mediatek_of_data + .has_ck_26m_sel = true, + }; + ++static const struct pwm_mediatek_of_data mt7986_pwm_data = { ++ .num_pwms = 2, ++ .pwm45_fixup = false, ++ .has_ck_26m_sel = true, ++}; ++ + static const struct pwm_mediatek_of_data mt8516_pwm_data = { + .num_pwms = 5, + .pwm45_fixup = false, +@@ -342,6 +348,7 @@ static const struct of_device_id pwm_med + { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, + { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, + { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, ++ { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, + { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, + { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data }, + { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, diff --git a/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch b/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch new file mode 100644 index 0000000000..f130fdbc56 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch @@ -0,0 +1,129 @@ +From fae82621ac33e2a4a96220c56e90d1ec6237d394 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 6 Nov 2022 09:01:12 +0100 +Subject: [PATCH] pinctrl: mediatek: extend pinctrl-moore to support new bias + functions + +Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") +introduced SoC specify 'pull_type' attribute to mtk_pinconf_bias_set_combo +and mtk_pinconf_bias_get_combo, and make the functions able to support +almost all Mediatek SoCs that use pinctrl-mtk-common-v2.c. + +This patch enables pinctrl_moore to support these functions. + +Signed-off-by: Sam Shih +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221106080114.7426-6-linux@fw-web.de +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-moore.c | 49 ++++++++++++++++++++---- + 1 file changed, 42 insertions(+), 7 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-moore.c ++++ b/drivers/pinctrl/mediatek/pinctrl-moore.c +@@ -8,6 +8,7 @@ + * + */ + ++#include + #include + #include "pinctrl-moore.h" + +@@ -105,7 +106,7 @@ static int mtk_pinconf_get(struct pinctr + { + struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); + u32 param = pinconf_to_config_param(*config); +- int val, val2, err, reg, ret = 1; ++ int val, val2, err, pullup, reg, ret = 1; + const struct mtk_pin_desc *desc; + + desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; +@@ -114,7 +115,13 @@ static int mtk_pinconf_get(struct pinctr + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- if (hw->soc->bias_disable_get) { ++ if (hw->soc->bias_get_combo) { ++ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); ++ if (err) ++ return err; ++ if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE) ++ return -EINVAL; ++ } else if (hw->soc->bias_disable_get) { + err = hw->soc->bias_disable_get(hw, desc, &ret); + if (err) + return err; +@@ -123,7 +130,15 @@ static int mtk_pinconf_get(struct pinctr + } + break; + case PIN_CONFIG_BIAS_PULL_UP: +- if (hw->soc->bias_get) { ++ if (hw->soc->bias_get_combo) { ++ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); ++ if (err) ++ return err; ++ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) ++ return -EINVAL; ++ if (!pullup) ++ return -EINVAL; ++ } else if (hw->soc->bias_get) { + err = hw->soc->bias_get(hw, desc, 1, &ret); + if (err) + return err; +@@ -132,7 +147,15 @@ static int mtk_pinconf_get(struct pinctr + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: +- if (hw->soc->bias_get) { ++ if (hw->soc->bias_get_combo) { ++ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); ++ if (err) ++ return err; ++ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) ++ return -EINVAL; ++ if (pullup) ++ return -EINVAL; ++ } else if (hw->soc->bias_get) { + err = hw->soc->bias_get(hw, desc, 0, &ret); + if (err) + return err; +@@ -235,7 +258,11 @@ static int mtk_pinconf_set(struct pinctr + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- if (hw->soc->bias_disable_set) { ++ if (hw->soc->bias_set_combo) { ++ err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); ++ if (err) ++ return err; ++ } else if (hw->soc->bias_disable_set) { + err = hw->soc->bias_disable_set(hw, desc); + if (err) + return err; +@@ -244,7 +271,11 @@ static int mtk_pinconf_set(struct pinctr + } + break; + case PIN_CONFIG_BIAS_PULL_UP: +- if (hw->soc->bias_set) { ++ if (hw->soc->bias_set_combo) { ++ err = hw->soc->bias_set_combo(hw, desc, 1, arg); ++ if (err) ++ return err; ++ } else if (hw->soc->bias_set) { + err = hw->soc->bias_set(hw, desc, 1); + if (err) + return err; +@@ -253,7 +284,11 @@ static int mtk_pinconf_set(struct pinctr + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: +- if (hw->soc->bias_set) { ++ if (hw->soc->bias_set_combo) { ++ err = hw->soc->bias_set_combo(hw, desc, 0, arg); ++ if (err) ++ return err; ++ } else if (hw->soc->bias_set) { + err = hw->soc->bias_set(hw, desc, 0); + if (err) + return err; diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch b/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch new file mode 100644 index 0000000000..694b73a2b1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch @@ -0,0 +1,37 @@ +From f167da186acf90847e1a6d3716e253825a6218ec Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Thu, 12 Jan 2023 22:44:49 -0800 +Subject: [PATCH 01/42] thermal/drivers/mtk_thermal: Fix kernel-doc function + name + +Use the correct function name in a kernel-doc comment to prevent +a warning: + +drivers/thermal/mtk_thermal.c:562: warning: expecting prototype for raw_to_mcelsius(). Prototype was for raw_to_mcelsius_v1() instead + +Signed-off-by: Randy Dunlap +Cc: "Rafael J. Wysocki" +Cc: Daniel Lezcano +Cc: Amit Kucheria +Cc: Zhang Rui +Cc: Matthias Brugger +Cc: linux-pm@vger.kernel.org +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-mediatek@lists.infradead.org +Link: https://lore.kernel.org/r/20230113064449.15061-1-rdunlap@infradead.org +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mtk_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -550,7 +550,7 @@ static const struct mtk_thermal_data mt8 + }; + + /** +- * raw_to_mcelsius - convert a raw ADC value to mcelsius ++ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius + * @mt: The thermal controller + * @sensno: sensor number + * @raw: raw ADC value diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch b/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch new file mode 100644 index 0000000000..aaed9d7e90 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch @@ -0,0 +1,37 @@ +From 255509232417ee71fd606cb957d44cf6544f0c43 Mon Sep 17 00:00:00 2001 +From: ye xingchen +Date: Wed, 18 Jan 2023 16:37:47 +0800 +Subject: [PATCH 02/42] thermal/drivers/mtk_thermal: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: ye xingchen +Link: https://lore.kernel.org/r/202301181637472073620@zte.com.cn +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mtk_thermal.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -990,7 +990,6 @@ static int mtk_thermal_probe(struct plat + int ret, i, ctrl_id; + struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; + struct mtk_thermal *mt; +- struct resource *res; + u64 auxadc_phys_base, apmixed_phys_base; + struct thermal_zone_device *tzdev; + void __iomem *apmixed_base, *auxadc_base; +@@ -1009,8 +1008,7 @@ static int mtk_thermal_probe(struct plat + if (IS_ERR(mt->clk_auxadc)) + return PTR_ERR(mt->clk_auxadc); + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- mt->thermal_base = devm_ioremap_resource(&pdev->dev, res); ++ mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(mt->thermal_base)) + return PTR_ERR(mt->thermal_base); + diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch new file mode 100644 index 0000000000..215b0fd7de --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch @@ -0,0 +1,60 @@ +From ca86dbd309ba03bef38ae91f037e2030bb671ab7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 18 Jan 2023 15:40:39 +0000 +Subject: [PATCH 03/42] thermal/drivers/mtk: Use function pointer for + raw_to_mcelsius + +Instead of having if-else logic selecting either raw_to_mcelsius_v1 or +raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function +pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the +probe function. + +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Golle +Reviewed-by: Matthias Brugger +Link: https://lore.kernel.org/r/69c17529e8418da3eec703dde31e1b01e5b0f7e8.1674055882.git.daniel@makrotopia.org +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mtk_thermal.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -292,6 +292,8 @@ struct mtk_thermal { + + const struct mtk_thermal_data *conf; + struct mtk_thermal_bank banks[MAX_NUM_ZONES]; ++ ++ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); + }; + + /* MT8183 thermal sensor data */ +@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature( + for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { + raw = readl(mt->thermal_base + conf->msr[i]); + +- if (mt->conf->version == MTK_THERMAL_V1) { +- temp = raw_to_mcelsius_v1( +- mt, conf->bank_data[bank->id].sensors[i], raw); +- } else { +- temp = raw_to_mcelsius_v2( +- mt, conf->bank_data[bank->id].sensors[i], raw); +- } ++ temp = mt->raw_to_mcelsius( ++ mt, conf->bank_data[bank->id].sensors[i], raw); ++ + + /* + * The first read of a sensor often contains very high bogus +@@ -1073,6 +1071,11 @@ static int mtk_thermal_probe(struct plat + mtk_thermal_release_periodic_ts(mt, auxadc_base); + } + ++ if (mt->conf->version == MTK_THERMAL_V1) ++ mt->raw_to_mcelsius = raw_to_mcelsius_v1; ++ else ++ mt->raw_to_mcelsius = raw_to_mcelsius_v2; ++ + for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) + for (i = 0; i < mt->conf->num_banks; i++) + mtk_thermal_init_bank(mt, i, apmixed_phys_base, diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch b/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch new file mode 100644 index 0000000000..ef2006775a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch @@ -0,0 +1,236 @@ +From aec1d89dccc7cba04fdb3e52dfda328f3302ba17 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 18 Jan 2023 15:40:58 +0000 +Subject: [PATCH 04/42] thermal/drivers/mtk: Add support for MT7986 and MT7981 + +Add support for V3 generation thermal found in MT7986 and MT7981 SoCs. +Brings code to assign values from efuse as well as new function to +convert raw temperature to millidegree celsius, as found in MediaTek's +SDK sources (but cleaned up and de-duplicated) + +[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b + +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/2d341fc45266217249586eb4bd3be3ac4ca83a12.1674055882.git.daniel@makrotopia.org +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mtk_thermal.c | 128 ++++++++++++++++++++++++++++++++-- + 1 file changed, 124 insertions(+), 4 deletions(-) + +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -150,6 +150,20 @@ + #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) + #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) + ++/* ++ * Layout of the fuses providing the calibration data ++ * These macros can be used for MT7981 and MT7986. ++ */ ++#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) ++#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) ++#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) ++#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) ++#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) ++#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) ++#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) ++#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) ++#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) ++ + enum { + VTS1, + VTS2, +@@ -163,6 +177,7 @@ enum { + enum mtk_thermal_version { + MTK_THERMAL_V1 = 1, + MTK_THERMAL_V2, ++ MTK_THERMAL_V3, + }; + + /* MT2701 thermal sensors */ +@@ -245,6 +260,27 @@ enum mtk_thermal_version { + /* The calibration coefficient of sensor */ + #define MT8183_CALIBRATION 153 + ++/* AUXADC channel 11 is used for the temperature sensors */ ++#define MT7986_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT7986 */ ++#define MT7986_NUM_SENSORS 1 ++ ++/* The number of banks in the MT7986 */ ++#define MT7986_NUM_ZONES 1 ++ ++/* The number of sensing points per bank */ ++#define MT7986_NUM_SENSORS_PER_ZONE 1 ++ ++/* MT7986 thermal sensors */ ++#define MT7986_TS1 0 ++ ++/* The number of controller in the MT7986 */ ++#define MT7986_NUM_CONTROLLER 1 ++ ++/* The calibration coefficient of sensor */ ++#define MT7986_CALIBRATION 165 ++ + struct mtk_thermal; + + struct thermal_bank_cfg { +@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762 + static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; + static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; + ++/* MT7986 thermal sensor data */ ++static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; ++static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; ++static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; ++static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; ++static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; ++static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; ++ + /* + * The MT8173 thermal controller has four banks. Each bank can read up to + * four temperature sensors simultaneously. The MT8173 has a total of 5 +@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8 + .version = MTK_THERMAL_V1, + }; + ++/* ++ * MT7986 uses AUXADC Channel 11 for raw data access. ++ */ ++static const struct mtk_thermal_data mt7986_thermal_data = { ++ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT7986_NUM_ZONES, ++ .num_sensors = MT7986_NUM_SENSORS, ++ .vts_index = mt7986_vts_index, ++ .cali_val = MT7986_CALIBRATION, ++ .num_controller = MT7986_NUM_CONTROLLER, ++ .controller_offset = mt7986_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 1, ++ .sensors = mt7986_bank_data, ++ }, ++ }, ++ .msr = mt7986_msr, ++ .adcpnp = mt7986_adcpnp, ++ .sensor_mux_values = mt7986_mux_values, ++ .version = MTK_THERMAL_V3, ++}; ++ + /** + * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius + * @mt: The thermal controller +@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk + return (format_2 - tmp) * 100; + } + ++static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) ++{ ++ s32 tmp; ++ ++ if (raw == 0) ++ return 0; ++ ++ raw &= 0xfff; ++ tmp = 100000 * 15 / 16 * 10000; ++ tmp /= 4096 - 512 + mt->adc_ge; ++ tmp /= 1490; ++ tmp *= raw - mt->vts[sensno] - 2900; ++ ++ return mt->degc_cali * 500 - tmp; ++} ++ + /** + * mtk_thermal_get_bank - get bank + * @bank: The bank +@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2( + return 0; + } + ++static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) ++{ ++ if (!CALIB_BUF1_VALID_V3(buf[1])) ++ return -EINVAL; ++ ++ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); ++ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); ++ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); ++ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); ++ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); ++ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); ++ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); ++ ++ if (CALIB_BUF1_ID_V3(buf[1]) == 0) ++ mt->o_slope = 0; ++ ++ return 0; ++} ++ + static int mtk_thermal_get_calibration_data(struct device *dev, + struct mtk_thermal *mt) + { +@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d + + /* Start with default values */ + mt->adc_ge = 512; ++ mt->adc_oe = 512; + for (i = 0; i < mt->conf->num_sensors; i++) + mt->vts[i] = 260; + mt->degc_cali = 40; +@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d + goto out; + } + +- if (mt->conf->version == MTK_THERMAL_V1) ++ switch (mt->conf->version) { ++ case MTK_THERMAL_V1: + ret = mtk_thermal_extract_efuse_v1(mt, buf); +- else ++ break; ++ case MTK_THERMAL_V2: + ret = mtk_thermal_extract_efuse_v2(mt, buf); ++ break; ++ case MTK_THERMAL_V3: ++ ret = mtk_thermal_extract_efuse_v3(mt, buf); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } + + if (ret) { + dev_info(dev, "Device not calibrated, using default calibration values\n"); +@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the + .data = (void *)&mt7622_thermal_data, + }, + { ++ .compatible = "mediatek,mt7986-thermal", ++ .data = (void *)&mt7986_thermal_data, ++ }, ++ { + .compatible = "mediatek,mt8183-thermal", + .data = (void *)&mt8183_thermal_data, + }, { +@@ -1066,15 +1184,17 @@ static int mtk_thermal_probe(struct plat + goto err_disable_clk_auxadc; + } + +- if (mt->conf->version == MTK_THERMAL_V2) { ++ if (mt->conf->version != MTK_THERMAL_V1) { + mtk_thermal_turn_on_buffer(apmixed_base); + mtk_thermal_release_periodic_ts(mt, auxadc_base); + } + + if (mt->conf->version == MTK_THERMAL_V1) + mt->raw_to_mcelsius = raw_to_mcelsius_v1; +- else ++ else if (mt->conf->version == MTK_THERMAL_V2) + mt->raw_to_mcelsius = raw_to_mcelsius_v2; ++ else ++ mt->raw_to_mcelsius = raw_to_mcelsius_v3; + + for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) + for (i = 0; i < mt->conf->num_banks; i++) diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch b/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch new file mode 100644 index 0000000000..e102a338cd --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch @@ -0,0 +1,2602 @@ +From 5e3aac197a74914ccec2732a89c29d960730d28f Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Thu, 9 Feb 2023 11:56:23 +0100 +Subject: [PATCH 05/42] thermal/drivers/mediatek: Relocate driver to mediatek + folder + +Add MediaTek proprietary folder to upstream more thermal zone and cooler +drivers, relocate the original thermal controller driver to it, and rename it +as "auxadc_thermal.c" to show its purpose more clearly. + +Signed-off-by: Balsam CHIHI +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230209105628.50294-2-bchihi@baylibre.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/Kconfig | 14 ++++--------- + drivers/thermal/Makefile | 2 +- + drivers/thermal/mediatek/Kconfig | 21 +++++++++++++++++++ + drivers/thermal/mediatek/Makefile | 1 + + .../auxadc_thermal.c} | 2 +- + 5 files changed, 28 insertions(+), 12 deletions(-) + create mode 100644 drivers/thermal/mediatek/Kconfig + create mode 100644 drivers/thermal/mediatek/Makefile + rename drivers/thermal/{mtk_thermal.c => mediatek/auxadc_thermal.c} (99%) + +--- a/drivers/thermal/Kconfig ++++ b/drivers/thermal/Kconfig +@@ -412,16 +412,10 @@ config DA9062_THERMAL + zone. + Compatible with the DA9062 and DA9061 PMICs. + +-config MTK_THERMAL +- tristate "Temperature sensor driver for mediatek SoCs" +- depends on ARCH_MEDIATEK || COMPILE_TEST +- depends on HAS_IOMEM +- depends on NVMEM || NVMEM=n +- depends on RESET_CONTROLLER +- default y +- help +- Enable this option if you want to have support for thermal management +- controller present in Mediatek SoCs ++menu "Mediatek thermal drivers" ++depends on ARCH_MEDIATEK || COMPILE_TEST ++source "drivers/thermal/mediatek/Kconfig" ++endmenu + + config AMLOGIC_THERMAL + tristate "Amlogic Thermal Support" +--- a/drivers/thermal/Makefile ++++ b/drivers/thermal/Makefile +@@ -55,7 +55,7 @@ obj-y += st/ + obj-y += qcom/ + obj-y += tegra/ + obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o +-obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o ++obj-y += mediatek/ + obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o + obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o + obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o +--- /dev/null ++++ b/drivers/thermal/mediatek/Kconfig +@@ -0,0 +1,21 @@ ++config MTK_THERMAL ++ tristate "MediaTek thermal drivers" ++ depends on THERMAL_OF ++ help ++ This is the option for MediaTek thermal software solutions. ++ Please enable corresponding options to get temperature ++ information from thermal sensors or turn on throttle ++ mechaisms for thermal mitigation. ++ ++if MTK_THERMAL ++ ++config MTK_SOC_THERMAL ++ tristate "AUXADC temperature sensor driver for MediaTek SoCs" ++ depends on HAS_IOMEM ++ help ++ Enable this option if you want to get SoC temperature ++ information for MediaTek platforms. ++ This driver configures thermal controllers to collect ++ temperature via AUXADC interface. ++ ++endif +--- /dev/null ++++ b/drivers/thermal/mediatek/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o +--- a/drivers/thermal/mtk_thermal.c ++++ /dev/null +@@ -1,1254 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (c) 2015 MediaTek Inc. +- * Author: Hanyi Wu +- * Sascha Hauer +- * Dawei Chien +- * Louis Yu +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "thermal_hwmon.h" +- +-/* AUXADC Registers */ +-#define AUXADC_CON1_SET_V 0x008 +-#define AUXADC_CON1_CLR_V 0x00c +-#define AUXADC_CON2_V 0x010 +-#define AUXADC_DATA(channel) (0x14 + (channel) * 4) +- +-#define APMIXED_SYS_TS_CON1 0x604 +- +-/* Thermal Controller Registers */ +-#define TEMP_MONCTL0 0x000 +-#define TEMP_MONCTL1 0x004 +-#define TEMP_MONCTL2 0x008 +-#define TEMP_MONIDET0 0x014 +-#define TEMP_MONIDET1 0x018 +-#define TEMP_MSRCTL0 0x038 +-#define TEMP_MSRCTL1 0x03c +-#define TEMP_AHBPOLL 0x040 +-#define TEMP_AHBTO 0x044 +-#define TEMP_ADCPNP0 0x048 +-#define TEMP_ADCPNP1 0x04c +-#define TEMP_ADCPNP2 0x050 +-#define TEMP_ADCPNP3 0x0b4 +- +-#define TEMP_ADCMUX 0x054 +-#define TEMP_ADCEN 0x060 +-#define TEMP_PNPMUXADDR 0x064 +-#define TEMP_ADCMUXADDR 0x068 +-#define TEMP_ADCENADDR 0x074 +-#define TEMP_ADCVALIDADDR 0x078 +-#define TEMP_ADCVOLTADDR 0x07c +-#define TEMP_RDCTRL 0x080 +-#define TEMP_ADCVALIDMASK 0x084 +-#define TEMP_ADCVOLTAGESHIFT 0x088 +-#define TEMP_ADCWRITECTRL 0x08c +-#define TEMP_MSR0 0x090 +-#define TEMP_MSR1 0x094 +-#define TEMP_MSR2 0x098 +-#define TEMP_MSR3 0x0B8 +- +-#define TEMP_SPARE0 0x0f0 +- +-#define TEMP_ADCPNP0_1 0x148 +-#define TEMP_ADCPNP1_1 0x14c +-#define TEMP_ADCPNP2_1 0x150 +-#define TEMP_MSR0_1 0x190 +-#define TEMP_MSR1_1 0x194 +-#define TEMP_MSR2_1 0x198 +-#define TEMP_ADCPNP3_1 0x1b4 +-#define TEMP_MSR3_1 0x1B8 +- +-#define PTPCORESEL 0x400 +- +-#define TEMP_MONCTL1_PERIOD_UNIT(x) ((x) & 0x3ff) +- +-#define TEMP_MONCTL2_FILTER_INTERVAL(x) (((x) & 0x3ff) << 16) +-#define TEMP_MONCTL2_SENSOR_INTERVAL(x) ((x) & 0x3ff) +- +-#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x) (x) +- +-#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE BIT(0) +-#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE BIT(1) +- +-#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5) +-#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit) +- +-/* MT8173 thermal sensors */ +-#define MT8173_TS1 0 +-#define MT8173_TS2 1 +-#define MT8173_TS3 2 +-#define MT8173_TS4 3 +-#define MT8173_TSABB 4 +- +-/* AUXADC channel 11 is used for the temperature sensors */ +-#define MT8173_TEMP_AUXADC_CHANNEL 11 +- +-/* The total number of temperature sensors in the MT8173 */ +-#define MT8173_NUM_SENSORS 5 +- +-/* The number of banks in the MT8173 */ +-#define MT8173_NUM_ZONES 4 +- +-/* The number of sensing points per bank */ +-#define MT8173_NUM_SENSORS_PER_ZONE 4 +- +-/* The number of controller in the MT8173 */ +-#define MT8173_NUM_CONTROLLER 1 +- +-/* The calibration coefficient of sensor */ +-#define MT8173_CALIBRATION 165 +- +-/* +- * Layout of the fuses providing the calibration data +- * These macros could be used for MT8183, MT8173, MT2701, and MT2712. +- * MT8183 has 6 sensors and needs 6 VTS calibration data. +- * MT8173 has 5 sensors and needs 5 VTS calibration data. +- * MT2701 has 3 sensors and needs 3 VTS calibration data. +- * MT2712 has 4 sensors and needs 4 VTS calibration data. +- */ +-#define CALIB_BUF0_VALID_V1 BIT(0) +-#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) +-#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) +-#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) +-#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) +-#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) +-#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) +-#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) +-#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) +-#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) +-#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) +-#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) +- +-/* +- * Layout of the fuses providing the calibration data +- * These macros could be used for MT7622. +- */ +-#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) +-#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) +-#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) +-#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) +-#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) +-#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) +-#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) +-#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) +-#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) +- +-/* +- * Layout of the fuses providing the calibration data +- * These macros can be used for MT7981 and MT7986. +- */ +-#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) +-#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) +-#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) +-#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) +-#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) +-#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) +-#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) +-#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) +-#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) +- +-enum { +- VTS1, +- VTS2, +- VTS3, +- VTS4, +- VTS5, +- VTSABB, +- MAX_NUM_VTS, +-}; +- +-enum mtk_thermal_version { +- MTK_THERMAL_V1 = 1, +- MTK_THERMAL_V2, +- MTK_THERMAL_V3, +-}; +- +-/* MT2701 thermal sensors */ +-#define MT2701_TS1 0 +-#define MT2701_TS2 1 +-#define MT2701_TSABB 2 +- +-/* AUXADC channel 11 is used for the temperature sensors */ +-#define MT2701_TEMP_AUXADC_CHANNEL 11 +- +-/* The total number of temperature sensors in the MT2701 */ +-#define MT2701_NUM_SENSORS 3 +- +-/* The number of sensing points per bank */ +-#define MT2701_NUM_SENSORS_PER_ZONE 3 +- +-/* The number of controller in the MT2701 */ +-#define MT2701_NUM_CONTROLLER 1 +- +-/* The calibration coefficient of sensor */ +-#define MT2701_CALIBRATION 165 +- +-/* MT2712 thermal sensors */ +-#define MT2712_TS1 0 +-#define MT2712_TS2 1 +-#define MT2712_TS3 2 +-#define MT2712_TS4 3 +- +-/* AUXADC channel 11 is used for the temperature sensors */ +-#define MT2712_TEMP_AUXADC_CHANNEL 11 +- +-/* The total number of temperature sensors in the MT2712 */ +-#define MT2712_NUM_SENSORS 4 +- +-/* The number of sensing points per bank */ +-#define MT2712_NUM_SENSORS_PER_ZONE 4 +- +-/* The number of controller in the MT2712 */ +-#define MT2712_NUM_CONTROLLER 1 +- +-/* The calibration coefficient of sensor */ +-#define MT2712_CALIBRATION 165 +- +-#define MT7622_TEMP_AUXADC_CHANNEL 11 +-#define MT7622_NUM_SENSORS 1 +-#define MT7622_NUM_ZONES 1 +-#define MT7622_NUM_SENSORS_PER_ZONE 1 +-#define MT7622_TS1 0 +-#define MT7622_NUM_CONTROLLER 1 +- +-/* The maximum number of banks */ +-#define MAX_NUM_ZONES 8 +- +-/* The calibration coefficient of sensor */ +-#define MT7622_CALIBRATION 165 +- +-/* MT8183 thermal sensors */ +-#define MT8183_TS1 0 +-#define MT8183_TS2 1 +-#define MT8183_TS3 2 +-#define MT8183_TS4 3 +-#define MT8183_TS5 4 +-#define MT8183_TSABB 5 +- +-/* AUXADC channel is used for the temperature sensors */ +-#define MT8183_TEMP_AUXADC_CHANNEL 11 +- +-/* The total number of temperature sensors in the MT8183 */ +-#define MT8183_NUM_SENSORS 6 +- +-/* The number of banks in the MT8183 */ +-#define MT8183_NUM_ZONES 1 +- +-/* The number of sensing points per bank */ +-#define MT8183_NUM_SENSORS_PER_ZONE 6 +- +-/* The number of controller in the MT8183 */ +-#define MT8183_NUM_CONTROLLER 2 +- +-/* The calibration coefficient of sensor */ +-#define MT8183_CALIBRATION 153 +- +-/* AUXADC channel 11 is used for the temperature sensors */ +-#define MT7986_TEMP_AUXADC_CHANNEL 11 +- +-/* The total number of temperature sensors in the MT7986 */ +-#define MT7986_NUM_SENSORS 1 +- +-/* The number of banks in the MT7986 */ +-#define MT7986_NUM_ZONES 1 +- +-/* The number of sensing points per bank */ +-#define MT7986_NUM_SENSORS_PER_ZONE 1 +- +-/* MT7986 thermal sensors */ +-#define MT7986_TS1 0 +- +-/* The number of controller in the MT7986 */ +-#define MT7986_NUM_CONTROLLER 1 +- +-/* The calibration coefficient of sensor */ +-#define MT7986_CALIBRATION 165 +- +-struct mtk_thermal; +- +-struct thermal_bank_cfg { +- unsigned int num_sensors; +- const int *sensors; +-}; +- +-struct mtk_thermal_bank { +- struct mtk_thermal *mt; +- int id; +-}; +- +-struct mtk_thermal_data { +- s32 num_banks; +- s32 num_sensors; +- s32 auxadc_channel; +- const int *vts_index; +- const int *sensor_mux_values; +- const int *msr; +- const int *adcpnp; +- const int cali_val; +- const int num_controller; +- const int *controller_offset; +- bool need_switch_bank; +- struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; +- enum mtk_thermal_version version; +-}; +- +-struct mtk_thermal { +- struct device *dev; +- void __iomem *thermal_base; +- +- struct clk *clk_peri_therm; +- struct clk *clk_auxadc; +- /* lock: for getting and putting banks */ +- struct mutex lock; +- +- /* Calibration values */ +- s32 adc_ge; +- s32 adc_oe; +- s32 degc_cali; +- s32 o_slope; +- s32 o_slope_sign; +- s32 vts[MAX_NUM_VTS]; +- +- const struct mtk_thermal_data *conf; +- struct mtk_thermal_bank banks[MAX_NUM_ZONES]; +- +- int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); +-}; +- +-/* MT8183 thermal sensor data */ +-static const int mt8183_bank_data[MT8183_NUM_SENSORS] = { +- MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB +-}; +- +-static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = { +- TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1 +-}; +- +-static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = { +- TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1, +- TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1 +-}; +- +-static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 }; +-static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100}; +- +-static const int mt8183_vts_index[MT8183_NUM_SENSORS] = { +- VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB +-}; +- +-/* MT8173 thermal sensor data */ +-static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { +- { MT8173_TS2, MT8173_TS3 }, +- { MT8173_TS2, MT8173_TS4 }, +- { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, +- { MT8173_TS2 }, +-}; +- +-static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { +- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 +-}; +- +-static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { +- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 +-}; +- +-static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; +-static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, }; +- +-static const int mt8173_vts_index[MT8173_NUM_SENSORS] = { +- VTS1, VTS2, VTS3, VTS4, VTSABB +-}; +- +-/* MT2701 thermal sensor data */ +-static const int mt2701_bank_data[MT2701_NUM_SENSORS] = { +- MT2701_TS1, MT2701_TS2, MT2701_TSABB +-}; +- +-static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { +- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 +-}; +- +-static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { +- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 +-}; +- +-static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; +-static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, }; +- +-static const int mt2701_vts_index[MT2701_NUM_SENSORS] = { +- VTS1, VTS2, VTS3 +-}; +- +-/* MT2712 thermal sensor data */ +-static const int mt2712_bank_data[MT2712_NUM_SENSORS] = { +- MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4 +-}; +- +-static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = { +- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 +-}; +- +-static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { +- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 +-}; +- +-static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; +-static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, }; +- +-static const int mt2712_vts_index[MT2712_NUM_SENSORS] = { +- VTS1, VTS2, VTS3, VTS4 +-}; +- +-/* MT7622 thermal sensor data */ +-static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; +-static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; +-static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; +-static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; +-static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; +-static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; +- +-/* MT7986 thermal sensor data */ +-static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; +-static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; +-static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; +-static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; +-static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; +-static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; +- +-/* +- * The MT8173 thermal controller has four banks. Each bank can read up to +- * four temperature sensors simultaneously. The MT8173 has a total of 5 +- * temperature sensors. We use each bank to measure a certain area of the +- * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple +- * areas, hence is used in different banks. +- * +- * The thermal core only gets the maximum temperature of all banks, so +- * the bank concept wouldn't be necessary here. However, the SVS (Smart +- * Voltage Scaling) unit makes its decisions based on the same bank +- * data, and this indeed needs the temperatures of the individual banks +- * for making better decisions. +- */ +-static const struct mtk_thermal_data mt8173_thermal_data = { +- .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL, +- .num_banks = MT8173_NUM_ZONES, +- .num_sensors = MT8173_NUM_SENSORS, +- .vts_index = mt8173_vts_index, +- .cali_val = MT8173_CALIBRATION, +- .num_controller = MT8173_NUM_CONTROLLER, +- .controller_offset = mt8173_tc_offset, +- .need_switch_bank = true, +- .bank_data = { +- { +- .num_sensors = 2, +- .sensors = mt8173_bank_data[0], +- }, { +- .num_sensors = 2, +- .sensors = mt8173_bank_data[1], +- }, { +- .num_sensors = 3, +- .sensors = mt8173_bank_data[2], +- }, { +- .num_sensors = 1, +- .sensors = mt8173_bank_data[3], +- }, +- }, +- .msr = mt8173_msr, +- .adcpnp = mt8173_adcpnp, +- .sensor_mux_values = mt8173_mux_values, +- .version = MTK_THERMAL_V1, +-}; +- +-/* +- * The MT2701 thermal controller has one bank, which can read up to +- * three temperature sensors simultaneously. The MT2701 has a total of 3 +- * temperature sensors. +- * +- * The thermal core only gets the maximum temperature of this one bank, +- * so the bank concept wouldn't be necessary here. However, the SVS (Smart +- * Voltage Scaling) unit makes its decisions based on the same bank +- * data. +- */ +-static const struct mtk_thermal_data mt2701_thermal_data = { +- .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL, +- .num_banks = 1, +- .num_sensors = MT2701_NUM_SENSORS, +- .vts_index = mt2701_vts_index, +- .cali_val = MT2701_CALIBRATION, +- .num_controller = MT2701_NUM_CONTROLLER, +- .controller_offset = mt2701_tc_offset, +- .need_switch_bank = true, +- .bank_data = { +- { +- .num_sensors = 3, +- .sensors = mt2701_bank_data, +- }, +- }, +- .msr = mt2701_msr, +- .adcpnp = mt2701_adcpnp, +- .sensor_mux_values = mt2701_mux_values, +- .version = MTK_THERMAL_V1, +-}; +- +-/* +- * The MT2712 thermal controller has one bank, which can read up to +- * four temperature sensors simultaneously. The MT2712 has a total of 4 +- * temperature sensors. +- * +- * The thermal core only gets the maximum temperature of this one bank, +- * so the bank concept wouldn't be necessary here. However, the SVS (Smart +- * Voltage Scaling) unit makes its decisions based on the same bank +- * data. +- */ +-static const struct mtk_thermal_data mt2712_thermal_data = { +- .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL, +- .num_banks = 1, +- .num_sensors = MT2712_NUM_SENSORS, +- .vts_index = mt2712_vts_index, +- .cali_val = MT2712_CALIBRATION, +- .num_controller = MT2712_NUM_CONTROLLER, +- .controller_offset = mt2712_tc_offset, +- .need_switch_bank = true, +- .bank_data = { +- { +- .num_sensors = 4, +- .sensors = mt2712_bank_data, +- }, +- }, +- .msr = mt2712_msr, +- .adcpnp = mt2712_adcpnp, +- .sensor_mux_values = mt2712_mux_values, +- .version = MTK_THERMAL_V1, +-}; +- +-/* +- * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data +- * access. +- */ +-static const struct mtk_thermal_data mt7622_thermal_data = { +- .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, +- .num_banks = MT7622_NUM_ZONES, +- .num_sensors = MT7622_NUM_SENSORS, +- .vts_index = mt7622_vts_index, +- .cali_val = MT7622_CALIBRATION, +- .num_controller = MT7622_NUM_CONTROLLER, +- .controller_offset = mt7622_tc_offset, +- .need_switch_bank = true, +- .bank_data = { +- { +- .num_sensors = 1, +- .sensors = mt7622_bank_data, +- }, +- }, +- .msr = mt7622_msr, +- .adcpnp = mt7622_adcpnp, +- .sensor_mux_values = mt7622_mux_values, +- .version = MTK_THERMAL_V2, +-}; +- +-/* +- * The MT8183 thermal controller has one bank for the current SW framework. +- * The MT8183 has a total of 6 temperature sensors. +- * There are two thermal controller to control the six sensor. +- * The first one bind 2 sensor, and the other bind 4 sensors. +- * The thermal core only gets the maximum temperature of all sensor, so +- * the bank concept wouldn't be necessary here. However, the SVS (Smart +- * Voltage Scaling) unit makes its decisions based on the same bank +- * data, and this indeed needs the temperatures of the individual banks +- * for making better decisions. +- */ +-static const struct mtk_thermal_data mt8183_thermal_data = { +- .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL, +- .num_banks = MT8183_NUM_ZONES, +- .num_sensors = MT8183_NUM_SENSORS, +- .vts_index = mt8183_vts_index, +- .cali_val = MT8183_CALIBRATION, +- .num_controller = MT8183_NUM_CONTROLLER, +- .controller_offset = mt8183_tc_offset, +- .need_switch_bank = false, +- .bank_data = { +- { +- .num_sensors = 6, +- .sensors = mt8183_bank_data, +- }, +- }, +- +- .msr = mt8183_msr, +- .adcpnp = mt8183_adcpnp, +- .sensor_mux_values = mt8183_mux_values, +- .version = MTK_THERMAL_V1, +-}; +- +-/* +- * MT7986 uses AUXADC Channel 11 for raw data access. +- */ +-static const struct mtk_thermal_data mt7986_thermal_data = { +- .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, +- .num_banks = MT7986_NUM_ZONES, +- .num_sensors = MT7986_NUM_SENSORS, +- .vts_index = mt7986_vts_index, +- .cali_val = MT7986_CALIBRATION, +- .num_controller = MT7986_NUM_CONTROLLER, +- .controller_offset = mt7986_tc_offset, +- .need_switch_bank = true, +- .bank_data = { +- { +- .num_sensors = 1, +- .sensors = mt7986_bank_data, +- }, +- }, +- .msr = mt7986_msr, +- .adcpnp = mt7986_adcpnp, +- .sensor_mux_values = mt7986_mux_values, +- .version = MTK_THERMAL_V3, +-}; +- +-/** +- * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius +- * @mt: The thermal controller +- * @sensno: sensor number +- * @raw: raw ADC value +- * +- * This converts the raw ADC value to mcelsius using the SoC specific +- * calibration constants +- */ +-static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) +-{ +- s32 tmp; +- +- raw &= 0xfff; +- +- tmp = 203450520 << 3; +- tmp /= mt->conf->cali_val + mt->o_slope; +- tmp /= 10000 + mt->adc_ge; +- tmp *= raw - mt->vts[sensno] - 3350; +- tmp >>= 3; +- +- return mt->degc_cali * 500 - tmp; +-} +- +-static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) +-{ +- s32 format_1; +- s32 format_2; +- s32 g_oe; +- s32 g_gain; +- s32 g_x_roomt; +- s32 tmp; +- +- if (raw == 0) +- return 0; +- +- raw &= 0xfff; +- g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); +- g_oe = mt->adc_oe - 512; +- format_1 = mt->vts[VTS2] + 3105 - g_oe; +- format_2 = (mt->degc_cali * 10) >> 1; +- g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; +- +- tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; +- tmp = tmp * 10 * 100 / 11; +- +- if (mt->o_slope_sign == 0) +- tmp = tmp / (165 - mt->o_slope); +- else +- tmp = tmp / (165 + mt->o_slope); +- +- return (format_2 - tmp) * 100; +-} +- +-static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) +-{ +- s32 tmp; +- +- if (raw == 0) +- return 0; +- +- raw &= 0xfff; +- tmp = 100000 * 15 / 16 * 10000; +- tmp /= 4096 - 512 + mt->adc_ge; +- tmp /= 1490; +- tmp *= raw - mt->vts[sensno] - 2900; +- +- return mt->degc_cali * 500 - tmp; +-} +- +-/** +- * mtk_thermal_get_bank - get bank +- * @bank: The bank +- * +- * The bank registers are banked, we have to select a bank in the +- * PTPCORESEL register to access it. +- */ +-static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank) +-{ +- struct mtk_thermal *mt = bank->mt; +- u32 val; +- +- if (mt->conf->need_switch_bank) { +- mutex_lock(&mt->lock); +- +- val = readl(mt->thermal_base + PTPCORESEL); +- val &= ~0xf; +- val |= bank->id; +- writel(val, mt->thermal_base + PTPCORESEL); +- } +-} +- +-/** +- * mtk_thermal_put_bank - release bank +- * @bank: The bank +- * +- * release a bank previously taken with mtk_thermal_get_bank, +- */ +-static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank) +-{ +- struct mtk_thermal *mt = bank->mt; +- +- if (mt->conf->need_switch_bank) +- mutex_unlock(&mt->lock); +-} +- +-/** +- * mtk_thermal_bank_temperature - get the temperature of a bank +- * @bank: The bank +- * +- * The temperature of a bank is considered the maximum temperature of +- * the sensors associated to the bank. +- */ +-static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) +-{ +- struct mtk_thermal *mt = bank->mt; +- const struct mtk_thermal_data *conf = mt->conf; +- int i, temp = INT_MIN, max = INT_MIN; +- u32 raw; +- +- for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { +- raw = readl(mt->thermal_base + conf->msr[i]); +- +- temp = mt->raw_to_mcelsius( +- mt, conf->bank_data[bank->id].sensors[i], raw); +- +- +- /* +- * The first read of a sensor often contains very high bogus +- * temperature value. Filter these out so that the system does +- * not immediately shut down. +- */ +- if (temp > 200000) +- temp = 0; +- +- if (temp > max) +- max = temp; +- } +- +- return max; +-} +- +-static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) +-{ +- struct mtk_thermal *mt = tz->devdata; +- int i; +- int tempmax = INT_MIN; +- +- for (i = 0; i < mt->conf->num_banks; i++) { +- struct mtk_thermal_bank *bank = &mt->banks[i]; +- +- mtk_thermal_get_bank(bank); +- +- tempmax = max(tempmax, mtk_thermal_bank_temperature(bank)); +- +- mtk_thermal_put_bank(bank); +- } +- +- *temperature = tempmax; +- +- return 0; +-} +- +-static const struct thermal_zone_device_ops mtk_thermal_ops = { +- .get_temp = mtk_read_temp, +-}; +- +-static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, +- u32 apmixed_phys_base, u32 auxadc_phys_base, +- int ctrl_id) +-{ +- struct mtk_thermal_bank *bank = &mt->banks[num]; +- const struct mtk_thermal_data *conf = mt->conf; +- int i; +- +- int offset = mt->conf->controller_offset[ctrl_id]; +- void __iomem *controller_base = mt->thermal_base + offset; +- +- bank->id = num; +- bank->mt = mt; +- +- mtk_thermal_get_bank(bank); +- +- /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */ +- writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1); +- +- /* +- * filt interval is 1 * 46.540us = 46.54us, +- * sen interval is 429 * 46.540us = 19.96ms +- */ +- writel(TEMP_MONCTL2_FILTER_INTERVAL(1) | +- TEMP_MONCTL2_SENSOR_INTERVAL(429), +- controller_base + TEMP_MONCTL2); +- +- /* poll is set to 10u */ +- writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768), +- controller_base + TEMP_AHBPOLL); +- +- /* temperature sampling control, 1 sample */ +- writel(0x0, controller_base + TEMP_MSRCTL0); +- +- /* exceed this polling time, IRQ would be inserted */ +- writel(0xffffffff, controller_base + TEMP_AHBTO); +- +- /* number of interrupts per event, 1 is enough */ +- writel(0x0, controller_base + TEMP_MONIDET0); +- writel(0x0, controller_base + TEMP_MONIDET1); +- +- /* +- * The MT8173 thermal controller does not have its own ADC. Instead it +- * uses AHB bus accesses to control the AUXADC. To do this the thermal +- * controller has to be programmed with the physical addresses of the +- * AUXADC registers and with the various bit positions in the AUXADC. +- * Also the thermal controller controls a mux in the APMIXEDSYS register +- * space. +- */ +- +- /* +- * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) +- * automatically by hw +- */ +- writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX); +- +- /* AHB address for auxadc mux selection */ +- writel(auxadc_phys_base + AUXADC_CON1_CLR_V, +- controller_base + TEMP_ADCMUXADDR); +- +- if (mt->conf->version == MTK_THERMAL_V1) { +- /* AHB address for pnp sensor mux selection */ +- writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, +- controller_base + TEMP_PNPMUXADDR); +- } +- +- /* AHB value for auxadc enable */ +- writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); +- +- /* AHB address for auxadc enable (channel 0 immediate mode selected) */ +- writel(auxadc_phys_base + AUXADC_CON1_SET_V, +- controller_base + TEMP_ADCENADDR); +- +- /* AHB address for auxadc valid bit */ +- writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), +- controller_base + TEMP_ADCVALIDADDR); +- +- /* AHB address for auxadc voltage output */ +- writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), +- controller_base + TEMP_ADCVOLTADDR); +- +- /* read valid & voltage are at the same register */ +- writel(0x0, controller_base + TEMP_RDCTRL); +- +- /* indicate where the valid bit is */ +- writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12), +- controller_base + TEMP_ADCVALIDMASK); +- +- /* no shift */ +- writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT); +- +- /* enable auxadc mux write transaction */ +- writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE, +- controller_base + TEMP_ADCWRITECTRL); +- +- for (i = 0; i < conf->bank_data[num].num_sensors; i++) +- writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]], +- mt->thermal_base + conf->adcpnp[i]); +- +- writel((1 << conf->bank_data[num].num_sensors) - 1, +- controller_base + TEMP_MONCTL0); +- +- writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE | +- TEMP_ADCWRITECTRL_ADC_MUX_WRITE, +- controller_base + TEMP_ADCWRITECTRL); +- +- mtk_thermal_put_bank(bank); +-} +- +-static u64 of_get_phys_base(struct device_node *np) +-{ +- u64 size64; +- const __be32 *regaddr_p; +- +- regaddr_p = of_get_address(np, 0, &size64, NULL); +- if (!regaddr_p) +- return OF_BAD_ADDR; +- +- return of_translate_address(np, regaddr_p); +-} +- +-static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) +-{ +- int i; +- +- if (!(buf[0] & CALIB_BUF0_VALID_V1)) +- return -EINVAL; +- +- mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); +- +- for (i = 0; i < mt->conf->num_sensors; i++) { +- switch (mt->conf->vts_index[i]) { +- case VTS1: +- mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); +- break; +- case VTS2: +- mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); +- break; +- case VTS3: +- mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); +- break; +- case VTS4: +- mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); +- break; +- case VTS5: +- mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); +- break; +- case VTSABB: +- mt->vts[VTSABB] = +- CALIB_BUF2_VTS_TSABB_V1(buf[2]); +- break; +- default: +- break; +- } +- } +- +- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); +- if (CALIB_BUF1_ID_V1(buf[1]) & +- CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) +- mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); +- else +- mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); +- +- return 0; +-} +- +-static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) +-{ +- if (!CALIB_BUF1_VALID_V2(buf[1])) +- return -EINVAL; +- +- mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); +- mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); +- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); +- mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); +- mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); +- mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); +- mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); +- mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); +- +- return 0; +-} +- +-static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) +-{ +- if (!CALIB_BUF1_VALID_V3(buf[1])) +- return -EINVAL; +- +- mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); +- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); +- mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); +- mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); +- mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); +- mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); +- mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); +- +- if (CALIB_BUF1_ID_V3(buf[1]) == 0) +- mt->o_slope = 0; +- +- return 0; +-} +- +-static int mtk_thermal_get_calibration_data(struct device *dev, +- struct mtk_thermal *mt) +-{ +- struct nvmem_cell *cell; +- u32 *buf; +- size_t len; +- int i, ret = 0; +- +- /* Start with default values */ +- mt->adc_ge = 512; +- mt->adc_oe = 512; +- for (i = 0; i < mt->conf->num_sensors; i++) +- mt->vts[i] = 260; +- mt->degc_cali = 40; +- mt->o_slope = 0; +- +- cell = nvmem_cell_get(dev, "calibration-data"); +- if (IS_ERR(cell)) { +- if (PTR_ERR(cell) == -EPROBE_DEFER) +- return PTR_ERR(cell); +- return 0; +- } +- +- buf = (u32 *)nvmem_cell_read(cell, &len); +- +- nvmem_cell_put(cell); +- +- if (IS_ERR(buf)) +- return PTR_ERR(buf); +- +- if (len < 3 * sizeof(u32)) { +- dev_warn(dev, "invalid calibration data\n"); +- ret = -EINVAL; +- goto out; +- } +- +- switch (mt->conf->version) { +- case MTK_THERMAL_V1: +- ret = mtk_thermal_extract_efuse_v1(mt, buf); +- break; +- case MTK_THERMAL_V2: +- ret = mtk_thermal_extract_efuse_v2(mt, buf); +- break; +- case MTK_THERMAL_V3: +- ret = mtk_thermal_extract_efuse_v3(mt, buf); +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- if (ret) { +- dev_info(dev, "Device not calibrated, using default calibration values\n"); +- ret = 0; +- } +- +-out: +- kfree(buf); +- +- return ret; +-} +- +-static const struct of_device_id mtk_thermal_of_match[] = { +- { +- .compatible = "mediatek,mt8173-thermal", +- .data = (void *)&mt8173_thermal_data, +- }, +- { +- .compatible = "mediatek,mt2701-thermal", +- .data = (void *)&mt2701_thermal_data, +- }, +- { +- .compatible = "mediatek,mt2712-thermal", +- .data = (void *)&mt2712_thermal_data, +- }, +- { +- .compatible = "mediatek,mt7622-thermal", +- .data = (void *)&mt7622_thermal_data, +- }, +- { +- .compatible = "mediatek,mt7986-thermal", +- .data = (void *)&mt7986_thermal_data, +- }, +- { +- .compatible = "mediatek,mt8183-thermal", +- .data = (void *)&mt8183_thermal_data, +- }, { +- }, +-}; +-MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); +- +-static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) +-{ +- int tmp; +- +- tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); +- tmp &= ~(0x37); +- tmp |= 0x1; +- writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); +- udelay(200); +-} +- +-static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, +- void __iomem *auxadc_base) +-{ +- int tmp; +- +- writel(0x800, auxadc_base + AUXADC_CON1_SET_V); +- writel(0x1, mt->thermal_base + TEMP_MONCTL0); +- tmp = readl(mt->thermal_base + TEMP_MSRCTL1); +- writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); +-} +- +-static int mtk_thermal_probe(struct platform_device *pdev) +-{ +- int ret, i, ctrl_id; +- struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; +- struct mtk_thermal *mt; +- u64 auxadc_phys_base, apmixed_phys_base; +- struct thermal_zone_device *tzdev; +- void __iomem *apmixed_base, *auxadc_base; +- +- mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); +- if (!mt) +- return -ENOMEM; +- +- mt->conf = of_device_get_match_data(&pdev->dev); +- +- mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); +- if (IS_ERR(mt->clk_peri_therm)) +- return PTR_ERR(mt->clk_peri_therm); +- +- mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); +- if (IS_ERR(mt->clk_auxadc)) +- return PTR_ERR(mt->clk_auxadc); +- +- mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); +- if (IS_ERR(mt->thermal_base)) +- return PTR_ERR(mt->thermal_base); +- +- ret = mtk_thermal_get_calibration_data(&pdev->dev, mt); +- if (ret) +- return ret; +- +- mutex_init(&mt->lock); +- +- mt->dev = &pdev->dev; +- +- auxadc = of_parse_phandle(np, "mediatek,auxadc", 0); +- if (!auxadc) { +- dev_err(&pdev->dev, "missing auxadc node\n"); +- return -ENODEV; +- } +- +- auxadc_base = of_iomap(auxadc, 0); +- auxadc_phys_base = of_get_phys_base(auxadc); +- +- of_node_put(auxadc); +- +- if (auxadc_phys_base == OF_BAD_ADDR) { +- dev_err(&pdev->dev, "Can't get auxadc phys address\n"); +- return -EINVAL; +- } +- +- apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0); +- if (!apmixedsys) { +- dev_err(&pdev->dev, "missing apmixedsys node\n"); +- return -ENODEV; +- } +- +- apmixed_base = of_iomap(apmixedsys, 0); +- apmixed_phys_base = of_get_phys_base(apmixedsys); +- +- of_node_put(apmixedsys); +- +- if (apmixed_phys_base == OF_BAD_ADDR) { +- dev_err(&pdev->dev, "Can't get auxadc phys address\n"); +- return -EINVAL; +- } +- +- ret = device_reset_optional(&pdev->dev); +- if (ret) +- return ret; +- +- ret = clk_prepare_enable(mt->clk_auxadc); +- if (ret) { +- dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); +- return ret; +- } +- +- ret = clk_prepare_enable(mt->clk_peri_therm); +- if (ret) { +- dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); +- goto err_disable_clk_auxadc; +- } +- +- if (mt->conf->version != MTK_THERMAL_V1) { +- mtk_thermal_turn_on_buffer(apmixed_base); +- mtk_thermal_release_periodic_ts(mt, auxadc_base); +- } +- +- if (mt->conf->version == MTK_THERMAL_V1) +- mt->raw_to_mcelsius = raw_to_mcelsius_v1; +- else if (mt->conf->version == MTK_THERMAL_V2) +- mt->raw_to_mcelsius = raw_to_mcelsius_v2; +- else +- mt->raw_to_mcelsius = raw_to_mcelsius_v3; +- +- for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) +- for (i = 0; i < mt->conf->num_banks; i++) +- mtk_thermal_init_bank(mt, i, apmixed_phys_base, +- auxadc_phys_base, ctrl_id); +- +- platform_set_drvdata(pdev, mt); +- +- tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, +- &mtk_thermal_ops); +- if (IS_ERR(tzdev)) { +- ret = PTR_ERR(tzdev); +- goto err_disable_clk_peri_therm; +- } +- +- ret = devm_thermal_add_hwmon_sysfs(tzdev); +- if (ret) +- dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); +- +- return 0; +- +-err_disable_clk_peri_therm: +- clk_disable_unprepare(mt->clk_peri_therm); +-err_disable_clk_auxadc: +- clk_disable_unprepare(mt->clk_auxadc); +- +- return ret; +-} +- +-static int mtk_thermal_remove(struct platform_device *pdev) +-{ +- struct mtk_thermal *mt = platform_get_drvdata(pdev); +- +- clk_disable_unprepare(mt->clk_peri_therm); +- clk_disable_unprepare(mt->clk_auxadc); +- +- return 0; +-} +- +-static struct platform_driver mtk_thermal_driver = { +- .probe = mtk_thermal_probe, +- .remove = mtk_thermal_remove, +- .driver = { +- .name = "mtk-thermal", +- .of_match_table = mtk_thermal_of_match, +- }, +-}; +- +-module_platform_driver(mtk_thermal_driver); +- +-MODULE_AUTHOR("Michael Kao "); +-MODULE_AUTHOR("Louis Yu "); +-MODULE_AUTHOR("Dawei Chien "); +-MODULE_AUTHOR("Sascha Hauer "); +-MODULE_AUTHOR("Hanyi Wu "); +-MODULE_DESCRIPTION("Mediatek thermal driver"); +-MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -0,0 +1,1254 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2015 MediaTek Inc. ++ * Author: Hanyi Wu ++ * Sascha Hauer ++ * Dawei Chien ++ * Louis Yu ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../thermal_hwmon.h" ++ ++/* AUXADC Registers */ ++#define AUXADC_CON1_SET_V 0x008 ++#define AUXADC_CON1_CLR_V 0x00c ++#define AUXADC_CON2_V 0x010 ++#define AUXADC_DATA(channel) (0x14 + (channel) * 4) ++ ++#define APMIXED_SYS_TS_CON1 0x604 ++ ++/* Thermal Controller Registers */ ++#define TEMP_MONCTL0 0x000 ++#define TEMP_MONCTL1 0x004 ++#define TEMP_MONCTL2 0x008 ++#define TEMP_MONIDET0 0x014 ++#define TEMP_MONIDET1 0x018 ++#define TEMP_MSRCTL0 0x038 ++#define TEMP_MSRCTL1 0x03c ++#define TEMP_AHBPOLL 0x040 ++#define TEMP_AHBTO 0x044 ++#define TEMP_ADCPNP0 0x048 ++#define TEMP_ADCPNP1 0x04c ++#define TEMP_ADCPNP2 0x050 ++#define TEMP_ADCPNP3 0x0b4 ++ ++#define TEMP_ADCMUX 0x054 ++#define TEMP_ADCEN 0x060 ++#define TEMP_PNPMUXADDR 0x064 ++#define TEMP_ADCMUXADDR 0x068 ++#define TEMP_ADCENADDR 0x074 ++#define TEMP_ADCVALIDADDR 0x078 ++#define TEMP_ADCVOLTADDR 0x07c ++#define TEMP_RDCTRL 0x080 ++#define TEMP_ADCVALIDMASK 0x084 ++#define TEMP_ADCVOLTAGESHIFT 0x088 ++#define TEMP_ADCWRITECTRL 0x08c ++#define TEMP_MSR0 0x090 ++#define TEMP_MSR1 0x094 ++#define TEMP_MSR2 0x098 ++#define TEMP_MSR3 0x0B8 ++ ++#define TEMP_SPARE0 0x0f0 ++ ++#define TEMP_ADCPNP0_1 0x148 ++#define TEMP_ADCPNP1_1 0x14c ++#define TEMP_ADCPNP2_1 0x150 ++#define TEMP_MSR0_1 0x190 ++#define TEMP_MSR1_1 0x194 ++#define TEMP_MSR2_1 0x198 ++#define TEMP_ADCPNP3_1 0x1b4 ++#define TEMP_MSR3_1 0x1B8 ++ ++#define PTPCORESEL 0x400 ++ ++#define TEMP_MONCTL1_PERIOD_UNIT(x) ((x) & 0x3ff) ++ ++#define TEMP_MONCTL2_FILTER_INTERVAL(x) (((x) & 0x3ff) << 16) ++#define TEMP_MONCTL2_SENSOR_INTERVAL(x) ((x) & 0x3ff) ++ ++#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x) (x) ++ ++#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE BIT(0) ++#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE BIT(1) ++ ++#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5) ++#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit) ++ ++/* MT8173 thermal sensors */ ++#define MT8173_TS1 0 ++#define MT8173_TS2 1 ++#define MT8173_TS3 2 ++#define MT8173_TS4 3 ++#define MT8173_TSABB 4 ++ ++/* AUXADC channel 11 is used for the temperature sensors */ ++#define MT8173_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT8173 */ ++#define MT8173_NUM_SENSORS 5 ++ ++/* The number of banks in the MT8173 */ ++#define MT8173_NUM_ZONES 4 ++ ++/* The number of sensing points per bank */ ++#define MT8173_NUM_SENSORS_PER_ZONE 4 ++ ++/* The number of controller in the MT8173 */ ++#define MT8173_NUM_CONTROLLER 1 ++ ++/* The calibration coefficient of sensor */ ++#define MT8173_CALIBRATION 165 ++ ++/* ++ * Layout of the fuses providing the calibration data ++ * These macros could be used for MT8183, MT8173, MT2701, and MT2712. ++ * MT8183 has 6 sensors and needs 6 VTS calibration data. ++ * MT8173 has 5 sensors and needs 5 VTS calibration data. ++ * MT2701 has 3 sensors and needs 3 VTS calibration data. ++ * MT2712 has 4 sensors and needs 4 VTS calibration data. ++ */ ++#define CALIB_BUF0_VALID_V1 BIT(0) ++#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) ++#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) ++#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) ++#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) ++#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) ++#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) ++#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) ++#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) ++#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) ++#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) ++#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) ++ ++/* ++ * Layout of the fuses providing the calibration data ++ * These macros could be used for MT7622. ++ */ ++#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) ++#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) ++#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) ++#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) ++#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) ++#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) ++#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) ++#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) ++#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) ++ ++/* ++ * Layout of the fuses providing the calibration data ++ * These macros can be used for MT7981 and MT7986. ++ */ ++#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) ++#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) ++#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) ++#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) ++#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) ++#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) ++#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) ++#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) ++#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) ++ ++enum { ++ VTS1, ++ VTS2, ++ VTS3, ++ VTS4, ++ VTS5, ++ VTSABB, ++ MAX_NUM_VTS, ++}; ++ ++enum mtk_thermal_version { ++ MTK_THERMAL_V1 = 1, ++ MTK_THERMAL_V2, ++ MTK_THERMAL_V3, ++}; ++ ++/* MT2701 thermal sensors */ ++#define MT2701_TS1 0 ++#define MT2701_TS2 1 ++#define MT2701_TSABB 2 ++ ++/* AUXADC channel 11 is used for the temperature sensors */ ++#define MT2701_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT2701 */ ++#define MT2701_NUM_SENSORS 3 ++ ++/* The number of sensing points per bank */ ++#define MT2701_NUM_SENSORS_PER_ZONE 3 ++ ++/* The number of controller in the MT2701 */ ++#define MT2701_NUM_CONTROLLER 1 ++ ++/* The calibration coefficient of sensor */ ++#define MT2701_CALIBRATION 165 ++ ++/* MT2712 thermal sensors */ ++#define MT2712_TS1 0 ++#define MT2712_TS2 1 ++#define MT2712_TS3 2 ++#define MT2712_TS4 3 ++ ++/* AUXADC channel 11 is used for the temperature sensors */ ++#define MT2712_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT2712 */ ++#define MT2712_NUM_SENSORS 4 ++ ++/* The number of sensing points per bank */ ++#define MT2712_NUM_SENSORS_PER_ZONE 4 ++ ++/* The number of controller in the MT2712 */ ++#define MT2712_NUM_CONTROLLER 1 ++ ++/* The calibration coefficient of sensor */ ++#define MT2712_CALIBRATION 165 ++ ++#define MT7622_TEMP_AUXADC_CHANNEL 11 ++#define MT7622_NUM_SENSORS 1 ++#define MT7622_NUM_ZONES 1 ++#define MT7622_NUM_SENSORS_PER_ZONE 1 ++#define MT7622_TS1 0 ++#define MT7622_NUM_CONTROLLER 1 ++ ++/* The maximum number of banks */ ++#define MAX_NUM_ZONES 8 ++ ++/* The calibration coefficient of sensor */ ++#define MT7622_CALIBRATION 165 ++ ++/* MT8183 thermal sensors */ ++#define MT8183_TS1 0 ++#define MT8183_TS2 1 ++#define MT8183_TS3 2 ++#define MT8183_TS4 3 ++#define MT8183_TS5 4 ++#define MT8183_TSABB 5 ++ ++/* AUXADC channel is used for the temperature sensors */ ++#define MT8183_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT8183 */ ++#define MT8183_NUM_SENSORS 6 ++ ++/* The number of banks in the MT8183 */ ++#define MT8183_NUM_ZONES 1 ++ ++/* The number of sensing points per bank */ ++#define MT8183_NUM_SENSORS_PER_ZONE 6 ++ ++/* The number of controller in the MT8183 */ ++#define MT8183_NUM_CONTROLLER 2 ++ ++/* The calibration coefficient of sensor */ ++#define MT8183_CALIBRATION 153 ++ ++/* AUXADC channel 11 is used for the temperature sensors */ ++#define MT7986_TEMP_AUXADC_CHANNEL 11 ++ ++/* The total number of temperature sensors in the MT7986 */ ++#define MT7986_NUM_SENSORS 1 ++ ++/* The number of banks in the MT7986 */ ++#define MT7986_NUM_ZONES 1 ++ ++/* The number of sensing points per bank */ ++#define MT7986_NUM_SENSORS_PER_ZONE 1 ++ ++/* MT7986 thermal sensors */ ++#define MT7986_TS1 0 ++ ++/* The number of controller in the MT7986 */ ++#define MT7986_NUM_CONTROLLER 1 ++ ++/* The calibration coefficient of sensor */ ++#define MT7986_CALIBRATION 165 ++ ++struct mtk_thermal; ++ ++struct thermal_bank_cfg { ++ unsigned int num_sensors; ++ const int *sensors; ++}; ++ ++struct mtk_thermal_bank { ++ struct mtk_thermal *mt; ++ int id; ++}; ++ ++struct mtk_thermal_data { ++ s32 num_banks; ++ s32 num_sensors; ++ s32 auxadc_channel; ++ const int *vts_index; ++ const int *sensor_mux_values; ++ const int *msr; ++ const int *adcpnp; ++ const int cali_val; ++ const int num_controller; ++ const int *controller_offset; ++ bool need_switch_bank; ++ struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; ++ enum mtk_thermal_version version; ++}; ++ ++struct mtk_thermal { ++ struct device *dev; ++ void __iomem *thermal_base; ++ ++ struct clk *clk_peri_therm; ++ struct clk *clk_auxadc; ++ /* lock: for getting and putting banks */ ++ struct mutex lock; ++ ++ /* Calibration values */ ++ s32 adc_ge; ++ s32 adc_oe; ++ s32 degc_cali; ++ s32 o_slope; ++ s32 o_slope_sign; ++ s32 vts[MAX_NUM_VTS]; ++ ++ const struct mtk_thermal_data *conf; ++ struct mtk_thermal_bank banks[MAX_NUM_ZONES]; ++ ++ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); ++}; ++ ++/* MT8183 thermal sensor data */ ++static const int mt8183_bank_data[MT8183_NUM_SENSORS] = { ++ MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB ++}; ++ ++static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = { ++ TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1 ++}; ++ ++static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = { ++ TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1, ++ TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1 ++}; ++ ++static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 }; ++static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100}; ++ ++static const int mt8183_vts_index[MT8183_NUM_SENSORS] = { ++ VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB ++}; ++ ++/* MT8173 thermal sensor data */ ++static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { ++ { MT8173_TS2, MT8173_TS3 }, ++ { MT8173_TS2, MT8173_TS4 }, ++ { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, ++ { MT8173_TS2 }, ++}; ++ ++static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { ++ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 ++}; ++ ++static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { ++ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 ++}; ++ ++static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; ++static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, }; ++ ++static const int mt8173_vts_index[MT8173_NUM_SENSORS] = { ++ VTS1, VTS2, VTS3, VTS4, VTSABB ++}; ++ ++/* MT2701 thermal sensor data */ ++static const int mt2701_bank_data[MT2701_NUM_SENSORS] = { ++ MT2701_TS1, MT2701_TS2, MT2701_TSABB ++}; ++ ++static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { ++ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 ++}; ++ ++static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { ++ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 ++}; ++ ++static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; ++static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, }; ++ ++static const int mt2701_vts_index[MT2701_NUM_SENSORS] = { ++ VTS1, VTS2, VTS3 ++}; ++ ++/* MT2712 thermal sensor data */ ++static const int mt2712_bank_data[MT2712_NUM_SENSORS] = { ++ MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4 ++}; ++ ++static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = { ++ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 ++}; ++ ++static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { ++ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 ++}; ++ ++static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; ++static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, }; ++ ++static const int mt2712_vts_index[MT2712_NUM_SENSORS] = { ++ VTS1, VTS2, VTS3, VTS4 ++}; ++ ++/* MT7622 thermal sensor data */ ++static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; ++static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; ++static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; ++static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; ++static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; ++static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; ++ ++/* MT7986 thermal sensor data */ ++static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; ++static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; ++static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; ++static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; ++static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; ++static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; ++ ++/* ++ * The MT8173 thermal controller has four banks. Each bank can read up to ++ * four temperature sensors simultaneously. The MT8173 has a total of 5 ++ * temperature sensors. We use each bank to measure a certain area of the ++ * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple ++ * areas, hence is used in different banks. ++ * ++ * The thermal core only gets the maximum temperature of all banks, so ++ * the bank concept wouldn't be necessary here. However, the SVS (Smart ++ * Voltage Scaling) unit makes its decisions based on the same bank ++ * data, and this indeed needs the temperatures of the individual banks ++ * for making better decisions. ++ */ ++static const struct mtk_thermal_data mt8173_thermal_data = { ++ .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT8173_NUM_ZONES, ++ .num_sensors = MT8173_NUM_SENSORS, ++ .vts_index = mt8173_vts_index, ++ .cali_val = MT8173_CALIBRATION, ++ .num_controller = MT8173_NUM_CONTROLLER, ++ .controller_offset = mt8173_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 2, ++ .sensors = mt8173_bank_data[0], ++ }, { ++ .num_sensors = 2, ++ .sensors = mt8173_bank_data[1], ++ }, { ++ .num_sensors = 3, ++ .sensors = mt8173_bank_data[2], ++ }, { ++ .num_sensors = 1, ++ .sensors = mt8173_bank_data[3], ++ }, ++ }, ++ .msr = mt8173_msr, ++ .adcpnp = mt8173_adcpnp, ++ .sensor_mux_values = mt8173_mux_values, ++ .version = MTK_THERMAL_V1, ++}; ++ ++/* ++ * The MT2701 thermal controller has one bank, which can read up to ++ * three temperature sensors simultaneously. The MT2701 has a total of 3 ++ * temperature sensors. ++ * ++ * The thermal core only gets the maximum temperature of this one bank, ++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart ++ * Voltage Scaling) unit makes its decisions based on the same bank ++ * data. ++ */ ++static const struct mtk_thermal_data mt2701_thermal_data = { ++ .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL, ++ .num_banks = 1, ++ .num_sensors = MT2701_NUM_SENSORS, ++ .vts_index = mt2701_vts_index, ++ .cali_val = MT2701_CALIBRATION, ++ .num_controller = MT2701_NUM_CONTROLLER, ++ .controller_offset = mt2701_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 3, ++ .sensors = mt2701_bank_data, ++ }, ++ }, ++ .msr = mt2701_msr, ++ .adcpnp = mt2701_adcpnp, ++ .sensor_mux_values = mt2701_mux_values, ++ .version = MTK_THERMAL_V1, ++}; ++ ++/* ++ * The MT2712 thermal controller has one bank, which can read up to ++ * four temperature sensors simultaneously. The MT2712 has a total of 4 ++ * temperature sensors. ++ * ++ * The thermal core only gets the maximum temperature of this one bank, ++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart ++ * Voltage Scaling) unit makes its decisions based on the same bank ++ * data. ++ */ ++static const struct mtk_thermal_data mt2712_thermal_data = { ++ .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL, ++ .num_banks = 1, ++ .num_sensors = MT2712_NUM_SENSORS, ++ .vts_index = mt2712_vts_index, ++ .cali_val = MT2712_CALIBRATION, ++ .num_controller = MT2712_NUM_CONTROLLER, ++ .controller_offset = mt2712_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 4, ++ .sensors = mt2712_bank_data, ++ }, ++ }, ++ .msr = mt2712_msr, ++ .adcpnp = mt2712_adcpnp, ++ .sensor_mux_values = mt2712_mux_values, ++ .version = MTK_THERMAL_V1, ++}; ++ ++/* ++ * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data ++ * access. ++ */ ++static const struct mtk_thermal_data mt7622_thermal_data = { ++ .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT7622_NUM_ZONES, ++ .num_sensors = MT7622_NUM_SENSORS, ++ .vts_index = mt7622_vts_index, ++ .cali_val = MT7622_CALIBRATION, ++ .num_controller = MT7622_NUM_CONTROLLER, ++ .controller_offset = mt7622_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 1, ++ .sensors = mt7622_bank_data, ++ }, ++ }, ++ .msr = mt7622_msr, ++ .adcpnp = mt7622_adcpnp, ++ .sensor_mux_values = mt7622_mux_values, ++ .version = MTK_THERMAL_V2, ++}; ++ ++/* ++ * The MT8183 thermal controller has one bank for the current SW framework. ++ * The MT8183 has a total of 6 temperature sensors. ++ * There are two thermal controller to control the six sensor. ++ * The first one bind 2 sensor, and the other bind 4 sensors. ++ * The thermal core only gets the maximum temperature of all sensor, so ++ * the bank concept wouldn't be necessary here. However, the SVS (Smart ++ * Voltage Scaling) unit makes its decisions based on the same bank ++ * data, and this indeed needs the temperatures of the individual banks ++ * for making better decisions. ++ */ ++static const struct mtk_thermal_data mt8183_thermal_data = { ++ .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT8183_NUM_ZONES, ++ .num_sensors = MT8183_NUM_SENSORS, ++ .vts_index = mt8183_vts_index, ++ .cali_val = MT8183_CALIBRATION, ++ .num_controller = MT8183_NUM_CONTROLLER, ++ .controller_offset = mt8183_tc_offset, ++ .need_switch_bank = false, ++ .bank_data = { ++ { ++ .num_sensors = 6, ++ .sensors = mt8183_bank_data, ++ }, ++ }, ++ ++ .msr = mt8183_msr, ++ .adcpnp = mt8183_adcpnp, ++ .sensor_mux_values = mt8183_mux_values, ++ .version = MTK_THERMAL_V1, ++}; ++ ++/* ++ * MT7986 uses AUXADC Channel 11 for raw data access. ++ */ ++static const struct mtk_thermal_data mt7986_thermal_data = { ++ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT7986_NUM_ZONES, ++ .num_sensors = MT7986_NUM_SENSORS, ++ .vts_index = mt7986_vts_index, ++ .cali_val = MT7986_CALIBRATION, ++ .num_controller = MT7986_NUM_CONTROLLER, ++ .controller_offset = mt7986_tc_offset, ++ .need_switch_bank = true, ++ .bank_data = { ++ { ++ .num_sensors = 1, ++ .sensors = mt7986_bank_data, ++ }, ++ }, ++ .msr = mt7986_msr, ++ .adcpnp = mt7986_adcpnp, ++ .sensor_mux_values = mt7986_mux_values, ++ .version = MTK_THERMAL_V3, ++}; ++ ++/** ++ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius ++ * @mt: The thermal controller ++ * @sensno: sensor number ++ * @raw: raw ADC value ++ * ++ * This converts the raw ADC value to mcelsius using the SoC specific ++ * calibration constants ++ */ ++static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) ++{ ++ s32 tmp; ++ ++ raw &= 0xfff; ++ ++ tmp = 203450520 << 3; ++ tmp /= mt->conf->cali_val + mt->o_slope; ++ tmp /= 10000 + mt->adc_ge; ++ tmp *= raw - mt->vts[sensno] - 3350; ++ tmp >>= 3; ++ ++ return mt->degc_cali * 500 - tmp; ++} ++ ++static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) ++{ ++ s32 format_1; ++ s32 format_2; ++ s32 g_oe; ++ s32 g_gain; ++ s32 g_x_roomt; ++ s32 tmp; ++ ++ if (raw == 0) ++ return 0; ++ ++ raw &= 0xfff; ++ g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); ++ g_oe = mt->adc_oe - 512; ++ format_1 = mt->vts[VTS2] + 3105 - g_oe; ++ format_2 = (mt->degc_cali * 10) >> 1; ++ g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; ++ ++ tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; ++ tmp = tmp * 10 * 100 / 11; ++ ++ if (mt->o_slope_sign == 0) ++ tmp = tmp / (165 - mt->o_slope); ++ else ++ tmp = tmp / (165 + mt->o_slope); ++ ++ return (format_2 - tmp) * 100; ++} ++ ++static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) ++{ ++ s32 tmp; ++ ++ if (raw == 0) ++ return 0; ++ ++ raw &= 0xfff; ++ tmp = 100000 * 15 / 16 * 10000; ++ tmp /= 4096 - 512 + mt->adc_ge; ++ tmp /= 1490; ++ tmp *= raw - mt->vts[sensno] - 2900; ++ ++ return mt->degc_cali * 500 - tmp; ++} ++ ++/** ++ * mtk_thermal_get_bank - get bank ++ * @bank: The bank ++ * ++ * The bank registers are banked, we have to select a bank in the ++ * PTPCORESEL register to access it. ++ */ ++static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank) ++{ ++ struct mtk_thermal *mt = bank->mt; ++ u32 val; ++ ++ if (mt->conf->need_switch_bank) { ++ mutex_lock(&mt->lock); ++ ++ val = readl(mt->thermal_base + PTPCORESEL); ++ val &= ~0xf; ++ val |= bank->id; ++ writel(val, mt->thermal_base + PTPCORESEL); ++ } ++} ++ ++/** ++ * mtk_thermal_put_bank - release bank ++ * @bank: The bank ++ * ++ * release a bank previously taken with mtk_thermal_get_bank, ++ */ ++static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank) ++{ ++ struct mtk_thermal *mt = bank->mt; ++ ++ if (mt->conf->need_switch_bank) ++ mutex_unlock(&mt->lock); ++} ++ ++/** ++ * mtk_thermal_bank_temperature - get the temperature of a bank ++ * @bank: The bank ++ * ++ * The temperature of a bank is considered the maximum temperature of ++ * the sensors associated to the bank. ++ */ ++static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) ++{ ++ struct mtk_thermal *mt = bank->mt; ++ const struct mtk_thermal_data *conf = mt->conf; ++ int i, temp = INT_MIN, max = INT_MIN; ++ u32 raw; ++ ++ for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { ++ raw = readl(mt->thermal_base + conf->msr[i]); ++ ++ temp = mt->raw_to_mcelsius( ++ mt, conf->bank_data[bank->id].sensors[i], raw); ++ ++ ++ /* ++ * The first read of a sensor often contains very high bogus ++ * temperature value. Filter these out so that the system does ++ * not immediately shut down. ++ */ ++ if (temp > 200000) ++ temp = 0; ++ ++ if (temp > max) ++ max = temp; ++ } ++ ++ return max; ++} ++ ++static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) ++{ ++ struct mtk_thermal *mt = tz->devdata; ++ int i; ++ int tempmax = INT_MIN; ++ ++ for (i = 0; i < mt->conf->num_banks; i++) { ++ struct mtk_thermal_bank *bank = &mt->banks[i]; ++ ++ mtk_thermal_get_bank(bank); ++ ++ tempmax = max(tempmax, mtk_thermal_bank_temperature(bank)); ++ ++ mtk_thermal_put_bank(bank); ++ } ++ ++ *temperature = tempmax; ++ ++ return 0; ++} ++ ++static const struct thermal_zone_device_ops mtk_thermal_ops = { ++ .get_temp = mtk_read_temp, ++}; ++ ++static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, ++ u32 apmixed_phys_base, u32 auxadc_phys_base, ++ int ctrl_id) ++{ ++ struct mtk_thermal_bank *bank = &mt->banks[num]; ++ const struct mtk_thermal_data *conf = mt->conf; ++ int i; ++ ++ int offset = mt->conf->controller_offset[ctrl_id]; ++ void __iomem *controller_base = mt->thermal_base + offset; ++ ++ bank->id = num; ++ bank->mt = mt; ++ ++ mtk_thermal_get_bank(bank); ++ ++ /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */ ++ writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1); ++ ++ /* ++ * filt interval is 1 * 46.540us = 46.54us, ++ * sen interval is 429 * 46.540us = 19.96ms ++ */ ++ writel(TEMP_MONCTL2_FILTER_INTERVAL(1) | ++ TEMP_MONCTL2_SENSOR_INTERVAL(429), ++ controller_base + TEMP_MONCTL2); ++ ++ /* poll is set to 10u */ ++ writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768), ++ controller_base + TEMP_AHBPOLL); ++ ++ /* temperature sampling control, 1 sample */ ++ writel(0x0, controller_base + TEMP_MSRCTL0); ++ ++ /* exceed this polling time, IRQ would be inserted */ ++ writel(0xffffffff, controller_base + TEMP_AHBTO); ++ ++ /* number of interrupts per event, 1 is enough */ ++ writel(0x0, controller_base + TEMP_MONIDET0); ++ writel(0x0, controller_base + TEMP_MONIDET1); ++ ++ /* ++ * The MT8173 thermal controller does not have its own ADC. Instead it ++ * uses AHB bus accesses to control the AUXADC. To do this the thermal ++ * controller has to be programmed with the physical addresses of the ++ * AUXADC registers and with the various bit positions in the AUXADC. ++ * Also the thermal controller controls a mux in the APMIXEDSYS register ++ * space. ++ */ ++ ++ /* ++ * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) ++ * automatically by hw ++ */ ++ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX); ++ ++ /* AHB address for auxadc mux selection */ ++ writel(auxadc_phys_base + AUXADC_CON1_CLR_V, ++ controller_base + TEMP_ADCMUXADDR); ++ ++ if (mt->conf->version == MTK_THERMAL_V1) { ++ /* AHB address for pnp sensor mux selection */ ++ writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, ++ controller_base + TEMP_PNPMUXADDR); ++ } ++ ++ /* AHB value for auxadc enable */ ++ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); ++ ++ /* AHB address for auxadc enable (channel 0 immediate mode selected) */ ++ writel(auxadc_phys_base + AUXADC_CON1_SET_V, ++ controller_base + TEMP_ADCENADDR); ++ ++ /* AHB address for auxadc valid bit */ ++ writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), ++ controller_base + TEMP_ADCVALIDADDR); ++ ++ /* AHB address for auxadc voltage output */ ++ writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), ++ controller_base + TEMP_ADCVOLTADDR); ++ ++ /* read valid & voltage are at the same register */ ++ writel(0x0, controller_base + TEMP_RDCTRL); ++ ++ /* indicate where the valid bit is */ ++ writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12), ++ controller_base + TEMP_ADCVALIDMASK); ++ ++ /* no shift */ ++ writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT); ++ ++ /* enable auxadc mux write transaction */ ++ writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE, ++ controller_base + TEMP_ADCWRITECTRL); ++ ++ for (i = 0; i < conf->bank_data[num].num_sensors; i++) ++ writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]], ++ mt->thermal_base + conf->adcpnp[i]); ++ ++ writel((1 << conf->bank_data[num].num_sensors) - 1, ++ controller_base + TEMP_MONCTL0); ++ ++ writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE | ++ TEMP_ADCWRITECTRL_ADC_MUX_WRITE, ++ controller_base + TEMP_ADCWRITECTRL); ++ ++ mtk_thermal_put_bank(bank); ++} ++ ++static u64 of_get_phys_base(struct device_node *np) ++{ ++ u64 size64; ++ const __be32 *regaddr_p; ++ ++ regaddr_p = of_get_address(np, 0, &size64, NULL); ++ if (!regaddr_p) ++ return OF_BAD_ADDR; ++ ++ return of_translate_address(np, regaddr_p); ++} ++ ++static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) ++{ ++ int i; ++ ++ if (!(buf[0] & CALIB_BUF0_VALID_V1)) ++ return -EINVAL; ++ ++ mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); ++ ++ for (i = 0; i < mt->conf->num_sensors; i++) { ++ switch (mt->conf->vts_index[i]) { ++ case VTS1: ++ mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); ++ break; ++ case VTS2: ++ mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); ++ break; ++ case VTS3: ++ mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); ++ break; ++ case VTS4: ++ mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); ++ break; ++ case VTS5: ++ mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); ++ break; ++ case VTSABB: ++ mt->vts[VTSABB] = ++ CALIB_BUF2_VTS_TSABB_V1(buf[2]); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); ++ if (CALIB_BUF1_ID_V1(buf[1]) & ++ CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) ++ mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); ++ else ++ mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); ++ ++ return 0; ++} ++ ++static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) ++{ ++ if (!CALIB_BUF1_VALID_V2(buf[1])) ++ return -EINVAL; ++ ++ mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); ++ mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); ++ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); ++ mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); ++ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); ++ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); ++ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); ++ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); ++ ++ return 0; ++} ++ ++static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) ++{ ++ if (!CALIB_BUF1_VALID_V3(buf[1])) ++ return -EINVAL; ++ ++ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); ++ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); ++ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); ++ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); ++ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); ++ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); ++ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); ++ ++ if (CALIB_BUF1_ID_V3(buf[1]) == 0) ++ mt->o_slope = 0; ++ ++ return 0; ++} ++ ++static int mtk_thermal_get_calibration_data(struct device *dev, ++ struct mtk_thermal *mt) ++{ ++ struct nvmem_cell *cell; ++ u32 *buf; ++ size_t len; ++ int i, ret = 0; ++ ++ /* Start with default values */ ++ mt->adc_ge = 512; ++ mt->adc_oe = 512; ++ for (i = 0; i < mt->conf->num_sensors; i++) ++ mt->vts[i] = 260; ++ mt->degc_cali = 40; ++ mt->o_slope = 0; ++ ++ cell = nvmem_cell_get(dev, "calibration-data"); ++ if (IS_ERR(cell)) { ++ if (PTR_ERR(cell) == -EPROBE_DEFER) ++ return PTR_ERR(cell); ++ return 0; ++ } ++ ++ buf = (u32 *)nvmem_cell_read(cell, &len); ++ ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ if (len < 3 * sizeof(u32)) { ++ dev_warn(dev, "invalid calibration data\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ switch (mt->conf->version) { ++ case MTK_THERMAL_V1: ++ ret = mtk_thermal_extract_efuse_v1(mt, buf); ++ break; ++ case MTK_THERMAL_V2: ++ ret = mtk_thermal_extract_efuse_v2(mt, buf); ++ break; ++ case MTK_THERMAL_V3: ++ ret = mtk_thermal_extract_efuse_v3(mt, buf); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret) { ++ dev_info(dev, "Device not calibrated, using default calibration values\n"); ++ ret = 0; ++ } ++ ++out: ++ kfree(buf); ++ ++ return ret; ++} ++ ++static const struct of_device_id mtk_thermal_of_match[] = { ++ { ++ .compatible = "mediatek,mt8173-thermal", ++ .data = (void *)&mt8173_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt2701-thermal", ++ .data = (void *)&mt2701_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt2712-thermal", ++ .data = (void *)&mt2712_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt7622-thermal", ++ .data = (void *)&mt7622_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt7986-thermal", ++ .data = (void *)&mt7986_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt8183-thermal", ++ .data = (void *)&mt8183_thermal_data, ++ }, { ++ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); ++ ++static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) ++{ ++ int tmp; ++ ++ tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); ++ tmp &= ~(0x37); ++ tmp |= 0x1; ++ writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); ++ udelay(200); ++} ++ ++static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, ++ void __iomem *auxadc_base) ++{ ++ int tmp; ++ ++ writel(0x800, auxadc_base + AUXADC_CON1_SET_V); ++ writel(0x1, mt->thermal_base + TEMP_MONCTL0); ++ tmp = readl(mt->thermal_base + TEMP_MSRCTL1); ++ writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); ++} ++ ++static int mtk_thermal_probe(struct platform_device *pdev) ++{ ++ int ret, i, ctrl_id; ++ struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; ++ struct mtk_thermal *mt; ++ u64 auxadc_phys_base, apmixed_phys_base; ++ struct thermal_zone_device *tzdev; ++ void __iomem *apmixed_base, *auxadc_base; ++ ++ mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); ++ if (!mt) ++ return -ENOMEM; ++ ++ mt->conf = of_device_get_match_data(&pdev->dev); ++ ++ mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); ++ if (IS_ERR(mt->clk_peri_therm)) ++ return PTR_ERR(mt->clk_peri_therm); ++ ++ mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); ++ if (IS_ERR(mt->clk_auxadc)) ++ return PTR_ERR(mt->clk_auxadc); ++ ++ mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); ++ if (IS_ERR(mt->thermal_base)) ++ return PTR_ERR(mt->thermal_base); ++ ++ ret = mtk_thermal_get_calibration_data(&pdev->dev, mt); ++ if (ret) ++ return ret; ++ ++ mutex_init(&mt->lock); ++ ++ mt->dev = &pdev->dev; ++ ++ auxadc = of_parse_phandle(np, "mediatek,auxadc", 0); ++ if (!auxadc) { ++ dev_err(&pdev->dev, "missing auxadc node\n"); ++ return -ENODEV; ++ } ++ ++ auxadc_base = of_iomap(auxadc, 0); ++ auxadc_phys_base = of_get_phys_base(auxadc); ++ ++ of_node_put(auxadc); ++ ++ if (auxadc_phys_base == OF_BAD_ADDR) { ++ dev_err(&pdev->dev, "Can't get auxadc phys address\n"); ++ return -EINVAL; ++ } ++ ++ apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0); ++ if (!apmixedsys) { ++ dev_err(&pdev->dev, "missing apmixedsys node\n"); ++ return -ENODEV; ++ } ++ ++ apmixed_base = of_iomap(apmixedsys, 0); ++ apmixed_phys_base = of_get_phys_base(apmixedsys); ++ ++ of_node_put(apmixedsys); ++ ++ if (apmixed_phys_base == OF_BAD_ADDR) { ++ dev_err(&pdev->dev, "Can't get auxadc phys address\n"); ++ return -EINVAL; ++ } ++ ++ ret = device_reset_optional(&pdev->dev); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(mt->clk_auxadc); ++ if (ret) { ++ dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(mt->clk_peri_therm); ++ if (ret) { ++ dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); ++ goto err_disable_clk_auxadc; ++ } ++ ++ if (mt->conf->version != MTK_THERMAL_V1) { ++ mtk_thermal_turn_on_buffer(apmixed_base); ++ mtk_thermal_release_periodic_ts(mt, auxadc_base); ++ } ++ ++ if (mt->conf->version == MTK_THERMAL_V1) ++ mt->raw_to_mcelsius = raw_to_mcelsius_v1; ++ else if (mt->conf->version == MTK_THERMAL_V2) ++ mt->raw_to_mcelsius = raw_to_mcelsius_v2; ++ else ++ mt->raw_to_mcelsius = raw_to_mcelsius_v3; ++ ++ for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) ++ for (i = 0; i < mt->conf->num_banks; i++) ++ mtk_thermal_init_bank(mt, i, apmixed_phys_base, ++ auxadc_phys_base, ctrl_id); ++ ++ platform_set_drvdata(pdev, mt); ++ ++ tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, ++ &mtk_thermal_ops); ++ if (IS_ERR(tzdev)) { ++ ret = PTR_ERR(tzdev); ++ goto err_disable_clk_peri_therm; ++ } ++ ++ ret = devm_thermal_add_hwmon_sysfs(tzdev); ++ if (ret) ++ dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); ++ ++ return 0; ++ ++err_disable_clk_peri_therm: ++ clk_disable_unprepare(mt->clk_peri_therm); ++err_disable_clk_auxadc: ++ clk_disable_unprepare(mt->clk_auxadc); ++ ++ return ret; ++} ++ ++static int mtk_thermal_remove(struct platform_device *pdev) ++{ ++ struct mtk_thermal *mt = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(mt->clk_peri_therm); ++ clk_disable_unprepare(mt->clk_auxadc); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_thermal_driver = { ++ .probe = mtk_thermal_probe, ++ .remove = mtk_thermal_remove, ++ .driver = { ++ .name = "mtk-thermal", ++ .of_match_table = mtk_thermal_of_match, ++ }, ++}; ++ ++module_platform_driver(mtk_thermal_driver); ++ ++MODULE_AUTHOR("Michael Kao "); ++MODULE_AUTHOR("Louis Yu "); ++MODULE_AUTHOR("Dawei Chien "); ++MODULE_AUTHOR("Sascha Hauer "); ++MODULE_AUTHOR("Hanyi Wu "); ++MODULE_DESCRIPTION("Mediatek thermal driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch b/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch new file mode 100644 index 0000000000..2ae3734e40 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch @@ -0,0 +1,1298 @@ +From 325fadf27b21f7d79843c3cc282b7f3e6620ad3d Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Thu, 9 Feb 2023 11:56:26 +0100 +Subject: [PATCH 06/42] thermal/drivers/mediatek: Add the Low Voltage Thermal + Sensor driver + +The Low Voltage Thermal Sensor (LVTS) is a multiple sensors, multi +controllers contained in a thermal domain. + +A thermal domains can be the MCU or the AP. + +Each thermal domains contain up to seven controllers, each thermal +controller handle up to four thermal sensors. + +The LVTS has two Finite State Machines (FSM), one to handle the +functionin temperatures range like hot or cold temperature and another +one to handle monitoring trip point. The FSM notifies via interrupts +when a trip point is crossed. + +The interrupt is managed at the thermal controller level, so when an +interrupt occurs, the driver has to find out which sensor triggered +such an interrupt. + +The sampling of the thermal can be filtered or immediate. For the +former, the LVTS measures several points and applies a low pass +filter. + +Signed-off-by: Balsam CHIHI +Reviewed-by: AngeloGioacchino Del Regno + +On MT8195 Tomato Chromebook: + +Tested-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230209105628.50294-5-bchihi@baylibre.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/mediatek/Kconfig | 16 + + drivers/thermal/mediatek/Makefile | 1 + + drivers/thermal/mediatek/lvts_thermal.c | 1224 +++++++++++++++++++++++ + 3 files changed, 1241 insertions(+) + create mode 100644 drivers/thermal/mediatek/lvts_thermal.c + +--- a/drivers/thermal/mediatek/Kconfig ++++ b/drivers/thermal/mediatek/Kconfig +@@ -18,4 +18,20 @@ config MTK_SOC_THERMAL + This driver configures thermal controllers to collect + temperature via AUXADC interface. + ++config MTK_LVTS_THERMAL ++ tristate "LVTS Thermal Driver for MediaTek SoCs" ++ depends on HAS_IOMEM ++ help ++ Enable this option if you want to get SoC temperature ++ information for supported MediaTek platforms. ++ This driver configures LVTS (Low Voltage Thermal Sensor) ++ thermal controllers to collect temperatures via ASIF ++ (Analog Serial Interface). ++ ++config MTK_LVTS_THERMAL_DEBUGFS ++ bool "LVTS thermal debugfs" ++ depends on MTK_LVTS_THERMAL && DEBUG_FS ++ help ++ Enable this option to debug the internals of the device driver. ++ + endif +--- a/drivers/thermal/mediatek/Makefile ++++ b/drivers/thermal/mediatek/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o ++obj-$(CONFIG_MTK_LVTS_THERMAL) += lvts_thermal.o +--- /dev/null ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -0,0 +1,1224 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2023 MediaTek Inc. ++ * Author: Balsam CHIHI ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define LVTS_MONCTL0(__base) (__base + 0x0000) ++#define LVTS_MONCTL1(__base) (__base + 0x0004) ++#define LVTS_MONCTL2(__base) (__base + 0x0008) ++#define LVTS_MONINT(__base) (__base + 0x000C) ++#define LVTS_MONINTSTS(__base) (__base + 0x0010) ++#define LVTS_MONIDET0(__base) (__base + 0x0014) ++#define LVTS_MONIDET1(__base) (__base + 0x0018) ++#define LVTS_MONIDET2(__base) (__base + 0x001C) ++#define LVTS_MONIDET3(__base) (__base + 0x0020) ++#define LVTS_H2NTHRE(__base) (__base + 0x0024) ++#define LVTS_HTHRE(__base) (__base + 0x0028) ++#define LVTS_OFFSETH(__base) (__base + 0x0030) ++#define LVTS_OFFSETL(__base) (__base + 0x0034) ++#define LVTS_MSRCTL0(__base) (__base + 0x0038) ++#define LVTS_MSRCTL1(__base) (__base + 0x003C) ++#define LVTS_TSSEL(__base) (__base + 0x0040) ++#define LVTS_CALSCALE(__base) (__base + 0x0048) ++#define LVTS_ID(__base) (__base + 0x004C) ++#define LVTS_CONFIG(__base) (__base + 0x0050) ++#define LVTS_EDATA00(__base) (__base + 0x0054) ++#define LVTS_EDATA01(__base) (__base + 0x0058) ++#define LVTS_EDATA02(__base) (__base + 0x005C) ++#define LVTS_EDATA03(__base) (__base + 0x0060) ++#define LVTS_MSR0(__base) (__base + 0x0090) ++#define LVTS_MSR1(__base) (__base + 0x0094) ++#define LVTS_MSR2(__base) (__base + 0x0098) ++#define LVTS_MSR3(__base) (__base + 0x009C) ++#define LVTS_IMMD0(__base) (__base + 0x00A0) ++#define LVTS_IMMD1(__base) (__base + 0x00A4) ++#define LVTS_IMMD2(__base) (__base + 0x00A8) ++#define LVTS_IMMD3(__base) (__base + 0x00AC) ++#define LVTS_PROTCTL(__base) (__base + 0x00C0) ++#define LVTS_PROTTA(__base) (__base + 0x00C4) ++#define LVTS_PROTTB(__base) (__base + 0x00C8) ++#define LVTS_PROTTC(__base) (__base + 0x00CC) ++#define LVTS_CLKEN(__base) (__base + 0x00E4) ++ ++#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) ++#define LVTS_GROUP_INTERVAL 1 ++#define LVTS_FILTER_INTERVAL 1 ++#define LVTS_SENSOR_INTERVAL 1 ++#define LVTS_HW_FILTER 0x2 ++#define LVTS_TSSEL_CONF 0x13121110 ++#define LVTS_CALSCALE_CONF 0x300 ++#define LVTS_MONINT_CONF 0x9FBF7BDE ++ ++#define LVTS_INT_SENSOR0 0x0009001F ++#define LVTS_INT_SENSOR1 0X000881F0 ++#define LVTS_INT_SENSOR2 0x00247C00 ++#define LVTS_INT_SENSOR3 0x1FC00000 ++ ++#define LVTS_SENSOR_MAX 4 ++#define LVTS_GOLDEN_TEMP_MAX 62 ++#define LVTS_GOLDEN_TEMP_DEFAULT 50 ++#define LVTS_COEFF_A -250460 ++#define LVTS_COEFF_B 250460 ++ ++#define LVTS_MSR_IMMEDIATE_MODE 0 ++#define LVTS_MSR_FILTERED_MODE 1 ++ ++#define LVTS_HW_SHUTDOWN_MT8195 105000 ++ ++static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; ++static int coeff_b = LVTS_COEFF_B; ++ ++struct lvts_sensor_data { ++ int dt_id; ++}; ++ ++struct lvts_ctrl_data { ++ struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; ++ int cal_offset[LVTS_SENSOR_MAX]; ++ int hw_tshut_temp; ++ int num_lvts_sensor; ++ int offset; ++ int mode; ++}; ++ ++struct lvts_data { ++ const struct lvts_ctrl_data *lvts_ctrl; ++ int num_lvts_ctrl; ++}; ++ ++struct lvts_sensor { ++ struct thermal_zone_device *tz; ++ void __iomem *msr; ++ void __iomem *base; ++ int id; ++ int dt_id; ++}; ++ ++struct lvts_ctrl { ++ struct lvts_sensor sensors[LVTS_SENSOR_MAX]; ++ u32 calibration[LVTS_SENSOR_MAX]; ++ u32 hw_tshut_raw_temp; ++ int num_lvts_sensor; ++ int mode; ++ void __iomem *base; ++}; ++ ++struct lvts_domain { ++ struct lvts_ctrl *lvts_ctrl; ++ struct reset_control *reset; ++ struct clk *clk; ++ int num_lvts_ctrl; ++ void __iomem *base; ++ size_t calib_len; ++ u8 *calib; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *dom_dentry; ++#endif ++}; ++ ++#ifdef CONFIG_MTK_LVTS_THERMAL_DEBUGFS ++ ++#define LVTS_DEBUG_FS_REGS(__reg) \ ++{ \ ++ .name = __stringify(__reg), \ ++ .offset = __reg(0), \ ++} ++ ++static const struct debugfs_reg32 lvts_regs[] = { ++ LVTS_DEBUG_FS_REGS(LVTS_MONCTL0), ++ LVTS_DEBUG_FS_REGS(LVTS_MONCTL1), ++ LVTS_DEBUG_FS_REGS(LVTS_MONCTL2), ++ LVTS_DEBUG_FS_REGS(LVTS_MONINT), ++ LVTS_DEBUG_FS_REGS(LVTS_MONINTSTS), ++ LVTS_DEBUG_FS_REGS(LVTS_MONIDET0), ++ LVTS_DEBUG_FS_REGS(LVTS_MONIDET1), ++ LVTS_DEBUG_FS_REGS(LVTS_MONIDET2), ++ LVTS_DEBUG_FS_REGS(LVTS_MONIDET3), ++ LVTS_DEBUG_FS_REGS(LVTS_H2NTHRE), ++ LVTS_DEBUG_FS_REGS(LVTS_HTHRE), ++ LVTS_DEBUG_FS_REGS(LVTS_OFFSETH), ++ LVTS_DEBUG_FS_REGS(LVTS_OFFSETL), ++ LVTS_DEBUG_FS_REGS(LVTS_MSRCTL0), ++ LVTS_DEBUG_FS_REGS(LVTS_MSRCTL1), ++ LVTS_DEBUG_FS_REGS(LVTS_TSSEL), ++ LVTS_DEBUG_FS_REGS(LVTS_CALSCALE), ++ LVTS_DEBUG_FS_REGS(LVTS_ID), ++ LVTS_DEBUG_FS_REGS(LVTS_CONFIG), ++ LVTS_DEBUG_FS_REGS(LVTS_EDATA00), ++ LVTS_DEBUG_FS_REGS(LVTS_EDATA01), ++ LVTS_DEBUG_FS_REGS(LVTS_EDATA02), ++ LVTS_DEBUG_FS_REGS(LVTS_EDATA03), ++ LVTS_DEBUG_FS_REGS(LVTS_MSR0), ++ LVTS_DEBUG_FS_REGS(LVTS_MSR1), ++ LVTS_DEBUG_FS_REGS(LVTS_MSR2), ++ LVTS_DEBUG_FS_REGS(LVTS_MSR3), ++ LVTS_DEBUG_FS_REGS(LVTS_IMMD0), ++ LVTS_DEBUG_FS_REGS(LVTS_IMMD1), ++ LVTS_DEBUG_FS_REGS(LVTS_IMMD2), ++ LVTS_DEBUG_FS_REGS(LVTS_IMMD3), ++ LVTS_DEBUG_FS_REGS(LVTS_PROTCTL), ++ LVTS_DEBUG_FS_REGS(LVTS_PROTTA), ++ LVTS_DEBUG_FS_REGS(LVTS_PROTTB), ++ LVTS_DEBUG_FS_REGS(LVTS_PROTTC), ++ LVTS_DEBUG_FS_REGS(LVTS_CLKEN), ++}; ++ ++static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) ++{ ++ struct debugfs_regset32 *regset; ++ struct lvts_ctrl *lvts_ctrl; ++ struct dentry *dentry; ++ char name[64]; ++ int i; ++ ++ lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); ++ if (!lvts_td->dom_dentry) ++ return 0; ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { ++ ++ lvts_ctrl = &lvts_td->lvts_ctrl[i]; ++ ++ sprintf(name, "controller%d", i); ++ dentry = debugfs_create_dir(name, lvts_td->dom_dentry); ++ if (!dentry) ++ continue; ++ ++ regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ continue; ++ ++ regset->base = lvts_ctrl->base; ++ regset->regs = lvts_regs; ++ regset->nregs = ARRAY_SIZE(lvts_regs); ++ ++ debugfs_create_regset32("registers", 0400, dentry, regset); ++ } ++ ++ return 0; ++} ++ ++static void lvts_debugfs_exit(struct lvts_domain *lvts_td) ++{ ++ debugfs_remove_recursive(lvts_td->dom_dentry); ++} ++ ++#else ++ ++static inline int lvts_debugfs_init(struct device *dev, ++ struct lvts_domain *lvts_td) ++{ ++ return 0; ++} ++ ++static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } ++ ++#endif ++ ++static int lvts_raw_to_temp(u32 raw_temp) ++{ ++ int temperature; ++ ++ temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; ++ temperature += coeff_b; ++ ++ return temperature; ++} ++ ++static u32 lvts_temp_to_raw(int temperature) ++{ ++ u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; ++ ++ raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); ++ ++ return raw_temp; ++} ++ ++static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) ++{ ++ struct lvts_sensor *lvts_sensor = tz->devdata; ++ void __iomem *msr = lvts_sensor->msr; ++ u32 value; ++ ++ /* ++ * Measurement registers: ++ * ++ * LVTS_MSR[0-3] / LVTS_IMMD[0-3] ++ * ++ * Bits: ++ * ++ * 32-17: Unused ++ * 16 : Valid temperature ++ * 15-0 : Raw temperature ++ */ ++ value = readl(msr); ++ ++ /* ++ * As the thermal zone temperature will read before the ++ * hardware sensor is fully initialized, we have to check the ++ * validity of the temperature returned when reading the ++ * measurement register. The thermal controller will set the ++ * valid bit temperature only when it is totally initialized. ++ * ++ * Otherwise, we may end up with garbage values out of the ++ * functionning temperature and directly jump to a system ++ * shutdown. ++ */ ++ if (!(value & BIT(16))) ++ return -EAGAIN; ++ ++ *temp = lvts_raw_to_temp(value & 0xFFFF); ++ ++ return 0; ++} ++ ++static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) ++{ ++ struct lvts_sensor *lvts_sensor = tz->devdata; ++ void __iomem *base = lvts_sensor->base; ++ u32 raw_low = lvts_temp_to_raw(low); ++ u32 raw_high = lvts_temp_to_raw(high); ++ ++ /* ++ * Hot to normal temperature threshold ++ * ++ * LVTS_H2NTHRE ++ * ++ * Bits: ++ * ++ * 14-0 : Raw temperature for threshold ++ */ ++ if (low != -INT_MAX) { ++ dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low); ++ writel(raw_low, LVTS_H2NTHRE(base)); ++ } ++ ++ /* ++ * Hot temperature threshold ++ * ++ * LVTS_HTHRE ++ * ++ * Bits: ++ * ++ * 14-0 : Raw temperature for threshold ++ */ ++ dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high); ++ writel(raw_high, LVTS_HTHRE(base)); ++ ++ return 0; ++} ++ ++static irqreturn_t lvts_ctrl_irq_handler(struct lvts_ctrl *lvts_ctrl) ++{ ++ irqreturn_t iret = IRQ_NONE; ++ u32 value; ++ u32 masks[] = { ++ LVTS_INT_SENSOR0, ++ LVTS_INT_SENSOR1, ++ LVTS_INT_SENSOR2, ++ LVTS_INT_SENSOR3 ++ }; ++ int i; ++ ++ /* ++ * Interrupt monitoring status ++ * ++ * LVTS_MONINTST ++ * ++ * Bits: ++ * ++ * 31 : Interrupt for stage 3 ++ * 30 : Interrupt for stage 2 ++ * 29 : Interrupt for state 1 ++ * 28 : Interrupt using filter on sensor 3 ++ * ++ * 27 : Interrupt using immediate on sensor 3 ++ * 26 : Interrupt normal to hot on sensor 3 ++ * 25 : Interrupt high offset on sensor 3 ++ * 24 : Interrupt low offset on sensor 3 ++ * ++ * 23 : Interrupt hot threshold on sensor 3 ++ * 22 : Interrupt cold threshold on sensor 3 ++ * 21 : Interrupt using filter on sensor 2 ++ * 20 : Interrupt using filter on sensor 1 ++ * ++ * 19 : Interrupt using filter on sensor 0 ++ * 18 : Interrupt using immediate on sensor 2 ++ * 17 : Interrupt using immediate on sensor 1 ++ * 16 : Interrupt using immediate on sensor 0 ++ * ++ * 15 : Interrupt device access timeout interrupt ++ * 14 : Interrupt normal to hot on sensor 2 ++ * 13 : Interrupt high offset interrupt on sensor 2 ++ * 12 : Interrupt low offset interrupt on sensor 2 ++ * ++ * 11 : Interrupt hot threshold on sensor 2 ++ * 10 : Interrupt cold threshold on sensor 2 ++ * 9 : Interrupt normal to hot on sensor 1 ++ * 8 : Interrupt high offset interrupt on sensor 1 ++ * ++ * 7 : Interrupt low offset interrupt on sensor 1 ++ * 6 : Interrupt hot threshold on sensor 1 ++ * 5 : Interrupt cold threshold on sensor 1 ++ * 4 : Interrupt normal to hot on sensor 0 ++ * ++ * 3 : Interrupt high offset interrupt on sensor 0 ++ * 2 : Interrupt low offset interrupt on sensor 0 ++ * 1 : Interrupt hot threshold on sensor 0 ++ * 0 : Interrupt cold threshold on sensor 0 ++ * ++ * We are interested in the sensor(s) responsible of the ++ * interrupt event. We update the thermal framework with the ++ * thermal zone associated with the sensor. The framework will ++ * take care of the rest whatever the kind of interrupt, we ++ * are only interested in which sensor raised the interrupt. ++ * ++ * sensor 3 interrupt: 0001 1111 1100 0000 0000 0000 0000 0000 ++ * => 0x1FC00000 ++ * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000 ++ * => 0x00247C00 ++ * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000 ++ * => 0X000881F0 ++ * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111 ++ * => 0x0009001F ++ */ ++ value = readl(LVTS_MONINTSTS(lvts_ctrl->base)); ++ ++ /* ++ * Let's figure out which sensors raised the interrupt ++ * ++ * NOTE: the masks array must be ordered with the index ++ * corresponding to the sensor id eg. index=0, mask for ++ * sensor0. ++ */ ++ for (i = 0; i < ARRAY_SIZE(masks); i++) { ++ ++ if (!(value & masks[i])) ++ continue; ++ ++ thermal_zone_device_update(lvts_ctrl->sensors[i].tz, ++ THERMAL_TRIP_VIOLATED); ++ iret = IRQ_HANDLED; ++ } ++ ++ /* ++ * Write back to clear the interrupt status (W1C) ++ */ ++ writel(value, LVTS_MONINTSTS(lvts_ctrl->base)); ++ ++ return iret; ++} ++ ++/* ++ * Temperature interrupt handler. Even if the driver supports more ++ * interrupt modes, we use the interrupt when the temperature crosses ++ * the hot threshold the way up and the way down (modulo the ++ * hysteresis). ++ * ++ * Each thermal domain has a couple of interrupts, one for hardware ++ * reset and another one for all the thermal events happening on the ++ * different sensors. ++ * ++ * The interrupt is configured for thermal events when crossing the ++ * hot temperature limit. At each interrupt, we check in every ++ * controller if there is an interrupt pending. ++ */ ++static irqreturn_t lvts_irq_handler(int irq, void *data) ++{ ++ struct lvts_domain *lvts_td = data; ++ irqreturn_t aux, iret = IRQ_NONE; ++ int i; ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { ++ ++ aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); ++ if (aux != IRQ_HANDLED) ++ continue; ++ ++ iret = IRQ_HANDLED; ++ } ++ ++ return iret; ++} ++ ++static struct thermal_zone_device_ops lvts_ops = { ++ .get_temp = lvts_get_temp, ++ .set_trips = lvts_set_trips, ++}; ++ ++static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, ++ const struct lvts_ctrl_data *lvts_ctrl_data) ++{ ++ struct lvts_sensor *lvts_sensor = lvts_ctrl->sensors; ++ void __iomem *msr_regs[] = { ++ LVTS_MSR0(lvts_ctrl->base), ++ LVTS_MSR1(lvts_ctrl->base), ++ LVTS_MSR2(lvts_ctrl->base), ++ LVTS_MSR3(lvts_ctrl->base) ++ }; ++ ++ void __iomem *imm_regs[] = { ++ LVTS_IMMD0(lvts_ctrl->base), ++ LVTS_IMMD1(lvts_ctrl->base), ++ LVTS_IMMD2(lvts_ctrl->base), ++ LVTS_IMMD3(lvts_ctrl->base) ++ }; ++ ++ int i; ++ ++ for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { ++ ++ int dt_id = lvts_ctrl_data->lvts_sensor[i].dt_id; ++ ++ /* ++ * At this point, we don't know which id matches which ++ * sensor. Let's set arbitrally the id from the index. ++ */ ++ lvts_sensor[i].id = i; ++ ++ /* ++ * The thermal zone registration will set the trip ++ * point interrupt in the thermal controller ++ * register. But this one will be reset in the ++ * initialization after. So we need to post pone the ++ * thermal zone creation after the controller is ++ * setup. For this reason, we store the device tree ++ * node id from the data in the sensor structure ++ */ ++ lvts_sensor[i].dt_id = dt_id; ++ ++ /* ++ * We assign the base address of the thermal ++ * controller as a back pointer. So it will be ++ * accessible from the different thermal framework ops ++ * as we pass the lvts_sensor pointer as thermal zone ++ * private data. ++ */ ++ lvts_sensor[i].base = lvts_ctrl->base; ++ ++ /* ++ * Each sensor has its own register address to read from. ++ */ ++ lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? ++ imm_regs[i] : msr_regs[i]; ++ }; ++ ++ lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; ++ ++ return 0; ++} ++ ++/* ++ * The efuse blob values follows the sensor enumeration per thermal ++ * controller. The decoding of the stream is as follow: ++ * ++ * <--?-> <----big0 ???---> <-sensor0-> <-0-> ++ * ------------------------------------------ ++ * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | ++ * ------------------------------------------ ++ * ++ * <--sensor1--><-0-> <----big1 ???---> <-sen ++ * ------------------------------------------ ++ * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | ++ * ------------------------------------------ ++ * ++ * sor0-> <-0-> <-sensor1-> <-0-> .......... ++ * ------------------------------------------ ++ * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | ++ * ------------------------------------------ ++ * ++ * And so on ... ++ * ++ * The data description gives the offset of the calibration data in ++ * this bytes stream for each sensor. ++ * ++ * Each thermal controller can handle up to 4 sensors max, we don't ++ * care if there are less as the array of calibration is sized to 4 ++ * anyway. The unused sensor slot will be zeroed. ++ */ ++static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, ++ const struct lvts_ctrl_data *lvts_ctrl_data, ++ u8 *efuse_calibration) ++{ ++ int i; ++ ++ for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) ++ memcpy(&lvts_ctrl->calibration[i], ++ efuse_calibration + lvts_ctrl_data->cal_offset[i], 2); ++ ++ return 0; ++} ++ ++/* ++ * The efuse bytes stream can be split into different chunk of ++ * nvmems. This function reads and concatenate those into a single ++ * buffer so it can be read sequentially when initializing the ++ * calibration data. ++ */ ++static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td, ++ const struct lvts_data *lvts_data) ++{ ++ struct device_node *np = dev_of_node(dev); ++ struct nvmem_cell *cell; ++ struct property *prop; ++ const char *cell_name; ++ ++ of_property_for_each_string(np, "nvmem-cell-names", prop, cell_name) { ++ size_t len; ++ u8 *efuse; ++ ++ cell = of_nvmem_cell_get(np, cell_name); ++ if (IS_ERR(cell)) { ++ dev_err(dev, "Failed to get cell '%s'\n", cell_name); ++ return PTR_ERR(cell); ++ } ++ ++ efuse = nvmem_cell_read(cell, &len); ++ ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(efuse)) { ++ dev_err(dev, "Failed to read cell '%s'\n", cell_name); ++ return PTR_ERR(efuse); ++ } ++ ++ lvts_td->calib = devm_krealloc(dev, lvts_td->calib, ++ lvts_td->calib_len + len, GFP_KERNEL); ++ if (!lvts_td->calib) ++ return -ENOMEM; ++ ++ memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len); ++ ++ lvts_td->calib_len += len; ++ ++ kfree(efuse); ++ } ++ ++ return 0; ++} ++ ++static int lvts_golden_temp_init(struct device *dev, u32 *value) ++{ ++ u32 gt; ++ ++ gt = (*value) >> 24; ++ ++ if (gt && gt < LVTS_GOLDEN_TEMP_MAX) ++ golden_temp = gt; ++ ++ coeff_b = golden_temp * 500 + LVTS_COEFF_B; ++ ++ return 0; ++} ++ ++static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, ++ const struct lvts_data *lvts_data) ++{ ++ size_t size = sizeof(*lvts_td->lvts_ctrl) * lvts_data->num_lvts_ctrl; ++ struct lvts_ctrl *lvts_ctrl; ++ int i, ret; ++ ++ /* ++ * Create the calibration bytes stream from efuse data ++ */ ++ ret = lvts_calibration_read(dev, lvts_td, lvts_data); ++ if (ret) ++ return ret; ++ ++ /* ++ * The golden temp information is contained in the first chunk ++ * of efuse data. ++ */ ++ ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); ++ if (ret) ++ return ret; ++ ++ lvts_ctrl = devm_kzalloc(dev, size, GFP_KERNEL); ++ if (!lvts_ctrl) ++ return -ENOMEM; ++ ++ for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { ++ ++ lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; ++ ++ ret = lvts_sensor_init(dev, &lvts_ctrl[i], ++ &lvts_data->lvts_ctrl[i]); ++ if (ret) ++ return ret; ++ ++ ret = lvts_calibration_init(dev, &lvts_ctrl[i], ++ &lvts_data->lvts_ctrl[i], ++ lvts_td->calib); ++ if (ret) ++ return ret; ++ ++ /* ++ * The mode the ctrl will use to read the temperature ++ * (filtered or immediate) ++ */ ++ lvts_ctrl[i].mode = lvts_data->lvts_ctrl[i].mode; ++ ++ /* ++ * The temperature to raw temperature must be done ++ * after initializing the calibration. ++ */ ++ lvts_ctrl[i].hw_tshut_raw_temp = ++ lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); ++ } ++ ++ /* ++ * We no longer need the efuse bytes stream, let's free it ++ */ ++ devm_kfree(dev, lvts_td->calib); ++ ++ lvts_td->lvts_ctrl = lvts_ctrl; ++ lvts_td->num_lvts_ctrl = lvts_data->num_lvts_ctrl; ++ ++ return 0; ++} ++ ++/* ++ * At this point the configuration register is the only place in the ++ * driver where we write multiple values. Per hardware constraint, ++ * each write in the configuration register must be separated by a ++ * delay of 2 us. ++ */ ++static void lvts_write_config(struct lvts_ctrl *lvts_ctrl, u32 *cmds, int nr_cmds) ++{ ++ int i; ++ ++ /* ++ * Configuration register ++ */ ++ for (i = 0; i < nr_cmds; i++) { ++ writel(cmds[i], LVTS_CONFIG(lvts_ctrl->base)); ++ usleep_range(2, 4); ++ } ++} ++ ++static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) ++{ ++ /* ++ * LVTS_PROTCTL : Thermal Protection Sensor Selection ++ * ++ * Bits: ++ * ++ * 19-18 : Sensor to base the protection on ++ * 17-16 : Strategy: ++ * 00 : Average of 4 sensors ++ * 01 : Max of 4 sensors ++ * 10 : Selected sensor with bits 19-18 ++ * 11 : Reserved ++ */ ++ writel(BIT(16), LVTS_PROTCTL(lvts_ctrl->base)); ++ ++ /* ++ * LVTS_PROTTA : Stage 1 temperature threshold ++ * LVTS_PROTTB : Stage 2 temperature threshold ++ * LVTS_PROTTC : Stage 3 temperature threshold ++ * ++ * Bits: ++ * ++ * 14-0: Raw temperature threshold ++ * ++ * writel(0x0, LVTS_PROTTA(lvts_ctrl->base)); ++ * writel(0x0, LVTS_PROTTB(lvts_ctrl->base)); ++ */ ++ writel(lvts_ctrl->hw_tshut_raw_temp, LVTS_PROTTC(lvts_ctrl->base)); ++ ++ /* ++ * LVTS_MONINT : Interrupt configuration register ++ * ++ * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS ++ * register, except we set the bits to enable the interrupt. ++ */ ++ writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); ++ ++ return 0; ++} ++ ++static int lvts_domain_reset(struct device *dev, struct reset_control *reset) ++{ ++ int ret; ++ ++ ret = reset_control_assert(reset); ++ if (ret) ++ return ret; ++ ++ return reset_control_deassert(reset); ++} ++ ++/* ++ * Enable or disable the clocks of a specified thermal controller ++ */ ++static int lvts_ctrl_set_enable(struct lvts_ctrl *lvts_ctrl, int enable) ++{ ++ /* ++ * LVTS_CLKEN : Internal LVTS clock ++ * ++ * Bits: ++ * ++ * 0 : enable / disable clock ++ */ ++ writel(enable, LVTS_CLKEN(lvts_ctrl->base)); ++ ++ return 0; ++} ++ ++static int lvts_ctrl_connect(struct device *dev, struct lvts_ctrl *lvts_ctrl) ++{ ++ u32 id, cmds[] = { 0xC103FFFF, 0xC502FF55 }; ++ ++ lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); ++ ++ /* ++ * LVTS_ID : Get ID and status of the thermal controller ++ * ++ * Bits: ++ * ++ * 0-5 : thermal controller id ++ * 7 : thermal controller connection is valid ++ */ ++ id = readl(LVTS_ID(lvts_ctrl->base)); ++ if (!(id & BIT(7))) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int lvts_ctrl_initialize(struct device *dev, struct lvts_ctrl *lvts_ctrl) ++{ ++ /* ++ * Write device mask: 0xC1030000 ++ */ ++ u32 cmds[] = { ++ 0xC1030E01, 0xC1030CFC, 0xC1030A8C, 0xC103098D, 0xC10308F1, ++ 0xC10307A6, 0xC10306B8, 0xC1030500, 0xC1030420, 0xC1030300, ++ 0xC1030030, 0xC10300F6, 0xC1030050, 0xC1030060, 0xC10300AC, ++ 0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1 ++ }; ++ ++ lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); ++ ++ return 0; ++} ++ ++static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl) ++{ ++ int i; ++ void __iomem *lvts_edata[] = { ++ LVTS_EDATA00(lvts_ctrl->base), ++ LVTS_EDATA01(lvts_ctrl->base), ++ LVTS_EDATA02(lvts_ctrl->base), ++ LVTS_EDATA03(lvts_ctrl->base) ++ }; ++ ++ /* ++ * LVTS_EDATA0X : Efuse calibration reference value for sensor X ++ * ++ * Bits: ++ * ++ * 20-0 : Efuse value for normalization data ++ */ ++ for (i = 0; i < LVTS_SENSOR_MAX; i++) ++ writel(lvts_ctrl->calibration[i], lvts_edata[i]); ++ ++ return 0; ++} ++ ++static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl) ++{ ++ u32 value; ++ ++ /* ++ * LVTS_TSSEL : Sensing point index numbering ++ * ++ * Bits: ++ * ++ * 31-24: ADC Sense 3 ++ * 23-16: ADC Sense 2 ++ * 15-8 : ADC Sense 1 ++ * 7-0 : ADC Sense 0 ++ */ ++ value = LVTS_TSSEL_CONF; ++ writel(value, LVTS_TSSEL(lvts_ctrl->base)); ++ ++ /* ++ * LVTS_CALSCALE : ADC voltage round ++ */ ++ value = 0x300; ++ value = LVTS_CALSCALE_CONF; ++ ++ /* ++ * LVTS_MSRCTL0 : Sensor filtering strategy ++ * ++ * Filters: ++ * ++ * 000 : One sample ++ * 001 : Avg 2 samples ++ * 010 : 4 samples, drop min and max, avg 2 samples ++ * 011 : 6 samples, drop min and max, avg 4 samples ++ * 100 : 10 samples, drop min and max, avg 8 samples ++ * 101 : 18 samples, drop min and max, avg 16 samples ++ * ++ * Bits: ++ * ++ * 0-2 : Sensor0 filter ++ * 3-5 : Sensor1 filter ++ * 6-8 : Sensor2 filter ++ * 9-11 : Sensor3 filter ++ */ ++ value = LVTS_HW_FILTER << 9 | LVTS_HW_FILTER << 6 | ++ LVTS_HW_FILTER << 3 | LVTS_HW_FILTER; ++ writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); ++ ++ /* ++ * LVTS_MSRCTL1 : Measurement control ++ * ++ * Bits: ++ * ++ * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 ++ * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 ++ * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 ++ * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 ++ * ++ * That configuration will ignore the filtering and the delays ++ * introduced below in MONCTL1 and MONCTL2 ++ */ ++ if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { ++ value = BIT(9) | BIT(6) | BIT(5) | BIT(4); ++ writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); ++ } ++ ++ /* ++ * LVTS_MONCTL1 : Period unit and group interval configuration ++ * ++ * The clock source of LVTS thermal controller is 26MHz. ++ * ++ * The period unit is a time base for all the interval delays ++ * specified in the registers. By default we use 12. The time ++ * conversion is done by multiplying by 256 and 1/26.10^6 ++ * ++ * An interval delay multiplied by the period unit gives the ++ * duration in seconds. ++ * ++ * - Filter interval delay is a delay between two samples of ++ * the same sensor. ++ * ++ * - Sensor interval delay is a delay between two samples of ++ * different sensors. ++ * ++ * - Group interval delay is a delay between different rounds. ++ * ++ * For example: ++ * If Period unit = C, filter delay = 1, sensor delay = 2, group delay = 1, ++ * and two sensors, TS1 and TS2, are in a LVTS thermal controller ++ * and then ++ * Period unit time = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us ++ * Filter interval delay = 1 * Period unit = 118.149us ++ * Sensor interval delay = 2 * Period unit = 236.298us ++ * Group interval delay = 1 * Period unit = 118.149us ++ * ++ * TS1 TS1 ... TS1 TS2 TS2 ... TS2 TS1... ++ * <--> Filter interval delay ++ * <--> Sensor interval delay ++ * <--> Group interval delay ++ * Bits: ++ * 29 - 20 : Group interval ++ * 16 - 13 : Send a single interrupt when crossing the hot threshold (1) ++ * or an interrupt everytime the hot threshold is crossed (0) ++ * 9 - 0 : Period unit ++ * ++ */ ++ value = LVTS_GROUP_INTERVAL << 20 | LVTS_PERIOD_UNIT; ++ writel(value, LVTS_MONCTL1(lvts_ctrl->base)); ++ ++ /* ++ * LVTS_MONCTL2 : Filtering and sensor interval ++ * ++ * Bits: ++ * ++ * 25-16 : Interval unit in PERIOD_UNIT between sample on ++ * the same sensor, filter interval ++ * 9-0 : Interval unit in PERIOD_UNIT between each sensor ++ * ++ */ ++ value = LVTS_FILTER_INTERVAL << 16 | LVTS_SENSOR_INTERVAL; ++ writel(value, LVTS_MONCTL2(lvts_ctrl->base)); ++ ++ return lvts_irq_init(lvts_ctrl); ++} ++ ++static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) ++{ ++ struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors; ++ struct thermal_zone_device *tz; ++ u32 sensor_map = 0; ++ int i; ++ ++ for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { ++ ++ int dt_id = lvts_sensors[i].dt_id; ++ ++ tz = devm_thermal_of_zone_register(dev, dt_id, &lvts_sensors[i], ++ &lvts_ops); ++ if (IS_ERR(tz)) { ++ /* ++ * This thermal zone is not described in the ++ * device tree. It is not an error from the ++ * thermal OF code POV, we just continue. ++ */ ++ if (PTR_ERR(tz) == -ENODEV) ++ continue; ++ ++ return PTR_ERR(tz); ++ } ++ ++ /* ++ * The thermal zone pointer will be needed in the ++ * interrupt handler, we store it in the sensor ++ * structure. The thermal domain structure will be ++ * passed to the interrupt handler private data as the ++ * interrupt is shared for all the controller ++ * belonging to the thermal domain. ++ */ ++ lvts_sensors[i].tz = tz; ++ ++ /* ++ * This sensor was correctly associated with a thermal ++ * zone, let's set the corresponding bit in the sensor ++ * map, so we can enable the temperature monitoring in ++ * the hardware thermal controller. ++ */ ++ sensor_map |= BIT(i); ++ } ++ ++ /* ++ * Bits: ++ * 9: Single point access flow ++ * 0-3: Enable sensing point 0-3 ++ * ++ * The initialization of the thermal zones give us ++ * which sensor point to enable. If any thermal zone ++ * was not described in the device tree, it won't be ++ * enabled here in the sensor map. ++ */ ++ writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); ++ ++ return 0; ++} ++ ++static int lvts_domain_init(struct device *dev, struct lvts_domain *lvts_td, ++ const struct lvts_data *lvts_data) ++{ ++ struct lvts_ctrl *lvts_ctrl; ++ int i, ret; ++ ++ ret = lvts_ctrl_init(dev, lvts_td, lvts_data); ++ if (ret) ++ return ret; ++ ++ ret = lvts_domain_reset(dev, lvts_td->reset); ++ if (ret) { ++ dev_dbg(dev, "Failed to reset domain"); ++ return ret; ++ } ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { ++ ++ lvts_ctrl = &lvts_td->lvts_ctrl[i]; ++ ++ /* ++ * Initialization steps: ++ * ++ * - Enable the clock ++ * - Connect to the LVTS ++ * - Initialize the LVTS ++ * - Prepare the calibration data ++ * - Select monitored sensors ++ * [ Configure sampling ] ++ * [ Configure the interrupt ] ++ * - Start measurement ++ */ ++ ret = lvts_ctrl_set_enable(lvts_ctrl, true); ++ if (ret) { ++ dev_dbg(dev, "Failed to enable LVTS clock"); ++ return ret; ++ } ++ ++ ret = lvts_ctrl_connect(dev, lvts_ctrl); ++ if (ret) { ++ dev_dbg(dev, "Failed to connect to LVTS controller"); ++ return ret; ++ } ++ ++ ret = lvts_ctrl_initialize(dev, lvts_ctrl); ++ if (ret) { ++ dev_dbg(dev, "Failed to initialize controller"); ++ return ret; ++ } ++ ++ ret = lvts_ctrl_calibrate(dev, lvts_ctrl); ++ if (ret) { ++ dev_dbg(dev, "Failed to calibrate controller"); ++ return ret; ++ } ++ ++ ret = lvts_ctrl_configure(dev, lvts_ctrl); ++ if (ret) { ++ dev_dbg(dev, "Failed to configure controller"); ++ return ret; ++ } ++ ++ ret = lvts_ctrl_start(dev, lvts_ctrl); ++ if (ret) { ++ dev_dbg(dev, "Failed to start controller"); ++ return ret; ++ } ++ } ++ ++ return lvts_debugfs_init(dev, lvts_td); ++} ++ ++static int lvts_probe(struct platform_device *pdev) ++{ ++ const struct lvts_data *lvts_data; ++ struct lvts_domain *lvts_td; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ int irq, ret; ++ ++ lvts_td = devm_kzalloc(dev, sizeof(*lvts_td), GFP_KERNEL); ++ if (!lvts_td) ++ return -ENOMEM; ++ ++ lvts_data = of_device_get_match_data(dev); ++ ++ lvts_td->clk = devm_clk_get_enabled(dev, NULL); ++ if (IS_ERR(lvts_td->clk)) ++ return dev_err_probe(dev, PTR_ERR(lvts_td->clk), "Failed to retrieve clock\n"); ++ ++ res = platform_get_mem_or_io(pdev, 0); ++ if (!res) ++ return dev_err_probe(dev, (-ENXIO), "No IO resource\n"); ++ ++ lvts_td->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(lvts_td->base)) ++ return dev_err_probe(dev, PTR_ERR(lvts_td->base), "Failed to map io resource\n"); ++ ++ lvts_td->reset = devm_reset_control_get_by_index(dev, 0); ++ if (IS_ERR(lvts_td->reset)) ++ return dev_err_probe(dev, PTR_ERR(lvts_td->reset), "Failed to get reset control\n"); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return dev_err_probe(dev, irq, "No irq resource\n"); ++ ++ ret = lvts_domain_init(dev, lvts_td, lvts_data); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); ++ ++ /* ++ * At this point the LVTS is initialized and enabled. We can ++ * safely enable the interrupt. ++ */ ++ ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler, ++ IRQF_ONESHOT, dev_name(dev), lvts_td); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to request interrupt\n"); ++ ++ platform_set_drvdata(pdev, lvts_td); ++ ++ return 0; ++} ++ ++static int lvts_remove(struct platform_device *pdev) ++{ ++ struct lvts_domain *lvts_td; ++ int i; ++ ++ lvts_td = platform_get_drvdata(pdev); ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) ++ lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); ++ ++ lvts_debugfs_exit(lvts_td); ++ ++ return 0; ++} ++ ++static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = { ++ { ++ .cal_offset = { 0x04, 0x07 }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_MCU_BIG_CPU0 }, ++ { .dt_id = MT8195_MCU_BIG_CPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x0, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ }, ++ { ++ .cal_offset = { 0x0d, 0x10 }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_MCU_BIG_CPU2 }, ++ { .dt_id = MT8195_MCU_BIG_CPU3 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x100, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ }, ++ { ++ .cal_offset = { 0x16, 0x19, 0x1c, 0x1f }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_MCU_LITTLE_CPU0 }, ++ { .dt_id = MT8195_MCU_LITTLE_CPU1 }, ++ { .dt_id = MT8195_MCU_LITTLE_CPU2 }, ++ { .dt_id = MT8195_MCU_LITTLE_CPU3 } ++ }, ++ .num_lvts_sensor = 4, ++ .offset = 0x200, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ } ++}; ++ ++static const struct lvts_data mt8195_lvts_mcu_data = { ++ .lvts_ctrl = mt8195_lvts_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_data_ctrl), ++}; ++ ++static const struct of_device_id lvts_of_match[] = { ++ { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, lvts_of_match); ++ ++static struct platform_driver lvts_driver = { ++ .probe = lvts_probe, ++ .remove = lvts_remove, ++ .driver = { ++ .name = "mtk-lvts-thermal", ++ .of_match_table = lvts_of_match, ++ }, ++}; ++module_platform_driver(lvts_driver); ++ ++MODULE_AUTHOR("Balsam CHIHI "); ++MODULE_DESCRIPTION("MediaTek LVTS Thermal Driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch b/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch new file mode 100644 index 0000000000..b6a5f64090 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch @@ -0,0 +1,186 @@ +From 498e2f7a6e69dcbca24715de2b4b97569fdfeff4 Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Thu, 9 Feb 2023 11:56:24 +0100 +Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal controllers + +Add LVTS thermal controllers dt-binding definition for mt8192 and mt8195. + +Signed-off-by: Balsam CHIHI +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20230209105628.50294-3-bchihi@baylibre.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +--- + .../thermal/mediatek,lvts-thermal.yaml | 142 ++++++++++++++++++ + .../thermal/mediatek,lvts-thermal.h | 19 +++ + 2 files changed, 161 insertions(+) + create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml + create mode 100644 include/dt-bindings/thermal/mediatek,lvts-thermal.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml +@@ -0,0 +1,142 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/thermal/mediatek,lvts-thermal.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek SoC Low Voltage Thermal Sensor (LVTS) ++ ++maintainers: ++ - Balsam CHIHI ++ ++description: | ++ LVTS is a thermal management architecture composed of three subsystems, ++ a Sensing device - Thermal Sensing Micro Circuit Unit (TSMCU), ++ a Converter - Low Voltage Thermal Sensor converter (LVTS), and ++ a Digital controller (LVTS_CTRL). ++ ++properties: ++ compatible: ++ enum: ++ - mediatek,mt8192-lvts-ap ++ - mediatek,mt8192-lvts-mcu ++ - mediatek,mt8195-lvts-ap ++ - mediatek,mt8195-lvts-mcu ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ description: LVTS reset for clearing temporary data on AP/MCU. ++ ++ nvmem-cells: ++ minItems: 1 ++ items: ++ - description: Calibration eFuse data 1 for LVTS ++ - description: Calibration eFuse data 2 for LVTS ++ ++ nvmem-cell-names: ++ minItems: 1 ++ items: ++ - const: lvts-calib-data-1 ++ - const: lvts-calib-data-2 ++ ++ "#thermal-sensor-cells": ++ const: 1 ++ ++allOf: ++ - $ref: thermal-sensor.yaml# ++ ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - mediatek,mt8192-lvts-ap ++ - mediatek,mt8192-lvts-mcu ++ then: ++ properties: ++ nvmem-cells: ++ maxItems: 1 ++ ++ nvmem-cell-names: ++ maxItems: 1 ++ ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - mediatek,mt8195-lvts-ap ++ - mediatek,mt8195-lvts-mcu ++ then: ++ properties: ++ nvmem-cells: ++ minItems: 2 ++ ++ nvmem-cell-names: ++ minItems: 2 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - resets ++ - nvmem-cells ++ - nvmem-cell-names ++ - "#thermal-sensor-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ lvts_mcu: thermal-sensor@11278000 { ++ compatible = "mediatek,mt8195-lvts-mcu"; ++ reg = <0 0x11278000 0 0x1000>; ++ interrupts = ; ++ clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; ++ resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>; ++ nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>; ++ nvmem-cell-names = "lvts-calib-data-1", "lvts-calib-data-2"; ++ #thermal-sensor-cells = <1>; ++ }; ++ }; ++ ++ thermal_zones: thermal-zones { ++ cpu0-thermal { ++ polling-delay = <1000>; ++ polling-delay-passive = <250>; ++ thermal-sensors = <&lvts_mcu MT8195_MCU_LITTLE_CPU0>; ++ ++ trips { ++ cpu0_alert: trip-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu0_crit: trip-crit { ++ temperature = <100000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; +--- /dev/null ++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (c) 2023 MediaTek Inc. ++ * Author: Balsam CHIHI ++ */ ++ ++#ifndef __MEDIATEK_LVTS_DT_H ++#define __MEDIATEK_LVTS_DT_H ++ ++#define MT8195_MCU_BIG_CPU0 0 ++#define MT8195_MCU_BIG_CPU1 1 ++#define MT8195_MCU_BIG_CPU2 2 ++#define MT8195_MCU_BIG_CPU3 3 ++#define MT8195_MCU_LITTLE_CPU0 4 ++#define MT8195_MCU_LITTLE_CPU1 5 ++#define MT8195_MCU_LITTLE_CPU2 6 ++#define MT8195_MCU_LITTLE_CPU3 7 ++ ++#endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch new file mode 100644 index 0000000000..efb0d8b64f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch @@ -0,0 +1,35 @@ +From 05aaa7fdb0736262e224369b9b9f1410320fc71b Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 7 Mar 2023 16:45:21 +0100 +Subject: [PATCH] dt-bindings: thermal: mediatek: Add AP domain to LVTS thermal + controllers for mt8195 + +Add AP Domain to LVTS thermal controllers dt-binding definition for mt8195. + +Signed-off-by: Balsam CHIHI +Acked-by: Rob Herring +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: Chen-Yu Tsai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230307154524.118541-2-bchihi@baylibre.com +--- + include/dt-bindings/thermal/mediatek,lvts-thermal.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h ++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h +@@ -16,4 +16,14 @@ + #define MT8195_MCU_LITTLE_CPU2 6 + #define MT8195_MCU_LITTLE_CPU3 7 + ++#define MT8195_AP_VPU0 8 ++#define MT8195_AP_VPU1 9 ++#define MT8195_AP_GPU0 10 ++#define MT8195_AP_GPU1 11 ++#define MT8195_AP_VDEC 12 ++#define MT8195_AP_IMG 13 ++#define MT8195_AP_INFRA 14 ++#define MT8195_AP_CAM0 15 ++#define MT8195_AP_CAM1 16 ++ + #endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch b/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch new file mode 100644 index 0000000000..c68969321e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch @@ -0,0 +1,65 @@ +From a6ff3c0021468721b96e84892a8cae24bde8d65f Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:29 +0100 +Subject: [PATCH] thermal/core: Add a thermal zone 'devdata' accessor + +The thermal zone device structure is exposed to the different drivers +and obviously they access the internals while that should be +restricted to the core thermal code. + +In order to self-encapsulate the thermal core code, we need to prevent +the drivers accessing directly the thermal zone structure and provide +accessor functions to deal with. + +Provide an accessor to the 'devdata' structure and make use of it in +the different drivers. + +No functional changes intended. + +Signed-off-by: Daniel Lezcano +Acked-by: Rafael J. Wysocki +Acked-by: Mark Brown +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/thermal_core.c | 6 ++++++ + include/linux/thermal.h | 7 +++++++ + 2 files changed, 13 insertions(+) + +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1346,6 +1346,12 @@ struct thermal_zone_device *thermal_zone + } + EXPORT_SYMBOL_GPL(thermal_zone_device_register); + ++void *thermal_zone_device_priv(struct thermal_zone_device *tzd) ++{ ++ return tzd->devdata; ++} ++EXPORT_SYMBOL_GPL(thermal_zone_device_priv); ++ + /** + * thermal_zone_device_unregister - removes the registered thermal zone device + * @tz: the thermal zone device to remove +--- a/include/linux/thermal.h ++++ b/include/linux/thermal.h +@@ -346,6 +346,8 @@ thermal_zone_device_register_with_trips( + void *, struct thermal_zone_device_ops *, + struct thermal_zone_params *, int, int); + ++void *thermal_zone_device_priv(struct thermal_zone_device *tzd); ++ + int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, + struct thermal_cooling_device *, + unsigned long, unsigned long, +@@ -417,6 +419,11 @@ static inline int thermal_zone_get_offse + struct thermal_zone_device *tz) + { return -ENODEV; } + ++static inline void *thermal_zone_device_priv(struct thermal_zone_device *tz) ++{ ++ return NULL; ++} ++ + static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) + { return -ENODEV; } + diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch new file mode 100644 index 0000000000..66d3c9e302 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch @@ -0,0 +1,55 @@ +From 072e35c98806100182c0a7263cf4cba09ce43463 Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:38 +0100 +Subject: [PATCH] thermal/core: Add thermal_zone_device structure 'type' + accessor + +The thermal zone device structure is exposed via the exported +thermal.h header. This structure should stay private the thermal core +code. In order to encapsulate the structure, let's add an accessor to +get the 'type' of the thermal zone. + +Signed-off-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/thermal_core.c | 6 ++++++ + include/linux/thermal.h | 6 ++++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1352,6 +1352,12 @@ void *thermal_zone_device_priv(struct th + } + EXPORT_SYMBOL_GPL(thermal_zone_device_priv); + ++const char *thermal_zone_device_type(struct thermal_zone_device *tzd) ++{ ++ return tzd->type; ++} ++EXPORT_SYMBOL_GPL(thermal_zone_device_type); ++ + /** + * thermal_zone_device_unregister - removes the registered thermal zone device + * @tz: the thermal zone device to remove +--- a/include/linux/thermal.h ++++ b/include/linux/thermal.h +@@ -347,6 +347,7 @@ thermal_zone_device_register_with_trips( + struct thermal_zone_params *, int, int); + + void *thermal_zone_device_priv(struct thermal_zone_device *tzd); ++const char *thermal_zone_device_type(struct thermal_zone_device *tzd); + + int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, + struct thermal_cooling_device *, +@@ -423,6 +424,11 @@ static inline void *thermal_zone_device_ + { + return NULL; + } ++ ++static inline const char *thermal_zone_device_type(struct thermal_zone_device *tzd) ++{ ++ return NULL; ++} + + static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) + { return -ENODEV; } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch b/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch new file mode 100644 index 0000000000..57bc910d3e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch @@ -0,0 +1,74 @@ +From 7d78bab533eb9aa0e5240e25a204e8f416723ed6 Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:30 +0100 +Subject: [PATCH 07/42] thermal/core: Use the thermal zone 'devdata' accessor + in thermal located drivers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The thermal zone device structure is exposed to the different drivers +and obviously they access the internals while that should be +restricted to the core thermal code. + +In order to self-encapsulate the thermal core code, we need to prevent +the drivers accessing directly the thermal zone structure and provide +accessor functions to deal with. + +Use the devdata accessor introduced in the previous patch. + +No functional changes intended. + +[skipped drivers not relevant for mediatek target] + +Signed-off-by: Daniel Lezcano +Reviewed-by: Niklas Söderlund #R-Car +Acked-by: Mark Brown +Reviewed-by: AngeloGioacchino Del Regno #MediaTek auxadc and lvts +Reviewed-by: Balsam CHIHI #Mediatek lvts +Reviewed-by: Adam Ward #da9062 +Reviewed-by: Baolin Wang #spread +Acked-by: Jernej Skrabec #sun8i_thermal +Acked-by: Rafael J. Wysocki +Acked-by: Florian Fainelli #Broadcom +Reviewed-by: Dhruva Gole # K3 bandgap +Acked-by: Linus Walleij +Acked-by: Heiko Stuebner #rockchip +Reviewed-by: Kunihiko Hayashi #uniphier +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/mediatek/auxadc_thermal.c | 2 +- + drivers/thermal/mediatek/lvts_thermal.c | 4 ++-- + 43 files changed, 71 insertions(+), 73 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -763,7 +763,7 @@ static int mtk_thermal_bank_temperature( + + static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) + { +- struct mtk_thermal *mt = tz->devdata; ++ struct mtk_thermal *mt = thermal_zone_device_priv(tz); + int i; + int tempmax = INT_MIN; + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -252,7 +252,7 @@ static u32 lvts_temp_to_raw(int temperat + + static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) + { +- struct lvts_sensor *lvts_sensor = tz->devdata; ++ struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + void __iomem *msr = lvts_sensor->msr; + u32 value; + +@@ -290,7 +290,7 @@ static int lvts_get_temp(struct thermal_ + + static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) + { +- struct lvts_sensor *lvts_sensor = tz->devdata; ++ struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + void __iomem *base = lvts_sensor->base; + u32 raw_low = lvts_temp_to_raw(low); + u32 raw_high = lvts_temp_to_raw(high); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch b/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch new file mode 100644 index 0000000000..647b3b0eca --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch @@ -0,0 +1,201 @@ +From cc9c60e9cfeeac45d63361fa8c085c43c4bdfe3a Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:36 +0100 +Subject: [PATCH 08/42] thermal/hwmon: Use the right device for + devm_thermal_add_hwmon_sysfs() + +The devres variant of thermal_add_hwmon_sysfs() only takes the thermal +zone structure pointer as parameter. + +Actually, it uses the tz->device to add it in the devres list. + +It is preferable to use the device registering the thermal zone +instead of the thermal zone device itself. That prevents the driver +accessing the thermal zone structure internals and it is from my POV +more correct regarding how devm_ is used. + +[skipped imx thermal which did not apply cleanly and irrelevant on +mediatek target] + +Signed-off-by: Daniel Lezcano +Acked-by: Martin Blumenstingl #amlogic_thermal +Acked-by: Jernej Skrabec #sun8i_thermal +Reviewed-by: AngeloGioacchino Del Regno #MediaTek auxadc +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/amlogic_thermal.c | 2 +- + drivers/thermal/imx_sc_thermal.c | 2 +- + drivers/thermal/k3_bandgap.c | 2 +- + drivers/thermal/mediatek/auxadc_thermal.c | 2 +- + drivers/thermal/qcom/qcom-spmi-adc-tm5.c | 2 +- + drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 2 +- + drivers/thermal/qcom/tsens.c | 2 +- + drivers/thermal/qoriq_thermal.c | 2 +- + drivers/thermal/sun8i_thermal.c | 2 +- + drivers/thermal/tegra/tegra30-tsensor.c | 2 +- + drivers/thermal/thermal_hwmon.c | 4 ++-- + drivers/thermal/thermal_hwmon.h | 4 ++-- + drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- + 13 files changed, 15 insertions(+), 15 deletions(-) + +--- a/drivers/thermal/amlogic_thermal.c ++++ b/drivers/thermal/amlogic_thermal.c +@@ -286,7 +286,7 @@ static int amlogic_thermal_probe(struct + return ret; + } + +- if (devm_thermal_add_hwmon_sysfs(pdata->tzd)) ++ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd)) + dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n"); + + ret = amlogic_thermal_initialize(pdata); +--- a/drivers/thermal/imx_sc_thermal.c ++++ b/drivers/thermal/imx_sc_thermal.c +@@ -120,7 +120,7 @@ static int imx_sc_thermal_probe(struct p + return ret; + } + +- if (devm_thermal_add_hwmon_sysfs(sensor->tzd)) ++ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd)) + dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n"); + } + +--- a/drivers/thermal/k3_bandgap.c ++++ b/drivers/thermal/k3_bandgap.c +@@ -222,7 +222,7 @@ static int k3_bandgap_probe(struct platf + goto err_alloc; + } + +- if (devm_thermal_add_hwmon_sysfs(data[id].tzd)) ++ if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd)) + dev_warn(dev, "Failed to add hwmon sysfs attributes\n"); + } + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1210,7 +1210,7 @@ static int mtk_thermal_probe(struct plat + goto err_disable_clk_peri_therm; + } + +- ret = devm_thermal_add_hwmon_sysfs(tzdev); ++ ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev); + if (ret) + dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); + +--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c ++++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +@@ -688,7 +688,7 @@ static int adc_tm5_register_tzd(struct a + return PTR_ERR(tzd); + } + adc_tm->channels[i].tzd = tzd; +- if (devm_thermal_add_hwmon_sysfs(tzd)) ++ if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd)) + dev_warn(adc_tm->dev, + "Failed to add hwmon sysfs attributes\n"); + } +--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c ++++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +@@ -460,7 +460,7 @@ static int qpnp_tm_probe(struct platform + return ret; + } + +- if (devm_thermal_add_hwmon_sysfs(chip->tz_dev)) ++ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev)) + dev_warn(&pdev->dev, + "Failed to add hwmon sysfs attributes\n"); + +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -1056,7 +1056,7 @@ static int tsens_register(struct tsens_p + if (priv->ops->enable) + priv->ops->enable(priv, i); + +- if (devm_thermal_add_hwmon_sysfs(tzd)) ++ if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd)) + dev_warn(priv->dev, + "Failed to add hwmon sysfs attributes\n"); + } +--- a/drivers/thermal/qoriq_thermal.c ++++ b/drivers/thermal/qoriq_thermal.c +@@ -158,7 +158,7 @@ static int qoriq_tmu_register_tmu_zone(s + return ret; + } + +- if (devm_thermal_add_hwmon_sysfs(tzd)) ++ if (devm_thermal_add_hwmon_sysfs(dev, tzd)) + dev_warn(dev, + "Failed to add hwmon sysfs attributes\n"); + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -468,7 +468,7 @@ static int sun8i_ths_register(struct ths + if (IS_ERR(tmdev->sensor[i].tzd)) + return PTR_ERR(tmdev->sensor[i].tzd); + +- if (devm_thermal_add_hwmon_sysfs(tmdev->sensor[i].tzd)) ++ if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd)) + dev_warn(tmdev->dev, + "Failed to add hwmon sysfs attributes\n"); + } +--- a/drivers/thermal/tegra/tegra30-tsensor.c ++++ b/drivers/thermal/tegra/tegra30-tsensor.c +@@ -530,7 +530,7 @@ static int tegra_tsensor_register_channe + return 0; + } + +- if (devm_thermal_add_hwmon_sysfs(tsc->tzd)) ++ if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd)) + dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n"); + + return 0; +--- a/drivers/thermal/thermal_hwmon.c ++++ b/drivers/thermal/thermal_hwmon.c +@@ -255,7 +255,7 @@ static void devm_thermal_hwmon_release(s + thermal_remove_hwmon_sysfs(*(struct thermal_zone_device **)res); + } + +-int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) ++int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz) + { + struct thermal_zone_device **ptr; + int ret; +@@ -272,7 +272,7 @@ int devm_thermal_add_hwmon_sysfs(struct + } + + *ptr = tz; +- devres_add(&tz->device, ptr); ++ devres_add(dev, ptr); + + return ret; + } +--- a/drivers/thermal/thermal_hwmon.h ++++ b/drivers/thermal/thermal_hwmon.h +@@ -17,7 +17,7 @@ + + #ifdef CONFIG_THERMAL_HWMON + int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz); +-int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz); ++int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz); + void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz); + #else + static inline int +@@ -27,7 +27,7 @@ thermal_add_hwmon_sysfs(struct thermal_z + } + + static inline int +-devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) ++devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz) + { + return 0; + } +--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c ++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +@@ -182,7 +182,7 @@ int ti_thermal_expose_sensor(struct ti_b + ti_bandgap_set_sensor_data(bgp, id, data); + ti_bandgap_write_update_interval(bgp, data->sensor_id, interval); + +- if (devm_thermal_add_hwmon_sysfs(data->ti_thermal)) ++ if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal)) + dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n"); + + return 0; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch b/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch new file mode 100644 index 0000000000..9dedc2cb68 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch @@ -0,0 +1,79 @@ +From 5a72b8e4bac753e4dc74dc0a1335d120f63df97a Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:37 +0100 +Subject: [PATCH 09/42] thermal: Don't use 'device' internal thermal zone + structure field + +Some drivers are directly using the thermal zone's 'device' structure +field. + +Use the driver device pointer instead of the thermal zone device when +it is available. + +Remove the traces when they are duplicate with the traces in the core +code. + +[again skipped imx_thermal.c] + +Cc: Jean Delvare +Cc: Guenter Roeck +Signed-off-by: Daniel Lezcano +Reviewed-by: Balsam CHIHI #Mediatek LVTS +Reviewed-by: AngeloGioacchino Del Regno #MediaTek LVTS +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/mediatek/lvts_thermal.c | 4 ++-- + drivers/thermal/thermal_hwmon.c | 4 ++-- + drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -305,7 +305,7 @@ static int lvts_set_trips(struct thermal + * 14-0 : Raw temperature for threshold + */ + if (low != -INT_MAX) { +- dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low); ++ pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low); + writel(raw_low, LVTS_H2NTHRE(base)); + } + +@@ -318,7 +318,7 @@ static int lvts_set_trips(struct thermal + * + * 14-0 : Raw temperature for threshold + */ +- dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high); ++ pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high); + writel(raw_high, LVTS_HTHRE(base)); + + return 0; +--- a/drivers/thermal/thermal_hwmon.c ++++ b/drivers/thermal/thermal_hwmon.c +@@ -220,14 +220,14 @@ void thermal_remove_hwmon_sysfs(struct t + hwmon = thermal_hwmon_lookup_by_type(tz); + if (unlikely(!hwmon)) { + /* Should never happen... */ +- dev_dbg(&tz->device, "hwmon device lookup failed!\n"); ++ dev_dbg(hwmon->device, "hwmon device lookup failed!\n"); + return; + } + + temp = thermal_hwmon_lookup_temp(hwmon, tz); + if (unlikely(!temp)) { + /* Should never happen... */ +- dev_dbg(&tz->device, "temperature input lookup failed!\n"); ++ dev_dbg(hwmon->device, "temperature input lookup failed!\n"); + return; + } + +--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c ++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +@@ -43,7 +43,7 @@ static void ti_thermal_work(struct work_ + + thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED); + +- dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n", ++ dev_dbg(data->bgp->dev, "updated thermal zone %s\n", + data->ti_thermal->type); + } + diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch b/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch new file mode 100644 index 0000000000..8cec9aba97 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch @@ -0,0 +1,62 @@ +From 66b3a292d3fc749e8ec7ac5278a17e8a5757ecbc Mon Sep 17 00:00:00 2001 +From: Daniel Lezcano +Date: Wed, 1 Mar 2023 21:14:41 +0100 +Subject: [PATCH 10/42] thermal: Use thermal_zone_device_type() accessor + +Replace the accesses to 'tz->type' by its accessor version in order to +self-encapsulate the thermal_zone_device structure. + +Signed-off-by: Daniel Lezcano +Reviewed-by: Ido Schimmel #mlxsw +Reviewed-by: AngeloGioacchino Del Regno #MediaTek LVTS +Signed-off-by: Rafael J. Wysocki +--- + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 2 +- + drivers/thermal/mediatek/lvts_thermal.c | 6 ++++-- + drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -168,7 +168,7 @@ mlxsw_thermal_module_trips_update(struct + + if (crit_temp > emerg_temp) { + dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n", +- tz->tzdev->type, crit_temp, emerg_temp); ++ thermal_zone_device_type(tz->tzdev), crit_temp, emerg_temp); + return 0; + } + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -305,7 +305,8 @@ static int lvts_set_trips(struct thermal + * 14-0 : Raw temperature for threshold + */ + if (low != -INT_MAX) { +- pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low); ++ pr_debug("%s: Setting low limit temperature interrupt: %d\n", ++ thermal_zone_device_type(tz), low); + writel(raw_low, LVTS_H2NTHRE(base)); + } + +@@ -318,7 +319,8 @@ static int lvts_set_trips(struct thermal + * + * 14-0 : Raw temperature for threshold + */ +- pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high); ++ pr_debug("%s: Setting high limit temperature interrupt: %d\n", ++ thermal_zone_device_type(tz), high); + writel(raw_high, LVTS_HTHRE(base)); + + return 0; +--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c ++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +@@ -44,7 +44,7 @@ static void ti_thermal_work(struct work_ + thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED); + + dev_dbg(data->bgp->dev, "updated thermal zone %s\n", +- data->ti_thermal->type); ++ thermal_zone_device_type(data->ti_thermal)); + } + + /** diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch new file mode 100644 index 0000000000..68f41fdd16 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch @@ -0,0 +1,81 @@ +From f6658c1c4ae98477d6be00495226c0617354fe76 Mon Sep 17 00:00:00 2001 +From: Markus Schneider-Pargmann +Date: Fri, 27 Jan 2023 16:44:43 +0100 +Subject: [PATCH 11/42] thermal/drivers/mediatek: Control buffer enablement + tweaks + +Add logic in order to be able to turn on the control buffer on MT8365. +This change now allows to have control buffer support for MTK_THERMAL_V1, +and it allows to define the register offset, and mask used to enable it. + +Signed-off-by: Markus Schneider-Pargmann +Signed-off-by: Fabien Parent +Signed-off-by: Amjad Ouled-Ameur +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-2-55a1ae14af74@baylibre.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mediatek/auxadc_thermal.c | 28 +++++++++++++++-------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -307,6 +307,9 @@ struct mtk_thermal_data { + bool need_switch_bank; + struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; + enum mtk_thermal_version version; ++ u32 apmixed_buffer_ctl_reg; ++ u32 apmixed_buffer_ctl_mask; ++ u32 apmixed_buffer_ctl_set; + }; + + struct mtk_thermal { +@@ -560,6 +563,9 @@ static const struct mtk_thermal_data mt7 + .adcpnp = mt7622_adcpnp, + .sensor_mux_values = mt7622_mux_values, + .version = MTK_THERMAL_V2, ++ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1, ++ .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3), ++ .apmixed_buffer_ctl_set = BIT(0), + }; + + /* +@@ -1079,14 +1085,18 @@ static const struct of_device_id mtk_the + }; + MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); + +-static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) ++static void mtk_thermal_turn_on_buffer(struct mtk_thermal *mt, ++ void __iomem *apmixed_base) + { +- int tmp; ++ u32 tmp; ++ ++ if (!mt->conf->apmixed_buffer_ctl_reg) ++ return; + +- tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); +- tmp &= ~(0x37); +- tmp |= 0x1; +- writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); ++ tmp = readl(apmixed_base + mt->conf->apmixed_buffer_ctl_reg); ++ tmp &= mt->conf->apmixed_buffer_ctl_mask; ++ tmp |= mt->conf->apmixed_buffer_ctl_set; ++ writel(tmp, apmixed_base + mt->conf->apmixed_buffer_ctl_reg); + udelay(200); + } + +@@ -1184,10 +1194,10 @@ static int mtk_thermal_probe(struct plat + goto err_disable_clk_auxadc; + } + +- if (mt->conf->version != MTK_THERMAL_V1) { +- mtk_thermal_turn_on_buffer(apmixed_base); ++ mtk_thermal_turn_on_buffer(mt, apmixed_base); ++ ++ if (mt->conf->version != MTK_THERMAL_V2) + mtk_thermal_release_periodic_ts(mt, auxadc_base); +- } + + if (mt->conf->version == MTK_THERMAL_V1) + mt->raw_to_mcelsius = raw_to_mcelsius_v1; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch b/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch new file mode 100644 index 0000000000..285c6f6a7b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch @@ -0,0 +1,123 @@ +From c4eff784465f88218dc5eb51320320464db83d3f Mon Sep 17 00:00:00 2001 +From: Fabien Parent +Date: Fri, 27 Jan 2023 16:44:44 +0100 +Subject: [PATCH 12/42] thermal/drivers/mediatek: Add support for MT8365 SoC + +MT8365 is similar to the other SoCs supported by the driver. It has only +one bank and 3 actual sensors that can be multiplexed. There is another +one sensor that does not have usable data. + +Signed-off-by: Fabien Parent +Signed-off-by: Amjad Ouled-Ameur +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-3-55a1ae14af74@baylibre.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mediatek/auxadc_thermal.c | 68 +++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -31,6 +31,7 @@ + #define AUXADC_CON2_V 0x010 + #define AUXADC_DATA(channel) (0x14 + (channel) * 4) + ++#define APMIXED_SYS_TS_CON0 0x600 + #define APMIXED_SYS_TS_CON1 0x604 + + /* Thermal Controller Registers */ +@@ -281,6 +282,17 @@ enum mtk_thermal_version { + /* The calibration coefficient of sensor */ + #define MT7986_CALIBRATION 165 + ++/* MT8365 */ ++#define MT8365_TEMP_AUXADC_CHANNEL 11 ++#define MT8365_CALIBRATION 164 ++#define MT8365_NUM_CONTROLLER 1 ++#define MT8365_NUM_BANKS 1 ++#define MT8365_NUM_SENSORS 3 ++#define MT8365_NUM_SENSORS_PER_ZONE 3 ++#define MT8365_TS1 0 ++#define MT8365_TS2 1 ++#define MT8365_TS3 2 ++ + struct mtk_thermal; + + struct thermal_bank_cfg { +@@ -435,6 +447,24 @@ static const int mt7986_mux_values[MT798 + static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; + static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; + ++/* MT8365 thermal sensor data */ ++static const int mt8365_bank_data[MT8365_NUM_SENSORS] = { ++ MT8365_TS1, MT8365_TS2, MT8365_TS3 ++}; ++ ++static const int mt8365_msr[MT8365_NUM_SENSORS_PER_ZONE] = { ++ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 ++}; ++ ++static const int mt8365_adcpnp[MT8365_NUM_SENSORS_PER_ZONE] = { ++ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 ++}; ++ ++static const int mt8365_mux_values[MT8365_NUM_SENSORS] = { 0, 1, 2 }; ++static const int mt8365_tc_offset[MT8365_NUM_CONTROLLER] = { 0 }; ++ ++static const int mt8365_vts_index[MT8365_NUM_SENSORS] = { VTS1, VTS2, VTS3 }; ++ + /* + * The MT8173 thermal controller has four banks. Each bank can read up to + * four temperature sensors simultaneously. The MT8173 has a total of 5 +@@ -510,6 +540,40 @@ static const struct mtk_thermal_data mt2 + }; + + /* ++ * The MT8365 thermal controller has one bank, which can read up to ++ * four temperature sensors simultaneously. The MT8365 has a total of 3 ++ * temperature sensors. ++ * ++ * The thermal core only gets the maximum temperature of this one bank, ++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart ++ * Voltage Scaling) unit makes its decisions based on the same bank ++ * data. ++ */ ++static const struct mtk_thermal_data mt8365_thermal_data = { ++ .auxadc_channel = MT8365_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT8365_NUM_BANKS, ++ .num_sensors = MT8365_NUM_SENSORS, ++ .vts_index = mt8365_vts_index, ++ .cali_val = MT8365_CALIBRATION, ++ .num_controller = MT8365_NUM_CONTROLLER, ++ .controller_offset = mt8365_tc_offset, ++ .need_switch_bank = false, ++ .bank_data = { ++ { ++ .num_sensors = MT8365_NUM_SENSORS, ++ .sensors = mt8365_bank_data ++ }, ++ }, ++ .msr = mt8365_msr, ++ .adcpnp = mt8365_adcpnp, ++ .sensor_mux_values = mt8365_mux_values, ++ .version = MTK_THERMAL_V1, ++ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON0, ++ .apmixed_buffer_ctl_mask = (u32) ~GENMASK(29, 28), ++ .apmixed_buffer_ctl_set = 0, ++}; ++ ++/* + * The MT2712 thermal controller has one bank, which can read up to + * four temperature sensors simultaneously. The MT2712 has a total of 4 + * temperature sensors. +@@ -1080,6 +1144,10 @@ static const struct of_device_id mtk_the + { + .compatible = "mediatek,mt8183-thermal", + .data = (void *)&mt8183_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt8365-thermal", ++ .data = (void *)&mt8365_thermal_data, + }, { + }, + }; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch b/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch new file mode 100644 index 0000000000..5c99aa80c1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch @@ -0,0 +1,50 @@ +From 4eead70db74922bc61e9d0b4591524369a335751 Mon Sep 17 00:00:00 2001 +From: Amjad Ouled-Ameur +Date: Fri, 27 Jan 2023 16:44:46 +0100 +Subject: [PATCH 13/42] thermal/drivers/mediatek: Add delay after thermal banks + initialization + +Thermal sensor reads performed immediately after thermal bank +initialization returns bogus values. This is currently tackled by returning +0 if the temperature is bogus (exceeding 200000). + +Instead, add a delay between the bank init and the thermal zone device +register to properly fix this. + +Signed-off-by: Michael Kao +Signed-off-by: Hsin-Yi Wang +Signed-off-by: Amjad Ouled-Ameur +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-5-55a1ae14af74@baylibre.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/mediatek/auxadc_thermal.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -816,14 +816,6 @@ static int mtk_thermal_bank_temperature( + mt, conf->bank_data[bank->id].sensors[i], raw); + + +- /* +- * The first read of a sensor often contains very high bogus +- * temperature value. Filter these out so that the system does +- * not immediately shut down. +- */ +- if (temp > 200000) +- temp = 0; +- + if (temp > max) + max = temp; + } +@@ -1281,6 +1273,9 @@ static int mtk_thermal_probe(struct plat + + platform_set_drvdata(pdev, mt); + ++ /* Delay for thermal banks to be ready */ ++ msleep(30); ++ + tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); + if (IS_ERR(tzdev)) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch b/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch new file mode 100644 index 0000000000..734f5c1e77 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch @@ -0,0 +1,46 @@ +From ad9dc9e92367803a4f9576aea0dab110d03fc510 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 28 Mar 2023 11:10:17 +0800 +Subject: [PATCH 14/42] thermal/drivers/mediatek/lvts_thermal: Fix sensor 1 + interrupt status bitmask + +The binary representation for sensor 1 interrupt status was incorrectly +assembled, when compared to the full table given in the same comment +section. The conversion into hex was also incorrect, leading to +incorrect interrupt status bitmask for sensor 1. This would cause the +driver to incorrectly identify changes for sensor 1, when in fact it +was sensor 0, or a sensor access time out. + +Fix the binary and hex representations in the comments, and the actual +bitmask macro. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230328031017.1360976-1-wenst@chromium.org +--- + drivers/thermal/mediatek/lvts_thermal.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -66,7 +66,7 @@ + #define LVTS_MONINT_CONF 0x9FBF7BDE + + #define LVTS_INT_SENSOR0 0x0009001F +-#define LVTS_INT_SENSOR1 0X000881F0 ++#define LVTS_INT_SENSOR1 0x001203E0 + #define LVTS_INT_SENSOR2 0x00247C00 + #define LVTS_INT_SENSOR3 0x1FC00000 + +@@ -395,8 +395,8 @@ static irqreturn_t lvts_ctrl_irq_handler + * => 0x1FC00000 + * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000 + * => 0x00247C00 +- * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000 +- * => 0X000881F0 ++ * sensor 1 interrupt: 0000 0000 0001 0010 0000 0011 1110 0000 ++ * => 0X001203E0 + * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111 + * => 0x0009001F + */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch new file mode 100644 index 0000000000..d09c2055a3 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch @@ -0,0 +1,149 @@ +From 9aad43ad3285fc21158fb416830a6156a9a31fa5 Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 7 Mar 2023 16:45:22 +0100 +Subject: [PATCH 15/42] thermal/drivers/mediatek/lvts_thermal: Add AP domain + for mt8195 + +Add MT8195 AP Domain support to LVTS Driver. + +Take the opportunity to update the comments to show calibration data +information related to the new domain. + +[dlezcano]: Massaged a bit the changelog + +Signed-off-by: Balsam CHIHI +Tested-by: Chen-Yu Tsai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230307154524.118541-3-bchihi@baylibre.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 94 +++++++++++++++++++------ + 1 file changed, 74 insertions(+), 20 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -530,29 +530,33 @@ static int lvts_sensor_init(struct devic + * The efuse blob values follows the sensor enumeration per thermal + * controller. The decoding of the stream is as follow: + * +- * <--?-> <----big0 ???---> <-sensor0-> <-0-> +- * ------------------------------------------ +- * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | +- * ------------------------------------------ ++ * stream index map for MCU Domain : + * +- * <--sensor1--><-0-> <----big1 ???---> <-sen +- * ------------------------------------------ +- * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | +- * ------------------------------------------ ++ * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> ++ * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 + * +- * sor0-> <-0-> <-sensor1-> <-0-> .......... +- * ------------------------------------------ +- * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | +- * ------------------------------------------ ++ * <-----mcu-tc#1-----> <-----sensor#2-----> <-----sensor#3-----> ++ * 0x0A | 0x0B | 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 + * +- * And so on ... ++ * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> ++ * 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 ++ * ++ * stream index map for AP Domain : ++ * ++ * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1-----> ++ * 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A ++ * ++ * <-----ap--tc#1-----> <-----sensor#2-----> <-----sensor#3-----> ++ * 0x2B | 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33 ++ * ++ * <-----ap--tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> ++ * 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F ++ * ++ * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8-----> ++ * 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 + * + * The data description gives the offset of the calibration data in + * this bytes stream for each sensor. +- * +- * Each thermal controller can handle up to 4 sensors max, we don't +- * care if there are less as the array of calibration is sized to 4 +- * anyway. The unused sensor slot will be zeroed. + */ + static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, + const struct lvts_ctrl_data *lvts_ctrl_data, +@@ -1165,7 +1169,7 @@ static int lvts_remove(struct platform_d + return 0; + } + +-static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = { ++static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { + { + .cal_offset = { 0x04, 0x07 }, + .lvts_sensor = { +@@ -1200,13 +1204,63 @@ static const struct lvts_ctrl_data mt819 + } + }; + ++static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { ++ { ++ .cal_offset = { 0x25, 0x28 }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_AP_VPU0 }, ++ { .dt_id = MT8195_AP_VPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x0, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ }, ++ { ++ .cal_offset = { 0x2e, 0x31 }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_AP_GPU0 }, ++ { .dt_id = MT8195_AP_GPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x100, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ }, ++ { ++ .cal_offset = { 0x37, 0x3a, 0x3d }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_AP_VDEC }, ++ { .dt_id = MT8195_AP_IMG }, ++ { .dt_id = MT8195_AP_INFRA }, ++ }, ++ .num_lvts_sensor = 3, ++ .offset = 0x200, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ }, ++ { ++ .cal_offset = { 0x43, 0x46 }, ++ .lvts_sensor = { ++ { .dt_id = MT8195_AP_CAM0 }, ++ { .dt_id = MT8195_AP_CAM1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x300, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, ++ } ++}; ++ + static const struct lvts_data mt8195_lvts_mcu_data = { +- .lvts_ctrl = mt8195_lvts_data_ctrl, +- .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_data_ctrl), ++ .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), ++}; ++ ++static const struct lvts_data mt8195_lvts_ap_data = { ++ .lvts_ctrl = mt8195_lvts_ap_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), + }; + + static const struct of_device_id lvts_of_match[] = { + { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, ++ { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, lvts_of_match); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch b/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch new file mode 100644 index 0000000000..a48ea3742b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch @@ -0,0 +1,53 @@ +From 7105a86760bd9e4d107075cefc75016b693a5542 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Wed, 19 Apr 2023 08:11:45 +0200 +Subject: [PATCH 16/42] Revert "thermal/drivers/mediatek: Add delay after + thermal banks initialization" + +Some more testing revealed that this commit introduces a regression on some +MT8173 Chromebooks and at least on one MT6795 Sony Xperia M5 smartphone due +to the delay being apparently variable and machine specific. + +Another solution would be to delay for a bit more (~70ms) but this is not +feasible for two reasons: first of all, we're adding an even bigger delay +in a probe function; second, some machines need less, some may need even +more, making the msleep at probe solution highly suboptimal. + +This reverts commit 10debf8c2da8011c8009dd4b3f6d0ab85891c81b. + +Fixes: 10debf8c2da8 ("thermal/drivers/mediatek: Add delay after thermal banks initialization") +Reported-by: "kernelci.org bot" +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230419061146.22246-2-angelogioacchino.delregno@collabora.com +--- + drivers/thermal/mediatek/auxadc_thermal.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -816,6 +816,14 @@ static int mtk_thermal_bank_temperature( + mt, conf->bank_data[bank->id].sensors[i], raw); + + ++ /* ++ * The first read of a sensor often contains very high bogus ++ * temperature value. Filter these out so that the system does ++ * not immediately shut down. ++ */ ++ if (temp > 200000) ++ temp = 0; ++ + if (temp > max) + max = temp; + } +@@ -1273,9 +1281,6 @@ static int mtk_thermal_probe(struct plat + + platform_set_drvdata(pdev, mt); + +- /* Delay for thermal banks to be ready */ +- msleep(30); +- + tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); + if (IS_ERR(tzdev)) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch b/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch new file mode 100644 index 0000000000..aae87af5d1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch @@ -0,0 +1,78 @@ +From 681b652c9dfc4037d4a55b2733e091a4e1a5de18 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Wed, 19 Apr 2023 08:11:46 +0200 +Subject: [PATCH 17/42] thermal/drivers/mediatek: Add temperature constraints + to validate read +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The AUXADC thermal v1 allows reading temperature range between -20°C to +150°C and any value out of this range is invalid. + +Add new definitions for MT8173_TEMP_{MIN_MAX} and a new small helper +mtk_thermal_temp_is_valid() to check if new readings are in range: if +not, we tell to the API that the reading is invalid by returning +THERMAL_TEMP_INVALID. + +It was chosen to introduce the helper function because, even though this +temperature range is realistically ok for all, it comes from a downstream +kernel driver for version 1, but here we also support v2 and v3 which may +may have wider constraints. + +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230419061146.22246-3-angelogioacchino.delregno@collabora.com +--- + drivers/thermal/mediatek/auxadc_thermal.c | 24 +++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -116,6 +116,10 @@ + /* The calibration coefficient of sensor */ + #define MT8173_CALIBRATION 165 + ++/* Valid temperatures range */ ++#define MT8173_TEMP_MIN -20000 ++#define MT8173_TEMP_MAX 150000 ++ + /* + * Layout of the fuses providing the calibration data + * These macros could be used for MT8183, MT8173, MT2701, and MT2712. +@@ -689,6 +693,11 @@ static const struct mtk_thermal_data mt7 + .version = MTK_THERMAL_V3, + }; + ++static bool mtk_thermal_temp_is_valid(int temp) ++{ ++ return (temp >= MT8173_TEMP_MIN) && (temp <= MT8173_TEMP_MAX); ++} ++ + /** + * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius + * @mt: The thermal controller +@@ -815,14 +824,17 @@ static int mtk_thermal_bank_temperature( + temp = mt->raw_to_mcelsius( + mt, conf->bank_data[bank->id].sensors[i], raw); + +- + /* +- * The first read of a sensor often contains very high bogus +- * temperature value. Filter these out so that the system does +- * not immediately shut down. ++ * Depending on the filt/sen intervals and ADC polling time, ++ * we may need up to 60 milliseconds after initialization: this ++ * will result in the first reading containing an out of range ++ * temperature value. ++ * Validate the reading to both address the aforementioned issue ++ * and to eventually avoid bogus readings during runtime in the ++ * event that the AUXADC gets unstable due to high EMI, etc. + */ +- if (temp > 200000) +- temp = 0; ++ if (!mtk_thermal_temp_is_valid(temp)) ++ temp = THERMAL_TEMP_INVALID; + + if (temp > max) + max = temp; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch new file mode 100644 index 0000000000..782684aacc --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch @@ -0,0 +1,53 @@ +From 458fa1d508de3f17e49d974a0158d9aeff273a58 Mon Sep 17 00:00:00 2001 +From: Kang Chen +Date: Wed, 19 Apr 2023 10:07:48 +0800 +Subject: [PATCH 18/42] thermal/drivers/mediatek: Use devm_of_iomap to avoid + resource leak in mtk_thermal_probe + +Smatch reports: +1. mtk_thermal_probe() warn: 'apmixed_base' from of_iomap() not released. +2. mtk_thermal_probe() warn: 'auxadc_base' from of_iomap() not released. + +The original code forgets to release iomap resource when handling errors, +fix it by switch to devm_of_iomap. + +Fixes: 89945047b166 ("thermal: mediatek: Add tsensor support for V2 thermal system") +Signed-off-by: Kang Chen +Reviewed-by: Dongliang Mu +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230419020749.621257-1-void0red@hust.edu.cn +--- + drivers/thermal/mediatek/auxadc_thermal.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1232,7 +1232,12 @@ static int mtk_thermal_probe(struct plat + return -ENODEV; + } + +- auxadc_base = of_iomap(auxadc, 0); ++ auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); ++ if (IS_ERR(auxadc_base)) { ++ of_node_put(auxadc); ++ return PTR_ERR(auxadc_base); ++ } ++ + auxadc_phys_base = of_get_phys_base(auxadc); + + of_node_put(auxadc); +@@ -1248,7 +1253,12 @@ static int mtk_thermal_probe(struct plat + return -ENODEV; + } + +- apmixed_base = of_iomap(apmixedsys, 0); ++ apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); ++ if (IS_ERR(apmixed_base)) { ++ of_node_put(apmixedsys); ++ return PTR_ERR(apmixed_base); ++ } ++ + apmixed_phys_base = of_get_phys_base(apmixedsys); + + of_node_put(apmixedsys); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch new file mode 100644 index 0000000000..d7896dbd60 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch @@ -0,0 +1,100 @@ +From 227d1856924ec00a4f5bdf5afcf77bc7f3f04e86 Mon Sep 17 00:00:00 2001 +From: Kang Chen +Date: Wed, 19 Apr 2023 10:07:49 +0800 +Subject: [PATCH 19/42] thermal/drivers/mediatek: Change clk_prepare_enable to + devm_clk_get_enabled in mtk_thermal_probe + +Use devm_clk_get_enabled to do automatic resource management. +Meanwhile, remove error handling labels in the probe function and +the whole remove function. + +Signed-off-by: Kang Chen +Reviewed-by: Dongliang Mu +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230419020749.621257-2-void0red@hust.edu.cn +--- + drivers/thermal/mediatek/auxadc_thermal.c | 44 +++++------------------ + 1 file changed, 9 insertions(+), 35 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1206,14 +1206,6 @@ static int mtk_thermal_probe(struct plat + + mt->conf = of_device_get_match_data(&pdev->dev); + +- mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); +- if (IS_ERR(mt->clk_peri_therm)) +- return PTR_ERR(mt->clk_peri_therm); +- +- mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); +- if (IS_ERR(mt->clk_auxadc)) +- return PTR_ERR(mt->clk_auxadc); +- + mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(mt->thermal_base)) + return PTR_ERR(mt->thermal_base); +@@ -1272,16 +1264,18 @@ static int mtk_thermal_probe(struct plat + if (ret) + return ret; + +- ret = clk_prepare_enable(mt->clk_auxadc); +- if (ret) { ++ mt->clk_auxadc = devm_clk_get_enabled(&pdev->dev, "auxadc"); ++ if (IS_ERR(mt->clk_auxadc)) { ++ ret = PTR_ERR(mt->clk_auxadc); + dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); + return ret; + } + +- ret = clk_prepare_enable(mt->clk_peri_therm); +- if (ret) { ++ mt->clk_peri_therm = devm_clk_get_enabled(&pdev->dev, "therm"); ++ if (IS_ERR(mt->clk_peri_therm)) { ++ ret = PTR_ERR(mt->clk_peri_therm); + dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); +- goto err_disable_clk_auxadc; ++ return ret; + } + + mtk_thermal_turn_on_buffer(mt, apmixed_base); +@@ -1305,38 +1299,18 @@ static int mtk_thermal_probe(struct plat + + tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); +- if (IS_ERR(tzdev)) { +- ret = PTR_ERR(tzdev); +- goto err_disable_clk_peri_therm; +- } ++ if (IS_ERR(tzdev)) ++ return PTR_ERR(tzdev); + + ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev); + if (ret) + dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); + + return 0; +- +-err_disable_clk_peri_therm: +- clk_disable_unprepare(mt->clk_peri_therm); +-err_disable_clk_auxadc: +- clk_disable_unprepare(mt->clk_auxadc); +- +- return ret; +-} +- +-static int mtk_thermal_remove(struct platform_device *pdev) +-{ +- struct mtk_thermal *mt = platform_get_drvdata(pdev); +- +- clk_disable_unprepare(mt->clk_peri_therm); +- clk_disable_unprepare(mt->clk_auxadc); +- +- return 0; + } + + static struct platform_driver mtk_thermal_driver = { + .probe = mtk_thermal_probe, +- .remove = mtk_thermal_remove, + .driver = { + .name = "mtk-thermal", + .of_match_table = mtk_thermal_of_match, diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch b/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch new file mode 100644 index 0000000000..fd18a5365c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch @@ -0,0 +1,36 @@ +From 655fe2533ac05323a07c19ba079bf2064e7741af Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Sun, 19 Mar 2023 11:32:31 -0500 +Subject: [PATCH 20/42] thermal/drivers/mediatek: Use of_address_to_resource() + +Replace of_get_address() and of_translate_address() calls with single +call to of_address_to_resource(). + +Signed-off-by: Rob Herring +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230319163231.226738-1-robh@kernel.org +--- + drivers/thermal/mediatek/auxadc_thermal.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -979,14 +979,12 @@ static void mtk_thermal_init_bank(struct + + static u64 of_get_phys_base(struct device_node *np) + { +- u64 size64; +- const __be32 *regaddr_p; ++ struct resource res; + +- regaddr_p = of_get_address(np, 0, &size64, NULL); +- if (!regaddr_p) ++ if (of_address_to_resource(np, 0, &res)) + return OF_BAD_ADDR; + +- return of_translate_address(np, regaddr_p); ++ return res.start; + } + + static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch b/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch new file mode 100644 index 0000000000..c3ff17d517 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch @@ -0,0 +1,57 @@ +From 2c380d07215e6fce3ac66cc5af059bc2c2a69f7a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo?= +Date: Thu, 25 May 2023 14:18:11 +0200 +Subject: [PATCH 21/42] Revert "thermal/drivers/mediatek: Use devm_of_iomap to + avoid resource leak in mtk_thermal_probe" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit f05c7b7d9ea9477fcc388476c6f4ade8c66d2d26. + +That change was causing a regression in the generic-adc-thermal-probed +bootrr test as reported in the kernelci-results list [1]. +A proper rework will take longer, so revert it for now. + +[1] https://groups.io/g/kernelci-results/message/42660 + +Fixes: f05c7b7d9ea9 ("thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe") +Signed-off-by: Ricardo Cañuelo +Suggested-by: AngeloGioacchino Del Regno +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230525121811.3360268-1-ricardo.canuelo@collabora.com +--- + drivers/thermal/mediatek/auxadc_thermal.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct plat + return -ENODEV; + } + +- auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); +- if (IS_ERR(auxadc_base)) { +- of_node_put(auxadc); +- return PTR_ERR(auxadc_base); +- } +- ++ auxadc_base = of_iomap(auxadc, 0); + auxadc_phys_base = of_get_phys_base(auxadc); + + of_node_put(auxadc); +@@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct plat + return -ENODEV; + } + +- apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); +- if (IS_ERR(apmixed_base)) { +- of_node_put(apmixedsys); +- return PTR_ERR(apmixed_base); +- } +- ++ apmixed_base = of_iomap(apmixedsys, 0); + apmixed_phys_base = of_get_phys_base(apmixedsys); + + of_node_put(apmixedsys); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch b/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch new file mode 100644 index 0000000000..c4456529c1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch @@ -0,0 +1,37 @@ +From 496f4b08981d8a788ad5a2073fa1c65a2af1862b Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 13 Jun 2023 17:13:16 +0800 +Subject: [PATCH 22/42] thermal/drivers/mediatek/lvts_thermal: Register thermal + zones as hwmon sensors + +Register thermal zones as hwmon sensors to let userspace read +temperatures using standard hwmon interface. + +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230613091317.1691247-1-wenst@chromium.org +--- + drivers/thermal/mediatek/lvts_thermal.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -19,6 +19,8 @@ + #include + #include + ++#include "../thermal_hwmon.h" ++ + #define LVTS_MONCTL0(__base) (__base + 0x0000) + #define LVTS_MONCTL1(__base) (__base + 0x0004) + #define LVTS_MONCTL2(__base) (__base + 0x0008) +@@ -996,6 +998,9 @@ static int lvts_ctrl_start(struct device + return PTR_ERR(tz); + } + ++ if (devm_thermal_add_hwmon_sysfs(dev, tz)) ++ dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id); ++ + /* + * The thermal zone pointer will be needed in the + * interrupt handler, we store it in the sensor diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch b/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch new file mode 100644 index 0000000000..22e7a954ed --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch @@ -0,0 +1,28 @@ +From 885b9768ce2a66ed5d250822aed53d5114c895da Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Tue, 20 Jun 2023 17:07:31 +0800 +Subject: [PATCH 23/42] thermal/drivers/mediatek/lvts_thermal: Remove redundant + msg in lvts_ctrl_start() + +The upper-layer devm_thermal_add_hwmon_sysfs() function can directly +print error information. + +Signed-off-by: Yangtao Li +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230620090732.50025-10-frank.li@vivo.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -998,8 +998,7 @@ static int lvts_ctrl_start(struct device + return PTR_ERR(tz); + } + +- if (devm_thermal_add_hwmon_sysfs(dev, tz)) +- dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id); ++ devm_thermal_add_hwmon_sysfs(dev, tz); + + /* + * The thermal zone pointer will be needed in the diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch new file mode 100644 index 0000000000..bc67727423 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch @@ -0,0 +1,40 @@ +From 27b389d9f62c2174f95fe4002b11e77d4cb3ce80 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:32 -0400 +Subject: [PATCH 25/42] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on + all controllers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a single IRQ handler for each LVTS thermal domain, and it is +supposed to check each of its underlying controllers for the origin of +the interrupt and clear its status. However due to a typo, only the +first controller was ever being handled, which resulted in the interrupt +never being cleared when it happened on the other controllers. Add the +missing index so interrupts are handled for all controllers. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: Chen-Yu Tsai +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-2-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -451,7 +451,7 @@ static irqreturn_t lvts_irq_handler(int + + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { + +- aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); ++ aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]); + if (aux != IRQ_HANDLED) + continue; + diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch new file mode 100644 index 0000000000..51d119c05b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch @@ -0,0 +1,120 @@ +From 6d827142643ee10c13ff9a1d90f38fb399aa9fff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:33 -0400 +Subject: [PATCH 26/42] thermal/drivers/mediatek/lvts_thermal: Honor sensors in + immediate mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Each controller can be configured to operate on immediate or filtered +mode. On filtered mode, the sensors are enabled by setting the +corresponding bits in MONCTL0, while on immediate mode, by setting +MSRCTL1. + +Previously, the code would set MSRCTL1 for all four sensors when +configured to immediate mode, but given that the controller might not +have all four sensors connected, this would cause interrupts to trigger +for non-existent sensors. Fix this by handling the MSRCTL1 register +analogously to the MONCTL0: only enable the sensors that were declared. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: Chen-Yu Tsai +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-3-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 57 ++++++++++++++----------- + 1 file changed, 33 insertions(+), 24 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -897,24 +897,6 @@ static int lvts_ctrl_configure(struct de + writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); + + /* +- * LVTS_MSRCTL1 : Measurement control +- * +- * Bits: +- * +- * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 +- * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 +- * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 +- * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 +- * +- * That configuration will ignore the filtering and the delays +- * introduced below in MONCTL1 and MONCTL2 +- */ +- if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { +- value = BIT(9) | BIT(6) | BIT(5) | BIT(4); +- writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); +- } +- +- /* + * LVTS_MONCTL1 : Period unit and group interval configuration + * + * The clock source of LVTS thermal controller is 26MHz. +@@ -979,6 +961,15 @@ static int lvts_ctrl_start(struct device + struct thermal_zone_device *tz; + u32 sensor_map = 0; + int i; ++ /* ++ * Bitmaps to enable each sensor on immediate and filtered modes, as ++ * described in MSRCTL1 and MONCTL0 registers below, respectively. ++ */ ++ u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) }; ++ u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; ++ ++ u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ? ++ sensor_imm_bitmap : sensor_filt_bitmap; + + for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { + +@@ -1016,20 +1007,38 @@ static int lvts_ctrl_start(struct device + * map, so we can enable the temperature monitoring in + * the hardware thermal controller. + */ +- sensor_map |= BIT(i); ++ sensor_map |= sensor_bitmap[i]; + } + + /* +- * Bits: +- * 9: Single point access flow +- * 0-3: Enable sensing point 0-3 +- * + * The initialization of the thermal zones give us + * which sensor point to enable. If any thermal zone + * was not described in the device tree, it won't be + * enabled here in the sensor map. + */ +- writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); ++ if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { ++ /* ++ * LVTS_MSRCTL1 : Measurement control ++ * ++ * Bits: ++ * ++ * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 ++ * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 ++ * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 ++ * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 ++ * ++ * That configuration will ignore the filtering and the delays ++ * introduced in MONCTL1 and MONCTL2 ++ */ ++ writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base)); ++ } else { ++ /* ++ * Bits: ++ * 9: Single point access flow ++ * 0-3: Enable sensing point 0-3 ++ */ ++ writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); ++ } + + return 0; + } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch b/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch new file mode 100644 index 0000000000..bfbadee350 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch @@ -0,0 +1,77 @@ +From 93bb11dd19bdcc1fc97c7ceababd0db9fde128ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:34 -0400 +Subject: [PATCH 27/42] thermal/drivers/mediatek/lvts_thermal: Use offset + threshold for IRQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are two kinds of temperature monitoring interrupts available: +* High Offset, Low Offset +* Hot, Hot to normal, Cold + +The code currently uses the hot/h2n/cold interrupts, however in a way +that doesn't work: the cold threshold is left uninitialized, which +prevents the other thresholds from ever triggering, and the h2n +interrupt is used as the lower threshold, which prevents the hot +interrupt from triggering again after the thresholds are updated by the +thermal framework, since a hot interrupt can only trigger again after +the hot to normal interrupt has been triggered. + +But better yet than addressing those issues, is to use the high/low +offset interrupts instead. This way only two thresholds need to be +managed, which have a simpler state machine, making them a better match +to the thermal framework's high and low thresholds. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-4-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -298,9 +298,9 @@ static int lvts_set_trips(struct thermal + u32 raw_high = lvts_temp_to_raw(high); + + /* +- * Hot to normal temperature threshold ++ * Low offset temperature threshold + * +- * LVTS_H2NTHRE ++ * LVTS_OFFSETL + * + * Bits: + * +@@ -309,13 +309,13 @@ static int lvts_set_trips(struct thermal + if (low != -INT_MAX) { + pr_debug("%s: Setting low limit temperature interrupt: %d\n", + thermal_zone_device_type(tz), low); +- writel(raw_low, LVTS_H2NTHRE(base)); ++ writel(raw_low, LVTS_OFFSETL(base)); + } + + /* +- * Hot temperature threshold ++ * High offset temperature threshold + * +- * LVTS_HTHRE ++ * LVTS_OFFSETH + * + * Bits: + * +@@ -323,7 +323,7 @@ static int lvts_set_trips(struct thermal + */ + pr_debug("%s: Setting high limit temperature interrupt: %d\n", + thermal_zone_device_type(tz), high); +- writel(raw_high, LVTS_HTHRE(base)); ++ writel(raw_high, LVTS_OFFSETH(base)); + + return 0; + } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch b/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch new file mode 100644 index 0000000000..1c35d0ad19 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch @@ -0,0 +1,51 @@ +From 8f8cab9d3e90acf1db278ef44ad05f10aefb973f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:35 -0400 +Subject: [PATCH 28/42] thermal/drivers/mediatek/lvts_thermal: Disable + undesired interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Out of the many interrupts supported by the hardware, the only ones of +interest to the driver currently are: +* The temperature went over the high offset threshold, for any of the + sensors +* The temperature went below the low offset threshold, for any of the + sensors +* The temperature went over the stage3 threshold + +These are the only thresholds configured by the driver through the +OFFSETH, OFFSETL, and PROTTC registers, respectively. + +The current interrupt mask in LVTS_MONINT_CONF, enables many more +interrupts, including data ready on sensors for both filtered and +immediate mode. These are not only not handled by the driver, but they +are also triggered too often, causing unneeded overhead. Disable these +unnecessary interrupts. + +The meaning of each bit can be seen in the comment describing +LVTS_MONINTST in the IRQ handler. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Alexandre Mergnat +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-5-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -65,7 +65,7 @@ + #define LVTS_HW_FILTER 0x2 + #define LVTS_TSSEL_CONF 0x13121110 + #define LVTS_CALSCALE_CONF 0x300 +-#define LVTS_MONINT_CONF 0x9FBF7BDE ++#define LVTS_MONINT_CONF 0x8300318C + + #define LVTS_INT_SENSOR0 0x0009001F + #define LVTS_INT_SENSOR1 0x001203E0 diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch b/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch new file mode 100644 index 0000000000..60942fdb89 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch @@ -0,0 +1,70 @@ +From bd1ccf9408e6155564530af5e09b53ae497fe332 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:36 -0400 +Subject: [PATCH 29/42] thermal/drivers/mediatek/lvts_thermal: Don't leave + threshold zeroed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The thermal framework might leave the low threshold unset if there +aren't any lower trip points. This leaves the register zeroed, which +translates to a very high temperature for the low threshold. The +interrupt for this threshold is then immediately triggered, and the +state machine gets stuck, preventing any other temperature monitoring +interrupts to ever trigger. + +(The same happens by not setting the Cold or Hot to Normal thresholds +when using those) + +Set the unused threshold to a valid low value. This value was chosen so +that for any valid golden temperature read from the efuse, when the +value is converted to raw and back again to milliCelsius, the result +doesn't underflow. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-6-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -83,6 +83,8 @@ + + #define LVTS_HW_SHUTDOWN_MT8195 105000 + ++#define LVTS_MINIMUM_THRESHOLD 20000 ++ + static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; + static int coeff_b = LVTS_COEFF_B; + +@@ -294,7 +296,7 @@ static int lvts_set_trips(struct thermal + { + struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + void __iomem *base = lvts_sensor->base; +- u32 raw_low = lvts_temp_to_raw(low); ++ u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); + u32 raw_high = lvts_temp_to_raw(high); + + /* +@@ -306,11 +308,9 @@ static int lvts_set_trips(struct thermal + * + * 14-0 : Raw temperature for threshold + */ +- if (low != -INT_MAX) { +- pr_debug("%s: Setting low limit temperature interrupt: %d\n", +- thermal_zone_device_type(tz), low); +- writel(raw_low, LVTS_OFFSETL(base)); +- } ++ pr_debug("%s: Setting low limit temperature interrupt: %d\n", ++ thermal_zone_device_type(tz), low); ++ writel(raw_low, LVTS_OFFSETL(base)); + + /* + * High offset temperature threshold diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch b/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch new file mode 100644 index 0000000000..e99aa0cdfd --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch @@ -0,0 +1,156 @@ +From d4dd09968cab3249e6148e1c3fccb51824edb411 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 6 Jul 2023 11:37:37 -0400 +Subject: [PATCH 30/42] thermal/drivers/mediatek/lvts_thermal: Manage threshold + between sensors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Each LVTS thermal controller can have up to four sensors, each capable +of triggering its own interrupt when its measured temperature crosses +the configured threshold. The threshold for each sensor is handled +separately by the thermal framework, since each one is registered with +its own thermal zone and trips. However, the temperature thresholds are +configured on the controller, and therefore are shared between all +sensors on that controller. + +When the temperature measured by the sensors is different enough to +cause the thermal framework to configure different thresholds for each +one, interrupts start triggering on sensors outside the last threshold +configured. + +To address the issue, track the thresholds required by each sensor and +only actually set the highest one in the hardware, and disable +interrupts for all sensors outside the current configured range. + +Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230706153823.201943-7-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 69 +++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -67,6 +67,11 @@ + #define LVTS_CALSCALE_CONF 0x300 + #define LVTS_MONINT_CONF 0x8300318C + ++#define LVTS_MONINT_OFFSET_SENSOR0 0xC ++#define LVTS_MONINT_OFFSET_SENSOR1 0x180 ++#define LVTS_MONINT_OFFSET_SENSOR2 0x3000 ++#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000 ++ + #define LVTS_INT_SENSOR0 0x0009001F + #define LVTS_INT_SENSOR1 0x001203E0 + #define LVTS_INT_SENSOR2 0x00247C00 +@@ -112,6 +117,8 @@ struct lvts_sensor { + void __iomem *base; + int id; + int dt_id; ++ int low_thresh; ++ int high_thresh; + }; + + struct lvts_ctrl { +@@ -121,6 +128,8 @@ struct lvts_ctrl { + int num_lvts_sensor; + int mode; + void __iomem *base; ++ int low_thresh; ++ int high_thresh; + }; + + struct lvts_domain { +@@ -292,12 +301,66 @@ static int lvts_get_temp(struct thermal_ + return 0; + } + ++static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl) ++{ ++ u32 masks[] = { ++ LVTS_MONINT_OFFSET_SENSOR0, ++ LVTS_MONINT_OFFSET_SENSOR1, ++ LVTS_MONINT_OFFSET_SENSOR2, ++ LVTS_MONINT_OFFSET_SENSOR3, ++ }; ++ u32 value = 0; ++ int i; ++ ++ value = readl(LVTS_MONINT(lvts_ctrl->base)); ++ ++ for (i = 0; i < ARRAY_SIZE(masks); i++) { ++ if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh ++ && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) ++ value |= masks[i]; ++ else ++ value &= ~masks[i]; ++ } ++ ++ writel(value, LVTS_MONINT(lvts_ctrl->base)); ++} ++ ++static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) ++{ ++ int i; ++ ++ if (high > lvts_ctrl->high_thresh) ++ return true; ++ ++ for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) ++ if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh ++ && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) ++ return false; ++ ++ return true; ++} ++ + static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) + { + struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); ++ struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); + void __iomem *base = lvts_sensor->base; + u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); + u32 raw_high = lvts_temp_to_raw(high); ++ bool should_update_thresh; ++ ++ lvts_sensor->low_thresh = low; ++ lvts_sensor->high_thresh = high; ++ ++ should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high); ++ if (should_update_thresh) { ++ lvts_ctrl->high_thresh = high; ++ lvts_ctrl->low_thresh = low; ++ } ++ lvts_update_irq_mask(lvts_ctrl); ++ ++ if (!should_update_thresh) ++ return 0; + + /* + * Low offset temperature threshold +@@ -521,6 +584,9 @@ static int lvts_sensor_init(struct devic + */ + lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? + imm_regs[i] : msr_regs[i]; ++ ++ lvts_sensor[i].low_thresh = INT_MIN; ++ lvts_sensor[i].high_thresh = INT_MIN; + }; + + lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; +@@ -688,6 +754,9 @@ static int lvts_ctrl_init(struct device + */ + lvts_ctrl[i].hw_tshut_raw_temp = + lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); ++ ++ lvts_ctrl[i].low_thresh = INT_MIN; ++ lvts_ctrl[i].high_thresh = INT_MIN; + } + + /* diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch b/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch new file mode 100644 index 0000000000..9ce3eeb74b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch @@ -0,0 +1,29 @@ +From 5af4904adc8b840987000724977c13c706d3b7d8 Mon Sep 17 00:00:00 2001 +From: Minjie Du +Date: Thu, 13 Jul 2023 12:24:12 +0800 +Subject: [PATCH 31/42] thermal/drivers/mediatek/lvts: Fix parameter check in + lvts_debugfs_init() + +The documentation says "If an error occurs, ERR_PTR(-ERROR) will be +returned" but the current code checks against a NULL pointer returned. + +Fix this by checking if IS_ERR(). + +Signed-off-by: Minjie Du +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230713042413.2519-1-duminjie@vivo.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -201,7 +201,7 @@ static int lvts_debugfs_init(struct devi + int i; + + lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); +- if (!lvts_td->dom_dentry) ++ if (IS_ERR(lvts_td->dom_dentry)) + return 0; + + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch b/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch new file mode 100644 index 0000000000..4841054917 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch @@ -0,0 +1,33 @@ +From 6186be80317d1dbda34d35c06c084a083938f2d3 Mon Sep 17 00:00:00 2001 +From: Chen Jiahao +Date: Wed, 2 Aug 2023 17:45:27 +0800 +Subject: [PATCH 32/42] thermal/drivers/mediatek: Clean up redundant + dev_err_probe() + +Referring to platform_get_irq()'s definition, the return value has +already been checked if ret < 0, and printed via dev_err_probe(). +Calling dev_err_probe() one more time outside platform_get_irq() +is obviously redundant. + +Removing dev_err_probe() outside platform_get_irq() to clean up +above problem. + +Signed-off-by: Chen Jiahao +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230802094527.988842-1-chenjiahao16@huawei.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -1216,7 +1216,7 @@ static int lvts_probe(struct platform_de + + irq = platform_get_irq(pdev, 0); + if (irq < 0) +- return dev_err_probe(dev, irq, "No irq resource\n"); ++ return irq; + + ret = lvts_domain_init(dev, lvts_td, lvts_data); + if (ret) diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch new file mode 100644 index 0000000000..c88bf984fa --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch @@ -0,0 +1,95 @@ +From c2ab54ab0425388e65901a7af2fbf69ead968708 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= + +Date: Thu, 13 Jul 2023 11:42:37 -0400 +Subject: [PATCH 33/42] thermal/drivers/mediatek/lvts_thermal: Make readings + valid in filtered mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently, when a controller is configured to use filtered mode, thermal +readings are valid only about 30% of the time. + +Upon testing, it was noticed that lowering any of the interval settings +resulted in an improved rate of valid data. The same was observed when +decreasing the number of samples for each sensor (which also results in +quicker measurements). + +Retrying the read with a timeout longer than the time it takes to +resample (about 344us with these settings and 4 sensors) also improves +the rate. + +Lower all timing settings to the minimum, configure the filtering to +single sample, and poll the measurement register for at least one period +to improve the data validity on filtered mode. With these changes in +place, out of 100000 reads, a single one failed, ie 99.999% of the data +was valid. + +Reviewed-by: Chen-Yu Tsai +Tested-by: Chen-Yu Tsai +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230713154743.611870-1-nfraprado@collabora.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -58,11 +58,11 @@ + #define LVTS_PROTTC(__base) (__base + 0x00CC) + #define LVTS_CLKEN(__base) (__base + 0x00E4) + +-#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) +-#define LVTS_GROUP_INTERVAL 1 +-#define LVTS_FILTER_INTERVAL 1 +-#define LVTS_SENSOR_INTERVAL 1 +-#define LVTS_HW_FILTER 0x2 ++#define LVTS_PERIOD_UNIT 0 ++#define LVTS_GROUP_INTERVAL 0 ++#define LVTS_FILTER_INTERVAL 0 ++#define LVTS_SENSOR_INTERVAL 0 ++#define LVTS_HW_FILTER 0x0 + #define LVTS_TSSEL_CONF 0x13121110 + #define LVTS_CALSCALE_CONF 0x300 + #define LVTS_MONINT_CONF 0x8300318C +@@ -86,6 +86,9 @@ + #define LVTS_MSR_IMMEDIATE_MODE 0 + #define LVTS_MSR_FILTERED_MODE 1 + ++#define LVTS_MSR_READ_TIMEOUT_US 400 ++#define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) ++ + #define LVTS_HW_SHUTDOWN_MT8195 105000 + + #define LVTS_MINIMUM_THRESHOLD 20000 +@@ -268,6 +271,7 @@ static int lvts_get_temp(struct thermal_ + struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + void __iomem *msr = lvts_sensor->msr; + u32 value; ++ int rc; + + /* + * Measurement registers: +@@ -280,7 +284,8 @@ static int lvts_get_temp(struct thermal_ + * 16 : Valid temperature + * 15-0 : Raw temperature + */ +- value = readl(msr); ++ rc = readl_poll_timeout(msr, value, value & BIT(16), ++ LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US); + + /* + * As the thermal zone temperature will read before the +@@ -293,7 +298,7 @@ static int lvts_get_temp(struct thermal_ + * functionning temperature and directly jump to a system + * shutdown. + */ +- if (!(value & BIT(16))) ++ if (rc) + return -EAGAIN; + + *temp = lvts_raw_to_temp(value & 0xFFFF); diff --git a/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch b/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch new file mode 100644 index 0000000000..994461cdb1 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch @@ -0,0 +1,30 @@ +From c864ff9de3b225b43bb8e08dedb223632323e059 Mon Sep 17 00:00:00 2001 +From: Andrei Coardos +Date: Fri, 11 Aug 2023 22:28:47 +0300 +Subject: [PATCH 34/42] thermal/drivers/mediatek/auxadc_thermal: Removed call + to platform_set_drvdata() + +This function call was found to be unnecessary as there is no equivalent +platform_get_drvdata() call to access the private data of the driver. Also, +the private data is defined in this driver, so there is no risk of it being +accessed outside of this driver file. + +Signed-off-by: Andrei Coardos +Reviewed-by: Alexandru Ardelean +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230811192847.3838-1-aboutphysycs@gmail.com +--- + drivers/thermal/mediatek/auxadc_thermal.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1283,8 +1283,6 @@ static int mtk_thermal_probe(struct plat + mtk_thermal_init_bank(mt, i, apmixed_phys_base, + auxadc_phys_base, ctrl_id); + +- platform_set_drvdata(pdev, mt); +- + tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); + if (IS_ERR(tzdev)) diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch b/target/linux/mediatek/patches-6.6/830-v6.7-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch new file mode 100644 index 0000000000..b3bfa37458 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch @@ -0,0 +1,58 @@ +From 6cf96078969ec00b873db99bae4e47001290685e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Wed, 27 Sep 2023 21:37:23 +0200 +Subject: [PATCH 35/42] thermal: lvts: Convert to platform remove callback + returning void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The .remove() callback for a platform driver returns an int which makes +many driver authors wrongly assume it's possible to do error handling by +returning an error code. However the value returned is ignored (apart +from emitting a warning) and this typically results in resource leaks. + +To improve here there is a quest to make the remove callback return +void. In the first step of this quest all drivers are converted to +.remove_new(), which already returns void. Eventually after all drivers +are converted, .remove_new() will be renamed to .remove(). + +Trivially convert this driver from always returning zero in the remove +callback to the void returning variant. + +Signed-off-by: Uwe Kleine-König +Acked-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +--- + drivers/thermal/mediatek/lvts_thermal.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -1241,7 +1241,7 @@ static int lvts_probe(struct platform_de + return 0; + } + +-static int lvts_remove(struct platform_device *pdev) ++static void lvts_remove(struct platform_device *pdev) + { + struct lvts_domain *lvts_td; + int i; +@@ -1252,8 +1252,6 @@ static int lvts_remove(struct platform_d + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); + + lvts_debugfs_exit(lvts_td); +- +- return 0; + } + + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { +@@ -1354,7 +1352,7 @@ MODULE_DEVICE_TABLE(of, lvts_of_match); + + static struct platform_driver lvts_driver = { + .probe = lvts_probe, +- .remove = lvts_remove, ++ .remove_new = lvts_remove, + .driver = { + .name = "mtk-lvts-thermal", + .of_match_table = lvts_of_match, diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch b/target/linux/mediatek/patches-6.6/830-v6.7-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch new file mode 100644 index 0000000000..16a32f564b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch @@ -0,0 +1,198 @@ +From 26cc18a3d6d9eac21c4f4b4bb96147b2c6617c86 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 22 Sep 2023 07:50:19 +0200 +Subject: [PATCH 36/42] thermal/drivers/mediatek/lvts_thermal: Make coeff + configurable + +The upcoming mt7988 has different temperature coefficients so we +cannot use constants in the functions lvts_golden_temp_init, +lvts_golden_temp_init and lvts_raw_to_temp anymore. + +Add a field in the lvts_ctrl pointing to the lvts_data which now +contains the soc-specific temperature coefficents. + +To make the code better readable, rename static int coeff_b to +golden_temp_offset, COEFF_A to temp_factor and COEFF_B to temp_offset. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: Daniel Golle +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230922055020.6436-4-linux@fw-web.de +--- + drivers/thermal/mediatek/lvts_thermal.c | 51 ++++++++++++++++--------- + 1 file changed, 34 insertions(+), 17 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -80,8 +80,8 @@ + #define LVTS_SENSOR_MAX 4 + #define LVTS_GOLDEN_TEMP_MAX 62 + #define LVTS_GOLDEN_TEMP_DEFAULT 50 +-#define LVTS_COEFF_A -250460 +-#define LVTS_COEFF_B 250460 ++#define LVTS_COEFF_A_MT8195 -250460 ++#define LVTS_COEFF_B_MT8195 250460 + + #define LVTS_MSR_IMMEDIATE_MODE 0 + #define LVTS_MSR_FILTERED_MODE 1 +@@ -94,7 +94,7 @@ + #define LVTS_MINIMUM_THRESHOLD 20000 + + static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; +-static int coeff_b = LVTS_COEFF_B; ++static int golden_temp_offset; + + struct lvts_sensor_data { + int dt_id; +@@ -112,6 +112,8 @@ struct lvts_ctrl_data { + struct lvts_data { + const struct lvts_ctrl_data *lvts_ctrl; + int num_lvts_ctrl; ++ int temp_factor; ++ int temp_offset; + }; + + struct lvts_sensor { +@@ -126,6 +128,7 @@ struct lvts_sensor { + + struct lvts_ctrl { + struct lvts_sensor sensors[LVTS_SENSOR_MAX]; ++ const struct lvts_data *lvts_data; + u32 calibration[LVTS_SENSOR_MAX]; + u32 hw_tshut_raw_temp; + int num_lvts_sensor; +@@ -247,21 +250,21 @@ static void lvts_debugfs_exit(struct lvt + + #endif + +-static int lvts_raw_to_temp(u32 raw_temp) ++static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) + { + int temperature; + +- temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; +- temperature += coeff_b; ++ temperature = ((s64)(raw_temp & 0xFFFF) * temp_factor) >> 14; ++ temperature += golden_temp_offset; + + return temperature; + } + +-static u32 lvts_temp_to_raw(int temperature) ++static u32 lvts_temp_to_raw(int temperature, int temp_factor) + { +- u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; ++ u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14; + +- raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); ++ raw_temp = div_s64(raw_temp, -temp_factor); + + return raw_temp; + } +@@ -269,6 +272,9 @@ static u32 lvts_temp_to_raw(int temperat + static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) + { + struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); ++ struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, ++ sensors[lvts_sensor->id]); ++ const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; + void __iomem *msr = lvts_sensor->msr; + u32 value; + int rc; +@@ -301,7 +307,7 @@ static int lvts_get_temp(struct thermal_ + if (rc) + return -EAGAIN; + +- *temp = lvts_raw_to_temp(value & 0xFFFF); ++ *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor); + + return 0; + } +@@ -348,10 +354,13 @@ static bool lvts_should_update_thresh(st + static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) + { + struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); +- struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); ++ struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, ++ sensors[lvts_sensor->id]); ++ const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; + void __iomem *base = lvts_sensor->base; +- u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); +- u32 raw_high = lvts_temp_to_raw(high); ++ u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD, ++ lvts_data->temp_factor); ++ u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor); + bool should_update_thresh; + + lvts_sensor->low_thresh = low; +@@ -692,7 +701,7 @@ static int lvts_calibration_read(struct + return 0; + } + +-static int lvts_golden_temp_init(struct device *dev, u32 *value) ++static int lvts_golden_temp_init(struct device *dev, u32 *value, int temp_offset) + { + u32 gt; + +@@ -701,7 +710,7 @@ static int lvts_golden_temp_init(struct + if (gt && gt < LVTS_GOLDEN_TEMP_MAX) + golden_temp = gt; + +- coeff_b = golden_temp * 500 + LVTS_COEFF_B; ++ golden_temp_offset = golden_temp * 500 + temp_offset; + + return 0; + } +@@ -724,7 +733,7 @@ static int lvts_ctrl_init(struct device + * The golden temp information is contained in the first chunk + * of efuse data. + */ +- ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); ++ ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib, lvts_data->temp_offset); + if (ret) + return ret; + +@@ -735,6 +744,7 @@ static int lvts_ctrl_init(struct device + for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { + + lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; ++ lvts_ctrl[i].lvts_data = lvts_data; + + ret = lvts_sensor_init(dev, &lvts_ctrl[i], + &lvts_data->lvts_ctrl[i]); +@@ -758,7 +768,8 @@ static int lvts_ctrl_init(struct device + * after initializing the calibration. + */ + lvts_ctrl[i].hw_tshut_raw_temp = +- lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); ++ lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp, ++ lvts_data->temp_factor); + + lvts_ctrl[i].low_thresh = INT_MIN; + lvts_ctrl[i].high_thresh = INT_MIN; +@@ -1223,6 +1234,8 @@ static int lvts_probe(struct platform_de + if (irq < 0) + return irq; + ++ golden_temp_offset = lvts_data->temp_offset; ++ + ret = lvts_domain_init(dev, lvts_td, lvts_data); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); +@@ -1336,11 +1349,15 @@ static const struct lvts_ctrl_data mt819 + static const struct lvts_data mt8195_lvts_mcu_data = { + .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), ++ .temp_factor = LVTS_COEFF_A_MT8195, ++ .temp_offset = LVTS_COEFF_B_MT8195, + }; + + static const struct lvts_data mt8195_lvts_ap_data = { + .lvts_ctrl = mt8195_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), ++ .temp_factor = LVTS_COEFF_A_MT8195, ++ .temp_offset = LVTS_COEFF_B_MT8195, + }; + + static const struct of_device_id lvts_of_match[] = { diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch b/target/linux/mediatek/patches-6.6/830-v6.7-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch new file mode 100644 index 0000000000..1c2146f43f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch @@ -0,0 +1,35 @@ +From be2cc09bd5b46f13629d4fcdeac7ad1b18bb1a0b Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 22 Sep 2023 07:50:18 +0200 +Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal sensors for + mt7988 + +Add sensor constants for MT7988. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Conor Dooley +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230922055020.6436-3-linux@fw-web.de +--- + include/dt-bindings/thermal/mediatek,lvts-thermal.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h ++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h +@@ -7,6 +7,15 @@ + #ifndef __MEDIATEK_LVTS_DT_H + #define __MEDIATEK_LVTS_DT_H + ++#define MT7988_CPU_0 0 ++#define MT7988_CPU_1 1 ++#define MT7988_ETH2P5G_0 2 ++#define MT7988_ETH2P5G_1 3 ++#define MT7988_TOPS_0 4 ++#define MT7988_TOPS_1 5 ++#define MT7988_ETHWARP_0 6 ++#define MT7988_ETHWARP_1 7 ++ + #define MT8195_MCU_BIG_CPU0 0 + #define MT8195_MCU_BIG_CPU1 1 + #define MT8195_MCU_BIG_CPU2 2 diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch b/target/linux/mediatek/patches-6.6/830-v6.7-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch new file mode 100644 index 0000000000..97c803a820 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch @@ -0,0 +1,91 @@ +From 9924e9b91b43aaa1610a1d59c4caa43785948cf6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 22 Sep 2023 07:50:20 +0200 +Subject: [PATCH 37/42] thermal/drivers/mediatek/lvts_thermal: Add mt7988 + support + +Add Support for Mediatek Filogic 880/MT7988 LVTS. + +Signed-off-by: Frank Wunderlich +Tested-by: Daniel Golle +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230922055020.6436-5-linux@fw-web.de +--- + drivers/thermal/mediatek/lvts_thermal.c | 38 +++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -82,6 +82,8 @@ + #define LVTS_GOLDEN_TEMP_DEFAULT 50 + #define LVTS_COEFF_A_MT8195 -250460 + #define LVTS_COEFF_B_MT8195 250460 ++#define LVTS_COEFF_A_MT7988 -204650 ++#define LVTS_COEFF_B_MT7988 204650 + + #define LVTS_MSR_IMMEDIATE_MODE 0 + #define LVTS_MSR_FILTERED_MODE 1 +@@ -89,6 +91,7 @@ + #define LVTS_MSR_READ_TIMEOUT_US 400 + #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) + ++#define LVTS_HW_SHUTDOWN_MT7988 105000 + #define LVTS_HW_SHUTDOWN_MT8195 105000 + + #define LVTS_MINIMUM_THRESHOLD 20000 +@@ -1267,6 +1270,33 @@ static void lvts_remove(struct platform_ + lvts_debugfs_exit(lvts_td); + } + ++static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { ++ { ++ .cal_offset = { 0x00, 0x04, 0x08, 0x0c }, ++ .lvts_sensor = { ++ { .dt_id = MT7988_CPU_0 }, ++ { .dt_id = MT7988_CPU_1 }, ++ { .dt_id = MT7988_ETH2P5G_0 }, ++ { .dt_id = MT7988_ETH2P5G_1 } ++ }, ++ .num_lvts_sensor = 4, ++ .offset = 0x0, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, ++ }, ++ { ++ .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, ++ .lvts_sensor = { ++ { .dt_id = MT7988_TOPS_0}, ++ { .dt_id = MT7988_TOPS_1}, ++ { .dt_id = MT7988_ETHWARP_0}, ++ { .dt_id = MT7988_ETHWARP_1} ++ }, ++ .num_lvts_sensor = 4, ++ .offset = 0x100, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, ++ } ++}; ++ + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { + { + .cal_offset = { 0x04, 0x07 }, +@@ -1346,6 +1376,13 @@ static const struct lvts_ctrl_data mt819 + } + }; + ++static const struct lvts_data mt7988_lvts_ap_data = { ++ .lvts_ctrl = mt7988_lvts_ap_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt7988_lvts_ap_data_ctrl), ++ .temp_factor = LVTS_COEFF_A_MT7988, ++ .temp_offset = LVTS_COEFF_B_MT7988, ++}; ++ + static const struct lvts_data mt8195_lvts_mcu_data = { + .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), +@@ -1361,6 +1398,7 @@ static const struct lvts_data mt8195_lvt + }; + + static const struct of_device_id lvts_of_match[] = { ++ { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, + { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, + { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, + {}, diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch b/target/linux/mediatek/patches-6.6/830-v6.7-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch new file mode 100644 index 0000000000..5b212a2a37 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch @@ -0,0 +1,30 @@ +From fb1bbb5b63e4e3c788a978724749ced57d208054 Mon Sep 17 00:00:00 2001 +From: Minjie Du +Date: Thu, 21 Sep 2023 17:10:50 +0800 +Subject: [PATCH 38/42] thermal/drivers/mediatek/lvts_thermal: Fix error check + in lvts_debugfs_init() + +debugfs_create_dir() function returns an error value embedded in +the pointer (PTR_ERR). Evaluate the return value using IS_ERR +rather than checking for NULL. + +Signed-off-by: Minjie Du +Reviewed-by: Alexandre Mergnat +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230921091057.3812-1-duminjie@vivo.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -219,7 +219,7 @@ static int lvts_debugfs_init(struct devi + + sprintf(name, "controller%d", i); + dentry = debugfs_create_dir(name, lvts_td->dom_dentry); +- if (!dentry) ++ if (IS_ERR(dentry)) + continue; + + regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch b/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch new file mode 100644 index 0000000000..88f383c4ae --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch @@ -0,0 +1,33 @@ +From e6f43063f2fe9f08b34797bc6d223f7d63b01910 Mon Sep 17 00:00:00 2001 +From: Markus Schneider-Pargmann +Date: Mon, 18 Sep 2023 12:07:06 +0200 +Subject: [PATCH 39/42] thermal/drivers/mediatek: Fix probe for THERMAL_V2 + +Fix the probe function to call mtk_thermal_release_periodic_ts for +everything != MTK_THERMAL_V1. This was accidentally changed from V1 +to V2 in the original patch. + +Reported-by: Frank Wunderlich +Closes: https://lore.kernel.org/lkml/B0B3775B-B8D1-4284-814F-4F41EC22F532@public-files.de/ +Reported-by: Daniel Lezcano +Closes: https://lore.kernel.org/lkml/07a569b9-e691-64ea-dd65-3b49842af33d@linaro.org/ +Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks") +Signed-off-by: Markus Schneider-Pargmann +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20230918100706.1229239-1-msp@baylibre.com +--- + drivers/thermal/mediatek/auxadc_thermal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -1268,7 +1268,7 @@ static int mtk_thermal_probe(struct plat + + mtk_thermal_turn_on_buffer(mt, apmixed_base); + +- if (mt->conf->version != MTK_THERMAL_V2) ++ if (mt->conf->version != MTK_THERMAL_V1) + mtk_thermal_release_periodic_ts(mt, auxadc_base); + + if (mt->conf->version == MTK_THERMAL_V1) diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch b/target/linux/mediatek/patches-6.6/830-v6.7-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch new file mode 100644 index 0000000000..7b4b124b56 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch @@ -0,0 +1,83 @@ +From a1d874ef3376295ee8ed89b3b5315f4c840ff00b Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 17 Oct 2023 21:05:42 +0200 +Subject: [PATCH 40/42] thermal/drivers/mediatek/lvts_thermal: Add suspend and + resume +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add suspend and resume support to LVTS driver. + +Signed-off-by: Balsam CHIHI +[bero@baylibre.com: suspend/resume in noirq phase] +Co-developed-by: Bernhard Rosenkränzer +Signed-off-by: Bernhard Rosenkränzer +Reviewed-by: Matthias Brugger +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20231017190545.157282-3-bero@baylibre.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 37 +++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -1297,6 +1297,38 @@ static const struct lvts_ctrl_data mt798 + } + }; + ++static int lvts_suspend(struct device *dev) ++{ ++ struct lvts_domain *lvts_td; ++ int i; ++ ++ lvts_td = dev_get_drvdata(dev); ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) ++ lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); ++ ++ clk_disable_unprepare(lvts_td->clk); ++ ++ return 0; ++} ++ ++static int lvts_resume(struct device *dev) ++{ ++ struct lvts_domain *lvts_td; ++ int i, ret; ++ ++ lvts_td = dev_get_drvdata(dev); ++ ++ ret = clk_prepare_enable(lvts_td->clk); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) ++ lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true); ++ ++ return 0; ++} ++ + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { + { + .cal_offset = { 0x04, 0x07 }, +@@ -1405,12 +1437,17 @@ static const struct of_device_id lvts_of + }; + MODULE_DEVICE_TABLE(of, lvts_of_match); + ++static const struct dev_pm_ops lvts_pm_ops = { ++ NOIRQ_SYSTEM_SLEEP_PM_OPS(lvts_suspend, lvts_resume) ++}; ++ + static struct platform_driver lvts_driver = { + .probe = lvts_probe, + .remove_new = lvts_remove, + .driver = { + .name = "mtk-lvts-thermal", + .of_match_table = lvts_of_match, ++ .pm = &lvts_pm_ops, + }, + }; + module_platform_driver(lvts_driver); diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch b/target/linux/mediatek/patches-6.6/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch new file mode 100644 index 0000000000..c278168610 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch @@ -0,0 +1,49 @@ +From 0bb4937b58ab712f158588376dbac97f8e9df68e Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 17 Oct 2023 21:05:41 +0200 +Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal controller + definition for mt8192 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add LVTS thermal controller definition for MT8192. + +Signed-off-by: Balsam CHIHI +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Krzysztof Kozlowski +Signed-off-by: Bernhard Rosenkränzer +Reviewed-by: Matthias Brugger +Reviewed-by: Alexandre Mergnat +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20231017190545.157282-2-bero@baylibre.com +--- + .../thermal/mediatek,lvts-thermal.h | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h ++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h +@@ -35,4 +35,23 @@ + #define MT8195_AP_CAM0 15 + #define MT8195_AP_CAM1 16 + ++#define MT8192_MCU_BIG_CPU0 0 ++#define MT8192_MCU_BIG_CPU1 1 ++#define MT8192_MCU_BIG_CPU2 2 ++#define MT8192_MCU_BIG_CPU3 3 ++#define MT8192_MCU_LITTLE_CPU0 4 ++#define MT8192_MCU_LITTLE_CPU1 5 ++#define MT8192_MCU_LITTLE_CPU2 6 ++#define MT8192_MCU_LITTLE_CPU3 7 ++ ++#define MT8192_AP_VPU0 8 ++#define MT8192_AP_VPU1 9 ++#define MT8192_AP_GPU0 10 ++#define MT8192_AP_GPU1 11 ++#define MT8192_AP_INFRA 12 ++#define MT8192_AP_CAM 13 ++#define MT8192_AP_MD0 14 ++#define MT8192_AP_MD1 15 ++#define MT8192_AP_MD2 16 ++ + #endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch b/target/linux/mediatek/patches-6.6/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch new file mode 100644 index 0000000000..6d68a6cd57 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch @@ -0,0 +1,151 @@ +From 7d8b3864b38d881cf105328ff8569f47446811ad Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 17 Oct 2023 21:05:43 +0200 +Subject: [PATCH 41/42] thermal/drivers/mediatek/lvts_thermal: Add mt8192 + support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add LVTS Driver support for MT8192. + +Co-developed-by: Nícolas F. R. A. Prado +Signed-off-by: Nícolas F. R. A. Prado +Signed-off-by: Balsam CHIHI +Reviewed-by: Nícolas F. R. A. Prado +[bero@baylibre.com: cosmetic changes, rebase] +Signed-off-by: Bernhard Rosenkränzer +Reviewed-by: Matthias Brugger +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20231017190545.157282-4-bero@baylibre.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 95 +++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -92,6 +92,7 @@ + #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) + + #define LVTS_HW_SHUTDOWN_MT7988 105000 ++#define LVTS_HW_SHUTDOWN_MT8192 105000 + #define LVTS_HW_SHUTDOWN_MT8195 105000 + + #define LVTS_MINIMUM_THRESHOLD 20000 +@@ -1329,6 +1330,88 @@ static int lvts_resume(struct device *de + return 0; + } + ++static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { ++ { ++ .cal_offset = { 0x04, 0x08 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_MCU_BIG_CPU0 }, ++ { .dt_id = MT8192_MCU_BIG_CPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x0, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ .mode = LVTS_MSR_FILTERED_MODE, ++ }, ++ { ++ .cal_offset = { 0x0c, 0x10 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_MCU_BIG_CPU2 }, ++ { .dt_id = MT8192_MCU_BIG_CPU3 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x100, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ .mode = LVTS_MSR_FILTERED_MODE, ++ }, ++ { ++ .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_MCU_LITTLE_CPU0 }, ++ { .dt_id = MT8192_MCU_LITTLE_CPU1 }, ++ { .dt_id = MT8192_MCU_LITTLE_CPU2 }, ++ { .dt_id = MT8192_MCU_LITTLE_CPU3 } ++ }, ++ .num_lvts_sensor = 4, ++ .offset = 0x200, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ .mode = LVTS_MSR_FILTERED_MODE, ++ } ++}; ++ ++static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { ++ { ++ .cal_offset = { 0x24, 0x28 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_AP_VPU0 }, ++ { .dt_id = MT8192_AP_VPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x0, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ }, ++ { ++ .cal_offset = { 0x2c, 0x30 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_AP_GPU0 }, ++ { .dt_id = MT8192_AP_GPU1 } ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x100, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ }, ++ { ++ .cal_offset = { 0x34, 0x38 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_AP_INFRA }, ++ { .dt_id = MT8192_AP_CAM }, ++ }, ++ .num_lvts_sensor = 2, ++ .offset = 0x200, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ }, ++ { ++ .cal_offset = { 0x3c, 0x40, 0x44 }, ++ .lvts_sensor = { ++ { .dt_id = MT8192_AP_MD0 }, ++ { .dt_id = MT8192_AP_MD1 }, ++ { .dt_id = MT8192_AP_MD2 } ++ }, ++ .num_lvts_sensor = 3, ++ .offset = 0x300, ++ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, ++ } ++}; ++ + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { + { + .cal_offset = { 0x04, 0x07 }, +@@ -1415,6 +1498,16 @@ static const struct lvts_data mt7988_lvt + .temp_offset = LVTS_COEFF_B_MT7988, + }; + ++static const struct lvts_data mt8192_lvts_mcu_data = { ++ .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), ++}; ++ ++static const struct lvts_data mt8192_lvts_ap_data = { ++ .lvts_ctrl = mt8192_lvts_ap_data_ctrl, ++ .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), ++}; ++ + static const struct lvts_data mt8195_lvts_mcu_data = { + .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), +@@ -1431,6 +1524,8 @@ static const struct lvts_data mt8195_lvt + + static const struct of_device_id lvts_of_match[] = { + { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, ++ { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data }, ++ { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, + { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, + { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, + {}, diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch b/target/linux/mediatek/patches-6.6/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch new file mode 100644 index 0000000000..c20c0b5f2e --- /dev/null +++ b/target/linux/mediatek/patches-6.6/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch @@ -0,0 +1,70 @@ +From 5d126a3c87cf7964b28bacf3826eea4266265bce Mon Sep 17 00:00:00 2001 +From: Balsam CHIHI +Date: Tue, 17 Oct 2023 21:05:45 +0200 +Subject: [PATCH 42/42] thermal/drivers/mediatek/lvts_thermal: Update + calibration data documentation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Update LVTS calibration data documentation for mt8192 and mt8195. + +Signed-off-by: Balsam CHIHI +Reviewed-by: Nícolas F. R. A. Prado +[bero@baylibre.com: Fix issues pointed out by Nícolas F. R. A. Prado ] +Signed-off-by: Bernhard Rosenkränzer +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Alexandre Mergnat +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20231017190545.157282-6-bero@baylibre.com +--- + drivers/thermal/mediatek/lvts_thermal.c | 31 +++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -616,7 +616,34 @@ static int lvts_sensor_init(struct devic + * The efuse blob values follows the sensor enumeration per thermal + * controller. The decoding of the stream is as follow: + * +- * stream index map for MCU Domain : ++ * MT8192 : ++ * Stream index map for MCU Domain mt8192 : ++ * ++ * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> ++ * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B ++ * ++ * <-----sensor#2-----> <-----sensor#3-----> ++ * 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13 ++ * ++ * <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> ++ * 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23 ++ * ++ * Stream index map for AP Domain mt8192 : ++ * ++ * <-----sensor#0-----> <-----sensor#1-----> ++ * 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B ++ * ++ * <-----sensor#2-----> <-----sensor#3-----> ++ * 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33 ++ * ++ * <-----sensor#4-----> <-----sensor#5-----> ++ * 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B ++ * ++ * <-----sensor#6-----> <-----sensor#7-----> <-----sensor#8-----> ++ * 0x3C | 0x3D | 0x3E | 0x3F | 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 ++ * ++ * MT8195 : ++ * Stream index map for MCU Domain mt8195 : + * + * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> + * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 +@@ -627,7 +654,7 @@ static int lvts_sensor_init(struct devic + * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> + * 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 + * +- * stream index map for AP Domain : ++ * Stream index map for AP Domain mt8195 : + * + * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1-----> + * 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A diff --git a/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch b/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch new file mode 100644 index 0000000000..fc173646e0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch @@ -0,0 +1,59 @@ +From patchwork Thu Sep 7 11:20:18 2023 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Frank Wunderlich +X-Patchwork-Id: 13376356 +From: Frank Wunderlich +To: linux-mediatek@lists.infradead.org +Subject: [PATCH] thermal/drivers/mediatek: Fix control buffer enablement on + MT7896 +Date: Thu, 7 Sep 2023 13:20:18 +0200 +Message-Id: <20230907112018.52811-1-linux@fw-web.de> +X-Mailer: git-send-email 2.34.1 +MIME-Version: 1.0 +X-Mail-ID: e7eeb8e1-00de-41f6-a5df-ce2e9164136e +X-BeenThere: linux-mediatek@lists.infradead.org +X-Mailman-Version: 2.1.34 +Precedence: list +List-Id: +Cc: Daniel Lezcano , + "Rafael J. Wysocki" , linux-pm@vger.kernel.org, + Amit Kucheria , Daniel Golle , + stable@vger.kernel.org, linux-kernel@vger.kernel.org, + Matthias Brugger , Zhang Rui , + linux-arm-kernel@lists.infradead.org, + AngeloGioacchino Del Regno +Sender: "Linux-mediatek" + +From: Frank Wunderlich + +Reading thermal sensor on mt7986 devices returns invalid temperature: + +bpi-r3 ~ # cat /sys/class/thermal/thermal_zone0/temp + -274000 + +Fix this by adding missing members in mtk_thermal_data struct which were +used in mtk_thermal_turn_on_buffer after commit 33140e668b10. + +Cc: stable@vger.kernel.org +Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks") +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Markus Schneider-Pargmann +--- + drivers/thermal/mediatek/auxadc_thermal.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/thermal/mediatek/auxadc_thermal.c ++++ b/drivers/thermal/mediatek/auxadc_thermal.c +@@ -691,6 +691,9 @@ static const struct mtk_thermal_data mt7 + .adcpnp = mt7986_adcpnp, + .sensor_mux_values = mt7986_mux_values, + .version = MTK_THERMAL_V3, ++ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1, ++ .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3), ++ .apmixed_buffer_ctl_set = BIT(0), + }; + + static bool mtk_thermal_temp_is_valid(int temp) diff --git a/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch new file mode 100644 index 0000000000..4c398c59f9 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch @@ -0,0 +1,44 @@ +From 11f9a0f4e51887ad7b4a2898a368fcd0c2984e89 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 9 Oct 2022 12:16:31 +0200 +Subject: [PATCH 12/16] i2c: mediatek: add mt7986 support + +Add i2c support for MT7986 SoC. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Wolfram Sang +--- + drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible m + .max_dma_support = 33, + }; + ++static const struct mtk_i2c_compatible mt7986_compat = { ++ .quirks = &mt7622_i2c_quirks, ++ .regs = mt_i2c_regs_v1, ++ .pmic_i2c = 0, ++ .dcm = 1, ++ .auto_restart = 1, ++ .aux_len_reg = 1, ++ .timing_adjust = 0, ++ .dma_sync = 1, ++ .ltiming_adjust = 0, ++ .max_dma_support = 32, ++}; ++ + static const struct mtk_i2c_compatible mt8173_compat = { + .regs = mt_i2c_regs_v1, + .pmic_i2c = 0, +@@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c + { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, + { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, + { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, ++ { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, + { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, + { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, + { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, diff --git a/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch new file mode 100644 index 0000000000..18c66cdac5 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch @@ -0,0 +1,42 @@ +From 98204ccafd45a8a6109ff2d60e2c179b95d92578 Mon Sep 17 00:00:00 2001 +From: ye xingchen +Date: Thu, 19 Jan 2023 17:19:58 +0800 +Subject: [PATCH 13/16] i2c: mt65xx: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: ye xingchen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Wolfram Sang +--- + drivers/i2c/busses/i2c-mt65xx.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform + { + int ret = 0; + struct mtk_i2c *i2c; +- struct resource *res; + int i, irq, speed_clk; + + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res); ++ i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); + if (IS_ERR(i2c->pdmabase)) + return PTR_ERR(i2c->pdmabase); + diff --git a/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch new file mode 100644 index 0000000000..d000d53522 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch @@ -0,0 +1,33 @@ +From 8106fa2e0ae6082833fe1df97829c46c0183eaea Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Sat, 11 Mar 2023 12:16:54 +0100 +Subject: [PATCH 14/16] i2c: mt65xx: drop of_match_ptr for ID table +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The driver can match only via the DT table so the table should be always +used and the of_match_ptr does not have any sense (this also allows ACPI +matching via PRP0001, even though it might not be relevant here). + + drivers/i2c/busses/i2c-mt65xx.c:514:34: error: ‘mtk_i2c_of_match’ defined but not used [-Werror=unused-const-variable=] + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Guenter Roeck +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Wolfram Sang +--- + drivers/i2c/busses/i2c-mt65xx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -1546,7 +1546,7 @@ static struct platform_driver mtk_i2c_dr + .driver = { + .name = I2C_DRV_NAME, + .pm = &mtk_i2c_pm, +- .of_match_table = of_match_ptr(mtk_i2c_of_match), ++ .of_match_table = mtk_i2c_of_match, + }, + }; + diff --git a/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch new file mode 100644 index 0000000000..e0973741e2 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch @@ -0,0 +1,47 @@ +From f69f3d662ba3bf999c36d9ac1e684540c4487bc3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 10 Apr 2023 17:19:38 +0100 +Subject: [PATCH 15/16] i2c: mediatek: add support for MT7981 SoC + +Add support for the I2C units found in the MediaTek MT7981 and MT7988 +SoCs. Just like other recent MediaTek I2C units that also uses v3 +register offsets (which differ from v2 only by OFFSET_SLAVE_ADDR being +0x94 instead of 0x4). + +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Alexandre Mergnat +Signed-off-by: Wolfram Sang +--- + drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible m + .max_dma_support = 33, + }; + ++static const struct mtk_i2c_compatible mt7981_compat = { ++ .regs = mt_i2c_regs_v3, ++ .pmic_i2c = 0, ++ .dcm = 0, ++ .auto_restart = 1, ++ .aux_len_reg = 1, ++ .timing_adjust = 1, ++ .dma_sync = 1, ++ .ltiming_adjust = 1, ++ .max_dma_support = 33 ++}; ++ + static const struct mtk_i2c_compatible mt7986_compat = { + .quirks = &mt7622_i2c_quirks, + .regs = mt_i2c_regs_v1, +@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c + { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, + { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, + { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, ++ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat }, + { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, + { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, + { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, diff --git a/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch b/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch new file mode 100644 index 0000000000..69cc155d8d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch @@ -0,0 +1,45 @@ +From 3bf827929a44c17bfb1bf1000b143c02ce26a929 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 26 Aug 2023 21:56:51 +0100 +Subject: [PATCH] i2c: mt65xx: allow optional pmic clock + +Using the I2C host controller on the MT7981 SoC requires 4 clocks to +be enabled. One of them, the pmic clk, is only enabled in case +'mediatek,have-pmic' is also set which has other consequences which +are not desired in this case. + +Allow defining a pmic clk even in case the 'mediatek,have-pmic' propterty +is not present and the bus is not used to connect to a pmic, but may +still require to enable the pmic clock. + +Signed-off-by: Daniel Golle +--- + drivers/i2c/busses/i2c-mt65xx.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -1444,15 +1444,19 @@ static int mtk_i2c_probe(struct platform + if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk)) + return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk); + ++ i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get_optional(&pdev->dev, "pmic"); ++ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) { ++ dev_err(&pdev->dev, "cannot get pmic clock\n"); ++ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk); ++ } ++ + if (i2c->have_pmic) { +- i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic"); +- if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) { ++ if (!i2c->clocks[I2C_MT65XX_CLK_PMIC].clk) { + dev_err(&pdev->dev, "cannot get pmic clock\n"); +- return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk); ++ return -ENODEV; + } + speed_clk = I2C_MT65XX_CLK_PMIC; + } else { +- i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL; + speed_clk = I2C_MT65XX_CLK_MAIN; + } + diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch b/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch new file mode 100644 index 0000000000..9607eec821 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch @@ -0,0 +1,269 @@ +From d35469096915f2551ed1d26da1ab12ff500fc963 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:33 +0800 +Subject: [PATCH 1/9] ASoC: mediatek: mt7986: add common header + +Add header files for register definition and structure. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-2-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/mt7986/mt7986-afe-common.h | 49 +++++ + sound/soc/mediatek/mt7986/mt7986-reg.h | 196 ++++++++++++++++++ + 2 files changed, 245 insertions(+) + create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-common.h + create mode 100644 sound/soc/mediatek/mt7986/mt7986-reg.h + +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/mt7986-afe-common.h +@@ -0,0 +1,49 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * mt7986-afe-common.h -- MediaTek 7986 audio driver definitions ++ * ++ * Copyright (c) 2023 MediaTek Inc. ++ * Authors: Vic Wu ++ * Maso Huang ++ */ ++ ++#ifndef _MT_7986_AFE_COMMON_H_ ++#define _MT_7986_AFE_COMMON_H_ ++ ++#include ++#include ++#include ++#include ++#include "../common/mtk-base-afe.h" ++ ++enum { ++ MT7986_MEMIF_DL1, ++ MT7986_MEMIF_VUL12, ++ MT7986_MEMIF_NUM, ++ MT7986_DAI_ETDM = MT7986_MEMIF_NUM, ++ MT7986_DAI_NUM, ++}; ++ ++enum { ++ MT7986_IRQ_0, ++ MT7986_IRQ_1, ++ MT7986_IRQ_2, ++ MT7986_IRQ_NUM, ++}; ++ ++struct mt7986_afe_private { ++ struct clk_bulk_data *clks; ++ int num_clks; ++ ++ int pm_runtime_bypass_reg_ctl; ++ ++ /* dai */ ++ void *dai_priv[MT7986_DAI_NUM]; ++}; ++ ++unsigned int mt7986_afe_rate_transform(struct device *dev, ++ unsigned int rate); ++ ++/* dai register */ ++int mt7986_dai_etdm_register(struct mtk_base_afe *afe); ++#endif +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/mt7986-reg.h +@@ -0,0 +1,196 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * mt7986-reg.h -- MediaTek 7986 audio driver reg definition ++ * ++ * Copyright (c) 2023 MediaTek Inc. ++ * Authors: Vic Wu ++ * Maso Huang ++ */ ++ ++#ifndef _MT7986_REG_H_ ++#define _MT7986_REG_H_ ++ ++#define AUDIO_TOP_CON2 0x0008 ++#define AUDIO_TOP_CON4 0x0010 ++#define AUDIO_ENGEN_CON0 0x0014 ++#define AFE_IRQ_MCU_EN 0x0100 ++#define AFE_IRQ_MCU_STATUS 0x0120 ++#define AFE_IRQ_MCU_CLR 0x0128 ++#define AFE_IRQ0_MCU_CFG0 0x0140 ++#define AFE_IRQ0_MCU_CFG1 0x0144 ++#define AFE_IRQ1_MCU_CFG0 0x0148 ++#define AFE_IRQ1_MCU_CFG1 0x014c ++#define AFE_IRQ2_MCU_CFG0 0x0150 ++#define AFE_IRQ2_MCU_CFG1 0x0154 ++#define ETDM_IN5_CON0 0x13f0 ++#define ETDM_IN5_CON1 0x13f4 ++#define ETDM_IN5_CON2 0x13f8 ++#define ETDM_IN5_CON3 0x13fc ++#define ETDM_IN5_CON4 0x1400 ++#define ETDM_OUT5_CON0 0x1570 ++#define ETDM_OUT5_CON4 0x1580 ++#define ETDM_OUT5_CON5 0x1584 ++#define ETDM_4_7_COWORK_CON0 0x15e0 ++#define ETDM_4_7_COWORK_CON1 0x15e4 ++#define AFE_CONN018_1 0x1b44 ++#define AFE_CONN018_4 0x1b50 ++#define AFE_CONN019_1 0x1b64 ++#define AFE_CONN019_4 0x1b70 ++#define AFE_CONN124_1 0x2884 ++#define AFE_CONN124_4 0x2890 ++#define AFE_CONN125_1 0x28a4 ++#define AFE_CONN125_4 0x28b0 ++#define AFE_CONN_RS_0 0x3920 ++#define AFE_CONN_RS_3 0x392c ++#define AFE_CONN_16BIT_0 0x3960 ++#define AFE_CONN_16BIT_3 0x396c ++#define AFE_CONN_24BIT_0 0x3980 ++#define AFE_CONN_24BIT_3 0x398c ++#define AFE_MEMIF_CON0 0x3d98 ++#define AFE_MEMIF_RD_MON 0x3da0 ++#define AFE_MEMIF_WR_MON 0x3da4 ++#define AFE_DL0_BASE_MSB 0x3e40 ++#define AFE_DL0_BASE 0x3e44 ++#define AFE_DL0_CUR_MSB 0x3e48 ++#define AFE_DL0_CUR 0x3e4c ++#define AFE_DL0_END_MSB 0x3e50 ++#define AFE_DL0_END 0x3e54 ++#define AFE_DL0_RCH_MON 0x3e58 ++#define AFE_DL0_LCH_MON 0x3e5c ++#define AFE_DL0_CON0 0x3e60 ++#define AFE_VUL0_BASE_MSB 0x4220 ++#define AFE_VUL0_BASE 0x4224 ++#define AFE_VUL0_CUR_MSB 0x4228 ++#define AFE_VUL0_CUR 0x422c ++#define AFE_VUL0_END_MSB 0x4230 ++#define AFE_VUL0_END 0x4234 ++#define AFE_VUL0_CON0 0x4238 ++ ++#define AFE_MAX_REGISTER AFE_VUL0_CON0 ++#define AFE_IRQ_STATUS_BITS 0x7 ++#define AFE_IRQ_CNT_SHIFT 0 ++#define AFE_IRQ_CNT_MASK 0xffffff ++ ++/* AUDIO_TOP_CON2 */ ++#define CLK_OUT5_PDN BIT(14) ++#define CLK_OUT5_PDN_MASK BIT(14) ++#define CLK_IN5_PDN BIT(7) ++#define CLK_IN5_PDN_MASK BIT(7) ++ ++/* AUDIO_TOP_CON4 */ ++#define PDN_APLL_TUNER2 BIT(12) ++#define PDN_APLL_TUNER2_MASK BIT(12) ++ ++/* AUDIO_ENGEN_CON0 */ ++#define AUD_APLL2_EN BIT(3) ++#define AUD_APLL2_EN_MASK BIT(3) ++#define AUD_26M_EN BIT(0) ++#define AUD_26M_EN_MASK BIT(0) ++ ++/* AFE_DL0_CON0 */ ++#define DL0_ON_SFT 28 ++#define DL0_ON_MASK 0x1 ++#define DL0_ON_MASK_SFT BIT(28) ++#define DL0_MINLEN_SFT 20 ++#define DL0_MINLEN_MASK 0xf ++#define DL0_MINLEN_MASK_SFT (0xf << 20) ++#define DL0_MODE_SFT 8 ++#define DL0_MODE_MASK 0x1f ++#define DL0_MODE_MASK_SFT (0x1f << 8) ++#define DL0_PBUF_SIZE_SFT 5 ++#define DL0_PBUF_SIZE_MASK 0x3 ++#define DL0_PBUF_SIZE_MASK_SFT (0x3 << 5) ++#define DL0_MONO_SFT 4 ++#define DL0_MONO_MASK 0x1 ++#define DL0_MONO_MASK_SFT BIT(4) ++#define DL0_HALIGN_SFT 2 ++#define DL0_HALIGN_MASK 0x1 ++#define DL0_HALIGN_MASK_SFT BIT(2) ++#define DL0_HD_MODE_SFT 0 ++#define DL0_HD_MODE_MASK 0x3 ++#define DL0_HD_MODE_MASK_SFT (0x3 << 0) ++ ++/* AFE_VUL0_CON0 */ ++#define VUL0_ON_SFT 28 ++#define VUL0_ON_MASK 0x1 ++#define VUL0_ON_MASK_SFT BIT(28) ++#define VUL0_MODE_SFT 8 ++#define VUL0_MODE_MASK 0x1f ++#define VUL0_MODE_MASK_SFT (0x1f << 8) ++#define VUL0_MONO_SFT 4 ++#define VUL0_MONO_MASK 0x1 ++#define VUL0_MONO_MASK_SFT BIT(4) ++#define VUL0_HALIGN_SFT 2 ++#define VUL0_HALIGN_MASK 0x1 ++#define VUL0_HALIGN_MASK_SFT BIT(2) ++#define VUL0_HD_MODE_SFT 0 ++#define VUL0_HD_MODE_MASK 0x3 ++#define VUL0_HD_MODE_MASK_SFT (0x3 << 0) ++ ++/* AFE_IRQ_MCU_CON */ ++#define IRQ_MCU_MODE_SFT 4 ++#define IRQ_MCU_MODE_MASK 0x1f ++#define IRQ_MCU_MODE_MASK_SFT (0x1f << 4) ++#define IRQ_MCU_ON_SFT 0 ++#define IRQ_MCU_ON_MASK 0x1 ++#define IRQ_MCU_ON_MASK_SFT BIT(0) ++#define IRQ0_MCU_CLR_SFT 0 ++#define IRQ0_MCU_CLR_MASK 0x1 ++#define IRQ0_MCU_CLR_MASK_SFT BIT(0) ++#define IRQ1_MCU_CLR_SFT 1 ++#define IRQ1_MCU_CLR_MASK 0x1 ++#define IRQ1_MCU_CLR_MASK_SFT BIT(1) ++#define IRQ2_MCU_CLR_SFT 2 ++#define IRQ2_MCU_CLR_MASK 0x1 ++#define IRQ2_MCU_CLR_MASK_SFT BIT(2) ++ ++/* ETDM_IN5_CON2 */ ++#define IN_CLK_SRC(x) ((x) << 10) ++#define IN_CLK_SRC_SFT 10 ++#define IN_CLK_SRC_MASK GENMASK(12, 10) ++ ++/* ETDM_IN5_CON3 */ ++#define IN_SEL_FS(x) ((x) << 26) ++#define IN_SEL_FS_SFT 26 ++#define IN_SEL_FS_MASK GENMASK(30, 26) ++ ++/* ETDM_IN5_CON4 */ ++#define IN_RELATCH(x) ((x) << 20) ++#define IN_RELATCH_SFT 20 ++#define IN_RELATCH_MASK GENMASK(24, 20) ++#define IN_CLK_INV BIT(18) ++#define IN_CLK_INV_MASK BIT(18) ++ ++/* ETDM_IN5_CON0 & ETDM_OUT5_CON0 */ ++#define RELATCH_SRC_MASK GENMASK(30, 28) ++#define ETDM_CH_NUM_MASK GENMASK(27, 23) ++#define ETDM_WRD_LEN_MASK GENMASK(20, 16) ++#define ETDM_BIT_LEN_MASK GENMASK(15, 11) ++#define ETDM_FMT_MASK GENMASK(8, 6) ++#define ETDM_SYNC BIT(1) ++#define ETDM_SYNC_MASK BIT(1) ++#define ETDM_EN BIT(0) ++#define ETDM_EN_MASK BIT(0) ++ ++/* ETDM_OUT5_CON4 */ ++#define OUT_RELATCH(x) ((x) << 24) ++#define OUT_RELATCH_SFT 24 ++#define OUT_RELATCH_MASK GENMASK(28, 24) ++#define OUT_CLK_SRC(x) ((x) << 6) ++#define OUT_CLK_SRC_SFT 6 ++#define OUT_CLK_SRC_MASK GENMASK(8, 6) ++#define OUT_SEL_FS(x) (x) ++#define OUT_SEL_FS_SFT 0 ++#define OUT_SEL_FS_MASK GENMASK(4, 0) ++ ++/* ETDM_OUT5_CON5 */ ++#define ETDM_CLK_DIV BIT(12) ++#define ETDM_CLK_DIV_MASK BIT(12) ++#define OUT_CLK_INV BIT(9) ++#define OUT_CLK_INV_MASK BIT(9) ++ ++/* ETDM_4_7_COWORK_CON0 */ ++#define OUT_SEL(x) ((x) << 12) ++#define OUT_SEL_SFT 12 ++#define OUT_SEL_MASK GENMASK(15, 12) ++#endif diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch b/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch new file mode 100644 index 0000000000..f22add580f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch @@ -0,0 +1,430 @@ +From 948a288897015fb3ee63b3f720b396b590c17fd7 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:34 +0800 +Subject: [PATCH 2/9] ASoC: mediatek: mt7986: support etdm in platform driver + +Add mt7986 etdm dai driver support. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-3-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/mt7986/mt7986-dai-etdm.c | 411 ++++++++++++++++++++ + 1 file changed, 411 insertions(+) + create mode 100644 sound/soc/mediatek/mt7986/mt7986-dai-etdm.c + +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c +@@ -0,0 +1,411 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MediaTek ALSA SoC Audio DAI eTDM Control ++ * ++ * Copyright (c) 2023 MediaTek Inc. ++ * Authors: Vic Wu ++ * Maso Huang ++ */ ++ ++#include ++#include ++#include ++#include ++#include "mt7986-afe-common.h" ++#include "mt7986-reg.h" ++ ++#define HOPPING_CLK 0 ++#define APLL_CLK 1 ++#define MTK_DAI_ETDM_FORMAT_I2S 0 ++#define MTK_DAI_ETDM_FORMAT_DSPA 4 ++#define MTK_DAI_ETDM_FORMAT_DSPB 5 ++ ++enum { ++ MTK_ETDM_RATE_8K = 0, ++ MTK_ETDM_RATE_12K = 1, ++ MTK_ETDM_RATE_16K = 2, ++ MTK_ETDM_RATE_24K = 3, ++ MTK_ETDM_RATE_32K = 4, ++ MTK_ETDM_RATE_48K = 5, ++ MTK_ETDM_RATE_96K = 7, ++ MTK_ETDM_RATE_192K = 9, ++ MTK_ETDM_RATE_11K = 16, ++ MTK_ETDM_RATE_22K = 17, ++ MTK_ETDM_RATE_44K = 18, ++ MTK_ETDM_RATE_88K = 19, ++ MTK_ETDM_RATE_176K = 20, ++}; ++ ++struct mtk_dai_etdm_priv { ++ bool bck_inv; ++ bool lrck_inv; ++ bool slave_mode; ++ unsigned int format; ++}; ++ ++static unsigned int mt7986_etdm_rate_transform(struct device *dev, unsigned int rate) ++{ ++ switch (rate) { ++ case 8000: ++ return MTK_ETDM_RATE_8K; ++ case 11025: ++ return MTK_ETDM_RATE_11K; ++ case 12000: ++ return MTK_ETDM_RATE_12K; ++ case 16000: ++ return MTK_ETDM_RATE_16K; ++ case 22050: ++ return MTK_ETDM_RATE_22K; ++ case 24000: ++ return MTK_ETDM_RATE_24K; ++ case 32000: ++ return MTK_ETDM_RATE_32K; ++ case 44100: ++ return MTK_ETDM_RATE_44K; ++ case 48000: ++ return MTK_ETDM_RATE_48K; ++ case 88200: ++ return MTK_ETDM_RATE_88K; ++ case 96000: ++ return MTK_ETDM_RATE_96K; ++ case 176400: ++ return MTK_ETDM_RATE_176K; ++ case 192000: ++ return MTK_ETDM_RATE_192K; ++ default: ++ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", ++ __func__, rate, MTK_ETDM_RATE_48K); ++ return MTK_ETDM_RATE_48K; ++ } ++} ++ ++static int get_etdm_wlen(unsigned int bitwidth) ++{ ++ return bitwidth <= 16 ? 16 : 32; ++} ++ ++/* dai component */ ++/* interconnection */ ++ ++static const struct snd_kcontrol_new o124_mix[] = { ++ SOC_DAPM_SINGLE_AUTODISABLE("I032_Switch", AFE_CONN124_1, 0, 1, 0), ++}; ++ ++static const struct snd_kcontrol_new o125_mix[] = { ++ SOC_DAPM_SINGLE_AUTODISABLE("I033_Switch", AFE_CONN125_1, 1, 1, 0), ++}; ++ ++static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = { ++ ++ /* DL */ ++ SND_SOC_DAPM_MIXER("I150", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_MIXER("I151", SND_SOC_NOPM, 0, 0, NULL, 0), ++ /* UL */ ++ SND_SOC_DAPM_MIXER("O124", SND_SOC_NOPM, 0, 0, o124_mix, ARRAY_SIZE(o124_mix)), ++ SND_SOC_DAPM_MIXER("O125", SND_SOC_NOPM, 0, 0, o125_mix, ARRAY_SIZE(o125_mix)), ++}; ++ ++static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { ++ {"I150", NULL, "ETDM Capture"}, ++ {"I151", NULL, "ETDM Capture"}, ++ {"ETDM Playback", NULL, "O124"}, ++ {"ETDM Playback", NULL, "O125"}, ++ {"O124", "I032_Switch", "I032"}, ++ {"O125", "I033_Switch", "I033"}, ++}; ++ ++/* dai ops */ ++static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); ++ if (ret) ++ return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); ++ ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, 0); ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, 0); ++ ++ return 0; ++} ++ ++static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, ++ CLK_OUT5_PDN); ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, ++ CLK_IN5_PDN); ++ ++ clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); ++} ++ ++static unsigned int get_etdm_ch_fixup(unsigned int channels) ++{ ++ if (channels > 16) ++ return 24; ++ else if (channels > 8) ++ return 16; ++ else if (channels > 4) ++ return 8; ++ else if (channels > 2) ++ return 4; ++ else ++ return 2; ++} ++ ++static int mtk_dai_etdm_config(struct mtk_base_afe *afe, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai, ++ int stream) ++{ ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; ++ unsigned int rate = params_rate(params); ++ unsigned int etdm_rate = mt7986_etdm_rate_transform(afe->dev, rate); ++ unsigned int afe_rate = mt7986_afe_rate_transform(afe->dev, rate); ++ unsigned int channels = params_channels(params); ++ unsigned int bit_width = params_width(params); ++ unsigned int wlen = get_etdm_wlen(bit_width); ++ unsigned int val = 0; ++ unsigned int mask = 0; ++ ++ dev_dbg(afe->dev, "%s(), stream %d, rate %u, bitwidth %u\n", ++ __func__, stream, rate, bit_width); ++ ++ /* CON0 */ ++ mask |= ETDM_BIT_LEN_MASK; ++ val |= FIELD_PREP(ETDM_BIT_LEN_MASK, bit_width - 1); ++ mask |= ETDM_WRD_LEN_MASK; ++ val |= FIELD_PREP(ETDM_WRD_LEN_MASK, wlen - 1); ++ mask |= ETDM_FMT_MASK; ++ val |= FIELD_PREP(ETDM_FMT_MASK, etdm_data->format); ++ mask |= ETDM_CH_NUM_MASK; ++ val |= FIELD_PREP(ETDM_CH_NUM_MASK, get_etdm_ch_fixup(channels) - 1); ++ mask |= RELATCH_SRC_MASK; ++ val |= FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK); ++ ++ switch (stream) { ++ case SNDRV_PCM_STREAM_PLAYBACK: ++ /* set ETDM_OUT5_CON0 */ ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, mask, val); ++ ++ /* set ETDM_OUT5_CON4 */ ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, ++ OUT_RELATCH_MASK, OUT_RELATCH(afe_rate)); ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, ++ OUT_CLK_SRC_MASK, OUT_CLK_SRC(APLL_CLK)); ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, ++ OUT_SEL_FS_MASK, OUT_SEL_FS(etdm_rate)); ++ ++ /* set ETDM_OUT5_CON5 */ ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON5, ++ ETDM_CLK_DIV_MASK, ETDM_CLK_DIV); ++ break; ++ case SNDRV_PCM_STREAM_CAPTURE: ++ /* set ETDM_IN5_CON0 */ ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, mask, val); ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ++ ETDM_SYNC_MASK, ETDM_SYNC); ++ ++ /* set ETDM_IN5_CON2 */ ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON2, ++ IN_CLK_SRC_MASK, IN_CLK_SRC(APLL_CLK)); ++ ++ /* set ETDM_IN5_CON3 */ ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON3, ++ IN_SEL_FS_MASK, IN_SEL_FS(etdm_rate)); ++ ++ /* set ETDM_IN5_CON4 */ ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON4, ++ IN_RELATCH_MASK, IN_RELATCH(afe_rate)); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); ++ ++ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK); ++ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE); ++ ++ return 0; ++} ++ ++static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); ++ ++ dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id); ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, ++ ETDM_EN); ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, ++ ETDM_EN); ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, ++ 0); ++ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, ++ 0); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++{ ++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ struct mtk_dai_etdm_priv *etdm_data; ++ void *priv_data; ++ ++ switch (dai->id) { ++ case MT7986_DAI_ETDM: ++ break; ++ default: ++ dev_warn(afe->dev, "%s(), id %d not support\n", ++ __func__, dai->id); ++ return -EINVAL; ++ } ++ ++ priv_data = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_etdm_priv), ++ GFP_KERNEL); ++ if (!priv_data) ++ return -ENOMEM; ++ ++ afe_priv->dai_priv[dai->id] = priv_data; ++ etdm_data = afe_priv->dai_priv[dai->id]; ++ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; ++ break; ++ case SND_SOC_DAIFMT_DSP_A: ++ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA; ++ break; ++ case SND_SOC_DAIFMT_DSP_B: ++ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ etdm_data->bck_inv = false; ++ etdm_data->lrck_inv = false; ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ etdm_data->bck_inv = false; ++ etdm_data->lrck_inv = true; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ etdm_data->bck_inv = true; ++ etdm_data->lrck_inv = false; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ etdm_data->bck_inv = true; ++ etdm_data->lrck_inv = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ etdm_data->slave_mode = true; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ etdm_data->slave_mode = false; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { ++ .startup = mtk_dai_etdm_startup, ++ .shutdown = mtk_dai_etdm_shutdown, ++ .hw_params = mtk_dai_etdm_hw_params, ++ .trigger = mtk_dai_etdm_trigger, ++ .set_fmt = mtk_dai_etdm_set_fmt, ++}; ++ ++/* dai driver */ ++#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ ++ SNDRV_PCM_RATE_88200 |\ ++ SNDRV_PCM_RATE_96000 |\ ++ SNDRV_PCM_RATE_176400 |\ ++ SNDRV_PCM_RATE_192000) ++ ++#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE |\ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = { ++ { ++ .name = "ETDM", ++ .id = MT7986_DAI_ETDM, ++ .capture = { ++ .stream_name = "ETDM Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = MTK_ETDM_RATES, ++ .formats = MTK_ETDM_FORMATS, ++ }, ++ .playback = { ++ .stream_name = "ETDM Playback", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = MTK_ETDM_RATES, ++ .formats = MTK_ETDM_FORMATS, ++ }, ++ .ops = &mtk_dai_etdm_ops, ++ .symmetric_rate = 1, ++ .symmetric_sample_bits = 1, ++ }, ++}; ++ ++int mt7986_dai_etdm_register(struct mtk_base_afe *afe) ++{ ++ struct mtk_base_afe_dai *dai; ++ ++ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); ++ if (!dai) ++ return -ENOMEM; ++ ++ list_add(&dai->list, &afe->sub_dais); ++ ++ dai->dai_drivers = mtk_dai_etdm_driver; ++ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver); ++ ++ dai->dapm_widgets = mtk_dai_etdm_widgets; ++ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets); ++ dai->dapm_routes = mtk_dai_etdm_routes; ++ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes); ++ ++ return 0; ++} diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch b/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch new file mode 100644 index 0000000000..b899b963d2 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch @@ -0,0 +1,685 @@ +From fc7776dee86bc07d22820a904760a95f49a2f12e Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:35 +0800 +Subject: [PATCH 3/9] ASoC: mediatek: mt7986: add platform driver + +Add mt7986 platform driver. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-4-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/Kconfig | 10 + + sound/soc/mediatek/Makefile | 1 + + sound/soc/mediatek/mt7986/Makefile | 8 + + sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 622 +++++++++++++++++++++ + 4 files changed, 641 insertions(+) + create mode 100644 sound/soc/mediatek/mt7986/Makefile + create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-pcm.c + +--- a/sound/soc/mediatek/Kconfig ++++ b/sound/soc/mediatek/Kconfig +@@ -54,6 +54,16 @@ config SND_SOC_MT6797_MT6351 + Select Y if you have such device. + If unsure select "N". + ++config SND_SOC_MT7986 ++ tristate "ASoC support for Mediatek MT7986 chip" ++ depends on ARCH_MEDIATEK ++ select SND_SOC_MEDIATEK ++ help ++ This adds ASoC platform driver support for MediaTek MT7986 chip ++ that can be used with other codecs. ++ Select Y if you have such device. ++ If unsure select "N". ++ + config SND_SOC_MT8173 + tristate "ASoC support for Mediatek MT8173 chip" + depends on ARCH_MEDIATEK +--- a/sound/soc/mediatek/Makefile ++++ b/sound/soc/mediatek/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_SND_SOC_MEDIATEK) += common/ + obj-$(CONFIG_SND_SOC_MT2701) += mt2701/ + obj-$(CONFIG_SND_SOC_MT6797) += mt6797/ ++obj-$(CONFIG_SND_SOC_MT7986) += mt7986/ + obj-$(CONFIG_SND_SOC_MT8173) += mt8173/ + obj-$(CONFIG_SND_SOC_MT8183) += mt8183/ + obj-$(CONFIG_SND_SOC_MT8186) += mt8186/ +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++# platform driver ++snd-soc-mt7986-afe-objs := \ ++ mt7986-afe-pcm.o \ ++ mt7986-dai-etdm.o ++ ++obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c +@@ -0,0 +1,622 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MediaTek ALSA SoC AFE platform driver for MT7986 ++ * ++ * Copyright (c) 2023 MediaTek Inc. ++ * Authors: Vic Wu ++ * Maso Huang ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mt7986-afe-common.h" ++#include "mt7986-reg.h" ++#include "../common/mtk-afe-platform-driver.h" ++#include "../common/mtk-afe-fe-dai.h" ++ ++enum { ++ MTK_AFE_RATE_8K = 0, ++ MTK_AFE_RATE_11K = 1, ++ MTK_AFE_RATE_12K = 2, ++ MTK_AFE_RATE_16K = 4, ++ MTK_AFE_RATE_22K = 5, ++ MTK_AFE_RATE_24K = 6, ++ MTK_AFE_RATE_32K = 8, ++ MTK_AFE_RATE_44K = 9, ++ MTK_AFE_RATE_48K = 10, ++ MTK_AFE_RATE_88K = 13, ++ MTK_AFE_RATE_96K = 14, ++ MTK_AFE_RATE_176K = 17, ++ MTK_AFE_RATE_192K = 18, ++}; ++ ++enum { ++ CLK_INFRA_AUD_BUS_CK = 0, ++ CLK_INFRA_AUD_26M_CK, ++ CLK_INFRA_AUD_L_CK, ++ CLK_INFRA_AUD_AUD_CK, ++ CLK_INFRA_AUD_EG2_CK, ++ CLK_NUM ++}; ++ ++static const char *aud_clks[CLK_NUM] = { ++ [CLK_INFRA_AUD_BUS_CK] = "aud_bus_ck", ++ [CLK_INFRA_AUD_26M_CK] = "aud_26m_ck", ++ [CLK_INFRA_AUD_L_CK] = "aud_l_ck", ++ [CLK_INFRA_AUD_AUD_CK] = "aud_aud_ck", ++ [CLK_INFRA_AUD_EG2_CK] = "aud_eg2_ck", ++}; ++ ++unsigned int mt7986_afe_rate_transform(struct device *dev, unsigned int rate) ++{ ++ switch (rate) { ++ case 8000: ++ return MTK_AFE_RATE_8K; ++ case 11025: ++ return MTK_AFE_RATE_11K; ++ case 12000: ++ return MTK_AFE_RATE_12K; ++ case 16000: ++ return MTK_AFE_RATE_16K; ++ case 22050: ++ return MTK_AFE_RATE_22K; ++ case 24000: ++ return MTK_AFE_RATE_24K; ++ case 32000: ++ return MTK_AFE_RATE_32K; ++ case 44100: ++ return MTK_AFE_RATE_44K; ++ case 48000: ++ return MTK_AFE_RATE_48K; ++ case 88200: ++ return MTK_AFE_RATE_88K; ++ case 96000: ++ return MTK_AFE_RATE_96K; ++ case 176400: ++ return MTK_AFE_RATE_176K; ++ case 192000: ++ return MTK_AFE_RATE_192K; ++ default: ++ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", ++ __func__, rate, MTK_AFE_RATE_48K); ++ return MTK_AFE_RATE_48K; ++ } ++} ++ ++static const struct snd_pcm_hardware mt7986_afe_hardware = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_MMAP_VALID, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ .period_bytes_min = 256, ++ .period_bytes_max = 4 * 48 * 1024, ++ .periods_min = 2, ++ .periods_max = 256, ++ .buffer_bytes_max = 8 * 48 * 1024, ++ .fifo_size = 0, ++}; ++ ++static int mt7986_memif_fs(struct snd_pcm_substream *substream, ++ unsigned int rate) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); ++ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); ++ ++ return mt7986_afe_rate_transform(afe->dev, rate); ++} ++ ++static int mt7986_irq_fs(struct snd_pcm_substream *substream, ++ unsigned int rate) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); ++ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); ++ ++ return mt7986_afe_rate_transform(afe->dev, rate); ++} ++ ++#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\ ++ SNDRV_PCM_RATE_88200 |\ ++ SNDRV_PCM_RATE_96000 |\ ++ SNDRV_PCM_RATE_176400 |\ ++ SNDRV_PCM_RATE_192000) ++ ++#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE |\ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++static struct snd_soc_dai_driver mt7986_memif_dai_driver[] = { ++ /* FE DAIs: memory intefaces to CPU */ ++ { ++ .name = "DL1", ++ .id = MT7986_MEMIF_DL1, ++ .playback = { ++ .stream_name = "DL1", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = MTK_PCM_RATES, ++ .formats = MTK_PCM_FORMATS, ++ }, ++ .ops = &mtk_afe_fe_ops, ++ }, ++ { ++ .name = "UL1", ++ .id = MT7986_MEMIF_VUL12, ++ .capture = { ++ .stream_name = "UL1", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = MTK_PCM_RATES, ++ .formats = MTK_PCM_FORMATS, ++ }, ++ .ops = &mtk_afe_fe_ops, ++ }, ++}; ++ ++static const struct snd_kcontrol_new o018_mix[] = { ++ SOC_DAPM_SINGLE_AUTODISABLE("I150_Switch", AFE_CONN018_4, 22, 1, 0), ++}; ++ ++static const struct snd_kcontrol_new o019_mix[] = { ++ SOC_DAPM_SINGLE_AUTODISABLE("I151_Switch", AFE_CONN019_4, 23, 1, 0), ++}; ++ ++static const struct snd_soc_dapm_widget mt7986_memif_widgets[] = { ++ /* DL */ ++ SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0), ++ ++ /* UL */ ++ SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0, ++ o018_mix, ARRAY_SIZE(o018_mix)), ++ SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0, ++ o019_mix, ARRAY_SIZE(o019_mix)), ++}; ++ ++static const struct snd_soc_dapm_route mt7986_memif_routes[] = { ++ {"I032", NULL, "DL1"}, ++ {"I033", NULL, "DL1"}, ++ {"UL1", NULL, "O018"}, ++ {"UL1", NULL, "O019"}, ++ {"O018", "I150_Switch", "I150"}, ++ {"O019", "I151_Switch", "I151"}, ++}; ++ ++static const struct snd_soc_component_driver mt7986_afe_pcm_dai_component = { ++ .name = "mt7986-afe-pcm-dai", ++}; ++ ++static const struct mtk_base_memif_data memif_data[MT7986_MEMIF_NUM] = { ++ [MT7986_MEMIF_DL1] = { ++ .name = "DL1", ++ .id = MT7986_MEMIF_DL1, ++ .reg_ofs_base = AFE_DL0_BASE, ++ .reg_ofs_cur = AFE_DL0_CUR, ++ .reg_ofs_end = AFE_DL0_END, ++ .reg_ofs_base_msb = AFE_DL0_BASE_MSB, ++ .reg_ofs_cur_msb = AFE_DL0_CUR_MSB, ++ .reg_ofs_end_msb = AFE_DL0_END_MSB, ++ .fs_reg = AFE_DL0_CON0, ++ .fs_shift = DL0_MODE_SFT, ++ .fs_maskbit = DL0_MODE_MASK, ++ .mono_reg = AFE_DL0_CON0, ++ .mono_shift = DL0_MONO_SFT, ++ .enable_reg = AFE_DL0_CON0, ++ .enable_shift = DL0_ON_SFT, ++ .hd_reg = AFE_DL0_CON0, ++ .hd_shift = DL0_HD_MODE_SFT, ++ .hd_align_reg = AFE_DL0_CON0, ++ .hd_align_mshift = DL0_HALIGN_SFT, ++ .pbuf_reg = AFE_DL0_CON0, ++ .pbuf_shift = DL0_PBUF_SIZE_SFT, ++ .minlen_reg = AFE_DL0_CON0, ++ .minlen_shift = DL0_MINLEN_SFT, ++ }, ++ [MT7986_MEMIF_VUL12] = { ++ .name = "VUL12", ++ .id = MT7986_MEMIF_VUL12, ++ .reg_ofs_base = AFE_VUL0_BASE, ++ .reg_ofs_cur = AFE_VUL0_CUR, ++ .reg_ofs_end = AFE_VUL0_END, ++ .reg_ofs_base_msb = AFE_VUL0_BASE_MSB, ++ .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB, ++ .reg_ofs_end_msb = AFE_VUL0_END_MSB, ++ .fs_reg = AFE_VUL0_CON0, ++ .fs_shift = VUL0_MODE_SFT, ++ .fs_maskbit = VUL0_MODE_MASK, ++ .mono_reg = AFE_VUL0_CON0, ++ .mono_shift = VUL0_MONO_SFT, ++ .enable_reg = AFE_VUL0_CON0, ++ .enable_shift = VUL0_ON_SFT, ++ .hd_reg = AFE_VUL0_CON0, ++ .hd_shift = VUL0_HD_MODE_SFT, ++ .hd_align_reg = AFE_VUL0_CON0, ++ .hd_align_mshift = VUL0_HALIGN_SFT, ++ }, ++}; ++ ++static const struct mtk_base_irq_data irq_data[MT7986_IRQ_NUM] = { ++ [MT7986_IRQ_0] = { ++ .id = MT7986_IRQ_0, ++ .irq_cnt_reg = AFE_IRQ0_MCU_CFG1, ++ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, ++ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, ++ .irq_fs_reg = AFE_IRQ0_MCU_CFG0, ++ .irq_fs_shift = IRQ_MCU_MODE_SFT, ++ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, ++ .irq_en_reg = AFE_IRQ0_MCU_CFG0, ++ .irq_en_shift = IRQ_MCU_ON_SFT, ++ .irq_clr_reg = AFE_IRQ_MCU_CLR, ++ .irq_clr_shift = IRQ0_MCU_CLR_SFT, ++ }, ++ [MT7986_IRQ_1] = { ++ .id = MT7986_IRQ_1, ++ .irq_cnt_reg = AFE_IRQ1_MCU_CFG1, ++ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, ++ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, ++ .irq_fs_reg = AFE_IRQ1_MCU_CFG0, ++ .irq_fs_shift = IRQ_MCU_MODE_SFT, ++ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, ++ .irq_en_reg = AFE_IRQ1_MCU_CFG0, ++ .irq_en_shift = IRQ_MCU_ON_SFT, ++ .irq_clr_reg = AFE_IRQ_MCU_CLR, ++ .irq_clr_shift = IRQ1_MCU_CLR_SFT, ++ }, ++ [MT7986_IRQ_2] = { ++ .id = MT7986_IRQ_2, ++ .irq_cnt_reg = AFE_IRQ2_MCU_CFG1, ++ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, ++ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, ++ .irq_fs_reg = AFE_IRQ2_MCU_CFG0, ++ .irq_fs_shift = IRQ_MCU_MODE_SFT, ++ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, ++ .irq_en_reg = AFE_IRQ2_MCU_CFG0, ++ .irq_en_shift = IRQ_MCU_ON_SFT, ++ .irq_clr_reg = AFE_IRQ_MCU_CLR, ++ .irq_clr_shift = IRQ2_MCU_CLR_SFT, ++ }, ++}; ++ ++static bool mt7986_is_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ /* ++ * Those auto-gen regs are read-only, so put it as volatile because ++ * volatile registers cannot be cached, which means that they cannot ++ * be set when power is off ++ */ ++ ++ switch (reg) { ++ case AFE_DL0_CUR_MSB: ++ case AFE_DL0_CUR: ++ case AFE_DL0_RCH_MON: ++ case AFE_DL0_LCH_MON: ++ case AFE_VUL0_CUR_MSB: ++ case AFE_VUL0_CUR: ++ case AFE_IRQ_MCU_STATUS: ++ case AFE_MEMIF_RD_MON: ++ case AFE_MEMIF_WR_MON: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static const struct regmap_config mt7986_afe_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .volatile_reg = mt7986_is_volatile_reg, ++ .max_register = AFE_MAX_REGISTER, ++ .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1), ++}; ++ ++static int mt7986_init_clock(struct mtk_base_afe *afe) ++{ ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ int ret, i; ++ ++ afe_priv->clks = devm_kcalloc(afe->dev, CLK_NUM, ++ sizeof(*afe_priv->clks), GFP_KERNEL); ++ if (!afe_priv->clks) ++ return -ENOMEM; ++ afe_priv->num_clks = CLK_NUM; ++ ++ for (i = 0; i < afe_priv->num_clks; i++) ++ afe_priv->clks[i].id = aud_clks[i]; ++ ++ ret = devm_clk_bulk_get(afe->dev, afe_priv->num_clks, afe_priv->clks); ++ if (ret) ++ return dev_err_probe(afe->dev, ret, "Failed to get clocks\n"); ++ ++ return 0; ++} ++ ++static irqreturn_t mt7986_afe_irq_handler(int irq_id, void *dev) ++{ ++ struct mtk_base_afe *afe = dev; ++ struct mtk_base_afe_irq *irq; ++ u32 mcu_en, status, status_mcu; ++ int i, ret; ++ irqreturn_t irq_ret = IRQ_HANDLED; ++ ++ /* get irq that is sent to MCU */ ++ regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en); ++ ++ ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status); ++ /* only care IRQ which is sent to MCU */ ++ status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS; ++ ++ if (ret || status_mcu == 0) { ++ dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x, mcu_en 0x%x\n", ++ __func__, ret, status, mcu_en); ++ ++ irq_ret = IRQ_NONE; ++ goto err_irq; ++ } ++ ++ for (i = 0; i < MT7986_MEMIF_NUM; i++) { ++ struct mtk_base_afe_memif *memif = &afe->memif[i]; ++ ++ if (!memif->substream) ++ continue; ++ ++ if (memif->irq_usage < 0) ++ continue; ++ ++ irq = &afe->irqs[memif->irq_usage]; ++ ++ if (status_mcu & (1 << irq->irq_data->irq_en_shift)) ++ snd_pcm_period_elapsed(memif->substream); ++ } ++ ++err_irq: ++ /* clear irq */ ++ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, status_mcu); ++ ++ return irq_ret; ++} ++ ++static int mt7986_afe_runtime_suspend(struct device *dev) ++{ ++ struct mtk_base_afe *afe = dev_get_drvdata(dev); ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ ++ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) ++ goto skip_regmap; ++ ++ /* disable clk*/ ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0x3fff); ++ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, 0); ++ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, 0); ++ ++ /* make sure all irq status are cleared, twice intended */ ++ regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CLR, 0xffff, 0xffff); ++ ++skip_regmap: ++ clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); ++ ++ return 0; ++} ++ ++static int mt7986_afe_runtime_resume(struct device *dev) ++{ ++ struct mtk_base_afe *afe = dev_get_drvdata(dev); ++ struct mt7986_afe_private *afe_priv = afe->platform_priv; ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); ++ if (ret) ++ return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); ++ ++ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) ++ return 0; ++ ++ /* enable clk*/ ++ regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0); ++ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, ++ AUD_APLL2_EN); ++ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, ++ AUD_26M_EN); ++ ++ return 0; ++} ++ ++static int mt7986_afe_component_probe(struct snd_soc_component *component) ++{ ++ return mtk_afe_add_sub_dai_control(component); ++} ++ ++static const struct snd_soc_component_driver mt7986_afe_component = { ++ .name = AFE_PCM_NAME, ++ .probe = mt7986_afe_component_probe, ++ .pointer = mtk_afe_pcm_pointer, ++ .pcm_construct = mtk_afe_pcm_new, ++}; ++ ++static int mt7986_dai_memif_register(struct mtk_base_afe *afe) ++{ ++ struct mtk_base_afe_dai *dai; ++ ++ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); ++ if (!dai) ++ return -ENOMEM; ++ ++ list_add(&dai->list, &afe->sub_dais); ++ ++ dai->dai_drivers = mt7986_memif_dai_driver; ++ dai->num_dai_drivers = ARRAY_SIZE(mt7986_memif_dai_driver); ++ ++ dai->dapm_widgets = mt7986_memif_widgets; ++ dai->num_dapm_widgets = ARRAY_SIZE(mt7986_memif_widgets); ++ dai->dapm_routes = mt7986_memif_routes; ++ dai->num_dapm_routes = ARRAY_SIZE(mt7986_memif_routes); ++ ++ return 0; ++} ++ ++typedef int (*dai_register_cb)(struct mtk_base_afe *); ++static const dai_register_cb dai_register_cbs[] = { ++ mt7986_dai_etdm_register, ++ mt7986_dai_memif_register, ++}; ++ ++static int mt7986_afe_pcm_dev_probe(struct platform_device *pdev) ++{ ++ struct mtk_base_afe *afe; ++ struct mt7986_afe_private *afe_priv; ++ struct device *dev; ++ int i, irq_id, ret; ++ ++ afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); ++ if (!afe) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, afe); ++ ++ afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), ++ GFP_KERNEL); ++ if (!afe->platform_priv) ++ return -ENOMEM; ++ ++ afe_priv = afe->platform_priv; ++ afe->dev = &pdev->dev; ++ dev = afe->dev; ++ ++ afe->base_addr = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(afe->base_addr)) ++ return PTR_ERR(afe->base_addr); ++ ++ /* initial audio related clock */ ++ ret = mt7986_init_clock(afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot initialize clocks\n"); ++ ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return ret; ++ ++ /* enable clock for regcache get default value from hw */ ++ afe_priv->pm_runtime_bypass_reg_ctl = true; ++ pm_runtime_get_sync(&pdev->dev); ++ ++ afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, ++ &mt7986_afe_regmap_config); ++ ++ pm_runtime_put_sync(&pdev->dev); ++ if (IS_ERR(afe->regmap)) ++ return PTR_ERR(afe->regmap); ++ ++ afe_priv->pm_runtime_bypass_reg_ctl = false; ++ ++ /* init memif */ ++ afe->memif_size = MT7986_MEMIF_NUM; ++ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), ++ GFP_KERNEL); ++ if (!afe->memif) ++ return -ENOMEM; ++ ++ for (i = 0; i < afe->memif_size; i++) { ++ afe->memif[i].data = &memif_data[i]; ++ afe->memif[i].irq_usage = -1; ++ } ++ ++ mutex_init(&afe->irq_alloc_lock); ++ ++ /* irq initialize */ ++ afe->irqs_size = MT7986_IRQ_NUM; ++ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), ++ GFP_KERNEL); ++ if (!afe->irqs) ++ return -ENOMEM; ++ ++ for (i = 0; i < afe->irqs_size; i++) ++ afe->irqs[i].irq_data = &irq_data[i]; ++ ++ /* request irq */ ++ irq_id = platform_get_irq(pdev, 0); ++ if (irq_id < 0) { ++ ret = irq_id; ++ return dev_err_probe(dev, ret, "No irq found\n"); ++ } ++ ret = devm_request_irq(dev, irq_id, mt7986_afe_irq_handler, ++ IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to request irq for asys-isr\n"); ++ ++ /* init sub_dais */ ++ INIT_LIST_HEAD(&afe->sub_dais); ++ ++ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { ++ ret = dai_register_cbs[i](afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "DAI register failed, i: %d\n", i); ++ } ++ ++ /* init dai_driver and component_driver */ ++ ret = mtk_afe_combine_sub_dai(afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n"); ++ ++ afe->mtk_afe_hardware = &mt7986_afe_hardware; ++ afe->memif_fs = mt7986_memif_fs; ++ afe->irq_fs = mt7986_irq_fs; ++ ++ afe->runtime_resume = mt7986_afe_runtime_resume; ++ afe->runtime_suspend = mt7986_afe_runtime_suspend; ++ ++ /* register component */ ++ ret = devm_snd_soc_register_component(&pdev->dev, ++ &mt7986_afe_component, ++ NULL, 0); ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot register AFE component\n"); ++ ++ ret = devm_snd_soc_register_component(afe->dev, ++ &mt7986_afe_pcm_dai_component, ++ afe->dai_drivers, ++ afe->num_dai_drivers); ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot register PCM DAI component\n"); ++ ++ return 0; ++} ++ ++static void mt7986_afe_pcm_dev_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ if (!pm_runtime_status_suspended(&pdev->dev)) ++ mt7986_afe_runtime_suspend(&pdev->dev); ++} ++ ++static const struct of_device_id mt7986_afe_pcm_dt_match[] = { ++ { .compatible = "mediatek,mt7986-afe" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mt7986_afe_pcm_dt_match); ++ ++static const struct dev_pm_ops mt7986_afe_pm_ops = { ++ SET_RUNTIME_PM_OPS(mt7986_afe_runtime_suspend, ++ mt7986_afe_runtime_resume, NULL) ++}; ++ ++static struct platform_driver mt7986_afe_pcm_driver = { ++ .driver = { ++ .name = "mt7986-audio", ++ .of_match_table = mt7986_afe_pcm_dt_match, ++ .pm = &mt7986_afe_pm_ops, ++ }, ++ .probe = mt7986_afe_pcm_dev_probe, ++ .remove_new = mt7986_afe_pcm_dev_remove, ++}; ++module_platform_driver(mt7986_afe_pcm_driver); ++ ++MODULE_DESCRIPTION("MediaTek SoC AFE platform driver for ALSA MT7986"); ++MODULE_AUTHOR("Vic Wu "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch b/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch new file mode 100644 index 0000000000..dd354c04e3 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch @@ -0,0 +1,243 @@ +From ddf6abc1c78072f8ccad59166be95f0ca5af8ca4 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:36 +0800 +Subject: [PATCH 4/9] ASoC: mediatek: mt7986: add machine driver with wm8960 + +Add support for mt7986 board with wm8960. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-5-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/Kconfig | 10 ++ + sound/soc/mediatek/mt7986/Makefile | 1 + + sound/soc/mediatek/mt7986/mt7986-wm8960.c | 196 ++++++++++++++++++++++ + 3 files changed, 207 insertions(+) + create mode 100644 sound/soc/mediatek/mt7986/mt7986-wm8960.c + +--- a/sound/soc/mediatek/Kconfig ++++ b/sound/soc/mediatek/Kconfig +@@ -64,6 +64,16 @@ config SND_SOC_MT7986 + Select Y if you have such device. + If unsure select "N". + ++config SND_SOC_MT7986_WM8960 ++ tristate "ASoc Audio driver for MT7986 with WM8960 codec" ++ depends on SND_SOC_MT7986 && I2C ++ select SND_SOC_WM8960 ++ help ++ This adds support for ASoC machine driver for MediaTek MT7986 ++ boards with the WM8960 codecs. ++ Select Y if you have such device. ++ If unsure select "N". ++ + config SND_SOC_MT8173 + tristate "ASoC support for Mediatek MT8173 chip" + depends on ARCH_MEDIATEK +--- a/sound/soc/mediatek/mt7986/Makefile ++++ b/sound/soc/mediatek/mt7986/Makefile +@@ -6,3 +6,4 @@ snd-soc-mt7986-afe-objs := \ + mt7986-dai-etdm.o + + obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o ++obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o +--- /dev/null ++++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c +@@ -0,0 +1,196 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * mt7986-wm8960.c -- MT7986-WM8960 ALSA SoC machine driver ++ * ++ * Copyright (c) 2023 MediaTek Inc. ++ * Authors: Vic Wu ++ * Maso Huang ++ */ ++ ++#include ++#include ++ ++#include "mt7986-afe-common.h" ++ ++struct mt7986_wm8960_priv { ++ struct device_node *platform_node; ++ struct device_node *codec_node; ++}; ++ ++static const struct snd_soc_dapm_widget mt7986_wm8960_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone", NULL), ++ SND_SOC_DAPM_MIC("AMIC", NULL), ++}; ++ ++static const struct snd_kcontrol_new mt7986_wm8960_controls[] = { ++ SOC_DAPM_PIN_SWITCH("Headphone"), ++ SOC_DAPM_PIN_SWITCH("AMIC"), ++}; ++ ++SND_SOC_DAILINK_DEFS(playback, ++ DAILINK_COMP_ARRAY(COMP_CPU("DL1")), ++ DAILINK_COMP_ARRAY(COMP_DUMMY()), ++ DAILINK_COMP_ARRAY(COMP_EMPTY())); ++ ++SND_SOC_DAILINK_DEFS(capture, ++ DAILINK_COMP_ARRAY(COMP_CPU("UL1")), ++ DAILINK_COMP_ARRAY(COMP_DUMMY()), ++ DAILINK_COMP_ARRAY(COMP_EMPTY())); ++ ++SND_SOC_DAILINK_DEFS(codec, ++ DAILINK_COMP_ARRAY(COMP_CPU("ETDM")), ++ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")), ++ DAILINK_COMP_ARRAY(COMP_EMPTY())); ++ ++static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = { ++ /* FE */ ++ { ++ .name = "wm8960-playback", ++ .stream_name = "wm8960-playback", ++ .trigger = {SND_SOC_DPCM_TRIGGER_POST, ++ SND_SOC_DPCM_TRIGGER_POST}, ++ .dynamic = 1, ++ .dpcm_playback = 1, ++ SND_SOC_DAILINK_REG(playback), ++ }, ++ { ++ .name = "wm8960-capture", ++ .stream_name = "wm8960-capture", ++ .trigger = {SND_SOC_DPCM_TRIGGER_POST, ++ SND_SOC_DPCM_TRIGGER_POST}, ++ .dynamic = 1, ++ .dpcm_capture = 1, ++ SND_SOC_DAILINK_REG(capture), ++ }, ++ /* BE */ ++ { ++ .name = "wm8960-codec", ++ .no_pcm = 1, ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS | ++ SND_SOC_DAIFMT_GATED, ++ .dpcm_playback = 1, ++ .dpcm_capture = 1, ++ SND_SOC_DAILINK_REG(codec), ++ }, ++}; ++ ++static struct snd_soc_card mt7986_wm8960_card = { ++ .name = "mt7986-wm8960", ++ .owner = THIS_MODULE, ++ .dai_link = mt7986_wm8960_dai_links, ++ .num_links = ARRAY_SIZE(mt7986_wm8960_dai_links), ++ .controls = mt7986_wm8960_controls, ++ .num_controls = ARRAY_SIZE(mt7986_wm8960_controls), ++ .dapm_widgets = mt7986_wm8960_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(mt7986_wm8960_widgets), ++}; ++ ++static int mt7986_wm8960_machine_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &mt7986_wm8960_card; ++ struct snd_soc_dai_link *dai_link; ++ struct device_node *platform, *codec; ++ struct mt7986_wm8960_priv *priv; ++ int ret, i; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ platform = of_get_child_by_name(pdev->dev.of_node, "platform"); ++ ++ if (platform) { ++ priv->platform_node = of_parse_phandle(platform, "sound-dai", 0); ++ of_node_put(platform); ++ ++ if (!priv->platform_node) { ++ dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n"); ++ return -EINVAL; ++ } ++ } else { ++ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); ++ return -EINVAL; ++ } ++ ++ for_each_card_prelinks(card, i, dai_link) { ++ if (dai_link->platforms->name) ++ continue; ++ dai_link->platforms->of_node = priv->platform_node; ++ } ++ ++ card->dev = &pdev->dev; ++ ++ codec = of_get_child_by_name(pdev->dev.of_node, "codec"); ++ ++ if (codec) { ++ priv->codec_node = of_parse_phandle(codec, "sound-dai", 0); ++ of_node_put(codec); ++ ++ if (!priv->codec_node) { ++ of_node_put(priv->platform_node); ++ dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n"); ++ return -EINVAL; ++ } ++ } else { ++ of_node_put(priv->platform_node); ++ dev_err(&pdev->dev, "Property 'codec' missing or invalid\n"); ++ return -EINVAL; ++ } ++ ++ for_each_card_prelinks(card, i, dai_link) { ++ if (dai_link->codecs->name) ++ continue; ++ dai_link->codecs->of_node = priv->codec_node; ++ } ++ ++ ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to parse audio-routing: %d\n", ret); ++ goto err_of_node_put; ++ } ++ ++ ret = devm_snd_soc_register_card(&pdev->dev, card); ++ if (ret) { ++ dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret); ++ goto err_of_node_put; ++ } ++ ++err_of_node_put: ++ of_node_put(priv->codec_node); ++ of_node_put(priv->platform_node); ++ return ret; ++} ++ ++static void mt7986_wm8960_machine_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ struct mt7986_wm8960_priv *priv = snd_soc_card_get_drvdata(card); ++ ++ of_node_put(priv->codec_node); ++ of_node_put(priv->platform_node); ++} ++ ++static const struct of_device_id mt7986_wm8960_machine_dt_match[] = { ++ {.compatible = "mediatek,mt7986-wm8960-sound"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mt7986_wm8960_machine_dt_match); ++ ++static struct platform_driver mt7986_wm8960_machine = { ++ .driver = { ++ .name = "mt7986-wm8960", ++ .of_match_table = mt7986_wm8960_machine_dt_match, ++ }, ++ .probe = mt7986_wm8960_machine_probe, ++ .remove_new = mt7986_wm8960_machine_remove, ++}; ++ ++module_platform_driver(mt7986_wm8960_machine); ++ ++/* Module information */ ++MODULE_DESCRIPTION("MT7986 WM8960 ALSA SoC machine driver"); ++MODULE_AUTHOR("Vic Wu "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("mt7986 wm8960 soc card"); diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch b/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch new file mode 100644 index 0000000000..8cf0b5464a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch @@ -0,0 +1,87 @@ +From 72469f950b629e57e60fbcbefed45e083619b986 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:37 +0800 +Subject: [PATCH 5/9] ASoC: dt-bindings: mediatek,mt7986-wm8960: add + mt7986-wm8960 document + +Add document for mt7986 board with wm8960. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-6-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + .../sound/mediatek,mt7986-wm8960.yaml | 67 +++++++++++++++++++ + 1 file changed, 67 insertions(+) + create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt7986-wm8960.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/mediatek,mt7986-wm8960.yaml +@@ -0,0 +1,67 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/mediatek,mt7986-wm8960.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek MT7986 sound card with WM8960 codec ++ ++maintainers: ++ - Maso Huang ++ ++allOf: ++ - $ref: sound-card-common.yaml# ++ ++properties: ++ compatible: ++ const: mediatek,mt7986-wm8960-sound ++ ++ platform: ++ type: object ++ additionalProperties: false ++ properties: ++ sound-dai: ++ description: The phandle of MT7986 platform. ++ maxItems: 1 ++ required: ++ - sound-dai ++ ++ codec: ++ type: object ++ additionalProperties: false ++ properties: ++ sound-dai: ++ description: The phandle of wm8960 codec. ++ maxItems: 1 ++ required: ++ - sound-dai ++ ++unevaluatedProperties: false ++ ++required: ++ - compatible ++ - audio-routing ++ - platform ++ - codec ++ ++examples: ++ - | ++ sound { ++ compatible = "mediatek,mt7986-wm8960-sound"; ++ model = "mt7986-wm8960"; ++ audio-routing = ++ "Headphone", "HP_L", ++ "Headphone", "HP_R", ++ "LINPUT1", "AMIC", ++ "RINPUT1", "AMIC"; ++ ++ platform { ++ sound-dai = <&afe>; ++ }; ++ ++ codec { ++ sound-dai = <&wm8960>; ++ }; ++ }; ++ ++... diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch b/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch new file mode 100644 index 0000000000..236d6a217c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch @@ -0,0 +1,180 @@ +From d16202eb38585adbc16e32d11188dbc2127015de Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 17 Aug 2023 18:13:38 +0800 +Subject: [PATCH 6/9] ASoC: dt-bindings: mediatek,mt7986-afe: add audio afe + document + +Add mt7986 audio afe document. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20230817101338.18782-7-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + .../bindings/sound/mediatek,mt7986-afe.yaml | 160 ++++++++++++++++++ + 1 file changed, 160 insertions(+) + create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt7986-afe.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/mediatek,mt7986-afe.yaml +@@ -0,0 +1,160 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/sound/mediatek,mt7986-afe.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek AFE PCM controller for MT7986 ++ ++maintainers: ++ - Maso Huang ++ ++properties: ++ compatible: ++ oneOf: ++ - const: mediatek,mt7986-afe ++ - items: ++ - enum: ++ - mediatek,mt7981-afe ++ - mediatek,mt7988-afe ++ - const: mediatek,mt7986-afe ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 5 ++ items: ++ - description: audio bus clock ++ - description: audio 26M clock ++ - description: audio intbus clock ++ - description: audio hopping clock ++ - description: audio pll clock ++ - description: mux for pcm_mck ++ - description: audio i2s/pcm mck ++ ++ clock-names: ++ minItems: 5 ++ items: ++ - const: bus_ck ++ - const: 26m_ck ++ - const: l_ck ++ - const: aud_ck ++ - const: eg2_ck ++ - const: sel ++ - const: i2s_m ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: mediatek,mt7986-afe ++ then: ++ properties: ++ clocks: ++ items: ++ - description: audio bus clock ++ - description: audio 26M clock ++ - description: audio intbus clock ++ - description: audio hopping clock ++ - description: audio pll clock ++ clock-names: ++ items: ++ - const: bus_ck ++ - const: 26m_ck ++ - const: l_ck ++ - const: aud_ck ++ - const: eg2_ck ++ ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: mediatek,mt7981-afe ++ then: ++ properties: ++ clocks: ++ items: ++ - description: audio bus clock ++ - description: audio 26M clock ++ - description: audio intbus clock ++ - description: audio hopping clock ++ - description: audio pll clock ++ - description: mux for pcm_mck ++ clock-names: ++ items: ++ - const: bus_ck ++ - const: 26m_ck ++ - const: l_ck ++ - const: aud_ck ++ - const: eg2_ck ++ - const: sel ++ ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: mediatek,mt7988-afe ++ then: ++ properties: ++ clocks: ++ items: ++ - description: audio bus clock ++ - description: audio 26M clock ++ - description: audio intbus clock ++ - description: audio hopping clock ++ - description: audio pll clock ++ - description: mux for pcm_mck ++ - description: audio i2s/pcm mck ++ clock-names: ++ items: ++ - const: bus_ck ++ - const: 26m_ck ++ - const: l_ck ++ - const: aud_ck ++ - const: eg2_ck ++ - const: sel ++ - const: i2s_m ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ ++ afe@11210000 { ++ compatible = "mediatek,mt7986-afe"; ++ reg = <0x11210000 0x9000>; ++ interrupts = ; ++ clocks = <&infracfg_ao CLK_INFRA_AUD_BUS_CK>, ++ <&infracfg_ao CLK_INFRA_AUD_26M_CK>, ++ <&infracfg_ao CLK_INFRA_AUD_L_CK>, ++ <&infracfg_ao CLK_INFRA_AUD_AUD_CK>, ++ <&infracfg_ao CLK_INFRA_AUD_EG2_CK>; ++ clock-names = "bus_ck", ++ "26m_ck", ++ "l_ck", ++ "aud_ck", ++ "eg2_ck"; ++ assigned-clocks = <&topckgen CLK_TOP_A1SYS_SEL>, ++ <&topckgen CLK_TOP_AUD_L_SEL>, ++ <&topckgen CLK_TOP_A_TUNER_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_APLL2_D4>, ++ <&apmixedsys CLK_APMIXED_APLL2>, ++ <&topckgen CLK_TOP_APLL2_D4>; ++ }; ++ ++... diff --git a/target/linux/mediatek/patches-6.6/860-v6.7-07-ASoC-mediatek-mt7986-drop-the-remove-callback-of-mt7.patch b/target/linux/mediatek/patches-6.6/860-v6.7-07-ASoC-mediatek-mt7986-drop-the-remove-callback-of-mt7.patch new file mode 100644 index 0000000000..413db8233f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.7-07-ASoC-mediatek-mt7986-drop-the-remove-callback-of-mt7.patch @@ -0,0 +1,42 @@ +From f3f0934e5c7b9c16e0cb2435be3555382e6293ad Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Tue, 24 Oct 2023 11:50:17 +0800 +Subject: [PATCH 7/9] ASoC: mediatek: mt7986: drop the remove callback of + mt7986_wm8960 + +Drop the remove callback of mt7986_wm8960. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20231024035019.11732-2-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/mt7986/mt7986-wm8960.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/sound/soc/mediatek/mt7986/mt7986-wm8960.c ++++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c +@@ -163,15 +163,6 @@ err_of_node_put: + return ret; + } + +-static void mt7986_wm8960_machine_remove(struct platform_device *pdev) +-{ +- struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct mt7986_wm8960_priv *priv = snd_soc_card_get_drvdata(card); +- +- of_node_put(priv->codec_node); +- of_node_put(priv->platform_node); +-} +- + static const struct of_device_id mt7986_wm8960_machine_dt_match[] = { + {.compatible = "mediatek,mt7986-wm8960-sound"}, + { /* sentinel */ } +@@ -184,7 +175,6 @@ static struct platform_driver mt7986_wm8 + .of_match_table = mt7986_wm8960_machine_dt_match, + }, + .probe = mt7986_wm8960_machine_probe, +- .remove_new = mt7986_wm8960_machine_remove, + }; + + module_platform_driver(mt7986_wm8960_machine); diff --git a/target/linux/mediatek/patches-6.6/860-v6.7-08-ASoC-mediatek-mt7986-remove-the-mt7986_wm8960_priv-s.patch b/target/linux/mediatek/patches-6.6/860-v6.7-08-ASoC-mediatek-mt7986-remove-the-mt7986_wm8960_priv-s.patch new file mode 100644 index 0000000000..5c596fc49c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.7-08-ASoC-mediatek-mt7986-remove-the-mt7986_wm8960_priv-s.patch @@ -0,0 +1,105 @@ +From 98b8fb2cb4fcab1903d0baf611bf0c3f822a08dc Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Tue, 24 Oct 2023 11:50:18 +0800 +Subject: [PATCH 8/9] ASoC: mediatek: mt7986: remove the mt7986_wm8960_priv + structure + +Remove the mt7986_wm8960_priv structure. + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20231024035019.11732-3-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/mt7986/mt7986-wm8960.c | 33 +++++++++-------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +--- a/sound/soc/mediatek/mt7986/mt7986-wm8960.c ++++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c +@@ -12,11 +12,6 @@ + + #include "mt7986-afe-common.h" + +-struct mt7986_wm8960_priv { +- struct device_node *platform_node; +- struct device_node *codec_node; +-}; +- + static const struct snd_soc_dapm_widget mt7986_wm8960_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("AMIC", NULL), +@@ -92,20 +87,18 @@ static int mt7986_wm8960_machine_probe(s + struct snd_soc_card *card = &mt7986_wm8960_card; + struct snd_soc_dai_link *dai_link; + struct device_node *platform, *codec; +- struct mt7986_wm8960_priv *priv; ++ struct device_node *platform_dai_node, *codec_dai_node; + int ret, i; + +- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ card->dev = &pdev->dev; + + platform = of_get_child_by_name(pdev->dev.of_node, "platform"); + + if (platform) { +- priv->platform_node = of_parse_phandle(platform, "sound-dai", 0); ++ platform_dai_node = of_parse_phandle(platform, "sound-dai", 0); + of_node_put(platform); + +- if (!priv->platform_node) { ++ if (!platform_dai_node) { + dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n"); + return -EINVAL; + } +@@ -117,24 +110,22 @@ static int mt7986_wm8960_machine_probe(s + for_each_card_prelinks(card, i, dai_link) { + if (dai_link->platforms->name) + continue; +- dai_link->platforms->of_node = priv->platform_node; ++ dai_link->platforms->of_node = platform_dai_node; + } + +- card->dev = &pdev->dev; +- + codec = of_get_child_by_name(pdev->dev.of_node, "codec"); + + if (codec) { +- priv->codec_node = of_parse_phandle(codec, "sound-dai", 0); ++ codec_dai_node = of_parse_phandle(codec, "sound-dai", 0); + of_node_put(codec); + +- if (!priv->codec_node) { +- of_node_put(priv->platform_node); ++ if (!codec_dai_node) { ++ of_node_put(platform_dai_node); + dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n"); + return -EINVAL; + } + } else { +- of_node_put(priv->platform_node); ++ of_node_put(platform_dai_node); + dev_err(&pdev->dev, "Property 'codec' missing or invalid\n"); + return -EINVAL; + } +@@ -142,7 +133,7 @@ static int mt7986_wm8960_machine_probe(s + for_each_card_prelinks(card, i, dai_link) { + if (dai_link->codecs->name) + continue; +- dai_link->codecs->of_node = priv->codec_node; ++ dai_link->codecs->of_node = codec_dai_node; + } + + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); +@@ -158,8 +149,8 @@ static int mt7986_wm8960_machine_probe(s + } + + err_of_node_put: +- of_node_put(priv->codec_node); +- of_node_put(priv->platform_node); ++ of_node_put(platform_dai_node); ++ of_node_put(codec_dai_node); + return ret; + } + diff --git a/target/linux/mediatek/patches-6.6/860-v6.7-09-ASoC-mediatek-mt7986-add-sample-rate-checker.patch b/target/linux/mediatek/patches-6.6/860-v6.7-09-ASoC-mediatek-mt7986-add-sample-rate-checker.patch new file mode 100644 index 0000000000..d4128deabc --- /dev/null +++ b/target/linux/mediatek/patches-6.6/860-v6.7-09-ASoC-mediatek-mt7986-add-sample-rate-checker.patch @@ -0,0 +1,49 @@ +From 4e229f4264f4be7a6a554487714c0913ef59cf7f Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Tue, 24 Oct 2023 11:50:19 +0800 +Subject: [PATCH 9/9] ASoC: mediatek: mt7986: add sample rate checker + +mt7986 only supports 8/12/16/24/32/48/96/192 kHz + +Signed-off-by: Maso Huang +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20231024035019.11732-4-maso.huang@mediatek.com +Signed-off-by: Mark Brown +--- + sound/soc/mediatek/mt7986/mt7986-dai-etdm.c | 23 +++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +--- a/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c ++++ b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c +@@ -237,12 +237,27 @@ static int mtk_dai_etdm_hw_params(struct + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) + { ++ unsigned int rate = params_rate(params); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + +- mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK); +- mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE); +- +- return 0; ++ switch (rate) { ++ case 8000: ++ case 12000: ++ case 16000: ++ case 24000: ++ case 32000: ++ case 48000: ++ case 96000: ++ case 192000: ++ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK); ++ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE); ++ return 0; ++ default: ++ dev_err(afe->dev, ++ "Sample rate %d invalid. Supported rates: 8/12/16/24/32/48/96/192 kHz\n", ++ rate); ++ return -EINVAL; ++ } + } + + static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, diff --git a/target/linux/mediatek/patches-6.6/861-pending-10-ASoC-mediatek-mt7986-silence-error-in-case-of-EPROBE.patch b/target/linux/mediatek/patches-6.6/861-pending-10-ASoC-mediatek-mt7986-silence-error-in-case-of-EPROBE.patch new file mode 100644 index 0000000000..a40c249257 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/861-pending-10-ASoC-mediatek-mt7986-silence-error-in-case-of-EPROBE.patch @@ -0,0 +1,26 @@ +From e4cde335d1771863a60b6931e51357b8470e85c4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 10 Dec 2023 22:41:39 +0000 +Subject: [PATCH] ASoC: mediatek: mt7986: silence error in case of + -EPROBE_DEFER + +If probe is defered no error should be printed. Mute it. + +Signed-off-by: Daniel Golle +--- + sound/soc/mediatek/mt7986/mt7986-wm8960.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/sound/soc/mediatek/mt7986/mt7986-wm8960.c ++++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c +@@ -144,7 +144,9 @@ static int mt7986_wm8960_machine_probe(s + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { +- dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret); ++ + goto err_of_node_put; + } + diff --git a/target/linux/mediatek/patches-6.6/862-arm64-dts-mt7986-add-afe.patch b/target/linux/mediatek/patches-6.6/862-arm64-dts-mt7986-add-afe.patch new file mode 100644 index 0000000000..b31710fe69 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/862-arm64-dts-mt7986-add-afe.patch @@ -0,0 +1,40 @@ +From 1c09b694a1e9378931085e77d834a4d9786a5356 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 7 Sep 2023 10:54:37 +0800 +Subject: [PATCH] arm64: dts: mt7986: add afe + +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 23 +++++++++++ + 1 files changed, 23 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -248,6 +248,28 @@ + status = "disabled"; + }; + ++ afe: audio-controller@11210000 { ++ compatible = "mediatek,mt7986-afe"; ++ reg = <0 0x11210000 0 0x9000>; ++ interrupts = ; ++ clocks = <&infracfg CLK_INFRA_AUD_BUS_CK>, ++ <&infracfg CLK_INFRA_AUD_26M_CK>, ++ <&infracfg CLK_INFRA_AUD_L_CK>, ++ <&infracfg CLK_INFRA_AUD_AUD_CK>, ++ <&infracfg CLK_INFRA_AUD_EG2_CK>; ++ clock-names = "aud_bus_ck", ++ "aud_26m_ck", ++ "aud_l_ck", ++ "aud_aud_ck", ++ "aud_eg2_ck"; ++ assigned-clocks = <&topckgen CLK_TOP_A1SYS_SEL>, ++ <&topckgen CLK_TOP_AUD_L_SEL>, ++ <&topckgen CLK_TOP_A_TUNER_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_APLL2_D4>, ++ <&apmixedsys CLK_APMIXED_APLL2>, ++ <&topckgen CLK_TOP_APLL2_D4>; ++ }; ++ + pwm: pwm@10048000 { + compatible = "mediatek,mt7986-pwm"; + reg = <0 0x10048000 0 0x1000>; diff --git a/target/linux/mediatek/patches-6.6/863-arm64-dts-mt7986-add-sound-wm8960.patch b/target/linux/mediatek/patches-6.6/863-arm64-dts-mt7986-add-sound-wm8960.patch new file mode 100644 index 0000000000..15e30dec56 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/863-arm64-dts-mt7986-add-sound-wm8960.patch @@ -0,0 +1,61 @@ +From 1c09b694a1e9378931085e77d834a4d9786a5356 Mon Sep 17 00:00:00 2001 +From: Maso Huang +Date: Thu, 7 Sep 2023 10:54:37 +0800 +Subject: [PATCH] arm64: dts: mt7986: add sound wm8960 + +--- + .../dts/mediatek/mt7986a-rfb-spim-nand.dts | 39 +++++++++++++++++++ + 1 files changed, 39 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts +@@ -4,6 +4,35 @@ + + / { + compatible = "mediatek,mt7986a-rfb-snand"; ++ ++ sound_wm8960 { ++ compatible = "mediatek,mt7986-wm8960-sound"; ++ audio-routing = "Headphone", "HP_L", ++ "Headphone", "HP_R", ++ "LINPUT1", "AMIC", ++ "RINPUT1", "AMIC"; ++ ++ status = "okay"; ++ ++ platform { ++ sound-dai = <&afe>; ++ }; ++ ++ codec { ++ sound-dai = <&wm8960>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c_pins>; ++ status = "okay"; ++ ++ wm8960: wm8960@1a { ++ compatible = "wlf,wm8960"; ++ reg = <0x1a>; ++ }; + }; + + &spi0 { +@@ -50,3 +79,13 @@ + &wifi { + mediatek,mtd-eeprom = <&factory 0>; + }; ++ ++&pio { ++ i2c_pins: i2c-pins-3-4 { ++ mux { ++ function = "i2c"; ++ groups = "i2c"; ++ }; ++ }; ++}; ++ diff --git a/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch b/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch new file mode 100644 index 0000000000..bddcd4bb0c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch @@ -0,0 +1,75 @@ +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-respeaker-2mics.dtso +@@ -0,0 +1,62 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR MIT) ++/* ++ * Copyright (C) 2023 MediaTek Inc. ++ * Author: Maso Huang ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ sound_wm8960 { ++ compatible = "mediatek,mt7986-wm8960-sound"; ++ audio-routing = "Headphone", "HP_L", ++ "Headphone", "HP_R", ++ "LINPUT1", "AMIC", ++ "RINPUT1", "AMIC"; ++ ++ status = "okay"; ++ ++ platform { ++ sound-dai = <&afe>; ++ }; ++ ++ codec { ++ sound-dai = <&wm8960>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c0>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c_pins>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ wm8960: wm8960@1a { ++ compatible = "wlf,wm8960"; ++ reg = <0x1a>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&pio>; ++ __overlay__ { ++ i2c_pins: i2c-pins-3-4 { ++ mux { ++ function = "i2c"; ++ groups = "i2c"; ++ }; ++ }; ++ }; ++ }; ++}; +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-b + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-respeaker-2mics.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb diff --git a/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch new file mode 100644 index 0000000000..6dede02003 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch @@ -0,0 +1,65 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -312,7 +312,7 @@ + /* Attention: GPIO 90 is used to switch between PCIe@1,0 and + * SATA functions. i.e. output-high: PCIe, output-low: SATA + */ +- asm_sel { ++ asmsel: asm_sel { + gpio-hog; + gpios = <90 GPIO_ACTIVE_HIGH>; + output-high; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-sata.dtso +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++ ++#include ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; ++ ++ fragment@0 { ++ target = <&asmsel>; ++ __overlay__ { ++ gpios = <90 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&sata>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sata_phy>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-pcie1.dtso +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++ ++#include ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; ++ ++ fragment@0 { ++ target = <&asmsel>; ++ __overlay__ { ++ gpios = <90 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; diff --git a/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch new file mode 100644 index 0000000000..bfca4b6389 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch @@ -0,0 +1,54 @@ +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1589,6 +1589,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN + + endchoice + ++config CMDLINE_OVERRIDE ++ bool "Use alternative cmdline from device tree" ++ help ++ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can ++ be used, this is not a good option for kernels that are shared across ++ devices. This setting enables using "chosen/cmdline-override" as the ++ cmdline if it exists in the device tree. ++ + config CMDLINE + string "Default kernel command string" + default "" +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1187,6 +1187,17 @@ int __init early_init_dt_scan_chosen(cha + if (p != NULL && l > 0) + strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + ++ /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different ++ * device tree option of chosen/bootargs-override. This is ++ * helpful on boards where u-boot sets bootargs, and is unable ++ * to be modified. ++ */ ++#ifdef CONFIG_CMDLINE_OVERRIDE ++ p = of_get_flat_dt_prop(node, "bootargs-override", &l); ++ if (p != NULL && l > 0) ++ strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++#endif ++ + handle_cmdline: + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -2240,6 +2240,14 @@ config CMDLINE_FORCE + + endchoice + ++config CMDLINE_OVERRIDE ++ bool "Use alternative cmdline from device tree" ++ help ++ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can ++ be used, this is not a good option for kernels that are shared across ++ devices. This setting enables using "chosen/cmdline-override" as the ++ cmdline if it exists in the device tree. ++ + config EFI_STUB + bool + diff --git a/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch new file mode 100644 index 0000000000..09ce417c35 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch @@ -0,0 +1,31 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -639,5 +639,28 @@ + }; + + &wmac { ++ mediatek,eeprom-data = <0x22760500 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x44000020 0x0 0x10002000 ++ 0x4400 0x4000000 0x0 0x0 ++ 0x200000b3 0x40b6c3c3 0x26000000 0x41c42600 ++ 0x41c4 0x26000000 0xc0c52600 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0xc6c6 ++ 0xc3c3c2c1 0xc300c3 0x818181 0x83c1c182 ++ 0x83838382 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x84002e00 0x90000087 0x8a000000 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0xb000009 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x7707>; ++ + status = "okay"; + }; diff --git a/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch b/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch new file mode 100644 index 0000000000..5d3153ded4 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch @@ -0,0 +1,103 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -32,6 +32,9 @@ + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; ++ rootdisk-emmc = <&emmc_rootfs>; ++ rootdisk-sd = <&sd_rootfs>; ++ rootdisk-snfi = <&ubi_rootfs>; + }; + + cpus { +@@ -233,6 +236,26 @@ + assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; + non-removable; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ block-partition-env { ++ partname = "ubootenv"; ++ nvmem-layout { ++ compatible = "u-boot,env-layout"; ++ }; ++ }; ++ emmc_rootfs: block-partition-production { ++ partname = "production"; ++ }; ++ }; ++ }; ++ }; + }; + + &mmc1 { +@@ -249,6 +272,26 @@ + vqmmc-supply = <®_3p3v>; + assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; ++ ++ card@0 { ++ compatible = "mmc-card"; ++ reg = <0>; ++ ++ block { ++ compatible = "block-device"; ++ partitions { ++ block-partition-env { ++ partname = "ubootenv"; ++ nvmem-layout { ++ compatible = "u-boot,env-layout"; ++ }; ++ }; ++ sd_rootfs: block-partition-production { ++ partname = "production"; ++ }; ++ }; ++ }; ++ }; + }; + + &nandc { +@@ -283,14 +326,29 @@ + }; + + partition@80000 { +- label = "fip"; +- reg = <0x80000 0x200000>; +- read-only; +- }; +- +- ubi: partition@280000 { + label = "ubi"; +- reg = <0x280000 0x7d80000>; ++ reg = <0x80000 0x7f80000>; ++ compatible = "linux,ubi"; ++ ++ volumes { ++ ubi-volume-ubootenv { ++ volname = "ubootenv"; ++ nvmem-layout { ++ compatible = "u-boot,env-redundant-bool-layout"; ++ }; ++ }; ++ ++ ubi-volume-ubootenv2 { ++ volname = "ubootenv2"; ++ nvmem-layout { ++ compatible = "u-boot,env-redundant-bool-layout"; ++ }; ++ }; ++ ++ ubi_rootfs: ubi-volume-fit { ++ volname = "fit"; ++ }; ++ }; + }; + }; + }; diff --git a/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch b/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch new file mode 100644 index 0000000000..6e6810b42a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch @@ -0,0 +1,18 @@ +--- a/drivers/spi/spi-mt65xx.c ++++ b/drivers/spi/spi-mt65xx.c +@@ -1225,8 +1225,15 @@ static int mtk_spi_probe(struct platform + if (ret < 0) + return dev_err_probe(dev, ret, "failed to enable hclk\n"); + ++ ret = clk_prepare_enable(mdata->sel_clk); ++ if (ret < 0) { ++ clk_disable_unprepare(mdata->spi_hclk); ++ return dev_err_probe(dev, ret, "failed to enable sel_clk\n"); ++ } ++ + ret = clk_prepare_enable(mdata->spi_clk); + if (ret < 0) { ++ clk_disable_unprepare(mdata->sel_clk); + clk_disable_unprepare(mdata->spi_hclk); + return dev_err_probe(dev, ret, "failed to enable spi_clk\n"); + } diff --git a/target/linux/mediatek/patches-6.6/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch b/target/linux/mediatek/patches-6.6/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch new file mode 100644 index 0000000000..30be53518a --- /dev/null +++ b/target/linux/mediatek/patches-6.6/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch @@ -0,0 +1,37 @@ +From 3cf212c4ce6cd72c09bc47f35f539ba0afd4d106 Mon Sep 17 00:00:00 2001 +Message-Id: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Sun, 12 Mar 2023 16:40:31 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mtk_wed: rename + mtk_wed_get_memory_region in mtk_wed_get_reserved_memory_region + +This is a preliminary patch to move wed ilm/dlm and cpuboot properties in +dedicated dts nodes. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -234,8 +234,8 @@ int mtk_wed_mcu_msg_update(struct mtk_we + } + + static int +-mtk_wed_get_memory_region(struct mtk_wed_hw *hw, int index, +- struct mtk_wed_wo_memory_region *region) ++mtk_wed_get_reserved_memory_region(struct mtk_wed_hw *hw, int index, ++ struct mtk_wed_wo_memory_region *region) + { + struct reserved_mem *rmem; + struct device_node *np; +@@ -321,7 +321,7 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + if (index < 0) + continue; + +- ret = mtk_wed_get_memory_region(wo->hw, index, &mem_region[i]); ++ ret = mtk_wed_get_reserved_memory_region(wo->hw, index, &mem_region[i]); + if (ret) + return ret; + } diff --git a/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch new file mode 100644 index 0000000000..3ba485346c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch @@ -0,0 +1,66 @@ +From 247e566e3459481f1fa98733534bfed767e18b42 Mon Sep 17 00:00:00 2001 +Message-Id: <247e566e3459481f1fa98733534bfed767e18b42.1678620342.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Sat, 11 Mar 2023 16:32:41 +0100 +Subject: [PATCH net-next] arm64: dts: mt7986: move cpuboot in a dedicated node + +Signed-off-by: Lorenzo Bianconi +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -121,12 +121,6 @@ + reg = <0 0x151f8000 0 0x2000>; + no-map; + }; +- +- wo_boot: wo-boot@15194000 { +- reg = <0 0x15194000 0 0x1000>; +- no-map; +- }; +- + }; + + timer { +@@ -540,10 +534,11 @@ + interrupt-parent = <&gic>; + interrupts = ; + memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, +- <&wo_data>, <&wo_boot>; ++ <&wo_data>; + memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", +- "wo-data", "wo-boot"; ++ "wo-data"; + mediatek,wo-ccif = <&wo_ccif0>; ++ mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + + wed1: wed@15011000 { +@@ -553,10 +548,11 @@ + interrupt-parent = <&gic>; + interrupts = ; + memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, +- <&wo_data>, <&wo_boot>; ++ <&wo_data>; + memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", +- "wo-data", "wo-boot"; ++ "wo-data"; + mediatek,wo-ccif = <&wo_ccif1>; ++ mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + + wo_ccif0: syscon@151a5000 { +@@ -573,6 +569,11 @@ + interrupts = ; + }; + ++ wo_cpuboot: syscon@15194000 { ++ compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; ++ reg = <0 0x15194000 0 0x1000>; ++ }; ++ + eth: ethernet@15100000 { + compatible = "mediatek,mt7986-eth"; + reg = <0 0x15100000 0 0x80000>; diff --git a/target/linux/mediatek/patches-6.6/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch b/target/linux/mediatek/patches-6.6/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch new file mode 100644 index 0000000000..b4bea2087b --- /dev/null +++ b/target/linux/mediatek/patches-6.6/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch @@ -0,0 +1,81 @@ +From f292d1bf83ec160bef2532b58aa08f5b71041923 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> +References: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Sat, 11 Mar 2023 18:13:04 +0100 +Subject: [PATCH net-next 2/2] net: ethernet: mtk_wed: move cpuboot in a + dedicated dts node + +Since the cpuboot memory region is not part of the RAM SoC, move cpuboot +in a deidicated syscon node. +This patch helps to keep backward-compatibility with older version of +uboot codebase where we have a limit of 8 reserved-memory dts child +nodes. +Keep backward-compatibility with older dts version where cpuboot was +defined as reserved-memory child node. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 34 +++++++++++++++++---- + drivers/net/ethernet/mediatek/mtk_wed_wo.h | 3 +- + 2 files changed, 30 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -34,12 +34,23 @@ static struct mtk_wed_wo_memory_region m + + static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) + { +- return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); ++ u32 val; ++ ++ if (!wo->boot_regmap) ++ return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); ++ ++ if (regmap_read(wo->boot_regmap, reg, &val)) ++ val = ~0; ++ ++ return val; + } + + static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) + { +- writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); ++ if (wo->boot_regmap) ++ regmap_write(wo->boot_regmap, reg, val); ++ else ++ writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + } + + static struct sk_buff * +@@ -313,6 +324,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + u32 val, boot_cr; + int ret, i; + ++ wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, ++ "mediatek,wo-cpuboot"); ++ + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { + int index = of_property_match_string(wo->hw->node, +@@ -321,6 +335,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + if (index < 0) + continue; + ++ if (index == MTK_WED_WO_REGION_BOOT && !IS_ERR(wo->boot_regmap)) ++ continue; ++ + ret = mtk_wed_get_reserved_memory_region(wo->hw, index, &mem_region[i]); + if (ret) + return ret; +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -231,6 +231,7 @@ struct mtk_wed_wo_queue { + struct mtk_wed_wo { + struct mtk_wed_hw *hw; + ++ struct regmap *boot_regmap; + struct mtk_wed_wo_queue q_tx; + struct mtk_wed_wo_queue q_rx; + diff --git a/target/linux/mediatek/patches-6.6/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-6.6/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch new file mode 100644 index 0000000000..b4ba5b0d2d --- /dev/null +++ b/target/linux/mediatek/patches-6.6/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch @@ -0,0 +1,86 @@ +From f3565e6c2276411275e707a5442d3f69cc111273 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Lorenzo Bianconi +Date: Sun, 12 Mar 2023 18:51:47 +0100 +Subject: [PATCH net-next 1/3] net: ethernet: mtk_wed: move ilm a dedicated dts + node + +Since the ilm memory region is not part of the RAM SoC, move ilm in a +deidicated syscon node. +This patch helps to keep backward-compatibility with older version of +uboot codebase where we have a limit of 8 reserved-memory dts child +nodes. +Keep backward-compatibility with older dts version where ilm was defined +as reserved-memory child node. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 55 ++++++++++++++++++--- + 1 file changed, 49 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -316,6 +316,39 @@ next: + } + + static int ++mtk_wed_mcu_load_ilm(struct mtk_wed_wo *wo) ++{ ++ struct mtk_wed_wo_memory_region *ilm_region; ++ struct resource res; ++ struct device_node *np; ++ int ret; ++ ++ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ilm", 0); ++ if (!np) ++ return 0; ++ ++ ret = of_address_to_resource(np, 0, &res); ++ of_node_put(np); ++ ++ if (ret < 0) ++ return ret; ++ ++ ilm_region = &mem_region[MTK_WED_WO_REGION_ILM]; ++ ilm_region->phy_addr = res.start; ++ ilm_region->size = resource_size(&res); ++ ilm_region->addr = devm_ioremap(wo->hw->dev, res.start, ++ resource_size(&res)); ++ ++ if (!IS_ERR(ilm_region->addr)) ++ return 0; ++ ++ ret = PTR_ERR(ilm_region->addr); ++ ilm_region->addr = NULL; ++ ++ return ret; ++} ++ ++static int + mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) + { + const struct mtk_wed_fw_trailer *trailer; +@@ -324,14 +357,20 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + u32 val, boot_cr; + int ret, i; + ++ mtk_wed_mcu_load_ilm(wo); + wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, + "mediatek,wo-cpuboot"); + + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +- int index = of_property_match_string(wo->hw->node, +- "memory-region-names", +- mem_region[i].name); ++ int index; ++ ++ if (mem_region[i].addr) ++ continue; ++ ++ index = of_property_match_string(wo->hw->node, ++ "memory-region-names", ++ mem_region[i].name); + if (index < 0) + continue; + diff --git a/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch new file mode 100644 index 0000000000..c92fcd43ce --- /dev/null +++ b/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch @@ -0,0 +1,57 @@ +From b74ba226be2c45091b93bd49192bdd6d2178729e Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Lorenzo Bianconi +Date: Mon, 13 Mar 2023 15:45:16 +0100 +Subject: [PATCH net-next 3/3] net: ethernet: mtk_wed: move dlm a dedicated dts + node + +Since the dlm memory region is not part of the RAM SoC, move dlm in a +deidicated syscon node. +This patch helps to keep backward-compatibility with older version of +uboot codebase where we have a limit of 8 reserved-memory dts child +nodes. +Keep backward-compatibility with older dts version where dlm was defined +as reserved-memory child node. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_wed.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1320,6 +1320,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device + struct device_node *np; + int index; + ++ np = of_parse_phandle(dev->hw->node, "mediatek,wo-dlm", 0); ++ if (np) { ++ struct resource res; ++ int ret; ++ ++ ret = of_address_to_resource(np, 0, &res); ++ of_node_put(np); ++ ++ if (ret < 0) ++ return ret; ++ ++ dev->rro.miod_phys = res.start; ++ goto out; ++ } ++ ++ /* For backward compatibility, we need to check if DLM ++ * node is defined through reserved memory property. ++ */ + index = of_property_match_string(dev->hw->node, "memory-region-names", + "wo-dlm"); + if (index < 0) +@@ -1336,6 +1354,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device + return -ENODEV; + + dev->rro.miod_phys = rmem->base; ++out: + dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; + + return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, diff --git a/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch new file mode 100644 index 0000000000..0ba9bd7cf0 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch @@ -0,0 +1,83 @@ +From 01561065af5bf1d2a4244896d897e3a1eafbcd46 Mon Sep 17 00:00:00 2001 +Message-Id: <01561065af5bf1d2a4244896d897e3a1eafbcd46.1678717704.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Mon, 13 Mar 2023 15:10:56 +0100 +Subject: [PATCH net-next] arm64: dts: mt7986: move ilm in a dedicated node + +Since the ilm memory region is not part of the RAM SoC, move ilm in a +deidicated syscon node. +This patch helps to keep backward-compatibility with older version of +uboot codebase where we have a limit of 8 reserved-memory dts child +nodes. + +Signed-off-by: Lorenzo Bianconi +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 34 +++++++++++------------ + 1 file changed, 16 insertions(+), 18 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -97,16 +97,6 @@ + no-map; + }; + +- wo_ilm0: wo-ilm@151e0000 { +- reg = <0 0x151e0000 0 0x8000>; +- no-map; +- }; +- +- wo_ilm1: wo-ilm@151f0000 { +- reg = <0 0x151f0000 0 0x8000>; +- no-map; +- }; +- + wo_data: wo-data@4fd80000 { + reg = <0 0x4fd80000 0 0x240000>; + no-map; +@@ -533,11 +523,10 @@ + reg = <0 0x15010000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; +- memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, +- <&wo_data>; +- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", +- "wo-data"; ++ memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; + mediatek,wo-ccif = <&wo_ccif0>; ++ mediatek,wo-ilm = <&wo_ilm0>; + mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + +@@ -547,11 +536,10 @@ + reg = <0 0x15011000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; +- memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, +- <&wo_data>; +- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", +- "wo-data"; ++ memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; + mediatek,wo-ccif = <&wo_ccif1>; ++ mediatek,wo-ilm = <&wo_ilm1>; + mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + +@@ -569,6 +557,16 @@ + interrupts = ; + }; + ++ wo_ilm0: syscon@151e0000 { ++ compatible = "mediatek,mt7986-wo-ilm", "syscon"; ++ reg = <0 0x151e0000 0 0x8000>; ++ }; ++ ++ wo_ilm1: syscon@151f0000 { ++ compatible = "mediatek,mt7986-wo-ilm", "syscon"; ++ reg = <0 0x151f0000 0 0x8000>; ++ }; ++ + wo_cpuboot: syscon@15194000 { + compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; + reg = <0 0x15194000 0 0x1000>; diff --git a/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch new file mode 100644 index 0000000000..90b2bb91a2 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch @@ -0,0 +1,81 @@ +From 9f76be683a8ec498563c294bc1cc279468058302 Mon Sep 17 00:00:00 2001 +Message-Id: <9f76be683a8ec498563c294bc1cc279468058302.1678719283.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Mon, 13 Mar 2023 15:53:30 +0100 +Subject: [PATCH net-next] arm64: dts: mt7986: move dlm in a dedicated node + +Since the dlm memory region is not part of the RAM SoC, move dlm in a +deidicated syscon node. +This patch helps to keep backward-compatibility with older version of +uboot codebase where we have a limit of 8 reserved-memory dts child +nodes. + +Signed-off-by: Lorenzo Bianconi +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 30 ++++++++++++----------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -101,16 +101,6 @@ + reg = <0 0x4fd80000 0 0x240000>; + no-map; + }; +- +- wo_dlm0: wo-dlm@151e8000 { +- reg = <0 0x151e8000 0 0x2000>; +- no-map; +- }; +- +- wo_dlm1: wo-dlm@151f8000 { +- reg = <0 0x151f8000 0 0x2000>; +- no-map; +- }; + }; + + timer { +@@ -523,10 +513,11 @@ + reg = <0 0x15010000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; +- memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; +- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; ++ memory-region = <&wo_emi0>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-data"; + mediatek,wo-ccif = <&wo_ccif0>; + mediatek,wo-ilm = <&wo_ilm0>; ++ mediatek,wo-dlm = <&wo_dlm0>; + mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + +@@ -536,10 +527,11 @@ + reg = <0 0x15011000 0 0x1000>; + interrupt-parent = <&gic>; + interrupts = ; +- memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; +- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; ++ memory-region = <&wo_emi1>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-data"; + mediatek,wo-ccif = <&wo_ccif1>; + mediatek,wo-ilm = <&wo_ilm1>; ++ mediatek,wo-dlm = <&wo_dlm1>; + mediatek,wo-cpuboot = <&wo_cpuboot>; + }; + +@@ -567,6 +559,16 @@ + reg = <0 0x151f0000 0 0x8000>; + }; + ++ wo_dlm0: syscon@151e8000 { ++ compatible = "mediatek,mt7986-wo-dlm", "syscon"; ++ reg = <0 0x151e8000 0 0x2000>; ++ }; ++ ++ wo_dlm1: syscon@151f8000 { ++ compatible = "mediatek,mt7986-wo-dlm", "syscon"; ++ reg = <0 0x151f8000 0 0x2000>; ++ }; ++ + wo_cpuboot: syscon@15194000 { + compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; + reg = <0 0x15194000 0 0x1000>; diff --git a/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch b/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch new file mode 100644 index 0000000000..8b86c50429 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch @@ -0,0 +1,34 @@ +--- + drivers/leds/Kconfig | 10 ++++++++++ + drivers/leds/Makefile | 1 + + 2 files changed, 11 insertions(+) + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -874,6 +874,16 @@ source "drivers/leds/flash/Kconfig" + comment "RGB LED drivers" + source "drivers/leds/rgb/Kconfig" + ++config LEDS_SMARTRG_LED ++ tristate "LED support for Adtran SmartRG" ++ depends on LEDS_CLASS && I2C && OF ++ help ++ This option enables support for the Adtran SmartRG platform ++ system LED driver. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called leds-smartrg-system. ++ + comment "LED Triggers" + source "drivers/leds/trigger/Kconfig" + +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -76,6 +76,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o + obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o + obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o + obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o ++obj-$(CONFIG_LEDS_SMARTRG_LED) += leds-smartrg-system.o + obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o + obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o + obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch new file mode 100644 index 0000000000..71cb3006ab --- /dev/null +++ b/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -0,0 +1,599 @@ +From: Lorenzo Bianconi +Date: Thu, 2 Nov 2023 16:47:07 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mediatek: split tx and rx fields + in mtk_soc_data struct + +Split tx and rx fields in mtk_soc_data struct. This is a preliminary +patch to roll back to QDMA for MT7986 SoC in order to fix a hw hang +if the device receives a corrupted packet. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 210 ++++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +-- + 2 files changed, 139 insertions(+), 100 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1264,7 +1264,7 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1280,16 +1280,16 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +@@ -1538,7 +1538,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1579,7 +1579,7 @@ static int mtk_tx_map(struct sk_buff *sk + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1592,7 +1592,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1635,7 +1635,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1644,7 +1644,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, NULL, false); +@@ -1669,7 +1669,7 @@ static int mtk_cal_txd_req(struct mtk_et + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1810,7 +1810,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1978,7 +1978,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1997,7 +1997,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -2035,7 +2035,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -2046,7 +2046,7 @@ static int mtk_xdp_submit_frame(struct m + + unmap: + while (htxd != txd) { +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, NULL, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2177,7 +2177,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2312,7 +2312,7 @@ static int mtk_poll_rx(struct napi_struc + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2436,7 +2436,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2487,7 +2487,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, &bq, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2577,7 +2577,7 @@ static int mtk_napi_rx(struct napi_struc + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2593,10 +2593,10 @@ static int mtk_napi_rx(struct napi_struc + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2605,7 +2605,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2728,14 +2728,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2790,15 +2790,15 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2809,7 +2809,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2900,7 +2900,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2917,7 +2917,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3280,7 +3280,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3330,7 +3330,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3356,9 +3356,9 @@ static irqreturn_t mtk_handle_irq(int ir + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3376,10 +3376,10 @@ static void mtk_poll_controller(struct n + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3545,7 +3545,7 @@ static int mtk_open(struct net_device *d + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3628,7 +3628,7 @@ static int mtk_stop(struct net_device *d + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -4107,9 +4107,9 @@ static int mtk_hw_init(struct mtk_eth *e + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5270,11 +5270,15 @@ static const struct mtk_soc_data mt2701_ + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5290,11 +5294,15 @@ static const struct mtk_soc_data mt7621_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5312,11 +5320,15 @@ static const struct mtk_soc_data mt7622_ + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5333,11 +5345,15 @@ static const struct mtk_soc_data mt7623_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5352,11 +5368,15 @@ static const struct mtk_soc_data mt7629_ + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5374,11 +5394,15 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .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, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5396,11 +5420,15 @@ static const struct mtk_soc_data mt7986_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .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, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5418,11 +5446,15 @@ static const struct mtk_soc_data mt7988_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .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, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5435,11 +5467,15 @@ static const struct mtk_soc_data rt5350_ + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -327,8 +327,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -348,8 +348,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1209,10 +1209,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1230,13 +1229,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) diff --git a/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch new file mode 100644 index 0000000000..8b7d5c0a1c --- /dev/null +++ b/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -0,0 +1,123 @@ +From: Daniel Golle +Date: Tue, 10 Oct 2023 21:06:43 +0200 +Subject: [PATCH net-next 2/2] net: ethernet: mediatek: use QDMA instead of + ADMAv2 on MT7981 and MT7986 + +ADMA is plagued by RX hangs which can't easily detected and happen upon +receival of a corrupted package. +Use QDMA just like on netsys v1 which is also still present and usable, and +doesn't suffer from that problem. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++----------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -110,16 +110,16 @@ static const struct mtk_reg_map mt7986_r + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1232,7 +1232,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_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -2184,7 +2184,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2296,7 +2296,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2846,7 +2846,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -4053,7 +4053,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -5400,11 +5400,11 @@ static const struct mtk_soc_data mt7981_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + +@@ -5426,11 +5426,11 @@ static const struct mtk_soc_data mt7986_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + diff --git a/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch new file mode 100644 index 0000000000..11b52d07ab --- /dev/null +++ b/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 18 Jan 2024 12:51:32 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix WED + wifi reset + +The WLAN + WED reset sequence relies on being able to receive interrupts from +the card, in order to synchronize individual steps with the firmware. +When WED is stopped, leave interrupts running and rely on the driver turning +off unwanted ones. +WED DMA also needs to be disabled before resetting. + +Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { ++ mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); +- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + + if (!mtk_wed_get_rx_capa(dev)) + return; +@@ -1090,7 +1090,6 @@ static void + mtk_wed_deinit(struct mtk_wed_device *dev) + { + mtk_wed_stop(dev); +- mtk_wed_dma_disable(dev); + + wed_clr(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WDMA_INT_AGENT_EN | +@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d + static void + mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) + { +- if (!dev->running) +- return; +- + mtk_wed_set_ext_int(dev, !!mask); + wed_w32(dev, MTK_WED_INT_MASK, mask); + } From 23a8e2825635a994814abb6770642b458c9ae01e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 01:57:56 +0000 Subject: [PATCH 078/108] mediatek: 6.6: drop backport patches Drop all backport patches that are now included in kernel 6.6. Signed-off-by: Daniel Golle --- ...-overlays-to-built-from-.dtso-named-.patch | 44 - ...ek-mt7986-add-support-for-RX-Wireles.patch | 106 - ...s-mt7986-harmonize-device-node-order.patch | 166 -- ...7986-add-crypto-related-device-nodes.patch | 68 - ...4-v6.2-arm64-dts-mt7986-add-i2c-node.patch | 37 - ...s-mediatek-mt7986-Add-SoC-compatible.patch | 61 - ...-mt7986-add-spi-related-device-nodes.patch | 157 - ...-mt7986-add-usb-related-device-nodes.patch | 127 - ...-mt7986-add-mmc-related-device-nodes.patch | 160 - ...mt7986-add-pcie-related-device-nodes.patch | 118 - ...6.3-arm64-dts-mt7986-add-Bananapi-R3.patch | 689 ----- ...ropagate-chassis-type-where-possible.patch | 323 -- .../012-v6.5-arm64-dts-mt7986-add-PWM.patch | 38 - ...5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch | 43 - ...-set-Wifi-Leds-low-active-for-BPI-R3.patch | 27 - ...-use-size-of-reserved-partition-for-.patch | 46 - ...m64-dts-mt7986-add-thermal-and-efuse.patch | 80 - ...5-arm64-dts-mt7986-add-thermal-zones.patch | 51 - ...-add-pwm-fan-and-cooling-maps-to-BPI.patch | 64 - ...-increase-bl2-partition-on-NAND-of-B.patch | 41 - ...-declare-SPI-NAND-present-on-BPI-R64.patch | 70 - ...-handle-interrupts-from-MT7531-switc.patch | 32 - ...llow-configuring-uart-rx-tx-and-rts-.patch | 88 - ...-add-pull_type-attribute-for-mediate.patch | 100 - ....3-pinctrl-add-mt7981-pinctrl-driver.patch | 1094 ------- ...-add-missing-options-to-PINCTRL_MT79.patch | 30 - ...diatek-fix-pull_type-data-for-MT7981.patch | 76 - ...-assign-functions-to-configure-pin-b.patch | 41 - ...-gate-Propagate-struct-device-with-m.patch | 536 ---- ...mux-Propagate-struct-device-where-po.patch | 140 - ...-mtk-Propagate-struct-device-for-com.patch | 181 -- ...-mux-Propagate-struct-device-for-mtk.patch | 103 - ...mediatek-clk-mtk-Add-dummy-clock-ops.patch | 74 - ...tch-to-mtk_clk_simple_probe-where-po.patch | 790 ----- ...-clk-mtk-Extend-mtk_clk_simple_probe.patch | 189 -- ...-mt7986-topckgen-Properly-keep-some-.patch | 97 - ...-mt7986-topckgen-Migrate-to-mtk_clk_.patch | 88 - ...986-apmixed-Use-PLL_AO-flag-to-set-c.patch | 38 - ...-clock-mediatek-add-mt7981-clock-IDs.patch | 237 -- ...lk-mediatek-add-MT7981-clock-support.patch | 932 ------ ...ngs-clock-Add-compatibles-for-MT7981.patch | 75 - ...mediatek-sgmiisys-Convert-to-DT-sche.patch | 107 - ...pcs-mediatek-sgmiisys-add-MT7981-SoC.patch | 37 - ...-mediatek-add-support-for-MT7986-SoC.patch | 47 - ...d-Inline-Crypto-Engine-clock-control.patch | 57 - ...fix-two-spelling-mistakes-in-comment.patch | 36 - ...d-open-coding-by-using-mmc_op_tuning.patch | 39 - ...405-v6.2-mt7986-trng-add-rng-support.patch | 43 - ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 1204 -------- ...phy-mediatek-ge-soc-support-PHY-LEDs.patch | 524 ---- .../804-v6.2-pwm-add-mt7986-support.patch | 23 - ...-extend-pinctrl-moore-to-support-new.patch | 129 - ...mtk_thermal-Fix-kernel-doc-function-.patch | 37 - ...mtk_thermal-Use-devm_platform_get_an.patch | 37 - ...mtk-Use-function-pointer-for-raw_to_.patch | 60 - ...mtk-Add-support-for-MT7986-and-MT798.patch | 236 -- ...mediatek-Relocate-driver-to-mediatek.patch | 2602 ----------------- ...mediatek-Add-the-Low-Voltage-Thermal.patch | 1298 -------- ...mal-mediatek-Add-LVTS-thermal-contro.patch | 186 -- ...mal-mediatek-Add-AP-domain-to-LVTS-t.patch | 35 - ...-Add-a-thermal-zone-devdata-accessor.patch | 65 - ...-thermal_zone_device-structure-type-.patch | 55 - ...-the-thermal-zone-devdata-accessor-i.patch | 74 - ...e-the-right-device-for-devm_thermal_.patch | 201 -- ...e-device-internal-thermal-zone-struc.patch | 79 - ...se-thermal_zone_device_type-accessor.patch | 62 - ...mediatek-Control-buffer-enablement-t.patch | 81 - ...-mediatek-Add-support-for-MT8365-SoC.patch | 123 - ...mediatek-Add-delay-after-thermal-ban.patch | 50 - ...mediatek-lvts_thermal-Fix-sensor-1-i.patch | 46 - ...mediatek-lvts_thermal-Add-AP-domain-.patch | 149 - ...rivers-mediatek-Add-delay-after-ther.patch | 53 - ...mediatek-Add-temperature-constraints.patch | 78 - ...mediatek-Use-devm_of_iomap-to-avoid-.patch | 53 - ...mediatek-Change-clk_prepare_enable-t.patch | 100 - ...-mediatek-Use-of_address_to_resource.patch | 36 - ...rivers-mediatek-Use-devm_of_iomap-to.patch | 57 - ...mediatek-lvts_thermal-Register-therm.patch | 37 - ...mediatek-lvts_thermal-Remove-redunda.patch | 28 - ...mediatek-lvts_thermal-Handle-IRQ-on-.patch | 40 - ...mediatek-lvts_thermal-Honor-sensors-.patch | 120 - ...mediatek-lvts_thermal-Use-offset-thr.patch | 77 - ...mediatek-lvts_thermal-Disable-undesi.patch | 51 - ...mediatek-lvts_thermal-Don-t-leave-th.patch | 70 - ...mediatek-lvts_thermal-Manage-thresho.patch | 156 - ...mediatek-lvts-Fix-parameter-check-in.patch | 29 - ...mediatek-Clean-up-redundant-dev_err_.patch | 33 - ...mediatek-lvts_thermal-Make-readings-.patch | 95 - ...mediatek-auxadc_thermal-Removed-call.patch | 30 - ...v6.2-i2c-mediatek-add-mt7986-support.patch | 44 - ...evm_platform_get_and_ioremap_resourc.patch | 42 - ...t65xx-drop-of_match_ptr-for-ID-table.patch | 33 - ...-mediatek-add-support-for-MT7981-SoC.patch | 47 - ...oC-mediatek-mt7986-add-common-header.patch | 269 -- ...7986-support-etdm-in-platform-driver.patch | 430 --- ...-mediatek-mt7986-add-platform-driver.patch | 685 ----- ...t7986-add-machine-driver-with-wm8960.patch | 243 -- ...-mediatek-mt7986-wm8960-add-mt7986-w.patch | 87 - ...-mediatek-mt7986-afe-add-audio-afe-d.patch | 180 -- 99 files changed, 18382 deletions(-) delete mode 100644 target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch delete mode 100644 target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch delete mode 100644 target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch delete mode 100644 target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch delete mode 100644 target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch delete mode 100644 target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch delete mode 100644 target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch delete mode 100644 target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch delete mode 100644 target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch delete mode 100644 target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch delete mode 100644 target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch delete mode 100644 target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch delete mode 100644 target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch delete mode 100644 target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch delete mode 100644 target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch delete mode 100644 target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch delete mode 100644 target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch delete mode 100644 target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch delete mode 100644 target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch delete mode 100644 target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch delete mode 100644 target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch delete mode 100644 target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch delete mode 100644 target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch delete mode 100644 target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch delete mode 100644 target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch delete mode 100644 target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch delete mode 100644 target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch delete mode 100644 target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch delete mode 100644 target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch delete mode 100644 target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch delete mode 100644 target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch delete mode 100644 target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch delete mode 100644 target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch delete mode 100644 target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch delete mode 100644 target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch delete mode 100644 target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch delete mode 100644 target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch delete mode 100644 target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch delete mode 100644 target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch delete mode 100644 target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch delete mode 100644 target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch delete mode 100644 target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch delete mode 100644 target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch delete mode 100644 target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch delete mode 100644 target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch delete mode 100644 target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch diff --git a/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch b/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch deleted file mode 100644 index 17c5c6098a..0000000000 --- a/target/linux/mediatek/patches-6.6/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 363547d2191cbc32ca954ba75d72908712398ff2 Mon Sep 17 00:00:00 2001 -From: Andrew Davis -Date: Mon, 24 Oct 2022 12:34:28 -0500 -Subject: [PATCH] kbuild: Allow DTB overlays to built from .dtso named source - files - -Currently DTB Overlays (.dtbo) are build from source files with the same -extension (.dts) as the base DTs (.dtb). This may become confusing and -even lead to wrong results. For example, a composite DTB (created from a -base DTB and a set of overlays) might have the same name as one of the -overlays that create it. - -Different files should be generated from differently named sources. - .dtb <-> .dts - .dtbo <-> .dtso - -We do not remove the ability to compile DTBO files from .dts files here, -only add a new rule allowing the .dtso file name. The current .dts named -overlays can be renamed with time. After all have been renamed we can -remove the other rule. - -Signed-off-by: Andrew Davis -Reviewed-by: Geert Uytterhoeven -Tested-by: Geert Uytterhoeven -Reviewed-by: Frank Rowand -Tested-by: Frank Rowand -Link: https://lore.kernel.org/r/20221024173434.32518-2-afd@ti.com -Signed-off-by: Rob Herring ---- - scripts/Makefile.lib | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -408,6 +408,9 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_T - $(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) - -+$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE -+ $(call if_changed_dep,dtc) -+ - dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) - - # Bzip2 diff --git a/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch b/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch deleted file mode 100644 index 970e0f92bb..0000000000 --- a/target/linux/mediatek/patches-6.6/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 2c4daed9580164522859fa100128be408cc69be2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:16 +0100 -Subject: [PATCH 01/19] arm64: dts: mediatek: mt7986: add support for RX - Wireless Ethernet Dispatch - -Similar to TX Wireless Ethernet Dispatch, introduce RX Wireless Ethernet -Dispatch to offload traffic received by the wlan interface to lan/wan -one. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 65 +++++++++++++++++++++++ - 1 file changed, 65 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -76,6 +76,47 @@ - no-map; - reg = <0 0x4fc00000 0 0x00100000>; - }; -+ -+ wo_emi0: wo-emi@4fd00000 { -+ reg = <0 0x4fd00000 0 0x40000>; -+ no-map; -+ }; -+ -+ wo_emi1: wo-emi@4fd40000 { -+ reg = <0 0x4fd40000 0 0x40000>; -+ no-map; -+ }; -+ -+ wo_ilm0: wo-ilm@151e0000 { -+ reg = <0 0x151e0000 0 0x8000>; -+ no-map; -+ }; -+ -+ wo_ilm1: wo-ilm@151f0000 { -+ reg = <0 0x151f0000 0 0x8000>; -+ no-map; -+ }; -+ -+ wo_data: wo-data@4fd80000 { -+ reg = <0 0x4fd80000 0 0x240000>; -+ no-map; -+ }; -+ -+ wo_dlm0: wo-dlm@151e8000 { -+ reg = <0 0x151e8000 0 0x2000>; -+ no-map; -+ }; -+ -+ wo_dlm1: wo-dlm@151f8000 { -+ reg = <0 0x151f8000 0 0x2000>; -+ no-map; -+ }; -+ -+ wo_boot: wo-boot@15194000 { -+ reg = <0 0x15194000 0 0x1000>; -+ no-map; -+ }; -+ - }; - - timer { -@@ -239,6 +280,11 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -+ memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -+ <&wo_data>, <&wo_boot>; -+ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -+ "wo-data", "wo-boot"; -+ mediatek,wo-ccif = <&wo_ccif0>; - }; - - wed1: wed@15011000 { -@@ -247,6 +293,25 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -+ memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -+ <&wo_data>, <&wo_boot>; -+ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -+ "wo-data", "wo-boot"; -+ mediatek,wo-ccif = <&wo_ccif1>; -+ }; -+ -+ wo_ccif0: syscon@151a5000 { -+ compatible = "mediatek,mt7986-wo-ccif", "syscon"; -+ reg = <0 0x151a5000 0 0x1000>; -+ interrupt-parent = <&gic>; -+ interrupts = ; -+ }; -+ -+ wo_ccif1: syscon@151ad000 { -+ compatible = "mediatek,mt7986-wo-ccif", "syscon"; -+ reg = <0 0x151ad000 0 0x1000>; -+ interrupt-parent = <&gic>; -+ interrupts = ; - }; - - eth: ethernet@15100000 { diff --git a/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch b/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch deleted file mode 100644 index b5091687a3..0000000000 --- a/target/linux/mediatek/patches-6.6/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 438e53828c08cf0e8a65b61cf6ce1e4b6620551a Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:50:24 +0100 -Subject: [PATCH 02/19] arm64: dts: mt7986: harmonize device node order - -This arrange device tree nodes in alphabetical order. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106085034.12582-2-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 94 ++++++++++---------- - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 22 ++--- - 2 files changed, 58 insertions(+), 58 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -54,6 +54,53 @@ - }; - }; - -+&pio { -+ uart1_pins: uart1-pins { -+ mux { -+ function = "uart"; -+ groups = "uart1"; -+ }; -+ }; -+ -+ uart2_pins: uart2-pins { -+ mux { -+ function = "uart"; -+ groups = "uart2"; -+ }; -+ }; -+ -+ wf_2g_5g_pins: wf-2g-5g-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_2g", "wf_5g"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_dbdc_pins: wf-dbdc-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_dbdc"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+}; -+ - &switch { - ports { - #address-cells = <1>; -@@ -121,50 +168,3 @@ - pinctrl-0 = <&wf_2g_5g_pins>; - pinctrl-1 = <&wf_dbdc_pins>; - }; -- --&pio { -- uart1_pins: uart1-pins { -- mux { -- function = "uart"; -- groups = "uart1"; -- }; -- }; -- -- uart2_pins: uart2-pins { -- mux { -- function = "uart"; -- groups = "uart2"; -- }; -- }; -- -- wf_2g_5g_pins: wf-2g-5g-pins { -- mux { -- function = "wifi"; -- groups = "wf_2g", "wf_5g"; -- }; -- conf { -- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -- "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -- "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -- "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -- "WF1_TOP_CLK", "WF1_TOP_DATA"; -- drive-strength = <4>; -- }; -- }; -- -- wf_dbdc_pins: wf-dbdc-pins { -- mux { -- function = "wifi"; -- groups = "wf_dbdc"; -- }; -- conf { -- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -- "WF0_TOP_CLK", "WF0_TOP_DATA"; -- drive-strength = <4>; -- }; -- }; --}; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -25,10 +25,6 @@ - }; - }; - --&uart0 { -- status = "okay"; --}; -- - ð { - status = "okay"; - -@@ -99,13 +95,6 @@ - }; - }; - --&wifi { -- status = "okay"; -- pinctrl-names = "default", "dbdc"; -- pinctrl-0 = <&wf_2g_5g_pins>; -- pinctrl-1 = <&wf_dbdc_pins>; --}; -- - &pio { - wf_2g_5g_pins: wf-2g-5g-pins { - mux { -@@ -138,3 +127,14 @@ - }; - }; - }; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&wifi { -+ status = "okay"; -+ pinctrl-names = "default", "dbdc"; -+ pinctrl-0 = <&wf_2g_5g_pins>; -+ pinctrl-1 = <&wf_dbdc_pins>; -+}; diff --git a/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch deleted file mode 100644 index 5706531a46..0000000000 --- a/target/linux/mediatek/patches-6.6/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From ffb05357b47f06b2b4d1e14ba89169e28feb727b Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:50:27 +0100 -Subject: [PATCH 03/19] arm64: dts: mt7986: add crypto related device nodes - -This patch adds crypto engine support for MT7986. - -Signed-off-by: Vic Wu -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20221106085034.12582-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 4 ++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 4 ++++ - 3 files changed, 23 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -25,6 +25,10 @@ - }; - }; - -+&crypto { -+ status = "okay"; -+}; -+ - ð { - status = "okay"; - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -223,6 +223,21 @@ - status = "disabled"; - }; - -+ crypto: crypto@10320000 { -+ compatible = "inside-secure,safexcel-eip97"; -+ reg = <0 0x10320000 0 0x40000>; -+ interrupts = , -+ , -+ , -+ ; -+ interrupt-names = "ring0", "ring1", "ring2", "ring3"; -+ clocks = <&infracfg CLK_INFRA_EIP97_CK>; -+ clock-names = "infra_eip97_ck"; -+ assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>; -+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>; -+ status = "disabled"; -+ }; -+ - uart0: serial@11002000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -25,6 +25,10 @@ - }; - }; - -+&crypto { -+ status = "okay"; -+}; -+ - ð { - status = "okay"; - diff --git a/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch b/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch deleted file mode 100644 index 0e5b77a11b..0000000000 --- a/target/linux/mediatek/patches-6.6/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b49b7dc404ded1d89cbc568d875009a5c1ed4ef6 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 6 Nov 2022 09:50:29 +0100 -Subject: [PATCH 04/19] arm64: dts: mt7986: add i2c node - -Add i2c Node to mt7986 devicetree. - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20221106085034.12582-7-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -279,6 +279,20 @@ - status = "disabled"; - }; - -+ i2c0: i2c@11008000 { -+ compatible = "mediatek,mt7986-i2c"; -+ reg = <0 0x11008000 0 0x90>, -+ <0 0x10217080 0 0x80>; -+ interrupts = ; -+ clock-div = <5>; -+ clocks = <&infracfg CLK_INFRA_I2C0_CK>, -+ <&infracfg CLK_INFRA_AP_DMA_CK>; -+ clock-names = "main", "dma"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch b/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch deleted file mode 100644 index 8201b47df6..0000000000 --- a/target/linux/mediatek/patches-6.6/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2cd6022800d6da7822e169f3e6f7f790c1431445 Mon Sep 17 00:00:00 2001 -From: Matthias Brugger -Date: Mon, 14 Nov 2022 13:16:53 +0100 -Subject: [PATCH 05/19] arm64: dts: mediatek: mt7986: Add SoC compatible - -Missing SoC compatible in the board file causes dt bindings check. - -Signed-off-by: Matthias Brugger -Link: https://lore.kernel.org/r/20221114121653.14739-1-matthias.bgg@kernel.org -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 2 +- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 1 + - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 2 +- - arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 3 +++ - 4 files changed, 6 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -9,7 +9,7 @@ - - / { - model = "MediaTek MT7986a RFB"; -- compatible = "mediatek,mt7986a-rfb"; -+ compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; - - aliases { - serial0 = &uart0; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -10,6 +10,7 @@ - #include - - / { -+ compatible = "mediatek,mt7986a"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -9,7 +9,7 @@ - - / { - model = "MediaTek MT7986b RFB"; -- compatible = "mediatek,mt7986b-rfb"; -+ compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; - - aliases { - serial0 = &uart0; ---- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi -@@ -5,6 +5,9 @@ - */ - - #include "mt7986a.dtsi" -+/ { -+ compatible = "mediatek,mt7986b"; -+}; - - &pio { - compatible = "mediatek,mt7986b-pinctrl"; diff --git a/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch deleted file mode 100644 index 3e5e3d880a..0000000000 --- a/target/linux/mediatek/patches-6.6/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch +++ /dev/null @@ -1,157 +0,0 @@ -From f4029538f063a845dc9aae46cce4cf386e6253a5 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 18 Nov 2022 20:01:21 +0100 -Subject: [PATCH 06/19] arm64: dts: mt7986: add spi related device nodes - -This patch adds spi support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221118190126.100895-7-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 35 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 ++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 35 ++++++++++++++++++++ - 3 files changed, 98 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -59,6 +59,20 @@ - }; - - &pio { -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_2"; -+ }; -+ }; -+ - uart1_pins: uart1-pins { - mux { - function = "uart"; -@@ -105,6 +119,27 @@ - }; - }; - -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ }; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+}; -+ - &switch { - ports { - #address-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -294,6 +294,34 @@ - status = "disabled"; - }; - -+ spi0: spi@1100a000 { -+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0 0x1100a000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPI_SEL>, -+ <&infracfg CLK_INFRA_SPI0_CK>, -+ <&infracfg CLK_INFRA_SPI0_HCK_CK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; -+ status = "disabled"; -+ }; -+ -+ spi1: spi@1100b000 { -+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0 0x1100b000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPIM_MST_SEL>, -+ <&infracfg CLK_INFRA_SPI1_CK>, -+ <&infracfg CLK_INFRA_SPI1_HCK_CK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; -+ status = "disabled"; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -100,6 +100,20 @@ - }; - - &pio { -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_2"; -+ }; -+ }; -+ - wf_2g_5g_pins: wf-2g-5g-pins { - mux { - function = "wifi"; -@@ -132,6 +146,27 @@ - }; - }; - -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ }; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+}; -+ - &uart0 { - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch deleted file mode 100644 index 53567c66a0..0000000000 --- a/target/linux/mediatek/patches-6.6/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 9e8e24ab716098e617195ce29b88e84608bf2108 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:42 +0100 -Subject: [PATCH 07/19] arm64: dts: mt7986: add usb related device nodes - -This patch adds USB support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: Chunfeng Yun -Link: https://lore.kernel.org/r/20230106152845.88717-3-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 8 +++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 55 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 8 +++ - 3 files changed, 71 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -140,6 +140,10 @@ - status = "okay"; - }; - -+&ssusb { -+ status = "okay"; -+}; -+ - &switch { - ports { - #address-cells = <1>; -@@ -201,6 +205,10 @@ - status = "okay"; - }; - -+&usb_phy { -+ status = "okay"; -+}; -+ - &wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -322,6 +322,61 @@ - status = "disabled"; - }; - -+ ssusb: usb@11200000 { -+ compatible = "mediatek,mt7986-xhci", -+ "mediatek,mtk-xhci"; -+ reg = <0 0x11200000 0 0x2e00>, -+ <0 0x11203e00 0 0x0100>; -+ reg-names = "mac", "ippc"; -+ interrupts = ; -+ clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, -+ <&infracfg CLK_INFRA_IUSB_CK>, -+ <&infracfg CLK_INFRA_IUSB_133_CK>, -+ <&infracfg CLK_INFRA_IUSB_66M_CK>, -+ <&topckgen CLK_TOP_U2U3_XHCI_SEL>; -+ clock-names = "sys_ck", -+ "ref_ck", -+ "mcu_ck", -+ "dma_ck", -+ "xhci_ck"; -+ phys = <&u2port0 PHY_TYPE_USB2>, -+ <&u3port0 PHY_TYPE_USB3>, -+ <&u2port1 PHY_TYPE_USB2>; -+ status = "disabled"; -+ }; -+ -+ usb_phy: t-phy@11e10000 { -+ compatible = "mediatek,mt7986-tphy", -+ "mediatek,generic-tphy-v2"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0 0x11e10000 0x1700>; -+ status = "disabled"; -+ -+ u2port0: usb-phy@0 { -+ reg = <0x0 0x700>; -+ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, -+ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; -+ clock-names = "ref", "da_ref"; -+ #phy-cells = <1>; -+ }; -+ -+ u3port0: usb-phy@700 { -+ reg = <0x700 0x900>; -+ clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; -+ clock-names = "ref"; -+ #phy-cells = <1>; -+ }; -+ -+ u2port1: usb-phy@1000 { -+ reg = <0x1000 0x700>; -+ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, -+ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; -+ clock-names = "ref", "da_ref"; -+ #phy-cells = <1>; -+ }; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -167,10 +167,18 @@ - status = "okay"; - }; - -+&ssusb { -+ status = "okay"; -+}; -+ - &uart0 { - status = "okay"; - }; - -+&usb_phy { -+ status = "okay"; -+}; -+ - &wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; diff --git a/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch deleted file mode 100644 index 9c0a48149d..0000000000 --- a/target/linux/mediatek/patches-6.6/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch +++ /dev/null @@ -1,160 +0,0 @@ -From c1744e9e75a6a8abc7c893f349bcbf725b9c0d74 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:43 +0100 -Subject: [PATCH 08/19] arm64: dts: mt7986: add mmc related device nodes - -This patch adds mmc support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230106152845.88717-4-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 96 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++ - 2 files changed, 111 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -5,6 +5,8 @@ - */ - - /dts-v1/; -+#include -+ - #include "mt7986a.dtsi" - - / { -@@ -23,6 +25,24 @@ - device_type = "memory"; - reg = <0 0x40000000 0 0x40000000>; - }; -+ -+ reg_1p8v: regulator-1p8v { -+ compatible = "regulator-fixed"; -+ regulator-name = "fixed-1.8V"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator-3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "fixed-3.3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; - }; - - &crypto { -@@ -58,7 +78,83 @@ - }; - }; - -+&mmc0 { -+ pinctrl-names = "default", "state_uhs"; -+ pinctrl-0 = <&mmc0_pins_default>; -+ pinctrl-1 = <&mmc0_pins_uhs>; -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ cap-mmc-highspeed; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ hs400-ds-delay = <0x14014>; -+ vmmc-supply = <®_3p3v>; -+ vqmmc-supply = <®_1p8v>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ status = "okay"; -+}; -+ - &pio { -+ mmc0_pins_default: mmc0-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ mmc0_pins_uhs: mmc0-uhs-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -345,6 +345,21 @@ - status = "disabled"; - }; - -+ mmc0: mmc@11230000 { -+ compatible = "mediatek,mt7986-mmc"; -+ reg = <0 0x11230000 0 0x1000>, -+ <0 0x11c20000 0 0x1000>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>, -+ <&infracfg CLK_INFRA_MSDC_HCK_CK>, -+ <&infracfg CLK_INFRA_MSDC_CK>, -+ <&infracfg CLK_INFRA_MSDC_133M_CK>, -+ <&infracfg CLK_INFRA_MSDC_66M_CK>; -+ clock-names = "source", "hclk", "source_cg", "bus_clk", -+ "sys_cg"; -+ status = "disabled"; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch b/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch deleted file mode 100644 index adc6394857..0000000000 --- a/target/linux/mediatek/patches-6.6/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 87a42ef1d6cf602e4aa40555b4404cad6149a90f Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:44 +0100 -Subject: [PATCH 09/19] arm64: dts: mt7986: add pcie related device nodes - -This patch adds PCIe support for MT7986. - -Signed-off-by: Jieyy Yang -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230106152845.88717-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 16 ++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 52 ++++++++++++++++++++ - 2 files changed, 68 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -93,6 +93,15 @@ - non-removable; - no-sd; - no-sdio; -+}; -+ -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie_pins>; -+ status = "okay"; -+}; -+ -+&pcie_phy { - status = "okay"; - }; - -@@ -155,6 +164,13 @@ - }; - }; - -+ pcie_pins: pcie-pins { -+ mux { -+ function = "pcie"; -+ groups = "pcie_clk", "pcie_wake", "pcie_pereset"; -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - / { - compatible = "mediatek,mt7986a"; -@@ -360,6 +361,57 @@ - status = "disabled"; - }; - -+ pcie: pcie@11280000 { -+ compatible = "mediatek,mt7986-pcie", -+ "mediatek,mt8192-pcie"; -+ device_type = "pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ reg = <0x00 0x11280000 0x00 0x4000>; -+ reg-names = "pcie-mac"; -+ interrupts = ; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0x00 0x20000000 0x00 -+ 0x20000000 0x00 0x10000000>; -+ clocks = <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, -+ <&infracfg CLK_INFRA_IPCIE_CK>, -+ <&infracfg CLK_INFRA_IPCIER_CK>, -+ <&infracfg CLK_INFRA_IPCIEB_CK>; -+ clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m"; -+ status = "disabled"; -+ -+ phys = <&pcie_port PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &pcie_intc 0>, -+ <0 0 0 2 &pcie_intc 1>, -+ <0 0 0 3 &pcie_intc 2>, -+ <0 0 0 4 &pcie_intc 3>; -+ pcie_intc: interrupt-controller { -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ interrupt-controller; -+ }; -+ }; -+ -+ pcie_phy: t-phy@11c00000 { -+ compatible = "mediatek,mt7986-tphy", -+ "mediatek,generic-tphy-v2"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "disabled"; -+ -+ pcie_port: pcie-phy@11c00000 { -+ reg = <0 0x11c00000 0 0x20000>; -+ clocks = <&clk40m>; -+ clock-names = "ref"; -+ #phy-cells = <1>; -+ }; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch b/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch deleted file mode 100644 index 38f159c74e..0000000000 --- a/target/linux/mediatek/patches-6.6/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch +++ /dev/null @@ -1,689 +0,0 @@ -From a751f7412e0098801673b80bc7a4738ae7d710ce Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Fri, 6 Jan 2023 16:28:45 +0100 -Subject: [PATCH 10/19] arm64: dts: mt7986: add Bananapi R3 - -Add support for Bananapi R3 SBC. - -- SD/eMMC support (switching first 4 bits of data-bus with sw6/D) -- SPI-NAND/NOR support (switched CS by sw5/C) -- all rj45 ports and both SFP working (eth1/lan4) -- all USB-Ports + SIM-Slot tested -- i2c and all uarts tested -- wifi tested (with eeprom calibration data) - -The device can boot from all 4 storage options. Both, SPI and MMC, can -be switched using hardware switches on the board, see -https://wiki.banana-pi.org/Banana_Pi_BPI-R3#Jumper_setting - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230106152845.88717-6-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/Makefile | 5 + - .../mt7986a-bananapi-bpi-r3-emmc.dtso | 29 ++ - .../mt7986a-bananapi-bpi-r3-nand.dtso | 55 +++ - .../mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 68 +++ - .../mediatek/mt7986a-bananapi-bpi-r3-sd.dtso | 23 + - .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 450 ++++++++++++++++++ - 6 files changed, 630 insertions(+) - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts - ---- a/arch/arm64/boot/dts/mediatek/Makefile -+++ b/arch/arm64/boot/dts/mediatek/Makefile -@@ -7,6 +7,11 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-ev - dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Author: Sam.Shih -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/mmc@11230000"; -+ __overlay__ { -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ cap-mmc-highspeed; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ hs400-ds-delay = <0x14014>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ status = "okay"; -+ }; -+ }; -+}; -+ ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -@@ -0,0 +1,55 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+/* -+ * Authors: Daniel Golle -+ * Frank Wunderlich -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/spi@1100a000"; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "reserved"; -+ reg = <0x80000 0x300000>; -+ }; -+ -+ partition@380000 { -+ label = "fip"; -+ reg = <0x380000 0x200000>; -+ read-only; -+ }; -+ -+ partition@580000 { -+ label = "ubi"; -+ reg = <0x580000 0x7a80000>; -+ }; -+ }; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -0,0 +1,68 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+/* -+ * Authors: Daniel Golle -+ * Frank Wunderlich -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/spi@1100a000"; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x20000>; -+ read-only; -+ }; -+ -+ partition@20000 { -+ label = "reserved"; -+ reg = <0x20000 0x20000>; -+ }; -+ -+ partition@40000 { -+ label = "u-boot-env"; -+ reg = <0x40000 0x40000>; -+ }; -+ -+ partition@80000 { -+ label = "reserved2"; -+ reg = <0x80000 0x80000>; -+ }; -+ -+ partition@100000 { -+ label = "fip"; -+ reg = <0x100000 0x80000>; -+ read-only; -+ }; -+ -+ partition@180000 { -+ label = "recovery"; -+ reg = <0x180000 0xa80000>; -+ }; -+ -+ partition@c00000 { -+ label = "fit"; -+ reg = <0xc00000 0x1400000>; -+ }; -+ }; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso -@@ -0,0 +1,23 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Author: Sam.Shih -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/mmc@11230000"; -+ __overlay__ { -+ bus-width = <4>; -+ max-frequency = <52000000>; -+ cap-sd-highspeed; -+ status = "okay"; -+ }; -+ }; -+}; -+ ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -0,0 +1,450 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Authors: Sam.Shih -+ * Frank Wunderlich -+ * Daniel Golle -+ */ -+ -+/dts-v1/; -+#include -+#include -+#include -+#include -+ -+#include "mt7986a.dtsi" -+ -+/ { -+ model = "Bananapi BPI-R3"; -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ aliases { -+ serial0 = &uart0; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ dcin: regulator-12vd { -+ compatible = "regulator-fixed"; -+ regulator-name = "12vd"; -+ regulator-min-microvolt = <12000000>; -+ regulator-max-microvolt = <12000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ -+ reset-key { -+ label = "reset"; -+ linux,code = ; -+ gpios = <&pio 9 GPIO_ACTIVE_LOW>; -+ }; -+ -+ wps-key { -+ label = "wps"; -+ linux,code = ; -+ gpios = <&pio 10 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ /* i2c of the left SFP cage (wan) */ -+ i2c_sfp1: i2c-gpio-0 { -+ compatible = "i2c-gpio"; -+ sda-gpios = <&pio 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ scl-gpios = <&pio 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ i2c-gpio,delay-us = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ /* i2c of the right SFP cage (lan) */ -+ i2c_sfp2: i2c-gpio-1 { -+ compatible = "i2c-gpio"; -+ sda-gpios = <&pio 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ scl-gpios = <&pio 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ i2c-gpio,delay-us = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ green_led: led-0 { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ gpios = <&pio 69 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ blue_led: led-1 { -+ color = ; -+ function = LED_FUNCTION_STATUS; -+ gpios = <&pio 86 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+ reg_1p8v: regulator-1p8v { -+ compatible = "regulator-fixed"; -+ regulator-name = "1.8vd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ vin-supply = <&dcin>; -+ }; -+ -+ reg_3p3v: regulator-3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "3.3vd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ vin-supply = <&dcin>; -+ }; -+ -+ /* left SFP cage (wan) */ -+ sfp1: sfp-1 { -+ compatible = "sff,sfp"; -+ i2c-bus = <&i2c_sfp1>; -+ los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; -+ mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; -+ tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; -+ tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ /* right SFP cage (lan) */ -+ sfp2: sfp-2 { -+ compatible = "sff,sfp"; -+ i2c-bus = <&i2c_sfp2>; -+ los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; -+ mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; -+ tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; -+ tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; -+ }; -+}; -+ -+&crypto { -+ status = "okay"; -+}; -+ -+ð { -+ status = "okay"; -+ -+ gmac0: mac@0 { -+ compatible = "mediatek,eth-mac"; -+ reg = <0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ -+ gmac1: mac@1 { -+ compatible = "mediatek,eth-mac"; -+ reg = <1>; -+ phy-mode = "2500base-x"; -+ sfp = <&sfp1>; -+ managed = "in-band-status"; -+ }; -+ -+ mdio: mdio-bus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+}; -+ -+&mdio { -+ switch: switch@1f { -+ compatible = "mediatek,mt7531"; -+ reg = <31>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&pio>; -+ interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; -+ reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; -+ }; -+}; -+ -+&mmc0 { -+ pinctrl-names = "default", "state_uhs"; -+ pinctrl-0 = <&mmc0_pins_default>; -+ pinctrl-1 = <&mmc0_pins_uhs>; -+ vmmc-supply = <®_3p3v>; -+ vqmmc-supply = <®_1p8v>; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c_pins>; -+ status = "okay"; -+}; -+ -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie_pins>; -+ status = "okay"; -+}; -+ -+&pcie_phy { -+ status = "okay"; -+}; -+ -+&pio { -+ i2c_pins: i2c-pins { -+ mux { -+ function = "i2c"; -+ groups = "i2c"; -+ }; -+ }; -+ -+ mmc0_pins_default: mmc0-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ mmc0_pins_uhs: mmc0-uhs-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ pcie_pins: pcie-pins { -+ mux { -+ function = "pcie"; -+ groups = "pcie_clk", "pcie_pereset"; -+ }; -+ }; -+ -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_0"; -+ }; -+ }; -+ -+ uart1_pins: uart1-pins { -+ mux { -+ function = "uart"; -+ groups = "uart1_rx_tx"; -+ }; -+ }; -+ -+ uart2_pins: uart2-pins { -+ mux { -+ function = "uart"; -+ groups = "uart2_0_rx_tx"; -+ }; -+ }; -+ -+ wf_2g_5g_pins: wf-2g-5g-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_2g", "wf_5g"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_dbdc_pins: wf-dbdc-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_dbdc"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_led_pins: wf-led-pins { -+ mux { -+ function = "led"; -+ groups = "wifi_led"; -+ }; -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ status = "okay"; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ status = "okay"; -+}; -+ -+&ssusb { -+ status = "okay"; -+}; -+ -+&switch { -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "wan"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan0"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan1"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan2"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "lan3"; -+ }; -+ -+ port5: port@5 { -+ reg = <5>; -+ label = "lan4"; -+ phy-mode = "2500base-x"; -+ sfp = <&sfp2>; -+ managed = "in-band-status"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; -+}; -+ -+&trng { -+ status = "okay"; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart2_pins>; -+ status = "okay"; -+}; -+ -+&usb_phy { -+ status = "okay"; -+}; -+ -+&watchdog { -+ status = "okay"; -+}; -+ -+&wifi { -+ status = "okay"; -+ pinctrl-names = "default", "dbdc"; -+ pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; -+ pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+}; -+ diff --git a/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch b/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch deleted file mode 100644 index 79038334c4..0000000000 --- a/target/linux/mediatek/patches-6.6/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 4c2d5411f4b101f7aa0fd74f80109e3afd6dc967 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 17 May 2023 12:11:08 +0200 -Subject: [PATCH 11/19] arm64: mediatek: Propagate chassis-type where possible - -The chassis-type string identifies the form-factor of the system: -add this property to all device trees of devices for which the form -factor is known. - -Signed-off-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230517101108.205654-1-angelogioacchino.delregno@collabora.com -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6755-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6779-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6795-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts | 1 + - .../boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8186-evb.dts | 1 + - 28 files changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT2712 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt2712-evb", "mediatek,mt2712"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6755-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6755-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6755 EVB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6755-evb", "mediatek,mt6755"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6779-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6779-evb.dts -@@ -10,6 +10,7 @@ - - / { - model = "MediaTek MT6779 EVB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6779-evb", "mediatek,mt6779"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6795-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6795-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6795 Evaluation Board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6795-evb", "mediatek,mt6795"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6797 Evaluation Board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6797-evb", "mediatek,mt6797"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts -@@ -12,6 +12,7 @@ - - / { - model = "Mediatek X20 Development Board"; -+ chassis-type = "embedded"; - compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -15,6 +15,7 @@ - - / { - model = "Bananapi BPI-R64"; -+ chassis-type = "embedded"; - compatible = "bananapi,bpi-r64", "mediatek,mt7622"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -15,6 +15,7 @@ - - / { - model = "MediaTek MT7622 RFB1 board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -16,6 +16,7 @@ - - / { - model = "Bananapi BPI-R3"; -+ chassis-type = "embedded"; - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT7986a RFB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT7986b RFB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts -@@ -11,6 +11,7 @@ - - / { - model = "Pumpkin MT8167"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8167-pumpkin", "mediatek,mt8167"; - - memory@40000000 { ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Hanawl"; -+ chassis-type = "laptop"; - compatible = "google,hana-rev7", "mediatek,mt8173"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Hana"; -+ chassis-type = "laptop"; - compatible = "google,hana-rev6", "google,hana-rev5", - "google,hana-rev4", "google,hana-rev3", - "google,hana", "mediatek,mt8173"; ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Elm"; -+ chassis-type = "laptop"; - compatible = "google,elm-rev8", "google,elm-rev7", "google,elm-rev6", - "google,elm-rev5", "google,elm-rev4", "google,elm-rev3", - "google,elm", "mediatek,mt8173"; ---- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts -@@ -10,6 +10,7 @@ - - / { - model = "MediaTek MT8173 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8173-evb", "mediatek,mt8173"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT8183 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8183-evb", "mediatek,mt8183"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google burnet board"; -+ chassis-type = "convertible"; - compatible = "google,burnet", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google damu board"; -+ chassis-type = "convertible"; - compatible = "google,damu", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google juniper sku16 board"; -+ chassis-type = "convertible"; - compatible = "google,juniper-sku16", "google,juniper", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek kakadu board sku22"; -+ chassis-type = "tablet"; - compatible = "google,kakadu-rev3-sku22", "google,kakadu-rev2-sku22", - "google,kakadu", "mediatek,mt8183"; - }; ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek kakadu board"; -+ chassis-type = "tablet"; - compatible = "google,kakadu-rev3", "google,kakadu-rev2", - "google,kakadu", "mediatek,mt8183"; - }; ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku16 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku16", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku272 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku272", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku288 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku288", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts -@@ -14,6 +14,7 @@ - - / { - model = "MediaTek krane sku0 board"; -+ chassis-type = "tablet"; - compatible = "google,krane-sku0", "google,krane", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts -@@ -14,6 +14,7 @@ - - / { - model = "MediaTek krane sku176 board"; -+ chassis-type = "tablet"; - compatible = "google,krane-sku176", "google,krane", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8186-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8186-evb.dts -@@ -7,6 +7,7 @@ - - / { - model = "MediaTek MT8186 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8186-evb", "mediatek,mt8186"; - - aliases { diff --git a/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch b/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch deleted file mode 100644 index e8c47945d6..0000000000 --- a/target/linux/mediatek/patches-6.6/012-v6.5-arm64-dts-mt7986-add-PWM.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 3b92c547e3d4a35c6214b3e7fa1103d0749d83b1 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 21 Apr 2023 15:20:44 +0200 -Subject: [PATCH 12/19] arm64: dts: mt7986: add PWM - -This adds pwm node to mt7986. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230421132047.42166-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -240,6 +240,20 @@ - status = "disabled"; - }; - -+ pwm: pwm@10048000 { -+ compatible = "mediatek,mt7986-pwm"; -+ reg = <0 0x10048000 0 0x1000>; -+ #clock-cells = <1>; -+ #pwm-cells = <2>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_PWM_SEL>, -+ <&infracfg CLK_INFRA_PWM_STA>, -+ <&infracfg CLK_INFRA_PWM1_CK>, -+ <&infracfg CLK_INFRA_PWM2_CK>; -+ clock-names = "top", "main", "pwm1", "pwm2"; -+ status = "disabled"; -+ }; -+ - uart0: serial@11002000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; diff --git a/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch b/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch deleted file mode 100644 index ce908e3d31..0000000000 --- a/target/linux/mediatek/patches-6.6/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 35e482bb599df010b4869017ff576dbb7a4d4c2e Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Fri, 21 Apr 2023 15:20:45 +0200 -Subject: [PATCH 13/19] arm64: dts: mt7986: add PWM to BPI-R3 - -Add pwm node and pinctrl to BananaPi R3 devicetree. - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230421132047.42166-6-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -275,6 +275,13 @@ - }; - }; - -+ pwm_pins: pwm-pins { -+ mux { -+ function = "pwm"; -+ groups = "pwm0", "pwm1_0"; -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; -@@ -345,6 +352,12 @@ - }; - }; - -+&pwm { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm_pins>; -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; diff --git a/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch b/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch deleted file mode 100644 index c7b38484f4..0000000000 --- a/target/linux/mediatek/patches-6.6/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ccdda5714446db8690505371442f7807f5d7c6fc Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 5 Feb 2023 18:48:33 +0100 -Subject: [PATCH 14/19] arm64: dts: mt7986: set Wifi Leds low-active for BPI-R3 - -Leds for Wifi are low-active, so add property to devicetree. - -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230205174833.107050-1-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -460,5 +460,9 @@ - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; - pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+ -+ led { -+ led-active-low; -+ }; - }; - diff --git a/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch b/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch deleted file mode 100644 index 0b84f1463a..0000000000 --- a/target/linux/mediatek/patches-6.6/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1423b4b780adcf3994e63a5988a62d5d1d509bb1 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 28 May 2023 13:33:42 +0200 -Subject: [PATCH 15/19] arm64: dts: mt7986: use size of reserved partition for - bl2 - -To store uncompressed bl2 more space is required than partition is -actually defined. - -There is currently no known usage of this reserved partition. -Openwrt uses same partition layout. - -We added same change to u-boot with commit d7bb1099 [1]. - -[1] https://source.denx.de/u-boot/u-boot/-/commit/d7bb109900c1ca754a0198b9afb50e3161ffc21e - -Cc: stable@vger.kernel.org -Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Daniel Golle -Link: https://lore.kernel.org/r/20230528113343.7649-1-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -27,15 +27,10 @@ - - partition@0 { - label = "bl2"; -- reg = <0x0 0x20000>; -+ reg = <0x0 0x40000>; - read-only; - }; - -- partition@20000 { -- label = "reserved"; -- reg = <0x20000 0x20000>; -- }; -- - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x40000>; diff --git a/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch b/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch deleted file mode 100644 index 0d12079d7c..0000000000 --- a/target/linux/mediatek/patches-6.6/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 40a5a767d698ef7a71f8be851ea18b0a7a8b47bd Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:33 +0200 -Subject: [PATCH 16/19] arm64: dts: mt7986: add thermal and efuse - -Add thermal related nodes to mt7986 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-3-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 36 ++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -337,6 +337,15 @@ - status = "disabled"; - }; - -+ auxadc: adc@1100d000 { -+ compatible = "mediatek,mt7986-auxadc"; -+ reg = <0 0x1100d000 0 0x1000>; -+ clocks = <&infracfg CLK_INFRA_ADC_26M_CK>; -+ clock-names = "main"; -+ #io-channel-cells = <1>; -+ status = "disabled"; -+ }; -+ - ssusb: usb@11200000 { - compatible = "mediatek,mt7986-xhci", - "mediatek,mtk-xhci"; -@@ -375,6 +384,21 @@ - status = "disabled"; - }; - -+ thermal: thermal@1100c800 { -+ #thermal-sensor-cells = <1>; -+ compatible = "mediatek,mt7986-thermal"; -+ reg = <0 0x1100c800 0 0x800>; -+ interrupts = ; -+ clocks = <&infracfg CLK_INFRA_THERM_CK>, -+ <&infracfg CLK_INFRA_ADC_26M_CK>, -+ <&infracfg CLK_INFRA_ADC_FRC_CK>; -+ clock-names = "therm", "auxadc", "adc_32k"; -+ mediatek,auxadc = <&auxadc>; -+ mediatek,apmixedsys = <&apmixedsys>; -+ nvmem-cells = <&thermal_calibration>; -+ nvmem-cell-names = "calibration-data"; -+ }; -+ - pcie: pcie@11280000 { - compatible = "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; -@@ -426,6 +450,17 @@ - }; - }; - -+ efuse: efuse@11d00000 { -+ compatible = "mediatek,mt7986-efuse", "mediatek,efuse"; -+ reg = <0 0x11d00000 0 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ thermal_calibration: calib@274 { -+ reg = <0x274 0xc>; -+ }; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; -@@ -567,5 +602,4 @@ - memory-region = <&wmcpu_emi>; - }; - }; -- - }; diff --git a/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch b/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch deleted file mode 100644 index 3fe3e885eb..0000000000 --- a/target/linux/mediatek/patches-6.6/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch +++ /dev/null @@ -1,51 +0,0 @@ -From bb78d0cf5117517f1ed296ae71048945d9107675 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:34 +0200 -Subject: [PATCH 17/19] arm64: dts: mt7986: add thermal-zones - -Add thermal-zones to mt7986 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-4-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 +++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -602,4 +602,32 @@ - memory-region = <&wmcpu_emi>; - }; - }; -+ -+ thermal-zones { -+ cpu_thermal: cpu-thermal { -+ polling-delay-passive = <1000>; -+ polling-delay = <1000>; -+ thermal-sensors = <&thermal 0>; -+ -+ trips { -+ cpu_trip_active_high: active-high { -+ temperature = <115000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ -+ cpu_trip_active_low: active-low { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ -+ cpu_trip_passive: passive { -+ temperature = <40000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ }; -+ }; -+ }; - }; diff --git a/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch b/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch deleted file mode 100644 index ca7d872a1b..0000000000 --- a/target/linux/mediatek/patches-6.6/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 5d90603b09e5814ffc38c47e79ccf9bc564f9296 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:35 +0200 -Subject: [PATCH 18/19] arm64: dts: mt7986: add pwm-fan and cooling-maps to - BPI-R3 dts - -Add pwm-fan and cooling-maps to BananaPi-R3 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 31 +++++++++++++++++++ - 1 file changed, 31 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -38,6 +38,15 @@ - regulator-always-on; - }; - -+ fan: pwm-fan { -+ compatible = "pwm-fan"; -+ #cooling-cells = <2>; -+ /* cooling level (0, 1, 2) - pwm inverted */ -+ cooling-levels = <255 96 0>; -+ pwms = <&pwm 0 10000 0>; -+ status = "okay"; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - -@@ -133,6 +142,28 @@ - }; - }; - -+&cpu_thermal { -+ cooling-maps { -+ cpu-active-high { -+ /* active: set fan to cooling level 2 */ -+ cooling-device = <&fan 2 2>; -+ trip = <&cpu_trip_active_high>; -+ }; -+ -+ cpu-active-low { -+ /* active: set fan to cooling level 1 */ -+ cooling-device = <&fan 1 1>; -+ trip = <&cpu_trip_active_low>; -+ }; -+ -+ cpu-passive { -+ /* passive: set fan to cooling level 0 */ -+ cooling-device = <&fan 0 0>; -+ trip = <&cpu_trip_passive>; -+ }; -+ }; -+}; -+ - &crypto { - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch b/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch deleted file mode 100644 index 9cc6cad0af..0000000000 --- a/target/linux/mediatek/patches-6.6/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6dd3b939370094eb79529683be84500f3c757404 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 6 Jun 2023 16:43:20 +0100 -Subject: [PATCH 19/19] arm64: dts: mt7986: increase bl2 partition on NAND of - Bananapi R3 - -The bootrom burned into the MT7986 SoC will try multiple locations on -the SPI-NAND flash to load bl2 in case the bl2 image located at the the -previously attempted offset is corrupt. - -Use 0x100000 instead of 0x80000 as partition size for bl2 on SPI-NAND, -allowing for up to four redundant copies of bl2 (typically sized a -bit less than 0x40000). - -Fixes: 8e01fb15b8157 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/ZH9UGF99RgzrHZ88@makrotopia.org -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -@@ -29,13 +29,13 @@ - - partition@0 { - label = "bl2"; -- reg = <0x0 0x80000>; -+ reg = <0x0 0x100000>; - read-only; - }; - -- partition@80000 { -+ partition@100000 { - label = "reserved"; -- reg = <0x80000 0x300000>; -+ reg = <0x100000 0x280000>; - }; - - partition@380000 { diff --git a/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch b/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch deleted file mode 100644 index 5fc55314ce..0000000000 --- a/target/linux/mediatek/patches-6.6/115-v6.5-arm64-dts-mt7622-declare-SPI-NAND-present-on-BPI-R64.patch +++ /dev/null @@ -1,70 +0,0 @@ -From d278f43f25beedfd0cb784d1dd0a9e7e8c8f123f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Apr 2023 20:15:53 +0100 -Subject: [PATCH] arm64: dts: mt7622: declare SPI-NAND present on BPI-R64 - -The SPI-NOR node in the device tree of the BananaPi R64 has most likely -been copied from the reference board's device tree even though the R64 -comes with an SPI-NAND chip rather than SPI-NOR. - -Setup the Serial NAND Flash Interface (SNFI) controller, enable -hardware BCH error detection and correction engine and add the SPI-NAND -chip including basic partitions, - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/ZEA96dmaXqTpk8u8@makrotopia.org -Signed-off-by: Matthias Brugger ---- - .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 38 ++++++++++++++++--- - 1 file changed, 33 insertions(+), 5 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -253,14 +253,42 @@ - status = "disabled"; - }; - --&nor_flash { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi_nor_pins>; -- status = "disabled"; -+&bch { -+ status = "okay"; -+}; - -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; - flash@0 { -- compatible = "jedec,spi-nor"; -+ compatible = "spi-nand"; - reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "fip"; -+ reg = <0x80000 0x200000>; -+ read-only; -+ }; -+ -+ ubi: partition@280000 { -+ label = "ubi"; -+ reg = <0x280000 0x7d80000>; -+ }; -+ }; - }; - }; - diff --git a/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch b/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch deleted file mode 100644 index 0a971c1f45..0000000000 --- a/target/linux/mediatek/patches-6.6/180-v6.5-arm64-dts-mt7622-handle-interrupts-from-MT7531-switc.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 983f37ee08acb60435744f1b1e2afea2d2a09c48 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Apr 2023 20:16:29 +0100 -Subject: [PATCH] arm64: dts: mt7622: handle interrupts from MT7531 switch on - BPI-R64 - -Since commit ba751e28d442 ("net: dsa: mt7530: add interrupt support") -the mt7530 driver can act as an interrupt controller. Wire up irq line -of the MT7531 switch on the BananaPi BPi-R64 board, so the status of -the PHYs of the five 1000Base-T ports doesn't need to be polled any -more. - -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/ZEA-DV_OsmFg5egL@makrotopia.org -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -154,6 +154,10 @@ - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&pio>; -+ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 54 0>; - - ports { diff --git a/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch b/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch deleted file mode 100644 index 3e16a533e1..0000000000 --- a/target/linux/mediatek/patches-6.6/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch +++ /dev/null @@ -1,88 +0,0 @@ -From f76e8bc416bebb0f7b9f57b1247eae945421c0b9 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sat, 8 Oct 2022 18:48:06 +0200 -Subject: [PATCH 1/2] pinctrl: mt7986: allow configuring uart rx/tx and rts/cts - separately - -Some mt7986 boards use uart rts/cts pins as gpio, -This patch allows to change rts/cts to gpio mode, but keep -rx/tx as UART function. - -Signed-off-by: Frank Wunderlich -Signed-off-by: Sam Shih -Link: https://lore.kernel.org/r/20221008164807.113590-1-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 32 ++++++++++++++++++----- - 1 file changed, 25 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -675,11 +675,17 @@ static int mt7986_uart1_1_funcs[] = { 4, - static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; - static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; - --static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, }; --static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, }; -+static int mt7986_uart1_2_rx_tx_pins[] = { 29, 30, }; -+static int mt7986_uart1_2_rx_tx_funcs[] = { 3, 3, }; - --static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, }; --static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, }; -+static int mt7986_uart1_2_cts_rts_pins[] = { 31, 32, }; -+static int mt7986_uart1_2_cts_rts_funcs[] = { 3, 3, }; -+ -+static int mt7986_uart2_0_rx_tx_pins[] = { 29, 30, }; -+static int mt7986_uart2_0_rx_tx_funcs[] = { 4, 4, }; -+ -+static int mt7986_uart2_0_cts_rts_pins[] = { 31, 32, }; -+static int mt7986_uart2_0_cts_rts_funcs[] = { 4, 4, }; - - static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; - static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; -@@ -708,6 +714,12 @@ static int mt7986_pcie_reset_funcs[] = { - static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; - static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; - -+static int mt7986_uart1_rx_tx_pins[] = { 42, 43, }; -+static int mt7986_uart1_rx_tx_funcs[] = { 1, 1, }; -+ -+static int mt7986_uart1_cts_rts_pins[] = { 44, 45, }; -+static int mt7986_uart1_cts_rts_funcs[] = { 1, 1, }; -+ - static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; - static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; - -@@ -749,6 +761,8 @@ static const struct group_desc mt7986_gr - PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), - PINCTRL_PIN_GROUP("i2c", mt7986_i2c), - PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), -+ PINCTRL_PIN_GROUP("uart1_rx_tx", mt7986_uart1_rx_tx), -+ PINCTRL_PIN_GROUP("uart1_cts_rts", mt7986_uart1_cts_rts), - PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), - PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), - PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), -@@ -760,8 +774,10 @@ static const struct group_desc mt7986_gr - PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), - PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), - PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), -- PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2), -- PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0), -+ PINCTRL_PIN_GROUP("uart1_2_rx_tx", mt7986_uart1_2_rx_tx), -+ PINCTRL_PIN_GROUP("uart1_2_cts_rts", mt7986_uart1_2_cts_rts), -+ PINCTRL_PIN_GROUP("uart2_0_rx_tx", mt7986_uart2_0_rx_tx), -+ PINCTRL_PIN_GROUP("uart2_0_cts_rts", mt7986_uart2_0_cts_rts), - PINCTRL_PIN_GROUP("spi0", mt7986_spi0), - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), - PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), -@@ -800,7 +816,9 @@ static const char *mt7986_pwm_groups[] = - static const char *mt7986_spi_groups[] = { - "spi0", "spi0_wp_hold", "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; - static const char *mt7986_uart_groups[] = { -- "uart1_0", "uart1_1", "uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", -+ "uart1_0", "uart1_1", "uart1_rx_tx", "uart1_cts_rts", -+ "uart1_2_rx_tx", "uart1_2_cts_rts", -+ "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0_rx_tx", "uart2_0_cts_rts", - "uart2_0", "uart2_1", "uart0", "uart1", "uart2", - }; - static const char *mt7986_wdt_groups[] = { "watchdog", }; diff --git a/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch b/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch deleted file mode 100644 index 47ded1aeb5..0000000000 --- a/target/linux/mediatek/patches-6.6/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 822d774abbcc66b811e28c68b59b40b964ba5b46 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:01:13 +0100 -Subject: [PATCH 2/2] pinctrl: mediatek: add pull_type attribute for mediatek - MT7986 SoC - -Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -add SoC specify 'pull_type' attribute for bias configuration. - -This patch add pull_type attribute to pinctrl-mt7986.c, and make -bias_set_combo and bias_get_combo available to mediatek MT7986 SoC. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106080114.7426-7-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 56 +++++++++++++++++++++++ - 1 file changed, 56 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -407,6 +407,60 @@ static const struct mtk_pin_field_calc m - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), - }; - -+static const unsigned int mt7986_pull_type[] = { -+ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -+ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -+ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -+ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -+ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -+ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -+ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -+ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -+ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -+ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -+ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -+ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -+ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -+ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -+ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -+ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -+ MTK_PULL_PU_PD_TYPE,/*100*/ -+}; -+ - static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), -@@ -868,6 +922,7 @@ static struct mtk_pin_soc mt7986a_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, -@@ -889,6 +944,7 @@ static struct mtk_pin_soc mt7986b_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, diff --git a/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch b/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch deleted file mode 100644 index 46dfa24b7b..0000000000 --- a/target/linux/mediatek/patches-6.6/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch +++ /dev/null @@ -1,1094 +0,0 @@ -From 6c83b2d94fcca735cf7d8aa7a55a4957eb404a9d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 00:34:56 +0000 -Subject: [PATCH] pinctrl: add mt7981 pinctrl driver - -Add pinctrl driver for the MediaTek MT7981 SoC, based on the driver -which can also be found the SDK. - -Signed-off-by: Daniel Golle -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/ef5112946d16cacc67e65e439ba7b52a9950c1bb.1674693008.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/Kconfig | 5 + - drivers/pinctrl/mediatek/Makefile | 1 + - drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1048 +++++++++++++++++++++ - 3 files changed, 1054 insertions(+) - create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c - ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -127,6 +127,11 @@ config PINCTRL_MT7622 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7981 -+ bool "Mediatek MT7981 pin control" -+ depends on OF -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT7986 - bool "Mediatek MT7986 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o - obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o -+obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o ---- /dev/null -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c -@@ -0,0 +1,1048 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * The MT7981 driver based on Linux generic pinctrl binding. -+ * -+ * Copyright (C) 2020 MediaTek Inc. -+ * Author: Sam Shih -+ */ -+ -+#include "pinctrl-moore.h" -+ -+#define MT7981_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 mt7981_pin_mode_range[] = { -+ PIN_FIELD(0, 56, 0x300, 0x10, 0, 4), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = { -+ PIN_FIELD(0, 56, 0x0, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_di_range[] = { -+ PIN_FIELD(0, 56, 0x200, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_do_range[] = { -+ PIN_FIELD(0, 56, 0x100, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x90, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = { -+ PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = { -+ PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3), -+ -+ PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), -+ -+ PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), -+ PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3), -+ PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1), -+}; -+ -+static const unsigned int mt7981_pull_type[] = { -+ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -+ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -+ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -+ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -+ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -+ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -+ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -+ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -+ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -+ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -+ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -+ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -+ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -+ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -+ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -+ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -+ MTK_PULL_PU_PD_TYPE,/*100*/ -+}; -+ -+static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { -+ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range), -+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range), -+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range), -+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range), -+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range), -+ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range), -+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range), -+ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range), -+ [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range), -+ [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range), -+ [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range), -+ [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range), -+}; -+ -+static const struct mtk_pin_desc mt7981_pins[] = { -+ MT7981_PIN(0, "GPIO_WPS"), -+ MT7981_PIN(1, "GPIO_RESET"), -+ MT7981_PIN(2, "SYS_WATCHDOG"), -+ MT7981_PIN(3, "PCIE_PERESET_N"), -+ MT7981_PIN(4, "JTAG_JTDO"), -+ MT7981_PIN(5, "JTAG_JTDI"), -+ MT7981_PIN(6, "JTAG_JTMS"), -+ MT7981_PIN(7, "JTAG_JTCLK"), -+ MT7981_PIN(8, "JTAG_JTRST_N"), -+ MT7981_PIN(9, "WO_JTAG_JTDO"), -+ MT7981_PIN(10, "WO_JTAG_JTDI"), -+ MT7981_PIN(11, "WO_JTAG_JTMS"), -+ MT7981_PIN(12, "WO_JTAG_JTCLK"), -+ MT7981_PIN(13, "WO_JTAG_JTRST_N"), -+ MT7981_PIN(14, "USB_VBUS"), -+ MT7981_PIN(15, "PWM0"), -+ MT7981_PIN(16, "SPI0_CLK"), -+ MT7981_PIN(17, "SPI0_MOSI"), -+ MT7981_PIN(18, "SPI0_MISO"), -+ MT7981_PIN(19, "SPI0_CS"), -+ MT7981_PIN(20, "SPI0_HOLD"), -+ MT7981_PIN(21, "SPI0_WP"), -+ MT7981_PIN(22, "SPI1_CLK"), -+ MT7981_PIN(23, "SPI1_MOSI"), -+ MT7981_PIN(24, "SPI1_MISO"), -+ MT7981_PIN(25, "SPI1_CS"), -+ MT7981_PIN(26, "SPI2_CLK"), -+ MT7981_PIN(27, "SPI2_MOSI"), -+ MT7981_PIN(28, "SPI2_MISO"), -+ MT7981_PIN(29, "SPI2_CS"), -+ MT7981_PIN(30, "SPI2_HOLD"), -+ MT7981_PIN(31, "SPI2_WP"), -+ MT7981_PIN(32, "UART0_RXD"), -+ MT7981_PIN(33, "UART0_TXD"), -+ MT7981_PIN(34, "PCIE_CLK_REQ"), -+ MT7981_PIN(35, "PCIE_WAKE_N"), -+ MT7981_PIN(36, "SMI_MDC"), -+ MT7981_PIN(37, "SMI_MDIO"), -+ MT7981_PIN(38, "GBE_INT"), -+ MT7981_PIN(39, "GBE_RESET"), -+ MT7981_PIN(40, "WF_DIG_RESETB"), -+ MT7981_PIN(41, "WF_CBA_RESETB"), -+ MT7981_PIN(42, "WF_XO_REQ"), -+ MT7981_PIN(43, "WF_TOP_CLK"), -+ MT7981_PIN(44, "WF_TOP_DATA"), -+ MT7981_PIN(45, "WF_HB1"), -+ MT7981_PIN(46, "WF_HB2"), -+ MT7981_PIN(47, "WF_HB3"), -+ MT7981_PIN(48, "WF_HB4"), -+ MT7981_PIN(49, "WF_HB0"), -+ MT7981_PIN(50, "WF_HB0_B"), -+ MT7981_PIN(51, "WF_HB5"), -+ MT7981_PIN(52, "WF_HB6"), -+ MT7981_PIN(53, "WF_HB7"), -+ MT7981_PIN(54, "WF_HB8"), -+ MT7981_PIN(55, "WF_HB9"), -+ MT7981_PIN(56, "WF_HB10"), -+}; -+ -+/* List all groups consisting of these pins dedicated to the enablement of -+ * certain hardware block and the corresponding mode for all of the pins. -+ * The hardware probably has multiple combinations of these pinouts. -+ */ -+ -+/* WA_AICE */ -+static int mt7981_wa_aice1_pins[] = { 0, 1, }; -+static int mt7981_wa_aice1_funcs[] = { 2, 2, }; -+ -+static int mt7981_wa_aice2_pins[] = { 0, 1, }; -+static int mt7981_wa_aice2_funcs[] = { 3, 3, }; -+ -+static int mt7981_wa_aice3_pins[] = { 28, 29, }; -+static int mt7981_wa_aice3_funcs[] = { 3, 3, }; -+ -+static int mt7981_wm_aice1_pins[] = { 9, 10, }; -+static int mt7981_wm_aice1_funcs[] = { 2, 2, }; -+ -+static int mt7981_wm_aice2_pins[] = { 30, 31, }; -+static int mt7981_wm_aice2_funcs[] = { 5, 5, }; -+ -+/* WM_UART */ -+static int mt7981_wm_uart_0_pins[] = { 0, 1, }; -+static int mt7981_wm_uart_0_funcs[] = { 5, 5, }; -+ -+static int mt7981_wm_uart_1_pins[] = { 20, 21, }; -+static int mt7981_wm_uart_1_funcs[] = { 4, 4, }; -+ -+static int mt7981_wm_uart_2_pins[] = { 30, 31, }; -+static int mt7981_wm_uart_2_funcs[] = { 3, 3, }; -+ -+/* DFD */ -+static int mt7981_dfd_pins[] = { 0, 1, 4, 5, }; -+static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, }; -+ -+/* SYS_WATCHDOG */ -+static int mt7981_watchdog_pins[] = { 2, }; -+static int mt7981_watchdog_funcs[] = { 1, }; -+ -+static int mt7981_watchdog1_pins[] = { 13, }; -+static int mt7981_watchdog1_funcs[] = { 5, }; -+ -+/* PCIE_PERESET_N */ -+static int mt7981_pcie_pereset_pins[] = { 3, }; -+static int mt7981_pcie_pereset_funcs[] = { 1, }; -+ -+/* JTAG */ -+static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, }; -+static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, }; -+ -+/* WM_JTAG */ -+static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, }; -+static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, }; -+ -+static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, }; -+static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; -+ -+/* WO0_JTAG */ -+static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, }; -+static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, }; -+ -+static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, }; -+static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; -+ -+/* UART2 */ -+static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; -+static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; -+ -+/* GBE_LED0 */ -+static int mt7981_gbe_led0_pins[] = { 8, }; -+static int mt7981_gbe_led0_funcs[] = { 3, }; -+ -+/* PTA_EXT */ -+static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, }; -+static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, }; -+ -+static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, }; -+static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, }; -+ -+/* PWM2 */ -+static int mt7981_pwm2_pins[] = { 7, }; -+static int mt7981_pwm2_funcs[] = { 4, }; -+ -+/* NET_WO0_UART_TXD */ -+static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, }; -+static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, }; -+ -+static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, }; -+static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, }; -+ -+static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, }; -+static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, }; -+ -+/* SPI1 */ -+static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, }; -+static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, }; -+ -+/* I2C */ -+static int mt7981_i2c0_0_pins[] = { 6, 7, }; -+static int mt7981_i2c0_0_funcs[] = { 6, 6, }; -+ -+static int mt7981_i2c0_1_pins[] = { 30, 31, }; -+static int mt7981_i2c0_1_funcs[] = { 4, 4, }; -+ -+static int mt7981_i2c0_2_pins[] = { 36, 37, }; -+static int mt7981_i2c0_2_funcs[] = { 2, 2, }; -+ -+static int mt7981_u2_phy_i2c_pins[] = { 30, 31, }; -+static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, }; -+ -+static int mt7981_u3_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, }; -+ -+static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, }; -+ -+static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, }; -+ -+/* DFD_NTRST */ -+static int mt7981_dfd_ntrst_pins[] = { 8, }; -+static int mt7981_dfd_ntrst_funcs[] = { 6, }; -+ -+/* PWM0 */ -+static int mt7981_pwm0_0_pins[] = { 13, }; -+static int mt7981_pwm0_0_funcs[] = { 2, }; -+ -+static int mt7981_pwm0_1_pins[] = { 15, }; -+static int mt7981_pwm0_1_funcs[] = { 1, }; -+ -+/* PWM1 */ -+static int mt7981_pwm1_0_pins[] = { 14, }; -+static int mt7981_pwm1_0_funcs[] = { 2, }; -+ -+static int mt7981_pwm1_1_pins[] = { 15, }; -+static int mt7981_pwm1_1_funcs[] = { 3, }; -+ -+/* GBE_LED1 */ -+static int mt7981_gbe_led1_pins[] = { 13, }; -+static int mt7981_gbe_led1_funcs[] = { 3, }; -+ -+/* PCM */ -+static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 }; -+static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, }; -+ -+/* UDI */ -+static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, }; -+static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, }; -+ -+/* DRV_VBUS */ -+static int mt7981_drv_vbus_pins[] = { 14, }; -+static int mt7981_drv_vbus_funcs[] = { 1, }; -+ -+/* EMMC */ -+static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; -+static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; -+ -+/* SNFI */ -+static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, }; -+static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, }; -+ -+/* SPI0 */ -+static int mt7981_spi0_pins[] = { 16, 17, 18, 19, }; -+static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI0 */ -+static int mt7981_spi0_wp_hold_pins[] = { 20, 21, }; -+static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, }; -+ -+/* SPI1 */ -+static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, }; -+static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI2 */ -+static int mt7981_spi2_pins[] = { 26, 27, 28, 29, }; -+static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI2 */ -+static int mt7981_spi2_wp_hold_pins[] = { 30, 31, }; -+static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, }; -+ -+/* UART1 */ -+static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, }; -+static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, }; -+ -+static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; -+static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; -+ -+/* UART2 */ -+static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; -+static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; -+ -+/* UART0 */ -+static int mt7981_uart0_pins[] = { 32, 33, }; -+static int mt7981_uart0_funcs[] = { 1, 1, }; -+ -+/* PCIE_CLK_REQ */ -+static int mt7981_pcie_clk_pins[] = { 34, }; -+static int mt7981_pcie_clk_funcs[] = { 2, }; -+ -+/* PCIE_WAKE_N */ -+static int mt7981_pcie_wake_pins[] = { 35, }; -+static int mt7981_pcie_wake_funcs[] = { 2, }; -+ -+/* MDC_MDIO */ -+static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, }; -+static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, }; -+ -+static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, }; -+static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, }; -+ -+/* WF0_MODE1 */ -+static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }; -+static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -+ -+/* WF0_MODE3 */ -+static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 }; -+static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 }; -+ -+/* WF2G_LED */ -+static int mt7981_wf2g_led0_pins[] = { 30, }; -+static int mt7981_wf2g_led0_funcs[] = { 2, }; -+ -+static int mt7981_wf2g_led1_pins[] = { 34, }; -+static int mt7981_wf2g_led1_funcs[] = { 1, }; -+ -+/* WF5G_LED */ -+static int mt7981_wf5g_led0_pins[] = { 31, }; -+static int mt7981_wf5g_led0_funcs[] = { 2, }; -+ -+static int mt7981_wf5g_led1_pins[] = { 35, }; -+static int mt7981_wf5g_led1_funcs[] = { 1, }; -+ -+/* MT7531_INT */ -+static int mt7981_mt7531_int_pins[] = { 38, }; -+static int mt7981_mt7531_int_funcs[] = { 1, }; -+ -+/* ANT_SEL */ -+static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 }; -+static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; -+ -+static const struct group_desc mt7981_groups[] = { -+ /* @GPIO(0,1): WA_AICE(2) */ -+ PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1), -+ /* @GPIO(0,1): WA_AICE(3) */ -+ PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2), -+ /* @GPIO(0,1): WM_UART(5) */ -+ PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0), -+ /* @GPIO(0,1,4,5): DFD(6) */ -+ PINCTRL_PIN_GROUP("dfd", mt7981_dfd), -+ /* @GPIO(2): SYS_WATCHDOG(1) */ -+ PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog), -+ /* @GPIO(3): PCIE_PERESET_N(1) */ -+ PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset), -+ /* @GPIO(4,8) JTAG(1) */ -+ PINCTRL_PIN_GROUP("jtag", mt7981_jtag), -+ /* @GPIO(4,8) WM_JTAG(2) */ -+ PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0), -+ /* @GPIO(9,13) WO0_JTAG(1) */ -+ PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), -+ /* @GPIO(4,7) WM_JTAG(3) */ -+ PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), -+ /* @GPIO(8) GBE_LED0(3) */ -+ PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), -+ /* @GPIO(4,6) PTA_EXT(4) */ -+ PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0), -+ /* @GPIO(7) PWM2(4) */ -+ PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2), -+ /* @GPIO(8) NET_WO0_UART_TXD(4) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0), -+ /* @GPIO(4,7) SPI1(5) */ -+ PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0), -+ /* @GPIO(6,7) I2C(5) */ -+ PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0), -+ /* @GPIO(0,1,4,5): DFD_NTRST(6) */ -+ PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst), -+ /* @GPIO(9,10): WM_AICE(2) */ -+ PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1), -+ /* @GPIO(13): PWM0(2) */ -+ PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0), -+ /* @GPIO(15): PWM0(1) */ -+ PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1), -+ /* @GPIO(14): PWM1(2) */ -+ PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0), -+ /* @GPIO(15): PWM1(3) */ -+ PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1), -+ /* @GPIO(14) NET_WO0_UART_TXD(3) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1), -+ /* @GPIO(15) NET_WO0_UART_TXD(4) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2), -+ /* @GPIO(13) GBE_LED0(3) */ -+ PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1), -+ /* @GPIO(9,13) PCM(4) */ -+ PINCTRL_PIN_GROUP("pcm", mt7981_pcm), -+ /* @GPIO(13): SYS_WATCHDOG1(5) */ -+ PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1), -+ /* @GPIO(9,13) UDI(4) */ -+ PINCTRL_PIN_GROUP("udi", mt7981_udi), -+ /* @GPIO(14) DRV_VBUS(1) */ -+ PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), -+ /* @GPIO(15,25): EMMC(2) */ -+ PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), -+ /* @GPIO(16,21): SNFI(3) */ -+ PINCTRL_PIN_GROUP("snfi", mt7981_snfi), -+ /* @GPIO(16,19): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi0", mt7981_spi0), -+ /* @GPIO(20,21): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold), -+ /* @GPIO(22,25) SPI1(1) */ -+ PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1), -+ /* @GPIO(26,29): SPI2(1) */ -+ PINCTRL_PIN_GROUP("spi2", mt7981_spi2), -+ /* @GPIO(30,31): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold), -+ /* @GPIO(16,19): UART1(4) */ -+ PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), -+ /* @GPIO(26,29): UART1(2) */ -+ PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), -+ /* @GPIO(22,25): UART1(3) */ -+ PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), -+ /* @GPIO(22,24) PTA_EXT(4) */ -+ PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1), -+ /* @GPIO(20,21): WM_UART(4) */ -+ PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1), -+ /* @GPIO(30,31): WM_UART(3) */ -+ PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2), -+ /* @GPIO(20,24) WM_JTAG(5) */ -+ PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1), -+ /* @GPIO(25,29) WO0_JTAG(5) */ -+ PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1), -+ /* @GPIO(28,29): WA_AICE(3) */ -+ PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3), -+ /* @GPIO(30,31): WM_AICE(5) */ -+ PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2), -+ /* @GPIO(30,31): I2C(4) */ -+ PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1), -+ /* @GPIO(30,31): I2C(6) */ -+ PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c), -+ /* @GPIO(32,33): I2C(1) */ -+ PINCTRL_PIN_GROUP("uart0", mt7981_uart0), -+ /* @GPIO(32,33): I2C(2) */ -+ PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c), -+ /* @GPIO(32,33): I2C(3) */ -+ PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c), -+ /* @GPIO(32,33): I2C(5) */ -+ PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c), -+ /* @GPIO(34): PCIE_CLK_REQ(2) */ -+ PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk), -+ /* @GPIO(35): PCIE_WAKE_N(2) */ -+ PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake), -+ /* @GPIO(36,37): I2C(2) */ -+ PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2), -+ /* @GPIO(36,37): MDC_MDIO(1) */ -+ PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio), -+ /* @GPIO(36,37): MDC_MDIO(3) */ -+ PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio), -+ /* @GPIO(69,85): WF0_MODE1(1) */ -+ PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1), -+ /* @GPIO(74,80): WF0_MODE3(3) */ -+ PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3), -+ /* @GPIO(30): WF2G_LED(2) */ -+ PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0), -+ /* @GPIO(34): WF2G_LED(1) */ -+ PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1), -+ /* @GPIO(31): WF5G_LED(2) */ -+ PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0), -+ /* @GPIO(35): WF5G_LED(1) */ -+ PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1), -+ /* @GPIO(38): MT7531_INT(1) */ -+ PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int), -+ /* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */ -+ PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel), -+}; -+ -+/* 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 *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", -+ "wa_aice3", "wm_aice1_2", }; -+static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", -+ "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", -+ "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; -+static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; -+static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; -+static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; -+static const char *mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", "wo0_jtag_0", -+ "wo0_jtag_1", "wm_jtag_1", }; -+static const char *mt7981_led_groups[] = { "gbe_led0", "gbe_led1", "wf2g_led0", -+ "wf2g_led1", "wf5g_led0", "wf5g_led1", }; -+static const char *mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", }; -+static const char *mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1", -+ "pwm1_0", "pwm1_1", }; -+static const char *mt7981_spi_groups[] = { "spi1_0", "spi0", "spi0_wp_hold", "spi1_1", "spi2", -+ "spi2_wp_hold", }; -+static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c", -+ "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", "i2c0_2", }; -+static const char *mt7981_pcm_groups[] = { "pcm", }; -+static const char *mt7981_udi_groups[] = { "udi", }; -+static const char *mt7981_usb_groups[] = { "drv_vbus", }; -+static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; -+static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", -+ "wf0_mode1", "wf0_mode3", "mt7531_int", }; -+static const char *mt7981_ant_groups[] = { "ant_sel", }; -+ -+static const struct function_desc mt7981_functions[] = { -+ {"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)}, -+ {"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)}, -+ {"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)}, -+ {"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)}, -+ {"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)}, -+ {"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)}, -+ {"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)}, -+ {"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)}, -+ {"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)}, -+ {"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)}, -+ {"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)}, -+ {"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)}, -+ {"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)}, -+ {"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)}, -+ {"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)}, -+ {"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)}, -+ {"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)}, -+}; -+ -+static const struct mtk_eint_hw mt7981_eint_hw = { -+ .port_mask = 7, -+ .ports = 7, -+ .ap_num = ARRAY_SIZE(mt7981_pins), -+ .db_cnt = 16, -+}; -+ -+static const char * const mt7981_pinctrl_register_base_names[] = { -+ "gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb", -+ "iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl", -+}; -+ -+static struct mtk_pin_soc mt7981_data = { -+ .reg_cal = mt7981_reg_cals, -+ .pins = mt7981_pins, -+ .npins = ARRAY_SIZE(mt7981_pins), -+ .grps = mt7981_groups, -+ .ngrps = ARRAY_SIZE(mt7981_groups), -+ .funcs = mt7981_functions, -+ .nfuncs = ARRAY_SIZE(mt7981_functions), -+ .eint_hw = &mt7981_eint_hw, -+ .gpio_m = 0, -+ .ies_present = false, -+ .base_names = mt7981_pinctrl_register_base_names, -+ .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), -+ .pull_type = mt7981_pull_type, -+ .bias_set_combo = mtk_pinconf_bias_set_combo, -+ .bias_get_combo = mtk_pinconf_bias_get_combo, -+ .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 mt7981_pinctrl_of_match[] = { -+ { .compatible = "mediatek,mt7981-pinctrl", }, -+ {} -+}; -+ -+static int mt7981_pinctrl_probe(struct platform_device *pdev) -+{ -+ return mtk_moore_pinctrl_probe(pdev, &mt7981_data); -+} -+ -+static struct platform_driver mt7981_pinctrl_driver = { -+ .driver = { -+ .name = "mt7981-pinctrl", -+ .of_match_table = mt7981_pinctrl_of_match, -+ }, -+ .probe = mt7981_pinctrl_probe, -+}; -+ -+static int __init mt7981_pinctrl_init(void) -+{ -+ return platform_driver_register(&mt7981_pinctrl_driver); -+} -+arch_initcall(mt7981_pinctrl_init); diff --git a/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch b/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch deleted file mode 100644 index 995e0dc7ed..0000000000 --- a/target/linux/mediatek/patches-6.6/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c0ad453e94e5c404efbcf668648d07eaa1a71ed7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sat, 18 Feb 2023 09:51:06 +0300 -Subject: [PATCH] pinctrl: mediatek: add missing options to PINCTRL_MT7981 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There are options missing from PINCTRL_MT7981 whilst being on every other -pin controller. Add them. - -Signed-off-by: Arınç ÜNAL -Acked-by: Daniel Golle -Link: https://lore.kernel.org/r/20230218065108.8958-1-arinc.unal@arinc9.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/Kconfig | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -130,6 +130,8 @@ config PINCTRL_MT7622 - config PINCTRL_MT7981 - bool "Mediatek MT7981 pin control" - depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - - config PINCTRL_MT7986 diff --git a/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch b/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch deleted file mode 100644 index db2561695b..0000000000 --- a/target/linux/mediatek/patches-6.6/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 8f6f16fe1553ce63edfb98a39ef9d4754a0c39bf Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:02:35 +0100 -Subject: [PATCH] pinctrl: mediatek: fix pull_type data for MT7981 - -MediaTek has released pull_type data for MT7981 in their SDK. -Use it and set functions to configure pin bias. - -Fixes: 6c83b2d94fcc ("pinctrl: add mt7981 pinctrl driver") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/7bcc8ead25dbfabc7f5a85d066224a926fbb4941.1692327317.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7981.c | 44 +++++++---------------- - 1 file changed, 13 insertions(+), 31 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c -@@ -457,37 +457,15 @@ static const unsigned int mt7981_pull_ty - MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ - MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ - MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -- MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -- MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -- MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -- MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -- MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -- MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -- MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -- MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -- MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -- MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -- MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -- MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -- MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -- MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -- MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -- MTK_PULL_PU_PD_TYPE,/*100*/ -+ MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/ -+ MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/ -+ MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PU_PD_TYPE,/*45*/ -+ MTK_PULL_PU_PD_TYPE,/*46*/ MTK_PULL_PU_PD_TYPE,/*47*/ -+ MTK_PULL_PU_PD_TYPE,/*48*/ MTK_PULL_PU_PD_TYPE,/*49*/ -+ MTK_PULL_PU_PD_TYPE,/*50*/ MTK_PULL_PU_PD_TYPE,/*51*/ -+ MTK_PULL_PU_PD_TYPE,/*52*/ MTK_PULL_PU_PD_TYPE,/*53*/ -+ MTK_PULL_PU_PD_TYPE,/*54*/ MTK_PULL_PU_PD_TYPE,/*55*/ -+ MTK_PULL_PU_PD_TYPE,/*56*/ - }; - - static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { -@@ -1014,6 +992,10 @@ static struct mtk_pin_soc mt7981_data = - .ies_present = false, - .base_names = mt7981_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7981_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, - .pull_type = mt7981_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch b/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch deleted file mode 100644 index 7992a02677..0000000000 --- a/target/linux/mediatek/patches-6.6/219-v6.6-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0d8387fba9f151220e48dc3dcdc2335539708f13 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:03:26 +0100 -Subject: [PATCH] pinctrl: mediatek: assign functions to configure pin bias on - MT7986 - -Assign bias_disable_get/set and bias_get/set functions to allow -configuring pin bias on MT7986. - -Fixes: 2c58d8dc9cd0 ("pinctrl: mediatek: add pull_type attribute for mediatek MT7986 SoC") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/47f72372354312a839b9337e09476aadcc206e8b.1692327317.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -922,6 +922,10 @@ static struct mtk_pin_soc mt7986a_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_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, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, -@@ -944,6 +948,10 @@ static struct mtk_pin_soc mt7986b_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_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, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch b/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch deleted file mode 100644 index af5715e1f5..0000000000 --- a/target/linux/mediatek/patches-6.6/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch +++ /dev/null @@ -1,536 +0,0 @@ -From fe5c8d03f3de89ae058e365b783f8c1314f47490 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:33 +0100 -Subject: [PATCH 01/15] clk: mediatek: clk-gate: Propagate struct device with - mtk_clk_register_gates() - -Commit e4c23e19aa2a ("clk: mediatek: Register clock gate with device") -introduces a helper function for the sole purpose of propagating a -struct device pointer to the clk API when registering the mtk-gate -clocks to take advantage of Runtime PM when/where needed and where -a power domain is defined in devicetree. - -Function mtk_clk_register_gates() then becomes a wrapper around the -new mtk_clk_register_gates_with_dev() function that will simply pass -NULL as struct device: this is essential when registering drivers -with CLK_OF_DECLARE instead of as a platform device, as there will -be no struct device to pass... but we can as well simply have only -one function that always takes such pointer as a param and pass NULL -when unavoidable. - -This commit removes the mtk_clk_register_gates() wrapper and renames -mtk_clk_register_gates_with_dev() to the former and all of the calls -to either of the two functions were fixed in all drivers in order to -reflect this change; also, to improve consistency with other kernel -functions, the pointer to struct device was moved as the first param. - -Since a lot of MediaTek clock drivers are actually registering as a -platform device, but were still registering the mtk-gate clocks -without passing any struct device to the clock framework, they've -been changed to pass a valid one now, as to make all those platforms -able to use runtime power management where available. - -While at it, some much needed indentation changes were also done. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Reviewed-by: Markus Schneider-Pargmann -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-4-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd - -[daniel@makrotopia.org: dropped parts not relevant for OpenWrt] ---- - drivers/clk/mediatek/clk-gate.c | 23 +++++++--------------- - drivers/clk/mediatek/clk-gate.h | 7 +------ - drivers/clk/mediatek/clk-mt2701-aud.c | 4 ++-- - drivers/clk/mediatek/clk-mt2701-eth.c | 4 ++-- - drivers/clk/mediatek/clk-mt2701-g3d.c | 2 +- - drivers/clk/mediatek/clk-mt2701-hif.c | 4 ++-- - drivers/clk/mediatek/clk-mt2701-mm.c | 4 ++-- - drivers/clk/mediatek/clk-mt2701.c | 12 +++++------ - drivers/clk/mediatek/clk-mt2712-mm.c | 4 ++-- - drivers/clk/mediatek/clk-mt2712.c | 12 +++++------ - drivers/clk/mediatek/clk-mt7622-aud.c | 4 ++-- - drivers/clk/mediatek/clk-mt7622-eth.c | 8 ++++---- - drivers/clk/mediatek/clk-mt7622-hif.c | 8 ++++---- - drivers/clk/mediatek/clk-mt7622.c | 14 ++++++------- - drivers/clk/mediatek/clk-mt7629-eth.c | 7 ++++--- - drivers/clk/mediatek/clk-mt7629-hif.c | 8 ++++---- - drivers/clk/mediatek/clk-mt7629.c | 10 +++++----- - drivers/clk/mediatek/clk-mt7986-eth.c | 10 +++++----- - drivers/clk/mediatek/clk-mt7986-infracfg.c | 4 ++-- - 19 files changed, 68 insertions(+), 81 deletions(-) - ---- a/drivers/clk/mediatek/clk-gate.c -+++ b/drivers/clk/mediatek/clk-gate.c -@@ -152,12 +152,12 @@ const struct clk_ops mtk_clk_gate_ops_no - }; - EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv); - --static struct clk_hw *mtk_clk_register_gate(const char *name, -+static struct clk_hw *mtk_clk_register_gate(struct device *dev, const char *name, - const char *parent_name, - struct regmap *regmap, int set_ofs, - int clr_ofs, int sta_ofs, u8 bit, - const struct clk_ops *ops, -- unsigned long flags, struct device *dev) -+ unsigned long flags) - { - struct mtk_clk_gate *cg; - int ret; -@@ -202,10 +202,9 @@ static void mtk_clk_unregister_gate(stru - kfree(cg); - } - --int mtk_clk_register_gates_with_dev(struct device_node *node, -- const struct mtk_gate *clks, int num, -- struct clk_hw_onecell_data *clk_data, -- struct device *dev) -+int mtk_clk_register_gates(struct device *dev, struct device_node *node, -+ const struct mtk_gate *clks, int num, -+ struct clk_hw_onecell_data *clk_data) - { - int i; - struct clk_hw *hw; -@@ -229,13 +228,13 @@ int mtk_clk_register_gates_with_dev(stru - continue; - } - -- hw = mtk_clk_register_gate(gate->name, gate->parent_name, -+ hw = mtk_clk_register_gate(dev, gate->name, gate->parent_name, - regmap, - gate->regs->set_ofs, - gate->regs->clr_ofs, - gate->regs->sta_ofs, - gate->shift, gate->ops, -- gate->flags, dev); -+ gate->flags); - - if (IS_ERR(hw)) { - pr_err("Failed to register clk %s: %pe\n", gate->name, -@@ -261,14 +260,6 @@ err: - - return PTR_ERR(hw); - } --EXPORT_SYMBOL_GPL(mtk_clk_register_gates_with_dev); -- --int mtk_clk_register_gates(struct device_node *node, -- const struct mtk_gate *clks, int num, -- struct clk_hw_onecell_data *clk_data) --{ -- return mtk_clk_register_gates_with_dev(node, clks, num, clk_data, NULL); --} - EXPORT_SYMBOL_GPL(mtk_clk_register_gates); - - void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, ---- a/drivers/clk/mediatek/clk-gate.h -+++ b/drivers/clk/mediatek/clk-gate.h -@@ -50,15 +50,10 @@ struct mtk_gate { - #define GATE_MTK(_id, _name, _parent, _regs, _shift, _ops) \ - GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, _ops, 0) - --int mtk_clk_register_gates(struct device_node *node, -+int mtk_clk_register_gates(struct device *dev, struct device_node *node, - const struct mtk_gate *clks, int num, - struct clk_hw_onecell_data *clk_data); - --int mtk_clk_register_gates_with_dev(struct device_node *node, -- const struct mtk_gate *clks, int num, -- struct clk_hw_onecell_data *clk_data, -- struct device *dev); -- - void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, - struct clk_hw_onecell_data *clk_data); - ---- a/drivers/clk/mediatek/clk-mt2701-aud.c -+++ b/drivers/clk/mediatek/clk-mt2701-aud.c -@@ -127,8 +127,8 @@ static int clk_mt2701_aud_probe(struct p - - clk_data = mtk_alloc_clk_data(CLK_AUD_NR); - -- mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, audio_clks, -+ ARRAY_SIZE(audio_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { ---- a/drivers/clk/mediatek/clk-mt2701-eth.c -+++ b/drivers/clk/mediatek/clk-mt2701-eth.c -@@ -51,8 +51,8 @@ static int clk_mt2701_eth_probe(struct p - - clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); - -- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, eth_clks, -+ ARRAY_SIZE(eth_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt2701-g3d.c -+++ b/drivers/clk/mediatek/clk-mt2701-g3d.c -@@ -45,7 +45,7 @@ static int clk_mt2701_g3dsys_init(struct - - clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); - -- mtk_clk_register_gates(node, g3d_clks, ARRAY_SIZE(g3d_clks), -+ mtk_clk_register_gates(&pdev->dev, node, g3d_clks, ARRAY_SIZE(g3d_clks), - clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ---- a/drivers/clk/mediatek/clk-mt2701-hif.c -+++ b/drivers/clk/mediatek/clk-mt2701-hif.c -@@ -48,8 +48,8 @@ static int clk_mt2701_hif_probe(struct p - - clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); - -- mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, hif_clks, -+ ARRAY_SIZE(hif_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { ---- a/drivers/clk/mediatek/clk-mt2701-mm.c -+++ b/drivers/clk/mediatek/clk-mt2701-mm.c -@@ -76,8 +76,8 @@ static int clk_mt2701_mm_probe(struct pl - - clk_data = mtk_alloc_clk_data(CLK_MM_NR); - -- mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, mm_clks, -+ ARRAY_SIZE(mm_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -685,8 +685,8 @@ static int mtk_topckgen_init(struct plat - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), - base, &mt2701_clk_lock, clk_data); - -- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, top_clks, -+ ARRAY_SIZE(top_clks), clk_data); - - return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - } -@@ -789,8 +789,8 @@ static int mtk_infrasys_init(struct plat - } - } - -- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -- infra_clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, infra_clks, -+ ARRAY_SIZE(infra_clks), infra_clk_data); - mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), - infra_clk_data); - -@@ -902,8 +902,8 @@ static int mtk_pericfg_init(struct platf - if (!clk_data) - return -ENOMEM; - -- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, peri_clks, -+ ARRAY_SIZE(peri_clks), clk_data); - - mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, - &mt2701_clk_lock, clk_data); ---- a/drivers/clk/mediatek/clk-mt2712-mm.c -+++ b/drivers/clk/mediatek/clk-mt2712-mm.c -@@ -117,8 +117,8 @@ static int clk_mt2712_mm_probe(struct pl - - clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); - -- mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, mm_clks, -+ ARRAY_SIZE(mm_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - ---- a/drivers/clk/mediatek/clk-mt2712.c -+++ b/drivers/clk/mediatek/clk-mt2712.c -@@ -1324,8 +1324,8 @@ static int clk_mt2712_top_probe(struct p - &mt2712_clk_lock, top_clk_data); - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, - &mt2712_clk_lock, top_clk_data); -- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), -- top_clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, top_clks, -+ ARRAY_SIZE(top_clks), top_clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); - -@@ -1344,8 +1344,8 @@ static int clk_mt2712_infra_probe(struct - - clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); - -- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, infra_clks, -+ ARRAY_SIZE(infra_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - -@@ -1366,8 +1366,8 @@ static int clk_mt2712_peri_probe(struct - - clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); - -- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, peri_clks, -+ ARRAY_SIZE(peri_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - ---- a/drivers/clk/mediatek/clk-mt7622-aud.c -+++ b/drivers/clk/mediatek/clk-mt7622-aud.c -@@ -114,8 +114,8 @@ static int clk_mt7622_audiosys_init(stru - - clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); - -- mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, audio_clks, -+ ARRAY_SIZE(audio_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { ---- a/drivers/clk/mediatek/clk-mt7622-eth.c -+++ b/drivers/clk/mediatek/clk-mt7622-eth.c -@@ -69,8 +69,8 @@ static int clk_mt7622_ethsys_init(struct - - clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); - -- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, eth_clks, -+ ARRAY_SIZE(eth_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -91,8 +91,8 @@ static int clk_mt7622_sgmiisys_init(stru - - clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); - -- mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, sgmii_clks, -+ ARRAY_SIZE(sgmii_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt7622-hif.c -+++ b/drivers/clk/mediatek/clk-mt7622-hif.c -@@ -80,8 +80,8 @@ static int clk_mt7622_ssusbsys_init(stru - - clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); - -- mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -+ ARRAY_SIZE(ssusb_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -102,8 +102,8 @@ static int clk_mt7622_pciesys_init(struc - - clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); - -- mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -+ ARRAY_SIZE(pcie_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt7622.c -+++ b/drivers/clk/mediatek/clk-mt7622.c -@@ -621,8 +621,8 @@ static int mtk_topckgen_init(struct plat - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), - base, &mt7622_clk_lock, clk_data); - -- mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, top_clks, -+ ARRAY_SIZE(top_clks), clk_data); - - return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - } -@@ -635,8 +635,8 @@ static int mtk_infrasys_init(struct plat - - clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); - -- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, infra_clks, -+ ARRAY_SIZE(infra_clks), clk_data); - - mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), - clk_data); -@@ -663,7 +663,7 @@ static int mtk_apmixedsys_init(struct pl - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), - clk_data); - -- mtk_clk_register_gates(node, apmixed_clks, -+ mtk_clk_register_gates(&pdev->dev, node, apmixed_clks, - ARRAY_SIZE(apmixed_clks), clk_data); - - return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -@@ -682,8 +682,8 @@ static int mtk_pericfg_init(struct platf - - clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); - -- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, peri_clks, -+ ARRAY_SIZE(peri_clks), clk_data); - - mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, - &mt7622_clk_lock, clk_data); ---- a/drivers/clk/mediatek/clk-mt7629-eth.c -+++ b/drivers/clk/mediatek/clk-mt7629-eth.c -@@ -82,7 +82,8 @@ static int clk_mt7629_ethsys_init(struct - if (!clk_data) - return -ENOMEM; - -- mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, eth_clks, -+ CLK_ETH_NR_CLK, clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -106,8 +107,8 @@ static int clk_mt7629_sgmiisys_init(stru - if (!clk_data) - return -ENOMEM; - -- mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK, -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, sgmii_clks[id++], -+ CLK_SGMII_NR_CLK, clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt7629-hif.c -+++ b/drivers/clk/mediatek/clk-mt7629-hif.c -@@ -75,8 +75,8 @@ static int clk_mt7629_ssusbsys_init(stru - - clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); - -- mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -+ ARRAY_SIZE(ssusb_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -97,8 +97,8 @@ static int clk_mt7629_pciesys_init(struc - - clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); - -- mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -+ ARRAY_SIZE(pcie_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt7629.c -+++ b/drivers/clk/mediatek/clk-mt7629.c -@@ -585,8 +585,8 @@ static int mtk_infrasys_init(struct plat - if (!clk_data) - return -ENOMEM; - -- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, infra_clks, -+ ARRAY_SIZE(infra_clks), clk_data); - - mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), - clk_data); -@@ -610,8 +610,8 @@ static int mtk_pericfg_init(struct platf - if (!clk_data) - return -ENOMEM; - -- mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, peri_clks, -+ ARRAY_SIZE(peri_clks), clk_data); - - mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, - &mt7629_clk_lock, clk_data); -@@ -637,7 +637,7 @@ static int mtk_apmixedsys_init(struct pl - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), - clk_data); - -- mtk_clk_register_gates(node, apmixed_clks, -+ mtk_clk_register_gates(&pdev->dev, node, apmixed_clks, - ARRAY_SIZE(apmixed_clks), clk_data); - - clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); ---- a/drivers/clk/mediatek/clk-mt7986-eth.c -+++ b/drivers/clk/mediatek/clk-mt7986-eth.c -@@ -72,8 +72,8 @@ static void __init mtk_sgmiisys_0_init(s - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); - -- mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), -- clk_data); -+ mtk_clk_register_gates(NULL, node, sgmii0_clks, -+ ARRAY_SIZE(sgmii0_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -90,8 +90,8 @@ static void __init mtk_sgmiisys_1_init(s - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); - -- mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), -- clk_data); -+ mtk_clk_register_gates(NULL, node, sgmii1_clks, -+ ARRAY_SIZE(sgmii1_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - -@@ -109,7 +109,7 @@ static void __init mtk_ethsys_init(struc - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); - -- mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); -+ mtk_clk_register_gates(NULL, node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - ---- a/drivers/clk/mediatek/clk-mt7986-infracfg.c -+++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c -@@ -180,8 +180,8 @@ static int clk_mt7986_infracfg_probe(str - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, - &mt7986_clk_lock, clk_data); -- mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -- clk_data); -+ mtk_clk_register_gates(&pdev->dev, node, infra_clks, -+ ARRAY_SIZE(infra_clks), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -459,8 +459,8 @@ int mtk_clk_simple_probe(struct platform - if (!clk_data) - return -ENOMEM; - -- r = mtk_clk_register_gates_with_dev(node, mcd->clks, mcd->num_clks, -- clk_data, &pdev->dev); -+ r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, mcd->num_clks, -+ clk_data); - if (r) - goto free_data; - diff --git a/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch b/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch deleted file mode 100644 index 223155c59b..0000000000 --- a/target/linux/mediatek/patches-6.6/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch +++ /dev/null @@ -1,140 +0,0 @@ -From b888303c7d23d7bd0c8667cfc657669e5d153fea Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:34 +0100 -Subject: [PATCH 02/15] clk: mediatek: cpumux: Propagate struct device where - possible - -Take a pointer to a struct device in mtk_clk_register_cpumuxes() and -propagate the same to mtk_clk_register_cpumux() => clk_hw_register(). -Even though runtime pm is unlikely to be used with CPU muxes, this -helps with code consistency and possibly opens to commonization of -some mtk_clk_register_(x) functions. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Reviewed-by: Markus Schneider-Pargmann -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-5-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-cpumux.c | 8 ++++---- - drivers/clk/mediatek/clk-cpumux.h | 2 +- - drivers/clk/mediatek/clk-mt2701.c | 2 +- - drivers/clk/mediatek/clk-mt6795-infracfg.c | 3 ++- - drivers/clk/mediatek/clk-mt7622.c | 4 ++-- - drivers/clk/mediatek/clk-mt7629.c | 4 ++-- - drivers/clk/mediatek/clk-mt8173.c | 4 ++-- - 7 files changed, 14 insertions(+), 13 deletions(-) - ---- a/drivers/clk/mediatek/clk-cpumux.c -+++ b/drivers/clk/mediatek/clk-cpumux.c -@@ -58,7 +58,7 @@ static const struct clk_ops clk_cpumux_o - }; - - static struct clk_hw * --mtk_clk_register_cpumux(const struct mtk_composite *mux, -+mtk_clk_register_cpumux(struct device *dev, const struct mtk_composite *mux, - struct regmap *regmap) - { - struct mtk_clk_cpumux *cpumux; -@@ -81,7 +81,7 @@ mtk_clk_register_cpumux(const struct mtk - cpumux->regmap = regmap; - cpumux->hw.init = &init; - -- ret = clk_hw_register(NULL, &cpumux->hw); -+ ret = clk_hw_register(dev, &cpumux->hw); - if (ret) { - kfree(cpumux); - return ERR_PTR(ret); -@@ -102,7 +102,7 @@ static void mtk_clk_unregister_cpumux(st - kfree(cpumux); - } - --int mtk_clk_register_cpumuxes(struct device_node *node, -+int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, - const struct mtk_composite *clks, int num, - struct clk_hw_onecell_data *clk_data) - { -@@ -125,7 +125,7 @@ int mtk_clk_register_cpumuxes(struct dev - continue; - } - -- hw = mtk_clk_register_cpumux(mux, regmap); -+ hw = mtk_clk_register_cpumux(dev, mux, regmap); - if (IS_ERR(hw)) { - pr_err("Failed to register clk %s: %pe\n", mux->name, - hw); ---- a/drivers/clk/mediatek/clk-cpumux.h -+++ b/drivers/clk/mediatek/clk-cpumux.h -@@ -11,7 +11,7 @@ struct clk_hw_onecell_data; - struct device_node; - struct mtk_composite; - --int mtk_clk_register_cpumuxes(struct device_node *node, -+int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, - const struct mtk_composite *clks, int num, - struct clk_hw_onecell_data *clk_data); - ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -761,7 +761,7 @@ static void __init mtk_infrasys_init_ear - mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), - infra_clk_data); - -- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -+ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, ARRAY_SIZE(cpu_muxes), - infra_clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, ---- a/drivers/clk/mediatek/clk-mt6795-infracfg.c -+++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c -@@ -105,7 +105,8 @@ static int clk_mt6795_infracfg_probe(str - if (ret) - goto free_clk_data; - -- ret = mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); -+ ret = mtk_clk_register_cpumuxes(&pdev->dev, node, cpu_muxes, -+ ARRAY_SIZE(cpu_muxes), clk_data); - if (ret) - goto unregister_gates; - ---- a/drivers/clk/mediatek/clk-mt7622.c -+++ b/drivers/clk/mediatek/clk-mt7622.c -@@ -638,8 +638,8 @@ static int mtk_infrasys_init(struct plat - mtk_clk_register_gates(&pdev->dev, node, infra_clks, - ARRAY_SIZE(infra_clks), clk_data); - -- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, -+ ARRAY_SIZE(infra_muxes), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, - clk_data); ---- a/drivers/clk/mediatek/clk-mt7629.c -+++ b/drivers/clk/mediatek/clk-mt7629.c -@@ -588,8 +588,8 @@ static int mtk_infrasys_init(struct plat - mtk_clk_register_gates(&pdev->dev, node, infra_clks, - ARRAY_SIZE(infra_clks), clk_data); - -- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, -+ ARRAY_SIZE(infra_muxes), clk_data); - - return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, - clk_data); ---- a/drivers/clk/mediatek/clk-mt8173.c -+++ b/drivers/clk/mediatek/clk-mt8173.c -@@ -892,8 +892,8 @@ static void __init mtk_infrasys_init(str - clk_data); - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - -- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, -+ ARRAY_SIZE(cpu_muxes), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) diff --git a/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch b/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch deleted file mode 100644 index eca1b614cd..0000000000 --- a/target/linux/mediatek/patches-6.6/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch +++ /dev/null @@ -1,181 +0,0 @@ -From f23375db001ec0fe9f565be75eff43adde15407e Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:35 +0100 -Subject: [PATCH 03/15] clk: mediatek: clk-mtk: Propagate struct device for - composites - -Like done for cpumux clocks, propagate struct device for composite -clocks registered through clk-mtk helpers to be able to get runtime -pm support for MTK clocks. - -Signed-off-by: AngeloGioacchino Del Regno -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-6-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd - -[daniel@makrotopia.org: remove parts not relevant for OpenWrt] ---- - drivers/clk/mediatek/clk-mt2701.c | 10 ++++++---- - drivers/clk/mediatek/clk-mt2712.c | 12 ++++++++---- - drivers/clk/mediatek/clk-mt7622.c | 8 +++++--- - drivers/clk/mediatek/clk-mt7629.c | 8 +++++--- - drivers/clk/mediatek/clk-mtk.c | 11 ++++++----- - drivers/clk/mediatek/clk-mtk.h | 3 ++- - 6 files changed, 32 insertions(+), 20 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -679,8 +679,9 @@ static int mtk_topckgen_init(struct plat - mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), - clk_data); - -- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), -- base, &mt2701_clk_lock, clk_data); -+ mtk_clk_register_composites(&pdev->dev, top_muxes, -+ ARRAY_SIZE(top_muxes), base, -+ &mt2701_clk_lock, clk_data); - - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), - base, &mt2701_clk_lock, clk_data); -@@ -905,8 +906,9 @@ static int mtk_pericfg_init(struct platf - mtk_clk_register_gates(&pdev->dev, node, peri_clks, - ARRAY_SIZE(peri_clks), clk_data); - -- mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, -- &mt2701_clk_lock, clk_data); -+ mtk_clk_register_composites(&pdev->dev, peri_muxs, -+ ARRAY_SIZE(peri_muxs), base, -+ &mt2701_clk_lock, clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) ---- a/drivers/clk/mediatek/clk-mt2712.c -+++ b/drivers/clk/mediatek/clk-mt2712.c -@@ -1320,8 +1320,9 @@ static int clk_mt2712_top_probe(struct p - mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), - top_clk_data); - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); -- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, -- &mt2712_clk_lock, top_clk_data); -+ mtk_clk_register_composites(&pdev->dev, top_muxes, -+ ARRAY_SIZE(top_muxes), base, -+ &mt2712_clk_lock, top_clk_data); - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, - &mt2712_clk_lock, top_clk_data); - mtk_clk_register_gates(&pdev->dev, node, top_clks, -@@ -1395,8 +1396,11 @@ static int clk_mt2712_mcu_probe(struct p - - clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); - -- mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, -- &mt2712_clk_lock, clk_data); -+ r = mtk_clk_register_composites(&pdev->dev, mcu_muxes, -+ ARRAY_SIZE(mcu_muxes), base, -+ &mt2712_clk_lock, clk_data); -+ if (r) -+ dev_err(&pdev->dev, "Could not register composites: %d\n", r); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - ---- a/drivers/clk/mediatek/clk-mt7622.c -+++ b/drivers/clk/mediatek/clk-mt7622.c -@@ -615,8 +615,9 @@ static int mtk_topckgen_init(struct plat - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), - clk_data); - -- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), -- base, &mt7622_clk_lock, clk_data); -+ mtk_clk_register_composites(&pdev->dev, top_muxes, -+ ARRAY_SIZE(top_muxes), base, -+ &mt7622_clk_lock, clk_data); - - mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), - base, &mt7622_clk_lock, clk_data); -@@ -685,7 +686,8 @@ static int mtk_pericfg_init(struct platf - mtk_clk_register_gates(&pdev->dev, node, peri_clks, - ARRAY_SIZE(peri_clks), clk_data); - -- mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, -+ mtk_clk_register_composites(&pdev->dev, peri_muxes, -+ ARRAY_SIZE(peri_muxes), base, - &mt7622_clk_lock, clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ---- a/drivers/clk/mediatek/clk-mt7629.c -+++ b/drivers/clk/mediatek/clk-mt7629.c -@@ -566,8 +566,9 @@ static int mtk_topckgen_init(struct plat - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), - clk_data); - -- mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), -- base, &mt7629_clk_lock, clk_data); -+ mtk_clk_register_composites(&pdev->dev, top_muxes, -+ ARRAY_SIZE(top_muxes), base, -+ &mt7629_clk_lock, clk_data); - - clk_prepare_enable(clk_data->hws[CLK_TOP_AXI_SEL]->clk); - clk_prepare_enable(clk_data->hws[CLK_TOP_MEM_SEL]->clk); -@@ -613,7 +614,8 @@ static int mtk_pericfg_init(struct platf - mtk_clk_register_gates(&pdev->dev, node, peri_clks, - ARRAY_SIZE(peri_clks), clk_data); - -- mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, -+ mtk_clk_register_composites(&pdev->dev, peri_muxes, -+ ARRAY_SIZE(peri_muxes), base, - &mt7629_clk_lock, clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -197,8 +197,8 @@ void mtk_clk_unregister_factors(const st - } - EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); - --static struct clk_hw *mtk_clk_register_composite(const struct mtk_composite *mc, -- void __iomem *base, spinlock_t *lock) -+static struct clk_hw *mtk_clk_register_composite(struct device *dev, -+ const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) - { - struct clk_hw *hw; - struct clk_mux *mux = NULL; -@@ -264,7 +264,7 @@ static struct clk_hw *mtk_clk_register_c - div_ops = &clk_divider_ops; - } - -- hw = clk_hw_register_composite(NULL, mc->name, parent_names, num_parents, -+ hw = clk_hw_register_composite(dev, mc->name, parent_names, num_parents, - mux_hw, mux_ops, - div_hw, div_ops, - gate_hw, gate_ops, -@@ -308,7 +308,8 @@ static void mtk_clk_unregister_composite - kfree(mux); - } - --int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, -+int mtk_clk_register_composites(struct device *dev, -+ const struct mtk_composite *mcs, int num, - void __iomem *base, spinlock_t *lock, - struct clk_hw_onecell_data *clk_data) - { -@@ -327,7 +328,7 @@ int mtk_clk_register_composites(const st - continue; - } - -- hw = mtk_clk_register_composite(mc, base, lock); -+ hw = mtk_clk_register_composite(dev, mc, base, lock); - - if (IS_ERR(hw)) { - pr_err("Failed to register clk %s: %pe\n", mc->name, ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -149,7 +149,8 @@ struct mtk_composite { - .flags = 0, \ - } - --int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, -+int mtk_clk_register_composites(struct device *dev, -+ const struct mtk_composite *mcs, int num, - void __iomem *base, spinlock_t *lock, - struct clk_hw_onecell_data *clk_data); - void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, diff --git a/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch b/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch deleted file mode 100644 index a50422da58..0000000000 --- a/target/linux/mediatek/patches-6.6/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 5d911479e4c732729bfa798e4a9e3e5aec3e30a7 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:36 +0100 -Subject: [PATCH 04/15] clk: mediatek: clk-mux: Propagate struct device for - mtk-mux - -Like done for other clocks, propagate struct device for mtk mux clocks -registered through clk-mux helpers to enable runtime pm support. - -Signed-off-by: AngeloGioacchino Del Regno -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-7-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd - -[daniel@makrotopia.org: removed parts not relevant for OpenWrt] ---- - drivers/clk/mediatek/clk-mt7986-infracfg.c | 3 ++- - drivers/clk/mediatek/clk-mt7986-topckgen.c | 3 ++- - drivers/clk/mediatek/clk-mux.c | 14 ++++++++------ - drivers/clk/mediatek/clk-mux.h | 3 ++- - 4 files changed, 14 insertions(+), 9 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-infracfg.c -+++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c -@@ -178,7 +178,8 @@ static int clk_mt7986_infracfg_probe(str - return -ENOMEM; - - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); -- mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, -+ mtk_clk_register_muxes(&pdev->dev, infra_muxes, -+ ARRAY_SIZE(infra_muxes), node, - &mt7986_clk_lock, clk_data); - mtk_clk_register_gates(&pdev->dev, node, infra_clks, - ARRAY_SIZE(infra_clks), clk_data); ---- a/drivers/clk/mediatek/clk-mt7986-topckgen.c -+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c -@@ -303,7 +303,8 @@ static int clk_mt7986_topckgen_probe(str - 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, -+ mtk_clk_register_muxes(&pdev->dev, top_muxes, -+ ARRAY_SIZE(top_muxes), node, - &mt7986_clk_lock, clk_data); - - clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); ---- a/drivers/clk/mediatek/clk-mux.c -+++ b/drivers/clk/mediatek/clk-mux.c -@@ -154,9 +154,10 @@ const struct clk_ops mtk_mux_gate_clr_se - }; - EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops); - --static struct clk_hw *mtk_clk_register_mux(const struct mtk_mux *mux, -- struct regmap *regmap, -- spinlock_t *lock) -+static struct clk_hw *mtk_clk_register_mux(struct device *dev, -+ const struct mtk_mux *mux, -+ struct regmap *regmap, -+ spinlock_t *lock) - { - struct mtk_clk_mux *clk_mux; - struct clk_init_data init = {}; -@@ -177,7 +178,7 @@ static struct clk_hw *mtk_clk_register_m - clk_mux->lock = lock; - clk_mux->hw.init = &init; - -- ret = clk_hw_register(NULL, &clk_mux->hw); -+ ret = clk_hw_register(dev, &clk_mux->hw); - if (ret) { - kfree(clk_mux); - return ERR_PTR(ret); -@@ -198,7 +199,8 @@ static void mtk_clk_unregister_mux(struc - kfree(mux); - } - --int mtk_clk_register_muxes(const struct mtk_mux *muxes, -+int mtk_clk_register_muxes(struct device *dev, -+ const struct mtk_mux *muxes, - int num, struct device_node *node, - spinlock_t *lock, - struct clk_hw_onecell_data *clk_data) -@@ -222,7 +224,7 @@ int mtk_clk_register_muxes(const struct - continue; - } - -- hw = mtk_clk_register_mux(mux, regmap, lock); -+ hw = mtk_clk_register_mux(dev, mux, regmap, lock); - - if (IS_ERR(hw)) { - pr_err("Failed to register clk %s: %pe\n", mux->name, ---- a/drivers/clk/mediatek/clk-mux.h -+++ b/drivers/clk/mediatek/clk-mux.h -@@ -83,7 +83,8 @@ extern const struct clk_ops mtk_mux_gate - 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \ - mtk_mux_clr_set_upd_ops) - --int mtk_clk_register_muxes(const struct mtk_mux *muxes, -+int mtk_clk_register_muxes(struct device *dev, -+ const struct mtk_mux *muxes, - int num, struct device_node *node, - spinlock_t *lock, - struct clk_hw_onecell_data *clk_data); diff --git a/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch b/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch deleted file mode 100644 index de2e6976c3..0000000000 --- a/target/linux/mediatek/patches-6.6/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch +++ /dev/null @@ -1,74 +0,0 @@ -From b8eb1081d267708ba976525a1fe2162901b34f3a Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:37 +0100 -Subject: [PATCH] clk: mediatek: clk-mtk: Add dummy clock ops - -In order to migrate some (few) old clock drivers to the common -mtk_clk_simple_probe() function, add dummy clock ops to be able -to insert a dummy clock with ID 0 at the beginning of the list. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Reviewed-by: Chen-Yu Tsai -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-8-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mtk.c | 16 ++++++++++++++++ - drivers/clk/mediatek/clk-mtk.h | 19 +++++++++++++++++++ - 2 files changed, 35 insertions(+) - ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -18,6 +18,22 @@ - #include "clk-mtk.h" - #include "clk-gate.h" - -+const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; -+EXPORT_SYMBOL_GPL(cg_regs_dummy); -+ -+static int mtk_clk_dummy_enable(struct clk_hw *hw) -+{ -+ return 0; -+} -+ -+static void mtk_clk_dummy_disable(struct clk_hw *hw) { } -+ -+const struct clk_ops mtk_clk_dummy_ops = { -+ .enable = mtk_clk_dummy_enable, -+ .disable = mtk_clk_dummy_disable, -+}; -+EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops); -+ - static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data, - unsigned int clk_num) - { ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -22,6 +22,25 @@ - - struct platform_device; - -+/* -+ * We need the clock IDs to start from zero but to maintain devicetree -+ * backwards compatibility we can't change bindings to start from zero. -+ * Only a few platforms are affected, so we solve issues given by the -+ * commonized MTK clocks probe function(s) by adding a dummy clock at -+ * the beginning where needed. -+ */ -+#define CLK_DUMMY 0 -+ -+extern const struct clk_ops mtk_clk_dummy_ops; -+extern const struct mtk_gate_regs cg_regs_dummy; -+ -+#define GATE_DUMMY(_id, _name) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .regs = &cg_regs_dummy, \ -+ .ops = &mtk_clk_dummy_ops, \ -+ } -+ - struct mtk_fixed_clk { - int id; - const char *name; diff --git a/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch b/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch deleted file mode 100644 index becfcd0ed8..0000000000 --- a/target/linux/mediatek/patches-6.6/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch +++ /dev/null @@ -1,790 +0,0 @@ -From c26e28015b74af73e0b299f6ad3ff22931e600b4 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:41 +0100 -Subject: [PATCH 05/15] clk: mediatek: Switch to mtk_clk_simple_probe() where - possible - -mtk_clk_simple_probe() is a function that registers mtk gate clocks -and, if reset data is present, a reset controller and across all of -the MTK clock drivers, such a function is duplicated many times: -switch to the common mtk_clk_simple_probe() function for all of the -clock drivers that are registering as platform drivers. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-12-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd - -[daniel@makrotopia.org: removed parts not relevant for OpenWrt] ---- - drivers/clk/mediatek/clk-mt2701-aud.c | 31 ++++++---- - drivers/clk/mediatek/clk-mt2701-eth.c | 36 ++++-------- - drivers/clk/mediatek/clk-mt2701-g3d.c | 56 ++++-------------- - drivers/clk/mediatek/clk-mt2701-hif.c | 38 ++++-------- - drivers/clk/mediatek/clk-mt2712.c | 83 ++++++++++---------------- - drivers/clk/mediatek/clk-mt7622-aud.c | 54 ++++++----------- - drivers/clk/mediatek/clk-mt7622-eth.c | 82 +++++--------------------- - drivers/clk/mediatek/clk-mt7622-hif.c | 85 +++++---------------------- - drivers/clk/mediatek/clk-mt7629-hif.c | 85 +++++---------------------- - 9 files changed, 144 insertions(+), 406 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt2701-aud.c -+++ b/drivers/clk/mediatek/clk-mt2701-aud.c -@@ -52,6 +52,7 @@ static const struct mtk_gate_regs audio3 - }; - - static const struct mtk_gate audio_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "aud_dummy"), - /* AUDIO0 */ - GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2), - GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20), -@@ -114,29 +115,27 @@ static const struct mtk_gate audio_clks[ - GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), - }; - -+static const struct mtk_clk_desc audio_desc = { -+ .clks = audio_clks, -+ .num_clks = ARRAY_SIZE(audio_clks), -+}; -+ - static const struct of_device_id of_match_clk_mt2701_aud[] = { -- { .compatible = "mediatek,mt2701-audsys", }, -- {} -+ { .compatible = "mediatek,mt2701-audsys", .data = &audio_desc }, -+ { /* sentinel */ } - }; - - static int clk_mt2701_aud_probe(struct platform_device *pdev) - { -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; - int r; - -- clk_data = mtk_alloc_clk_data(CLK_AUD_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, audio_clks, -- ARRAY_SIZE(audio_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ r = mtk_clk_simple_probe(pdev); - if (r) { - dev_err(&pdev->dev, - "could not register clock provider: %s: %d\n", - pdev->name, r); - -- goto err_clk_provider; -+ return r; - } - - r = devm_of_platform_populate(&pdev->dev); -@@ -146,13 +145,19 @@ static int clk_mt2701_aud_probe(struct p - return 0; - - err_plat_populate: -- of_clk_del_provider(node); --err_clk_provider: -+ mtk_clk_simple_remove(pdev); - return r; - } - -+static int clk_mt2701_aud_remove(struct platform_device *pdev) -+{ -+ of_platform_depopulate(&pdev->dev); -+ return mtk_clk_simple_remove(pdev); -+} -+ - static struct platform_driver clk_mt2701_aud_drv = { - .probe = clk_mt2701_aud_probe, -+ .remove = clk_mt2701_aud_remove, - .driver = { - .name = "clk-mt2701-aud", - .of_match_table = of_match_clk_mt2701_aud, ---- a/drivers/clk/mediatek/clk-mt2701-eth.c -+++ b/drivers/clk/mediatek/clk-mt2701-eth.c -@@ -20,6 +20,7 @@ static const struct mtk_gate_regs eth_cg - GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) - - static const struct mtk_gate eth_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "eth_dummy"), - GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5), - GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6), - GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7), -@@ -38,35 +39,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static const struct of_device_id of_match_clk_mt2701_eth[] = { -- { .compatible = "mediatek,mt2701-ethsys", }, -- {} -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+ .rst_desc = &clk_rst_desc, - }; - --static int clk_mt2701_eth_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, eth_clks, -- ARRAY_SIZE(eth_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -+static const struct of_device_id of_match_clk_mt2701_eth[] = { -+ { .compatible = "mediatek,mt2701-ethsys", .data = ð_desc }, -+ { /* sentinel */ } -+}; - - static struct platform_driver clk_mt2701_eth_drv = { -- .probe = clk_mt2701_eth_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-eth", - .of_match_table = of_match_clk_mt2701_eth, ---- a/drivers/clk/mediatek/clk-mt2701-g3d.c -+++ b/drivers/clk/mediatek/clk-mt2701-g3d.c -@@ -26,6 +26,7 @@ static const struct mtk_gate_regs g3d_cg - }; - - static const struct mtk_gate g3d_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "g3d_dummy"), - GATE_G3D(CLK_G3DSYS_CORE, "g3d_core", "mfg_sel", 0), - }; - -@@ -37,57 +38,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt2701_g3dsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, g3d_clks, ARRAY_SIZE(g3d_clks), -- clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -+static const struct mtk_clk_desc g3d_desc = { -+ .clks = g3d_clks, -+ .num_clks = ARRAY_SIZE(g3d_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt2701_g3d[] = { -- { -- .compatible = "mediatek,mt2701-g3dsys", -- .data = clk_mt2701_g3dsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt2701-g3dsys", .data = &g3d_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt2701_g3d_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt2701_g3d_drv = { -- .probe = clk_mt2701_g3d_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-g3d", - .of_match_table = of_match_clk_mt2701_g3d, ---- a/drivers/clk/mediatek/clk-mt2701-hif.c -+++ b/drivers/clk/mediatek/clk-mt2701-hif.c -@@ -20,6 +20,7 @@ static const struct mtk_gate_regs hif_cg - GATE_MTK(_id, _name, _parent, &hif_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) - - static const struct mtk_gate hif_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "hif_dummy"), - GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21), - GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22), - GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24), -@@ -35,37 +36,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static const struct of_device_id of_match_clk_mt2701_hif[] = { -- { .compatible = "mediatek,mt2701-hifsys", }, -- {} -+static const struct mtk_clk_desc hif_desc = { -+ .clks = hif_clks, -+ .num_clks = ARRAY_SIZE(hif_clks), -+ .rst_desc = &clk_rst_desc, - }; - --static int clk_mt2701_hif_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, hif_clks, -- ARRAY_SIZE(hif_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) { -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- return r; -- } -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return 0; --} -+static const struct of_device_id of_match_clk_mt2701_hif[] = { -+ { .compatible = "mediatek,mt2701-hifsys", .data = &hif_desc }, -+ { /* sentinel */ } -+}; - - static struct platform_driver clk_mt2701_hif_drv = { -- .probe = clk_mt2701_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-hif", - .of_match_table = of_match_clk_mt2701_hif, ---- a/drivers/clk/mediatek/clk-mt2712.c -+++ b/drivers/clk/mediatek/clk-mt2712.c -@@ -1337,50 +1337,6 @@ static int clk_mt2712_top_probe(struct p - return r; - } - --static int clk_mt2712_infra_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, infra_clks, -- ARRAY_SIZE(infra_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- -- if (r != 0) -- pr_err("%s(): could not register clock provider: %d\n", -- __func__, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); -- -- return r; --} -- --static int clk_mt2712_peri_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, peri_clks, -- ARRAY_SIZE(peri_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- -- if (r != 0) -- pr_err("%s(): could not register clock provider: %d\n", -- __func__, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); -- -- return r; --} -- - static int clk_mt2712_mcu_probe(struct platform_device *pdev) - { - struct clk_hw_onecell_data *clk_data; -@@ -1419,12 +1375,6 @@ static const struct of_device_id of_matc - .compatible = "mediatek,mt2712-topckgen", - .data = clk_mt2712_top_probe, - }, { -- .compatible = "mediatek,mt2712-infracfg", -- .data = clk_mt2712_infra_probe, -- }, { -- .compatible = "mediatek,mt2712-pericfg", -- .data = clk_mt2712_peri_probe, -- }, { - .compatible = "mediatek,mt2712-mcucfg", - .data = clk_mt2712_mcu_probe, - }, { -@@ -1450,6 +1400,33 @@ static int clk_mt2712_probe(struct platf - return r; - } - -+static const struct mtk_clk_desc infra_desc = { -+ .clks = infra_clks, -+ .num_clks = ARRAY_SIZE(infra_clks), -+ .rst_desc = &clk_rst_desc[0], -+}; -+ -+static const struct mtk_clk_desc peri_desc = { -+ .clks = peri_clks, -+ .num_clks = ARRAY_SIZE(peri_clks), -+ .rst_desc = &clk_rst_desc[1], -+}; -+ -+static const struct of_device_id of_match_clk_mt2712_simple[] = { -+ { .compatible = "mediatek,mt2712-infracfg", .data = &infra_desc }, -+ { .compatible = "mediatek,mt2712-pericfg", .data = &peri_desc, }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt2712_simple_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt2712-simple", -+ .of_match_table = of_match_clk_mt2712_simple, -+ }, -+}; -+ - static struct platform_driver clk_mt2712_drv = { - .probe = clk_mt2712_probe, - .driver = { -@@ -1460,7 +1437,11 @@ static struct platform_driver clk_mt2712 - - static int __init clk_mt2712_init(void) - { -- return platform_driver_register(&clk_mt2712_drv); -+ int ret = platform_driver_register(&clk_mt2712_drv); -+ -+ if (ret) -+ return ret; -+ return platform_driver_register(&clk_mt2712_simple_drv); - } - - arch_initcall(clk_mt2712_init); ---- a/drivers/clk/mediatek/clk-mt7622-aud.c -+++ b/drivers/clk/mediatek/clk-mt7622-aud.c -@@ -106,24 +106,22 @@ static const struct mtk_gate audio_clks[ - GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), - }; - --static int clk_mt7622_audiosys_init(struct platform_device *pdev) -+static const struct mtk_clk_desc audio_desc = { -+ .clks = audio_clks, -+ .num_clks = ARRAY_SIZE(audio_clks), -+}; -+ -+static int clk_mt7622_aud_probe(struct platform_device *pdev) - { -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; - int r; - -- clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, audio_clks, -- ARRAY_SIZE(audio_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ r = mtk_clk_simple_probe(pdev); - if (r) { - dev_err(&pdev->dev, - "could not register clock provider: %s: %d\n", - pdev->name, r); - -- goto err_clk_provider; -+ return r; - } - - r = devm_of_platform_populate(&pdev->dev); -@@ -133,40 +131,24 @@ static int clk_mt7622_audiosys_init(stru - return 0; - - err_plat_populate: -- of_clk_del_provider(node); --err_clk_provider: -+ mtk_clk_simple_remove(pdev); - return r; - } - --static const struct of_device_id of_match_clk_mt7622_aud[] = { -- { -- .compatible = "mediatek,mt7622-audsys", -- .data = clk_mt7622_audiosys_init, -- }, { -- /* sentinel */ -- } --}; -- --static int clk_mt7622_aud_probe(struct platform_device *pdev) -+static int clk_mt7622_aud_remove(struct platform_device *pdev) - { -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; -+ of_platform_depopulate(&pdev->dev); -+ return mtk_clk_simple_remove(pdev); - } - -+static const struct of_device_id of_match_clk_mt7622_aud[] = { -+ { .compatible = "mediatek,mt7622-audsys", .data = &audio_desc }, -+ { /* sentinel */ } -+}; -+ - static struct platform_driver clk_mt7622_aud_drv = { - .probe = clk_mt7622_aud_probe, -+ .remove = clk_mt7622_aud_remove, - .driver = { - .name = "clk-mt7622-aud", - .of_match_table = of_match_clk_mt7622_aud, ---- a/drivers/clk/mediatek/clk-mt7622-eth.c -+++ b/drivers/clk/mediatek/clk-mt7622-eth.c -@@ -61,80 +61,26 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7622_ethsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, eth_clks, -- ARRAY_SIZE(eth_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, sgmii_clks, -- ARRAY_SIZE(sgmii_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc sgmii_desc = { -+ .clks = sgmii_clks, -+ .num_clks = ARRAY_SIZE(sgmii_clks), -+}; - - static const struct of_device_id of_match_clk_mt7622_eth[] = { -- { -- .compatible = "mediatek,mt7622-ethsys", -- .data = clk_mt7622_ethsys_init, -- }, { -- .compatible = "mediatek,mt7622-sgmiisys", -- .data = clk_mt7622_sgmiisys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7622-ethsys", .data = ð_desc }, -+ { .compatible = "mediatek,mt7622-sgmiisys", .data = &sgmii_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7622_eth_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7622_eth_drv = { -- .probe = clk_mt7622_eth_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7622-eth", - .of_match_table = of_match_clk_mt7622_eth, ---- a/drivers/clk/mediatek/clk-mt7622-hif.c -+++ b/drivers/clk/mediatek/clk-mt7622-hif.c -@@ -72,82 +72,27 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -- ARRAY_SIZE(ssusb_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7622_pciesys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -- ARRAY_SIZE(pcie_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -+static const struct mtk_clk_desc ssusb_desc = { -+ .clks = ssusb_clks, -+ .num_clks = ARRAY_SIZE(ssusb_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc pcie_desc = { -+ .clks = pcie_clks, -+ .num_clks = ARRAY_SIZE(pcie_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt7622_hif[] = { -- { -- .compatible = "mediatek,mt7622-pciesys", -- .data = clk_mt7622_pciesys_init, -- }, { -- .compatible = "mediatek,mt7622-ssusbsys", -- .data = clk_mt7622_ssusbsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7622-pciesys", .data = &pcie_desc }, -+ { .compatible = "mediatek,mt7622-ssusbsys", .data = &ssusb_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7622_hif_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7622_hif_drv = { -- .probe = clk_mt7622_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7622-hif", - .of_match_table = of_match_clk_mt7622_hif, ---- a/drivers/clk/mediatek/clk-mt7629-hif.c -+++ b/drivers/clk/mediatek/clk-mt7629-hif.c -@@ -67,82 +67,27 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -- ARRAY_SIZE(ssusb_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7629_pciesys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -- ARRAY_SIZE(pcie_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -+static const struct mtk_clk_desc ssusb_desc = { -+ .clks = ssusb_clks, -+ .num_clks = ARRAY_SIZE(ssusb_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc pcie_desc = { -+ .clks = pcie_clks, -+ .num_clks = ARRAY_SIZE(pcie_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt7629_hif[] = { -- { -- .compatible = "mediatek,mt7629-pciesys", -- .data = clk_mt7629_pciesys_init, -- }, { -- .compatible = "mediatek,mt7629-ssusbsys", -- .data = clk_mt7629_ssusbsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7629-pciesys", .data = &pcie_desc }, -+ { .compatible = "mediatek,mt7629-ssusbsys", .data = &ssusb_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7629_hif_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7629_hif_drv = { -- .probe = clk_mt7629_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7629-hif", - .of_match_table = of_match_clk_mt7629_hif, diff --git a/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch b/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch deleted file mode 100644 index ad02df10b6..0000000000 --- a/target/linux/mediatek/patches-6.6/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 7b6183108c8ccf0dc295f39cdf78bd8078455636 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:42 +0100 -Subject: [PATCH] clk: mediatek: clk-mtk: Extend mtk_clk_simple_probe() - -As a preparation to increase probe functions commonization across -various MediaTek SoC clock controller drivers, extend function -mtk_clk_simple_probe() to be able to register not only gates, but -also fixed clocks, factors, muxes and composites. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Reviewed-by: Chen-Yu Tsai -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-13-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mtk.c | 101 ++++++++++++++++++++++++++++++--- - drivers/clk/mediatek/clk-mtk.h | 10 ++++ - 2 files changed, 103 insertions(+), 8 deletions(-) - ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -11,12 +11,14 @@ - #include - #include - #include -+#include - #include - #include - #include - - #include "clk-mtk.h" - #include "clk-gate.h" -+#include "clk-mux.h" - - const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; - EXPORT_SYMBOL_GPL(cg_regs_dummy); -@@ -466,20 +468,71 @@ int mtk_clk_simple_probe(struct platform - const struct mtk_clk_desc *mcd; - struct clk_hw_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; -- int r; -+ void __iomem *base; -+ int num_clks, r; - - mcd = of_device_get_match_data(&pdev->dev); - if (!mcd) - return -EINVAL; - -- clk_data = mtk_alloc_clk_data(mcd->num_clks); -+ /* Composite clocks needs us to pass iomem pointer */ -+ if (mcd->composite_clks) { -+ if (!mcd->shared_io) -+ base = devm_platform_ioremap_resource(pdev, 0); -+ else -+ base = of_iomap(node, 0); -+ -+ if (IS_ERR_OR_NULL(base)) -+ return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM; -+ } -+ -+ /* Calculate how many clk_hw_onecell_data entries to allocate */ -+ num_clks = mcd->num_clks + mcd->num_composite_clks; -+ num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; -+ num_clks += mcd->num_mux_clks; -+ -+ clk_data = mtk_alloc_clk_data(num_clks); - if (!clk_data) - return -ENOMEM; - -- r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, mcd->num_clks, -- clk_data); -- if (r) -- goto free_data; -+ if (mcd->fixed_clks) { -+ r = mtk_clk_register_fixed_clks(mcd->fixed_clks, -+ mcd->num_fixed_clks, clk_data); -+ if (r) -+ goto free_data; -+ } -+ -+ if (mcd->factor_clks) { -+ r = mtk_clk_register_factors(mcd->factor_clks, -+ mcd->num_factor_clks, clk_data); -+ if (r) -+ goto unregister_fixed_clks; -+ } -+ -+ if (mcd->mux_clks) { -+ r = mtk_clk_register_muxes(&pdev->dev, mcd->mux_clks, -+ mcd->num_mux_clks, node, -+ mcd->clk_lock, clk_data); -+ if (r) -+ goto unregister_factors; -+ }; -+ -+ if (mcd->composite_clks) { -+ /* We don't check composite_lock because it's optional */ -+ r = mtk_clk_register_composites(&pdev->dev, -+ mcd->composite_clks, -+ mcd->num_composite_clks, -+ base, mcd->clk_lock, clk_data); -+ if (r) -+ goto unregister_muxes; -+ } -+ -+ if (mcd->clks) { -+ r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, -+ mcd->num_clks, clk_data); -+ if (r) -+ goto unregister_composites; -+ } - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) -@@ -497,9 +550,28 @@ int mtk_clk_simple_probe(struct platform - return r; - - unregister_clks: -- mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); -+ if (mcd->clks) -+ mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); -+unregister_composites: -+ if (mcd->composite_clks) -+ mtk_clk_unregister_composites(mcd->composite_clks, -+ mcd->num_composite_clks, clk_data); -+unregister_muxes: -+ if (mcd->mux_clks) -+ mtk_clk_unregister_muxes(mcd->mux_clks, -+ mcd->num_mux_clks, clk_data); -+unregister_factors: -+ if (mcd->factor_clks) -+ mtk_clk_unregister_factors(mcd->factor_clks, -+ mcd->num_factor_clks, clk_data); -+unregister_fixed_clks: -+ if (mcd->fixed_clks) -+ mtk_clk_unregister_fixed_clks(mcd->fixed_clks, -+ mcd->num_fixed_clks, clk_data); - free_data: - mtk_free_clk_data(clk_data); -+ if (mcd->shared_io && base) -+ iounmap(base); - return r; - } - EXPORT_SYMBOL_GPL(mtk_clk_simple_probe); -@@ -511,7 +583,20 @@ int mtk_clk_simple_remove(struct platfor - struct device_node *node = pdev->dev.of_node; - - of_clk_del_provider(node); -- mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); -+ if (mcd->clks) -+ mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); -+ if (mcd->composite_clks) -+ mtk_clk_unregister_composites(mcd->composite_clks, -+ mcd->num_composite_clks, clk_data); -+ if (mcd->mux_clks) -+ mtk_clk_unregister_muxes(mcd->mux_clks, -+ mcd->num_mux_clks, clk_data); -+ if (mcd->factor_clks) -+ mtk_clk_unregister_factors(mcd->factor_clks, -+ mcd->num_factor_clks, clk_data); -+ if (mcd->fixed_clks) -+ mtk_clk_unregister_fixed_clks(mcd->fixed_clks, -+ mcd->num_fixed_clks, clk_data); - mtk_free_clk_data(clk_data); - - return 0; ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -215,7 +215,17 @@ void mtk_clk_unregister_ref2usb_tx(struc - struct mtk_clk_desc { - const struct mtk_gate *clks; - size_t num_clks; -+ const struct mtk_composite *composite_clks; -+ size_t num_composite_clks; -+ const struct mtk_fixed_clk *fixed_clks; -+ size_t num_fixed_clks; -+ const struct mtk_fixed_factor *factor_clks; -+ size_t num_factor_clks; -+ const struct mtk_mux *mux_clks; -+ size_t num_mux_clks; - const struct mtk_clk_rst_desc *rst_desc; -+ spinlock_t *clk_lock; -+ bool shared_io; - }; - - int mtk_clk_simple_probe(struct platform_device *pdev); diff --git a/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch b/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch deleted file mode 100644 index bf9a172926..0000000000 --- a/target/linux/mediatek/patches-6.6/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 3511004225ce917a4aa6e6ac61481ac60f08f401 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:52 +0100 -Subject: [PATCH 06/15] clk: mediatek: clk-mt7986-topckgen: Properly keep some - clocks enabled - -Instead of calling clk_prepare_enable() on a bunch of clocks at probe -time, set the CLK_IS_CRITICAL flag to the same as these are required -to be always on, and this is the right way of achieving that. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Reviewed-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-23-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-topckgen.c | 46 +++++++++++----------- - 1 file changed, 24 insertions(+), 22 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-topckgen.c -+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c -@@ -202,16 +202,23 @@ static const struct mtk_mux top_muxes[] - MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", - f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, - 0x1C0, 10), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, -- 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", -+ f_26m_adc_parents, 0x020, 0x024, 0x028, -+ 24, 1, 31, 0x1C0, 11, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - /* CLK_CFG_3 */ -- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -- dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, -- 0x1C0, 12), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, -- 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, -- 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -+ dramc_md32_parents, 0x030, 0x034, 0x038, -+ 0, 1, 7, 0x1C0, 12, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", -+ sysaxi_parents, 0x030, 0x034, 0x038, -+ 8, 2, 15, 0x1C0, 13, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", -+ sysapb_parents, 0x030, 0x034, 0x038, -+ 16, 2, 23, 0x1C0, 14, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", - arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, - 31, 0x1C0, 15), -@@ -234,9 +241,10 @@ static const struct mtk_mux top_muxes[] - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", - sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, - 0x1C0, 21), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", -- sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, -- 0x1C0, 22), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", -+ sgm_reg_parents, 0x050, 0x054, 0x058, -+ 16, 1, 23, 0x1C0, 22, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), - /* CLK_CFG_6 */ -@@ -252,9 +260,10 @@ static const struct mtk_mux top_muxes[] - f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, - 0x1C0, 27), - /* CLK_CFG_7 */ -- MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", -- f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, -- 0x1C0, 28), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", -+ f_26m_adc_parents, 0x070, 0x074, 0x078, -+ 0, 1, 7, 0x1C0, 28, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", -@@ -307,13 +316,6 @@ static int clk_mt7986_topckgen_probe(str - ARRAY_SIZE(top_muxes), node, - &mt7986_clk_lock, clk_data); - -- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAPB_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_MD32_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_F26M_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_SGM_REG_SEL]->clk); -- - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - - if (r) { diff --git a/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch b/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch deleted file mode 100644 index d77b859f00..0000000000 --- a/target/linux/mediatek/patches-6.6/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 9ce3b4e4719d4eec38b2c8da939c073835573d1d Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:53 +0100 -Subject: [PATCH 07/15] clk: mediatek: clk-mt7986-topckgen: Migrate to - mtk_clk_simple_probe() - -There are no more non-common calls in clk_mt7986_topckgen_probe(): -migrate this driver to mtk_clk_simple_probe(). - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Reviewed-by: Chen-Yu Tsai -Link: https://lore.kernel.org/r/20230120092053.182923-24-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-topckgen.c | 55 +++++----------------- - 1 file changed, 13 insertions(+), 42 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-topckgen.c -+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c -@@ -290,53 +290,24 @@ static const struct mtk_mux top_muxes[] - 0x1C4, 5), - }; - --static int clk_mt7986_topckgen_probe(struct platform_device *pdev) --{ -- struct clk_hw_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); -- -- 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(&pdev->dev, top_muxes, -- ARRAY_SIZE(top_muxes), node, -- &mt7986_clk_lock, clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_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 struct mtk_clk_desc topck_desc = { -+ .fixed_clks = top_fixed_clks, -+ .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), -+ .factor_clks = top_divs, -+ .num_factor_clks = ARRAY_SIZE(top_divs), -+ .mux_clks = top_muxes, -+ .num_mux_clks = ARRAY_SIZE(top_muxes), -+ .clk_lock = &mt7986_clk_lock, -+}; - - static const struct of_device_id of_match_clk_mt7986_topckgen[] = { -- { .compatible = "mediatek,mt7986-topckgen", }, -- {} -+ { .compatible = "mediatek,mt7986-topckgen", .data = &topck_desc }, -+ { /* sentinel */ } - }; - - static struct platform_driver clk_mt7986_topckgen_drv = { -- .probe = clk_mt7986_topckgen_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7986-topckgen", - .of_match_table = of_match_clk_mt7986_topckgen, diff --git a/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch b/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch deleted file mode 100644 index a47dd4b053..0000000000 --- a/target/linux/mediatek/patches-6.6/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 06abdc84080729dc2c54946e1712c5ee1589ca1c Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Mon, 6 Mar 2023 15:05:21 +0100 -Subject: [PATCH 13/15] clk: mediatek: mt7986-apmixed: Use PLL_AO flag to set - critical clock - -Instead of calling clk_prepare_enable() at probe time, add the PLL_AO -flag to CLK_APMIXED_ARMPLL clock: this will set CLK_IS_CRITICAL. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230306140543.1813621-33-angelogioacchino.delregno@collabora.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-apmixed.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-apmixed.c -+++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c -@@ -42,7 +42,7 @@ - "clkxtal") - - static const struct mtk_pll_data plls[] = { -- PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, 0, 32, -+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, PLL_AO, 32, - 0x0200, 4, 0, 0x0204, 0), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x0, 0, 32, - 0x0210, 4, 0, 0x0214, 0), -@@ -77,8 +77,6 @@ static int clk_mt7986_apmixed_probe(stru - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - -- clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); -- - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", diff --git a/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch b/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch deleted file mode 100644 index ae76940e1d..0000000000 --- a/target/linux/mediatek/patches-6.6/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch +++ /dev/null @@ -1,237 +0,0 @@ -From a6473d0f9f07b1196f3a67099826f50a2a4e84e8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 03:34:05 +0000 -Subject: [PATCH] dt-bindings: clock: mediatek: add mt7981 clock IDs - -Add MT7981 clock dt-bindings, include topckgen, apmixedsys, -infracfg, and ethernet subsystem clocks. - -Acked-by: Krzysztof Kozlowski -Signed-off-by: Jianhui Zhao -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e353d32b5a4481766519a037afe1ed44e31ece1a.1674703830.git.daniel@makrotopia.org -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Stephen Boyd ---- - .../dt-bindings/clock/mediatek,mt7981-clk.h | 215 ++++++++++++++++++ - 1 file changed, 215 insertions(+) - create mode 100644 include/dt-bindings/clock/mediatek,mt7981-clk.h - ---- /dev/null -+++ b/include/dt-bindings/clock/mediatek,mt7981-clk.h -@@ -0,0 +1,215 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Wenzhen.Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_MT7981_H -+#define _DT_BINDINGS_CLK_MT7981_H -+ -+/* TOPCKGEN */ -+#define CLK_TOP_CB_CKSQ_40M 0 -+#define CLK_TOP_CB_M_416M 1 -+#define CLK_TOP_CB_M_D2 2 -+#define CLK_TOP_CB_M_D3 3 -+#define CLK_TOP_M_D3_D2 4 -+#define CLK_TOP_CB_M_D4 5 -+#define CLK_TOP_CB_M_D8 6 -+#define CLK_TOP_M_D8_D2 7 -+#define CLK_TOP_CB_MM_720M 8 -+#define CLK_TOP_CB_MM_D2 9 -+#define CLK_TOP_CB_MM_D3 10 -+#define CLK_TOP_CB_MM_D3_D5 11 -+#define CLK_TOP_CB_MM_D4 12 -+#define CLK_TOP_CB_MM_D6 13 -+#define CLK_TOP_MM_D6_D2 14 -+#define CLK_TOP_CB_MM_D8 15 -+#define CLK_TOP_CB_APLL2_196M 16 -+#define CLK_TOP_APLL2_D2 17 -+#define CLK_TOP_APLL2_D4 18 -+#define CLK_TOP_NET1_2500M 19 -+#define CLK_TOP_CB_NET1_D4 20 -+#define CLK_TOP_CB_NET1_D5 21 -+#define CLK_TOP_NET1_D5_D2 22 -+#define CLK_TOP_NET1_D5_D4 23 -+#define CLK_TOP_CB_NET1_D8 24 -+#define CLK_TOP_NET1_D8_D2 25 -+#define CLK_TOP_NET1_D8_D4 26 -+#define CLK_TOP_CB_NET2_800M 27 -+#define CLK_TOP_CB_NET2_D2 28 -+#define CLK_TOP_CB_NET2_D4 29 -+#define CLK_TOP_NET2_D4_D2 30 -+#define CLK_TOP_NET2_D4_D4 31 -+#define CLK_TOP_CB_NET2_D6 32 -+#define CLK_TOP_CB_WEDMCU_208M 33 -+#define CLK_TOP_CB_SGM_325M 34 -+#define CLK_TOP_CKSQ_40M_D2 35 -+#define CLK_TOP_CB_RTC_32K 36 -+#define CLK_TOP_CB_RTC_32P7K 37 -+#define CLK_TOP_USB_TX250M 38 -+#define CLK_TOP_FAUD 39 -+#define CLK_TOP_NFI1X 40 -+#define CLK_TOP_USB_EQ_RX250M 41 -+#define CLK_TOP_USB_CDR_CK 42 -+#define CLK_TOP_USB_LN0_CK 43 -+#define CLK_TOP_SPINFI_BCK 44 -+#define CLK_TOP_SPI 45 -+#define CLK_TOP_SPIM_MST 46 -+#define CLK_TOP_UART_BCK 47 -+#define CLK_TOP_PWM_BCK 48 -+#define CLK_TOP_I2C_BCK 49 -+#define CLK_TOP_PEXTP_TL 50 -+#define CLK_TOP_EMMC_208M 51 -+#define CLK_TOP_EMMC_400M 52 -+#define CLK_TOP_DRAMC_REF 53 -+#define CLK_TOP_DRAMC_MD32 54 -+#define CLK_TOP_SYSAXI 55 -+#define CLK_TOP_SYSAPB 56 -+#define CLK_TOP_ARM_DB_MAIN 57 -+#define CLK_TOP_AP2CNN_HOST 58 -+#define CLK_TOP_NETSYS 59 -+#define CLK_TOP_NETSYS_500M 60 -+#define CLK_TOP_NETSYS_WED_MCU 61 -+#define CLK_TOP_NETSYS_2X 62 -+#define CLK_TOP_SGM_325M 63 -+#define CLK_TOP_SGM_REG 64 -+#define CLK_TOP_F26M 65 -+#define CLK_TOP_EIP97B 66 -+#define CLK_TOP_USB3_PHY 67 -+#define CLK_TOP_AUD 68 -+#define CLK_TOP_A1SYS 69 -+#define CLK_TOP_AUD_L 70 -+#define CLK_TOP_A_TUNER 71 -+#define CLK_TOP_U2U3_REF 72 -+#define CLK_TOP_U2U3_SYS 73 -+#define CLK_TOP_U2U3_XHCI 74 -+#define CLK_TOP_USB_FRMCNT 75 -+#define CLK_TOP_NFI1X_SEL 76 -+#define CLK_TOP_SPINFI_SEL 77 -+#define CLK_TOP_SPI_SEL 78 -+#define CLK_TOP_SPIM_MST_SEL 79 -+#define CLK_TOP_UART_SEL 80 -+#define CLK_TOP_PWM_SEL 81 -+#define CLK_TOP_I2C_SEL 82 -+#define CLK_TOP_PEXTP_TL_SEL 83 -+#define CLK_TOP_EMMC_208M_SEL 84 -+#define CLK_TOP_EMMC_400M_SEL 85 -+#define CLK_TOP_F26M_SEL 86 -+#define CLK_TOP_DRAMC_SEL 87 -+#define CLK_TOP_DRAMC_MD32_SEL 88 -+#define CLK_TOP_SYSAXI_SEL 89 -+#define CLK_TOP_SYSAPB_SEL 90 -+#define CLK_TOP_ARM_DB_MAIN_SEL 91 -+#define CLK_TOP_AP2CNN_HOST_SEL 92 -+#define CLK_TOP_NETSYS_SEL 93 -+#define CLK_TOP_NETSYS_500M_SEL 94 -+#define CLK_TOP_NETSYS_MCU_SEL 95 -+#define CLK_TOP_NETSYS_2X_SEL 96 -+#define CLK_TOP_SGM_325M_SEL 97 -+#define CLK_TOP_SGM_REG_SEL 98 -+#define CLK_TOP_EIP97B_SEL 99 -+#define CLK_TOP_USB3_PHY_SEL 100 -+#define CLK_TOP_AUD_SEL 101 -+#define CLK_TOP_A1SYS_SEL 102 -+#define CLK_TOP_AUD_L_SEL 103 -+#define CLK_TOP_A_TUNER_SEL 104 -+#define CLK_TOP_U2U3_SEL 105 -+#define CLK_TOP_U2U3_SYS_SEL 106 -+#define CLK_TOP_U2U3_XHCI_SEL 107 -+#define CLK_TOP_USB_FRMCNT_SEL 108 -+#define CLK_TOP_AUD_I2S_M 109 -+ -+/* INFRACFG */ -+#define CLK_INFRA_66M_MCK 0 -+#define CLK_INFRA_UART0_SEL 1 -+#define CLK_INFRA_UART1_SEL 2 -+#define CLK_INFRA_UART2_SEL 3 -+#define CLK_INFRA_SPI0_SEL 4 -+#define CLK_INFRA_SPI1_SEL 5 -+#define CLK_INFRA_SPI2_SEL 6 -+#define CLK_INFRA_PWM1_SEL 7 -+#define CLK_INFRA_PWM2_SEL 8 -+#define CLK_INFRA_PWM3_SEL 9 -+#define CLK_INFRA_PWM_BSEL 10 -+#define CLK_INFRA_PCIE_SEL 11 -+#define CLK_INFRA_GPT_STA 12 -+#define CLK_INFRA_PWM_HCK 13 -+#define CLK_INFRA_PWM_STA 14 -+#define CLK_INFRA_PWM1_CK 15 -+#define CLK_INFRA_PWM2_CK 16 -+#define CLK_INFRA_PWM3_CK 17 -+#define CLK_INFRA_CQ_DMA_CK 18 -+#define CLK_INFRA_AUD_BUS_CK 19 -+#define CLK_INFRA_AUD_26M_CK 20 -+#define CLK_INFRA_AUD_L_CK 21 -+#define CLK_INFRA_AUD_AUD_CK 22 -+#define CLK_INFRA_AUD_EG2_CK 23 -+#define CLK_INFRA_DRAMC_26M_CK 24 -+#define CLK_INFRA_DBG_CK 25 -+#define CLK_INFRA_AP_DMA_CK 26 -+#define CLK_INFRA_SEJ_CK 27 -+#define CLK_INFRA_SEJ_13M_CK 28 -+#define CLK_INFRA_THERM_CK 29 -+#define CLK_INFRA_I2C0_CK 30 -+#define CLK_INFRA_UART0_CK 31 -+#define CLK_INFRA_UART1_CK 32 -+#define CLK_INFRA_UART2_CK 33 -+#define CLK_INFRA_SPI2_CK 34 -+#define CLK_INFRA_SPI2_HCK_CK 35 -+#define CLK_INFRA_NFI1_CK 36 -+#define CLK_INFRA_SPINFI1_CK 37 -+#define CLK_INFRA_NFI_HCK_CK 38 -+#define CLK_INFRA_SPI0_CK 39 -+#define CLK_INFRA_SPI1_CK 40 -+#define CLK_INFRA_SPI0_HCK_CK 41 -+#define CLK_INFRA_SPI1_HCK_CK 42 -+#define CLK_INFRA_FRTC_CK 43 -+#define CLK_INFRA_MSDC_CK 44 -+#define CLK_INFRA_MSDC_HCK_CK 45 -+#define CLK_INFRA_MSDC_133M_CK 46 -+#define CLK_INFRA_MSDC_66M_CK 47 -+#define CLK_INFRA_ADC_26M_CK 48 -+#define CLK_INFRA_ADC_FRC_CK 49 -+#define CLK_INFRA_FBIST2FPC_CK 50 -+#define CLK_INFRA_I2C_MCK_CK 51 -+#define CLK_INFRA_I2C_PCK_CK 52 -+#define CLK_INFRA_IUSB_133_CK 53 -+#define CLK_INFRA_IUSB_66M_CK 54 -+#define CLK_INFRA_IUSB_SYS_CK 55 -+#define CLK_INFRA_IUSB_CK 56 -+#define CLK_INFRA_IPCIE_CK 57 -+#define CLK_INFRA_IPCIE_PIPE_CK 58 -+#define CLK_INFRA_IPCIER_CK 59 -+#define CLK_INFRA_IPCIEB_CK 60 -+ -+/* APMIXEDSYS */ -+#define CLK_APMIXED_ARMPLL 0 -+#define CLK_APMIXED_NET2PLL 1 -+#define CLK_APMIXED_MMPLL 2 -+#define CLK_APMIXED_SGMPLL 3 -+#define CLK_APMIXED_WEDMCUPLL 4 -+#define CLK_APMIXED_NET1PLL 5 -+#define CLK_APMIXED_MPLL 6 -+#define CLK_APMIXED_APLL2 7 -+ -+/* SGMIISYS_0 */ -+#define CLK_SGM0_TX_EN 0 -+#define CLK_SGM0_RX_EN 1 -+#define CLK_SGM0_CK0_EN 2 -+#define CLK_SGM0_CDR_CK0_EN 3 -+ -+/* SGMIISYS_1 */ -+#define CLK_SGM1_TX_EN 0 -+#define CLK_SGM1_RX_EN 1 -+#define CLK_SGM1_CK1_EN 2 -+#define CLK_SGM1_CDR_CK1_EN 3 -+ -+/* ETHSYS */ -+#define CLK_ETH_FE_EN 0 -+#define CLK_ETH_GP2_EN 1 -+#define CLK_ETH_GP1_EN 2 -+#define CLK_ETH_WOCPU0_EN 3 -+ -+#endif /* _DT_BINDINGS_CLK_MT7981_H */ diff --git a/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch b/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch deleted file mode 100644 index f9dd94a78a..0000000000 --- a/target/linux/mediatek/patches-6.6/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch +++ /dev/null @@ -1,932 +0,0 @@ -From 8efeeb9c8b4ecf4fb4a74be9403aba951403bbaa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 03:34:24 +0000 -Subject: [PATCH] clk: mediatek: add MT7981 clock support - -Add MT7981 clock support, include topckgen, apmixedsys, infracfg and -ethernet subsystem clocks. - -The drivers are based on clk-mt7981.c which can be found in MediaTek's -SDK sources. To be fit for upstream inclusion the driver has been split -into clock domains and the infracfg part has been significantly -de-bloated by removing all the 1:1 factors (aliases). - -Signed-off-by: Jianhui Zhao -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/8136eb5b2049177bc2f6d3e0f2aefecc342d626f.1674703830.git.daniel@makrotopia.org -Reviewed-by: AngeloGioacchino Del Regno -[sboyd@kernel.org: Add module license] -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/Kconfig | 17 + - drivers/clk/mediatek/Makefile | 4 + - drivers/clk/mediatek/clk-mt7981-apmixed.c | 102 +++++ - drivers/clk/mediatek/clk-mt7981-eth.c | 118 ++++++ - drivers/clk/mediatek/clk-mt7981-infracfg.c | 207 ++++++++++ - drivers/clk/mediatek/clk-mt7981-topckgen.c | 422 +++++++++++++++++++++ - 6 files changed, 870 insertions(+) - create mode 100644 drivers/clk/mediatek/clk-mt7981-apmixed.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-eth.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-infracfg.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-topckgen.c - ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -381,6 +381,23 @@ config COMMON_CLK_MT7629_HIFSYS - This driver supports MediaTek MT7629 HIFSYS clocks providing - to PCI-E and USB. - -+config COMMON_CLK_MT7981 -+ bool "Clock driver for MediaTek MT7981" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7981 basic clocks and clocks -+ required for various peripherals found on this SoC. -+ -+config COMMON_CLK_MT7981_ETHSYS -+ tristate "Clock driver for MediaTek MT7981 ETHSYS" -+ depends on COMMON_CLK_MT7981 -+ default COMMON_CLK_MT7981 -+ help -+ This driver adds support for clocks for Ethernet and SGMII -+ required on MediaTek MT7981 SoC. -+ - config COMMON_CLK_MT7986 - bool "Clock driver for MediaTek MT7986" - depends on ARCH_MEDIATEK || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -52,6 +52,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + - obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o - obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o - obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7981_ETHSYS) += clk-mt7981-eth.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-apmixed.c -@@ -0,0 +1,102 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-gate.h" -+#include "clk-mtk.h" -+#include "clk-mux.h" -+#include "clk-pll.h" -+ -+#include -+#include -+ -+#define MT7981_PLL_FMAX (2500UL * MHZ) -+#define CON0_MT7981_RST_BAR BIT(27) -+ -+#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ -+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ -+ _div_table, _parent_name) \ -+ { \ -+ .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ -+ .en_mask = _en_mask, .flags = _flags, \ -+ .rst_bar_mask = CON0_MT7981_RST_BAR, .fmax = MT7981_PLL_FMAX, \ -+ .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ -+ .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ -+ .pcw_shift = _pcw_shift, .div_table = _div_table, \ -+ .parent_name = _parent_name, \ -+ } -+ -+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ -+ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ -+ PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ -+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ -+ "clkxtal") -+ -+static const struct mtk_pll_data plls[] = { -+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, PLL_AO, -+ 32, 0x0200, 4, 0, 0x0204, 0), -+ PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, -+ 0x0210, 4, 0, 0x0214, 0), -+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, -+ 0x0220, 4, 0, 0x0224, 0), -+ PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023C, 0x00000001, 0, 32, -+ 0x0230, 4, 0, 0x0234, 0), -+ PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024C, 0x00000001, 0, 32, -+ 0x0240, 4, 0, 0x0244, 0), -+ PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025C, 0x00000001, 0, 32, -+ 0x0250, 4, 0, 0x0254, 0), -+ PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, -+ 0x0260, 4, 0, 0x0264, 0), -+ PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, -+ 0x0278, 4, 0, 0x027C, 0), -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_apmixed[] = { -+ { .compatible = "mediatek,mt7981-apmixedsys", }, -+ { /* sentinel */ } -+}; -+ -+static int clk_mt7981_apmixed_probe(struct platform_device *pdev) -+{ -+ struct clk_hw_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_hw_provider(node, of_clk_hw_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_mt7981_apmixed_drv = { -+ .probe = clk_mt7981_apmixed_probe, -+ .driver = { -+ .name = "clk-mt7981-apmixed", -+ .of_match_table = of_match_clk_mt7981_apmixed, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_apmixed_drv); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-eth.c -@@ -0,0 +1,118 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-mtk.h" -+#include "clk-gate.h" -+ -+#include -+ -+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[] __initconst = { -+ GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "usb_tx250m", 2), -+ GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "usb_eq_rx250m", 3), -+ GATE_SGMII0(CLK_SGM0_CK0_EN, "sgm0_ck0_en", "usb_ln0", 4), -+ GATE_SGMII0(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", "usb_cdr", 5), -+}; -+ -+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[] __initconst = { -+ GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "usb_tx250m", 2), -+ GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "usb_eq_rx250m", 3), -+ GATE_SGMII1(CLK_SGM1_CK1_EN, "sgm1_ck1_en", "usb_ln0", 4), -+ GATE_SGMII1(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", "usb_cdr", 5), -+}; -+ -+static const struct mtk_gate_regs eth_cg_regs = { -+ .set_ofs = 0x30, -+ .clr_ofs = 0x30, -+ .sta_ofs = 0x30, -+}; -+ -+#define GATE_ETH(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = ð_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate eth_clks[] __initconst = { -+ GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x", 6), -+ GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m", 7), -+ GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m", 8), -+ GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_wed_mcu", 15), -+}; -+ -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+}; -+ -+static const struct mtk_clk_desc sgmii0_desc = { -+ .clks = sgmii0_clks, -+ .num_clks = ARRAY_SIZE(sgmii0_clks), -+}; -+ -+static const struct mtk_clk_desc sgmii1_desc = { -+ .clks = sgmii1_clks, -+ .num_clks = ARRAY_SIZE(sgmii1_clks), -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_eth[] = { -+ { .compatible = "mediatek,mt7981-ethsys", .data = ð_desc }, -+ { .compatible = "mediatek,mt7981-sgmiisys_0", .data = &sgmii0_desc }, -+ { .compatible = "mediatek,mt7981-sgmiisys_1", .data = &sgmii1_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_eth_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-eth", -+ .of_match_table = of_match_clk_mt7981_eth, -+ }, -+}; -+module_platform_driver(clk_mt7981_eth_drv); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-infracfg.c -@@ -0,0 +1,207 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "clk-mtk.h" -+#include "clk-gate.h" -+#include "clk-mux.h" -+ -+#include -+#include -+ -+static DEFINE_SPINLOCK(mt7981_clk_lock); -+ -+static const struct mtk_fixed_factor infra_divs[] = { -+ FACTOR(CLK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi_sel", 1, 2), -+}; -+ -+static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", -+ "uart_sel" }; -+ -+static const char *const infra_spi0_parents[] __initconst = { "i2c_sel", -+ "spi_sel" }; -+ -+static const char *const infra_spi1_parents[] __initconst = { "i2c_sel", -+ "spim_mst_sel" }; -+ -+static const char *const infra_pwm1_parents[] __initconst = { "pwm_sel" }; -+ -+static const char *const infra_pwm_bsel_parents[] __initconst = { -+ "cb_rtc_32p7k", "csw_f26m_sel", "infra_66m_mck", "pwm_sel" -+}; -+ -+static const char *const infra_pcie_parents[] __initconst = { -+ "cb_rtc_32p7k", "csw_f26m_sel", "cb_cksq_40m", "pextp_tl_ck_sel" -+}; -+ -+static const struct mtk_mux infra_muxes[] = { -+ /* MODULE_CLK_SEL_0 */ -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", -+ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 4, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", -+ infra_spi1_parents, 0x0018, 0x0010, 0x0014, 5, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI2_SEL, "infra_spi2_sel", -+ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 6, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 9, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 11, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM3_SEL, "infra_pwm3_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 15, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", -+ infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, -+ 2, -1, -1, -1), -+ /* MODULE_CLK_SEL_1 */ -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", -+ infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, -+ -1, -1, -1), -+}; -+ -+static const struct mtk_gate_regs infra0_cg_regs = { -+ .set_ofs = 0x40, -+ .clr_ofs = 0x44, -+ .sta_ofs = 0x48, -+}; -+ -+static const struct mtk_gate_regs infra1_cg_regs = { -+ .set_ofs = 0x50, -+ .clr_ofs = 0x54, -+ .sta_ofs = 0x58, -+}; -+ -+static const struct mtk_gate_regs infra2_cg_regs = { -+ .set_ofs = 0x60, -+ .clr_ofs = 0x64, -+ .sta_ofs = 0x68, -+}; -+ -+#define GATE_INFRA0(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra0_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_INFRA1(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra1_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_INFRA2(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra2_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate infra_clks[] = { -+ /* INFRA0 */ -+ GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_66m_mck", 0), -+ GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1), -+ GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), -+ GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), -+ GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), -+ GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi", 6), -+ -+ GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi", 8), -+ GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), -+ GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l", 10), -+ GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys", 11), -+ GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner", 13), -+ GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", -+ 14), -+ GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_66m_mck", 15), -+ GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16), -+ GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24), -+ GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), -+ GATE_INFRA0(CLK_INFRA_PWM3_CK, "infra_pwm3", "infra_pwm3_sel", 27), -+ /* INFRA1 */ -+ GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), -+ GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_bck", 1), -+ GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), -+ GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), -+ GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), -+ GATE_INFRA1(CLK_INFRA_SPI2_CK, "infra_spi2", "infra_spi2_sel", 6), -+ GATE_INFRA1(CLK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", "infra_66m_mck", 7), -+ GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x", 8), -+ GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_bck", 9), -+ GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_66m_mck", 10), -+ GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), -+ GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), -+ GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_66m_mck", -+ 13), -+ GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_66m_mck", -+ 14), -+ GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "cb_rtc_32k", 15), -+ GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_400m", 16), -+ GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_208m", 17), -+ GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi", 18), -+ GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "sysaxi", 19), -+ GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), -+ GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m", 21), -+ GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x", 23), -+ GATE_INFRA1(CLK_INFRA_I2C_MCK_CK, "infra_i2c_mck", "sysaxi", 25), -+ GATE_INFRA1(CLK_INFRA_I2C_PCK_CK, "infra_i2c_pck", "infra_66m_mck", 26), -+ /* INFRA2 */ -+ GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi", 0), -+ GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "sysaxi", 1), -+ GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys", 2), -+ GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_ref", 3), -+ GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl", 12), -+ GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "cb_cksq_40m", -+ 13), -+ GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m", 14), -+ GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi", 15), -+}; -+ -+static const struct mtk_clk_desc infracfg_desc = { -+ .factor_clks = infra_divs, -+ .num_factor_clks = ARRAY_SIZE(infra_divs), -+ .mux_clks = infra_muxes, -+ .num_mux_clks = ARRAY_SIZE(infra_muxes), -+ .clks = infra_clks, -+ .num_clks = ARRAY_SIZE(infra_clks), -+ .clk_lock = &mt7981_clk_lock, -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_infracfg[] = { -+ { .compatible = "mediatek,mt7981-infracfg", .data = &infracfg_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_infracfg_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-infracfg", -+ .of_match_table = of_match_clk_mt7981_infracfg, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_infracfg_drv); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c -@@ -0,0 +1,422 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include "clk-mtk.h" -+#include "clk-gate.h" -+#include "clk-mux.h" -+ -+#include -+#include -+ -+static DEFINE_SPINLOCK(mt7981_clk_lock); -+ -+static const struct mtk_fixed_factor top_divs[] = { -+ FACTOR(CLK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1), -+ FACTOR(CLK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1), -+ FACTOR(CLK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2), -+ FACTOR(CLK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3), -+ FACTOR(CLK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2), -+ FACTOR(CLK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4), -+ FACTOR(CLK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8), -+ FACTOR(CLK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16), -+ FACTOR(CLK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1), -+ FACTOR(CLK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2), -+ FACTOR(CLK_TOP_CB_MM_D3, "cb_mm_d3", "mmpll", 1, 3), -+ FACTOR(CLK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15), -+ FACTOR(CLK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4), -+ FACTOR(CLK_TOP_CB_MM_D6, "cb_mm_d6", "mmpll", 1, 6), -+ FACTOR(CLK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12), -+ FACTOR(CLK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8), -+ FACTOR(CLK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1), -+ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), -+ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), -+ FACTOR(CLK_TOP_NET1_2500M, "net1_2500m", "net1pll", 1, 1), -+ FACTOR(CLK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4), -+ FACTOR(CLK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5), -+ FACTOR(CLK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10), -+ FACTOR(CLK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20), -+ FACTOR(CLK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8), -+ FACTOR(CLK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16), -+ FACTOR(CLK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32), -+ FACTOR(CLK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1), -+ FACTOR(CLK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2), -+ FACTOR(CLK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4), -+ FACTOR(CLK_TOP_NET2_D4_D2, "net2_d4_d2", "net2pll", 1, 8), -+ FACTOR(CLK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16), -+ FACTOR(CLK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6), -+ FACTOR(CLK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1), -+ FACTOR(CLK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1), -+ FACTOR(CLK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2), -+ FACTOR(CLK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250), -+ FACTOR(CLK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220), -+ FACTOR(CLK_TOP_USB_TX250M, "usb_tx250m", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_FAUD, "faud", "aud_sel", 1, 1), -+ FACTOR(CLK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1), -+ FACTOR(CLK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_USB_CDR_CK, "usb_cdr", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_USB_LN0_CK, "usb_ln0", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1), -+ FACTOR(CLK_TOP_SPI, "spi", "spi_sel", 1, 1), -+ FACTOR(CLK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1), -+ FACTOR(CLK_TOP_UART_BCK, "uart_bck", "uart_sel", 1, 1), -+ FACTOR(CLK_TOP_PWM_BCK, "pwm_bck", "pwm_sel", 1, 1), -+ FACTOR(CLK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1), -+ FACTOR(CLK_TOP_PEXTP_TL, "pextp_tl", "pextp_tl_ck_sel", 1, 1), -+ FACTOR(CLK_TOP_EMMC_208M, "emmc_208m", "emmc_208m_sel", 1, 1), -+ FACTOR(CLK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1), -+ FACTOR(CLK_TOP_DRAMC_REF, "dramc_ref", "dramc_sel", 1, 1), -+ FACTOR(CLK_TOP_DRAMC_MD32, "dramc_md32", "dramc_md32_sel", 1, 1), -+ FACTOR(CLK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1), -+ FACTOR(CLK_TOP_SYSAPB, "sysapb", "sysapb_sel", 1, 1), -+ FACTOR(CLK_TOP_ARM_DB_MAIN, "arm_db_main", "arm_db_main_sel", 1, 1), -+ FACTOR(CLK_TOP_AP2CNN_HOST, "ap2cnn_host", "ap2cnn_host_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS, "netsys", "netsys_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_500M, "netsys_500m", "netsys_500m_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1), -+ FACTOR(CLK_TOP_SGM_325M, "sgm_325m", "sgm_325m_sel", 1, 1), -+ FACTOR(CLK_TOP_SGM_REG, "sgm_reg", "sgm_reg_sel", 1, 1), -+ FACTOR(CLK_TOP_F26M, "csw_f26m", "csw_f26m_sel", 1, 1), -+ FACTOR(CLK_TOP_EIP97B, "eip97b", "eip97b_sel", 1, 1), -+ FACTOR(CLK_TOP_USB3_PHY, "usb3_phy", "usb3_phy_sel", 1, 1), -+ FACTOR(CLK_TOP_AUD, "aud", "faud", 1, 1), -+ FACTOR(CLK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1), -+ FACTOR(CLK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1), -+ FACTOR(CLK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_REF, "u2u3_ref", "u2u3_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_SYS, "u2u3_sys", "u2u3_sys_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_XHCI, "u2u3_xhci", "u2u3_xhci_sel", 1, 1), -+ FACTOR(CLK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1), -+}; -+ -+static const char * const nfi1x_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_net2_d6", -+ "cb_m_d4", -+ "cb_mm_d8", -+ "net1_d8_d4", -+ "cb_m_d8" -+}; -+ -+static const char * const spinfi_parents[] __initconst = { -+ "cksq_40m_d2", -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "cb_mm_d8", -+ "net1_d8_d4", -+ "mm_d6_d2", -+ "cb_m_d8" -+}; -+ -+static const char * const spi_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_net2_d6", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "net1_d8_d4" -+}; -+ -+static const char * const uart_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d8", -+ "m_d8_d2" -+}; -+ -+static const char * const pwm_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d2", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "m_d8_d2", -+ "cb_rtc_32k" -+}; -+ -+static const char * const i2c_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "net1_d8_d4" -+}; -+ -+static const char * const pextp_tl_ck_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "cb_rtc_32k" -+}; -+ -+static const char * const emmc_208m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_net2_d4", -+ "cb_apll2_196m", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_mm_d6" -+}; -+ -+static const char * const emmc_400m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d2", -+ "cb_mm_d2", -+ "cb_net2_d2" -+}; -+ -+static const char * const csw_f26m_parents[] __initconst = { -+ "cksq_40m_d2", -+ "m_d8_d2" -+}; -+ -+static const char * const dramc_md32_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_wedmcu_208m" -+}; -+ -+static const char * const sysaxi_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d2" -+}; -+ -+static const char * const sysapb_parents[] __initconst = { -+ "cb_cksq_40m", -+ "m_d3_d2" -+}; -+ -+static const char * const arm_db_main_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d6" -+}; -+ -+static const char * const ap2cnn_host_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d4" -+}; -+ -+static const char * const netsys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d2" -+}; -+ -+static const char * const netsys_500m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net1_d5" -+}; -+ -+static const char * const netsys_mcu_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_720m", -+ "cb_net1_d4", -+ "cb_net1_d5", -+ "cb_m_416m" -+}; -+ -+static const char * const netsys_2x_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_800m", -+ "cb_mm_720m" -+}; -+ -+static const char * const sgm_325m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_sgm_325m" -+}; -+ -+static const char * const sgm_reg_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d4" -+}; -+ -+static const char * const eip97b_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net1_d5", -+ "cb_m_416m", -+ "cb_mm_d2", -+ "net1_d5_d2" -+}; -+ -+static const char * const aud_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_apll2_196m" -+}; -+ -+static const char * const a1sys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "apll2_d4" -+}; -+ -+static const char * const aud_l_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_apll2_196m", -+ "m_d8_d2" -+}; -+ -+static const char * const a_tuner_parents[] __initconst = { -+ "cb_cksq_40m", -+ "apll2_d4", -+ "m_d8_d2" -+}; -+ -+static const char * const u2u3_parents[] __initconst = { -+ "cb_cksq_40m", -+ "m_d8_d2" -+}; -+ -+static const char * const u2u3_sys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4" -+}; -+ -+static const char * const usb_frmcnt_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d3_d5" -+}; -+ -+static const struct mtk_mux top_muxes[] = { -+ /* CLK_CFG_0 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, -+ 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, -+ 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, -+ 0x000, 0x004, 0x008, 16, 3, 23, 0x1C0, 2), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, -+ 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), -+ /* CLK_CFG_1 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, -+ 0x010, 0x014, 0x018, 0, 2, 7, 0x1C0, 4), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, -+ 0x010, 0x014, 0x018, 8, 3, 15, 0x1C0, 5), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, -+ 0x010, 0x014, 0x018, 16, 2, 23, 0x1C0, 6), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", -+ pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, -+ 0x1C0, 7), -+ /* CLK_CFG_2 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", -+ emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, -+ 0x1C0, 8), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", -+ emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, -+ 0x1C0, 9), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", -+ csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23, -+ 0x1C0, 10, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", -+ csw_f26m_parents, 0x020, 0x024, 0x028, 24, 1, -+ 31, 0x1C0, 11, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ /* CLK_CFG_3 */ -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -+ dramc_md32_parents, 0x030, 0x034, 0x038, 0, 2, -+ 7, 0x1C0, 12, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", -+ sysaxi_parents, 0x030, 0x034, 0x038, 8, 1, 15, -+ 0x1C0, 13, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", -+ sysapb_parents, 0x030, 0x034, 0x038, 16, 1, -+ 23, 0x1C0, 14, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", -+ arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, 31, -+ 0x1C0, 15), -+ /* CLK_CFG_4 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", -+ ap2cnn_host_parents, 0x040, 0x044, 0x048, 0, 1, 7, -+ 0x1C0, 16), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, -+ 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", -+ netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, 23, -+ 0x1C0, 18), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", -+ netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, -+ 0x1C0, 19), -+ /* CLK_CFG_5 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", -+ netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, -+ 0x1C0, 20), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", -+ sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, -+ 0x1C0, 21), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, -+ 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, -+ 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23), -+ /* CLK_CFG_6 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", -+ csw_f26m_parents, 0x060, 0x064, 0x068, 0, 1, -+ 7, 0x1C0, 24), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x060, -+ 0x064, 0x068, 8, 1, 15, 0x1C0, 25), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, -+ 0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, -+ 0x060, 0x064, 0x068, 24, 2, 31, 0x1C0, 27), -+ /* CLK_CFG_7 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", -+ a_tuner_parents, 0x070, 0x074, 0x078, 0, 2, 7, -+ 0x1C0, 28), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x070, -+ 0x074, 0x078, 8, 1, 15, 0x1C0, 29), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", -+ u2u3_sys_parents, 0x070, 0x074, 0x078, 16, 1, 23, -+ 0x1C0, 30), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", -+ u2u3_sys_parents, 0x070, 0x074, 0x078, 24, 1, 31, -+ 0x1C4, 0), -+ /* CLK_CFG_8 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", -+ usb_frmcnt_parents, 0x080, 0x084, 0x088, 0, 1, 7, -+ 0x1C4, 1), -+}; -+ -+static struct mtk_composite top_aud_divs[] = { -+ DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud", -+ 0x0420, 0, 0x0420, 8, 8), -+}; -+ -+static const struct mtk_clk_desc topck_desc = { -+ .factor_clks = top_divs, -+ .num_factor_clks = ARRAY_SIZE(top_divs), -+ .mux_clks = top_muxes, -+ .num_mux_clks = ARRAY_SIZE(top_muxes), -+ .composite_clks = top_aud_divs, -+ .num_composite_clks = ARRAY_SIZE(top_aud_divs), -+ .clk_lock = &mt7981_clk_lock, -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_topckgen[] = { -+ { .compatible = "mediatek,mt7981-topckgen", .data = &topck_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_topckgen_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-topckgen", -+ .of_match_table = of_match_clk_mt7981_topckgen, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_topckgen_drv); diff --git a/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch b/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch deleted file mode 100644 index ad4ecdf83f..0000000000 --- a/target/linux/mediatek/patches-6.6/241-v6.3-dt-bindings-clock-Add-compatibles-for-MT7981.patch +++ /dev/null @@ -1,75 +0,0 @@ -From cc4d9e0c77494fcf6bccbc57e23db0007cf681b7 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 03:33:46 +0000 -Subject: [PATCH] dt-bindings: clock: Add compatibles for MT7981 - -Add compatible string for MT7981 to existing bindings at - - mediatek,apmixedsys.yaml - - mediatek,topckgen.yaml - - mediatek,ethsys.txt - - mediatek,infracfg.yaml - - mediatek,sgmiisys.txt - -Signed-off-by: Jianhui Zhao -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/cc85ee470c781ff4013f6c21c92c0a21574b12b2.1674703830.git.daniel@makrotopia.org -Signed-off-by: Stephen Boyd ---- - .../devicetree/bindings/arm/mediatek/mediatek,ethsys.txt | 1 + - .../devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml | 1 + - .../devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt | 2 ++ - .../devicetree/bindings/clock/mediatek,apmixedsys.yaml | 1 + - Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml | 1 + - 5 files changed, 6 insertions(+) - ---- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt -+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt -@@ -10,6 +10,7 @@ Required Properties: - - "mediatek,mt7622-ethsys", "syscon" - - "mediatek,mt7623-ethsys", "mediatek,mt2701-ethsys", "syscon" - - "mediatek,mt7629-ethsys", "syscon" -+ - "mediatek,mt7981-ethsys", "syscon" - - "mediatek,mt7986-ethsys", "syscon" - - #clock-cells: Must be 1 - - #reset-cells: Must be 1 ---- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml -+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.yaml -@@ -28,6 +28,7 @@ properties: - - mediatek,mt6797-infracfg - - mediatek,mt7622-infracfg - - mediatek,mt7629-infracfg -+ - mediatek,mt7981-infracfg - - mediatek,mt7986-infracfg - - mediatek,mt8135-infracfg - - mediatek,mt8167-infracfg ---- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt -+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt -@@ -8,6 +8,8 @@ Required Properties: - - compatible: Should be: - - "mediatek,mt7622-sgmiisys", "syscon" - - "mediatek,mt7629-sgmiisys", "syscon" -+ - "mediatek,mt7981-sgmiisys_0", "syscon" -+ - "mediatek,mt7981-sgmiisys_1", "syscon" - - "mediatek,mt7986-sgmiisys_0", "syscon" - - "mediatek,mt7986-sgmiisys_1", "syscon" - - #clock-cells: Must be 1 ---- a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml -+++ b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml -@@ -20,6 +20,7 @@ properties: - - enum: - - mediatek,mt6797-apmixedsys - - mediatek,mt7622-apmixedsys -+ - mediatek,mt7981-apmixedsys - - mediatek,mt7986-apmixedsys - - mediatek,mt8135-apmixedsys - - mediatek,mt8173-apmixedsys ---- a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml -+++ b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml -@@ -35,6 +35,7 @@ properties: - - mediatek,mt6779-topckgen - - mediatek,mt6795-topckgen - - mediatek,mt7629-topckgen -+ - mediatek,mt7981-topckgen - - mediatek,mt7986-topckgen - - mediatek,mt8167-topckgen - - mediatek,mt8183-topckgen diff --git a/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch b/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch deleted file mode 100644 index 48d3d4e90c..0000000000 --- a/target/linux/mediatek/patches-6.6/242-v6.4-dt-bindings-arm-mediatek-sgmiisys-Convert-to-DT-sche.patch +++ /dev/null @@ -1,107 +0,0 @@ -From d4f08a703565abf47baa5a77d05365cf4598d55c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:56:52 +0000 -Subject: [PATCH 1/2] dt-bindings: arm: mediatek: sgmiisys: Convert to DT - schema - -Convert mediatek,sgmiiisys bindings to DT schema format. -Add maintainer Matthias Brugger, no maintainers were listed in the -original documentation. -As this node is also referenced by the Ethernet controller and used -as SGMII PCS add this fact to the description. -Move the file to Documentation/devicetree/bindings/net/pcs/ which seems -more appropriate given that the great majority of registers are related -to SGMII PCS functionality and only one register represents clock bits. - -Reviewed-by: Rob Herring -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - .../arm/mediatek/mediatek,sgmiisys.txt | 27 ---------- - .../bindings/net/pcs/mediatek,sgmiisys.yaml | 49 +++++++++++++++++++ - 2 files changed, 49 insertions(+), 27 deletions(-) - delete mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt - create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml - ---- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt -+++ /dev/null -@@ -1,27 +0,0 @@ --MediaTek SGMIISYS controller --============================ -- --The MediaTek SGMIISYS controller provides various clocks to the system. -- --Required Properties: -- --- compatible: Should be: -- - "mediatek,mt7622-sgmiisys", "syscon" -- - "mediatek,mt7629-sgmiisys", "syscon" -- - "mediatek,mt7981-sgmiisys_0", "syscon" -- - "mediatek,mt7981-sgmiisys_1", "syscon" -- - "mediatek,mt7986-sgmiisys_0", "syscon" -- - "mediatek,mt7986-sgmiisys_1", "syscon" --- #clock-cells: Must be 1 -- --The SGMIISYS controller uses the common clk binding from --Documentation/devicetree/bindings/clock/clock-bindings.txt --The available clocks are defined in dt-bindings/clock/mt*-clk.h. -- --Example: -- --sgmiisys: sgmiisys@1b128000 { -- compatible = "mediatek,mt7622-sgmiisys", "syscon"; -- reg = <0 0x1b128000 0 0x1000>; -- #clock-cells = <1>; --}; ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml -@@ -0,0 +1,49 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/pcs/mediatek,sgmiisys.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MediaTek SGMIISYS Controller -+ -+maintainers: -+ - Matthias Brugger -+ -+description: -+ The MediaTek SGMIISYS controller provides a SGMII PCS and some clocks -+ to the ethernet subsystem to which it is attached. -+ -+properties: -+ compatible: -+ items: -+ - enum: -+ - mediatek,mt7622-sgmiisys -+ - mediatek,mt7629-sgmiisys -+ - mediatek,mt7986-sgmiisys_0 -+ - mediatek,mt7986-sgmiisys_1 -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+ '#clock-cells': -+ const: 1 -+ -+required: -+ - compatible -+ - reg -+ - '#clock-cells' -+ -+additionalProperties: false -+ -+examples: -+ - | -+ soc { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ sgmiisys: syscon@1b128000 { -+ compatible = "mediatek,mt7622-sgmiisys", "syscon"; -+ reg = <0 0x1b128000 0 0x1000>; -+ #clock-cells = <1>; -+ }; -+ }; diff --git a/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch b/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch deleted file mode 100644 index 62a64b9dd0..0000000000 --- a/target/linux/mediatek/patches-6.6/243-v6.4-dt-bindings-net-pcs-mediatek-sgmiisys-add-MT7981-SoC.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 4f7eb19c4f44078100659f6ba073b0cc7191bc91 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 19 Mar 2023 12:57:04 +0000 -Subject: [PATCH 2/2] dt-bindings: net: pcs: mediatek,sgmiisys: add MT7981 SoC - -Add mediatek,pnswap boolean property needed on many boards using the -MediaTek MT7981 SoC. - -Reviewed-by: Rob Herring -Signed-off-by: Daniel Golle -Signed-off-by: Jakub Kicinski ---- - .../devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml -+++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml -@@ -19,6 +19,8 @@ properties: - - enum: - - mediatek,mt7622-sgmiisys - - mediatek,mt7629-sgmiisys -+ - mediatek,mt7981-sgmiisys_0 -+ - mediatek,mt7981-sgmiisys_1 - - mediatek,mt7986-sgmiisys_0 - - mediatek,mt7986-sgmiisys_1 - - const: syscon -@@ -29,6 +31,10 @@ properties: - '#clock-cells': - const: 1 - -+ mediatek,pnswap: -+ description: Invert polarity of the SGMII data lanes -+ type: boolean -+ - required: - - compatible - - reg diff --git a/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch deleted file mode 100644 index 5e3afd856f..0000000000 --- a/target/linux/mediatek/patches-6.6/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 24e961b93d292d0dd6380213d22a071a99ea787d Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Tue, 25 Oct 2022 15:29:53 +0200 -Subject: [PATCH 1/6] mmc: mediatek: add support for MT7986 SoC - -Adding mt7986 own characteristics and of_device_id to have support -of MT7986 SoC. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221025132953.81286-7-linux@fw-web.de -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -552,6 +552,19 @@ static const struct mtk_mmc_compatible m - .support_64g = false, - }; - -+static const struct mtk_mmc_compatible mt7986_compat = { -+ .clk_div_bits = 12, -+ .recheck_sdio_irq = true, -+ .hs400_tune = false, -+ .pad_tune_reg = MSDC_PAD_TUNE0, -+ .async_fifo = true, -+ .data_tune = true, -+ .busy_check = true, -+ .stop_clk_fix = true, -+ .enhance_rx = true, -+ .support_64g = true, -+}; -+ - static const struct mtk_mmc_compatible mt8135_compat = { - .clk_div_bits = 8, - .recheck_sdio_irq = true, -@@ -609,6 +622,7 @@ static const struct of_device_id msdc_of - { .compatible = "mediatek,mt6795-mmc", .data = &mt6795_compat}, - { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, - { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, -+ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, - { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, - { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat}, diff --git a/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch b/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch deleted file mode 100644 index db2802bd0f..0000000000 --- a/target/linux/mediatek/patches-6.6/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 7b438d0377fbd520b475a68bdd9de1692393f22d Mon Sep 17 00:00:00 2001 -From: Mengqi Zhang -Date: Sun, 6 Nov 2022 11:39:24 +0800 -Subject: [PATCH 2/6] mmc: mtk-sd: add Inline Crypto Engine clock control - -Add crypto clock control and ungate it before CQHCI init. - -Signed-off-by: Mengqi Zhang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106033924.9854-2-mengqi.zhang@mediatek.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -452,6 +452,7 @@ struct msdc_host { - struct clk *bus_clk; /* bus clock which used to access register */ - struct clk *src_clk_cg; /* msdc source clock control gate */ - struct clk *sys_clk_cg; /* msdc subsys clock control gate */ -+ struct clk *crypto_clk; /* msdc crypto clock control gate */ - struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; - u32 mclk; /* mmc subsystem clock frequency */ - u32 src_clk_freq; /* source clock frequency */ -@@ -840,6 +841,7 @@ static void msdc_set_busy_timeout(struct - static void msdc_gate_clock(struct msdc_host *host) - { - clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); -+ clk_disable_unprepare(host->crypto_clk); - clk_disable_unprepare(host->src_clk_cg); - clk_disable_unprepare(host->src_clk); - clk_disable_unprepare(host->bus_clk); -@@ -855,6 +857,7 @@ static int msdc_ungate_clock(struct msdc - clk_prepare_enable(host->bus_clk); - clk_prepare_enable(host->src_clk); - clk_prepare_enable(host->src_clk_cg); -+ clk_prepare_enable(host->crypto_clk); - ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); - if (ret) { - dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); -@@ -2670,6 +2673,15 @@ static int msdc_drv_probe(struct platfor - goto host_free; - } - -+ /* only eMMC has crypto property */ -+ if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) { -+ host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto"); -+ if (IS_ERR(host->crypto_clk)) -+ host->crypto_clk = NULL; -+ else -+ mmc->caps2 |= MMC_CAP2_CRYPTO; -+ } -+ - host->irq = platform_get_irq(pdev, 0); - if (host->irq < 0) { - ret = host->irq; diff --git a/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch b/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch deleted file mode 100644 index 921d249f8c..0000000000 --- a/target/linux/mediatek/patches-6.6/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4b323f02b6e8df1b04292635ef829e7f723bf50e Mon Sep 17 00:00:00 2001 -From: Yu Zhe -Date: Thu, 10 Nov 2022 15:28:19 +0800 -Subject: [PATCH 3/6] mmc: mtk-sd: fix two spelling mistakes in comment - -spelling mistake fix : "alreay" -> "already" - "checksume" -> "checksum" - -Signed-off-by: Yu Zhe -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221110072819.11530-1-yuzhe@nfschina.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -750,7 +750,7 @@ static inline void msdc_dma_setup(struct - else - bd[j].bd_info &= ~BDMA_DESC_EOL; - -- /* checksume need to clear first */ -+ /* checksum need to clear first */ - bd[j].bd_info &= ~BDMA_DESC_CHECKSUM; - bd[j].bd_info |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8; - } -@@ -1229,7 +1229,7 @@ static bool msdc_cmd_done(struct msdc_ho - !host->hs400_tuning)) - /* - * should not clear fifo/interrupt as the tune data -- * may have alreay come when cmd19/cmd21 gets response -+ * may have already come when cmd19/cmd21 gets response - * CRC error. - */ - msdc_reset_hw(host); diff --git a/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch b/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch deleted file mode 100644 index 8e2151e16b..0000000000 --- a/target/linux/mediatek/patches-6.6/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b98e7e8daf0ebab9dcc36812378a71e1be0b5089 Mon Sep 17 00:00:00 2001 -From: ChanWoo Lee -Date: Thu, 24 Nov 2022 17:00:31 +0900 -Subject: [PATCH 4/6] mmc: Avoid open coding by using mmc_op_tuning() - -Replace code with the already defined function. No functional changes. - -Signed-off-by: ChanWoo Lee -Reviewed-by: Adrian Hunter -Link: https://lore.kernel.org/r/20221124080031.14690-1-cw9316.lee@samsung.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -1224,9 +1224,7 @@ static bool msdc_cmd_done(struct msdc_ho - - if (!sbc_error && !(events & MSDC_INT_CMDRDY)) { - if (events & MSDC_INT_CMDTMO || -- (cmd->opcode != MMC_SEND_TUNING_BLOCK && -- cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && -- !host->hs400_tuning)) -+ (!mmc_op_tuning(cmd->opcode) && !host->hs400_tuning)) - /* - * should not clear fifo/interrupt as the tune data - * may have already come when cmd19/cmd21 gets response -@@ -1320,9 +1318,7 @@ static void msdc_cmd_next(struct msdc_ho - { - if ((cmd->error && - !(cmd->error == -EILSEQ && -- (cmd->opcode == MMC_SEND_TUNING_BLOCK || -- cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200 || -- host->hs400_tuning))) || -+ (mmc_op_tuning(cmd->opcode) || host->hs400_tuning))) || - (mrq->sbc && mrq->sbc->error)) - msdc_request_done(host, mrq); - else if (cmd == mrq->sbc) diff --git a/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch b/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch deleted file mode 100644 index 615a1a1d71..0000000000 --- a/target/linux/mediatek/patches-6.6/405-v6.2-mt7986-trng-add-rng-support.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f1da27b7c4191f78ed81d3dabf64c769f896296c Mon Sep 17 00:00:00 2001 -From: "Mingming.Su" -Date: Sat, 8 Oct 2022 18:45:53 +0200 -Subject: [PATCH] hwrng: mtk - add mt7986 support - -1. Add trng compatible name for MT7986 -2. Fix mtk_rng_wait_ready() function - -Signed-off-by: Mingming.Su -Signed-off-by: Frank Wunderlich -Signed-off-by: Herbert Xu ---- - drivers/char/hw_random/mtk-rng.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/char/hw_random/mtk-rng.c -+++ b/drivers/char/hw_random/mtk-rng.c -@@ -22,7 +22,7 @@ - #define RNG_AUTOSUSPEND_TIMEOUT 100 - - #define USEC_POLL 2 --#define TIMEOUT_POLL 20 -+#define TIMEOUT_POLL 60 - - #define RNG_CTRL 0x00 - #define RNG_EN BIT(0) -@@ -77,7 +77,7 @@ static bool mtk_rng_wait_ready(struct hw - readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready, - ready & RNG_READY, USEC_POLL, - TIMEOUT_POLL); -- return !!ready; -+ return !!(ready & RNG_READY); - } - - static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) -@@ -179,6 +179,7 @@ static const struct dev_pm_ops mtk_rng_p - #endif /* CONFIG_PM */ - - static const struct of_device_id mtk_rng_match[] = { -+ { .compatible = "mediatek,mt7986-rng" }, - { .compatible = "mediatek,mt7623-rng" }, - {}, - }; diff --git a/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch deleted file mode 100644 index 0bbf9ac773..0000000000 --- a/target/linux/mediatek/patches-6.6/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ /dev/null @@ -1,1204 +0,0 @@ -From 98c485eaf509bc0e2a85f9b58d17cd501f274c4e Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 11 Jun 2023 00:48:10 +0100 -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. -Despite the similar design the driver doesn't share any code with the -existing mediatek-ge.c. -Add support for such PHYs by introducing a new driver with basic -support for MediaTek SoCs MT7981 and MT7988 built-in 1GE PHYs. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 9 + - drivers/net/phy/Kconfig | 12 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-ge-soc.c | 1116 +++++++++++++++++++++++++++++ - drivers/net/phy/mediatek-ge.c | 3 +- - 5 files changed, 1140 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/phy/mediatek-ge-soc.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -12938,6 +12938,15 @@ F: drivers/net/pcs/pcs-mtk-usxgmii.c - F: include/linux/pcs/pcs-mtk-lynxi.h - F: include/linux/pcs/pcs-mtk-usxgmii.h - -+MEDIATEK ETHERNET PHY DRIVERS -+M: Daniel Golle -+M: Qingfang Deng -+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 - M: Qii Wang - L: linux-i2c@vger.kernel.org ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -314,6 +314,18 @@ config MEDIATEK_GE_PHY - help - Supports the MediaTek Gigabit Ethernet PHYs. - -+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. -+ -+ Include support for built-in Ethernet PHYs which are present in -+ the MT7981 and MT7988 SoCs. These PHYs need calibration data -+ present in the SoCs efuse and will dynamically calibrate VCM -+ (common-mode voltage) during startup. -+ - config MICREL_PHY - tristate "Micrel PHYs" - depends on PTP_1588_CLOCK_OPTIONAL ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -80,6 +80,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 ---- /dev/null -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -0,0 +1,1116 @@ -+// 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 -+ -+#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 -+}; -+ -+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 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 = mt798x_phy_calibration, -+ .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 = mt798x_phy_calibration, -+ .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); ---- a/drivers/net/phy/mediatek-ge.c -+++ b/drivers/net/phy/mediatek-ge.c -@@ -136,7 +136,8 @@ static struct phy_driver mtk_gephy_drive - module_phy_driver(mtk_gephy_driver); - - 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) }, - { } - }; - diff --git a/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch b/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch deleted file mode 100644 index 286ce96a7d..0000000000 --- a/target/linux/mediatek/patches-6.6/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch +++ /dev/null @@ -1,524 +0,0 @@ -From c66937b0f8dbb4c6c043663c702b1053fb47fab2 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 14 Aug 2023 02:58:14 +0100 -Subject: [PATCH] net: phy: mediatek-ge-soc: support PHY LEDs - -Implement netdev trigger and primitive bliking offloading as well as -simple set_brigthness function for both PHY LEDs of the in-SoC PHYs -found in MT7981 and MT7988. - -For MT7988, read boottrap register and apply LED polarities accordingly -to get uniform behavior from all LEDs on MT7988. -This requires syscon phandle 'mediatek,pio' present in parenting MDIO bus -which should point to the syscon holding the boottrap register. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/dc324d48c00cd7350f3a506eaa785324cae97372.1691977904.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek-ge-soc.c | 435 +++++++++++++++++++++++++++++- - 1 file changed, 426 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -1,11 +1,14 @@ - // SPDX-License-Identifier: GPL-2.0+ - #include -+#include -+#include - #include - #include - #include - #include - #include - #include -+#include - - #define MTK_GPHY_ID_MT7981 0x03a29461 - #define MTK_GPHY_ID_MT7988 0x03a29481 -@@ -208,9 +211,42 @@ - #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_LED1_ON_CTRL 0x26 -+#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) -+#define MTK_PHY_LED_ON_LINK1000 BIT(0) -+#define MTK_PHY_LED_ON_LINK100 BIT(1) -+#define MTK_PHY_LED_ON_LINK10 BIT(2) -+#define MTK_PHY_LED_ON_LINKDOWN BIT(3) -+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ -+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ -+#define MTK_PHY_LED_ON_FORCE_ON BIT(6) -+#define MTK_PHY_LED_ON_POLARITY BIT(14) -+#define MTK_PHY_LED_ON_ENABLE BIT(15) -+ -+#define MTK_PHY_LED0_BLINK_CTRL 0x25 -+#define MTK_PHY_LED1_BLINK_CTRL 0x27 -+#define MTK_PHY_LED_BLINK_1000TX BIT(0) -+#define MTK_PHY_LED_BLINK_1000RX BIT(1) -+#define MTK_PHY_LED_BLINK_100TX BIT(2) -+#define MTK_PHY_LED_BLINK_100RX BIT(3) -+#define MTK_PHY_LED_BLINK_10TX BIT(4) -+#define MTK_PHY_LED_BLINK_10RX BIT(5) -+#define MTK_PHY_LED_BLINK_COLLISION BIT(6) -+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) -+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) -+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) -+ -+#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) -+ - #define MTK_PHY_RG_BG_RASEL 0x115 - #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) - -+/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */ -+#define RG_GPIO_MISC_TPBANK0 0x6f0 -+#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8) -+ - /* 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)) -@@ -238,13 +274,6 @@ enum { - PAIR_D, - }; - --enum { -- GPHY_PORT0, -- GPHY_PORT1, -- GPHY_PORT2, -- GPHY_PORT3, --}; -- - enum calibration_mode { - EFUSE_K, - SW_K -@@ -263,6 +292,19 @@ enum CAL_MODE { - SW_M - }; - -+#define MTK_PHY_LED_STATE_FORCE_ON 0 -+#define MTK_PHY_LED_STATE_FORCE_BLINK 1 -+#define MTK_PHY_LED_STATE_NETDEV 2 -+ -+struct mtk_socphy_priv { -+ unsigned long led_state; -+}; -+ -+struct mtk_socphy_shared { -+ u32 boottrap; -+ struct mtk_socphy_priv priv[4]; -+}; -+ - static int mtk_socphy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -@@ -1073,6 +1115,371 @@ static int mt798x_phy_config_init(struct - return mt798x_phy_calibration(phydev); - } - -+static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -+ bool on) -+{ -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (on) -+ changed = !test_and_set_bit(bit_on, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_on, &priv->led_state); -+ -+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_MASK, -+ on ? MTK_PHY_LED_ON_FORCE_ON : 0); -+ else -+ return 0; -+} -+ -+static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, -+ bool blinking) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (blinking) -+ changed = !test_and_set_bit(bit_blink, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_blink, &priv->led_state); -+ -+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL, -+ blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -+ else -+ return 0; -+} -+ -+static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ bool blinking = false; -+ int err = 0; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { -+ blinking = true; -+ *delay_on = 50; -+ *delay_off = 50; -+ } -+ -+ err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); -+ if (err) -+ return err; -+ -+ return mt798x_phy_hw_led_on_set(phydev, index, false); -+} -+ -+static int mt798x_phy_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int err; -+ -+ err = mt798x_phy_hw_led_blink_set(phydev, index, false); -+ if (err) -+ return err; -+ -+ return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); -+} -+ -+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | -+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) | -+ BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)); -+ -+static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ if (index > 1) -+ return -EINVAL; -+ -+ /* All combinations of the supported triggers are allowed */ -+ if (rules & ~supported_triggers) -+ return -EOPNOTSUPP; -+ -+ return 0; -+}; -+ -+static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ int on, blink; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); -+ -+ if (on < 0) -+ return -EIO; -+ -+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL); -+ if (blink < 0) -+ return -EIO; -+ -+ if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | -+ MTK_PHY_LED_ON_LINK10)) || -+ (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | -+ MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX | -+ MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ if (on & MTK_PHY_LED_ON_FORCE_ON) -+ set_bit(bit_on, &priv->led_state); -+ else -+ clear_bit(bit_on, &priv->led_state); -+ -+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) -+ set_bit(bit_blink, &priv->led_state); -+ else -+ clear_bit(bit_blink, &priv->led_state); -+ -+ if (!rules) -+ return 0; -+ -+ if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10)) -+ *rules |= BIT(TRIGGER_NETDEV_LINK); -+ -+ if (on & MTK_PHY_LED_ON_LINK10) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_10); -+ -+ if (on & MTK_PHY_LED_ON_LINK100) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_100); -+ -+ if (on & MTK_PHY_LED_ON_LINK1000) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -+ -+ if (on & MTK_PHY_LED_ON_FDX) -+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); -+ -+ if (on & MTK_PHY_LED_ON_HDX) -+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); -+ -+ if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX)) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)) -+ *rules |= BIT(TRIGGER_NETDEV_TX); -+ -+ return 0; -+}; -+ -+static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ u16 on = 0, blink = 0; -+ int ret; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) -+ on |= MTK_PHY_LED_ON_FDX; -+ -+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) -+ on |= MTK_PHY_LED_ON_HDX; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK10; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK100; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK1000; -+ -+ if (rules & BIT(TRIGGER_NETDEV_RX)) { -+ blink |= MTK_PHY_LED_BLINK_10RX | -+ MTK_PHY_LED_BLINK_100RX | -+ MTK_PHY_LED_BLINK_1000RX; -+ } -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) { -+ blink |= MTK_PHY_LED_BLINK_10TX | -+ MTK_PHY_LED_BLINK_100TX | -+ MTK_PHY_LED_BLINK_1000TX; -+ } -+ -+ if (blink || on) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : -+ MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_FDX | -+ MTK_PHY_LED_ON_HDX | -+ MTK_PHY_LED_ON_LINK10 | -+ MTK_PHY_LED_ON_LINK100 | -+ MTK_PHY_LED_ON_LINK1000, -+ on); -+ -+ if (ret) -+ return ret; -+ -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, blink); -+}; -+ -+static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) -+{ -+ struct mtk_socphy_shared *priv = phydev->shared->priv; -+ u32 polarities; -+ -+ if (led_num == 0) -+ polarities = ~(priv->boottrap); -+ else -+ polarities = MTK_PHY_LED1_DEFAULT_POLARITIES; -+ -+ if (polarities & BIT(phydev->mdio.addr)) -+ return true; -+ -+ return false; -+} -+ -+static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev) -+{ -+ struct pinctrl *pinctrl; -+ int index; -+ -+ /* Setup LED polarity according to bootstrap use of LED pins */ -+ for (index = 0; index < 2; ++index) -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_POLARITY, -+ mt7988_phy_led_get_polarity(phydev, index) ? -+ MTK_PHY_LED_ON_POLARITY : 0); -+ -+ /* Only now setup pinctrl to avoid bogus blinking */ -+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); -+ if (IS_ERR(pinctrl)) -+ dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n"); -+ -+ return 0; -+} -+ -+static int mt7988_phy_probe_shared(struct phy_device *phydev) -+{ -+ struct device_node *np = dev_of_node(&phydev->mdio.bus->dev); -+ struct mtk_socphy_shared *shared = phydev->shared->priv; -+ struct regmap *regmap; -+ u32 reg; -+ int ret; -+ -+ /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B, -+ * LED_C and LED_D respectively. At the same time those pins are used to -+ * bootstrap configuration of the reference clock source (LED_A), -+ * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). -+ * In practise this is done using a LED and a resistor pulling the pin -+ * either to GND or to VIO. -+ * The detected value at boot time is accessible at run-time using the -+ * TPBANK0 register located in the gpio base of the pinctrl, in order -+ * to read it here it needs to be referenced by a phandle called -+ * 'mediatek,pio' in the MDIO bus hosting the PHY. -+ * The 4 bits in TPBANK0 are kept as package shared data and are used to -+ * set LED polarity for each of the LED0. -+ */ -+ regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio"); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®); -+ if (ret) -+ return ret; -+ -+ shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); -+ -+ return 0; -+} -+ -+static void mt798x_phy_leds_state_init(struct phy_device *phydev) -+{ -+ int i; -+ -+ for (i = 0; i < 2; ++i) -+ mt798x_phy_led_hw_control_get(phydev, i, NULL); -+} -+ -+static int mt7988_phy_probe(struct phy_device *phydev) -+{ -+ struct mtk_socphy_shared *shared; -+ struct mtk_socphy_priv *priv; -+ int err; -+ -+ if (phydev->mdio.addr > 3) -+ return -EINVAL; -+ -+ err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, -+ sizeof(struct mtk_socphy_shared)); -+ if (err) -+ return err; -+ -+ if (phy_package_probe_once(phydev)) { -+ err = mt7988_phy_probe_shared(phydev); -+ if (err) -+ return err; -+ } -+ -+ shared = phydev->shared->priv; -+ priv = &shared->priv[phydev->mdio.addr]; -+ -+ phydev->priv = priv; -+ -+ mt798x_phy_leds_state_init(phydev); -+ -+ err = mt7988_phy_fix_leds_polarities(phydev); -+ if (err) -+ return err; -+ -+ return mt798x_phy_calibration(phydev); -+} -+ -+static int mt7981_phy_probe(struct phy_device *phydev) -+{ -+ struct mtk_socphy_priv *priv; -+ -+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv), -+ GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ mt798x_phy_leds_state_init(phydev); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ - static struct phy_driver mtk_socphy_driver[] = { - { - PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), -@@ -1080,11 +1487,16 @@ static struct phy_driver mtk_socphy_driv - .config_init = mt798x_phy_config_init, - .config_intr = genphy_no_config_intr, - .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt798x_phy_calibration, -+ .probe = mt7981_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, - .read_page = mtk_socphy_read_page, - .write_page = mtk_socphy_write_page, -+ .led_blink_set = mt798x_phy_led_blink_set, -+ .led_brightness_set = mt798x_phy_led_brightness_set, -+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -+ .led_hw_control_set = mt798x_phy_led_hw_control_set, -+ .led_hw_control_get = mt798x_phy_led_hw_control_get, - }, - { - PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), -@@ -1092,11 +1504,16 @@ static struct phy_driver mtk_socphy_driv - .config_init = mt798x_phy_config_init, - .config_intr = genphy_no_config_intr, - .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt798x_phy_calibration, -+ .probe = mt7988_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, - .read_page = mtk_socphy_read_page, - .write_page = mtk_socphy_write_page, -+ .led_blink_set = mt798x_phy_led_blink_set, -+ .led_brightness_set = mt798x_phy_led_brightness_set, -+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -+ .led_hw_control_set = mt798x_phy_led_hw_control_set, -+ .led_hw_control_get = mt798x_phy_led_hw_control_get, - }, - }; - diff --git a/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch b/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch deleted file mode 100644 index 0c73d520b4..0000000000 --- a/target/linux/mediatek/patches-6.6/804-v6.2-pwm-add-mt7986-support.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/pwm/pwm-mediatek.c -+++ b/drivers/pwm/pwm-mediatek.c -@@ -329,6 +329,12 @@ static const struct pwm_mediatek_of_data - .has_ck_26m_sel = true, - }; - -+static const struct pwm_mediatek_of_data mt7986_pwm_data = { -+ .num_pwms = 2, -+ .pwm45_fixup = false, -+ .has_ck_26m_sel = true, -+}; -+ - static const struct pwm_mediatek_of_data mt8516_pwm_data = { - .num_pwms = 5, - .pwm45_fixup = false, -@@ -342,6 +348,7 @@ static const struct of_device_id pwm_med - { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, - { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, - { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, -+ { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, - { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, - { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data }, - { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, diff --git a/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch b/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch deleted file mode 100644 index f130fdbc56..0000000000 --- a/target/linux/mediatek/patches-6.6/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch +++ /dev/null @@ -1,129 +0,0 @@ -From fae82621ac33e2a4a96220c56e90d1ec6237d394 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:01:12 +0100 -Subject: [PATCH] pinctrl: mediatek: extend pinctrl-moore to support new bias - functions - -Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -introduced SoC specify 'pull_type' attribute to mtk_pinconf_bias_set_combo -and mtk_pinconf_bias_get_combo, and make the functions able to support -almost all Mediatek SoCs that use pinctrl-mtk-common-v2.c. - -This patch enables pinctrl_moore to support these functions. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106080114.7426-6-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-moore.c | 49 ++++++++++++++++++++---- - 1 file changed, 42 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-moore.c -+++ b/drivers/pinctrl/mediatek/pinctrl-moore.c -@@ -8,6 +8,7 @@ - * - */ - -+#include - #include - #include "pinctrl-moore.h" - -@@ -105,7 +106,7 @@ static int mtk_pinconf_get(struct pinctr - { - struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); - u32 param = pinconf_to_config_param(*config); -- int val, val2, err, reg, ret = 1; -+ int val, val2, err, pullup, reg, ret = 1; - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -@@ -114,7 +115,13 @@ static int mtk_pinconf_get(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE) -+ return -EINVAL; -+ } else if (hw->soc->bias_disable_get) { - err = hw->soc->bias_disable_get(hw, desc, &ret); - if (err) - return err; -@@ -123,7 +130,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (!pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 1, &ret); - if (err) - return err; -@@ -132,7 +147,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 0, &ret); - if (err) - return err; -@@ -235,7 +258,11 @@ static int mtk_pinconf_set(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_disable_set) { - err = hw->soc->bias_disable_set(hw, desc); - if (err) - return err; -@@ -244,7 +271,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 1, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 1); - if (err) - return err; -@@ -253,7 +284,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 0); - if (err) - return err; diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch b/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch deleted file mode 100644 index 694b73a2b1..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From f167da186acf90847e1a6d3716e253825a6218ec Mon Sep 17 00:00:00 2001 -From: Randy Dunlap -Date: Thu, 12 Jan 2023 22:44:49 -0800 -Subject: [PATCH 01/42] thermal/drivers/mtk_thermal: Fix kernel-doc function - name - -Use the correct function name in a kernel-doc comment to prevent -a warning: - -drivers/thermal/mtk_thermal.c:562: warning: expecting prototype for raw_to_mcelsius(). Prototype was for raw_to_mcelsius_v1() instead - -Signed-off-by: Randy Dunlap -Cc: "Rafael J. Wysocki" -Cc: Daniel Lezcano -Cc: Amit Kucheria -Cc: Zhang Rui -Cc: Matthias Brugger -Cc: linux-pm@vger.kernel.org -Cc: linux-arm-kernel@lists.infradead.org -Cc: linux-mediatek@lists.infradead.org -Link: https://lore.kernel.org/r/20230113064449.15061-1-rdunlap@infradead.org -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mtk_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -550,7 +550,7 @@ static const struct mtk_thermal_data mt8 - }; - - /** -- * raw_to_mcelsius - convert a raw ADC value to mcelsius -+ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius - * @mt: The thermal controller - * @sensno: sensor number - * @raw: raw ADC value diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch b/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch deleted file mode 100644 index aaed9d7e90..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 255509232417ee71fd606cb957d44cf6544f0c43 Mon Sep 17 00:00:00 2001 -From: ye xingchen -Date: Wed, 18 Jan 2023 16:37:47 +0800 -Subject: [PATCH 02/42] thermal/drivers/mtk_thermal: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: ye xingchen -Link: https://lore.kernel.org/r/202301181637472073620@zte.com.cn -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mtk_thermal.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -990,7 +990,6 @@ static int mtk_thermal_probe(struct plat - int ret, i, ctrl_id; - struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; - struct mtk_thermal *mt; -- struct resource *res; - u64 auxadc_phys_base, apmixed_phys_base; - struct thermal_zone_device *tzdev; - void __iomem *apmixed_base, *auxadc_base; -@@ -1009,8 +1008,7 @@ static int mtk_thermal_probe(struct plat - if (IS_ERR(mt->clk_auxadc)) - return PTR_ERR(mt->clk_auxadc); - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- mt->thermal_base = devm_ioremap_resource(&pdev->dev, res); -+ mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(mt->thermal_base)) - return PTR_ERR(mt->thermal_base); - diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch deleted file mode 100644 index 215b0fd7de..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch +++ /dev/null @@ -1,60 +0,0 @@ -From ca86dbd309ba03bef38ae91f037e2030bb671ab7 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 18 Jan 2023 15:40:39 +0000 -Subject: [PATCH 03/42] thermal/drivers/mtk: Use function pointer for - raw_to_mcelsius - -Instead of having if-else logic selecting either raw_to_mcelsius_v1 or -raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function -pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the -probe function. - -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Golle -Reviewed-by: Matthias Brugger -Link: https://lore.kernel.org/r/69c17529e8418da3eec703dde31e1b01e5b0f7e8.1674055882.git.daniel@makrotopia.org -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mtk_thermal.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -292,6 +292,8 @@ struct mtk_thermal { - - const struct mtk_thermal_data *conf; - struct mtk_thermal_bank banks[MAX_NUM_ZONES]; -+ -+ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); - }; - - /* MT8183 thermal sensor data */ -@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature( - for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { - raw = readl(mt->thermal_base + conf->msr[i]); - -- if (mt->conf->version == MTK_THERMAL_V1) { -- temp = raw_to_mcelsius_v1( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } else { -- temp = raw_to_mcelsius_v2( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } -+ temp = mt->raw_to_mcelsius( -+ mt, conf->bank_data[bank->id].sensors[i], raw); -+ - - /* - * The first read of a sensor often contains very high bogus -@@ -1073,6 +1071,11 @@ static int mtk_thermal_probe(struct plat - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - -+ if (mt->conf->version == MTK_THERMAL_V1) -+ mt->raw_to_mcelsius = raw_to_mcelsius_v1; -+ else -+ mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) - mtk_thermal_init_bank(mt, i, apmixed_phys_base, diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch b/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch deleted file mode 100644 index ef2006775a..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch +++ /dev/null @@ -1,236 +0,0 @@ -From aec1d89dccc7cba04fdb3e52dfda328f3302ba17 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 18 Jan 2023 15:40:58 +0000 -Subject: [PATCH 04/42] thermal/drivers/mtk: Add support for MT7986 and MT7981 - -Add support for V3 generation thermal found in MT7986 and MT7981 SoCs. -Brings code to assign values from efuse as well as new function to -convert raw temperature to millidegree celsius, as found in MediaTek's -SDK sources (but cleaned up and de-duplicated) - -[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b - -Signed-off-by: Daniel Golle -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/2d341fc45266217249586eb4bd3be3ac4ca83a12.1674055882.git.daniel@makrotopia.org -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mtk_thermal.c | 128 ++++++++++++++++++++++++++++++++-- - 1 file changed, 124 insertions(+), 4 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -150,6 +150,20 @@ - #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) - #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) - -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros can be used for MT7981 and MT7986. -+ */ -+#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) -+#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) -+#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) -+#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) -+#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) -+#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) -+#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) -+#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) -+ - enum { - VTS1, - VTS2, -@@ -163,6 +177,7 @@ enum { - enum mtk_thermal_version { - MTK_THERMAL_V1 = 1, - MTK_THERMAL_V2, -+ MTK_THERMAL_V3, - }; - - /* MT2701 thermal sensors */ -@@ -245,6 +260,27 @@ enum mtk_thermal_version { - /* The calibration coefficient of sensor */ - #define MT8183_CALIBRATION 153 - -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT7986_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT7986 */ -+#define MT7986_NUM_SENSORS 1 -+ -+/* The number of banks in the MT7986 */ -+#define MT7986_NUM_ZONES 1 -+ -+/* The number of sensing points per bank */ -+#define MT7986_NUM_SENSORS_PER_ZONE 1 -+ -+/* MT7986 thermal sensors */ -+#define MT7986_TS1 0 -+ -+/* The number of controller in the MT7986 */ -+#define MT7986_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT7986_CALIBRATION 165 -+ - struct mtk_thermal; - - struct thermal_bank_cfg { -@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762 - static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; - static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; - -+/* MT7986 thermal sensor data */ -+static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; -+static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; -+static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; -+static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; -+static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; -+static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; -+ - /* - * The MT8173 thermal controller has four banks. Each bank can read up to - * four temperature sensors simultaneously. The MT8173 has a total of 5 -@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8 - .version = MTK_THERMAL_V1, - }; - -+/* -+ * MT7986 uses AUXADC Channel 11 for raw data access. -+ */ -+static const struct mtk_thermal_data mt7986_thermal_data = { -+ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT7986_NUM_ZONES, -+ .num_sensors = MT7986_NUM_SENSORS, -+ .vts_index = mt7986_vts_index, -+ .cali_val = MT7986_CALIBRATION, -+ .num_controller = MT7986_NUM_CONTROLLER, -+ .controller_offset = mt7986_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 1, -+ .sensors = mt7986_bank_data, -+ }, -+ }, -+ .msr = mt7986_msr, -+ .adcpnp = mt7986_adcpnp, -+ .sensor_mux_values = mt7986_mux_values, -+ .version = MTK_THERMAL_V3, -+}; -+ - /** - * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius - * @mt: The thermal controller -@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk - return (format_2 - tmp) * 100; - } - -+static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 tmp; -+ -+ if (raw == 0) -+ return 0; -+ -+ raw &= 0xfff; -+ tmp = 100000 * 15 / 16 * 10000; -+ tmp /= 4096 - 512 + mt->adc_ge; -+ tmp /= 1490; -+ tmp *= raw - mt->vts[sensno] - 2900; -+ -+ return mt->degc_cali * 500 - tmp; -+} -+ - /** - * mtk_thermal_get_bank - get bank - * @bank: The bank -@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2( - return 0; - } - -+static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) -+{ -+ if (!CALIB_BUF1_VALID_V3(buf[1])) -+ return -EINVAL; -+ -+ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); -+ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); -+ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); -+ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); -+ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); -+ -+ if (CALIB_BUF1_ID_V3(buf[1]) == 0) -+ mt->o_slope = 0; -+ -+ return 0; -+} -+ - static int mtk_thermal_get_calibration_data(struct device *dev, - struct mtk_thermal *mt) - { -@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d - - /* Start with default values */ - mt->adc_ge = 512; -+ mt->adc_oe = 512; - for (i = 0; i < mt->conf->num_sensors; i++) - mt->vts[i] = 260; - mt->degc_cali = 40; -@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d - goto out; - } - -- if (mt->conf->version == MTK_THERMAL_V1) -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: - ret = mtk_thermal_extract_efuse_v1(mt, buf); -- else -+ break; -+ case MTK_THERMAL_V2: - ret = mtk_thermal_extract_efuse_v2(mt, buf); -+ break; -+ case MTK_THERMAL_V3: -+ ret = mtk_thermal_extract_efuse_v3(mt, buf); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } - - if (ret) { - dev_info(dev, "Device not calibrated, using default calibration values\n"); -@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the - .data = (void *)&mt7622_thermal_data, - }, - { -+ .compatible = "mediatek,mt7986-thermal", -+ .data = (void *)&mt7986_thermal_data, -+ }, -+ { - .compatible = "mediatek,mt8183-thermal", - .data = (void *)&mt8183_thermal_data, - }, { -@@ -1066,15 +1184,17 @@ static int mtk_thermal_probe(struct plat - goto err_disable_clk_auxadc; - } - -- if (mt->conf->version == MTK_THERMAL_V2) { -+ if (mt->conf->version != MTK_THERMAL_V1) { - mtk_thermal_turn_on_buffer(apmixed_base); - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - - if (mt->conf->version == MTK_THERMAL_V1) - mt->raw_to_mcelsius = raw_to_mcelsius_v1; -- else -+ else if (mt->conf->version == MTK_THERMAL_V2) - mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ else -+ mt->raw_to_mcelsius = raw_to_mcelsius_v3; - - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch b/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch deleted file mode 100644 index e102a338cd..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch +++ /dev/null @@ -1,2602 +0,0 @@ -From 5e3aac197a74914ccec2732a89c29d960730d28f Mon Sep 17 00:00:00 2001 -From: Balsam CHIHI -Date: Thu, 9 Feb 2023 11:56:23 +0100 -Subject: [PATCH 05/42] thermal/drivers/mediatek: Relocate driver to mediatek - folder - -Add MediaTek proprietary folder to upstream more thermal zone and cooler -drivers, relocate the original thermal controller driver to it, and rename it -as "auxadc_thermal.c" to show its purpose more clearly. - -Signed-off-by: Balsam CHIHI -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230209105628.50294-2-bchihi@baylibre.com -Signed-off-by: Daniel Lezcano -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/Kconfig | 14 ++++--------- - drivers/thermal/Makefile | 2 +- - drivers/thermal/mediatek/Kconfig | 21 +++++++++++++++++++ - drivers/thermal/mediatek/Makefile | 1 + - .../auxadc_thermal.c} | 2 +- - 5 files changed, 28 insertions(+), 12 deletions(-) - create mode 100644 drivers/thermal/mediatek/Kconfig - create mode 100644 drivers/thermal/mediatek/Makefile - rename drivers/thermal/{mtk_thermal.c => mediatek/auxadc_thermal.c} (99%) - ---- a/drivers/thermal/Kconfig -+++ b/drivers/thermal/Kconfig -@@ -412,16 +412,10 @@ config DA9062_THERMAL - zone. - Compatible with the DA9062 and DA9061 PMICs. - --config MTK_THERMAL -- tristate "Temperature sensor driver for mediatek SoCs" -- depends on ARCH_MEDIATEK || COMPILE_TEST -- depends on HAS_IOMEM -- depends on NVMEM || NVMEM=n -- depends on RESET_CONTROLLER -- default y -- help -- Enable this option if you want to have support for thermal management -- controller present in Mediatek SoCs -+menu "Mediatek thermal drivers" -+depends on ARCH_MEDIATEK || COMPILE_TEST -+source "drivers/thermal/mediatek/Kconfig" -+endmenu - - config AMLOGIC_THERMAL - tristate "Amlogic Thermal Support" ---- a/drivers/thermal/Makefile -+++ b/drivers/thermal/Makefile -@@ -55,7 +55,7 @@ obj-y += st/ - obj-y += qcom/ - obj-y += tegra/ - obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o --obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o -+obj-y += mediatek/ - obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o - obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o - obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o ---- /dev/null -+++ b/drivers/thermal/mediatek/Kconfig -@@ -0,0 +1,21 @@ -+config MTK_THERMAL -+ tristate "MediaTek thermal drivers" -+ depends on THERMAL_OF -+ help -+ This is the option for MediaTek thermal software solutions. -+ Please enable corresponding options to get temperature -+ information from thermal sensors or turn on throttle -+ mechaisms for thermal mitigation. -+ -+if MTK_THERMAL -+ -+config MTK_SOC_THERMAL -+ tristate "AUXADC temperature sensor driver for MediaTek SoCs" -+ depends on HAS_IOMEM -+ help -+ Enable this option if you want to get SoC temperature -+ information for MediaTek platforms. -+ This driver configures thermal controllers to collect -+ temperature via AUXADC interface. -+ -+endif ---- /dev/null -+++ b/drivers/thermal/mediatek/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o ---- a/drivers/thermal/mtk_thermal.c -+++ /dev/null -@@ -1,1254 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-only --/* -- * Copyright (c) 2015 MediaTek Inc. -- * Author: Hanyi Wu -- * Sascha Hauer -- * Dawei Chien -- * Louis Yu -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "thermal_hwmon.h" -- --/* AUXADC Registers */ --#define AUXADC_CON1_SET_V 0x008 --#define AUXADC_CON1_CLR_V 0x00c --#define AUXADC_CON2_V 0x010 --#define AUXADC_DATA(channel) (0x14 + (channel) * 4) -- --#define APMIXED_SYS_TS_CON1 0x604 -- --/* Thermal Controller Registers */ --#define TEMP_MONCTL0 0x000 --#define TEMP_MONCTL1 0x004 --#define TEMP_MONCTL2 0x008 --#define TEMP_MONIDET0 0x014 --#define TEMP_MONIDET1 0x018 --#define TEMP_MSRCTL0 0x038 --#define TEMP_MSRCTL1 0x03c --#define TEMP_AHBPOLL 0x040 --#define TEMP_AHBTO 0x044 --#define TEMP_ADCPNP0 0x048 --#define TEMP_ADCPNP1 0x04c --#define TEMP_ADCPNP2 0x050 --#define TEMP_ADCPNP3 0x0b4 -- --#define TEMP_ADCMUX 0x054 --#define TEMP_ADCEN 0x060 --#define TEMP_PNPMUXADDR 0x064 --#define TEMP_ADCMUXADDR 0x068 --#define TEMP_ADCENADDR 0x074 --#define TEMP_ADCVALIDADDR 0x078 --#define TEMP_ADCVOLTADDR 0x07c --#define TEMP_RDCTRL 0x080 --#define TEMP_ADCVALIDMASK 0x084 --#define TEMP_ADCVOLTAGESHIFT 0x088 --#define TEMP_ADCWRITECTRL 0x08c --#define TEMP_MSR0 0x090 --#define TEMP_MSR1 0x094 --#define TEMP_MSR2 0x098 --#define TEMP_MSR3 0x0B8 -- --#define TEMP_SPARE0 0x0f0 -- --#define TEMP_ADCPNP0_1 0x148 --#define TEMP_ADCPNP1_1 0x14c --#define TEMP_ADCPNP2_1 0x150 --#define TEMP_MSR0_1 0x190 --#define TEMP_MSR1_1 0x194 --#define TEMP_MSR2_1 0x198 --#define TEMP_ADCPNP3_1 0x1b4 --#define TEMP_MSR3_1 0x1B8 -- --#define PTPCORESEL 0x400 -- --#define TEMP_MONCTL1_PERIOD_UNIT(x) ((x) & 0x3ff) -- --#define TEMP_MONCTL2_FILTER_INTERVAL(x) (((x) & 0x3ff) << 16) --#define TEMP_MONCTL2_SENSOR_INTERVAL(x) ((x) & 0x3ff) -- --#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x) (x) -- --#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE BIT(0) --#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE BIT(1) -- --#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5) --#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit) -- --/* MT8173 thermal sensors */ --#define MT8173_TS1 0 --#define MT8173_TS2 1 --#define MT8173_TS3 2 --#define MT8173_TS4 3 --#define MT8173_TSABB 4 -- --/* AUXADC channel 11 is used for the temperature sensors */ --#define MT8173_TEMP_AUXADC_CHANNEL 11 -- --/* The total number of temperature sensors in the MT8173 */ --#define MT8173_NUM_SENSORS 5 -- --/* The number of banks in the MT8173 */ --#define MT8173_NUM_ZONES 4 -- --/* The number of sensing points per bank */ --#define MT8173_NUM_SENSORS_PER_ZONE 4 -- --/* The number of controller in the MT8173 */ --#define MT8173_NUM_CONTROLLER 1 -- --/* The calibration coefficient of sensor */ --#define MT8173_CALIBRATION 165 -- --/* -- * Layout of the fuses providing the calibration data -- * These macros could be used for MT8183, MT8173, MT2701, and MT2712. -- * MT8183 has 6 sensors and needs 6 VTS calibration data. -- * MT8173 has 5 sensors and needs 5 VTS calibration data. -- * MT2701 has 3 sensors and needs 3 VTS calibration data. -- * MT2712 has 4 sensors and needs 4 VTS calibration data. -- */ --#define CALIB_BUF0_VALID_V1 BIT(0) --#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) --#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) --#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) --#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) --#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) --#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) --#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) --#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) --#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) --#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) --#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) -- --/* -- * Layout of the fuses providing the calibration data -- * These macros could be used for MT7622. -- */ --#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) --#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) --#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) --#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) --#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) --#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) --#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) --#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) --#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) -- --/* -- * Layout of the fuses providing the calibration data -- * These macros can be used for MT7981 and MT7986. -- */ --#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) --#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) --#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) --#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) --#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) --#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) --#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) --#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) --#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) -- --enum { -- VTS1, -- VTS2, -- VTS3, -- VTS4, -- VTS5, -- VTSABB, -- MAX_NUM_VTS, --}; -- --enum mtk_thermal_version { -- MTK_THERMAL_V1 = 1, -- MTK_THERMAL_V2, -- MTK_THERMAL_V3, --}; -- --/* MT2701 thermal sensors */ --#define MT2701_TS1 0 --#define MT2701_TS2 1 --#define MT2701_TSABB 2 -- --/* AUXADC channel 11 is used for the temperature sensors */ --#define MT2701_TEMP_AUXADC_CHANNEL 11 -- --/* The total number of temperature sensors in the MT2701 */ --#define MT2701_NUM_SENSORS 3 -- --/* The number of sensing points per bank */ --#define MT2701_NUM_SENSORS_PER_ZONE 3 -- --/* The number of controller in the MT2701 */ --#define MT2701_NUM_CONTROLLER 1 -- --/* The calibration coefficient of sensor */ --#define MT2701_CALIBRATION 165 -- --/* MT2712 thermal sensors */ --#define MT2712_TS1 0 --#define MT2712_TS2 1 --#define MT2712_TS3 2 --#define MT2712_TS4 3 -- --/* AUXADC channel 11 is used for the temperature sensors */ --#define MT2712_TEMP_AUXADC_CHANNEL 11 -- --/* The total number of temperature sensors in the MT2712 */ --#define MT2712_NUM_SENSORS 4 -- --/* The number of sensing points per bank */ --#define MT2712_NUM_SENSORS_PER_ZONE 4 -- --/* The number of controller in the MT2712 */ --#define MT2712_NUM_CONTROLLER 1 -- --/* The calibration coefficient of sensor */ --#define MT2712_CALIBRATION 165 -- --#define MT7622_TEMP_AUXADC_CHANNEL 11 --#define MT7622_NUM_SENSORS 1 --#define MT7622_NUM_ZONES 1 --#define MT7622_NUM_SENSORS_PER_ZONE 1 --#define MT7622_TS1 0 --#define MT7622_NUM_CONTROLLER 1 -- --/* The maximum number of banks */ --#define MAX_NUM_ZONES 8 -- --/* The calibration coefficient of sensor */ --#define MT7622_CALIBRATION 165 -- --/* MT8183 thermal sensors */ --#define MT8183_TS1 0 --#define MT8183_TS2 1 --#define MT8183_TS3 2 --#define MT8183_TS4 3 --#define MT8183_TS5 4 --#define MT8183_TSABB 5 -- --/* AUXADC channel is used for the temperature sensors */ --#define MT8183_TEMP_AUXADC_CHANNEL 11 -- --/* The total number of temperature sensors in the MT8183 */ --#define MT8183_NUM_SENSORS 6 -- --/* The number of banks in the MT8183 */ --#define MT8183_NUM_ZONES 1 -- --/* The number of sensing points per bank */ --#define MT8183_NUM_SENSORS_PER_ZONE 6 -- --/* The number of controller in the MT8183 */ --#define MT8183_NUM_CONTROLLER 2 -- --/* The calibration coefficient of sensor */ --#define MT8183_CALIBRATION 153 -- --/* AUXADC channel 11 is used for the temperature sensors */ --#define MT7986_TEMP_AUXADC_CHANNEL 11 -- --/* The total number of temperature sensors in the MT7986 */ --#define MT7986_NUM_SENSORS 1 -- --/* The number of banks in the MT7986 */ --#define MT7986_NUM_ZONES 1 -- --/* The number of sensing points per bank */ --#define MT7986_NUM_SENSORS_PER_ZONE 1 -- --/* MT7986 thermal sensors */ --#define MT7986_TS1 0 -- --/* The number of controller in the MT7986 */ --#define MT7986_NUM_CONTROLLER 1 -- --/* The calibration coefficient of sensor */ --#define MT7986_CALIBRATION 165 -- --struct mtk_thermal; -- --struct thermal_bank_cfg { -- unsigned int num_sensors; -- const int *sensors; --}; -- --struct mtk_thermal_bank { -- struct mtk_thermal *mt; -- int id; --}; -- --struct mtk_thermal_data { -- s32 num_banks; -- s32 num_sensors; -- s32 auxadc_channel; -- const int *vts_index; -- const int *sensor_mux_values; -- const int *msr; -- const int *adcpnp; -- const int cali_val; -- const int num_controller; -- const int *controller_offset; -- bool need_switch_bank; -- struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; -- enum mtk_thermal_version version; --}; -- --struct mtk_thermal { -- struct device *dev; -- void __iomem *thermal_base; -- -- struct clk *clk_peri_therm; -- struct clk *clk_auxadc; -- /* lock: for getting and putting banks */ -- struct mutex lock; -- -- /* Calibration values */ -- s32 adc_ge; -- s32 adc_oe; -- s32 degc_cali; -- s32 o_slope; -- s32 o_slope_sign; -- s32 vts[MAX_NUM_VTS]; -- -- const struct mtk_thermal_data *conf; -- struct mtk_thermal_bank banks[MAX_NUM_ZONES]; -- -- int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); --}; -- --/* MT8183 thermal sensor data */ --static const int mt8183_bank_data[MT8183_NUM_SENSORS] = { -- MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB --}; -- --static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = { -- TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1 --}; -- --static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = { -- TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1, -- TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1 --}; -- --static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 }; --static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100}; -- --static const int mt8183_vts_index[MT8183_NUM_SENSORS] = { -- VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB --}; -- --/* MT8173 thermal sensor data */ --static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { -- { MT8173_TS2, MT8173_TS3 }, -- { MT8173_TS2, MT8173_TS4 }, -- { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, -- { MT8173_TS2 }, --}; -- --static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { -- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 --}; -- --static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { -- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 --}; -- --static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; --static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, }; -- --static const int mt8173_vts_index[MT8173_NUM_SENSORS] = { -- VTS1, VTS2, VTS3, VTS4, VTSABB --}; -- --/* MT2701 thermal sensor data */ --static const int mt2701_bank_data[MT2701_NUM_SENSORS] = { -- MT2701_TS1, MT2701_TS2, MT2701_TSABB --}; -- --static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { -- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 --}; -- --static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { -- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 --}; -- --static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; --static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, }; -- --static const int mt2701_vts_index[MT2701_NUM_SENSORS] = { -- VTS1, VTS2, VTS3 --}; -- --/* MT2712 thermal sensor data */ --static const int mt2712_bank_data[MT2712_NUM_SENSORS] = { -- MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4 --}; -- --static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = { -- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 --}; -- --static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { -- TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 --}; -- --static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; --static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, }; -- --static const int mt2712_vts_index[MT2712_NUM_SENSORS] = { -- VTS1, VTS2, VTS3, VTS4 --}; -- --/* MT7622 thermal sensor data */ --static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; --static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; --static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; --static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; --static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; --static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; -- --/* MT7986 thermal sensor data */ --static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; --static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; --static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; --static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; --static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; --static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; -- --/* -- * The MT8173 thermal controller has four banks. Each bank can read up to -- * four temperature sensors simultaneously. The MT8173 has a total of 5 -- * temperature sensors. We use each bank to measure a certain area of the -- * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple -- * areas, hence is used in different banks. -- * -- * The thermal core only gets the maximum temperature of all banks, so -- * the bank concept wouldn't be necessary here. However, the SVS (Smart -- * Voltage Scaling) unit makes its decisions based on the same bank -- * data, and this indeed needs the temperatures of the individual banks -- * for making better decisions. -- */ --static const struct mtk_thermal_data mt8173_thermal_data = { -- .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL, -- .num_banks = MT8173_NUM_ZONES, -- .num_sensors = MT8173_NUM_SENSORS, -- .vts_index = mt8173_vts_index, -- .cali_val = MT8173_CALIBRATION, -- .num_controller = MT8173_NUM_CONTROLLER, -- .controller_offset = mt8173_tc_offset, -- .need_switch_bank = true, -- .bank_data = { -- { -- .num_sensors = 2, -- .sensors = mt8173_bank_data[0], -- }, { -- .num_sensors = 2, -- .sensors = mt8173_bank_data[1], -- }, { -- .num_sensors = 3, -- .sensors = mt8173_bank_data[2], -- }, { -- .num_sensors = 1, -- .sensors = mt8173_bank_data[3], -- }, -- }, -- .msr = mt8173_msr, -- .adcpnp = mt8173_adcpnp, -- .sensor_mux_values = mt8173_mux_values, -- .version = MTK_THERMAL_V1, --}; -- --/* -- * The MT2701 thermal controller has one bank, which can read up to -- * three temperature sensors simultaneously. The MT2701 has a total of 3 -- * temperature sensors. -- * -- * The thermal core only gets the maximum temperature of this one bank, -- * so the bank concept wouldn't be necessary here. However, the SVS (Smart -- * Voltage Scaling) unit makes its decisions based on the same bank -- * data. -- */ --static const struct mtk_thermal_data mt2701_thermal_data = { -- .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL, -- .num_banks = 1, -- .num_sensors = MT2701_NUM_SENSORS, -- .vts_index = mt2701_vts_index, -- .cali_val = MT2701_CALIBRATION, -- .num_controller = MT2701_NUM_CONTROLLER, -- .controller_offset = mt2701_tc_offset, -- .need_switch_bank = true, -- .bank_data = { -- { -- .num_sensors = 3, -- .sensors = mt2701_bank_data, -- }, -- }, -- .msr = mt2701_msr, -- .adcpnp = mt2701_adcpnp, -- .sensor_mux_values = mt2701_mux_values, -- .version = MTK_THERMAL_V1, --}; -- --/* -- * The MT2712 thermal controller has one bank, which can read up to -- * four temperature sensors simultaneously. The MT2712 has a total of 4 -- * temperature sensors. -- * -- * The thermal core only gets the maximum temperature of this one bank, -- * so the bank concept wouldn't be necessary here. However, the SVS (Smart -- * Voltage Scaling) unit makes its decisions based on the same bank -- * data. -- */ --static const struct mtk_thermal_data mt2712_thermal_data = { -- .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL, -- .num_banks = 1, -- .num_sensors = MT2712_NUM_SENSORS, -- .vts_index = mt2712_vts_index, -- .cali_val = MT2712_CALIBRATION, -- .num_controller = MT2712_NUM_CONTROLLER, -- .controller_offset = mt2712_tc_offset, -- .need_switch_bank = true, -- .bank_data = { -- { -- .num_sensors = 4, -- .sensors = mt2712_bank_data, -- }, -- }, -- .msr = mt2712_msr, -- .adcpnp = mt2712_adcpnp, -- .sensor_mux_values = mt2712_mux_values, -- .version = MTK_THERMAL_V1, --}; -- --/* -- * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data -- * access. -- */ --static const struct mtk_thermal_data mt7622_thermal_data = { -- .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, -- .num_banks = MT7622_NUM_ZONES, -- .num_sensors = MT7622_NUM_SENSORS, -- .vts_index = mt7622_vts_index, -- .cali_val = MT7622_CALIBRATION, -- .num_controller = MT7622_NUM_CONTROLLER, -- .controller_offset = mt7622_tc_offset, -- .need_switch_bank = true, -- .bank_data = { -- { -- .num_sensors = 1, -- .sensors = mt7622_bank_data, -- }, -- }, -- .msr = mt7622_msr, -- .adcpnp = mt7622_adcpnp, -- .sensor_mux_values = mt7622_mux_values, -- .version = MTK_THERMAL_V2, --}; -- --/* -- * The MT8183 thermal controller has one bank for the current SW framework. -- * The MT8183 has a total of 6 temperature sensors. -- * There are two thermal controller to control the six sensor. -- * The first one bind 2 sensor, and the other bind 4 sensors. -- * The thermal core only gets the maximum temperature of all sensor, so -- * the bank concept wouldn't be necessary here. However, the SVS (Smart -- * Voltage Scaling) unit makes its decisions based on the same bank -- * data, and this indeed needs the temperatures of the individual banks -- * for making better decisions. -- */ --static const struct mtk_thermal_data mt8183_thermal_data = { -- .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL, -- .num_banks = MT8183_NUM_ZONES, -- .num_sensors = MT8183_NUM_SENSORS, -- .vts_index = mt8183_vts_index, -- .cali_val = MT8183_CALIBRATION, -- .num_controller = MT8183_NUM_CONTROLLER, -- .controller_offset = mt8183_tc_offset, -- .need_switch_bank = false, -- .bank_data = { -- { -- .num_sensors = 6, -- .sensors = mt8183_bank_data, -- }, -- }, -- -- .msr = mt8183_msr, -- .adcpnp = mt8183_adcpnp, -- .sensor_mux_values = mt8183_mux_values, -- .version = MTK_THERMAL_V1, --}; -- --/* -- * MT7986 uses AUXADC Channel 11 for raw data access. -- */ --static const struct mtk_thermal_data mt7986_thermal_data = { -- .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, -- .num_banks = MT7986_NUM_ZONES, -- .num_sensors = MT7986_NUM_SENSORS, -- .vts_index = mt7986_vts_index, -- .cali_val = MT7986_CALIBRATION, -- .num_controller = MT7986_NUM_CONTROLLER, -- .controller_offset = mt7986_tc_offset, -- .need_switch_bank = true, -- .bank_data = { -- { -- .num_sensors = 1, -- .sensors = mt7986_bank_data, -- }, -- }, -- .msr = mt7986_msr, -- .adcpnp = mt7986_adcpnp, -- .sensor_mux_values = mt7986_mux_values, -- .version = MTK_THERMAL_V3, --}; -- --/** -- * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius -- * @mt: The thermal controller -- * @sensno: sensor number -- * @raw: raw ADC value -- * -- * This converts the raw ADC value to mcelsius using the SoC specific -- * calibration constants -- */ --static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) --{ -- s32 tmp; -- -- raw &= 0xfff; -- -- tmp = 203450520 << 3; -- tmp /= mt->conf->cali_val + mt->o_slope; -- tmp /= 10000 + mt->adc_ge; -- tmp *= raw - mt->vts[sensno] - 3350; -- tmp >>= 3; -- -- return mt->degc_cali * 500 - tmp; --} -- --static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) --{ -- s32 format_1; -- s32 format_2; -- s32 g_oe; -- s32 g_gain; -- s32 g_x_roomt; -- s32 tmp; -- -- if (raw == 0) -- return 0; -- -- raw &= 0xfff; -- g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); -- g_oe = mt->adc_oe - 512; -- format_1 = mt->vts[VTS2] + 3105 - g_oe; -- format_2 = (mt->degc_cali * 10) >> 1; -- g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; -- -- tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; -- tmp = tmp * 10 * 100 / 11; -- -- if (mt->o_slope_sign == 0) -- tmp = tmp / (165 - mt->o_slope); -- else -- tmp = tmp / (165 + mt->o_slope); -- -- return (format_2 - tmp) * 100; --} -- --static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) --{ -- s32 tmp; -- -- if (raw == 0) -- return 0; -- -- raw &= 0xfff; -- tmp = 100000 * 15 / 16 * 10000; -- tmp /= 4096 - 512 + mt->adc_ge; -- tmp /= 1490; -- tmp *= raw - mt->vts[sensno] - 2900; -- -- return mt->degc_cali * 500 - tmp; --} -- --/** -- * mtk_thermal_get_bank - get bank -- * @bank: The bank -- * -- * The bank registers are banked, we have to select a bank in the -- * PTPCORESEL register to access it. -- */ --static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank) --{ -- struct mtk_thermal *mt = bank->mt; -- u32 val; -- -- if (mt->conf->need_switch_bank) { -- mutex_lock(&mt->lock); -- -- val = readl(mt->thermal_base + PTPCORESEL); -- val &= ~0xf; -- val |= bank->id; -- writel(val, mt->thermal_base + PTPCORESEL); -- } --} -- --/** -- * mtk_thermal_put_bank - release bank -- * @bank: The bank -- * -- * release a bank previously taken with mtk_thermal_get_bank, -- */ --static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank) --{ -- struct mtk_thermal *mt = bank->mt; -- -- if (mt->conf->need_switch_bank) -- mutex_unlock(&mt->lock); --} -- --/** -- * mtk_thermal_bank_temperature - get the temperature of a bank -- * @bank: The bank -- * -- * The temperature of a bank is considered the maximum temperature of -- * the sensors associated to the bank. -- */ --static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) --{ -- struct mtk_thermal *mt = bank->mt; -- const struct mtk_thermal_data *conf = mt->conf; -- int i, temp = INT_MIN, max = INT_MIN; -- u32 raw; -- -- for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { -- raw = readl(mt->thermal_base + conf->msr[i]); -- -- temp = mt->raw_to_mcelsius( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- -- -- /* -- * The first read of a sensor often contains very high bogus -- * temperature value. Filter these out so that the system does -- * not immediately shut down. -- */ -- if (temp > 200000) -- temp = 0; -- -- if (temp > max) -- max = temp; -- } -- -- return max; --} -- --static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) --{ -- struct mtk_thermal *mt = tz->devdata; -- int i; -- int tempmax = INT_MIN; -- -- for (i = 0; i < mt->conf->num_banks; i++) { -- struct mtk_thermal_bank *bank = &mt->banks[i]; -- -- mtk_thermal_get_bank(bank); -- -- tempmax = max(tempmax, mtk_thermal_bank_temperature(bank)); -- -- mtk_thermal_put_bank(bank); -- } -- -- *temperature = tempmax; -- -- return 0; --} -- --static const struct thermal_zone_device_ops mtk_thermal_ops = { -- .get_temp = mtk_read_temp, --}; -- --static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, -- u32 apmixed_phys_base, u32 auxadc_phys_base, -- int ctrl_id) --{ -- struct mtk_thermal_bank *bank = &mt->banks[num]; -- const struct mtk_thermal_data *conf = mt->conf; -- int i; -- -- int offset = mt->conf->controller_offset[ctrl_id]; -- void __iomem *controller_base = mt->thermal_base + offset; -- -- bank->id = num; -- bank->mt = mt; -- -- mtk_thermal_get_bank(bank); -- -- /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */ -- writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1); -- -- /* -- * filt interval is 1 * 46.540us = 46.54us, -- * sen interval is 429 * 46.540us = 19.96ms -- */ -- writel(TEMP_MONCTL2_FILTER_INTERVAL(1) | -- TEMP_MONCTL2_SENSOR_INTERVAL(429), -- controller_base + TEMP_MONCTL2); -- -- /* poll is set to 10u */ -- writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768), -- controller_base + TEMP_AHBPOLL); -- -- /* temperature sampling control, 1 sample */ -- writel(0x0, controller_base + TEMP_MSRCTL0); -- -- /* exceed this polling time, IRQ would be inserted */ -- writel(0xffffffff, controller_base + TEMP_AHBTO); -- -- /* number of interrupts per event, 1 is enough */ -- writel(0x0, controller_base + TEMP_MONIDET0); -- writel(0x0, controller_base + TEMP_MONIDET1); -- -- /* -- * The MT8173 thermal controller does not have its own ADC. Instead it -- * uses AHB bus accesses to control the AUXADC. To do this the thermal -- * controller has to be programmed with the physical addresses of the -- * AUXADC registers and with the various bit positions in the AUXADC. -- * Also the thermal controller controls a mux in the APMIXEDSYS register -- * space. -- */ -- -- /* -- * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) -- * automatically by hw -- */ -- writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX); -- -- /* AHB address for auxadc mux selection */ -- writel(auxadc_phys_base + AUXADC_CON1_CLR_V, -- controller_base + TEMP_ADCMUXADDR); -- -- if (mt->conf->version == MTK_THERMAL_V1) { -- /* AHB address for pnp sensor mux selection */ -- writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, -- controller_base + TEMP_PNPMUXADDR); -- } -- -- /* AHB value for auxadc enable */ -- writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); -- -- /* AHB address for auxadc enable (channel 0 immediate mode selected) */ -- writel(auxadc_phys_base + AUXADC_CON1_SET_V, -- controller_base + TEMP_ADCENADDR); -- -- /* AHB address for auxadc valid bit */ -- writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), -- controller_base + TEMP_ADCVALIDADDR); -- -- /* AHB address for auxadc voltage output */ -- writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), -- controller_base + TEMP_ADCVOLTADDR); -- -- /* read valid & voltage are at the same register */ -- writel(0x0, controller_base + TEMP_RDCTRL); -- -- /* indicate where the valid bit is */ -- writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12), -- controller_base + TEMP_ADCVALIDMASK); -- -- /* no shift */ -- writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT); -- -- /* enable auxadc mux write transaction */ -- writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE, -- controller_base + TEMP_ADCWRITECTRL); -- -- for (i = 0; i < conf->bank_data[num].num_sensors; i++) -- writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]], -- mt->thermal_base + conf->adcpnp[i]); -- -- writel((1 << conf->bank_data[num].num_sensors) - 1, -- controller_base + TEMP_MONCTL0); -- -- writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE | -- TEMP_ADCWRITECTRL_ADC_MUX_WRITE, -- controller_base + TEMP_ADCWRITECTRL); -- -- mtk_thermal_put_bank(bank); --} -- --static u64 of_get_phys_base(struct device_node *np) --{ -- u64 size64; -- const __be32 *regaddr_p; -- -- regaddr_p = of_get_address(np, 0, &size64, NULL); -- if (!regaddr_p) -- return OF_BAD_ADDR; -- -- return of_translate_address(np, regaddr_p); --} -- --static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) --{ -- int i; -- -- if (!(buf[0] & CALIB_BUF0_VALID_V1)) -- return -EINVAL; -- -- mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); -- -- for (i = 0; i < mt->conf->num_sensors; i++) { -- switch (mt->conf->vts_index[i]) { -- case VTS1: -- mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); -- break; -- case VTS2: -- mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); -- break; -- case VTS3: -- mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); -- break; -- case VTS4: -- mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); -- break; -- case VTS5: -- mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); -- break; -- case VTSABB: -- mt->vts[VTSABB] = -- CALIB_BUF2_VTS_TSABB_V1(buf[2]); -- break; -- default: -- break; -- } -- } -- -- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); -- if (CALIB_BUF1_ID_V1(buf[1]) & -- CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) -- mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); -- else -- mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); -- -- return 0; --} -- --static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) --{ -- if (!CALIB_BUF1_VALID_V2(buf[1])) -- return -EINVAL; -- -- mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); -- mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); -- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); -- mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); -- mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); -- mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); -- mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); -- mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); -- -- return 0; --} -- --static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) --{ -- if (!CALIB_BUF1_VALID_V3(buf[1])) -- return -EINVAL; -- -- mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); -- mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); -- mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); -- mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); -- mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); -- mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); -- mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); -- -- if (CALIB_BUF1_ID_V3(buf[1]) == 0) -- mt->o_slope = 0; -- -- return 0; --} -- --static int mtk_thermal_get_calibration_data(struct device *dev, -- struct mtk_thermal *mt) --{ -- struct nvmem_cell *cell; -- u32 *buf; -- size_t len; -- int i, ret = 0; -- -- /* Start with default values */ -- mt->adc_ge = 512; -- mt->adc_oe = 512; -- for (i = 0; i < mt->conf->num_sensors; i++) -- mt->vts[i] = 260; -- mt->degc_cali = 40; -- mt->o_slope = 0; -- -- cell = nvmem_cell_get(dev, "calibration-data"); -- if (IS_ERR(cell)) { -- if (PTR_ERR(cell) == -EPROBE_DEFER) -- return PTR_ERR(cell); -- return 0; -- } -- -- buf = (u32 *)nvmem_cell_read(cell, &len); -- -- nvmem_cell_put(cell); -- -- if (IS_ERR(buf)) -- return PTR_ERR(buf); -- -- if (len < 3 * sizeof(u32)) { -- dev_warn(dev, "invalid calibration data\n"); -- ret = -EINVAL; -- goto out; -- } -- -- switch (mt->conf->version) { -- case MTK_THERMAL_V1: -- ret = mtk_thermal_extract_efuse_v1(mt, buf); -- break; -- case MTK_THERMAL_V2: -- ret = mtk_thermal_extract_efuse_v2(mt, buf); -- break; -- case MTK_THERMAL_V3: -- ret = mtk_thermal_extract_efuse_v3(mt, buf); -- break; -- default: -- ret = -EINVAL; -- break; -- } -- -- if (ret) { -- dev_info(dev, "Device not calibrated, using default calibration values\n"); -- ret = 0; -- } -- --out: -- kfree(buf); -- -- return ret; --} -- --static const struct of_device_id mtk_thermal_of_match[] = { -- { -- .compatible = "mediatek,mt8173-thermal", -- .data = (void *)&mt8173_thermal_data, -- }, -- { -- .compatible = "mediatek,mt2701-thermal", -- .data = (void *)&mt2701_thermal_data, -- }, -- { -- .compatible = "mediatek,mt2712-thermal", -- .data = (void *)&mt2712_thermal_data, -- }, -- { -- .compatible = "mediatek,mt7622-thermal", -- .data = (void *)&mt7622_thermal_data, -- }, -- { -- .compatible = "mediatek,mt7986-thermal", -- .data = (void *)&mt7986_thermal_data, -- }, -- { -- .compatible = "mediatek,mt8183-thermal", -- .data = (void *)&mt8183_thermal_data, -- }, { -- }, --}; --MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); -- --static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) --{ -- int tmp; -- -- tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); -- tmp &= ~(0x37); -- tmp |= 0x1; -- writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); -- udelay(200); --} -- --static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, -- void __iomem *auxadc_base) --{ -- int tmp; -- -- writel(0x800, auxadc_base + AUXADC_CON1_SET_V); -- writel(0x1, mt->thermal_base + TEMP_MONCTL0); -- tmp = readl(mt->thermal_base + TEMP_MSRCTL1); -- writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); --} -- --static int mtk_thermal_probe(struct platform_device *pdev) --{ -- int ret, i, ctrl_id; -- struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; -- struct mtk_thermal *mt; -- u64 auxadc_phys_base, apmixed_phys_base; -- struct thermal_zone_device *tzdev; -- void __iomem *apmixed_base, *auxadc_base; -- -- mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); -- if (!mt) -- return -ENOMEM; -- -- mt->conf = of_device_get_match_data(&pdev->dev); -- -- mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); -- if (IS_ERR(mt->clk_peri_therm)) -- return PTR_ERR(mt->clk_peri_therm); -- -- mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); -- if (IS_ERR(mt->clk_auxadc)) -- return PTR_ERR(mt->clk_auxadc); -- -- mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); -- if (IS_ERR(mt->thermal_base)) -- return PTR_ERR(mt->thermal_base); -- -- ret = mtk_thermal_get_calibration_data(&pdev->dev, mt); -- if (ret) -- return ret; -- -- mutex_init(&mt->lock); -- -- mt->dev = &pdev->dev; -- -- auxadc = of_parse_phandle(np, "mediatek,auxadc", 0); -- if (!auxadc) { -- dev_err(&pdev->dev, "missing auxadc node\n"); -- return -ENODEV; -- } -- -- auxadc_base = of_iomap(auxadc, 0); -- auxadc_phys_base = of_get_phys_base(auxadc); -- -- of_node_put(auxadc); -- -- if (auxadc_phys_base == OF_BAD_ADDR) { -- dev_err(&pdev->dev, "Can't get auxadc phys address\n"); -- return -EINVAL; -- } -- -- apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0); -- if (!apmixedsys) { -- dev_err(&pdev->dev, "missing apmixedsys node\n"); -- return -ENODEV; -- } -- -- apmixed_base = of_iomap(apmixedsys, 0); -- apmixed_phys_base = of_get_phys_base(apmixedsys); -- -- of_node_put(apmixedsys); -- -- if (apmixed_phys_base == OF_BAD_ADDR) { -- dev_err(&pdev->dev, "Can't get auxadc phys address\n"); -- return -EINVAL; -- } -- -- ret = device_reset_optional(&pdev->dev); -- if (ret) -- return ret; -- -- ret = clk_prepare_enable(mt->clk_auxadc); -- if (ret) { -- dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); -- return ret; -- } -- -- ret = clk_prepare_enable(mt->clk_peri_therm); -- if (ret) { -- dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); -- goto err_disable_clk_auxadc; -- } -- -- if (mt->conf->version != MTK_THERMAL_V1) { -- mtk_thermal_turn_on_buffer(apmixed_base); -- mtk_thermal_release_periodic_ts(mt, auxadc_base); -- } -- -- if (mt->conf->version == MTK_THERMAL_V1) -- mt->raw_to_mcelsius = raw_to_mcelsius_v1; -- else if (mt->conf->version == MTK_THERMAL_V2) -- mt->raw_to_mcelsius = raw_to_mcelsius_v2; -- else -- mt->raw_to_mcelsius = raw_to_mcelsius_v3; -- -- for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) -- for (i = 0; i < mt->conf->num_banks; i++) -- mtk_thermal_init_bank(mt, i, apmixed_phys_base, -- auxadc_phys_base, ctrl_id); -- -- platform_set_drvdata(pdev, mt); -- -- tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, -- &mtk_thermal_ops); -- if (IS_ERR(tzdev)) { -- ret = PTR_ERR(tzdev); -- goto err_disable_clk_peri_therm; -- } -- -- ret = devm_thermal_add_hwmon_sysfs(tzdev); -- if (ret) -- dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); -- -- return 0; -- --err_disable_clk_peri_therm: -- clk_disable_unprepare(mt->clk_peri_therm); --err_disable_clk_auxadc: -- clk_disable_unprepare(mt->clk_auxadc); -- -- return ret; --} -- --static int mtk_thermal_remove(struct platform_device *pdev) --{ -- struct mtk_thermal *mt = platform_get_drvdata(pdev); -- -- clk_disable_unprepare(mt->clk_peri_therm); -- clk_disable_unprepare(mt->clk_auxadc); -- -- return 0; --} -- --static struct platform_driver mtk_thermal_driver = { -- .probe = mtk_thermal_probe, -- .remove = mtk_thermal_remove, -- .driver = { -- .name = "mtk-thermal", -- .of_match_table = mtk_thermal_of_match, -- }, --}; -- --module_platform_driver(mtk_thermal_driver); -- --MODULE_AUTHOR("Michael Kao "); --MODULE_AUTHOR("Louis Yu "); --MODULE_AUTHOR("Dawei Chien "); --MODULE_AUTHOR("Sascha Hauer "); --MODULE_AUTHOR("Hanyi Wu "); --MODULE_DESCRIPTION("Mediatek thermal driver"); --MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -0,0 +1,1254 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2015 MediaTek Inc. -+ * Author: Hanyi Wu -+ * Sascha Hauer -+ * Dawei Chien -+ * Louis Yu -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../thermal_hwmon.h" -+ -+/* AUXADC Registers */ -+#define AUXADC_CON1_SET_V 0x008 -+#define AUXADC_CON1_CLR_V 0x00c -+#define AUXADC_CON2_V 0x010 -+#define AUXADC_DATA(channel) (0x14 + (channel) * 4) -+ -+#define APMIXED_SYS_TS_CON1 0x604 -+ -+/* Thermal Controller Registers */ -+#define TEMP_MONCTL0 0x000 -+#define TEMP_MONCTL1 0x004 -+#define TEMP_MONCTL2 0x008 -+#define TEMP_MONIDET0 0x014 -+#define TEMP_MONIDET1 0x018 -+#define TEMP_MSRCTL0 0x038 -+#define TEMP_MSRCTL1 0x03c -+#define TEMP_AHBPOLL 0x040 -+#define TEMP_AHBTO 0x044 -+#define TEMP_ADCPNP0 0x048 -+#define TEMP_ADCPNP1 0x04c -+#define TEMP_ADCPNP2 0x050 -+#define TEMP_ADCPNP3 0x0b4 -+ -+#define TEMP_ADCMUX 0x054 -+#define TEMP_ADCEN 0x060 -+#define TEMP_PNPMUXADDR 0x064 -+#define TEMP_ADCMUXADDR 0x068 -+#define TEMP_ADCENADDR 0x074 -+#define TEMP_ADCVALIDADDR 0x078 -+#define TEMP_ADCVOLTADDR 0x07c -+#define TEMP_RDCTRL 0x080 -+#define TEMP_ADCVALIDMASK 0x084 -+#define TEMP_ADCVOLTAGESHIFT 0x088 -+#define TEMP_ADCWRITECTRL 0x08c -+#define TEMP_MSR0 0x090 -+#define TEMP_MSR1 0x094 -+#define TEMP_MSR2 0x098 -+#define TEMP_MSR3 0x0B8 -+ -+#define TEMP_SPARE0 0x0f0 -+ -+#define TEMP_ADCPNP0_1 0x148 -+#define TEMP_ADCPNP1_1 0x14c -+#define TEMP_ADCPNP2_1 0x150 -+#define TEMP_MSR0_1 0x190 -+#define TEMP_MSR1_1 0x194 -+#define TEMP_MSR2_1 0x198 -+#define TEMP_ADCPNP3_1 0x1b4 -+#define TEMP_MSR3_1 0x1B8 -+ -+#define PTPCORESEL 0x400 -+ -+#define TEMP_MONCTL1_PERIOD_UNIT(x) ((x) & 0x3ff) -+ -+#define TEMP_MONCTL2_FILTER_INTERVAL(x) (((x) & 0x3ff) << 16) -+#define TEMP_MONCTL2_SENSOR_INTERVAL(x) ((x) & 0x3ff) -+ -+#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x) (x) -+ -+#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE BIT(0) -+#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE BIT(1) -+ -+#define TEMP_ADCVALIDMASK_VALID_HIGH BIT(5) -+#define TEMP_ADCVALIDMASK_VALID_POS(bit) (bit) -+ -+/* MT8173 thermal sensors */ -+#define MT8173_TS1 0 -+#define MT8173_TS2 1 -+#define MT8173_TS3 2 -+#define MT8173_TS4 3 -+#define MT8173_TSABB 4 -+ -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT8173_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT8173 */ -+#define MT8173_NUM_SENSORS 5 -+ -+/* The number of banks in the MT8173 */ -+#define MT8173_NUM_ZONES 4 -+ -+/* The number of sensing points per bank */ -+#define MT8173_NUM_SENSORS_PER_ZONE 4 -+ -+/* The number of controller in the MT8173 */ -+#define MT8173_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT8173_CALIBRATION 165 -+ -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros could be used for MT8183, MT8173, MT2701, and MT2712. -+ * MT8183 has 6 sensors and needs 6 VTS calibration data. -+ * MT8173 has 5 sensors and needs 5 VTS calibration data. -+ * MT2701 has 3 sensors and needs 3 VTS calibration data. -+ * MT2712 has 4 sensors and needs 4 VTS calibration data. -+ */ -+#define CALIB_BUF0_VALID_V1 BIT(0) -+#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) -+#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) -+#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) -+#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) -+#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) -+#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) -+#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) -+#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) -+#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) -+ -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros could be used for MT7622. -+ */ -+#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) -+#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) -+#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) -+#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) -+#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) -+#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) -+#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) -+#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) -+ -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros can be used for MT7981 and MT7986. -+ */ -+#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) -+#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) -+#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) -+#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) -+#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) -+#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) -+#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) -+#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) -+ -+enum { -+ VTS1, -+ VTS2, -+ VTS3, -+ VTS4, -+ VTS5, -+ VTSABB, -+ MAX_NUM_VTS, -+}; -+ -+enum mtk_thermal_version { -+ MTK_THERMAL_V1 = 1, -+ MTK_THERMAL_V2, -+ MTK_THERMAL_V3, -+}; -+ -+/* MT2701 thermal sensors */ -+#define MT2701_TS1 0 -+#define MT2701_TS2 1 -+#define MT2701_TSABB 2 -+ -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT2701_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT2701 */ -+#define MT2701_NUM_SENSORS 3 -+ -+/* The number of sensing points per bank */ -+#define MT2701_NUM_SENSORS_PER_ZONE 3 -+ -+/* The number of controller in the MT2701 */ -+#define MT2701_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT2701_CALIBRATION 165 -+ -+/* MT2712 thermal sensors */ -+#define MT2712_TS1 0 -+#define MT2712_TS2 1 -+#define MT2712_TS3 2 -+#define MT2712_TS4 3 -+ -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT2712_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT2712 */ -+#define MT2712_NUM_SENSORS 4 -+ -+/* The number of sensing points per bank */ -+#define MT2712_NUM_SENSORS_PER_ZONE 4 -+ -+/* The number of controller in the MT2712 */ -+#define MT2712_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT2712_CALIBRATION 165 -+ -+#define MT7622_TEMP_AUXADC_CHANNEL 11 -+#define MT7622_NUM_SENSORS 1 -+#define MT7622_NUM_ZONES 1 -+#define MT7622_NUM_SENSORS_PER_ZONE 1 -+#define MT7622_TS1 0 -+#define MT7622_NUM_CONTROLLER 1 -+ -+/* The maximum number of banks */ -+#define MAX_NUM_ZONES 8 -+ -+/* The calibration coefficient of sensor */ -+#define MT7622_CALIBRATION 165 -+ -+/* MT8183 thermal sensors */ -+#define MT8183_TS1 0 -+#define MT8183_TS2 1 -+#define MT8183_TS3 2 -+#define MT8183_TS4 3 -+#define MT8183_TS5 4 -+#define MT8183_TSABB 5 -+ -+/* AUXADC channel is used for the temperature sensors */ -+#define MT8183_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT8183 */ -+#define MT8183_NUM_SENSORS 6 -+ -+/* The number of banks in the MT8183 */ -+#define MT8183_NUM_ZONES 1 -+ -+/* The number of sensing points per bank */ -+#define MT8183_NUM_SENSORS_PER_ZONE 6 -+ -+/* The number of controller in the MT8183 */ -+#define MT8183_NUM_CONTROLLER 2 -+ -+/* The calibration coefficient of sensor */ -+#define MT8183_CALIBRATION 153 -+ -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT7986_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT7986 */ -+#define MT7986_NUM_SENSORS 1 -+ -+/* The number of banks in the MT7986 */ -+#define MT7986_NUM_ZONES 1 -+ -+/* The number of sensing points per bank */ -+#define MT7986_NUM_SENSORS_PER_ZONE 1 -+ -+/* MT7986 thermal sensors */ -+#define MT7986_TS1 0 -+ -+/* The number of controller in the MT7986 */ -+#define MT7986_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT7986_CALIBRATION 165 -+ -+struct mtk_thermal; -+ -+struct thermal_bank_cfg { -+ unsigned int num_sensors; -+ const int *sensors; -+}; -+ -+struct mtk_thermal_bank { -+ struct mtk_thermal *mt; -+ int id; -+}; -+ -+struct mtk_thermal_data { -+ s32 num_banks; -+ s32 num_sensors; -+ s32 auxadc_channel; -+ const int *vts_index; -+ const int *sensor_mux_values; -+ const int *msr; -+ const int *adcpnp; -+ const int cali_val; -+ const int num_controller; -+ const int *controller_offset; -+ bool need_switch_bank; -+ struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; -+ enum mtk_thermal_version version; -+}; -+ -+struct mtk_thermal { -+ struct device *dev; -+ void __iomem *thermal_base; -+ -+ struct clk *clk_peri_therm; -+ struct clk *clk_auxadc; -+ /* lock: for getting and putting banks */ -+ struct mutex lock; -+ -+ /* Calibration values */ -+ s32 adc_ge; -+ s32 adc_oe; -+ s32 degc_cali; -+ s32 o_slope; -+ s32 o_slope_sign; -+ s32 vts[MAX_NUM_VTS]; -+ -+ const struct mtk_thermal_data *conf; -+ struct mtk_thermal_bank banks[MAX_NUM_ZONES]; -+ -+ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); -+}; -+ -+/* MT8183 thermal sensor data */ -+static const int mt8183_bank_data[MT8183_NUM_SENSORS] = { -+ MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB -+}; -+ -+static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = { -+ TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1 -+}; -+ -+static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = { -+ TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1, -+ TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1 -+}; -+ -+static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 }; -+static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100}; -+ -+static const int mt8183_vts_index[MT8183_NUM_SENSORS] = { -+ VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB -+}; -+ -+/* MT8173 thermal sensor data */ -+static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = { -+ { MT8173_TS2, MT8173_TS3 }, -+ { MT8173_TS2, MT8173_TS4 }, -+ { MT8173_TS1, MT8173_TS2, MT8173_TSABB }, -+ { MT8173_TS2 }, -+}; -+ -+static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = { -+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 -+}; -+ -+static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = { -+ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 -+}; -+ -+static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 }; -+static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, }; -+ -+static const int mt8173_vts_index[MT8173_NUM_SENSORS] = { -+ VTS1, VTS2, VTS3, VTS4, VTSABB -+}; -+ -+/* MT2701 thermal sensor data */ -+static const int mt2701_bank_data[MT2701_NUM_SENSORS] = { -+ MT2701_TS1, MT2701_TS2, MT2701_TSABB -+}; -+ -+static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = { -+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 -+}; -+ -+static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = { -+ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 -+}; -+ -+static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 }; -+static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, }; -+ -+static const int mt2701_vts_index[MT2701_NUM_SENSORS] = { -+ VTS1, VTS2, VTS3 -+}; -+ -+/* MT2712 thermal sensor data */ -+static const int mt2712_bank_data[MT2712_NUM_SENSORS] = { -+ MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4 -+}; -+ -+static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = { -+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3 -+}; -+ -+static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { -+ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3 -+}; -+ -+static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; -+static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, }; -+ -+static const int mt2712_vts_index[MT2712_NUM_SENSORS] = { -+ VTS1, VTS2, VTS3, VTS4 -+}; -+ -+/* MT7622 thermal sensor data */ -+static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; -+static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; -+static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; -+static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; -+static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; -+static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; -+ -+/* MT7986 thermal sensor data */ -+static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; -+static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; -+static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; -+static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; -+static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; -+static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; -+ -+/* -+ * The MT8173 thermal controller has four banks. Each bank can read up to -+ * four temperature sensors simultaneously. The MT8173 has a total of 5 -+ * temperature sensors. We use each bank to measure a certain area of the -+ * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple -+ * areas, hence is used in different banks. -+ * -+ * The thermal core only gets the maximum temperature of all banks, so -+ * the bank concept wouldn't be necessary here. However, the SVS (Smart -+ * Voltage Scaling) unit makes its decisions based on the same bank -+ * data, and this indeed needs the temperatures of the individual banks -+ * for making better decisions. -+ */ -+static const struct mtk_thermal_data mt8173_thermal_data = { -+ .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT8173_NUM_ZONES, -+ .num_sensors = MT8173_NUM_SENSORS, -+ .vts_index = mt8173_vts_index, -+ .cali_val = MT8173_CALIBRATION, -+ .num_controller = MT8173_NUM_CONTROLLER, -+ .controller_offset = mt8173_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 2, -+ .sensors = mt8173_bank_data[0], -+ }, { -+ .num_sensors = 2, -+ .sensors = mt8173_bank_data[1], -+ }, { -+ .num_sensors = 3, -+ .sensors = mt8173_bank_data[2], -+ }, { -+ .num_sensors = 1, -+ .sensors = mt8173_bank_data[3], -+ }, -+ }, -+ .msr = mt8173_msr, -+ .adcpnp = mt8173_adcpnp, -+ .sensor_mux_values = mt8173_mux_values, -+ .version = MTK_THERMAL_V1, -+}; -+ -+/* -+ * The MT2701 thermal controller has one bank, which can read up to -+ * three temperature sensors simultaneously. The MT2701 has a total of 3 -+ * temperature sensors. -+ * -+ * The thermal core only gets the maximum temperature of this one bank, -+ * so the bank concept wouldn't be necessary here. However, the SVS (Smart -+ * Voltage Scaling) unit makes its decisions based on the same bank -+ * data. -+ */ -+static const struct mtk_thermal_data mt2701_thermal_data = { -+ .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL, -+ .num_banks = 1, -+ .num_sensors = MT2701_NUM_SENSORS, -+ .vts_index = mt2701_vts_index, -+ .cali_val = MT2701_CALIBRATION, -+ .num_controller = MT2701_NUM_CONTROLLER, -+ .controller_offset = mt2701_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 3, -+ .sensors = mt2701_bank_data, -+ }, -+ }, -+ .msr = mt2701_msr, -+ .adcpnp = mt2701_adcpnp, -+ .sensor_mux_values = mt2701_mux_values, -+ .version = MTK_THERMAL_V1, -+}; -+ -+/* -+ * The MT2712 thermal controller has one bank, which can read up to -+ * four temperature sensors simultaneously. The MT2712 has a total of 4 -+ * temperature sensors. -+ * -+ * The thermal core only gets the maximum temperature of this one bank, -+ * so the bank concept wouldn't be necessary here. However, the SVS (Smart -+ * Voltage Scaling) unit makes its decisions based on the same bank -+ * data. -+ */ -+static const struct mtk_thermal_data mt2712_thermal_data = { -+ .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL, -+ .num_banks = 1, -+ .num_sensors = MT2712_NUM_SENSORS, -+ .vts_index = mt2712_vts_index, -+ .cali_val = MT2712_CALIBRATION, -+ .num_controller = MT2712_NUM_CONTROLLER, -+ .controller_offset = mt2712_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 4, -+ .sensors = mt2712_bank_data, -+ }, -+ }, -+ .msr = mt2712_msr, -+ .adcpnp = mt2712_adcpnp, -+ .sensor_mux_values = mt2712_mux_values, -+ .version = MTK_THERMAL_V1, -+}; -+ -+/* -+ * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data -+ * access. -+ */ -+static const struct mtk_thermal_data mt7622_thermal_data = { -+ .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT7622_NUM_ZONES, -+ .num_sensors = MT7622_NUM_SENSORS, -+ .vts_index = mt7622_vts_index, -+ .cali_val = MT7622_CALIBRATION, -+ .num_controller = MT7622_NUM_CONTROLLER, -+ .controller_offset = mt7622_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 1, -+ .sensors = mt7622_bank_data, -+ }, -+ }, -+ .msr = mt7622_msr, -+ .adcpnp = mt7622_adcpnp, -+ .sensor_mux_values = mt7622_mux_values, -+ .version = MTK_THERMAL_V2, -+}; -+ -+/* -+ * The MT8183 thermal controller has one bank for the current SW framework. -+ * The MT8183 has a total of 6 temperature sensors. -+ * There are two thermal controller to control the six sensor. -+ * The first one bind 2 sensor, and the other bind 4 sensors. -+ * The thermal core only gets the maximum temperature of all sensor, so -+ * the bank concept wouldn't be necessary here. However, the SVS (Smart -+ * Voltage Scaling) unit makes its decisions based on the same bank -+ * data, and this indeed needs the temperatures of the individual banks -+ * for making better decisions. -+ */ -+static const struct mtk_thermal_data mt8183_thermal_data = { -+ .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT8183_NUM_ZONES, -+ .num_sensors = MT8183_NUM_SENSORS, -+ .vts_index = mt8183_vts_index, -+ .cali_val = MT8183_CALIBRATION, -+ .num_controller = MT8183_NUM_CONTROLLER, -+ .controller_offset = mt8183_tc_offset, -+ .need_switch_bank = false, -+ .bank_data = { -+ { -+ .num_sensors = 6, -+ .sensors = mt8183_bank_data, -+ }, -+ }, -+ -+ .msr = mt8183_msr, -+ .adcpnp = mt8183_adcpnp, -+ .sensor_mux_values = mt8183_mux_values, -+ .version = MTK_THERMAL_V1, -+}; -+ -+/* -+ * MT7986 uses AUXADC Channel 11 for raw data access. -+ */ -+static const struct mtk_thermal_data mt7986_thermal_data = { -+ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT7986_NUM_ZONES, -+ .num_sensors = MT7986_NUM_SENSORS, -+ .vts_index = mt7986_vts_index, -+ .cali_val = MT7986_CALIBRATION, -+ .num_controller = MT7986_NUM_CONTROLLER, -+ .controller_offset = mt7986_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 1, -+ .sensors = mt7986_bank_data, -+ }, -+ }, -+ .msr = mt7986_msr, -+ .adcpnp = mt7986_adcpnp, -+ .sensor_mux_values = mt7986_mux_values, -+ .version = MTK_THERMAL_V3, -+}; -+ -+/** -+ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius -+ * @mt: The thermal controller -+ * @sensno: sensor number -+ * @raw: raw ADC value -+ * -+ * This converts the raw ADC value to mcelsius using the SoC specific -+ * calibration constants -+ */ -+static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 tmp; -+ -+ raw &= 0xfff; -+ -+ tmp = 203450520 << 3; -+ tmp /= mt->conf->cali_val + mt->o_slope; -+ tmp /= 10000 + mt->adc_ge; -+ tmp *= raw - mt->vts[sensno] - 3350; -+ tmp >>= 3; -+ -+ return mt->degc_cali * 500 - tmp; -+} -+ -+static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 format_1; -+ s32 format_2; -+ s32 g_oe; -+ s32 g_gain; -+ s32 g_x_roomt; -+ s32 tmp; -+ -+ if (raw == 0) -+ return 0; -+ -+ raw &= 0xfff; -+ g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); -+ g_oe = mt->adc_oe - 512; -+ format_1 = mt->vts[VTS2] + 3105 - g_oe; -+ format_2 = (mt->degc_cali * 10) >> 1; -+ g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; -+ -+ tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; -+ tmp = tmp * 10 * 100 / 11; -+ -+ if (mt->o_slope_sign == 0) -+ tmp = tmp / (165 - mt->o_slope); -+ else -+ tmp = tmp / (165 + mt->o_slope); -+ -+ return (format_2 - tmp) * 100; -+} -+ -+static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 tmp; -+ -+ if (raw == 0) -+ return 0; -+ -+ raw &= 0xfff; -+ tmp = 100000 * 15 / 16 * 10000; -+ tmp /= 4096 - 512 + mt->adc_ge; -+ tmp /= 1490; -+ tmp *= raw - mt->vts[sensno] - 2900; -+ -+ return mt->degc_cali * 500 - tmp; -+} -+ -+/** -+ * mtk_thermal_get_bank - get bank -+ * @bank: The bank -+ * -+ * The bank registers are banked, we have to select a bank in the -+ * PTPCORESEL register to access it. -+ */ -+static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank) -+{ -+ struct mtk_thermal *mt = bank->mt; -+ u32 val; -+ -+ if (mt->conf->need_switch_bank) { -+ mutex_lock(&mt->lock); -+ -+ val = readl(mt->thermal_base + PTPCORESEL); -+ val &= ~0xf; -+ val |= bank->id; -+ writel(val, mt->thermal_base + PTPCORESEL); -+ } -+} -+ -+/** -+ * mtk_thermal_put_bank - release bank -+ * @bank: The bank -+ * -+ * release a bank previously taken with mtk_thermal_get_bank, -+ */ -+static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank) -+{ -+ struct mtk_thermal *mt = bank->mt; -+ -+ if (mt->conf->need_switch_bank) -+ mutex_unlock(&mt->lock); -+} -+ -+/** -+ * mtk_thermal_bank_temperature - get the temperature of a bank -+ * @bank: The bank -+ * -+ * The temperature of a bank is considered the maximum temperature of -+ * the sensors associated to the bank. -+ */ -+static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) -+{ -+ struct mtk_thermal *mt = bank->mt; -+ const struct mtk_thermal_data *conf = mt->conf; -+ int i, temp = INT_MIN, max = INT_MIN; -+ u32 raw; -+ -+ for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { -+ raw = readl(mt->thermal_base + conf->msr[i]); -+ -+ temp = mt->raw_to_mcelsius( -+ mt, conf->bank_data[bank->id].sensors[i], raw); -+ -+ -+ /* -+ * The first read of a sensor often contains very high bogus -+ * temperature value. Filter these out so that the system does -+ * not immediately shut down. -+ */ -+ if (temp > 200000) -+ temp = 0; -+ -+ if (temp > max) -+ max = temp; -+ } -+ -+ return max; -+} -+ -+static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) -+{ -+ struct mtk_thermal *mt = tz->devdata; -+ int i; -+ int tempmax = INT_MIN; -+ -+ for (i = 0; i < mt->conf->num_banks; i++) { -+ struct mtk_thermal_bank *bank = &mt->banks[i]; -+ -+ mtk_thermal_get_bank(bank); -+ -+ tempmax = max(tempmax, mtk_thermal_bank_temperature(bank)); -+ -+ mtk_thermal_put_bank(bank); -+ } -+ -+ *temperature = tempmax; -+ -+ return 0; -+} -+ -+static const struct thermal_zone_device_ops mtk_thermal_ops = { -+ .get_temp = mtk_read_temp, -+}; -+ -+static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, -+ u32 apmixed_phys_base, u32 auxadc_phys_base, -+ int ctrl_id) -+{ -+ struct mtk_thermal_bank *bank = &mt->banks[num]; -+ const struct mtk_thermal_data *conf = mt->conf; -+ int i; -+ -+ int offset = mt->conf->controller_offset[ctrl_id]; -+ void __iomem *controller_base = mt->thermal_base + offset; -+ -+ bank->id = num; -+ bank->mt = mt; -+ -+ mtk_thermal_get_bank(bank); -+ -+ /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */ -+ writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1); -+ -+ /* -+ * filt interval is 1 * 46.540us = 46.54us, -+ * sen interval is 429 * 46.540us = 19.96ms -+ */ -+ writel(TEMP_MONCTL2_FILTER_INTERVAL(1) | -+ TEMP_MONCTL2_SENSOR_INTERVAL(429), -+ controller_base + TEMP_MONCTL2); -+ -+ /* poll is set to 10u */ -+ writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768), -+ controller_base + TEMP_AHBPOLL); -+ -+ /* temperature sampling control, 1 sample */ -+ writel(0x0, controller_base + TEMP_MSRCTL0); -+ -+ /* exceed this polling time, IRQ would be inserted */ -+ writel(0xffffffff, controller_base + TEMP_AHBTO); -+ -+ /* number of interrupts per event, 1 is enough */ -+ writel(0x0, controller_base + TEMP_MONIDET0); -+ writel(0x0, controller_base + TEMP_MONIDET1); -+ -+ /* -+ * The MT8173 thermal controller does not have its own ADC. Instead it -+ * uses AHB bus accesses to control the AUXADC. To do this the thermal -+ * controller has to be programmed with the physical addresses of the -+ * AUXADC registers and with the various bit positions in the AUXADC. -+ * Also the thermal controller controls a mux in the APMIXEDSYS register -+ * space. -+ */ -+ -+ /* -+ * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) -+ * automatically by hw -+ */ -+ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX); -+ -+ /* AHB address for auxadc mux selection */ -+ writel(auxadc_phys_base + AUXADC_CON1_CLR_V, -+ controller_base + TEMP_ADCMUXADDR); -+ -+ if (mt->conf->version == MTK_THERMAL_V1) { -+ /* AHB address for pnp sensor mux selection */ -+ writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, -+ controller_base + TEMP_PNPMUXADDR); -+ } -+ -+ /* AHB value for auxadc enable */ -+ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); -+ -+ /* AHB address for auxadc enable (channel 0 immediate mode selected) */ -+ writel(auxadc_phys_base + AUXADC_CON1_SET_V, -+ controller_base + TEMP_ADCENADDR); -+ -+ /* AHB address for auxadc valid bit */ -+ writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), -+ controller_base + TEMP_ADCVALIDADDR); -+ -+ /* AHB address for auxadc voltage output */ -+ writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel), -+ controller_base + TEMP_ADCVOLTADDR); -+ -+ /* read valid & voltage are at the same register */ -+ writel(0x0, controller_base + TEMP_RDCTRL); -+ -+ /* indicate where the valid bit is */ -+ writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12), -+ controller_base + TEMP_ADCVALIDMASK); -+ -+ /* no shift */ -+ writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT); -+ -+ /* enable auxadc mux write transaction */ -+ writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE, -+ controller_base + TEMP_ADCWRITECTRL); -+ -+ for (i = 0; i < conf->bank_data[num].num_sensors; i++) -+ writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]], -+ mt->thermal_base + conf->adcpnp[i]); -+ -+ writel((1 << conf->bank_data[num].num_sensors) - 1, -+ controller_base + TEMP_MONCTL0); -+ -+ writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE | -+ TEMP_ADCWRITECTRL_ADC_MUX_WRITE, -+ controller_base + TEMP_ADCWRITECTRL); -+ -+ mtk_thermal_put_bank(bank); -+} -+ -+static u64 of_get_phys_base(struct device_node *np) -+{ -+ u64 size64; -+ const __be32 *regaddr_p; -+ -+ regaddr_p = of_get_address(np, 0, &size64, NULL); -+ if (!regaddr_p) -+ return OF_BAD_ADDR; -+ -+ return of_translate_address(np, regaddr_p); -+} -+ -+static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) -+{ -+ int i; -+ -+ if (!(buf[0] & CALIB_BUF0_VALID_V1)) -+ return -EINVAL; -+ -+ mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); -+ -+ for (i = 0; i < mt->conf->num_sensors; i++) { -+ switch (mt->conf->vts_index[i]) { -+ case VTS1: -+ mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); -+ break; -+ case VTS2: -+ mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); -+ break; -+ case VTS3: -+ mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); -+ break; -+ case VTS4: -+ mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); -+ break; -+ case VTS5: -+ mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); -+ break; -+ case VTSABB: -+ mt->vts[VTSABB] = -+ CALIB_BUF2_VTS_TSABB_V1(buf[2]); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); -+ if (CALIB_BUF1_ID_V1(buf[1]) & -+ CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) -+ mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); -+ else -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); -+ -+ return 0; -+} -+ -+static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) -+{ -+ if (!CALIB_BUF1_VALID_V2(buf[1])) -+ return -EINVAL; -+ -+ mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); -+ mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); -+ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); -+ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); -+ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); -+ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); -+ -+ return 0; -+} -+ -+static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) -+{ -+ if (!CALIB_BUF1_VALID_V3(buf[1])) -+ return -EINVAL; -+ -+ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); -+ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); -+ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); -+ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); -+ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); -+ -+ if (CALIB_BUF1_ID_V3(buf[1]) == 0) -+ mt->o_slope = 0; -+ -+ return 0; -+} -+ -+static int mtk_thermal_get_calibration_data(struct device *dev, -+ struct mtk_thermal *mt) -+{ -+ struct nvmem_cell *cell; -+ u32 *buf; -+ size_t len; -+ int i, ret = 0; -+ -+ /* Start with default values */ -+ mt->adc_ge = 512; -+ mt->adc_oe = 512; -+ for (i = 0; i < mt->conf->num_sensors; i++) -+ mt->vts[i] = 260; -+ mt->degc_cali = 40; -+ mt->o_slope = 0; -+ -+ cell = nvmem_cell_get(dev, "calibration-data"); -+ if (IS_ERR(cell)) { -+ if (PTR_ERR(cell) == -EPROBE_DEFER) -+ return PTR_ERR(cell); -+ return 0; -+ } -+ -+ buf = (u32 *)nvmem_cell_read(cell, &len); -+ -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(buf)) -+ return PTR_ERR(buf); -+ -+ if (len < 3 * sizeof(u32)) { -+ dev_warn(dev, "invalid calibration data\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: -+ ret = mtk_thermal_extract_efuse_v1(mt, buf); -+ break; -+ case MTK_THERMAL_V2: -+ ret = mtk_thermal_extract_efuse_v2(mt, buf); -+ break; -+ case MTK_THERMAL_V3: -+ ret = mtk_thermal_extract_efuse_v3(mt, buf); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (ret) { -+ dev_info(dev, "Device not calibrated, using default calibration values\n"); -+ ret = 0; -+ } -+ -+out: -+ kfree(buf); -+ -+ return ret; -+} -+ -+static const struct of_device_id mtk_thermal_of_match[] = { -+ { -+ .compatible = "mediatek,mt8173-thermal", -+ .data = (void *)&mt8173_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt2701-thermal", -+ .data = (void *)&mt2701_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt2712-thermal", -+ .data = (void *)&mt2712_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt7622-thermal", -+ .data = (void *)&mt7622_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt7986-thermal", -+ .data = (void *)&mt7986_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt8183-thermal", -+ .data = (void *)&mt8183_thermal_data, -+ }, { -+ }, -+}; -+MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); -+ -+static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) -+{ -+ int tmp; -+ -+ tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); -+ tmp &= ~(0x37); -+ tmp |= 0x1; -+ writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); -+ udelay(200); -+} -+ -+static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, -+ void __iomem *auxadc_base) -+{ -+ int tmp; -+ -+ writel(0x800, auxadc_base + AUXADC_CON1_SET_V); -+ writel(0x1, mt->thermal_base + TEMP_MONCTL0); -+ tmp = readl(mt->thermal_base + TEMP_MSRCTL1); -+ writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); -+} -+ -+static int mtk_thermal_probe(struct platform_device *pdev) -+{ -+ int ret, i, ctrl_id; -+ struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node; -+ struct mtk_thermal *mt; -+ u64 auxadc_phys_base, apmixed_phys_base; -+ struct thermal_zone_device *tzdev; -+ void __iomem *apmixed_base, *auxadc_base; -+ -+ mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); -+ if (!mt) -+ return -ENOMEM; -+ -+ mt->conf = of_device_get_match_data(&pdev->dev); -+ -+ mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); -+ if (IS_ERR(mt->clk_peri_therm)) -+ return PTR_ERR(mt->clk_peri_therm); -+ -+ mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); -+ if (IS_ERR(mt->clk_auxadc)) -+ return PTR_ERR(mt->clk_auxadc); -+ -+ mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); -+ if (IS_ERR(mt->thermal_base)) -+ return PTR_ERR(mt->thermal_base); -+ -+ ret = mtk_thermal_get_calibration_data(&pdev->dev, mt); -+ if (ret) -+ return ret; -+ -+ mutex_init(&mt->lock); -+ -+ mt->dev = &pdev->dev; -+ -+ auxadc = of_parse_phandle(np, "mediatek,auxadc", 0); -+ if (!auxadc) { -+ dev_err(&pdev->dev, "missing auxadc node\n"); -+ return -ENODEV; -+ } -+ -+ auxadc_base = of_iomap(auxadc, 0); -+ auxadc_phys_base = of_get_phys_base(auxadc); -+ -+ of_node_put(auxadc); -+ -+ if (auxadc_phys_base == OF_BAD_ADDR) { -+ dev_err(&pdev->dev, "Can't get auxadc phys address\n"); -+ return -EINVAL; -+ } -+ -+ apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0); -+ if (!apmixedsys) { -+ dev_err(&pdev->dev, "missing apmixedsys node\n"); -+ return -ENODEV; -+ } -+ -+ apmixed_base = of_iomap(apmixedsys, 0); -+ apmixed_phys_base = of_get_phys_base(apmixedsys); -+ -+ of_node_put(apmixedsys); -+ -+ if (apmixed_phys_base == OF_BAD_ADDR) { -+ dev_err(&pdev->dev, "Can't get auxadc phys address\n"); -+ return -EINVAL; -+ } -+ -+ ret = device_reset_optional(&pdev->dev); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(mt->clk_auxadc); -+ if (ret) { -+ dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(mt->clk_peri_therm); -+ if (ret) { -+ dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); -+ goto err_disable_clk_auxadc; -+ } -+ -+ if (mt->conf->version != MTK_THERMAL_V1) { -+ mtk_thermal_turn_on_buffer(apmixed_base); -+ mtk_thermal_release_periodic_ts(mt, auxadc_base); -+ } -+ -+ if (mt->conf->version == MTK_THERMAL_V1) -+ mt->raw_to_mcelsius = raw_to_mcelsius_v1; -+ else if (mt->conf->version == MTK_THERMAL_V2) -+ mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ else -+ mt->raw_to_mcelsius = raw_to_mcelsius_v3; -+ -+ for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) -+ for (i = 0; i < mt->conf->num_banks; i++) -+ mtk_thermal_init_bank(mt, i, apmixed_phys_base, -+ auxadc_phys_base, ctrl_id); -+ -+ platform_set_drvdata(pdev, mt); -+ -+ tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, -+ &mtk_thermal_ops); -+ if (IS_ERR(tzdev)) { -+ ret = PTR_ERR(tzdev); -+ goto err_disable_clk_peri_therm; -+ } -+ -+ ret = devm_thermal_add_hwmon_sysfs(tzdev); -+ if (ret) -+ dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); -+ -+ return 0; -+ -+err_disable_clk_peri_therm: -+ clk_disable_unprepare(mt->clk_peri_therm); -+err_disable_clk_auxadc: -+ clk_disable_unprepare(mt->clk_auxadc); -+ -+ return ret; -+} -+ -+static int mtk_thermal_remove(struct platform_device *pdev) -+{ -+ struct mtk_thermal *mt = platform_get_drvdata(pdev); -+ -+ clk_disable_unprepare(mt->clk_peri_therm); -+ clk_disable_unprepare(mt->clk_auxadc); -+ -+ return 0; -+} -+ -+static struct platform_driver mtk_thermal_driver = { -+ .probe = mtk_thermal_probe, -+ .remove = mtk_thermal_remove, -+ .driver = { -+ .name = "mtk-thermal", -+ .of_match_table = mtk_thermal_of_match, -+ }, -+}; -+ -+module_platform_driver(mtk_thermal_driver); -+ -+MODULE_AUTHOR("Michael Kao "); -+MODULE_AUTHOR("Louis Yu "); -+MODULE_AUTHOR("Dawei Chien "); -+MODULE_AUTHOR("Sascha Hauer "); -+MODULE_AUTHOR("Hanyi Wu "); -+MODULE_DESCRIPTION("Mediatek thermal driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch b/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch deleted file mode 100644 index 2ae3734e40..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch +++ /dev/null @@ -1,1298 +0,0 @@ -From 325fadf27b21f7d79843c3cc282b7f3e6620ad3d Mon Sep 17 00:00:00 2001 -From: Balsam CHIHI -Date: Thu, 9 Feb 2023 11:56:26 +0100 -Subject: [PATCH 06/42] thermal/drivers/mediatek: Add the Low Voltage Thermal - Sensor driver - -The Low Voltage Thermal Sensor (LVTS) is a multiple sensors, multi -controllers contained in a thermal domain. - -A thermal domains can be the MCU or the AP. - -Each thermal domains contain up to seven controllers, each thermal -controller handle up to four thermal sensors. - -The LVTS has two Finite State Machines (FSM), one to handle the -functionin temperatures range like hot or cold temperature and another -one to handle monitoring trip point. The FSM notifies via interrupts -when a trip point is crossed. - -The interrupt is managed at the thermal controller level, so when an -interrupt occurs, the driver has to find out which sensor triggered -such an interrupt. - -The sampling of the thermal can be filtered or immediate. For the -former, the LVTS measures several points and applies a low pass -filter. - -Signed-off-by: Balsam CHIHI -Reviewed-by: AngeloGioacchino Del Regno - -On MT8195 Tomato Chromebook: - -Tested-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230209105628.50294-5-bchihi@baylibre.com -Signed-off-by: Daniel Lezcano -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/mediatek/Kconfig | 16 + - drivers/thermal/mediatek/Makefile | 1 + - drivers/thermal/mediatek/lvts_thermal.c | 1224 +++++++++++++++++++++++ - 3 files changed, 1241 insertions(+) - create mode 100644 drivers/thermal/mediatek/lvts_thermal.c - ---- a/drivers/thermal/mediatek/Kconfig -+++ b/drivers/thermal/mediatek/Kconfig -@@ -18,4 +18,20 @@ config MTK_SOC_THERMAL - This driver configures thermal controllers to collect - temperature via AUXADC interface. - -+config MTK_LVTS_THERMAL -+ tristate "LVTS Thermal Driver for MediaTek SoCs" -+ depends on HAS_IOMEM -+ help -+ Enable this option if you want to get SoC temperature -+ information for supported MediaTek platforms. -+ This driver configures LVTS (Low Voltage Thermal Sensor) -+ thermal controllers to collect temperatures via ASIF -+ (Analog Serial Interface). -+ -+config MTK_LVTS_THERMAL_DEBUGFS -+ bool "LVTS thermal debugfs" -+ depends on MTK_LVTS_THERMAL && DEBUG_FS -+ help -+ Enable this option to debug the internals of the device driver. -+ - endif ---- a/drivers/thermal/mediatek/Makefile -+++ b/drivers/thermal/mediatek/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o -+obj-$(CONFIG_MTK_LVTS_THERMAL) += lvts_thermal.o ---- /dev/null -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -0,0 +1,1224 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2023 MediaTek Inc. -+ * Author: Balsam CHIHI -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define LVTS_MONCTL0(__base) (__base + 0x0000) -+#define LVTS_MONCTL1(__base) (__base + 0x0004) -+#define LVTS_MONCTL2(__base) (__base + 0x0008) -+#define LVTS_MONINT(__base) (__base + 0x000C) -+#define LVTS_MONINTSTS(__base) (__base + 0x0010) -+#define LVTS_MONIDET0(__base) (__base + 0x0014) -+#define LVTS_MONIDET1(__base) (__base + 0x0018) -+#define LVTS_MONIDET2(__base) (__base + 0x001C) -+#define LVTS_MONIDET3(__base) (__base + 0x0020) -+#define LVTS_H2NTHRE(__base) (__base + 0x0024) -+#define LVTS_HTHRE(__base) (__base + 0x0028) -+#define LVTS_OFFSETH(__base) (__base + 0x0030) -+#define LVTS_OFFSETL(__base) (__base + 0x0034) -+#define LVTS_MSRCTL0(__base) (__base + 0x0038) -+#define LVTS_MSRCTL1(__base) (__base + 0x003C) -+#define LVTS_TSSEL(__base) (__base + 0x0040) -+#define LVTS_CALSCALE(__base) (__base + 0x0048) -+#define LVTS_ID(__base) (__base + 0x004C) -+#define LVTS_CONFIG(__base) (__base + 0x0050) -+#define LVTS_EDATA00(__base) (__base + 0x0054) -+#define LVTS_EDATA01(__base) (__base + 0x0058) -+#define LVTS_EDATA02(__base) (__base + 0x005C) -+#define LVTS_EDATA03(__base) (__base + 0x0060) -+#define LVTS_MSR0(__base) (__base + 0x0090) -+#define LVTS_MSR1(__base) (__base + 0x0094) -+#define LVTS_MSR2(__base) (__base + 0x0098) -+#define LVTS_MSR3(__base) (__base + 0x009C) -+#define LVTS_IMMD0(__base) (__base + 0x00A0) -+#define LVTS_IMMD1(__base) (__base + 0x00A4) -+#define LVTS_IMMD2(__base) (__base + 0x00A8) -+#define LVTS_IMMD3(__base) (__base + 0x00AC) -+#define LVTS_PROTCTL(__base) (__base + 0x00C0) -+#define LVTS_PROTTA(__base) (__base + 0x00C4) -+#define LVTS_PROTTB(__base) (__base + 0x00C8) -+#define LVTS_PROTTC(__base) (__base + 0x00CC) -+#define LVTS_CLKEN(__base) (__base + 0x00E4) -+ -+#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) -+#define LVTS_GROUP_INTERVAL 1 -+#define LVTS_FILTER_INTERVAL 1 -+#define LVTS_SENSOR_INTERVAL 1 -+#define LVTS_HW_FILTER 0x2 -+#define LVTS_TSSEL_CONF 0x13121110 -+#define LVTS_CALSCALE_CONF 0x300 -+#define LVTS_MONINT_CONF 0x9FBF7BDE -+ -+#define LVTS_INT_SENSOR0 0x0009001F -+#define LVTS_INT_SENSOR1 0X000881F0 -+#define LVTS_INT_SENSOR2 0x00247C00 -+#define LVTS_INT_SENSOR3 0x1FC00000 -+ -+#define LVTS_SENSOR_MAX 4 -+#define LVTS_GOLDEN_TEMP_MAX 62 -+#define LVTS_GOLDEN_TEMP_DEFAULT 50 -+#define LVTS_COEFF_A -250460 -+#define LVTS_COEFF_B 250460 -+ -+#define LVTS_MSR_IMMEDIATE_MODE 0 -+#define LVTS_MSR_FILTERED_MODE 1 -+ -+#define LVTS_HW_SHUTDOWN_MT8195 105000 -+ -+static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; -+static int coeff_b = LVTS_COEFF_B; -+ -+struct lvts_sensor_data { -+ int dt_id; -+}; -+ -+struct lvts_ctrl_data { -+ struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; -+ int cal_offset[LVTS_SENSOR_MAX]; -+ int hw_tshut_temp; -+ int num_lvts_sensor; -+ int offset; -+ int mode; -+}; -+ -+struct lvts_data { -+ const struct lvts_ctrl_data *lvts_ctrl; -+ int num_lvts_ctrl; -+}; -+ -+struct lvts_sensor { -+ struct thermal_zone_device *tz; -+ void __iomem *msr; -+ void __iomem *base; -+ int id; -+ int dt_id; -+}; -+ -+struct lvts_ctrl { -+ struct lvts_sensor sensors[LVTS_SENSOR_MAX]; -+ u32 calibration[LVTS_SENSOR_MAX]; -+ u32 hw_tshut_raw_temp; -+ int num_lvts_sensor; -+ int mode; -+ void __iomem *base; -+}; -+ -+struct lvts_domain { -+ struct lvts_ctrl *lvts_ctrl; -+ struct reset_control *reset; -+ struct clk *clk; -+ int num_lvts_ctrl; -+ void __iomem *base; -+ size_t calib_len; -+ u8 *calib; -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *dom_dentry; -+#endif -+}; -+ -+#ifdef CONFIG_MTK_LVTS_THERMAL_DEBUGFS -+ -+#define LVTS_DEBUG_FS_REGS(__reg) \ -+{ \ -+ .name = __stringify(__reg), \ -+ .offset = __reg(0), \ -+} -+ -+static const struct debugfs_reg32 lvts_regs[] = { -+ LVTS_DEBUG_FS_REGS(LVTS_MONCTL0), -+ LVTS_DEBUG_FS_REGS(LVTS_MONCTL1), -+ LVTS_DEBUG_FS_REGS(LVTS_MONCTL2), -+ LVTS_DEBUG_FS_REGS(LVTS_MONINT), -+ LVTS_DEBUG_FS_REGS(LVTS_MONINTSTS), -+ LVTS_DEBUG_FS_REGS(LVTS_MONIDET0), -+ LVTS_DEBUG_FS_REGS(LVTS_MONIDET1), -+ LVTS_DEBUG_FS_REGS(LVTS_MONIDET2), -+ LVTS_DEBUG_FS_REGS(LVTS_MONIDET3), -+ LVTS_DEBUG_FS_REGS(LVTS_H2NTHRE), -+ LVTS_DEBUG_FS_REGS(LVTS_HTHRE), -+ LVTS_DEBUG_FS_REGS(LVTS_OFFSETH), -+ LVTS_DEBUG_FS_REGS(LVTS_OFFSETL), -+ LVTS_DEBUG_FS_REGS(LVTS_MSRCTL0), -+ LVTS_DEBUG_FS_REGS(LVTS_MSRCTL1), -+ LVTS_DEBUG_FS_REGS(LVTS_TSSEL), -+ LVTS_DEBUG_FS_REGS(LVTS_CALSCALE), -+ LVTS_DEBUG_FS_REGS(LVTS_ID), -+ LVTS_DEBUG_FS_REGS(LVTS_CONFIG), -+ LVTS_DEBUG_FS_REGS(LVTS_EDATA00), -+ LVTS_DEBUG_FS_REGS(LVTS_EDATA01), -+ LVTS_DEBUG_FS_REGS(LVTS_EDATA02), -+ LVTS_DEBUG_FS_REGS(LVTS_EDATA03), -+ LVTS_DEBUG_FS_REGS(LVTS_MSR0), -+ LVTS_DEBUG_FS_REGS(LVTS_MSR1), -+ LVTS_DEBUG_FS_REGS(LVTS_MSR2), -+ LVTS_DEBUG_FS_REGS(LVTS_MSR3), -+ LVTS_DEBUG_FS_REGS(LVTS_IMMD0), -+ LVTS_DEBUG_FS_REGS(LVTS_IMMD1), -+ LVTS_DEBUG_FS_REGS(LVTS_IMMD2), -+ LVTS_DEBUG_FS_REGS(LVTS_IMMD3), -+ LVTS_DEBUG_FS_REGS(LVTS_PROTCTL), -+ LVTS_DEBUG_FS_REGS(LVTS_PROTTA), -+ LVTS_DEBUG_FS_REGS(LVTS_PROTTB), -+ LVTS_DEBUG_FS_REGS(LVTS_PROTTC), -+ LVTS_DEBUG_FS_REGS(LVTS_CLKEN), -+}; -+ -+static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) -+{ -+ struct debugfs_regset32 *regset; -+ struct lvts_ctrl *lvts_ctrl; -+ struct dentry *dentry; -+ char name[64]; -+ int i; -+ -+ lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); -+ if (!lvts_td->dom_dentry) -+ return 0; -+ -+ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { -+ -+ lvts_ctrl = &lvts_td->lvts_ctrl[i]; -+ -+ sprintf(name, "controller%d", i); -+ dentry = debugfs_create_dir(name, lvts_td->dom_dentry); -+ if (!dentry) -+ continue; -+ -+ regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); -+ if (!regset) -+ continue; -+ -+ regset->base = lvts_ctrl->base; -+ regset->regs = lvts_regs; -+ regset->nregs = ARRAY_SIZE(lvts_regs); -+ -+ debugfs_create_regset32("registers", 0400, dentry, regset); -+ } -+ -+ return 0; -+} -+ -+static void lvts_debugfs_exit(struct lvts_domain *lvts_td) -+{ -+ debugfs_remove_recursive(lvts_td->dom_dentry); -+} -+ -+#else -+ -+static inline int lvts_debugfs_init(struct device *dev, -+ struct lvts_domain *lvts_td) -+{ -+ return 0; -+} -+ -+static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } -+ -+#endif -+ -+static int lvts_raw_to_temp(u32 raw_temp) -+{ -+ int temperature; -+ -+ temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; -+ temperature += coeff_b; -+ -+ return temperature; -+} -+ -+static u32 lvts_temp_to_raw(int temperature) -+{ -+ u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; -+ -+ raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); -+ -+ return raw_temp; -+} -+ -+static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) -+{ -+ struct lvts_sensor *lvts_sensor = tz->devdata; -+ void __iomem *msr = lvts_sensor->msr; -+ u32 value; -+ -+ /* -+ * Measurement registers: -+ * -+ * LVTS_MSR[0-3] / LVTS_IMMD[0-3] -+ * -+ * Bits: -+ * -+ * 32-17: Unused -+ * 16 : Valid temperature -+ * 15-0 : Raw temperature -+ */ -+ value = readl(msr); -+ -+ /* -+ * As the thermal zone temperature will read before the -+ * hardware sensor is fully initialized, we have to check the -+ * validity of the temperature returned when reading the -+ * measurement register. The thermal controller will set the -+ * valid bit temperature only when it is totally initialized. -+ * -+ * Otherwise, we may end up with garbage values out of the -+ * functionning temperature and directly jump to a system -+ * shutdown. -+ */ -+ if (!(value & BIT(16))) -+ return -EAGAIN; -+ -+ *temp = lvts_raw_to_temp(value & 0xFFFF); -+ -+ return 0; -+} -+ -+static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) -+{ -+ struct lvts_sensor *lvts_sensor = tz->devdata; -+ void __iomem *base = lvts_sensor->base; -+ u32 raw_low = lvts_temp_to_raw(low); -+ u32 raw_high = lvts_temp_to_raw(high); -+ -+ /* -+ * Hot to normal temperature threshold -+ * -+ * LVTS_H2NTHRE -+ * -+ * Bits: -+ * -+ * 14-0 : Raw temperature for threshold -+ */ -+ if (low != -INT_MAX) { -+ dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low); -+ writel(raw_low, LVTS_H2NTHRE(base)); -+ } -+ -+ /* -+ * Hot temperature threshold -+ * -+ * LVTS_HTHRE -+ * -+ * Bits: -+ * -+ * 14-0 : Raw temperature for threshold -+ */ -+ dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high); -+ writel(raw_high, LVTS_HTHRE(base)); -+ -+ return 0; -+} -+ -+static irqreturn_t lvts_ctrl_irq_handler(struct lvts_ctrl *lvts_ctrl) -+{ -+ irqreturn_t iret = IRQ_NONE; -+ u32 value; -+ u32 masks[] = { -+ LVTS_INT_SENSOR0, -+ LVTS_INT_SENSOR1, -+ LVTS_INT_SENSOR2, -+ LVTS_INT_SENSOR3 -+ }; -+ int i; -+ -+ /* -+ * Interrupt monitoring status -+ * -+ * LVTS_MONINTST -+ * -+ * Bits: -+ * -+ * 31 : Interrupt for stage 3 -+ * 30 : Interrupt for stage 2 -+ * 29 : Interrupt for state 1 -+ * 28 : Interrupt using filter on sensor 3 -+ * -+ * 27 : Interrupt using immediate on sensor 3 -+ * 26 : Interrupt normal to hot on sensor 3 -+ * 25 : Interrupt high offset on sensor 3 -+ * 24 : Interrupt low offset on sensor 3 -+ * -+ * 23 : Interrupt hot threshold on sensor 3 -+ * 22 : Interrupt cold threshold on sensor 3 -+ * 21 : Interrupt using filter on sensor 2 -+ * 20 : Interrupt using filter on sensor 1 -+ * -+ * 19 : Interrupt using filter on sensor 0 -+ * 18 : Interrupt using immediate on sensor 2 -+ * 17 : Interrupt using immediate on sensor 1 -+ * 16 : Interrupt using immediate on sensor 0 -+ * -+ * 15 : Interrupt device access timeout interrupt -+ * 14 : Interrupt normal to hot on sensor 2 -+ * 13 : Interrupt high offset interrupt on sensor 2 -+ * 12 : Interrupt low offset interrupt on sensor 2 -+ * -+ * 11 : Interrupt hot threshold on sensor 2 -+ * 10 : Interrupt cold threshold on sensor 2 -+ * 9 : Interrupt normal to hot on sensor 1 -+ * 8 : Interrupt high offset interrupt on sensor 1 -+ * -+ * 7 : Interrupt low offset interrupt on sensor 1 -+ * 6 : Interrupt hot threshold on sensor 1 -+ * 5 : Interrupt cold threshold on sensor 1 -+ * 4 : Interrupt normal to hot on sensor 0 -+ * -+ * 3 : Interrupt high offset interrupt on sensor 0 -+ * 2 : Interrupt low offset interrupt on sensor 0 -+ * 1 : Interrupt hot threshold on sensor 0 -+ * 0 : Interrupt cold threshold on sensor 0 -+ * -+ * We are interested in the sensor(s) responsible of the -+ * interrupt event. We update the thermal framework with the -+ * thermal zone associated with the sensor. The framework will -+ * take care of the rest whatever the kind of interrupt, we -+ * are only interested in which sensor raised the interrupt. -+ * -+ * sensor 3 interrupt: 0001 1111 1100 0000 0000 0000 0000 0000 -+ * => 0x1FC00000 -+ * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000 -+ * => 0x00247C00 -+ * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000 -+ * => 0X000881F0 -+ * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111 -+ * => 0x0009001F -+ */ -+ value = readl(LVTS_MONINTSTS(lvts_ctrl->base)); -+ -+ /* -+ * Let's figure out which sensors raised the interrupt -+ * -+ * NOTE: the masks array must be ordered with the index -+ * corresponding to the sensor id eg. index=0, mask for -+ * sensor0. -+ */ -+ for (i = 0; i < ARRAY_SIZE(masks); i++) { -+ -+ if (!(value & masks[i])) -+ continue; -+ -+ thermal_zone_device_update(lvts_ctrl->sensors[i].tz, -+ THERMAL_TRIP_VIOLATED); -+ iret = IRQ_HANDLED; -+ } -+ -+ /* -+ * Write back to clear the interrupt status (W1C) -+ */ -+ writel(value, LVTS_MONINTSTS(lvts_ctrl->base)); -+ -+ return iret; -+} -+ -+/* -+ * Temperature interrupt handler. Even if the driver supports more -+ * interrupt modes, we use the interrupt when the temperature crosses -+ * the hot threshold the way up and the way down (modulo the -+ * hysteresis). -+ * -+ * Each thermal domain has a couple of interrupts, one for hardware -+ * reset and another one for all the thermal events happening on the -+ * different sensors. -+ * -+ * The interrupt is configured for thermal events when crossing the -+ * hot temperature limit. At each interrupt, we check in every -+ * controller if there is an interrupt pending. -+ */ -+static irqreturn_t lvts_irq_handler(int irq, void *data) -+{ -+ struct lvts_domain *lvts_td = data; -+ irqreturn_t aux, iret = IRQ_NONE; -+ int i; -+ -+ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { -+ -+ aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); -+ if (aux != IRQ_HANDLED) -+ continue; -+ -+ iret = IRQ_HANDLED; -+ } -+ -+ return iret; -+} -+ -+static struct thermal_zone_device_ops lvts_ops = { -+ .get_temp = lvts_get_temp, -+ .set_trips = lvts_set_trips, -+}; -+ -+static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, -+ const struct lvts_ctrl_data *lvts_ctrl_data) -+{ -+ struct lvts_sensor *lvts_sensor = lvts_ctrl->sensors; -+ void __iomem *msr_regs[] = { -+ LVTS_MSR0(lvts_ctrl->base), -+ LVTS_MSR1(lvts_ctrl->base), -+ LVTS_MSR2(lvts_ctrl->base), -+ LVTS_MSR3(lvts_ctrl->base) -+ }; -+ -+ void __iomem *imm_regs[] = { -+ LVTS_IMMD0(lvts_ctrl->base), -+ LVTS_IMMD1(lvts_ctrl->base), -+ LVTS_IMMD2(lvts_ctrl->base), -+ LVTS_IMMD3(lvts_ctrl->base) -+ }; -+ -+ int i; -+ -+ for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) { -+ -+ int dt_id = lvts_ctrl_data->lvts_sensor[i].dt_id; -+ -+ /* -+ * At this point, we don't know which id matches which -+ * sensor. Let's set arbitrally the id from the index. -+ */ -+ lvts_sensor[i].id = i; -+ -+ /* -+ * The thermal zone registration will set the trip -+ * point interrupt in the thermal controller -+ * register. But this one will be reset in the -+ * initialization after. So we need to post pone the -+ * thermal zone creation after the controller is -+ * setup. For this reason, we store the device tree -+ * node id from the data in the sensor structure -+ */ -+ lvts_sensor[i].dt_id = dt_id; -+ -+ /* -+ * We assign the base address of the thermal -+ * controller as a back pointer. So it will be -+ * accessible from the different thermal framework ops -+ * as we pass the lvts_sensor pointer as thermal zone -+ * private data. -+ */ -+ lvts_sensor[i].base = lvts_ctrl->base; -+ -+ /* -+ * Each sensor has its own register address to read from. -+ */ -+ lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? -+ imm_regs[i] : msr_regs[i]; -+ }; -+ -+ lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; -+ -+ return 0; -+} -+ -+/* -+ * The efuse blob values follows the sensor enumeration per thermal -+ * controller. The decoding of the stream is as follow: -+ * -+ * <--?-> <----big0 ???---> <-sensor0-> <-0-> -+ * ------------------------------------------ -+ * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | -+ * ------------------------------------------ -+ * -+ * <--sensor1--><-0-> <----big1 ???---> <-sen -+ * ------------------------------------------ -+ * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | -+ * ------------------------------------------ -+ * -+ * sor0-> <-0-> <-sensor1-> <-0-> .......... -+ * ------------------------------------------ -+ * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | -+ * ------------------------------------------ -+ * -+ * And so on ... -+ * -+ * The data description gives the offset of the calibration data in -+ * this bytes stream for each sensor. -+ * -+ * Each thermal controller can handle up to 4 sensors max, we don't -+ * care if there are less as the array of calibration is sized to 4 -+ * anyway. The unused sensor slot will be zeroed. -+ */ -+static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, -+ const struct lvts_ctrl_data *lvts_ctrl_data, -+ u8 *efuse_calibration) -+{ -+ int i; -+ -+ for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) -+ memcpy(&lvts_ctrl->calibration[i], -+ efuse_calibration + lvts_ctrl_data->cal_offset[i], 2); -+ -+ return 0; -+} -+ -+/* -+ * The efuse bytes stream can be split into different chunk of -+ * nvmems. This function reads and concatenate those into a single -+ * buffer so it can be read sequentially when initializing the -+ * calibration data. -+ */ -+static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td, -+ const struct lvts_data *lvts_data) -+{ -+ struct device_node *np = dev_of_node(dev); -+ struct nvmem_cell *cell; -+ struct property *prop; -+ const char *cell_name; -+ -+ of_property_for_each_string(np, "nvmem-cell-names", prop, cell_name) { -+ size_t len; -+ u8 *efuse; -+ -+ cell = of_nvmem_cell_get(np, cell_name); -+ if (IS_ERR(cell)) { -+ dev_err(dev, "Failed to get cell '%s'\n", cell_name); -+ return PTR_ERR(cell); -+ } -+ -+ efuse = nvmem_cell_read(cell, &len); -+ -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(efuse)) { -+ dev_err(dev, "Failed to read cell '%s'\n", cell_name); -+ return PTR_ERR(efuse); -+ } -+ -+ lvts_td->calib = devm_krealloc(dev, lvts_td->calib, -+ lvts_td->calib_len + len, GFP_KERNEL); -+ if (!lvts_td->calib) -+ return -ENOMEM; -+ -+ memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len); -+ -+ lvts_td->calib_len += len; -+ -+ kfree(efuse); -+ } -+ -+ return 0; -+} -+ -+static int lvts_golden_temp_init(struct device *dev, u32 *value) -+{ -+ u32 gt; -+ -+ gt = (*value) >> 24; -+ -+ if (gt && gt < LVTS_GOLDEN_TEMP_MAX) -+ golden_temp = gt; -+ -+ coeff_b = golden_temp * 500 + LVTS_COEFF_B; -+ -+ return 0; -+} -+ -+static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, -+ const struct lvts_data *lvts_data) -+{ -+ size_t size = sizeof(*lvts_td->lvts_ctrl) * lvts_data->num_lvts_ctrl; -+ struct lvts_ctrl *lvts_ctrl; -+ int i, ret; -+ -+ /* -+ * Create the calibration bytes stream from efuse data -+ */ -+ ret = lvts_calibration_read(dev, lvts_td, lvts_data); -+ if (ret) -+ return ret; -+ -+ /* -+ * The golden temp information is contained in the first chunk -+ * of efuse data. -+ */ -+ ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); -+ if (ret) -+ return ret; -+ -+ lvts_ctrl = devm_kzalloc(dev, size, GFP_KERNEL); -+ if (!lvts_ctrl) -+ return -ENOMEM; -+ -+ for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { -+ -+ lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; -+ -+ ret = lvts_sensor_init(dev, &lvts_ctrl[i], -+ &lvts_data->lvts_ctrl[i]); -+ if (ret) -+ return ret; -+ -+ ret = lvts_calibration_init(dev, &lvts_ctrl[i], -+ &lvts_data->lvts_ctrl[i], -+ lvts_td->calib); -+ if (ret) -+ return ret; -+ -+ /* -+ * The mode the ctrl will use to read the temperature -+ * (filtered or immediate) -+ */ -+ lvts_ctrl[i].mode = lvts_data->lvts_ctrl[i].mode; -+ -+ /* -+ * The temperature to raw temperature must be done -+ * after initializing the calibration. -+ */ -+ lvts_ctrl[i].hw_tshut_raw_temp = -+ lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); -+ } -+ -+ /* -+ * We no longer need the efuse bytes stream, let's free it -+ */ -+ devm_kfree(dev, lvts_td->calib); -+ -+ lvts_td->lvts_ctrl = lvts_ctrl; -+ lvts_td->num_lvts_ctrl = lvts_data->num_lvts_ctrl; -+ -+ return 0; -+} -+ -+/* -+ * At this point the configuration register is the only place in the -+ * driver where we write multiple values. Per hardware constraint, -+ * each write in the configuration register must be separated by a -+ * delay of 2 us. -+ */ -+static void lvts_write_config(struct lvts_ctrl *lvts_ctrl, u32 *cmds, int nr_cmds) -+{ -+ int i; -+ -+ /* -+ * Configuration register -+ */ -+ for (i = 0; i < nr_cmds; i++) { -+ writel(cmds[i], LVTS_CONFIG(lvts_ctrl->base)); -+ usleep_range(2, 4); -+ } -+} -+ -+static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) -+{ -+ /* -+ * LVTS_PROTCTL : Thermal Protection Sensor Selection -+ * -+ * Bits: -+ * -+ * 19-18 : Sensor to base the protection on -+ * 17-16 : Strategy: -+ * 00 : Average of 4 sensors -+ * 01 : Max of 4 sensors -+ * 10 : Selected sensor with bits 19-18 -+ * 11 : Reserved -+ */ -+ writel(BIT(16), LVTS_PROTCTL(lvts_ctrl->base)); -+ -+ /* -+ * LVTS_PROTTA : Stage 1 temperature threshold -+ * LVTS_PROTTB : Stage 2 temperature threshold -+ * LVTS_PROTTC : Stage 3 temperature threshold -+ * -+ * Bits: -+ * -+ * 14-0: Raw temperature threshold -+ * -+ * writel(0x0, LVTS_PROTTA(lvts_ctrl->base)); -+ * writel(0x0, LVTS_PROTTB(lvts_ctrl->base)); -+ */ -+ writel(lvts_ctrl->hw_tshut_raw_temp, LVTS_PROTTC(lvts_ctrl->base)); -+ -+ /* -+ * LVTS_MONINT : Interrupt configuration register -+ * -+ * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS -+ * register, except we set the bits to enable the interrupt. -+ */ -+ writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); -+ -+ return 0; -+} -+ -+static int lvts_domain_reset(struct device *dev, struct reset_control *reset) -+{ -+ int ret; -+ -+ ret = reset_control_assert(reset); -+ if (ret) -+ return ret; -+ -+ return reset_control_deassert(reset); -+} -+ -+/* -+ * Enable or disable the clocks of a specified thermal controller -+ */ -+static int lvts_ctrl_set_enable(struct lvts_ctrl *lvts_ctrl, int enable) -+{ -+ /* -+ * LVTS_CLKEN : Internal LVTS clock -+ * -+ * Bits: -+ * -+ * 0 : enable / disable clock -+ */ -+ writel(enable, LVTS_CLKEN(lvts_ctrl->base)); -+ -+ return 0; -+} -+ -+static int lvts_ctrl_connect(struct device *dev, struct lvts_ctrl *lvts_ctrl) -+{ -+ u32 id, cmds[] = { 0xC103FFFF, 0xC502FF55 }; -+ -+ lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); -+ -+ /* -+ * LVTS_ID : Get ID and status of the thermal controller -+ * -+ * Bits: -+ * -+ * 0-5 : thermal controller id -+ * 7 : thermal controller connection is valid -+ */ -+ id = readl(LVTS_ID(lvts_ctrl->base)); -+ if (!(id & BIT(7))) -+ return -EIO; -+ -+ return 0; -+} -+ -+static int lvts_ctrl_initialize(struct device *dev, struct lvts_ctrl *lvts_ctrl) -+{ -+ /* -+ * Write device mask: 0xC1030000 -+ */ -+ u32 cmds[] = { -+ 0xC1030E01, 0xC1030CFC, 0xC1030A8C, 0xC103098D, 0xC10308F1, -+ 0xC10307A6, 0xC10306B8, 0xC1030500, 0xC1030420, 0xC1030300, -+ 0xC1030030, 0xC10300F6, 0xC1030050, 0xC1030060, 0xC10300AC, -+ 0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1 -+ }; -+ -+ lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds)); -+ -+ return 0; -+} -+ -+static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl) -+{ -+ int i; -+ void __iomem *lvts_edata[] = { -+ LVTS_EDATA00(lvts_ctrl->base), -+ LVTS_EDATA01(lvts_ctrl->base), -+ LVTS_EDATA02(lvts_ctrl->base), -+ LVTS_EDATA03(lvts_ctrl->base) -+ }; -+ -+ /* -+ * LVTS_EDATA0X : Efuse calibration reference value for sensor X -+ * -+ * Bits: -+ * -+ * 20-0 : Efuse value for normalization data -+ */ -+ for (i = 0; i < LVTS_SENSOR_MAX; i++) -+ writel(lvts_ctrl->calibration[i], lvts_edata[i]); -+ -+ return 0; -+} -+ -+static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl) -+{ -+ u32 value; -+ -+ /* -+ * LVTS_TSSEL : Sensing point index numbering -+ * -+ * Bits: -+ * -+ * 31-24: ADC Sense 3 -+ * 23-16: ADC Sense 2 -+ * 15-8 : ADC Sense 1 -+ * 7-0 : ADC Sense 0 -+ */ -+ value = LVTS_TSSEL_CONF; -+ writel(value, LVTS_TSSEL(lvts_ctrl->base)); -+ -+ /* -+ * LVTS_CALSCALE : ADC voltage round -+ */ -+ value = 0x300; -+ value = LVTS_CALSCALE_CONF; -+ -+ /* -+ * LVTS_MSRCTL0 : Sensor filtering strategy -+ * -+ * Filters: -+ * -+ * 000 : One sample -+ * 001 : Avg 2 samples -+ * 010 : 4 samples, drop min and max, avg 2 samples -+ * 011 : 6 samples, drop min and max, avg 4 samples -+ * 100 : 10 samples, drop min and max, avg 8 samples -+ * 101 : 18 samples, drop min and max, avg 16 samples -+ * -+ * Bits: -+ * -+ * 0-2 : Sensor0 filter -+ * 3-5 : Sensor1 filter -+ * 6-8 : Sensor2 filter -+ * 9-11 : Sensor3 filter -+ */ -+ value = LVTS_HW_FILTER << 9 | LVTS_HW_FILTER << 6 | -+ LVTS_HW_FILTER << 3 | LVTS_HW_FILTER; -+ writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); -+ -+ /* -+ * LVTS_MSRCTL1 : Measurement control -+ * -+ * Bits: -+ * -+ * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 -+ * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 -+ * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 -+ * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 -+ * -+ * That configuration will ignore the filtering and the delays -+ * introduced below in MONCTL1 and MONCTL2 -+ */ -+ if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { -+ value = BIT(9) | BIT(6) | BIT(5) | BIT(4); -+ writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); -+ } -+ -+ /* -+ * LVTS_MONCTL1 : Period unit and group interval configuration -+ * -+ * The clock source of LVTS thermal controller is 26MHz. -+ * -+ * The period unit is a time base for all the interval delays -+ * specified in the registers. By default we use 12. The time -+ * conversion is done by multiplying by 256 and 1/26.10^6 -+ * -+ * An interval delay multiplied by the period unit gives the -+ * duration in seconds. -+ * -+ * - Filter interval delay is a delay between two samples of -+ * the same sensor. -+ * -+ * - Sensor interval delay is a delay between two samples of -+ * different sensors. -+ * -+ * - Group interval delay is a delay between different rounds. -+ * -+ * For example: -+ * If Period unit = C, filter delay = 1, sensor delay = 2, group delay = 1, -+ * and two sensors, TS1 and TS2, are in a LVTS thermal controller -+ * and then -+ * Period unit time = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us -+ * Filter interval delay = 1 * Period unit = 118.149us -+ * Sensor interval delay = 2 * Period unit = 236.298us -+ * Group interval delay = 1 * Period unit = 118.149us -+ * -+ * TS1 TS1 ... TS1 TS2 TS2 ... TS2 TS1... -+ * <--> Filter interval delay -+ * <--> Sensor interval delay -+ * <--> Group interval delay -+ * Bits: -+ * 29 - 20 : Group interval -+ * 16 - 13 : Send a single interrupt when crossing the hot threshold (1) -+ * or an interrupt everytime the hot threshold is crossed (0) -+ * 9 - 0 : Period unit -+ * -+ */ -+ value = LVTS_GROUP_INTERVAL << 20 | LVTS_PERIOD_UNIT; -+ writel(value, LVTS_MONCTL1(lvts_ctrl->base)); -+ -+ /* -+ * LVTS_MONCTL2 : Filtering and sensor interval -+ * -+ * Bits: -+ * -+ * 25-16 : Interval unit in PERIOD_UNIT between sample on -+ * the same sensor, filter interval -+ * 9-0 : Interval unit in PERIOD_UNIT between each sensor -+ * -+ */ -+ value = LVTS_FILTER_INTERVAL << 16 | LVTS_SENSOR_INTERVAL; -+ writel(value, LVTS_MONCTL2(lvts_ctrl->base)); -+ -+ return lvts_irq_init(lvts_ctrl); -+} -+ -+static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) -+{ -+ struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors; -+ struct thermal_zone_device *tz; -+ u32 sensor_map = 0; -+ int i; -+ -+ for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { -+ -+ int dt_id = lvts_sensors[i].dt_id; -+ -+ tz = devm_thermal_of_zone_register(dev, dt_id, &lvts_sensors[i], -+ &lvts_ops); -+ if (IS_ERR(tz)) { -+ /* -+ * This thermal zone is not described in the -+ * device tree. It is not an error from the -+ * thermal OF code POV, we just continue. -+ */ -+ if (PTR_ERR(tz) == -ENODEV) -+ continue; -+ -+ return PTR_ERR(tz); -+ } -+ -+ /* -+ * The thermal zone pointer will be needed in the -+ * interrupt handler, we store it in the sensor -+ * structure. The thermal domain structure will be -+ * passed to the interrupt handler private data as the -+ * interrupt is shared for all the controller -+ * belonging to the thermal domain. -+ */ -+ lvts_sensors[i].tz = tz; -+ -+ /* -+ * This sensor was correctly associated with a thermal -+ * zone, let's set the corresponding bit in the sensor -+ * map, so we can enable the temperature monitoring in -+ * the hardware thermal controller. -+ */ -+ sensor_map |= BIT(i); -+ } -+ -+ /* -+ * Bits: -+ * 9: Single point access flow -+ * 0-3: Enable sensing point 0-3 -+ * -+ * The initialization of the thermal zones give us -+ * which sensor point to enable. If any thermal zone -+ * was not described in the device tree, it won't be -+ * enabled here in the sensor map. -+ */ -+ writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); -+ -+ return 0; -+} -+ -+static int lvts_domain_init(struct device *dev, struct lvts_domain *lvts_td, -+ const struct lvts_data *lvts_data) -+{ -+ struct lvts_ctrl *lvts_ctrl; -+ int i, ret; -+ -+ ret = lvts_ctrl_init(dev, lvts_td, lvts_data); -+ if (ret) -+ return ret; -+ -+ ret = lvts_domain_reset(dev, lvts_td->reset); -+ if (ret) { -+ dev_dbg(dev, "Failed to reset domain"); -+ return ret; -+ } -+ -+ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { -+ -+ lvts_ctrl = &lvts_td->lvts_ctrl[i]; -+ -+ /* -+ * Initialization steps: -+ * -+ * - Enable the clock -+ * - Connect to the LVTS -+ * - Initialize the LVTS -+ * - Prepare the calibration data -+ * - Select monitored sensors -+ * [ Configure sampling ] -+ * [ Configure the interrupt ] -+ * - Start measurement -+ */ -+ ret = lvts_ctrl_set_enable(lvts_ctrl, true); -+ if (ret) { -+ dev_dbg(dev, "Failed to enable LVTS clock"); -+ return ret; -+ } -+ -+ ret = lvts_ctrl_connect(dev, lvts_ctrl); -+ if (ret) { -+ dev_dbg(dev, "Failed to connect to LVTS controller"); -+ return ret; -+ } -+ -+ ret = lvts_ctrl_initialize(dev, lvts_ctrl); -+ if (ret) { -+ dev_dbg(dev, "Failed to initialize controller"); -+ return ret; -+ } -+ -+ ret = lvts_ctrl_calibrate(dev, lvts_ctrl); -+ if (ret) { -+ dev_dbg(dev, "Failed to calibrate controller"); -+ return ret; -+ } -+ -+ ret = lvts_ctrl_configure(dev, lvts_ctrl); -+ if (ret) { -+ dev_dbg(dev, "Failed to configure controller"); -+ return ret; -+ } -+ -+ ret = lvts_ctrl_start(dev, lvts_ctrl); -+ if (ret) { -+ dev_dbg(dev, "Failed to start controller"); -+ return ret; -+ } -+ } -+ -+ return lvts_debugfs_init(dev, lvts_td); -+} -+ -+static int lvts_probe(struct platform_device *pdev) -+{ -+ const struct lvts_data *lvts_data; -+ struct lvts_domain *lvts_td; -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ int irq, ret; -+ -+ lvts_td = devm_kzalloc(dev, sizeof(*lvts_td), GFP_KERNEL); -+ if (!lvts_td) -+ return -ENOMEM; -+ -+ lvts_data = of_device_get_match_data(dev); -+ -+ lvts_td->clk = devm_clk_get_enabled(dev, NULL); -+ if (IS_ERR(lvts_td->clk)) -+ return dev_err_probe(dev, PTR_ERR(lvts_td->clk), "Failed to retrieve clock\n"); -+ -+ res = platform_get_mem_or_io(pdev, 0); -+ if (!res) -+ return dev_err_probe(dev, (-ENXIO), "No IO resource\n"); -+ -+ lvts_td->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(lvts_td->base)) -+ return dev_err_probe(dev, PTR_ERR(lvts_td->base), "Failed to map io resource\n"); -+ -+ lvts_td->reset = devm_reset_control_get_by_index(dev, 0); -+ if (IS_ERR(lvts_td->reset)) -+ return dev_err_probe(dev, PTR_ERR(lvts_td->reset), "Failed to get reset control\n"); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return dev_err_probe(dev, irq, "No irq resource\n"); -+ -+ ret = lvts_domain_init(dev, lvts_td, lvts_data); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); -+ -+ /* -+ * At this point the LVTS is initialized and enabled. We can -+ * safely enable the interrupt. -+ */ -+ ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler, -+ IRQF_ONESHOT, dev_name(dev), lvts_td); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to request interrupt\n"); -+ -+ platform_set_drvdata(pdev, lvts_td); -+ -+ return 0; -+} -+ -+static int lvts_remove(struct platform_device *pdev) -+{ -+ struct lvts_domain *lvts_td; -+ int i; -+ -+ lvts_td = platform_get_drvdata(pdev); -+ -+ for (i = 0; i < lvts_td->num_lvts_ctrl; i++) -+ lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); -+ -+ lvts_debugfs_exit(lvts_td); -+ -+ return 0; -+} -+ -+static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = { -+ { -+ .cal_offset = { 0x04, 0x07 }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_MCU_BIG_CPU0 }, -+ { .dt_id = MT8195_MCU_BIG_CPU1 } -+ }, -+ .num_lvts_sensor = 2, -+ .offset = 0x0, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ }, -+ { -+ .cal_offset = { 0x0d, 0x10 }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_MCU_BIG_CPU2 }, -+ { .dt_id = MT8195_MCU_BIG_CPU3 } -+ }, -+ .num_lvts_sensor = 2, -+ .offset = 0x100, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ }, -+ { -+ .cal_offset = { 0x16, 0x19, 0x1c, 0x1f }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_MCU_LITTLE_CPU0 }, -+ { .dt_id = MT8195_MCU_LITTLE_CPU1 }, -+ { .dt_id = MT8195_MCU_LITTLE_CPU2 }, -+ { .dt_id = MT8195_MCU_LITTLE_CPU3 } -+ }, -+ .num_lvts_sensor = 4, -+ .offset = 0x200, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ } -+}; -+ -+static const struct lvts_data mt8195_lvts_mcu_data = { -+ .lvts_ctrl = mt8195_lvts_data_ctrl, -+ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_data_ctrl), -+}; -+ -+static const struct of_device_id lvts_of_match[] = { -+ { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, lvts_of_match); -+ -+static struct platform_driver lvts_driver = { -+ .probe = lvts_probe, -+ .remove = lvts_remove, -+ .driver = { -+ .name = "mtk-lvts-thermal", -+ .of_match_table = lvts_of_match, -+ }, -+}; -+module_platform_driver(lvts_driver); -+ -+MODULE_AUTHOR("Balsam CHIHI "); -+MODULE_DESCRIPTION("MediaTek LVTS Thermal Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch b/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch deleted file mode 100644 index b6a5f64090..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 498e2f7a6e69dcbca24715de2b4b97569fdfeff4 Mon Sep 17 00:00:00 2001 -From: Balsam CHIHI -Date: Thu, 9 Feb 2023 11:56:24 +0100 -Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal controllers - -Add LVTS thermal controllers dt-binding definition for mt8192 and mt8195. - -Signed-off-by: Balsam CHIHI -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/20230209105628.50294-3-bchihi@baylibre.com -Signed-off-by: Daniel Lezcano -Signed-off-by: Rafael J. Wysocki ---- - .../thermal/mediatek,lvts-thermal.yaml | 142 ++++++++++++++++++ - .../thermal/mediatek,lvts-thermal.h | 19 +++ - 2 files changed, 161 insertions(+) - create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml - create mode 100644 include/dt-bindings/thermal/mediatek,lvts-thermal.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml -@@ -0,0 +1,142 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/thermal/mediatek,lvts-thermal.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MediaTek SoC Low Voltage Thermal Sensor (LVTS) -+ -+maintainers: -+ - Balsam CHIHI -+ -+description: | -+ LVTS is a thermal management architecture composed of three subsystems, -+ a Sensing device - Thermal Sensing Micro Circuit Unit (TSMCU), -+ a Converter - Low Voltage Thermal Sensor converter (LVTS), and -+ a Digital controller (LVTS_CTRL). -+ -+properties: -+ compatible: -+ enum: -+ - mediatek,mt8192-lvts-ap -+ - mediatek,mt8192-lvts-mcu -+ - mediatek,mt8195-lvts-ap -+ - mediatek,mt8195-lvts-mcu -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 1 -+ -+ resets: -+ maxItems: 1 -+ description: LVTS reset for clearing temporary data on AP/MCU. -+ -+ nvmem-cells: -+ minItems: 1 -+ items: -+ - description: Calibration eFuse data 1 for LVTS -+ - description: Calibration eFuse data 2 for LVTS -+ -+ nvmem-cell-names: -+ minItems: 1 -+ items: -+ - const: lvts-calib-data-1 -+ - const: lvts-calib-data-2 -+ -+ "#thermal-sensor-cells": -+ const: 1 -+ -+allOf: -+ - $ref: thermal-sensor.yaml# -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ enum: -+ - mediatek,mt8192-lvts-ap -+ - mediatek,mt8192-lvts-mcu -+ then: -+ properties: -+ nvmem-cells: -+ maxItems: 1 -+ -+ nvmem-cell-names: -+ maxItems: 1 -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ enum: -+ - mediatek,mt8195-lvts-ap -+ - mediatek,mt8195-lvts-mcu -+ then: -+ properties: -+ nvmem-cells: -+ minItems: 2 -+ -+ nvmem-cell-names: -+ minItems: 2 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - resets -+ - nvmem-cells -+ - nvmem-cell-names -+ - "#thermal-sensor-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ #include -+ -+ soc { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ lvts_mcu: thermal-sensor@11278000 { -+ compatible = "mediatek,mt8195-lvts-mcu"; -+ reg = <0 0x11278000 0 0x1000>; -+ interrupts = ; -+ clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; -+ resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>; -+ nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>; -+ nvmem-cell-names = "lvts-calib-data-1", "lvts-calib-data-2"; -+ #thermal-sensor-cells = <1>; -+ }; -+ }; -+ -+ thermal_zones: thermal-zones { -+ cpu0-thermal { -+ polling-delay = <1000>; -+ polling-delay-passive = <250>; -+ thermal-sensors = <&lvts_mcu MT8195_MCU_LITTLE_CPU0>; -+ -+ trips { -+ cpu0_alert: trip-alert { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu0_crit: trip-crit { -+ temperature = <100000>; -+ hysteresis = <2000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h -@@ -0,0 +1,19 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2023 MediaTek Inc. -+ * Author: Balsam CHIHI -+ */ -+ -+#ifndef __MEDIATEK_LVTS_DT_H -+#define __MEDIATEK_LVTS_DT_H -+ -+#define MT8195_MCU_BIG_CPU0 0 -+#define MT8195_MCU_BIG_CPU1 1 -+#define MT8195_MCU_BIG_CPU2 2 -+#define MT8195_MCU_BIG_CPU3 3 -+#define MT8195_MCU_LITTLE_CPU0 4 -+#define MT8195_MCU_LITTLE_CPU1 5 -+#define MT8195_MCU_LITTLE_CPU2 6 -+#define MT8195_MCU_LITTLE_CPU3 7 -+ -+#endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch deleted file mode 100644 index efb0d8b64f..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 05aaa7fdb0736262e224369b9b9f1410320fc71b Mon Sep 17 00:00:00 2001 -From: Balsam CHIHI -Date: Tue, 7 Mar 2023 16:45:21 +0100 -Subject: [PATCH] dt-bindings: thermal: mediatek: Add AP domain to LVTS thermal - controllers for mt8195 - -Add AP Domain to LVTS thermal controllers dt-binding definition for mt8195. - -Signed-off-by: Balsam CHIHI -Acked-by: Rob Herring -Reviewed-by: AngeloGioacchino Del Regno -Tested-by: Chen-Yu Tsai -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230307154524.118541-2-bchihi@baylibre.com ---- - include/dt-bindings/thermal/mediatek,lvts-thermal.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h -+++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h -@@ -16,4 +16,14 @@ - #define MT8195_MCU_LITTLE_CPU2 6 - #define MT8195_MCU_LITTLE_CPU3 7 - -+#define MT8195_AP_VPU0 8 -+#define MT8195_AP_VPU1 9 -+#define MT8195_AP_GPU0 10 -+#define MT8195_AP_GPU1 11 -+#define MT8195_AP_VDEC 12 -+#define MT8195_AP_IMG 13 -+#define MT8195_AP_INFRA 14 -+#define MT8195_AP_CAM0 15 -+#define MT8195_AP_CAM1 16 -+ - #endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch b/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch deleted file mode 100644 index c68969321e..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch +++ /dev/null @@ -1,65 +0,0 @@ -From a6ff3c0021468721b96e84892a8cae24bde8d65f Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:29 +0100 -Subject: [PATCH] thermal/core: Add a thermal zone 'devdata' accessor - -The thermal zone device structure is exposed to the different drivers -and obviously they access the internals while that should be -restricted to the core thermal code. - -In order to self-encapsulate the thermal core code, we need to prevent -the drivers accessing directly the thermal zone structure and provide -accessor functions to deal with. - -Provide an accessor to the 'devdata' structure and make use of it in -the different drivers. - -No functional changes intended. - -Signed-off-by: Daniel Lezcano -Acked-by: Rafael J. Wysocki -Acked-by: Mark Brown -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/thermal_core.c | 6 ++++++ - include/linux/thermal.h | 7 +++++++ - 2 files changed, 13 insertions(+) - ---- a/drivers/thermal/thermal_core.c -+++ b/drivers/thermal/thermal_core.c -@@ -1346,6 +1346,12 @@ struct thermal_zone_device *thermal_zone - } - EXPORT_SYMBOL_GPL(thermal_zone_device_register); - -+void *thermal_zone_device_priv(struct thermal_zone_device *tzd) -+{ -+ return tzd->devdata; -+} -+EXPORT_SYMBOL_GPL(thermal_zone_device_priv); -+ - /** - * thermal_zone_device_unregister - removes the registered thermal zone device - * @tz: the thermal zone device to remove ---- a/include/linux/thermal.h -+++ b/include/linux/thermal.h -@@ -346,6 +346,8 @@ thermal_zone_device_register_with_trips( - void *, struct thermal_zone_device_ops *, - struct thermal_zone_params *, int, int); - -+void *thermal_zone_device_priv(struct thermal_zone_device *tzd); -+ - int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, - struct thermal_cooling_device *, - unsigned long, unsigned long, -@@ -417,6 +419,11 @@ static inline int thermal_zone_get_offse - struct thermal_zone_device *tz) - { return -ENODEV; } - -+static inline void *thermal_zone_device_priv(struct thermal_zone_device *tz) -+{ -+ return NULL; -+} -+ - static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) - { return -ENODEV; } - diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch deleted file mode 100644 index 66d3c9e302..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 072e35c98806100182c0a7263cf4cba09ce43463 Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:38 +0100 -Subject: [PATCH] thermal/core: Add thermal_zone_device structure 'type' - accessor - -The thermal zone device structure is exposed via the exported -thermal.h header. This structure should stay private the thermal core -code. In order to encapsulate the structure, let's add an accessor to -get the 'type' of the thermal zone. - -Signed-off-by: Daniel Lezcano -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/thermal_core.c | 6 ++++++ - include/linux/thermal.h | 6 ++++++ - 2 files changed, 12 insertions(+) - ---- a/drivers/thermal/thermal_core.c -+++ b/drivers/thermal/thermal_core.c -@@ -1352,6 +1352,12 @@ void *thermal_zone_device_priv(struct th - } - EXPORT_SYMBOL_GPL(thermal_zone_device_priv); - -+const char *thermal_zone_device_type(struct thermal_zone_device *tzd) -+{ -+ return tzd->type; -+} -+EXPORT_SYMBOL_GPL(thermal_zone_device_type); -+ - /** - * thermal_zone_device_unregister - removes the registered thermal zone device - * @tz: the thermal zone device to remove ---- a/include/linux/thermal.h -+++ b/include/linux/thermal.h -@@ -347,6 +347,7 @@ thermal_zone_device_register_with_trips( - struct thermal_zone_params *, int, int); - - void *thermal_zone_device_priv(struct thermal_zone_device *tzd); -+const char *thermal_zone_device_type(struct thermal_zone_device *tzd); - - int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, - struct thermal_cooling_device *, -@@ -423,6 +424,11 @@ static inline void *thermal_zone_device_ - { - return NULL; - } -+ -+static inline const char *thermal_zone_device_type(struct thermal_zone_device *tzd) -+{ -+ return NULL; -+} - - static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) - { return -ENODEV; } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch b/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch deleted file mode 100644 index 57bc910d3e..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 7d78bab533eb9aa0e5240e25a204e8f416723ed6 Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:30 +0100 -Subject: [PATCH 07/42] thermal/core: Use the thermal zone 'devdata' accessor - in thermal located drivers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The thermal zone device structure is exposed to the different drivers -and obviously they access the internals while that should be -restricted to the core thermal code. - -In order to self-encapsulate the thermal core code, we need to prevent -the drivers accessing directly the thermal zone structure and provide -accessor functions to deal with. - -Use the devdata accessor introduced in the previous patch. - -No functional changes intended. - -[skipped drivers not relevant for mediatek target] - -Signed-off-by: Daniel Lezcano -Reviewed-by: Niklas Söderlund #R-Car -Acked-by: Mark Brown -Reviewed-by: AngeloGioacchino Del Regno #MediaTek auxadc and lvts -Reviewed-by: Balsam CHIHI #Mediatek lvts -Reviewed-by: Adam Ward #da9062 -Reviewed-by: Baolin Wang #spread -Acked-by: Jernej Skrabec #sun8i_thermal -Acked-by: Rafael J. Wysocki -Acked-by: Florian Fainelli #Broadcom -Reviewed-by: Dhruva Gole # K3 bandgap -Acked-by: Linus Walleij -Acked-by: Heiko Stuebner #rockchip -Reviewed-by: Kunihiko Hayashi #uniphier -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/mediatek/auxadc_thermal.c | 2 +- - drivers/thermal/mediatek/lvts_thermal.c | 4 ++-- - 43 files changed, 71 insertions(+), 73 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -763,7 +763,7 @@ static int mtk_thermal_bank_temperature( - - static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) - { -- struct mtk_thermal *mt = tz->devdata; -+ struct mtk_thermal *mt = thermal_zone_device_priv(tz); - int i; - int tempmax = INT_MIN; - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -252,7 +252,7 @@ static u32 lvts_temp_to_raw(int temperat - - static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) - { -- struct lvts_sensor *lvts_sensor = tz->devdata; -+ struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); - void __iomem *msr = lvts_sensor->msr; - u32 value; - -@@ -290,7 +290,7 @@ static int lvts_get_temp(struct thermal_ - - static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) - { -- struct lvts_sensor *lvts_sensor = tz->devdata; -+ struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); - void __iomem *base = lvts_sensor->base; - u32 raw_low = lvts_temp_to_raw(low); - u32 raw_high = lvts_temp_to_raw(high); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch b/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch deleted file mode 100644 index 647b3b0eca..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch +++ /dev/null @@ -1,201 +0,0 @@ -From cc9c60e9cfeeac45d63361fa8c085c43c4bdfe3a Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:36 +0100 -Subject: [PATCH 08/42] thermal/hwmon: Use the right device for - devm_thermal_add_hwmon_sysfs() - -The devres variant of thermal_add_hwmon_sysfs() only takes the thermal -zone structure pointer as parameter. - -Actually, it uses the tz->device to add it in the devres list. - -It is preferable to use the device registering the thermal zone -instead of the thermal zone device itself. That prevents the driver -accessing the thermal zone structure internals and it is from my POV -more correct regarding how devm_ is used. - -[skipped imx thermal which did not apply cleanly and irrelevant on -mediatek target] - -Signed-off-by: Daniel Lezcano -Acked-by: Martin Blumenstingl #amlogic_thermal -Acked-by: Jernej Skrabec #sun8i_thermal -Reviewed-by: AngeloGioacchino Del Regno #MediaTek auxadc -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/amlogic_thermal.c | 2 +- - drivers/thermal/imx_sc_thermal.c | 2 +- - drivers/thermal/k3_bandgap.c | 2 +- - drivers/thermal/mediatek/auxadc_thermal.c | 2 +- - drivers/thermal/qcom/qcom-spmi-adc-tm5.c | 2 +- - drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 2 +- - drivers/thermal/qcom/tsens.c | 2 +- - drivers/thermal/qoriq_thermal.c | 2 +- - drivers/thermal/sun8i_thermal.c | 2 +- - drivers/thermal/tegra/tegra30-tsensor.c | 2 +- - drivers/thermal/thermal_hwmon.c | 4 ++-- - drivers/thermal/thermal_hwmon.h | 4 ++-- - drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- - 13 files changed, 15 insertions(+), 15 deletions(-) - ---- a/drivers/thermal/amlogic_thermal.c -+++ b/drivers/thermal/amlogic_thermal.c -@@ -286,7 +286,7 @@ static int amlogic_thermal_probe(struct - return ret; - } - -- if (devm_thermal_add_hwmon_sysfs(pdata->tzd)) -+ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd)) - dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n"); - - ret = amlogic_thermal_initialize(pdata); ---- a/drivers/thermal/imx_sc_thermal.c -+++ b/drivers/thermal/imx_sc_thermal.c -@@ -120,7 +120,7 @@ static int imx_sc_thermal_probe(struct p - return ret; - } - -- if (devm_thermal_add_hwmon_sysfs(sensor->tzd)) -+ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd)) - dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n"); - } - ---- a/drivers/thermal/k3_bandgap.c -+++ b/drivers/thermal/k3_bandgap.c -@@ -222,7 +222,7 @@ static int k3_bandgap_probe(struct platf - goto err_alloc; - } - -- if (devm_thermal_add_hwmon_sysfs(data[id].tzd)) -+ if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd)) - dev_warn(dev, "Failed to add hwmon sysfs attributes\n"); - } - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1210,7 +1210,7 @@ static int mtk_thermal_probe(struct plat - goto err_disable_clk_peri_therm; - } - -- ret = devm_thermal_add_hwmon_sysfs(tzdev); -+ ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev); - if (ret) - dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); - ---- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c -+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c -@@ -688,7 +688,7 @@ static int adc_tm5_register_tzd(struct a - return PTR_ERR(tzd); - } - adc_tm->channels[i].tzd = tzd; -- if (devm_thermal_add_hwmon_sysfs(tzd)) -+ if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd)) - dev_warn(adc_tm->dev, - "Failed to add hwmon sysfs attributes\n"); - } ---- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c -+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c -@@ -460,7 +460,7 @@ static int qpnp_tm_probe(struct platform - return ret; - } - -- if (devm_thermal_add_hwmon_sysfs(chip->tz_dev)) -+ if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev)) - dev_warn(&pdev->dev, - "Failed to add hwmon sysfs attributes\n"); - ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -1056,7 +1056,7 @@ static int tsens_register(struct tsens_p - if (priv->ops->enable) - priv->ops->enable(priv, i); - -- if (devm_thermal_add_hwmon_sysfs(tzd)) -+ if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd)) - dev_warn(priv->dev, - "Failed to add hwmon sysfs attributes\n"); - } ---- a/drivers/thermal/qoriq_thermal.c -+++ b/drivers/thermal/qoriq_thermal.c -@@ -158,7 +158,7 @@ static int qoriq_tmu_register_tmu_zone(s - return ret; - } - -- if (devm_thermal_add_hwmon_sysfs(tzd)) -+ if (devm_thermal_add_hwmon_sysfs(dev, tzd)) - dev_warn(dev, - "Failed to add hwmon sysfs attributes\n"); - ---- a/drivers/thermal/sun8i_thermal.c -+++ b/drivers/thermal/sun8i_thermal.c -@@ -468,7 +468,7 @@ static int sun8i_ths_register(struct ths - if (IS_ERR(tmdev->sensor[i].tzd)) - return PTR_ERR(tmdev->sensor[i].tzd); - -- if (devm_thermal_add_hwmon_sysfs(tmdev->sensor[i].tzd)) -+ if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd)) - dev_warn(tmdev->dev, - "Failed to add hwmon sysfs attributes\n"); - } ---- a/drivers/thermal/tegra/tegra30-tsensor.c -+++ b/drivers/thermal/tegra/tegra30-tsensor.c -@@ -530,7 +530,7 @@ static int tegra_tsensor_register_channe - return 0; - } - -- if (devm_thermal_add_hwmon_sysfs(tsc->tzd)) -+ if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd)) - dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n"); - - return 0; ---- a/drivers/thermal/thermal_hwmon.c -+++ b/drivers/thermal/thermal_hwmon.c -@@ -255,7 +255,7 @@ static void devm_thermal_hwmon_release(s - thermal_remove_hwmon_sysfs(*(struct thermal_zone_device **)res); - } - --int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) -+int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz) - { - struct thermal_zone_device **ptr; - int ret; -@@ -272,7 +272,7 @@ int devm_thermal_add_hwmon_sysfs(struct - } - - *ptr = tz; -- devres_add(&tz->device, ptr); -+ devres_add(dev, ptr); - - return ret; - } ---- a/drivers/thermal/thermal_hwmon.h -+++ b/drivers/thermal/thermal_hwmon.h -@@ -17,7 +17,7 @@ - - #ifdef CONFIG_THERMAL_HWMON - int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz); --int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz); -+int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz); - void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz); - #else - static inline int -@@ -27,7 +27,7 @@ thermal_add_hwmon_sysfs(struct thermal_z - } - - static inline int --devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) -+devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz) - { - return 0; - } ---- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -@@ -182,7 +182,7 @@ int ti_thermal_expose_sensor(struct ti_b - ti_bandgap_set_sensor_data(bgp, id, data); - ti_bandgap_write_update_interval(bgp, data->sensor_id, interval); - -- if (devm_thermal_add_hwmon_sysfs(data->ti_thermal)) -+ if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal)) - dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n"); - - return 0; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch b/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch deleted file mode 100644 index 9dedc2cb68..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 5a72b8e4bac753e4dc74dc0a1335d120f63df97a Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:37 +0100 -Subject: [PATCH 09/42] thermal: Don't use 'device' internal thermal zone - structure field - -Some drivers are directly using the thermal zone's 'device' structure -field. - -Use the driver device pointer instead of the thermal zone device when -it is available. - -Remove the traces when they are duplicate with the traces in the core -code. - -[again skipped imx_thermal.c] - -Cc: Jean Delvare -Cc: Guenter Roeck -Signed-off-by: Daniel Lezcano -Reviewed-by: Balsam CHIHI #Mediatek LVTS -Reviewed-by: AngeloGioacchino Del Regno #MediaTek LVTS -Signed-off-by: Rafael J. Wysocki ---- - drivers/thermal/mediatek/lvts_thermal.c | 4 ++-- - drivers/thermal/thermal_hwmon.c | 4 ++-- - drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- - 3 files changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -305,7 +305,7 @@ static int lvts_set_trips(struct thermal - * 14-0 : Raw temperature for threshold - */ - if (low != -INT_MAX) { -- dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low); -+ pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low); - writel(raw_low, LVTS_H2NTHRE(base)); - } - -@@ -318,7 +318,7 @@ static int lvts_set_trips(struct thermal - * - * 14-0 : Raw temperature for threshold - */ -- dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high); -+ pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high); - writel(raw_high, LVTS_HTHRE(base)); - - return 0; ---- a/drivers/thermal/thermal_hwmon.c -+++ b/drivers/thermal/thermal_hwmon.c -@@ -220,14 +220,14 @@ void thermal_remove_hwmon_sysfs(struct t - hwmon = thermal_hwmon_lookup_by_type(tz); - if (unlikely(!hwmon)) { - /* Should never happen... */ -- dev_dbg(&tz->device, "hwmon device lookup failed!\n"); -+ dev_dbg(hwmon->device, "hwmon device lookup failed!\n"); - return; - } - - temp = thermal_hwmon_lookup_temp(hwmon, tz); - if (unlikely(!temp)) { - /* Should never happen... */ -- dev_dbg(&tz->device, "temperature input lookup failed!\n"); -+ dev_dbg(hwmon->device, "temperature input lookup failed!\n"); - return; - } - ---- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -@@ -43,7 +43,7 @@ static void ti_thermal_work(struct work_ - - thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED); - -- dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n", -+ dev_dbg(data->bgp->dev, "updated thermal zone %s\n", - data->ti_thermal->type); - } - diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch b/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch deleted file mode 100644 index 8cec9aba97..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 66b3a292d3fc749e8ec7ac5278a17e8a5757ecbc Mon Sep 17 00:00:00 2001 -From: Daniel Lezcano -Date: Wed, 1 Mar 2023 21:14:41 +0100 -Subject: [PATCH 10/42] thermal: Use thermal_zone_device_type() accessor - -Replace the accesses to 'tz->type' by its accessor version in order to -self-encapsulate the thermal_zone_device structure. - -Signed-off-by: Daniel Lezcano -Reviewed-by: Ido Schimmel #mlxsw -Reviewed-by: AngeloGioacchino Del Regno #MediaTek LVTS -Signed-off-by: Rafael J. Wysocki ---- - drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 2 +- - drivers/thermal/mediatek/lvts_thermal.c | 6 ++++-- - drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- - 3 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c -@@ -168,7 +168,7 @@ mlxsw_thermal_module_trips_update(struct - - if (crit_temp > emerg_temp) { - dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n", -- tz->tzdev->type, crit_temp, emerg_temp); -+ thermal_zone_device_type(tz->tzdev), crit_temp, emerg_temp); - return 0; - } - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -305,7 +305,8 @@ static int lvts_set_trips(struct thermal - * 14-0 : Raw temperature for threshold - */ - if (low != -INT_MAX) { -- pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low); -+ pr_debug("%s: Setting low limit temperature interrupt: %d\n", -+ thermal_zone_device_type(tz), low); - writel(raw_low, LVTS_H2NTHRE(base)); - } - -@@ -318,7 +319,8 @@ static int lvts_set_trips(struct thermal - * - * 14-0 : Raw temperature for threshold - */ -- pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high); -+ pr_debug("%s: Setting high limit temperature interrupt: %d\n", -+ thermal_zone_device_type(tz), high); - writel(raw_high, LVTS_HTHRE(base)); - - return 0; ---- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c -@@ -44,7 +44,7 @@ static void ti_thermal_work(struct work_ - thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED); - - dev_dbg(data->bgp->dev, "updated thermal zone %s\n", -- data->ti_thermal->type); -+ thermal_zone_device_type(data->ti_thermal)); - } - - /** diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch deleted file mode 100644 index 68f41fdd16..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch +++ /dev/null @@ -1,81 +0,0 @@ -From f6658c1c4ae98477d6be00495226c0617354fe76 Mon Sep 17 00:00:00 2001 -From: Markus Schneider-Pargmann -Date: Fri, 27 Jan 2023 16:44:43 +0100 -Subject: [PATCH 11/42] thermal/drivers/mediatek: Control buffer enablement - tweaks - -Add logic in order to be able to turn on the control buffer on MT8365. -This change now allows to have control buffer support for MTK_THERMAL_V1, -and it allows to define the register offset, and mask used to enable it. - -Signed-off-by: Markus Schneider-Pargmann -Signed-off-by: Fabien Parent -Signed-off-by: Amjad Ouled-Ameur -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-2-55a1ae14af74@baylibre.com -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mediatek/auxadc_thermal.c | 28 +++++++++++++++-------- - 1 file changed, 19 insertions(+), 9 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -307,6 +307,9 @@ struct mtk_thermal_data { - bool need_switch_bank; - struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; - enum mtk_thermal_version version; -+ u32 apmixed_buffer_ctl_reg; -+ u32 apmixed_buffer_ctl_mask; -+ u32 apmixed_buffer_ctl_set; - }; - - struct mtk_thermal { -@@ -560,6 +563,9 @@ static const struct mtk_thermal_data mt7 - .adcpnp = mt7622_adcpnp, - .sensor_mux_values = mt7622_mux_values, - .version = MTK_THERMAL_V2, -+ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1, -+ .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3), -+ .apmixed_buffer_ctl_set = BIT(0), - }; - - /* -@@ -1079,14 +1085,18 @@ static const struct of_device_id mtk_the - }; - MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); - --static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) -+static void mtk_thermal_turn_on_buffer(struct mtk_thermal *mt, -+ void __iomem *apmixed_base) - { -- int tmp; -+ u32 tmp; -+ -+ if (!mt->conf->apmixed_buffer_ctl_reg) -+ return; - -- tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); -- tmp &= ~(0x37); -- tmp |= 0x1; -- writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); -+ tmp = readl(apmixed_base + mt->conf->apmixed_buffer_ctl_reg); -+ tmp &= mt->conf->apmixed_buffer_ctl_mask; -+ tmp |= mt->conf->apmixed_buffer_ctl_set; -+ writel(tmp, apmixed_base + mt->conf->apmixed_buffer_ctl_reg); - udelay(200); - } - -@@ -1184,10 +1194,10 @@ static int mtk_thermal_probe(struct plat - goto err_disable_clk_auxadc; - } - -- if (mt->conf->version != MTK_THERMAL_V1) { -- mtk_thermal_turn_on_buffer(apmixed_base); -+ mtk_thermal_turn_on_buffer(mt, apmixed_base); -+ -+ if (mt->conf->version != MTK_THERMAL_V2) - mtk_thermal_release_periodic_ts(mt, auxadc_base); -- } - - if (mt->conf->version == MTK_THERMAL_V1) - mt->raw_to_mcelsius = raw_to_mcelsius_v1; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch b/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch deleted file mode 100644 index 285c6f6a7b..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch +++ /dev/null @@ -1,123 +0,0 @@ -From c4eff784465f88218dc5eb51320320464db83d3f Mon Sep 17 00:00:00 2001 -From: Fabien Parent -Date: Fri, 27 Jan 2023 16:44:44 +0100 -Subject: [PATCH 12/42] thermal/drivers/mediatek: Add support for MT8365 SoC - -MT8365 is similar to the other SoCs supported by the driver. It has only -one bank and 3 actual sensors that can be multiplexed. There is another -one sensor that does not have usable data. - -Signed-off-by: Fabien Parent -Signed-off-by: Amjad Ouled-Ameur -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-3-55a1ae14af74@baylibre.com -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mediatek/auxadc_thermal.c | 68 +++++++++++++++++++++++ - 1 file changed, 68 insertions(+) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -31,6 +31,7 @@ - #define AUXADC_CON2_V 0x010 - #define AUXADC_DATA(channel) (0x14 + (channel) * 4) - -+#define APMIXED_SYS_TS_CON0 0x600 - #define APMIXED_SYS_TS_CON1 0x604 - - /* Thermal Controller Registers */ -@@ -281,6 +282,17 @@ enum mtk_thermal_version { - /* The calibration coefficient of sensor */ - #define MT7986_CALIBRATION 165 - -+/* MT8365 */ -+#define MT8365_TEMP_AUXADC_CHANNEL 11 -+#define MT8365_CALIBRATION 164 -+#define MT8365_NUM_CONTROLLER 1 -+#define MT8365_NUM_BANKS 1 -+#define MT8365_NUM_SENSORS 3 -+#define MT8365_NUM_SENSORS_PER_ZONE 3 -+#define MT8365_TS1 0 -+#define MT8365_TS2 1 -+#define MT8365_TS3 2 -+ - struct mtk_thermal; - - struct thermal_bank_cfg { -@@ -435,6 +447,24 @@ static const int mt7986_mux_values[MT798 - static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; - static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; - -+/* MT8365 thermal sensor data */ -+static const int mt8365_bank_data[MT8365_NUM_SENSORS] = { -+ MT8365_TS1, MT8365_TS2, MT8365_TS3 -+}; -+ -+static const int mt8365_msr[MT8365_NUM_SENSORS_PER_ZONE] = { -+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2 -+}; -+ -+static const int mt8365_adcpnp[MT8365_NUM_SENSORS_PER_ZONE] = { -+ TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2 -+}; -+ -+static const int mt8365_mux_values[MT8365_NUM_SENSORS] = { 0, 1, 2 }; -+static const int mt8365_tc_offset[MT8365_NUM_CONTROLLER] = { 0 }; -+ -+static const int mt8365_vts_index[MT8365_NUM_SENSORS] = { VTS1, VTS2, VTS3 }; -+ - /* - * The MT8173 thermal controller has four banks. Each bank can read up to - * four temperature sensors simultaneously. The MT8173 has a total of 5 -@@ -510,6 +540,40 @@ static const struct mtk_thermal_data mt2 - }; - - /* -+ * The MT8365 thermal controller has one bank, which can read up to -+ * four temperature sensors simultaneously. The MT8365 has a total of 3 -+ * temperature sensors. -+ * -+ * The thermal core only gets the maximum temperature of this one bank, -+ * so the bank concept wouldn't be necessary here. However, the SVS (Smart -+ * Voltage Scaling) unit makes its decisions based on the same bank -+ * data. -+ */ -+static const struct mtk_thermal_data mt8365_thermal_data = { -+ .auxadc_channel = MT8365_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT8365_NUM_BANKS, -+ .num_sensors = MT8365_NUM_SENSORS, -+ .vts_index = mt8365_vts_index, -+ .cali_val = MT8365_CALIBRATION, -+ .num_controller = MT8365_NUM_CONTROLLER, -+ .controller_offset = mt8365_tc_offset, -+ .need_switch_bank = false, -+ .bank_data = { -+ { -+ .num_sensors = MT8365_NUM_SENSORS, -+ .sensors = mt8365_bank_data -+ }, -+ }, -+ .msr = mt8365_msr, -+ .adcpnp = mt8365_adcpnp, -+ .sensor_mux_values = mt8365_mux_values, -+ .version = MTK_THERMAL_V1, -+ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON0, -+ .apmixed_buffer_ctl_mask = (u32) ~GENMASK(29, 28), -+ .apmixed_buffer_ctl_set = 0, -+}; -+ -+/* - * The MT2712 thermal controller has one bank, which can read up to - * four temperature sensors simultaneously. The MT2712 has a total of 4 - * temperature sensors. -@@ -1080,6 +1144,10 @@ static const struct of_device_id mtk_the - { - .compatible = "mediatek,mt8183-thermal", - .data = (void *)&mt8183_thermal_data, -+ }, -+ { -+ .compatible = "mediatek,mt8365-thermal", -+ .data = (void *)&mt8365_thermal_data, - }, { - }, - }; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch b/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch deleted file mode 100644 index 5c99aa80c1..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 4eead70db74922bc61e9d0b4591524369a335751 Mon Sep 17 00:00:00 2001 -From: Amjad Ouled-Ameur -Date: Fri, 27 Jan 2023 16:44:46 +0100 -Subject: [PATCH 13/42] thermal/drivers/mediatek: Add delay after thermal banks - initialization - -Thermal sensor reads performed immediately after thermal bank -initialization returns bogus values. This is currently tackled by returning -0 if the temperature is bogus (exceeding 200000). - -Instead, add a delay between the bank init and the thermal zone device -register to properly fix this. - -Signed-off-by: Michael Kao -Signed-off-by: Hsin-Yi Wang -Signed-off-by: Amjad Ouled-Ameur -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-5-55a1ae14af74@baylibre.com -Signed-off-by: Daniel Lezcano ---- - drivers/thermal/mediatek/auxadc_thermal.c | 11 +++-------- - 1 file changed, 3 insertions(+), 8 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -816,14 +816,6 @@ static int mtk_thermal_bank_temperature( - mt, conf->bank_data[bank->id].sensors[i], raw); - - -- /* -- * The first read of a sensor often contains very high bogus -- * temperature value. Filter these out so that the system does -- * not immediately shut down. -- */ -- if (temp > 200000) -- temp = 0; -- - if (temp > max) - max = temp; - } -@@ -1281,6 +1273,9 @@ static int mtk_thermal_probe(struct plat - - platform_set_drvdata(pdev, mt); - -+ /* Delay for thermal banks to be ready */ -+ msleep(30); -+ - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); - if (IS_ERR(tzdev)) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch b/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch deleted file mode 100644 index 734f5c1e77..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch +++ /dev/null @@ -1,46 +0,0 @@ -From ad9dc9e92367803a4f9576aea0dab110d03fc510 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Tue, 28 Mar 2023 11:10:17 +0800 -Subject: [PATCH 14/42] thermal/drivers/mediatek/lvts_thermal: Fix sensor 1 - interrupt status bitmask - -The binary representation for sensor 1 interrupt status was incorrectly -assembled, when compared to the full table given in the same comment -section. The conversion into hex was also incorrect, leading to -incorrect interrupt status bitmask for sensor 1. This would cause the -driver to incorrectly identify changes for sensor 1, when in fact it -was sensor 0, or a sensor access time out. - -Fix the binary and hex representations in the comments, and the actual -bitmask macro. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Signed-off-by: Chen-Yu Tsai -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230328031017.1360976-1-wenst@chromium.org ---- - drivers/thermal/mediatek/lvts_thermal.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -66,7 +66,7 @@ - #define LVTS_MONINT_CONF 0x9FBF7BDE - - #define LVTS_INT_SENSOR0 0x0009001F --#define LVTS_INT_SENSOR1 0X000881F0 -+#define LVTS_INT_SENSOR1 0x001203E0 - #define LVTS_INT_SENSOR2 0x00247C00 - #define LVTS_INT_SENSOR3 0x1FC00000 - -@@ -395,8 +395,8 @@ static irqreturn_t lvts_ctrl_irq_handler - * => 0x1FC00000 - * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000 - * => 0x00247C00 -- * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000 -- * => 0X000881F0 -+ * sensor 1 interrupt: 0000 0000 0001 0010 0000 0011 1110 0000 -+ * => 0X001203E0 - * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111 - * => 0x0009001F - */ diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch deleted file mode 100644 index d09c2055a3..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 9aad43ad3285fc21158fb416830a6156a9a31fa5 Mon Sep 17 00:00:00 2001 -From: Balsam CHIHI -Date: Tue, 7 Mar 2023 16:45:22 +0100 -Subject: [PATCH 15/42] thermal/drivers/mediatek/lvts_thermal: Add AP domain - for mt8195 - -Add MT8195 AP Domain support to LVTS Driver. - -Take the opportunity to update the comments to show calibration data -information related to the new domain. - -[dlezcano]: Massaged a bit the changelog - -Signed-off-by: Balsam CHIHI -Tested-by: Chen-Yu Tsai -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230307154524.118541-3-bchihi@baylibre.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 94 +++++++++++++++++++------ - 1 file changed, 74 insertions(+), 20 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -530,29 +530,33 @@ static int lvts_sensor_init(struct devic - * The efuse blob values follows the sensor enumeration per thermal - * controller. The decoding of the stream is as follow: - * -- * <--?-> <----big0 ???---> <-sensor0-> <-0-> -- * ------------------------------------------ -- * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | -- * ------------------------------------------ -+ * stream index map for MCU Domain : - * -- * <--sensor1--><-0-> <----big1 ???---> <-sen -- * ------------------------------------------ -- * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | -- * ------------------------------------------ -+ * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> -+ * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 - * -- * sor0-> <-0-> <-sensor1-> <-0-> .......... -- * ------------------------------------------ -- * | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD | -- * ------------------------------------------ -+ * <-----mcu-tc#1-----> <-----sensor#2-----> <-----sensor#3-----> -+ * 0x0A | 0x0B | 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 - * -- * And so on ... -+ * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> -+ * 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 -+ * -+ * stream index map for AP Domain : -+ * -+ * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1-----> -+ * 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A -+ * -+ * <-----ap--tc#1-----> <-----sensor#2-----> <-----sensor#3-----> -+ * 0x2B | 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33 -+ * -+ * <-----ap--tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> -+ * 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F -+ * -+ * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8-----> -+ * 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 - * - * The data description gives the offset of the calibration data in - * this bytes stream for each sensor. -- * -- * Each thermal controller can handle up to 4 sensors max, we don't -- * care if there are less as the array of calibration is sized to 4 -- * anyway. The unused sensor slot will be zeroed. - */ - static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, - const struct lvts_ctrl_data *lvts_ctrl_data, -@@ -1165,7 +1169,7 @@ static int lvts_remove(struct platform_d - return 0; - } - --static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = { -+static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { - { - .cal_offset = { 0x04, 0x07 }, - .lvts_sensor = { -@@ -1200,13 +1204,63 @@ static const struct lvts_ctrl_data mt819 - } - }; - -+static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { -+ { -+ .cal_offset = { 0x25, 0x28 }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_AP_VPU0 }, -+ { .dt_id = MT8195_AP_VPU1 } -+ }, -+ .num_lvts_sensor = 2, -+ .offset = 0x0, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ }, -+ { -+ .cal_offset = { 0x2e, 0x31 }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_AP_GPU0 }, -+ { .dt_id = MT8195_AP_GPU1 } -+ }, -+ .num_lvts_sensor = 2, -+ .offset = 0x100, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ }, -+ { -+ .cal_offset = { 0x37, 0x3a, 0x3d }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_AP_VDEC }, -+ { .dt_id = MT8195_AP_IMG }, -+ { .dt_id = MT8195_AP_INFRA }, -+ }, -+ .num_lvts_sensor = 3, -+ .offset = 0x200, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ }, -+ { -+ .cal_offset = { 0x43, 0x46 }, -+ .lvts_sensor = { -+ { .dt_id = MT8195_AP_CAM0 }, -+ { .dt_id = MT8195_AP_CAM1 } -+ }, -+ .num_lvts_sensor = 2, -+ .offset = 0x300, -+ .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195, -+ } -+}; -+ - static const struct lvts_data mt8195_lvts_mcu_data = { -- .lvts_ctrl = mt8195_lvts_data_ctrl, -- .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_data_ctrl), -+ .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, -+ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), -+}; -+ -+static const struct lvts_data mt8195_lvts_ap_data = { -+ .lvts_ctrl = mt8195_lvts_ap_data_ctrl, -+ .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), - }; - - static const struct of_device_id lvts_of_match[] = { - { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, -+ { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, - {}, - }; - MODULE_DEVICE_TABLE(of, lvts_of_match); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch b/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch deleted file mode 100644 index a48ea3742b..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 7105a86760bd9e4d107075cefc75016b693a5542 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 19 Apr 2023 08:11:45 +0200 -Subject: [PATCH 16/42] Revert "thermal/drivers/mediatek: Add delay after - thermal banks initialization" - -Some more testing revealed that this commit introduces a regression on some -MT8173 Chromebooks and at least on one MT6795 Sony Xperia M5 smartphone due -to the delay being apparently variable and machine specific. - -Another solution would be to delay for a bit more (~70ms) but this is not -feasible for two reasons: first of all, we're adding an even bigger delay -in a probe function; second, some machines need less, some may need even -more, making the msleep at probe solution highly suboptimal. - -This reverts commit 10debf8c2da8011c8009dd4b3f6d0ab85891c81b. - -Fixes: 10debf8c2da8 ("thermal/drivers/mediatek: Add delay after thermal banks initialization") -Reported-by: "kernelci.org bot" -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230419061146.22246-2-angelogioacchino.delregno@collabora.com ---- - drivers/thermal/mediatek/auxadc_thermal.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -816,6 +816,14 @@ static int mtk_thermal_bank_temperature( - mt, conf->bank_data[bank->id].sensors[i], raw); - - -+ /* -+ * The first read of a sensor often contains very high bogus -+ * temperature value. Filter these out so that the system does -+ * not immediately shut down. -+ */ -+ if (temp > 200000) -+ temp = 0; -+ - if (temp > max) - max = temp; - } -@@ -1273,9 +1281,6 @@ static int mtk_thermal_probe(struct plat - - platform_set_drvdata(pdev, mt); - -- /* Delay for thermal banks to be ready */ -- msleep(30); -- - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); - if (IS_ERR(tzdev)) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch b/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch deleted file mode 100644 index aae87af5d1..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 681b652c9dfc4037d4a55b2733e091a4e1a5de18 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 19 Apr 2023 08:11:46 +0200 -Subject: [PATCH 17/42] thermal/drivers/mediatek: Add temperature constraints - to validate read -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The AUXADC thermal v1 allows reading temperature range between -20°C to -150°C and any value out of this range is invalid. - -Add new definitions for MT8173_TEMP_{MIN_MAX} and a new small helper -mtk_thermal_temp_is_valid() to check if new readings are in range: if -not, we tell to the API that the reading is invalid by returning -THERMAL_TEMP_INVALID. - -It was chosen to introduce the helper function because, even though this -temperature range is realistically ok for all, it comes from a downstream -kernel driver for version 1, but here we also support v2 and v3 which may -may have wider constraints. - -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230419061146.22246-3-angelogioacchino.delregno@collabora.com ---- - drivers/thermal/mediatek/auxadc_thermal.c | 24 +++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -116,6 +116,10 @@ - /* The calibration coefficient of sensor */ - #define MT8173_CALIBRATION 165 - -+/* Valid temperatures range */ -+#define MT8173_TEMP_MIN -20000 -+#define MT8173_TEMP_MAX 150000 -+ - /* - * Layout of the fuses providing the calibration data - * These macros could be used for MT8183, MT8173, MT2701, and MT2712. -@@ -689,6 +693,11 @@ static const struct mtk_thermal_data mt7 - .version = MTK_THERMAL_V3, - }; - -+static bool mtk_thermal_temp_is_valid(int temp) -+{ -+ return (temp >= MT8173_TEMP_MIN) && (temp <= MT8173_TEMP_MAX); -+} -+ - /** - * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius - * @mt: The thermal controller -@@ -815,14 +824,17 @@ static int mtk_thermal_bank_temperature( - temp = mt->raw_to_mcelsius( - mt, conf->bank_data[bank->id].sensors[i], raw); - -- - /* -- * The first read of a sensor often contains very high bogus -- * temperature value. Filter these out so that the system does -- * not immediately shut down. -+ * Depending on the filt/sen intervals and ADC polling time, -+ * we may need up to 60 milliseconds after initialization: this -+ * will result in the first reading containing an out of range -+ * temperature value. -+ * Validate the reading to both address the aforementioned issue -+ * and to eventually avoid bogus readings during runtime in the -+ * event that the AUXADC gets unstable due to high EMI, etc. - */ -- if (temp > 200000) -- temp = 0; -+ if (!mtk_thermal_temp_is_valid(temp)) -+ temp = THERMAL_TEMP_INVALID; - - if (temp > max) - max = temp; diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch deleted file mode 100644 index 782684aacc..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 458fa1d508de3f17e49d974a0158d9aeff273a58 Mon Sep 17 00:00:00 2001 -From: Kang Chen -Date: Wed, 19 Apr 2023 10:07:48 +0800 -Subject: [PATCH 18/42] thermal/drivers/mediatek: Use devm_of_iomap to avoid - resource leak in mtk_thermal_probe - -Smatch reports: -1. mtk_thermal_probe() warn: 'apmixed_base' from of_iomap() not released. -2. mtk_thermal_probe() warn: 'auxadc_base' from of_iomap() not released. - -The original code forgets to release iomap resource when handling errors, -fix it by switch to devm_of_iomap. - -Fixes: 89945047b166 ("thermal: mediatek: Add tsensor support for V2 thermal system") -Signed-off-by: Kang Chen -Reviewed-by: Dongliang Mu -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230419020749.621257-1-void0red@hust.edu.cn ---- - drivers/thermal/mediatek/auxadc_thermal.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1232,7 +1232,12 @@ static int mtk_thermal_probe(struct plat - return -ENODEV; - } - -- auxadc_base = of_iomap(auxadc, 0); -+ auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); -+ if (IS_ERR(auxadc_base)) { -+ of_node_put(auxadc); -+ return PTR_ERR(auxadc_base); -+ } -+ - auxadc_phys_base = of_get_phys_base(auxadc); - - of_node_put(auxadc); -@@ -1248,7 +1253,12 @@ static int mtk_thermal_probe(struct plat - return -ENODEV; - } - -- apmixed_base = of_iomap(apmixedsys, 0); -+ apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); -+ if (IS_ERR(apmixed_base)) { -+ of_node_put(apmixedsys); -+ return PTR_ERR(apmixed_base); -+ } -+ - apmixed_phys_base = of_get_phys_base(apmixedsys); - - of_node_put(apmixedsys); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch b/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch deleted file mode 100644 index d7896dbd60..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 227d1856924ec00a4f5bdf5afcf77bc7f3f04e86 Mon Sep 17 00:00:00 2001 -From: Kang Chen -Date: Wed, 19 Apr 2023 10:07:49 +0800 -Subject: [PATCH 19/42] thermal/drivers/mediatek: Change clk_prepare_enable to - devm_clk_get_enabled in mtk_thermal_probe - -Use devm_clk_get_enabled to do automatic resource management. -Meanwhile, remove error handling labels in the probe function and -the whole remove function. - -Signed-off-by: Kang Chen -Reviewed-by: Dongliang Mu -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230419020749.621257-2-void0red@hust.edu.cn ---- - drivers/thermal/mediatek/auxadc_thermal.c | 44 +++++------------------ - 1 file changed, 9 insertions(+), 35 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1206,14 +1206,6 @@ static int mtk_thermal_probe(struct plat - - mt->conf = of_device_get_match_data(&pdev->dev); - -- mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm"); -- if (IS_ERR(mt->clk_peri_therm)) -- return PTR_ERR(mt->clk_peri_therm); -- -- mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc"); -- if (IS_ERR(mt->clk_auxadc)) -- return PTR_ERR(mt->clk_auxadc); -- - mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(mt->thermal_base)) - return PTR_ERR(mt->thermal_base); -@@ -1272,16 +1264,18 @@ static int mtk_thermal_probe(struct plat - if (ret) - return ret; - -- ret = clk_prepare_enable(mt->clk_auxadc); -- if (ret) { -+ mt->clk_auxadc = devm_clk_get_enabled(&pdev->dev, "auxadc"); -+ if (IS_ERR(mt->clk_auxadc)) { -+ ret = PTR_ERR(mt->clk_auxadc); - dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret); - return ret; - } - -- ret = clk_prepare_enable(mt->clk_peri_therm); -- if (ret) { -+ mt->clk_peri_therm = devm_clk_get_enabled(&pdev->dev, "therm"); -+ if (IS_ERR(mt->clk_peri_therm)) { -+ ret = PTR_ERR(mt->clk_peri_therm); - dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret); -- goto err_disable_clk_auxadc; -+ return ret; - } - - mtk_thermal_turn_on_buffer(mt, apmixed_base); -@@ -1305,38 +1299,18 @@ static int mtk_thermal_probe(struct plat - - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); -- if (IS_ERR(tzdev)) { -- ret = PTR_ERR(tzdev); -- goto err_disable_clk_peri_therm; -- } -+ if (IS_ERR(tzdev)) -+ return PTR_ERR(tzdev); - - ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev); - if (ret) - dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs"); - - return 0; -- --err_disable_clk_peri_therm: -- clk_disable_unprepare(mt->clk_peri_therm); --err_disable_clk_auxadc: -- clk_disable_unprepare(mt->clk_auxadc); -- -- return ret; --} -- --static int mtk_thermal_remove(struct platform_device *pdev) --{ -- struct mtk_thermal *mt = platform_get_drvdata(pdev); -- -- clk_disable_unprepare(mt->clk_peri_therm); -- clk_disable_unprepare(mt->clk_auxadc); -- -- return 0; - } - - static struct platform_driver mtk_thermal_driver = { - .probe = mtk_thermal_probe, -- .remove = mtk_thermal_remove, - .driver = { - .name = "mtk-thermal", - .of_match_table = mtk_thermal_of_match, diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch b/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch deleted file mode 100644 index fd18a5365c..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 655fe2533ac05323a07c19ba079bf2064e7741af Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Sun, 19 Mar 2023 11:32:31 -0500 -Subject: [PATCH 20/42] thermal/drivers/mediatek: Use of_address_to_resource() - -Replace of_get_address() and of_translate_address() calls with single -call to of_address_to_resource(). - -Signed-off-by: Rob Herring -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230319163231.226738-1-robh@kernel.org ---- - drivers/thermal/mediatek/auxadc_thermal.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -979,14 +979,12 @@ static void mtk_thermal_init_bank(struct - - static u64 of_get_phys_base(struct device_node *np) - { -- u64 size64; -- const __be32 *regaddr_p; -+ struct resource res; - -- regaddr_p = of_get_address(np, 0, &size64, NULL); -- if (!regaddr_p) -+ if (of_address_to_resource(np, 0, &res)) - return OF_BAD_ADDR; - -- return of_translate_address(np, regaddr_p); -+ return res.start; - } - - static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch b/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch deleted file mode 100644 index c3ff17d517..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 2c380d07215e6fce3ac66cc5af059bc2c2a69f7a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo?= -Date: Thu, 25 May 2023 14:18:11 +0200 -Subject: [PATCH 21/42] Revert "thermal/drivers/mediatek: Use devm_of_iomap to - avoid resource leak in mtk_thermal_probe" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit f05c7b7d9ea9477fcc388476c6f4ade8c66d2d26. - -That change was causing a regression in the generic-adc-thermal-probed -bootrr test as reported in the kernelci-results list [1]. -A proper rework will take longer, so revert it for now. - -[1] https://groups.io/g/kernelci-results/message/42660 - -Fixes: f05c7b7d9ea9 ("thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe") -Signed-off-by: Ricardo Cañuelo -Suggested-by: AngeloGioacchino Del Regno -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230525121811.3360268-1-ricardo.canuelo@collabora.com ---- - drivers/thermal/mediatek/auxadc_thermal.c | 14 ++------------ - 1 file changed, 2 insertions(+), 12 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct plat - return -ENODEV; - } - -- auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); -- if (IS_ERR(auxadc_base)) { -- of_node_put(auxadc); -- return PTR_ERR(auxadc_base); -- } -- -+ auxadc_base = of_iomap(auxadc, 0); - auxadc_phys_base = of_get_phys_base(auxadc); - - of_node_put(auxadc); -@@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct plat - return -ENODEV; - } - -- apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); -- if (IS_ERR(apmixed_base)) { -- of_node_put(apmixedsys); -- return PTR_ERR(apmixed_base); -- } -- -+ apmixed_base = of_iomap(apmixedsys, 0); - apmixed_phys_base = of_get_phys_base(apmixedsys); - - of_node_put(apmixedsys); diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch b/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch deleted file mode 100644 index c4456529c1..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 496f4b08981d8a788ad5a2073fa1c65a2af1862b Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Tue, 13 Jun 2023 17:13:16 +0800 -Subject: [PATCH 22/42] thermal/drivers/mediatek/lvts_thermal: Register thermal - zones as hwmon sensors - -Register thermal zones as hwmon sensors to let userspace read -temperatures using standard hwmon interface. - -Signed-off-by: Chen-Yu Tsai -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230613091317.1691247-1-wenst@chromium.org ---- - drivers/thermal/mediatek/lvts_thermal.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -19,6 +19,8 @@ - #include - #include - -+#include "../thermal_hwmon.h" -+ - #define LVTS_MONCTL0(__base) (__base + 0x0000) - #define LVTS_MONCTL1(__base) (__base + 0x0004) - #define LVTS_MONCTL2(__base) (__base + 0x0008) -@@ -996,6 +998,9 @@ static int lvts_ctrl_start(struct device - return PTR_ERR(tz); - } - -+ if (devm_thermal_add_hwmon_sysfs(dev, tz)) -+ dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id); -+ - /* - * The thermal zone pointer will be needed in the - * interrupt handler, we store it in the sensor diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch b/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch deleted file mode 100644 index 22e7a954ed..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 885b9768ce2a66ed5d250822aed53d5114c895da Mon Sep 17 00:00:00 2001 -From: Yangtao Li -Date: Tue, 20 Jun 2023 17:07:31 +0800 -Subject: [PATCH 23/42] thermal/drivers/mediatek/lvts_thermal: Remove redundant - msg in lvts_ctrl_start() - -The upper-layer devm_thermal_add_hwmon_sysfs() function can directly -print error information. - -Signed-off-by: Yangtao Li -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230620090732.50025-10-frank.li@vivo.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -998,8 +998,7 @@ static int lvts_ctrl_start(struct device - return PTR_ERR(tz); - } - -- if (devm_thermal_add_hwmon_sysfs(dev, tz)) -- dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id); -+ devm_thermal_add_hwmon_sysfs(dev, tz); - - /* - * The thermal zone pointer will be needed in the diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch deleted file mode 100644 index bc67727423..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 27b389d9f62c2174f95fe4002b11e77d4cb3ce80 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:32 -0400 -Subject: [PATCH 25/42] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on - all controllers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There is a single IRQ handler for each LVTS thermal domain, and it is -supposed to check each of its underlying controllers for the origin of -the interrupt and clear its status. However due to a typo, only the -first controller was ever being handled, which resulted in the interrupt -never being cleared when it happened on the other controllers. Add the -missing index so interrupts are handled for all controllers. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Reviewed-by: Matthias Brugger -Reviewed-by: AngeloGioacchino Del Regno -Tested-by: Chen-Yu Tsai -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-2-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -451,7 +451,7 @@ static irqreturn_t lvts_irq_handler(int - - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { - -- aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); -+ aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]); - if (aux != IRQ_HANDLED) - continue; - diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch deleted file mode 100644 index 51d119c05b..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 6d827142643ee10c13ff9a1d90f38fb399aa9fff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:33 -0400 -Subject: [PATCH 26/42] thermal/drivers/mediatek/lvts_thermal: Honor sensors in - immediate mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Each controller can be configured to operate on immediate or filtered -mode. On filtered mode, the sensors are enabled by setting the -corresponding bits in MONCTL0, while on immediate mode, by setting -MSRCTL1. - -Previously, the code would set MSRCTL1 for all four sensors when -configured to immediate mode, but given that the controller might not -have all four sensors connected, this would cause interrupts to trigger -for non-existent sensors. Fix this by handling the MSRCTL1 register -analogously to the MONCTL0: only enable the sensors that were declared. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Reviewed-by: AngeloGioacchino Del Regno -Tested-by: Chen-Yu Tsai -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-3-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 57 ++++++++++++++----------- - 1 file changed, 33 insertions(+), 24 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -897,24 +897,6 @@ static int lvts_ctrl_configure(struct de - writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); - - /* -- * LVTS_MSRCTL1 : Measurement control -- * -- * Bits: -- * -- * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 -- * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 -- * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 -- * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 -- * -- * That configuration will ignore the filtering and the delays -- * introduced below in MONCTL1 and MONCTL2 -- */ -- if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { -- value = BIT(9) | BIT(6) | BIT(5) | BIT(4); -- writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); -- } -- -- /* - * LVTS_MONCTL1 : Period unit and group interval configuration - * - * The clock source of LVTS thermal controller is 26MHz. -@@ -979,6 +961,15 @@ static int lvts_ctrl_start(struct device - struct thermal_zone_device *tz; - u32 sensor_map = 0; - int i; -+ /* -+ * Bitmaps to enable each sensor on immediate and filtered modes, as -+ * described in MSRCTL1 and MONCTL0 registers below, respectively. -+ */ -+ u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) }; -+ u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; -+ -+ u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ? -+ sensor_imm_bitmap : sensor_filt_bitmap; - - for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { - -@@ -1016,20 +1007,38 @@ static int lvts_ctrl_start(struct device - * map, so we can enable the temperature monitoring in - * the hardware thermal controller. - */ -- sensor_map |= BIT(i); -+ sensor_map |= sensor_bitmap[i]; - } - - /* -- * Bits: -- * 9: Single point access flow -- * 0-3: Enable sensing point 0-3 -- * - * The initialization of the thermal zones give us - * which sensor point to enable. If any thermal zone - * was not described in the device tree, it won't be - * enabled here in the sensor map. - */ -- writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); -+ if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { -+ /* -+ * LVTS_MSRCTL1 : Measurement control -+ * -+ * Bits: -+ * -+ * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 -+ * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 -+ * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 -+ * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 -+ * -+ * That configuration will ignore the filtering and the delays -+ * introduced in MONCTL1 and MONCTL2 -+ */ -+ writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base)); -+ } else { -+ /* -+ * Bits: -+ * 9: Single point access flow -+ * 0-3: Enable sensing point 0-3 -+ */ -+ writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); -+ } - - return 0; - } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch b/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch deleted file mode 100644 index bfbadee350..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 93bb11dd19bdcc1fc97c7ceababd0db9fde128ad Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:34 -0400 -Subject: [PATCH 27/42] thermal/drivers/mediatek/lvts_thermal: Use offset - threshold for IRQ -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There are two kinds of temperature monitoring interrupts available: -* High Offset, Low Offset -* Hot, Hot to normal, Cold - -The code currently uses the hot/h2n/cold interrupts, however in a way -that doesn't work: the cold threshold is left uninitialized, which -prevents the other thresholds from ever triggering, and the h2n -interrupt is used as the lower threshold, which prevents the hot -interrupt from triggering again after the thresholds are updated by the -thermal framework, since a hot interrupt can only trigger again after -the hot to normal interrupt has been triggered. - -But better yet than addressing those issues, is to use the high/low -offset interrupts instead. This way only two thresholds need to be -managed, which have a simpler state machine, making them a better match -to the thermal framework's high and low thresholds. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-4-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -298,9 +298,9 @@ static int lvts_set_trips(struct thermal - u32 raw_high = lvts_temp_to_raw(high); - - /* -- * Hot to normal temperature threshold -+ * Low offset temperature threshold - * -- * LVTS_H2NTHRE -+ * LVTS_OFFSETL - * - * Bits: - * -@@ -309,13 +309,13 @@ static int lvts_set_trips(struct thermal - if (low != -INT_MAX) { - pr_debug("%s: Setting low limit temperature interrupt: %d\n", - thermal_zone_device_type(tz), low); -- writel(raw_low, LVTS_H2NTHRE(base)); -+ writel(raw_low, LVTS_OFFSETL(base)); - } - - /* -- * Hot temperature threshold -+ * High offset temperature threshold - * -- * LVTS_HTHRE -+ * LVTS_OFFSETH - * - * Bits: - * -@@ -323,7 +323,7 @@ static int lvts_set_trips(struct thermal - */ - pr_debug("%s: Setting high limit temperature interrupt: %d\n", - thermal_zone_device_type(tz), high); -- writel(raw_high, LVTS_HTHRE(base)); -+ writel(raw_high, LVTS_OFFSETH(base)); - - return 0; - } diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch b/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch deleted file mode 100644 index 1c35d0ad19..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 8f8cab9d3e90acf1db278ef44ad05f10aefb973f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:35 -0400 -Subject: [PATCH 28/42] thermal/drivers/mediatek/lvts_thermal: Disable - undesired interrupts -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Out of the many interrupts supported by the hardware, the only ones of -interest to the driver currently are: -* The temperature went over the high offset threshold, for any of the - sensors -* The temperature went below the low offset threshold, for any of the - sensors -* The temperature went over the stage3 threshold - -These are the only thresholds configured by the driver through the -OFFSETH, OFFSETL, and PROTTC registers, respectively. - -The current interrupt mask in LVTS_MONINT_CONF, enables many more -interrupts, including data ready on sensors for both filtered and -immediate mode. These are not only not handled by the driver, but they -are also triggered too often, causing unneeded overhead. Disable these -unnecessary interrupts. - -The meaning of each bit can be seen in the comment describing -LVTS_MONINTST in the IRQ handler. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Alexandre Mergnat -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-5-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -65,7 +65,7 @@ - #define LVTS_HW_FILTER 0x2 - #define LVTS_TSSEL_CONF 0x13121110 - #define LVTS_CALSCALE_CONF 0x300 --#define LVTS_MONINT_CONF 0x9FBF7BDE -+#define LVTS_MONINT_CONF 0x8300318C - - #define LVTS_INT_SENSOR0 0x0009001F - #define LVTS_INT_SENSOR1 0x001203E0 diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch b/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch deleted file mode 100644 index 60942fdb89..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch +++ /dev/null @@ -1,70 +0,0 @@ -From bd1ccf9408e6155564530af5e09b53ae497fe332 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:36 -0400 -Subject: [PATCH 29/42] thermal/drivers/mediatek/lvts_thermal: Don't leave - threshold zeroed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The thermal framework might leave the low threshold unset if there -aren't any lower trip points. This leaves the register zeroed, which -translates to a very high temperature for the low threshold. The -interrupt for this threshold is then immediately triggered, and the -state machine gets stuck, preventing any other temperature monitoring -interrupts to ever trigger. - -(The same happens by not setting the Cold or Hot to Normal thresholds -when using those) - -Set the unused threshold to a valid low value. This value was chosen so -that for any valid golden temperature read from the efuse, when the -value is converted to raw and back again to milliCelsius, the result -doesn't underflow. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-6-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -83,6 +83,8 @@ - - #define LVTS_HW_SHUTDOWN_MT8195 105000 - -+#define LVTS_MINIMUM_THRESHOLD 20000 -+ - static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; - static int coeff_b = LVTS_COEFF_B; - -@@ -294,7 +296,7 @@ static int lvts_set_trips(struct thermal - { - struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); - void __iomem *base = lvts_sensor->base; -- u32 raw_low = lvts_temp_to_raw(low); -+ u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); - u32 raw_high = lvts_temp_to_raw(high); - - /* -@@ -306,11 +308,9 @@ static int lvts_set_trips(struct thermal - * - * 14-0 : Raw temperature for threshold - */ -- if (low != -INT_MAX) { -- pr_debug("%s: Setting low limit temperature interrupt: %d\n", -- thermal_zone_device_type(tz), low); -- writel(raw_low, LVTS_OFFSETL(base)); -- } -+ pr_debug("%s: Setting low limit temperature interrupt: %d\n", -+ thermal_zone_device_type(tz), low); -+ writel(raw_low, LVTS_OFFSETL(base)); - - /* - * High offset temperature threshold diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch b/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch deleted file mode 100644 index e99aa0cdfd..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch +++ /dev/null @@ -1,156 +0,0 @@ -From d4dd09968cab3249e6148e1c3fccb51824edb411 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 6 Jul 2023 11:37:37 -0400 -Subject: [PATCH 30/42] thermal/drivers/mediatek/lvts_thermal: Manage threshold - between sensors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Each LVTS thermal controller can have up to four sensors, each capable -of triggering its own interrupt when its measured temperature crosses -the configured threshold. The threshold for each sensor is handled -separately by the thermal framework, since each one is registered with -its own thermal zone and trips. However, the temperature thresholds are -configured on the controller, and therefore are shared between all -sensors on that controller. - -When the temperature measured by the sensors is different enough to -cause the thermal framework to configure different thresholds for each -one, interrupts start triggering on sensors outside the last threshold -configured. - -To address the issue, track the thresholds required by each sensor and -only actually set the highest one in the hardware, and disable -interrupts for all sensors outside the current configured range. - -Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver") -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230706153823.201943-7-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 69 +++++++++++++++++++++++++ - 1 file changed, 69 insertions(+) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -67,6 +67,11 @@ - #define LVTS_CALSCALE_CONF 0x300 - #define LVTS_MONINT_CONF 0x8300318C - -+#define LVTS_MONINT_OFFSET_SENSOR0 0xC -+#define LVTS_MONINT_OFFSET_SENSOR1 0x180 -+#define LVTS_MONINT_OFFSET_SENSOR2 0x3000 -+#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000 -+ - #define LVTS_INT_SENSOR0 0x0009001F - #define LVTS_INT_SENSOR1 0x001203E0 - #define LVTS_INT_SENSOR2 0x00247C00 -@@ -112,6 +117,8 @@ struct lvts_sensor { - void __iomem *base; - int id; - int dt_id; -+ int low_thresh; -+ int high_thresh; - }; - - struct lvts_ctrl { -@@ -121,6 +128,8 @@ struct lvts_ctrl { - int num_lvts_sensor; - int mode; - void __iomem *base; -+ int low_thresh; -+ int high_thresh; - }; - - struct lvts_domain { -@@ -292,12 +301,66 @@ static int lvts_get_temp(struct thermal_ - return 0; - } - -+static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl) -+{ -+ u32 masks[] = { -+ LVTS_MONINT_OFFSET_SENSOR0, -+ LVTS_MONINT_OFFSET_SENSOR1, -+ LVTS_MONINT_OFFSET_SENSOR2, -+ LVTS_MONINT_OFFSET_SENSOR3, -+ }; -+ u32 value = 0; -+ int i; -+ -+ value = readl(LVTS_MONINT(lvts_ctrl->base)); -+ -+ for (i = 0; i < ARRAY_SIZE(masks); i++) { -+ if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh -+ && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) -+ value |= masks[i]; -+ else -+ value &= ~masks[i]; -+ } -+ -+ writel(value, LVTS_MONINT(lvts_ctrl->base)); -+} -+ -+static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) -+{ -+ int i; -+ -+ if (high > lvts_ctrl->high_thresh) -+ return true; -+ -+ for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) -+ if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh -+ && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) -+ return false; -+ -+ return true; -+} -+ - static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) - { - struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); -+ struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); - void __iomem *base = lvts_sensor->base; - u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); - u32 raw_high = lvts_temp_to_raw(high); -+ bool should_update_thresh; -+ -+ lvts_sensor->low_thresh = low; -+ lvts_sensor->high_thresh = high; -+ -+ should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high); -+ if (should_update_thresh) { -+ lvts_ctrl->high_thresh = high; -+ lvts_ctrl->low_thresh = low; -+ } -+ lvts_update_irq_mask(lvts_ctrl); -+ -+ if (!should_update_thresh) -+ return 0; - - /* - * Low offset temperature threshold -@@ -521,6 +584,9 @@ static int lvts_sensor_init(struct devic - */ - lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? - imm_regs[i] : msr_regs[i]; -+ -+ lvts_sensor[i].low_thresh = INT_MIN; -+ lvts_sensor[i].high_thresh = INT_MIN; - }; - - lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; -@@ -688,6 +754,9 @@ static int lvts_ctrl_init(struct device - */ - lvts_ctrl[i].hw_tshut_raw_temp = - lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); -+ -+ lvts_ctrl[i].low_thresh = INT_MIN; -+ lvts_ctrl[i].high_thresh = INT_MIN; - } - - /* diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch b/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch deleted file mode 100644 index 9ce3eeb74b..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5af4904adc8b840987000724977c13c706d3b7d8 Mon Sep 17 00:00:00 2001 -From: Minjie Du -Date: Thu, 13 Jul 2023 12:24:12 +0800 -Subject: [PATCH 31/42] thermal/drivers/mediatek/lvts: Fix parameter check in - lvts_debugfs_init() - -The documentation says "If an error occurs, ERR_PTR(-ERROR) will be -returned" but the current code checks against a NULL pointer returned. - -Fix this by checking if IS_ERR(). - -Signed-off-by: Minjie Du -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230713042413.2519-1-duminjie@vivo.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -201,7 +201,7 @@ static int lvts_debugfs_init(struct devi - int i; - - lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); -- if (!lvts_td->dom_dentry) -+ if (IS_ERR(lvts_td->dom_dentry)) - return 0; - - for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch b/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch deleted file mode 100644 index 4841054917..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 6186be80317d1dbda34d35c06c084a083938f2d3 Mon Sep 17 00:00:00 2001 -From: Chen Jiahao -Date: Wed, 2 Aug 2023 17:45:27 +0800 -Subject: [PATCH 32/42] thermal/drivers/mediatek: Clean up redundant - dev_err_probe() - -Referring to platform_get_irq()'s definition, the return value has -already been checked if ret < 0, and printed via dev_err_probe(). -Calling dev_err_probe() one more time outside platform_get_irq() -is obviously redundant. - -Removing dev_err_probe() outside platform_get_irq() to clean up -above problem. - -Signed-off-by: Chen Jiahao -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230802094527.988842-1-chenjiahao16@huawei.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -1216,7 +1216,7 @@ static int lvts_probe(struct platform_de - - irq = platform_get_irq(pdev, 0); - if (irq < 0) -- return dev_err_probe(dev, irq, "No irq resource\n"); -+ return irq; - - ret = lvts_domain_init(dev, lvts_td, lvts_data); - if (ret) diff --git a/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch b/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch deleted file mode 100644 index c88bf984fa..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch +++ /dev/null @@ -1,95 +0,0 @@ -From c2ab54ab0425388e65901a7af2fbf69ead968708 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= - -Date: Thu, 13 Jul 2023 11:42:37 -0400 -Subject: [PATCH 33/42] thermal/drivers/mediatek/lvts_thermal: Make readings - valid in filtered mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently, when a controller is configured to use filtered mode, thermal -readings are valid only about 30% of the time. - -Upon testing, it was noticed that lowering any of the interval settings -resulted in an improved rate of valid data. The same was observed when -decreasing the number of samples for each sensor (which also results in -quicker measurements). - -Retrying the read with a timeout longer than the time it takes to -resample (about 344us with these settings and 4 sensors) also improves -the rate. - -Lower all timing settings to the minimum, configure the filtering to -single sample, and poll the measurement register for at least one period -to improve the data validity on filtered mode. With these changes in -place, out of 100000 reads, a single one failed, ie 99.999% of the data -was valid. - -Reviewed-by: Chen-Yu Tsai -Tested-by: Chen-Yu Tsai -Signed-off-by: Nícolas F. R. A. Prado -Reviewed-by: Alexandre Mergnat -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230713154743.611870-1-nfraprado@collabora.com ---- - drivers/thermal/mediatek/lvts_thermal.c | 19 ++++++++++++------- - 1 file changed, 12 insertions(+), 7 deletions(-) - ---- a/drivers/thermal/mediatek/lvts_thermal.c -+++ b/drivers/thermal/mediatek/lvts_thermal.c -@@ -58,11 +58,11 @@ - #define LVTS_PROTTC(__base) (__base + 0x00CC) - #define LVTS_CLKEN(__base) (__base + 0x00E4) - --#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) --#define LVTS_GROUP_INTERVAL 1 --#define LVTS_FILTER_INTERVAL 1 --#define LVTS_SENSOR_INTERVAL 1 --#define LVTS_HW_FILTER 0x2 -+#define LVTS_PERIOD_UNIT 0 -+#define LVTS_GROUP_INTERVAL 0 -+#define LVTS_FILTER_INTERVAL 0 -+#define LVTS_SENSOR_INTERVAL 0 -+#define LVTS_HW_FILTER 0x0 - #define LVTS_TSSEL_CONF 0x13121110 - #define LVTS_CALSCALE_CONF 0x300 - #define LVTS_MONINT_CONF 0x8300318C -@@ -86,6 +86,9 @@ - #define LVTS_MSR_IMMEDIATE_MODE 0 - #define LVTS_MSR_FILTERED_MODE 1 - -+#define LVTS_MSR_READ_TIMEOUT_US 400 -+#define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) -+ - #define LVTS_HW_SHUTDOWN_MT8195 105000 - - #define LVTS_MINIMUM_THRESHOLD 20000 -@@ -268,6 +271,7 @@ static int lvts_get_temp(struct thermal_ - struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); - void __iomem *msr = lvts_sensor->msr; - u32 value; -+ int rc; - - /* - * Measurement registers: -@@ -280,7 +284,8 @@ static int lvts_get_temp(struct thermal_ - * 16 : Valid temperature - * 15-0 : Raw temperature - */ -- value = readl(msr); -+ rc = readl_poll_timeout(msr, value, value & BIT(16), -+ LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US); - - /* - * As the thermal zone temperature will read before the -@@ -293,7 +298,7 @@ static int lvts_get_temp(struct thermal_ - * functionning temperature and directly jump to a system - * shutdown. - */ -- if (!(value & BIT(16))) -+ if (rc) - return -EAGAIN; - - *temp = lvts_raw_to_temp(value & 0xFFFF); diff --git a/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch b/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch deleted file mode 100644 index 994461cdb1..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.6-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c864ff9de3b225b43bb8e08dedb223632323e059 Mon Sep 17 00:00:00 2001 -From: Andrei Coardos -Date: Fri, 11 Aug 2023 22:28:47 +0300 -Subject: [PATCH 34/42] thermal/drivers/mediatek/auxadc_thermal: Removed call - to platform_set_drvdata() - -This function call was found to be unnecessary as there is no equivalent -platform_get_drvdata() call to access the private data of the driver. Also, -the private data is defined in this driver, so there is no risk of it being -accessed outside of this driver file. - -Signed-off-by: Andrei Coardos -Reviewed-by: Alexandru Ardelean -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230811192847.3838-1-aboutphysycs@gmail.com ---- - drivers/thermal/mediatek/auxadc_thermal.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1283,8 +1283,6 @@ static int mtk_thermal_probe(struct plat - mtk_thermal_init_bank(mt, i, apmixed_phys_base, - auxadc_phys_base, ctrl_id); - -- platform_set_drvdata(pdev, mt); -- - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); - if (IS_ERR(tzdev)) diff --git a/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch deleted file mode 100644 index 4c398c59f9..0000000000 --- a/target/linux/mediatek/patches-6.6/851-v6.2-i2c-mediatek-add-mt7986-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 11f9a0f4e51887ad7b4a2898a368fcd0c2984e89 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 9 Oct 2022 12:16:31 +0200 -Subject: [PATCH 12/16] i2c: mediatek: add mt7986 support - -Add i2c support for MT7986 SoC. - -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7986_compat = { -+ .quirks = &mt7622_i2c_quirks, -+ .regs = mt_i2c_regs_v1, -+ .pmic_i2c = 0, -+ .dcm = 1, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 0, -+ .dma_sync = 1, -+ .ltiming_adjust = 0, -+ .max_dma_support = 32, -+}; -+ - static const struct mtk_i2c_compatible mt8173_compat = { - .regs = mt_i2c_regs_v1, - .pmic_i2c = 0, -@@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, diff --git a/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch deleted file mode 100644 index 18c66cdac5..0000000000 --- a/target/linux/mediatek/patches-6.6/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 98204ccafd45a8a6109ff2d60e2c179b95d92578 Mon Sep 17 00:00:00 2001 -From: ye xingchen -Date: Thu, 19 Jan 2023 17:19:58 +0800 -Subject: [PATCH 13/16] i2c: mt65xx: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: ye xingchen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform - { - int ret = 0; - struct mtk_i2c *i2c; -- struct resource *res; - int i, irq, speed_clk; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- i2c->base = devm_ioremap_resource(&pdev->dev, res); -+ i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c->base)) - return PTR_ERR(i2c->base); - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -- i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res); -+ i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); - if (IS_ERR(i2c->pdmabase)) - return PTR_ERR(i2c->pdmabase); - diff --git a/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch deleted file mode 100644 index d000d53522..0000000000 --- a/target/linux/mediatek/patches-6.6/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8106fa2e0ae6082833fe1df97829c46c0183eaea Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Sat, 11 Mar 2023 12:16:54 +0100 -Subject: [PATCH 14/16] i2c: mt65xx: drop of_match_ptr for ID table -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The driver can match only via the DT table so the table should be always -used and the of_match_ptr does not have any sense (this also allows ACPI -matching via PRP0001, even though it might not be relevant here). - - drivers/i2c/busses/i2c-mt65xx.c:514:34: error: ‘mtk_i2c_of_match’ defined but not used [-Werror=unused-const-variable=] - -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Guenter Roeck -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1546,7 +1546,7 @@ static struct platform_driver mtk_i2c_dr - .driver = { - .name = I2C_DRV_NAME, - .pm = &mtk_i2c_pm, -- .of_match_table = of_match_ptr(mtk_i2c_of_match), -+ .of_match_table = mtk_i2c_of_match, - }, - }; - diff --git a/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch deleted file mode 100644 index e0973741e2..0000000000 --- a/target/linux/mediatek/patches-6.6/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f69f3d662ba3bf999c36d9ac1e684540c4487bc3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 10 Apr 2023 17:19:38 +0100 -Subject: [PATCH 15/16] i2c: mediatek: add support for MT7981 SoC - -Add support for the I2C units found in the MediaTek MT7981 and MT7988 -SoCs. Just like other recent MediaTek I2C units that also uses v3 -register offsets (which differ from v2 only by OFFSET_SLAVE_ADDR being -0x94 instead of 0x4). - -Signed-off-by: Daniel Golle -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Alexandre Mergnat -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7981_compat = { -+ .regs = mt_i2c_regs_v3, -+ .pmic_i2c = 0, -+ .dcm = 0, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 1, -+ .ltiming_adjust = 1, -+ .max_dma_support = 33 -+}; -+ - static const struct mtk_i2c_compatible mt7986_compat = { - .quirks = &mt7622_i2c_quirks, - .regs = mt_i2c_regs_v1, -@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat }, - { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch b/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch deleted file mode 100644 index 9607eec821..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-01-ASoC-mediatek-mt7986-add-common-header.patch +++ /dev/null @@ -1,269 +0,0 @@ -From d35469096915f2551ed1d26da1ab12ff500fc963 Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:33 +0800 -Subject: [PATCH 1/9] ASoC: mediatek: mt7986: add common header - -Add header files for register definition and structure. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-2-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - sound/soc/mediatek/mt7986/mt7986-afe-common.h | 49 +++++ - sound/soc/mediatek/mt7986/mt7986-reg.h | 196 ++++++++++++++++++ - 2 files changed, 245 insertions(+) - create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-common.h - create mode 100644 sound/soc/mediatek/mt7986/mt7986-reg.h - ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/mt7986-afe-common.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * mt7986-afe-common.h -- MediaTek 7986 audio driver definitions -+ * -+ * Copyright (c) 2023 MediaTek Inc. -+ * Authors: Vic Wu -+ * Maso Huang -+ */ -+ -+#ifndef _MT_7986_AFE_COMMON_H_ -+#define _MT_7986_AFE_COMMON_H_ -+ -+#include -+#include -+#include -+#include -+#include "../common/mtk-base-afe.h" -+ -+enum { -+ MT7986_MEMIF_DL1, -+ MT7986_MEMIF_VUL12, -+ MT7986_MEMIF_NUM, -+ MT7986_DAI_ETDM = MT7986_MEMIF_NUM, -+ MT7986_DAI_NUM, -+}; -+ -+enum { -+ MT7986_IRQ_0, -+ MT7986_IRQ_1, -+ MT7986_IRQ_2, -+ MT7986_IRQ_NUM, -+}; -+ -+struct mt7986_afe_private { -+ struct clk_bulk_data *clks; -+ int num_clks; -+ -+ int pm_runtime_bypass_reg_ctl; -+ -+ /* dai */ -+ void *dai_priv[MT7986_DAI_NUM]; -+}; -+ -+unsigned int mt7986_afe_rate_transform(struct device *dev, -+ unsigned int rate); -+ -+/* dai register */ -+int mt7986_dai_etdm_register(struct mtk_base_afe *afe); -+#endif ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/mt7986-reg.h -@@ -0,0 +1,196 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * mt7986-reg.h -- MediaTek 7986 audio driver reg definition -+ * -+ * Copyright (c) 2023 MediaTek Inc. -+ * Authors: Vic Wu -+ * Maso Huang -+ */ -+ -+#ifndef _MT7986_REG_H_ -+#define _MT7986_REG_H_ -+ -+#define AUDIO_TOP_CON2 0x0008 -+#define AUDIO_TOP_CON4 0x0010 -+#define AUDIO_ENGEN_CON0 0x0014 -+#define AFE_IRQ_MCU_EN 0x0100 -+#define AFE_IRQ_MCU_STATUS 0x0120 -+#define AFE_IRQ_MCU_CLR 0x0128 -+#define AFE_IRQ0_MCU_CFG0 0x0140 -+#define AFE_IRQ0_MCU_CFG1 0x0144 -+#define AFE_IRQ1_MCU_CFG0 0x0148 -+#define AFE_IRQ1_MCU_CFG1 0x014c -+#define AFE_IRQ2_MCU_CFG0 0x0150 -+#define AFE_IRQ2_MCU_CFG1 0x0154 -+#define ETDM_IN5_CON0 0x13f0 -+#define ETDM_IN5_CON1 0x13f4 -+#define ETDM_IN5_CON2 0x13f8 -+#define ETDM_IN5_CON3 0x13fc -+#define ETDM_IN5_CON4 0x1400 -+#define ETDM_OUT5_CON0 0x1570 -+#define ETDM_OUT5_CON4 0x1580 -+#define ETDM_OUT5_CON5 0x1584 -+#define ETDM_4_7_COWORK_CON0 0x15e0 -+#define ETDM_4_7_COWORK_CON1 0x15e4 -+#define AFE_CONN018_1 0x1b44 -+#define AFE_CONN018_4 0x1b50 -+#define AFE_CONN019_1 0x1b64 -+#define AFE_CONN019_4 0x1b70 -+#define AFE_CONN124_1 0x2884 -+#define AFE_CONN124_4 0x2890 -+#define AFE_CONN125_1 0x28a4 -+#define AFE_CONN125_4 0x28b0 -+#define AFE_CONN_RS_0 0x3920 -+#define AFE_CONN_RS_3 0x392c -+#define AFE_CONN_16BIT_0 0x3960 -+#define AFE_CONN_16BIT_3 0x396c -+#define AFE_CONN_24BIT_0 0x3980 -+#define AFE_CONN_24BIT_3 0x398c -+#define AFE_MEMIF_CON0 0x3d98 -+#define AFE_MEMIF_RD_MON 0x3da0 -+#define AFE_MEMIF_WR_MON 0x3da4 -+#define AFE_DL0_BASE_MSB 0x3e40 -+#define AFE_DL0_BASE 0x3e44 -+#define AFE_DL0_CUR_MSB 0x3e48 -+#define AFE_DL0_CUR 0x3e4c -+#define AFE_DL0_END_MSB 0x3e50 -+#define AFE_DL0_END 0x3e54 -+#define AFE_DL0_RCH_MON 0x3e58 -+#define AFE_DL0_LCH_MON 0x3e5c -+#define AFE_DL0_CON0 0x3e60 -+#define AFE_VUL0_BASE_MSB 0x4220 -+#define AFE_VUL0_BASE 0x4224 -+#define AFE_VUL0_CUR_MSB 0x4228 -+#define AFE_VUL0_CUR 0x422c -+#define AFE_VUL0_END_MSB 0x4230 -+#define AFE_VUL0_END 0x4234 -+#define AFE_VUL0_CON0 0x4238 -+ -+#define AFE_MAX_REGISTER AFE_VUL0_CON0 -+#define AFE_IRQ_STATUS_BITS 0x7 -+#define AFE_IRQ_CNT_SHIFT 0 -+#define AFE_IRQ_CNT_MASK 0xffffff -+ -+/* AUDIO_TOP_CON2 */ -+#define CLK_OUT5_PDN BIT(14) -+#define CLK_OUT5_PDN_MASK BIT(14) -+#define CLK_IN5_PDN BIT(7) -+#define CLK_IN5_PDN_MASK BIT(7) -+ -+/* AUDIO_TOP_CON4 */ -+#define PDN_APLL_TUNER2 BIT(12) -+#define PDN_APLL_TUNER2_MASK BIT(12) -+ -+/* AUDIO_ENGEN_CON0 */ -+#define AUD_APLL2_EN BIT(3) -+#define AUD_APLL2_EN_MASK BIT(3) -+#define AUD_26M_EN BIT(0) -+#define AUD_26M_EN_MASK BIT(0) -+ -+/* AFE_DL0_CON0 */ -+#define DL0_ON_SFT 28 -+#define DL0_ON_MASK 0x1 -+#define DL0_ON_MASK_SFT BIT(28) -+#define DL0_MINLEN_SFT 20 -+#define DL0_MINLEN_MASK 0xf -+#define DL0_MINLEN_MASK_SFT (0xf << 20) -+#define DL0_MODE_SFT 8 -+#define DL0_MODE_MASK 0x1f -+#define DL0_MODE_MASK_SFT (0x1f << 8) -+#define DL0_PBUF_SIZE_SFT 5 -+#define DL0_PBUF_SIZE_MASK 0x3 -+#define DL0_PBUF_SIZE_MASK_SFT (0x3 << 5) -+#define DL0_MONO_SFT 4 -+#define DL0_MONO_MASK 0x1 -+#define DL0_MONO_MASK_SFT BIT(4) -+#define DL0_HALIGN_SFT 2 -+#define DL0_HALIGN_MASK 0x1 -+#define DL0_HALIGN_MASK_SFT BIT(2) -+#define DL0_HD_MODE_SFT 0 -+#define DL0_HD_MODE_MASK 0x3 -+#define DL0_HD_MODE_MASK_SFT (0x3 << 0) -+ -+/* AFE_VUL0_CON0 */ -+#define VUL0_ON_SFT 28 -+#define VUL0_ON_MASK 0x1 -+#define VUL0_ON_MASK_SFT BIT(28) -+#define VUL0_MODE_SFT 8 -+#define VUL0_MODE_MASK 0x1f -+#define VUL0_MODE_MASK_SFT (0x1f << 8) -+#define VUL0_MONO_SFT 4 -+#define VUL0_MONO_MASK 0x1 -+#define VUL0_MONO_MASK_SFT BIT(4) -+#define VUL0_HALIGN_SFT 2 -+#define VUL0_HALIGN_MASK 0x1 -+#define VUL0_HALIGN_MASK_SFT BIT(2) -+#define VUL0_HD_MODE_SFT 0 -+#define VUL0_HD_MODE_MASK 0x3 -+#define VUL0_HD_MODE_MASK_SFT (0x3 << 0) -+ -+/* AFE_IRQ_MCU_CON */ -+#define IRQ_MCU_MODE_SFT 4 -+#define IRQ_MCU_MODE_MASK 0x1f -+#define IRQ_MCU_MODE_MASK_SFT (0x1f << 4) -+#define IRQ_MCU_ON_SFT 0 -+#define IRQ_MCU_ON_MASK 0x1 -+#define IRQ_MCU_ON_MASK_SFT BIT(0) -+#define IRQ0_MCU_CLR_SFT 0 -+#define IRQ0_MCU_CLR_MASK 0x1 -+#define IRQ0_MCU_CLR_MASK_SFT BIT(0) -+#define IRQ1_MCU_CLR_SFT 1 -+#define IRQ1_MCU_CLR_MASK 0x1 -+#define IRQ1_MCU_CLR_MASK_SFT BIT(1) -+#define IRQ2_MCU_CLR_SFT 2 -+#define IRQ2_MCU_CLR_MASK 0x1 -+#define IRQ2_MCU_CLR_MASK_SFT BIT(2) -+ -+/* ETDM_IN5_CON2 */ -+#define IN_CLK_SRC(x) ((x) << 10) -+#define IN_CLK_SRC_SFT 10 -+#define IN_CLK_SRC_MASK GENMASK(12, 10) -+ -+/* ETDM_IN5_CON3 */ -+#define IN_SEL_FS(x) ((x) << 26) -+#define IN_SEL_FS_SFT 26 -+#define IN_SEL_FS_MASK GENMASK(30, 26) -+ -+/* ETDM_IN5_CON4 */ -+#define IN_RELATCH(x) ((x) << 20) -+#define IN_RELATCH_SFT 20 -+#define IN_RELATCH_MASK GENMASK(24, 20) -+#define IN_CLK_INV BIT(18) -+#define IN_CLK_INV_MASK BIT(18) -+ -+/* ETDM_IN5_CON0 & ETDM_OUT5_CON0 */ -+#define RELATCH_SRC_MASK GENMASK(30, 28) -+#define ETDM_CH_NUM_MASK GENMASK(27, 23) -+#define ETDM_WRD_LEN_MASK GENMASK(20, 16) -+#define ETDM_BIT_LEN_MASK GENMASK(15, 11) -+#define ETDM_FMT_MASK GENMASK(8, 6) -+#define ETDM_SYNC BIT(1) -+#define ETDM_SYNC_MASK BIT(1) -+#define ETDM_EN BIT(0) -+#define ETDM_EN_MASK BIT(0) -+ -+/* ETDM_OUT5_CON4 */ -+#define OUT_RELATCH(x) ((x) << 24) -+#define OUT_RELATCH_SFT 24 -+#define OUT_RELATCH_MASK GENMASK(28, 24) -+#define OUT_CLK_SRC(x) ((x) << 6) -+#define OUT_CLK_SRC_SFT 6 -+#define OUT_CLK_SRC_MASK GENMASK(8, 6) -+#define OUT_SEL_FS(x) (x) -+#define OUT_SEL_FS_SFT 0 -+#define OUT_SEL_FS_MASK GENMASK(4, 0) -+ -+/* ETDM_OUT5_CON5 */ -+#define ETDM_CLK_DIV BIT(12) -+#define ETDM_CLK_DIV_MASK BIT(12) -+#define OUT_CLK_INV BIT(9) -+#define OUT_CLK_INV_MASK BIT(9) -+ -+/* ETDM_4_7_COWORK_CON0 */ -+#define OUT_SEL(x) ((x) << 12) -+#define OUT_SEL_SFT 12 -+#define OUT_SEL_MASK GENMASK(15, 12) -+#endif diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch b/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch deleted file mode 100644 index f22add580f..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-02-ASoC-mediatek-mt7986-support-etdm-in-platform-driver.patch +++ /dev/null @@ -1,430 +0,0 @@ -From 948a288897015fb3ee63b3f720b396b590c17fd7 Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:34 +0800 -Subject: [PATCH 2/9] ASoC: mediatek: mt7986: support etdm in platform driver - -Add mt7986 etdm dai driver support. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-3-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - sound/soc/mediatek/mt7986/mt7986-dai-etdm.c | 411 ++++++++++++++++++++ - 1 file changed, 411 insertions(+) - create mode 100644 sound/soc/mediatek/mt7986/mt7986-dai-etdm.c - ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c -@@ -0,0 +1,411 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * MediaTek ALSA SoC Audio DAI eTDM Control -+ * -+ * Copyright (c) 2023 MediaTek Inc. -+ * Authors: Vic Wu -+ * Maso Huang -+ */ -+ -+#include -+#include -+#include -+#include -+#include "mt7986-afe-common.h" -+#include "mt7986-reg.h" -+ -+#define HOPPING_CLK 0 -+#define APLL_CLK 1 -+#define MTK_DAI_ETDM_FORMAT_I2S 0 -+#define MTK_DAI_ETDM_FORMAT_DSPA 4 -+#define MTK_DAI_ETDM_FORMAT_DSPB 5 -+ -+enum { -+ MTK_ETDM_RATE_8K = 0, -+ MTK_ETDM_RATE_12K = 1, -+ MTK_ETDM_RATE_16K = 2, -+ MTK_ETDM_RATE_24K = 3, -+ MTK_ETDM_RATE_32K = 4, -+ MTK_ETDM_RATE_48K = 5, -+ MTK_ETDM_RATE_96K = 7, -+ MTK_ETDM_RATE_192K = 9, -+ MTK_ETDM_RATE_11K = 16, -+ MTK_ETDM_RATE_22K = 17, -+ MTK_ETDM_RATE_44K = 18, -+ MTK_ETDM_RATE_88K = 19, -+ MTK_ETDM_RATE_176K = 20, -+}; -+ -+struct mtk_dai_etdm_priv { -+ bool bck_inv; -+ bool lrck_inv; -+ bool slave_mode; -+ unsigned int format; -+}; -+ -+static unsigned int mt7986_etdm_rate_transform(struct device *dev, unsigned int rate) -+{ -+ switch (rate) { -+ case 8000: -+ return MTK_ETDM_RATE_8K; -+ case 11025: -+ return MTK_ETDM_RATE_11K; -+ case 12000: -+ return MTK_ETDM_RATE_12K; -+ case 16000: -+ return MTK_ETDM_RATE_16K; -+ case 22050: -+ return MTK_ETDM_RATE_22K; -+ case 24000: -+ return MTK_ETDM_RATE_24K; -+ case 32000: -+ return MTK_ETDM_RATE_32K; -+ case 44100: -+ return MTK_ETDM_RATE_44K; -+ case 48000: -+ return MTK_ETDM_RATE_48K; -+ case 88200: -+ return MTK_ETDM_RATE_88K; -+ case 96000: -+ return MTK_ETDM_RATE_96K; -+ case 176400: -+ return MTK_ETDM_RATE_176K; -+ case 192000: -+ return MTK_ETDM_RATE_192K; -+ default: -+ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", -+ __func__, rate, MTK_ETDM_RATE_48K); -+ return MTK_ETDM_RATE_48K; -+ } -+} -+ -+static int get_etdm_wlen(unsigned int bitwidth) -+{ -+ return bitwidth <= 16 ? 16 : 32; -+} -+ -+/* dai component */ -+/* interconnection */ -+ -+static const struct snd_kcontrol_new o124_mix[] = { -+ SOC_DAPM_SINGLE_AUTODISABLE("I032_Switch", AFE_CONN124_1, 0, 1, 0), -+}; -+ -+static const struct snd_kcontrol_new o125_mix[] = { -+ SOC_DAPM_SINGLE_AUTODISABLE("I033_Switch", AFE_CONN125_1, 1, 1, 0), -+}; -+ -+static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = { -+ -+ /* DL */ -+ SND_SOC_DAPM_MIXER("I150", SND_SOC_NOPM, 0, 0, NULL, 0), -+ SND_SOC_DAPM_MIXER("I151", SND_SOC_NOPM, 0, 0, NULL, 0), -+ /* UL */ -+ SND_SOC_DAPM_MIXER("O124", SND_SOC_NOPM, 0, 0, o124_mix, ARRAY_SIZE(o124_mix)), -+ SND_SOC_DAPM_MIXER("O125", SND_SOC_NOPM, 0, 0, o125_mix, ARRAY_SIZE(o125_mix)), -+}; -+ -+static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { -+ {"I150", NULL, "ETDM Capture"}, -+ {"I151", NULL, "ETDM Capture"}, -+ {"ETDM Playback", NULL, "O124"}, -+ {"ETDM Playback", NULL, "O125"}, -+ {"O124", "I032_Switch", "I032"}, -+ {"O125", "I033_Switch", "I033"}, -+}; -+ -+/* dai ops */ -+static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ int ret; -+ -+ ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); -+ if (ret) -+ return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); -+ -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, 0); -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, 0); -+ -+ return 0; -+} -+ -+static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, -+ CLK_OUT5_PDN); -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, -+ CLK_IN5_PDN); -+ -+ clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); -+} -+ -+static unsigned int get_etdm_ch_fixup(unsigned int channels) -+{ -+ if (channels > 16) -+ return 24; -+ else if (channels > 8) -+ return 16; -+ else if (channels > 4) -+ return 8; -+ else if (channels > 2) -+ return 4; -+ else -+ return 2; -+} -+ -+static int mtk_dai_etdm_config(struct mtk_base_afe *afe, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai, -+ int stream) -+{ -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; -+ unsigned int rate = params_rate(params); -+ unsigned int etdm_rate = mt7986_etdm_rate_transform(afe->dev, rate); -+ unsigned int afe_rate = mt7986_afe_rate_transform(afe->dev, rate); -+ unsigned int channels = params_channels(params); -+ unsigned int bit_width = params_width(params); -+ unsigned int wlen = get_etdm_wlen(bit_width); -+ unsigned int val = 0; -+ unsigned int mask = 0; -+ -+ dev_dbg(afe->dev, "%s(), stream %d, rate %u, bitwidth %u\n", -+ __func__, stream, rate, bit_width); -+ -+ /* CON0 */ -+ mask |= ETDM_BIT_LEN_MASK; -+ val |= FIELD_PREP(ETDM_BIT_LEN_MASK, bit_width - 1); -+ mask |= ETDM_WRD_LEN_MASK; -+ val |= FIELD_PREP(ETDM_WRD_LEN_MASK, wlen - 1); -+ mask |= ETDM_FMT_MASK; -+ val |= FIELD_PREP(ETDM_FMT_MASK, etdm_data->format); -+ mask |= ETDM_CH_NUM_MASK; -+ val |= FIELD_PREP(ETDM_CH_NUM_MASK, get_etdm_ch_fixup(channels) - 1); -+ mask |= RELATCH_SRC_MASK; -+ val |= FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK); -+ -+ switch (stream) { -+ case SNDRV_PCM_STREAM_PLAYBACK: -+ /* set ETDM_OUT5_CON0 */ -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, mask, val); -+ -+ /* set ETDM_OUT5_CON4 */ -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, -+ OUT_RELATCH_MASK, OUT_RELATCH(afe_rate)); -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, -+ OUT_CLK_SRC_MASK, OUT_CLK_SRC(APLL_CLK)); -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, -+ OUT_SEL_FS_MASK, OUT_SEL_FS(etdm_rate)); -+ -+ /* set ETDM_OUT5_CON5 */ -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON5, -+ ETDM_CLK_DIV_MASK, ETDM_CLK_DIV); -+ break; -+ case SNDRV_PCM_STREAM_CAPTURE: -+ /* set ETDM_IN5_CON0 */ -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, mask, val); -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, -+ ETDM_SYNC_MASK, ETDM_SYNC); -+ -+ /* set ETDM_IN5_CON2 */ -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON2, -+ IN_CLK_SRC_MASK, IN_CLK_SRC(APLL_CLK)); -+ -+ /* set ETDM_IN5_CON3 */ -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON3, -+ IN_SEL_FS_MASK, IN_SEL_FS(etdm_rate)); -+ -+ /* set ETDM_IN5_CON4 */ -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON4, -+ IN_RELATCH_MASK, IN_RELATCH(afe_rate)); -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); -+ -+ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK); -+ mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE); -+ -+ return 0; -+} -+ -+static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, -+ struct snd_soc_dai *dai) -+{ -+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); -+ -+ dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id); -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, -+ ETDM_EN); -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, -+ ETDM_EN); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK, -+ 0); -+ regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK, -+ 0); -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -+{ -+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ struct mtk_dai_etdm_priv *etdm_data; -+ void *priv_data; -+ -+ switch (dai->id) { -+ case MT7986_DAI_ETDM: -+ break; -+ default: -+ dev_warn(afe->dev, "%s(), id %d not support\n", -+ __func__, dai->id); -+ return -EINVAL; -+ } -+ -+ priv_data = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_etdm_priv), -+ GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ afe_priv->dai_priv[dai->id] = priv_data; -+ etdm_data = afe_priv->dai_priv[dai->id]; -+ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; -+ break; -+ case SND_SOC_DAIFMT_DSP_A: -+ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA; -+ break; -+ case SND_SOC_DAIFMT_DSP_B: -+ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ etdm_data->bck_inv = false; -+ etdm_data->lrck_inv = false; -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ etdm_data->bck_inv = false; -+ etdm_data->lrck_inv = true; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ etdm_data->bck_inv = true; -+ etdm_data->lrck_inv = false; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ etdm_data->bck_inv = true; -+ etdm_data->lrck_inv = true; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBM_CFM: -+ etdm_data->slave_mode = true; -+ break; -+ case SND_SOC_DAIFMT_CBS_CFS: -+ etdm_data->slave_mode = false; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { -+ .startup = mtk_dai_etdm_startup, -+ .shutdown = mtk_dai_etdm_shutdown, -+ .hw_params = mtk_dai_etdm_hw_params, -+ .trigger = mtk_dai_etdm_trigger, -+ .set_fmt = mtk_dai_etdm_set_fmt, -+}; -+ -+/* dai driver */ -+#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ -+ SNDRV_PCM_RATE_88200 |\ -+ SNDRV_PCM_RATE_96000 |\ -+ SNDRV_PCM_RATE_176400 |\ -+ SNDRV_PCM_RATE_192000) -+ -+#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ -+ SNDRV_PCM_FMTBIT_S24_LE |\ -+ SNDRV_PCM_FMTBIT_S32_LE) -+ -+static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = { -+ { -+ .name = "ETDM", -+ .id = MT7986_DAI_ETDM, -+ .capture = { -+ .stream_name = "ETDM Capture", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = MTK_ETDM_RATES, -+ .formats = MTK_ETDM_FORMATS, -+ }, -+ .playback = { -+ .stream_name = "ETDM Playback", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = MTK_ETDM_RATES, -+ .formats = MTK_ETDM_FORMATS, -+ }, -+ .ops = &mtk_dai_etdm_ops, -+ .symmetric_rate = 1, -+ .symmetric_sample_bits = 1, -+ }, -+}; -+ -+int mt7986_dai_etdm_register(struct mtk_base_afe *afe) -+{ -+ struct mtk_base_afe_dai *dai; -+ -+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); -+ if (!dai) -+ return -ENOMEM; -+ -+ list_add(&dai->list, &afe->sub_dais); -+ -+ dai->dai_drivers = mtk_dai_etdm_driver; -+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver); -+ -+ dai->dapm_widgets = mtk_dai_etdm_widgets; -+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets); -+ dai->dapm_routes = mtk_dai_etdm_routes; -+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes); -+ -+ return 0; -+} diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch b/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch deleted file mode 100644 index b899b963d2..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-03-ASoC-mediatek-mt7986-add-platform-driver.patch +++ /dev/null @@ -1,685 +0,0 @@ -From fc7776dee86bc07d22820a904760a95f49a2f12e Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:35 +0800 -Subject: [PATCH 3/9] ASoC: mediatek: mt7986: add platform driver - -Add mt7986 platform driver. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-4-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - sound/soc/mediatek/Kconfig | 10 + - sound/soc/mediatek/Makefile | 1 + - sound/soc/mediatek/mt7986/Makefile | 8 + - sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 622 +++++++++++++++++++++ - 4 files changed, 641 insertions(+) - create mode 100644 sound/soc/mediatek/mt7986/Makefile - create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-pcm.c - ---- a/sound/soc/mediatek/Kconfig -+++ b/sound/soc/mediatek/Kconfig -@@ -54,6 +54,16 @@ config SND_SOC_MT6797_MT6351 - Select Y if you have such device. - If unsure select "N". - -+config SND_SOC_MT7986 -+ tristate "ASoC support for Mediatek MT7986 chip" -+ depends on ARCH_MEDIATEK -+ select SND_SOC_MEDIATEK -+ help -+ This adds ASoC platform driver support for MediaTek MT7986 chip -+ that can be used with other codecs. -+ Select Y if you have such device. -+ If unsure select "N". -+ - config SND_SOC_MT8173 - tristate "ASoC support for Mediatek MT8173 chip" - depends on ARCH_MEDIATEK ---- a/sound/soc/mediatek/Makefile -+++ b/sound/soc/mediatek/Makefile -@@ -2,6 +2,7 @@ - obj-$(CONFIG_SND_SOC_MEDIATEK) += common/ - obj-$(CONFIG_SND_SOC_MT2701) += mt2701/ - obj-$(CONFIG_SND_SOC_MT6797) += mt6797/ -+obj-$(CONFIG_SND_SOC_MT7986) += mt7986/ - obj-$(CONFIG_SND_SOC_MT8173) += mt8173/ - obj-$(CONFIG_SND_SOC_MT8183) += mt8183/ - obj-$(CONFIG_SND_SOC_MT8186) += mt8186/ ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/Makefile -@@ -0,0 +1,8 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+# platform driver -+snd-soc-mt7986-afe-objs := \ -+ mt7986-afe-pcm.o \ -+ mt7986-dai-etdm.o -+ -+obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c -@@ -0,0 +1,622 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * MediaTek ALSA SoC AFE platform driver for MT7986 -+ * -+ * Copyright (c) 2023 MediaTek Inc. -+ * Authors: Vic Wu -+ * Maso Huang -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mt7986-afe-common.h" -+#include "mt7986-reg.h" -+#include "../common/mtk-afe-platform-driver.h" -+#include "../common/mtk-afe-fe-dai.h" -+ -+enum { -+ MTK_AFE_RATE_8K = 0, -+ MTK_AFE_RATE_11K = 1, -+ MTK_AFE_RATE_12K = 2, -+ MTK_AFE_RATE_16K = 4, -+ MTK_AFE_RATE_22K = 5, -+ MTK_AFE_RATE_24K = 6, -+ MTK_AFE_RATE_32K = 8, -+ MTK_AFE_RATE_44K = 9, -+ MTK_AFE_RATE_48K = 10, -+ MTK_AFE_RATE_88K = 13, -+ MTK_AFE_RATE_96K = 14, -+ MTK_AFE_RATE_176K = 17, -+ MTK_AFE_RATE_192K = 18, -+}; -+ -+enum { -+ CLK_INFRA_AUD_BUS_CK = 0, -+ CLK_INFRA_AUD_26M_CK, -+ CLK_INFRA_AUD_L_CK, -+ CLK_INFRA_AUD_AUD_CK, -+ CLK_INFRA_AUD_EG2_CK, -+ CLK_NUM -+}; -+ -+static const char *aud_clks[CLK_NUM] = { -+ [CLK_INFRA_AUD_BUS_CK] = "aud_bus_ck", -+ [CLK_INFRA_AUD_26M_CK] = "aud_26m_ck", -+ [CLK_INFRA_AUD_L_CK] = "aud_l_ck", -+ [CLK_INFRA_AUD_AUD_CK] = "aud_aud_ck", -+ [CLK_INFRA_AUD_EG2_CK] = "aud_eg2_ck", -+}; -+ -+unsigned int mt7986_afe_rate_transform(struct device *dev, unsigned int rate) -+{ -+ switch (rate) { -+ case 8000: -+ return MTK_AFE_RATE_8K; -+ case 11025: -+ return MTK_AFE_RATE_11K; -+ case 12000: -+ return MTK_AFE_RATE_12K; -+ case 16000: -+ return MTK_AFE_RATE_16K; -+ case 22050: -+ return MTK_AFE_RATE_22K; -+ case 24000: -+ return MTK_AFE_RATE_24K; -+ case 32000: -+ return MTK_AFE_RATE_32K; -+ case 44100: -+ return MTK_AFE_RATE_44K; -+ case 48000: -+ return MTK_AFE_RATE_48K; -+ case 88200: -+ return MTK_AFE_RATE_88K; -+ case 96000: -+ return MTK_AFE_RATE_96K; -+ case 176400: -+ return MTK_AFE_RATE_176K; -+ case 192000: -+ return MTK_AFE_RATE_192K; -+ default: -+ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", -+ __func__, rate, MTK_AFE_RATE_48K); -+ return MTK_AFE_RATE_48K; -+ } -+} -+ -+static const struct snd_pcm_hardware mt7986_afe_hardware = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_MMAP_VALID, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE, -+ .period_bytes_min = 256, -+ .period_bytes_max = 4 * 48 * 1024, -+ .periods_min = 2, -+ .periods_max = 256, -+ .buffer_bytes_max = 8 * 48 * 1024, -+ .fifo_size = 0, -+}; -+ -+static int mt7986_memif_fs(struct snd_pcm_substream *substream, -+ unsigned int rate) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); -+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); -+ -+ return mt7986_afe_rate_transform(afe->dev, rate); -+} -+ -+static int mt7986_irq_fs(struct snd_pcm_substream *substream, -+ unsigned int rate) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); -+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); -+ -+ return mt7986_afe_rate_transform(afe->dev, rate); -+} -+ -+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\ -+ SNDRV_PCM_RATE_88200 |\ -+ SNDRV_PCM_RATE_96000 |\ -+ SNDRV_PCM_RATE_176400 |\ -+ SNDRV_PCM_RATE_192000) -+ -+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ -+ SNDRV_PCM_FMTBIT_S24_LE |\ -+ SNDRV_PCM_FMTBIT_S32_LE) -+ -+static struct snd_soc_dai_driver mt7986_memif_dai_driver[] = { -+ /* FE DAIs: memory intefaces to CPU */ -+ { -+ .name = "DL1", -+ .id = MT7986_MEMIF_DL1, -+ .playback = { -+ .stream_name = "DL1", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = MTK_PCM_RATES, -+ .formats = MTK_PCM_FORMATS, -+ }, -+ .ops = &mtk_afe_fe_ops, -+ }, -+ { -+ .name = "UL1", -+ .id = MT7986_MEMIF_VUL12, -+ .capture = { -+ .stream_name = "UL1", -+ .channels_min = 1, -+ .channels_max = 2, -+ .rates = MTK_PCM_RATES, -+ .formats = MTK_PCM_FORMATS, -+ }, -+ .ops = &mtk_afe_fe_ops, -+ }, -+}; -+ -+static const struct snd_kcontrol_new o018_mix[] = { -+ SOC_DAPM_SINGLE_AUTODISABLE("I150_Switch", AFE_CONN018_4, 22, 1, 0), -+}; -+ -+static const struct snd_kcontrol_new o019_mix[] = { -+ SOC_DAPM_SINGLE_AUTODISABLE("I151_Switch", AFE_CONN019_4, 23, 1, 0), -+}; -+ -+static const struct snd_soc_dapm_widget mt7986_memif_widgets[] = { -+ /* DL */ -+ SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0), -+ SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0), -+ -+ /* UL */ -+ SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0, -+ o018_mix, ARRAY_SIZE(o018_mix)), -+ SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0, -+ o019_mix, ARRAY_SIZE(o019_mix)), -+}; -+ -+static const struct snd_soc_dapm_route mt7986_memif_routes[] = { -+ {"I032", NULL, "DL1"}, -+ {"I033", NULL, "DL1"}, -+ {"UL1", NULL, "O018"}, -+ {"UL1", NULL, "O019"}, -+ {"O018", "I150_Switch", "I150"}, -+ {"O019", "I151_Switch", "I151"}, -+}; -+ -+static const struct snd_soc_component_driver mt7986_afe_pcm_dai_component = { -+ .name = "mt7986-afe-pcm-dai", -+}; -+ -+static const struct mtk_base_memif_data memif_data[MT7986_MEMIF_NUM] = { -+ [MT7986_MEMIF_DL1] = { -+ .name = "DL1", -+ .id = MT7986_MEMIF_DL1, -+ .reg_ofs_base = AFE_DL0_BASE, -+ .reg_ofs_cur = AFE_DL0_CUR, -+ .reg_ofs_end = AFE_DL0_END, -+ .reg_ofs_base_msb = AFE_DL0_BASE_MSB, -+ .reg_ofs_cur_msb = AFE_DL0_CUR_MSB, -+ .reg_ofs_end_msb = AFE_DL0_END_MSB, -+ .fs_reg = AFE_DL0_CON0, -+ .fs_shift = DL0_MODE_SFT, -+ .fs_maskbit = DL0_MODE_MASK, -+ .mono_reg = AFE_DL0_CON0, -+ .mono_shift = DL0_MONO_SFT, -+ .enable_reg = AFE_DL0_CON0, -+ .enable_shift = DL0_ON_SFT, -+ .hd_reg = AFE_DL0_CON0, -+ .hd_shift = DL0_HD_MODE_SFT, -+ .hd_align_reg = AFE_DL0_CON0, -+ .hd_align_mshift = DL0_HALIGN_SFT, -+ .pbuf_reg = AFE_DL0_CON0, -+ .pbuf_shift = DL0_PBUF_SIZE_SFT, -+ .minlen_reg = AFE_DL0_CON0, -+ .minlen_shift = DL0_MINLEN_SFT, -+ }, -+ [MT7986_MEMIF_VUL12] = { -+ .name = "VUL12", -+ .id = MT7986_MEMIF_VUL12, -+ .reg_ofs_base = AFE_VUL0_BASE, -+ .reg_ofs_cur = AFE_VUL0_CUR, -+ .reg_ofs_end = AFE_VUL0_END, -+ .reg_ofs_base_msb = AFE_VUL0_BASE_MSB, -+ .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB, -+ .reg_ofs_end_msb = AFE_VUL0_END_MSB, -+ .fs_reg = AFE_VUL0_CON0, -+ .fs_shift = VUL0_MODE_SFT, -+ .fs_maskbit = VUL0_MODE_MASK, -+ .mono_reg = AFE_VUL0_CON0, -+ .mono_shift = VUL0_MONO_SFT, -+ .enable_reg = AFE_VUL0_CON0, -+ .enable_shift = VUL0_ON_SFT, -+ .hd_reg = AFE_VUL0_CON0, -+ .hd_shift = VUL0_HD_MODE_SFT, -+ .hd_align_reg = AFE_VUL0_CON0, -+ .hd_align_mshift = VUL0_HALIGN_SFT, -+ }, -+}; -+ -+static const struct mtk_base_irq_data irq_data[MT7986_IRQ_NUM] = { -+ [MT7986_IRQ_0] = { -+ .id = MT7986_IRQ_0, -+ .irq_cnt_reg = AFE_IRQ0_MCU_CFG1, -+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, -+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, -+ .irq_fs_reg = AFE_IRQ0_MCU_CFG0, -+ .irq_fs_shift = IRQ_MCU_MODE_SFT, -+ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, -+ .irq_en_reg = AFE_IRQ0_MCU_CFG0, -+ .irq_en_shift = IRQ_MCU_ON_SFT, -+ .irq_clr_reg = AFE_IRQ_MCU_CLR, -+ .irq_clr_shift = IRQ0_MCU_CLR_SFT, -+ }, -+ [MT7986_IRQ_1] = { -+ .id = MT7986_IRQ_1, -+ .irq_cnt_reg = AFE_IRQ1_MCU_CFG1, -+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, -+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, -+ .irq_fs_reg = AFE_IRQ1_MCU_CFG0, -+ .irq_fs_shift = IRQ_MCU_MODE_SFT, -+ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, -+ .irq_en_reg = AFE_IRQ1_MCU_CFG0, -+ .irq_en_shift = IRQ_MCU_ON_SFT, -+ .irq_clr_reg = AFE_IRQ_MCU_CLR, -+ .irq_clr_shift = IRQ1_MCU_CLR_SFT, -+ }, -+ [MT7986_IRQ_2] = { -+ .id = MT7986_IRQ_2, -+ .irq_cnt_reg = AFE_IRQ2_MCU_CFG1, -+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, -+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, -+ .irq_fs_reg = AFE_IRQ2_MCU_CFG0, -+ .irq_fs_shift = IRQ_MCU_MODE_SFT, -+ .irq_fs_maskbit = IRQ_MCU_MODE_MASK, -+ .irq_en_reg = AFE_IRQ2_MCU_CFG0, -+ .irq_en_shift = IRQ_MCU_ON_SFT, -+ .irq_clr_reg = AFE_IRQ_MCU_CLR, -+ .irq_clr_shift = IRQ2_MCU_CLR_SFT, -+ }, -+}; -+ -+static bool mt7986_is_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ /* -+ * Those auto-gen regs are read-only, so put it as volatile because -+ * volatile registers cannot be cached, which means that they cannot -+ * be set when power is off -+ */ -+ -+ switch (reg) { -+ case AFE_DL0_CUR_MSB: -+ case AFE_DL0_CUR: -+ case AFE_DL0_RCH_MON: -+ case AFE_DL0_LCH_MON: -+ case AFE_VUL0_CUR_MSB: -+ case AFE_VUL0_CUR: -+ case AFE_IRQ_MCU_STATUS: -+ case AFE_MEMIF_RD_MON: -+ case AFE_MEMIF_WR_MON: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config mt7986_afe_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .volatile_reg = mt7986_is_volatile_reg, -+ .max_register = AFE_MAX_REGISTER, -+ .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1), -+}; -+ -+static int mt7986_init_clock(struct mtk_base_afe *afe) -+{ -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ int ret, i; -+ -+ afe_priv->clks = devm_kcalloc(afe->dev, CLK_NUM, -+ sizeof(*afe_priv->clks), GFP_KERNEL); -+ if (!afe_priv->clks) -+ return -ENOMEM; -+ afe_priv->num_clks = CLK_NUM; -+ -+ for (i = 0; i < afe_priv->num_clks; i++) -+ afe_priv->clks[i].id = aud_clks[i]; -+ -+ ret = devm_clk_bulk_get(afe->dev, afe_priv->num_clks, afe_priv->clks); -+ if (ret) -+ return dev_err_probe(afe->dev, ret, "Failed to get clocks\n"); -+ -+ return 0; -+} -+ -+static irqreturn_t mt7986_afe_irq_handler(int irq_id, void *dev) -+{ -+ struct mtk_base_afe *afe = dev; -+ struct mtk_base_afe_irq *irq; -+ u32 mcu_en, status, status_mcu; -+ int i, ret; -+ irqreturn_t irq_ret = IRQ_HANDLED; -+ -+ /* get irq that is sent to MCU */ -+ regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en); -+ -+ ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status); -+ /* only care IRQ which is sent to MCU */ -+ status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS; -+ -+ if (ret || status_mcu == 0) { -+ dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x, mcu_en 0x%x\n", -+ __func__, ret, status, mcu_en); -+ -+ irq_ret = IRQ_NONE; -+ goto err_irq; -+ } -+ -+ for (i = 0; i < MT7986_MEMIF_NUM; i++) { -+ struct mtk_base_afe_memif *memif = &afe->memif[i]; -+ -+ if (!memif->substream) -+ continue; -+ -+ if (memif->irq_usage < 0) -+ continue; -+ -+ irq = &afe->irqs[memif->irq_usage]; -+ -+ if (status_mcu & (1 << irq->irq_data->irq_en_shift)) -+ snd_pcm_period_elapsed(memif->substream); -+ } -+ -+err_irq: -+ /* clear irq */ -+ regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, status_mcu); -+ -+ return irq_ret; -+} -+ -+static int mt7986_afe_runtime_suspend(struct device *dev) -+{ -+ struct mtk_base_afe *afe = dev_get_drvdata(dev); -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ -+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) -+ goto skip_regmap; -+ -+ /* disable clk*/ -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0x3fff); -+ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, 0); -+ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, 0); -+ -+ /* make sure all irq status are cleared, twice intended */ -+ regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CLR, 0xffff, 0xffff); -+ -+skip_regmap: -+ clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); -+ -+ return 0; -+} -+ -+static int mt7986_afe_runtime_resume(struct device *dev) -+{ -+ struct mtk_base_afe *afe = dev_get_drvdata(dev); -+ struct mt7986_afe_private *afe_priv = afe->platform_priv; -+ int ret; -+ -+ ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); -+ if (ret) -+ return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); -+ -+ if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) -+ return 0; -+ -+ /* enable clk*/ -+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0); -+ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, -+ AUD_APLL2_EN); -+ regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, -+ AUD_26M_EN); -+ -+ return 0; -+} -+ -+static int mt7986_afe_component_probe(struct snd_soc_component *component) -+{ -+ return mtk_afe_add_sub_dai_control(component); -+} -+ -+static const struct snd_soc_component_driver mt7986_afe_component = { -+ .name = AFE_PCM_NAME, -+ .probe = mt7986_afe_component_probe, -+ .pointer = mtk_afe_pcm_pointer, -+ .pcm_construct = mtk_afe_pcm_new, -+}; -+ -+static int mt7986_dai_memif_register(struct mtk_base_afe *afe) -+{ -+ struct mtk_base_afe_dai *dai; -+ -+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); -+ if (!dai) -+ return -ENOMEM; -+ -+ list_add(&dai->list, &afe->sub_dais); -+ -+ dai->dai_drivers = mt7986_memif_dai_driver; -+ dai->num_dai_drivers = ARRAY_SIZE(mt7986_memif_dai_driver); -+ -+ dai->dapm_widgets = mt7986_memif_widgets; -+ dai->num_dapm_widgets = ARRAY_SIZE(mt7986_memif_widgets); -+ dai->dapm_routes = mt7986_memif_routes; -+ dai->num_dapm_routes = ARRAY_SIZE(mt7986_memif_routes); -+ -+ return 0; -+} -+ -+typedef int (*dai_register_cb)(struct mtk_base_afe *); -+static const dai_register_cb dai_register_cbs[] = { -+ mt7986_dai_etdm_register, -+ mt7986_dai_memif_register, -+}; -+ -+static int mt7986_afe_pcm_dev_probe(struct platform_device *pdev) -+{ -+ struct mtk_base_afe *afe; -+ struct mt7986_afe_private *afe_priv; -+ struct device *dev; -+ int i, irq_id, ret; -+ -+ afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); -+ if (!afe) -+ return -ENOMEM; -+ platform_set_drvdata(pdev, afe); -+ -+ afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), -+ GFP_KERNEL); -+ if (!afe->platform_priv) -+ return -ENOMEM; -+ -+ afe_priv = afe->platform_priv; -+ afe->dev = &pdev->dev; -+ dev = afe->dev; -+ -+ afe->base_addr = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(afe->base_addr)) -+ return PTR_ERR(afe->base_addr); -+ -+ /* initial audio related clock */ -+ ret = mt7986_init_clock(afe); -+ if (ret) -+ return dev_err_probe(dev, ret, "Cannot initialize clocks\n"); -+ -+ ret = devm_pm_runtime_enable(dev); -+ if (ret) -+ return ret; -+ -+ /* enable clock for regcache get default value from hw */ -+ afe_priv->pm_runtime_bypass_reg_ctl = true; -+ pm_runtime_get_sync(&pdev->dev); -+ -+ afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, -+ &mt7986_afe_regmap_config); -+ -+ pm_runtime_put_sync(&pdev->dev); -+ if (IS_ERR(afe->regmap)) -+ return PTR_ERR(afe->regmap); -+ -+ afe_priv->pm_runtime_bypass_reg_ctl = false; -+ -+ /* init memif */ -+ afe->memif_size = MT7986_MEMIF_NUM; -+ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), -+ GFP_KERNEL); -+ if (!afe->memif) -+ return -ENOMEM; -+ -+ for (i = 0; i < afe->memif_size; i++) { -+ afe->memif[i].data = &memif_data[i]; -+ afe->memif[i].irq_usage = -1; -+ } -+ -+ mutex_init(&afe->irq_alloc_lock); -+ -+ /* irq initialize */ -+ afe->irqs_size = MT7986_IRQ_NUM; -+ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), -+ GFP_KERNEL); -+ if (!afe->irqs) -+ return -ENOMEM; -+ -+ for (i = 0; i < afe->irqs_size; i++) -+ afe->irqs[i].irq_data = &irq_data[i]; -+ -+ /* request irq */ -+ irq_id = platform_get_irq(pdev, 0); -+ if (irq_id < 0) { -+ ret = irq_id; -+ return dev_err_probe(dev, ret, "No irq found\n"); -+ } -+ ret = devm_request_irq(dev, irq_id, mt7986_afe_irq_handler, -+ IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to request irq for asys-isr\n"); -+ -+ /* init sub_dais */ -+ INIT_LIST_HEAD(&afe->sub_dais); -+ -+ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { -+ ret = dai_register_cbs[i](afe); -+ if (ret) -+ return dev_err_probe(dev, ret, "DAI register failed, i: %d\n", i); -+ } -+ -+ /* init dai_driver and component_driver */ -+ ret = mtk_afe_combine_sub_dai(afe); -+ if (ret) -+ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n"); -+ -+ afe->mtk_afe_hardware = &mt7986_afe_hardware; -+ afe->memif_fs = mt7986_memif_fs; -+ afe->irq_fs = mt7986_irq_fs; -+ -+ afe->runtime_resume = mt7986_afe_runtime_resume; -+ afe->runtime_suspend = mt7986_afe_runtime_suspend; -+ -+ /* register component */ -+ ret = devm_snd_soc_register_component(&pdev->dev, -+ &mt7986_afe_component, -+ NULL, 0); -+ if (ret) -+ return dev_err_probe(dev, ret, "Cannot register AFE component\n"); -+ -+ ret = devm_snd_soc_register_component(afe->dev, -+ &mt7986_afe_pcm_dai_component, -+ afe->dai_drivers, -+ afe->num_dai_drivers); -+ if (ret) -+ return dev_err_probe(dev, ret, "Cannot register PCM DAI component\n"); -+ -+ return 0; -+} -+ -+static void mt7986_afe_pcm_dev_remove(struct platform_device *pdev) -+{ -+ pm_runtime_disable(&pdev->dev); -+ if (!pm_runtime_status_suspended(&pdev->dev)) -+ mt7986_afe_runtime_suspend(&pdev->dev); -+} -+ -+static const struct of_device_id mt7986_afe_pcm_dt_match[] = { -+ { .compatible = "mediatek,mt7986-afe" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, mt7986_afe_pcm_dt_match); -+ -+static const struct dev_pm_ops mt7986_afe_pm_ops = { -+ SET_RUNTIME_PM_OPS(mt7986_afe_runtime_suspend, -+ mt7986_afe_runtime_resume, NULL) -+}; -+ -+static struct platform_driver mt7986_afe_pcm_driver = { -+ .driver = { -+ .name = "mt7986-audio", -+ .of_match_table = mt7986_afe_pcm_dt_match, -+ .pm = &mt7986_afe_pm_ops, -+ }, -+ .probe = mt7986_afe_pcm_dev_probe, -+ .remove_new = mt7986_afe_pcm_dev_remove, -+}; -+module_platform_driver(mt7986_afe_pcm_driver); -+ -+MODULE_DESCRIPTION("MediaTek SoC AFE platform driver for ALSA MT7986"); -+MODULE_AUTHOR("Vic Wu "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch b/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch deleted file mode 100644 index dd354c04e3..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch +++ /dev/null @@ -1,243 +0,0 @@ -From ddf6abc1c78072f8ccad59166be95f0ca5af8ca4 Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:36 +0800 -Subject: [PATCH 4/9] ASoC: mediatek: mt7986: add machine driver with wm8960 - -Add support for mt7986 board with wm8960. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-5-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - sound/soc/mediatek/Kconfig | 10 ++ - sound/soc/mediatek/mt7986/Makefile | 1 + - sound/soc/mediatek/mt7986/mt7986-wm8960.c | 196 ++++++++++++++++++++++ - 3 files changed, 207 insertions(+) - create mode 100644 sound/soc/mediatek/mt7986/mt7986-wm8960.c - ---- a/sound/soc/mediatek/Kconfig -+++ b/sound/soc/mediatek/Kconfig -@@ -64,6 +64,16 @@ config SND_SOC_MT7986 - Select Y if you have such device. - If unsure select "N". - -+config SND_SOC_MT7986_WM8960 -+ tristate "ASoc Audio driver for MT7986 with WM8960 codec" -+ depends on SND_SOC_MT7986 && I2C -+ select SND_SOC_WM8960 -+ help -+ This adds support for ASoC machine driver for MediaTek MT7986 -+ boards with the WM8960 codecs. -+ Select Y if you have such device. -+ If unsure select "N". -+ - config SND_SOC_MT8173 - tristate "ASoC support for Mediatek MT8173 chip" - depends on ARCH_MEDIATEK ---- a/sound/soc/mediatek/mt7986/Makefile -+++ b/sound/soc/mediatek/mt7986/Makefile -@@ -6,3 +6,4 @@ snd-soc-mt7986-afe-objs := \ - mt7986-dai-etdm.o - - obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o -+obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o ---- /dev/null -+++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c -@@ -0,0 +1,196 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * mt7986-wm8960.c -- MT7986-WM8960 ALSA SoC machine driver -+ * -+ * Copyright (c) 2023 MediaTek Inc. -+ * Authors: Vic Wu -+ * Maso Huang -+ */ -+ -+#include -+#include -+ -+#include "mt7986-afe-common.h" -+ -+struct mt7986_wm8960_priv { -+ struct device_node *platform_node; -+ struct device_node *codec_node; -+}; -+ -+static const struct snd_soc_dapm_widget mt7986_wm8960_widgets[] = { -+ SND_SOC_DAPM_HP("Headphone", NULL), -+ SND_SOC_DAPM_MIC("AMIC", NULL), -+}; -+ -+static const struct snd_kcontrol_new mt7986_wm8960_controls[] = { -+ SOC_DAPM_PIN_SWITCH("Headphone"), -+ SOC_DAPM_PIN_SWITCH("AMIC"), -+}; -+ -+SND_SOC_DAILINK_DEFS(playback, -+ DAILINK_COMP_ARRAY(COMP_CPU("DL1")), -+ DAILINK_COMP_ARRAY(COMP_DUMMY()), -+ DAILINK_COMP_ARRAY(COMP_EMPTY())); -+ -+SND_SOC_DAILINK_DEFS(capture, -+ DAILINK_COMP_ARRAY(COMP_CPU("UL1")), -+ DAILINK_COMP_ARRAY(COMP_DUMMY()), -+ DAILINK_COMP_ARRAY(COMP_EMPTY())); -+ -+SND_SOC_DAILINK_DEFS(codec, -+ DAILINK_COMP_ARRAY(COMP_CPU("ETDM")), -+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")), -+ DAILINK_COMP_ARRAY(COMP_EMPTY())); -+ -+static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = { -+ /* FE */ -+ { -+ .name = "wm8960-playback", -+ .stream_name = "wm8960-playback", -+ .trigger = {SND_SOC_DPCM_TRIGGER_POST, -+ SND_SOC_DPCM_TRIGGER_POST}, -+ .dynamic = 1, -+ .dpcm_playback = 1, -+ SND_SOC_DAILINK_REG(playback), -+ }, -+ { -+ .name = "wm8960-capture", -+ .stream_name = "wm8960-capture", -+ .trigger = {SND_SOC_DPCM_TRIGGER_POST, -+ SND_SOC_DPCM_TRIGGER_POST}, -+ .dynamic = 1, -+ .dpcm_capture = 1, -+ SND_SOC_DAILINK_REG(capture), -+ }, -+ /* BE */ -+ { -+ .name = "wm8960-codec", -+ .no_pcm = 1, -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS | -+ SND_SOC_DAIFMT_GATED, -+ .dpcm_playback = 1, -+ .dpcm_capture = 1, -+ SND_SOC_DAILINK_REG(codec), -+ }, -+}; -+ -+static struct snd_soc_card mt7986_wm8960_card = { -+ .name = "mt7986-wm8960", -+ .owner = THIS_MODULE, -+ .dai_link = mt7986_wm8960_dai_links, -+ .num_links = ARRAY_SIZE(mt7986_wm8960_dai_links), -+ .controls = mt7986_wm8960_controls, -+ .num_controls = ARRAY_SIZE(mt7986_wm8960_controls), -+ .dapm_widgets = mt7986_wm8960_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(mt7986_wm8960_widgets), -+}; -+ -+static int mt7986_wm8960_machine_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = &mt7986_wm8960_card; -+ struct snd_soc_dai_link *dai_link; -+ struct device_node *platform, *codec; -+ struct mt7986_wm8960_priv *priv; -+ int ret, i; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ platform = of_get_child_by_name(pdev->dev.of_node, "platform"); -+ -+ if (platform) { -+ priv->platform_node = of_parse_phandle(platform, "sound-dai", 0); -+ of_node_put(platform); -+ -+ if (!priv->platform_node) { -+ dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n"); -+ return -EINVAL; -+ } -+ } else { -+ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); -+ return -EINVAL; -+ } -+ -+ for_each_card_prelinks(card, i, dai_link) { -+ if (dai_link->platforms->name) -+ continue; -+ dai_link->platforms->of_node = priv->platform_node; -+ } -+ -+ card->dev = &pdev->dev; -+ -+ codec = of_get_child_by_name(pdev->dev.of_node, "codec"); -+ -+ if (codec) { -+ priv->codec_node = of_parse_phandle(codec, "sound-dai", 0); -+ of_node_put(codec); -+ -+ if (!priv->codec_node) { -+ of_node_put(priv->platform_node); -+ dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n"); -+ return -EINVAL; -+ } -+ } else { -+ of_node_put(priv->platform_node); -+ dev_err(&pdev->dev, "Property 'codec' missing or invalid\n"); -+ return -EINVAL; -+ } -+ -+ for_each_card_prelinks(card, i, dai_link) { -+ if (dai_link->codecs->name) -+ continue; -+ dai_link->codecs->of_node = priv->codec_node; -+ } -+ -+ ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to parse audio-routing: %d\n", ret); -+ goto err_of_node_put; -+ } -+ -+ ret = devm_snd_soc_register_card(&pdev->dev, card); -+ if (ret) { -+ dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret); -+ goto err_of_node_put; -+ } -+ -+err_of_node_put: -+ of_node_put(priv->codec_node); -+ of_node_put(priv->platform_node); -+ return ret; -+} -+ -+static void mt7986_wm8960_machine_remove(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = platform_get_drvdata(pdev); -+ struct mt7986_wm8960_priv *priv = snd_soc_card_get_drvdata(card); -+ -+ of_node_put(priv->codec_node); -+ of_node_put(priv->platform_node); -+} -+ -+static const struct of_device_id mt7986_wm8960_machine_dt_match[] = { -+ {.compatible = "mediatek,mt7986-wm8960-sound"}, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, mt7986_wm8960_machine_dt_match); -+ -+static struct platform_driver mt7986_wm8960_machine = { -+ .driver = { -+ .name = "mt7986-wm8960", -+ .of_match_table = mt7986_wm8960_machine_dt_match, -+ }, -+ .probe = mt7986_wm8960_machine_probe, -+ .remove_new = mt7986_wm8960_machine_remove, -+}; -+ -+module_platform_driver(mt7986_wm8960_machine); -+ -+/* Module information */ -+MODULE_DESCRIPTION("MT7986 WM8960 ALSA SoC machine driver"); -+MODULE_AUTHOR("Vic Wu "); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("mt7986 wm8960 soc card"); diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch b/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch deleted file mode 100644 index 8cf0b5464a..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-05-ASoC-dt-bindings-mediatek-mt7986-wm8960-add-mt7986-w.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 72469f950b629e57e60fbcbefed45e083619b986 Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:37 +0800 -Subject: [PATCH 5/9] ASoC: dt-bindings: mediatek,mt7986-wm8960: add - mt7986-wm8960 document - -Add document for mt7986 board with wm8960. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-6-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - .../sound/mediatek,mt7986-wm8960.yaml | 67 +++++++++++++++++++ - 1 file changed, 67 insertions(+) - create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt7986-wm8960.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/mediatek,mt7986-wm8960.yaml -@@ -0,0 +1,67 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/sound/mediatek,mt7986-wm8960.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MediaTek MT7986 sound card with WM8960 codec -+ -+maintainers: -+ - Maso Huang -+ -+allOf: -+ - $ref: sound-card-common.yaml# -+ -+properties: -+ compatible: -+ const: mediatek,mt7986-wm8960-sound -+ -+ platform: -+ type: object -+ additionalProperties: false -+ properties: -+ sound-dai: -+ description: The phandle of MT7986 platform. -+ maxItems: 1 -+ required: -+ - sound-dai -+ -+ codec: -+ type: object -+ additionalProperties: false -+ properties: -+ sound-dai: -+ description: The phandle of wm8960 codec. -+ maxItems: 1 -+ required: -+ - sound-dai -+ -+unevaluatedProperties: false -+ -+required: -+ - compatible -+ - audio-routing -+ - platform -+ - codec -+ -+examples: -+ - | -+ sound { -+ compatible = "mediatek,mt7986-wm8960-sound"; -+ model = "mt7986-wm8960"; -+ audio-routing = -+ "Headphone", "HP_L", -+ "Headphone", "HP_R", -+ "LINPUT1", "AMIC", -+ "RINPUT1", "AMIC"; -+ -+ platform { -+ sound-dai = <&afe>; -+ }; -+ -+ codec { -+ sound-dai = <&wm8960>; -+ }; -+ }; -+ -+... diff --git a/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch b/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch deleted file mode 100644 index 236d6a217c..0000000000 --- a/target/linux/mediatek/patches-6.6/860-v6.6-06-ASoC-dt-bindings-mediatek-mt7986-afe-add-audio-afe-d.patch +++ /dev/null @@ -1,180 +0,0 @@ -From d16202eb38585adbc16e32d11188dbc2127015de Mon Sep 17 00:00:00 2001 -From: Maso Huang -Date: Thu, 17 Aug 2023 18:13:38 +0800 -Subject: [PATCH 6/9] ASoC: dt-bindings: mediatek,mt7986-afe: add audio afe - document - -Add mt7986 audio afe document. - -Signed-off-by: Maso Huang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230817101338.18782-7-maso.huang@mediatek.com -Signed-off-by: Mark Brown ---- - .../bindings/sound/mediatek,mt7986-afe.yaml | 160 ++++++++++++++++++ - 1 file changed, 160 insertions(+) - create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt7986-afe.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/sound/mediatek,mt7986-afe.yaml -@@ -0,0 +1,160 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/sound/mediatek,mt7986-afe.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MediaTek AFE PCM controller for MT7986 -+ -+maintainers: -+ - Maso Huang -+ -+properties: -+ compatible: -+ oneOf: -+ - const: mediatek,mt7986-afe -+ - items: -+ - enum: -+ - mediatek,mt7981-afe -+ - mediatek,mt7988-afe -+ - const: mediatek,mt7986-afe -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ clocks: -+ minItems: 5 -+ items: -+ - description: audio bus clock -+ - description: audio 26M clock -+ - description: audio intbus clock -+ - description: audio hopping clock -+ - description: audio pll clock -+ - description: mux for pcm_mck -+ - description: audio i2s/pcm mck -+ -+ clock-names: -+ minItems: 5 -+ items: -+ - const: bus_ck -+ - const: 26m_ck -+ - const: l_ck -+ - const: aud_ck -+ - const: eg2_ck -+ - const: sel -+ - const: i2s_m -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - clock-names -+ -+allOf: -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: mediatek,mt7986-afe -+ then: -+ properties: -+ clocks: -+ items: -+ - description: audio bus clock -+ - description: audio 26M clock -+ - description: audio intbus clock -+ - description: audio hopping clock -+ - description: audio pll clock -+ clock-names: -+ items: -+ - const: bus_ck -+ - const: 26m_ck -+ - const: l_ck -+ - const: aud_ck -+ - const: eg2_ck -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: mediatek,mt7981-afe -+ then: -+ properties: -+ clocks: -+ items: -+ - description: audio bus clock -+ - description: audio 26M clock -+ - description: audio intbus clock -+ - description: audio hopping clock -+ - description: audio pll clock -+ - description: mux for pcm_mck -+ clock-names: -+ items: -+ - const: bus_ck -+ - const: 26m_ck -+ - const: l_ck -+ - const: aud_ck -+ - const: eg2_ck -+ - const: sel -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: mediatek,mt7988-afe -+ then: -+ properties: -+ clocks: -+ items: -+ - description: audio bus clock -+ - description: audio 26M clock -+ - description: audio intbus clock -+ - description: audio hopping clock -+ - description: audio pll clock -+ - description: mux for pcm_mck -+ - description: audio i2s/pcm mck -+ clock-names: -+ items: -+ - const: bus_ck -+ - const: 26m_ck -+ - const: l_ck -+ - const: aud_ck -+ - const: eg2_ck -+ - const: sel -+ - const: i2s_m -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ -+ afe@11210000 { -+ compatible = "mediatek,mt7986-afe"; -+ reg = <0x11210000 0x9000>; -+ interrupts = ; -+ clocks = <&infracfg_ao CLK_INFRA_AUD_BUS_CK>, -+ <&infracfg_ao CLK_INFRA_AUD_26M_CK>, -+ <&infracfg_ao CLK_INFRA_AUD_L_CK>, -+ <&infracfg_ao CLK_INFRA_AUD_AUD_CK>, -+ <&infracfg_ao CLK_INFRA_AUD_EG2_CK>; -+ clock-names = "bus_ck", -+ "26m_ck", -+ "l_ck", -+ "aud_ck", -+ "eg2_ck"; -+ assigned-clocks = <&topckgen CLK_TOP_A1SYS_SEL>, -+ <&topckgen CLK_TOP_AUD_L_SEL>, -+ <&topckgen CLK_TOP_A_TUNER_SEL>; -+ assigned-clock-parents = <&topckgen CLK_TOP_APLL2_D4>, -+ <&apmixedsys CLK_APMIXED_APLL2>, -+ <&topckgen CLK_TOP_APLL2_D4>; -+ }; -+ -+... From f4223abd8faa683991a5077f5d01a7e1483629e1 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 01:59:21 +0000 Subject: [PATCH 079/108] mediatek: 6.6: drop patches backported as fixes Drop patches backported as fixes in later kernel version. Signed-off-by: Daniel Golle --- ...-define-3W-max-power-to-both-SFP-on-.patch | 34 --- ...rm64-dts-mt7986-change-cooling-trips.patch | 59 ---- ...t7986-change-thermal-trips-on-BPI-R3.patch | 38 --- ...-ge-soc-sync-driver-with-MediaTek-SD.patch | 270 ------------------ ...rs-mediatek-Fix-probe-for-THERMAL_V2.patch | 33 --- 5 files changed, 434 deletions(-) delete mode 100644 target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch delete mode 100644 target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch delete mode 100644 target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch delete mode 100644 target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch diff --git a/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch b/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch deleted file mode 100644 index 8cba3b2059..0000000000 --- a/target/linux/mediatek/patches-6.6/020-v6.7-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch +++ /dev/null @@ -1,34 +0,0 @@ -From f8ed4088ed9c61ae92193da6130d04c37e7b19f2 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:33 +0200 -Subject: [PATCH 20/22] arm64: dts: mt7986: define 3W max power to both SFP on - BPI-R3 - -All SFP power supplies are connected to the system VDD33 which is 3v3/8A. -Set 3A per SFP slot to allow SFPs work which need more power than the -default 1W. - -Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -126,6 +126,7 @@ - compatible = "sff,sfp"; - i2c-bus = <&i2c_sfp1>; - los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; -+ maximum-power-milliwatt = <3000>; - mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; - tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; -@@ -137,6 +138,7 @@ - i2c-bus = <&i2c_sfp2>; - los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; - mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; -+ maximum-power-milliwatt = <3000>; - tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; - }; diff --git a/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch b/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch deleted file mode 100644 index 20d4468cf0..0000000000 --- a/target/linux/mediatek/patches-6.6/021-v6.7-arm64-dts-mt7986-change-cooling-trips.patch +++ /dev/null @@ -1,59 +0,0 @@ -From aa3d6df9803c267725dc72286bb91602b7579882 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:34 +0200 -Subject: [PATCH 21/22] arm64: dts: mt7986: change cooling trips - -Add Critical and hot trips for emergency system shutdown and limiting -system load. - -Change passive trip to active to make sure fan is activated on the -lowest trip. - -Fixes: 1f5be05132f3 ("arm64: dts: mt7986: add thermal-zones") -Suggested-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -610,22 +610,34 @@ - thermal-sensors = <&thermal 0>; - - trips { -+ cpu_trip_crit: crit { -+ temperature = <125000>; -+ hysteresis = <2000>; -+ type = "critical"; -+ }; -+ -+ cpu_trip_hot: hot { -+ temperature = <120000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - -- cpu_trip_active_low: active-low { -+ cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - -- cpu_trip_passive: passive { -- temperature = <40000>; -+ cpu_trip_active_low: active-low { -+ temperature = <60000>; - hysteresis = <2000>; -- type = "passive"; -+ type = "active"; - }; - }; - }; diff --git a/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch b/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch deleted file mode 100644 index 7166ab6a14..0000000000 --- a/target/linux/mediatek/patches-6.6/022-v6.7-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 6ddf23526955b8dbedfeaa57e691261fd73f9d4e Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:35 +0200 -Subject: [PATCH 22/22] arm64: dts: mt7986: change thermal trips on BPI-R3 - -Apply new naming after mt7986 thermal trips were changed. - -Fixes: c26f779a2295 ("arm64: dts: mt7986: add pwm-fan and cooling-maps to BPI-R3 dts") -Suggested-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -152,16 +152,16 @@ - trip = <&cpu_trip_active_high>; - }; - -- cpu-active-low { -+ cpu-active-med { - /* active: set fan to cooling level 1 */ - cooling-device = <&fan 1 1>; -- trip = <&cpu_trip_active_low>; -+ trip = <&cpu_trip_active_med>; - }; - -- cpu-passive { -- /* passive: set fan to cooling level 0 */ -+ cpu-active-low { -+ /* active: set fan to cooling level 0 */ - cooling-device = <&fan 0 0>; -- trip = <&cpu_trip_passive>; -+ trip = <&cpu_trip_active_low>; - }; - }; - }; diff --git a/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch b/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch deleted file mode 100644 index 5daa62b6b7..0000000000 --- a/target/linux/mediatek/patches-6.6/734-v6.8-net-phy-mediatek-ge-soc-sync-driver-with-MediaTek-SD.patch +++ /dev/null @@ -1,270 +0,0 @@ -From f2195279c234c0f618946424b8236026126bc595 Mon Sep 17 00:00:00 2001 -Message-ID: -From: Daniel Golle -Date: Wed, 24 Jan 2024 02:27:04 +0000 -Subject: [PATCH net] net: phy: mediatek-ge-soc: sync driver with MediaTek SDK -To: Daniel Golle , - Qingfang Deng , - SkyLake Huang , - Andrew Lunn , - Heiner Kallweit , - Russell King , - David S. Miller , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Matthias Brugger , - AngeloGioacchino Del Regno , - netdev@vger.kernel.org, - linux-kernel@vger.kernel.org, - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org - -Sync initialization and calibration routines with MediaTek's reference -driver. Improves compliance and resolves link stability issues with -CH340 IoT devices connected to MT798x built-in PHYs. - -Fixes: 98c485eaf509 ("net: phy: add driver for MediaTek SoC built-in GE PHYs") -Signed-off-by: Daniel Golle ---- - drivers/net/phy/mediatek-ge-soc.c | 147 ++++++++++++++++-------------- - 1 file changed, 81 insertions(+), 66 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -491,7 +491,7 @@ static int tx_r50_fill_result(struct phy - u16 reg, val; - - if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) -- bias = -2; -+ bias = -1; - - val = clamp_val(bias + tx_r50_cal_val, 0, 63); - -@@ -707,6 +707,11 @@ restore: - static void mt798x_phy_common_finetune(struct phy_device *phydev) - { - 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); -+ - /* EnabRandUpdTrig = 1 */ - __phy_write(phydev, 0x11, 0x2f00); - __phy_write(phydev, 0x12, 0xe); -@@ -717,15 +722,56 @@ static void mt798x_phy_common_finetune(s - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x83aa); - -- /* TrFreeze = 0 */ -+ /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ -+ __phy_write(phydev, 0x11, 0x240); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9680); -+ -+ /* TrFreeze = 0 (mt7988 default) */ - __phy_write(phydev, 0x11, 0x0); - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x9686); - -+ /* SSTrKp100 = 5 */ -+ /* SSTrKf100 = 6 */ -+ /* SSTrKp1000Mas = 5 */ -+ /* SSTrKf1000Mas = 6 */ - /* SSTrKp1000Slv = 5 */ -+ /* SSTrKf1000Slv = 6 */ - __phy_write(phydev, 0x11, 0xbaef); - __phy_write(phydev, 0x12, 0x2e); - __phy_write(phydev, 0x10, 0x968c); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+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); -+ /* 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); - - /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, - * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 -@@ -740,7 +786,7 @@ static void mt798x_phy_common_finetune(s - __phy_write(phydev, 0x10, 0x8ec0); - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - -- /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ -+ /* 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)); -@@ -773,48 +819,6 @@ static void mt798x_phy_common_finetune(s - 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, -@@ -829,17 +833,7 @@ static void mt7988_phy_finetune(struct p - /* 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); -@@ -847,13 +841,27 @@ static void mt7988_phy_finetune(struct p - - /* VgaDecRate is 1 at default on mt7988 */ - -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, -+ * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 -+ */ -+ __phy_write(phydev, 0x11, 0xb90a); -+ __phy_write(phydev, 0x12, 0x6f); -+ __phy_write(phydev, 0x10, 0x8f82); -+ -+ /* RemAckCntLimitCtrl = 1 */ -+ __phy_write(phydev, 0x11, 0xfbba); -+ __phy_write(phydev, 0x12, 0xc3); -+ __phy_write(phydev, 0x10, 0x87f8); - -- 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 = 10 */ -+ 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, 0xa)); -+ -+ /* rg_tr_lpf_cnt_val = 1023 */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff); - } - - static void mt798x_phy_eee(struct phy_device *phydev) -@@ -886,11 +894,11 @@ static void mt798x_phy_eee(struct phy_de - 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)); -+ /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, -+ MTK_PHY_LPI_TXPCS_LOC_RCV); - -+ /* This also fixes some IoT issues, such as CH340 */ - 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) | -@@ -924,7 +932,7 @@ static void mt798x_phy_eee(struct phy_de - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x9690); - -- /* REG_EEE_st2TrKf1000 = 3 */ -+ /* REG_EEE_st2TrKf1000 = 2 */ - __phy_write(phydev, 0x11, 0x114f); - __phy_write(phydev, 0x12, 0x2); - __phy_write(phydev, 0x10, 0x969a); -@@ -949,7 +957,7 @@ static void mt798x_phy_eee(struct phy_de - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x96b8); - -- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ -+ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ - __phy_write(phydev, 0x11, 0x1463); - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x96ca); -@@ -1461,6 +1469,13 @@ static int mt7988_phy_probe(struct phy_d - if (err) - return err; - -+ /* Disable TX power saving at probing to: -+ * 1. Meet common mode compliance test criteria -+ * 2. Make sure that TX-VCM calibration works fine -+ */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -+ - return mt798x_phy_calibration(phydev); - } - diff --git a/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch b/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch deleted file mode 100644 index 88f383c4ae..0000000000 --- a/target/linux/mediatek/patches-6.6/830-v6.7-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e6f43063f2fe9f08b34797bc6d223f7d63b01910 Mon Sep 17 00:00:00 2001 -From: Markus Schneider-Pargmann -Date: Mon, 18 Sep 2023 12:07:06 +0200 -Subject: [PATCH 39/42] thermal/drivers/mediatek: Fix probe for THERMAL_V2 - -Fix the probe function to call mtk_thermal_release_periodic_ts for -everything != MTK_THERMAL_V1. This was accidentally changed from V1 -to V2 in the original patch. - -Reported-by: Frank Wunderlich -Closes: https://lore.kernel.org/lkml/B0B3775B-B8D1-4284-814F-4F41EC22F532@public-files.de/ -Reported-by: Daniel Lezcano -Closes: https://lore.kernel.org/lkml/07a569b9-e691-64ea-dd65-3b49842af33d@linaro.org/ -Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks") -Signed-off-by: Markus Schneider-Pargmann -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Daniel Lezcano -Link: https://lore.kernel.org/r/20230918100706.1229239-1-msp@baylibre.com ---- - drivers/thermal/mediatek/auxadc_thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/thermal/mediatek/auxadc_thermal.c -+++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -1268,7 +1268,7 @@ static int mtk_thermal_probe(struct plat - - mtk_thermal_turn_on_buffer(mt, apmixed_base); - -- if (mt->conf->version != MTK_THERMAL_V2) -+ if (mt->conf->version != MTK_THERMAL_V1) - mtk_thermal_release_periodic_ts(mt, auxadc_base); - - if (mt->conf->version == MTK_THERMAL_V1) From 5b4bbd1097d0ec2d13bd7d73f9d51027e19f0970 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 1 Mar 2024 02:22:25 +0000 Subject: [PATCH 080/108] mediatek: 6.6: refresh patches Refresh patches and fix changed path for 32-bit mediatek boards 'arch/arm/dts' -> 'arch/arm/dts/mediatek' Signed-off-by: Daniel Golle --- .../041-block-fit-partition-parser.patch | 10 +-- .../100-dts-update-mt7622-rfb1.patch | 4 +- .../101-dts-update-mt7629-rfb.patch | 4 +- .../105-dts-mt7622-enable-pstore.patch | 2 +- .../110-dts-fix-bpi2-console.patch | 4 +- .../112-dts-fix-bpi64-lan-names.patch | 2 +- .../114-dts-bpi64-disable-rtc.patch | 12 +-- .../130-dts-mt7629-add-snand-support.patch | 14 ++-- .../131-dts-mt7622-add-snand-support.patch | 2 +- ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 4 +- ...s-mt7623-eip97-inside-secure-support.patch | 6 +- .../160-dts-mt7623-bpi-r2-earlycon.patch | 4 +- ...1-dts-mt7623-bpi-r2-mmc-device-order.patch | 4 +- .../162-dts-mt7623-bpi-r2-led-aliases.patch | 4 +- ...163-dts-mt7623-bpi-r2-ethernet-alias.patch | 4 +- ...ts-mt7623-bpi-r2-rootdisk-for-fitblk.patch | 10 +-- ...-dts-mediatek-mt7622-fix-GICv2-range.patch | 2 +- .../193-dts-mt7623-thermal_zone_fix.patch | 6 +- ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 12 +-- ...981-topckgen-flag-SGM_REG_SEL-as-cri.patch | 2 +- ...-mediatek-add-support-for-MT7988-SoC.patch | 20 ++--- ...-pcw_chg_bit-control-for-PLLs-of-MT7.patch | 6 +- ...-mediatek-add-drivers-for-MT7988-SoC.patch | 10 +-- ...hdog-mediatek-mt7988-add-wdt-support.patch | 22 ++--- .../330-snand-mtk-bmt-support.patch | 6 +- .../331-mt7622-rfb1-enable-bmt.patch | 2 +- ...Add-support-for-the-Fidelix-FM35X1GA.patch | 13 +-- ...freq-mediatek-Add-support-for-MT7988.patch | 4 +- ...ypto-add-eip97-inside-secure-support.patch | 2 +- ...01-crypto-fix-eip97-cache-incoherent.patch | 2 +- .../patches-6.6/410-bt-mtk-serial-fix.patch | 2 +- ...xx-Move-chip_config-to-driver-s-priv.patch | 4 +- ...-Add-support-for-dynamic-calibration.patch | 22 ++--- ...ers-spi-mem-Add-spi-calibration-hook.patch | 2 +- ...and-Add-calibration-support-for-spin.patch | 4 +- ...nor-Add-calibration-support-for-spi-.patch | 10 +-- .../500-gsw-rtl8367s-mt7622-support.patch | 6 +- ...-don-t-use-SGMII-AN-if-using-phylink.patch | 10 +-- ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 6 +- ...-control-buffer-enablement-on-MT7896.patch | 2 +- ...i2c-mt65xx-allow-optional-pmic-clock.patch | 2 +- ...-mt7986-add-sound-overlay-for-bpi-r3.patch | 2 +- ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 2 +- .../901-arm-add-cmdline-override.patch | 6 +- .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 2 +- .../911-dts-mt7622-bpi-r64-add-rootdisk.patch | 8 +- .../930-spi-mt65xx-enable-sel-clk.patch | 2 +- ...986-move-cpuboot-in-a-dedicated-node.patch | 6 +- ...tk_wed-move-dlm-a-dedicated-dts-node.patch | 4 +- ...-mt7986-move-ilm-in-a-dedicated-node.patch | 6 +- ...-mt7986-move-dlm-in-a-dedicated-node.patch | 6 +- .../950-smartrg-i2c-led-driver.patch | 6 +- ...iatek-split-tx-and-rx-fields-in-mtk_.patch | 82 +++++++++---------- ...iatek-use-QDMA-instead-of-ADMAv2-on-.patch | 16 ++-- ...ernet-mtk_eth_soc-fix-WED-wifi-reset.patch | 6 +- 55 files changed, 209 insertions(+), 214 deletions(-) diff --git a/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch b/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch index bb87c20a91..feb50c157b 100644 --- a/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch +++ b/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch @@ -19,7 +19,7 @@ Subject: [PATCH] kernel: add block fit partition parser --- a/block/blk.h +++ b/block/blk.h -@@ -414,6 +414,8 @@ void blk_free_ext_minor(unsigned int min +@@ -423,6 +423,8 @@ void blk_free_ext_minor(unsigned int min #define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 @@ -82,7 +82,7 @@ Subject: [PATCH] kernel: add block fit partition parser #include "check.h" -@@ -48,6 +51,9 @@ static int (*check_part[])(struct parsed +@@ -48,6 +51,9 @@ static int (*const check_part[])(struct #ifdef CONFIG_EFI_PARTITION efi_partition, /* this must come before msdos */ #endif @@ -92,7 +92,7 @@ Subject: [PATCH] kernel: add block fit partition parser #ifdef CONFIG_SGI_PARTITION sgi_partition, #endif -@@ -439,6 +445,11 @@ static struct block_device *add_partitio +@@ -433,6 +439,11 @@ static struct block_device *add_partitio goto out_del; } @@ -104,7 +104,7 @@ Subject: [PATCH] kernel: add block fit partition parser /* everything is up and running, commence */ err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL); if (err) -@@ -631,6 +642,11 @@ static bool blk_add_partition(struct gen +@@ -625,6 +636,11 @@ static bool blk_add_partition(struct gen (state->parts[p].flags & ADDPART_FLAG_RAID)) md_autodetect_dev(part->bd_dev); @@ -193,7 +193,7 @@ Subject: [PATCH] kernel: add block fit partition parser set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -432,7 +432,9 @@ int ubiblock_create(struct ubi_volume_in +@@ -411,7 +411,9 @@ int ubiblock_create(struct ubi_volume_in ret = -ENODEV; goto out_cleanup_disk; } diff --git a/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch index d5bd9a316b..ed07eb367d 100644 --- a/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch +++ b/target/linux/mediatek/patches-6.6/100-dts-update-mt7622-rfb1.patch @@ -68,7 +68,7 @@ }; port@4 { -@@ -240,7 +239,22 @@ +@@ -239,7 +238,22 @@ status = "okay"; }; @@ -91,7 +91,7 @@ /* eMMC is shared pin with parallel NAND */ emmc_pins_default: emmc-pins-default { mux { -@@ -517,11 +531,11 @@ +@@ -516,11 +530,11 @@ }; &sata { diff --git a/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch index b1770371b0..166d97ab01 100644 --- a/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch +++ b/target/linux/mediatek/patches-6.6/101-dts-update-mt7629-rfb.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts +--- a/arch/arm/boot/dts/mediatek/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mediatek/mt7629-rfb.dts @@ -18,6 +18,7 @@ chosen { diff --git a/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch b/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch index 93da722e72..3e36a503ed 100644 --- a/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch +++ b/target/linux/mediatek/patches-6.6/105-dts-mt7622-enable-pstore.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -134,6 +134,13 @@ +@@ -135,6 +135,13 @@ #size-cells = <2>; ranges; diff --git a/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch index 8dc53d2985..d96d3b9581 100644 --- a/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch +++ b/target/linux/mediatek/patches-6.6/110-dts-fix-bpi2-console.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -19,6 +19,7 @@ chosen { diff --git a/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch index b012a48d75..816683e626 100644 --- a/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch +++ b/target/linux/mediatek/patches-6.6/112-dts-fix-bpi64-lan-names.patch @@ -8,7 +8,7 @@ }; chosen { -@@ -160,22 +161,22 @@ +@@ -164,22 +165,22 @@ port@1 { reg = <1>; diff --git a/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch index 0d324084b1..5a2c603486 100644 --- a/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch +++ b/target/linux/mediatek/patches-6.6/114-dts-bpi64-disable-rtc.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -556,12 +556,16 @@ +@@ -587,6 +587,10 @@ status = "okay"; }; @@ -9,13 +9,5 @@ +}; + &sata { -- status = "disable"; -+ status = "disabled"; + status = "disabled"; }; - - &sata_phy { -- status = "disable"; -+ status = "disabled"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch index 82654e683c..c7cd525a5c 100644 --- a/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.6/130-dts-mt7629-add-snand-support.patch @@ -5,13 +5,13 @@ Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 Signed-off-by: Xiangsheng Hou --- - arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ + arch/arm/boot/dts/mediatek/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/mediatek/mt7629.dtsi | 22 ++++++++++++++++ 3 files changed, 79 insertions(+) ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -272,6 +272,27 @@ +--- a/arch/arm/boot/dts/mediatek/mt7629.dtsi ++++ b/arch/arm/boot/dts/mediatek/mt7629.dtsi +@@ -271,6 +271,27 @@ status = "disabled"; }; @@ -39,8 +39,8 @@ Signed-off-by: Xiangsheng Hou spi: spi@1100a000 { compatible = "mediatek,mt7629-spi", "mediatek,mt7622-spi"; ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts +--- a/arch/arm/boot/dts/mediatek/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mediatek/mt7629-rfb.dts @@ -255,6 +255,50 @@ }; }; diff --git a/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch index d6e0ab1d41..a804087367 100644 --- a/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.6/131-dts-mt7622-add-snand-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -534,6 +534,65 @@ +@@ -533,6 +533,65 @@ status = "disabled"; }; diff --git a/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch index 117d5abde6..6d1e2f1ed2 100644 --- a/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch +++ b/target/linux/mediatek/patches-6.6/140-dts-fix-wmac-support-for-mt7622-rfb1.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -575,7 +575,7 @@ +@@ -574,7 +574,7 @@ reg = <0x140000 0x0080000>; }; @@ -9,7 +9,7 @@ label = "Factory"; reg = <0x1c0000 0x0100000>; }; -@@ -636,5 +636,6 @@ +@@ -635,5 +635,6 @@ &wmac { pinctrl-names = "default"; pinctrl-0 = <&wmac_pins>; diff --git a/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch index 0860a22c37..d54e3ed1fd 100644 --- a/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch +++ b/target/linux/mediatek/patches-6.6/150-dts-mt7623-eip97-inside-secure-support.patch @@ -1,6 +1,6 @@ ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -984,17 +984,15 @@ +--- a/arch/arm/boot/dts/mediatek/mt7623.dtsi ++++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi +@@ -995,17 +995,15 @@ }; crypto: crypto@1b240000 { diff --git a/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch b/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch index 091cffc3c0..5e02fb56ac 100644 --- a/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch +++ b/target/linux/mediatek/patches-6.6/160-dts-mt7623-bpi-r2-earlycon.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -19,7 +19,7 @@ chosen { diff --git a/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch b/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch index d1bafc1526..4b48219966 100644 --- a/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch +++ b/target/linux/mediatek/patches-6.6/161-dts-mt7623-bpi-r2-mmc-device-order.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -15,6 +15,8 @@ aliases { diff --git a/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch b/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch index f6745add5b..2d02a760f0 100644 --- a/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch +++ b/target/linux/mediatek/patches-6.6/162-dts-mt7623-bpi-r2-led-aliases.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -17,6 +17,10 @@ serial2 = &uart2; mmc0 = &mmc0; diff --git a/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch b/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch index b1dd75a414..b7e4a8c5cc 100644 --- a/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch +++ b/target/linux/mediatek/patches-6.6/163-dts-mt7623-bpi-r2-ethernet-alias.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -15,6 +15,7 @@ aliases { diff --git a/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch b/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch index 2675aa2589..f1a182b044 100644 --- a/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch +++ b/target/linux/mediatek/patches-6.6/164-dts-mt7623-bpi-r2-rootdisk-for-fitblk.patch @@ -1,5 +1,5 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -26,7 +26,9 @@ chosen { @@ -11,7 +11,7 @@ }; connector { -@@ -315,6 +317,20 @@ +@@ -338,6 +340,20 @@ vmmc-supply = <®_3p3v>; vqmmc-supply = <®_1p8v>; non-removable; @@ -32,7 +32,7 @@ }; &mmc1 { -@@ -328,6 +344,20 @@ +@@ -351,6 +367,20 @@ cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; vqmmc-supply = <®_3p3v>; @@ -52,4 +52,4 @@ + }; }; - &mt6323_leds { + &mt6323keys { diff --git a/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch b/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch index 1e04d23a0e..bd0c785fde 100644 --- a/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch +++ b/target/linux/mediatek/patches-6.6/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch @@ -95,7 +95,7 @@ Signed-off-by: Daniel Golle --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -346,7 +346,7 @@ +@@ -347,7 +347,7 @@ #interrupt-cells = <3>; interrupt-parent = <&gic>; reg = <0 0x10310000 0 0x1000>, diff --git a/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch b/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch index 1cfb53d620..da9ba5f305 100644 --- a/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch +++ b/target/linux/mediatek/patches-6.6/193-dts-mt7623-thermal_zone_fix.patch @@ -25,11 +25,11 @@ zone, and gives some operational headroom. Signed-off-by: Bruno Umuarama --- - arch/arm/boot/dts/mt7623.dtsi | 4 ++-- + arch/arm/boot/dts/mediatek/mt7623.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi +--- a/arch/arm/boot/dts/mediatek/mt7623.dtsi ++++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi @@ -160,13 +160,13 @@ trips { diff --git a/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch index 6347533aa8..e07aa5662b 100644 --- a/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch +++ b/target/linux/mediatek/patches-6.6/200-phy-phy-mtk-tphy-Add-hifsys-support.patch @@ -9,7 +9,7 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -17,6 +17,8 @@ +@@ -18,6 +18,8 @@ #include #include #include @@ -18,9 +18,9 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support #include "phy-mtk-io.h" -@@ -264,6 +266,9 @@ +@@ -267,6 +269,9 @@ - #define TPHY_CLKS_CNT 2 + #define USER_BUF_LEN(count) min_t(size_t, 8, (count)) +#define HIF_SYSCFG1 0x14 +#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) @@ -28,7 +28,7 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support enum mtk_phy_version { MTK_PHY_V1 = 1, MTK_PHY_V2, -@@ -331,6 +336,7 @@ struct mtk_tphy { +@@ -334,6 +339,7 @@ struct mtk_tphy { void __iomem *sif_base; /* only shared sif */ const struct mtk_phy_pdata *pdata; struct mtk_phy_instance **phys; @@ -36,7 +36,7 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support int nphys; int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ int src_coef; /* coefficient for slew rate calibrate */ -@@ -596,6 +602,10 @@ static void pcie_phy_instance_init(struc +@@ -951,6 +957,10 @@ static void pcie_phy_instance_init(struc if (tphy->pdata->version != MTK_PHY_V1) return; @@ -47,7 +47,7 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG0, P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H, FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) | -@@ -1241,6 +1251,16 @@ static int mtk_tphy_probe(struct platfor +@@ -1597,6 +1607,16 @@ static int mtk_tphy_probe(struct platfor &tphy->src_coef); } diff --git a/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch b/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch index 8820d57f01..dd06c4e096 100644 --- a/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch +++ b/target/linux/mediatek/patches-6.6/232-clk-mediatek-mt7981-topckgen-flag-SGM_REG_SEL-as-cri.patch @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle --- a/drivers/clk/mediatek/clk-mt7981-topckgen.c +++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c -@@ -359,8 +359,9 @@ static const struct mtk_mux top_muxes[] +@@ -357,8 +357,9 @@ static const struct mtk_mux top_muxes[] MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, 0x1C0, 21), diff --git a/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch index a365f0860b..c63510b5e2 100644 --- a/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch +++ b/target/linux/mediatek/patches-6.6/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch @@ -1,6 +1,6 @@ --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig -@@ -141,6 +141,13 @@ config PINCTRL_MT7986 +@@ -187,6 +187,13 @@ config PINCTRL_MT7986 default ARM64 && ARCH_MEDIATEK select PINCTRL_MTK_MOORE @@ -12,15 +12,15 @@ + select PINCTRL_MTK_MOORE + config PINCTRL_MT8167 - bool "Mediatek MT8167 pin control" + bool "MediaTek MT8167 pin control" depends on OF --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile -@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o - obj-$(CONFIG_PINCTRL_MT7981) += 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 +@@ -27,6 +27,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o + obj-$(CONFIG_PINCTRL_MT7981) += 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 diff --git a/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch b/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch index ca37fc793a..40e87bddfb 100644 --- a/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch +++ b/target/linux/mediatek/patches-6.6/248-v6.8-clk-mediatek-add-pcw_chg_bit-control-for-PLLs-of-MT7.patch @@ -28,7 +28,7 @@ Signed-off-by: Stephen Boyd #define AUDPLL_TUNER_EN BIT(31) -@@ -141,7 +141,8 @@ static void mtk_pll_set_rate_regs(struct +@@ -114,7 +114,8 @@ static void mtk_pll_set_rate_regs(struct pll->data->pcw_shift); val |= pcw << pll->data->pcw_shift; writel(val, pll->pcw_addr); @@ -40,11 +40,11 @@ Signed-off-by: Stephen Boyd writel(val + 1, pll->tuner_addr); --- a/drivers/clk/mediatek/clk-pll.h +++ b/drivers/clk/mediatek/clk-pll.h -@@ -46,6 +46,7 @@ struct mtk_pll_data { +@@ -48,6 +48,7 @@ struct mtk_pll_data { const char *parent_name; u32 en_reg; u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ + u8 pcw_chg_bit; }; - int mtk_clk_register_plls(struct device_node *node, + /* diff --git a/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch index 61664b934c..dab08a5a39 100644 --- a/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch +++ b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch @@ -33,7 +33,7 @@ Signed-off-by: Stephen Boyd --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig -@@ -415,6 +415,15 @@ config COMMON_CLK_MT7986_ETHSYS +@@ -423,6 +423,15 @@ config COMMON_CLK_MT7986_ETHSYS This driver adds support for clocks for Ethernet and SGMII required on MediaTek MT7986 SoC. @@ -47,11 +47,11 @@ Signed-off-by: Stephen Boyd + required for various periperals found on this SoC. + config COMMON_CLK_MT8135 - bool "Clock driver for MediaTek MT8135" + tristate "Clock driver for MediaTek MT8135" depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile -@@ -60,6 +60,11 @@ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-m +@@ -62,6 +62,11 @@ 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 @@ -60,8 +60,8 @@ Signed-off-by: Stephen Boyd +obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-infracfg.o +obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-eth.o +obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-xfipll.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o - obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o + obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135-apmixedsys.o clk-mt8135.o + obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167-apmixedsys.o clk-mt8167.o obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7988-apmixed.c diff --git a/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch b/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch index cb49ce1d25..b89b385eeb 100644 --- a/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch +++ b/target/linux/mediatek/patches-6.6/251-v6.8-watchdog-mediatek-mt7988-add-wdt-support.patch @@ -18,7 +18,7 @@ Signed-off-by: Wim Van Sebroeck --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c -@@ -56,9 +56,13 @@ +@@ -58,9 +58,13 @@ #define WDT_SWSYSRST 0x18U #define WDT_SWSYS_RST_KEY 0x88000000 @@ -32,10 +32,10 @@ Signed-off-by: Wim Van Sebroeck static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout; -@@ -68,10 +72,12 @@ struct mtk_wdt_dev { - spinlock_t lock; /* protects WDT_SWSYSRST reg */ +@@ -71,10 +75,12 @@ struct mtk_wdt_dev { struct reset_controller_dev rcdev; bool disable_wdt_extrst; + bool reset_by_toprgu; + bool has_swsysrst_en; }; @@ -45,7 +45,7 @@ Signed-off-by: Wim Van Sebroeck }; static const struct mtk_wdt_data mt2712_data = { -@@ -82,6 +88,11 @@ static const struct mtk_wdt_data mt7986_ +@@ -89,6 +95,11 @@ static const struct mtk_wdt_data mt7986_ .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM, }; @@ -57,7 +57,7 @@ Signed-off-by: Wim Van Sebroeck static const struct mtk_wdt_data mt8183_data = { .toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM, }; -@@ -98,6 +109,28 @@ static const struct mtk_wdt_data mt8195_ +@@ -109,6 +120,28 @@ static const struct mtk_wdt_data mt8195_ .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM, }; @@ -86,7 +86,7 @@ Signed-off-by: Wim Van Sebroeck static int toprgu_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert) { -@@ -108,6 +141,9 @@ static int toprgu_reset_update(struct re +@@ -119,6 +152,9 @@ static int toprgu_reset_update(struct re spin_lock_irqsave(&data->lock, flags); @@ -96,7 +96,7 @@ Signed-off-by: Wim Van Sebroeck tmp = readl(data->wdt_base + WDT_SWSYSRST); if (assert) tmp |= BIT(id); -@@ -116,6 +152,9 @@ static int toprgu_reset_update(struct re +@@ -127,6 +163,9 @@ static int toprgu_reset_update(struct re tmp |= WDT_SWSYS_RST_KEY; writel(tmp, data->wdt_base + WDT_SWSYSRST); @@ -106,7 +106,7 @@ Signed-off-by: Wim Van Sebroeck spin_unlock_irqrestore(&data->lock, flags); return 0; -@@ -393,6 +432,8 @@ static int mtk_wdt_probe(struct platform +@@ -406,6 +445,8 @@ static int mtk_wdt_probe(struct platform wdt_data->toprgu_sw_rst_num); if (err) return err; @@ -115,11 +115,11 @@ Signed-off-by: Wim Van Sebroeck } mtk_wdt->disable_wdt_extrst = -@@ -427,6 +468,7 @@ static const struct of_device_id mtk_wdt - { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, +@@ -444,6 +485,7 @@ static const struct of_device_id mtk_wdt { .compatible = "mediatek,mt6589-wdt" }, + { .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data }, { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, + { .compatible = "mediatek,mt7988-wdt", .data = &mt7988_data }, { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, { .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data }, - { .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data }, + { .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data }, diff --git a/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch b/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch index 55a308e46c..8a4ec2bcbd 100644 --- a/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch +++ b/target/linux/mediatek/patches-6.6/330-snand-mtk-bmt-support.patch @@ -8,7 +8,7 @@ static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) { -@@ -1344,6 +1345,7 @@ static int spinand_probe(struct spi_mem +@@ -1345,6 +1346,7 @@ static int spinand_probe(struct spi_mem if (ret) return ret; @@ -16,7 +16,7 @@ ret = mtd_device_register(mtd, NULL, 0); if (ret) goto err_spinand_cleanup; -@@ -1351,6 +1353,7 @@ static int spinand_probe(struct spi_mem +@@ -1352,6 +1354,7 @@ static int spinand_probe(struct spi_mem return 0; err_spinand_cleanup: @@ -24,7 +24,7 @@ spinand_cleanup(spinand); return ret; -@@ -1369,6 +1372,7 @@ static int spinand_remove(struct spi_mem +@@ -1370,6 +1373,7 @@ static int spinand_remove(struct spi_mem if (ret) return ret; diff --git a/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch index 3e956701cd..6d6463aade 100644 --- a/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch +++ b/target/linux/mediatek/patches-6.6/331-mt7622-rfb1-enable-bmt.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -548,6 +548,7 @@ +@@ -547,6 +547,7 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; nand-ecc-engine = <&snfi>; diff --git a/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch b/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch index ec66363dc9..7188c254ba 100644 --- a/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch +++ b/target/linux/mediatek/patches-6.6/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch @@ -16,15 +16,16 @@ Signed-off-by: Davide Fioravanti --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile -@@ -1,3 +1,3 @@ +@@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o ato.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o ato.o esmt.o etron.o fidelix.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o +-spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o gigadevice.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o gigadevice.o + spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -940,6 +940,7 @@ static const struct nand_ops spinand_ops - static const struct spinand_manufacturer *spinand_manufacturers[] = { +@@ -941,6 +941,7 @@ static const struct spinand_manufacturer + &alliancememory_spinand_manufacturer, &ato_spinand_manufacturer, &esmt_c8_spinand_manufacturer, + &fidelix_spinand_manufacturer, @@ -112,7 +113,7 @@ Signed-off-by: Davide Fioravanti +}; --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h -@@ -263,6 +263,7 @@ struct spinand_manufacturer { +@@ -264,6 +264,7 @@ extern const struct spinand_manufacturer extern const struct spinand_manufacturer ato_spinand_manufacturer; extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer etron_spinand_manufacturer; diff --git a/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch index 49cd62d0ae..f7b62f1d94 100644 --- a/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch +++ b/target/linux/mediatek/patches-6.6/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch @@ -15,7 +15,7 @@ Signed-off-by: Sam Shih --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -709,6 +709,15 @@ static const struct mtk_cpufreq_platform +@@ -707,6 +707,15 @@ static const struct mtk_cpufreq_platform .ccifreq_supported = false, }; @@ -31,7 +31,7 @@ Signed-off-by: Sam Shih static const struct mtk_cpufreq_platform_data mt8183_platform_data = { .min_volt_shift = 100000, .max_volt_shift = 200000, -@@ -742,6 +751,7 @@ static const struct of_device_id mtk_cpu +@@ -740,6 +749,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 = &mt7623_platform_data }, diff --git a/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch index 25ca9485e4..5808a93495 100644 --- a/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch +++ b/target/linux/mediatek/patches-6.6/400-crypto-add-eip97-inside-secure-support.patch @@ -1,6 +1,6 @@ --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c -@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex +@@ -608,6 +608,14 @@ static int safexcel_hw_init(struct safex val |= EIP197_MST_CTRL_TX_MAX_CMD(5); writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); } diff --git a/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch index 186c66f687..bd22b3699b 100644 --- a/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch +++ b/target/linux/mediatek/patches-6.6/401-crypto-fix-eip97-cache-incoherent.patch @@ -1,6 +1,6 @@ --- a/drivers/crypto/inside-secure/safexcel.h +++ b/drivers/crypto/inside-secure/safexcel.h -@@ -737,6 +737,9 @@ enum safexcel_eip_version { +@@ -743,6 +743,9 @@ struct safexcel_priv_data { /* Priority we use for advertising our algorithms */ #define SAFEXCEL_CRA_PRIORITY 300 diff --git a/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch index 5b94c9216d..f377487975 100644 --- a/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch +++ b/target/linux/mediatek/patches-6.6/410-bt-mtk-serial-fix.patch @@ -19,7 +19,7 @@ }, [PORT_NPCM] = { .name = "Nuvoton 16550", -@@ -2773,6 +2773,11 @@ serial8250_do_set_termios(struct uart_po +@@ -2780,6 +2780,11 @@ serial8250_do_set_termios(struct uart_po unsigned long flags; unsigned int baud, quot, frac = 0; diff --git a/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch b/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch index 8c2c80d6bf..a0bd46c5b7 100644 --- a/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch +++ b/target/linux/mediatek/patches-6.6/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch @@ -94,9 +94,9 @@ Signed-off-by: SkyLake.Huang - if (!spi->controller_data) - spi->controller_data = (void *)&mtk_default_chip_info; - - if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) + if (mdata->dev_comp->need_pad_sel && spi_get_csgpiod(spi, 0)) /* CS de-asserted, gpiolib will handle inversion */ - gpiod_direction_output(spi->cs_gpiod, 0); + gpiod_direction_output(spi_get_csgpiod(spi, 0), 0); @@ -1138,6 +1126,10 @@ static int mtk_spi_probe(struct platform mdata = spi_master_get_devdata(master); mdata->dev_comp = device_get_match_data(dev); diff --git a/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch index b2c9df4386..b5505c803a 100644 --- a/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-6.6/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1385,6 +1385,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1366,6 +1366,70 @@ static int spi_transfer_wait(struct spi_ return 0; } @@ -82,7 +82,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2223,6 +2287,75 @@ void spi_flush_queue(struct spi_controll +@@ -2211,6 +2275,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -155,10 +155,10 @@ Signed-off-by: SkyLake.Huang + return 0; +} + - static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, - struct device_node *nc) + static void of_spi_parse_dt_cs_delay(struct device_node *nc, + struct spi_delay *delay, const char *prop) { -@@ -2341,6 +2474,10 @@ of_register_spi_device(struct spi_contro +@@ -2350,6 +2483,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; @@ -168,10 +168,10 @@ Signed-off-by: SkyLake.Huang + /* Store a pointer to the node in the device structure */ of_node_get(nc); - spi->dev.of_node = nc; + --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h -@@ -318,6 +318,40 @@ struct spi_driver { +@@ -330,6 +330,40 @@ struct spi_driver { struct device_driver driver; }; @@ -212,7 +212,7 @@ Signed-off-by: SkyLake.Huang static inline struct spi_driver *to_spi_driver(struct device_driver *drv) { return drv ? container_of(drv, struct spi_driver, driver) : NULL; -@@ -703,6 +737,11 @@ struct spi_controller { +@@ -727,6 +761,11 @@ struct spi_controller { void *dummy_rx; void *dummy_tx; @@ -224,13 +224,13 @@ Signed-off-by: SkyLake.Huang int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); /* -@@ -1510,6 +1549,9 @@ spi_register_board_info(struct spi_board +@@ -1600,6 +1639,9 @@ spi_register_board_info(struct spi_board { return 0; } #endif +extern int spi_do_calibration(struct spi_controller *ctlr, + struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv); + - /* If you're hotplugging an adapter with devices (parport, usb, etc) + /* + * If you're hotplugging an adapter with devices (parport, USB, etc) * use spi_new_device() to describe each device. You can also call - * spi_unregister_device() to start making that device vanish, but diff --git a/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch b/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch index e87d63db69..d9fe480b17 100644 --- a/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch +++ b/target/linux/mediatek/patches-6.6/433-drivers-spi-mem-Add-spi-calibration-hook.patch @@ -28,7 +28,7 @@ Signed-off-by: SkyLake.Huang * upper layer if necessary --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h -@@ -366,6 +366,10 @@ bool spi_mem_supports_op(struct spi_mem +@@ -370,6 +370,10 @@ bool spi_mem_supports_op(struct spi_mem int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op); diff --git a/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch b/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch index 3991d8925a..bd8e738a37 100644 --- a/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch +++ b/target/linux/mediatek/patches-6.6/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -978,6 +978,56 @@ static int spinand_manufacturer_match(st +@@ -979,6 +979,56 @@ static int spinand_manufacturer_match(st return -ENOTSUPP; } @@ -68,7 +68,7 @@ Signed-off-by: SkyLake.Huang static int spinand_id_detect(struct spinand_device *spinand) { u8 *id = spinand->id.data; -@@ -1228,6 +1278,10 @@ static int spinand_init(struct spinand_d +@@ -1229,6 +1279,10 @@ static int spinand_init(struct spinand_d if (!spinand->scratchbuf) return -ENOMEM; diff --git a/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch b/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch index 1f747d1f4f..744042ae1a 100644 --- a/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch +++ b/target/linux/mediatek/patches-6.6/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch @@ -12,7 +12,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1019,7 +1019,10 @@ int spinand_cal_read(void *priv, u32 *ad +@@ -1020,7 +1020,10 @@ int spinand_cal_read(void *priv, u32 *ad if (ret) return ret; @@ -26,7 +26,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -2900,6 +2900,18 @@ static const struct flash_info *spi_nor_ +@@ -3378,6 +3378,18 @@ static const struct flash_info *spi_nor_ return NULL; } @@ -45,9 +45,9 @@ Signed-off-by: SkyLake.Huang static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, const char *name) { -@@ -3003,6 +3015,9 @@ int spi_nor_scan(struct spi_nor *nor, co - if (!nor->bouncebuf) - return -ENOMEM; +@@ -3506,6 +3518,9 @@ int spi_nor_scan(struct spi_nor *nor, co + if (ret) + return ret; + if(nor->spimem) + spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor); diff --git a/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch index 487990ab77..73f735828f 100644 --- a/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch +++ b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -384,6 +384,12 @@ config ROCKCHIP_PHY +@@ -419,6 +419,12 @@ config ROCKCHIP_PHY help Currently supports the integrated Ethernet PHY. @@ -12,10 +12,10 @@ + config SMSC_PHY tristate "SMSC PHYs" - help + select CRC16 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o +@@ -102,6 +102,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch index 76d8b0ef00..80179cc7dc 100644 --- a/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch +++ b/target/linux/mediatek/patches-6.6/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/mxl-gpy.c +++ b/drivers/net/phy/mxl-gpy.c -@@ -371,8 +371,11 @@ static bool gpy_2500basex_chk(struct phy +@@ -386,8 +386,11 @@ static bool gpy_2500basex_chk(struct phy phydev->speed = SPEED_2500; phydev->interface = PHY_INTERFACE_MODE_2500BASEX; @@ -28,7 +28,7 @@ Signed-off-by: Daniel Golle return true; } -@@ -396,6 +399,14 @@ static int gpy_config_aneg(struct phy_de +@@ -438,6 +441,14 @@ static int gpy_config_aneg(struct phy_de u32 adv; int ret; @@ -43,7 +43,7 @@ Signed-off-by: Daniel Golle if (phydev->autoneg == AUTONEG_DISABLE) { /* Configure half duplex with genphy_setup_forced, * because genphy_c45_pma_setup_forced does not support. -@@ -486,6 +497,8 @@ static void gpy_update_interface(struct +@@ -560,6 +571,8 @@ static int gpy_update_interface(struct p switch (phydev->speed) { case SPEED_2500: phydev->interface = PHY_INTERFACE_MODE_2500BASEX; @@ -51,8 +51,8 @@ Signed-off-by: Daniel Golle + break; ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, VSPEC1_SGMII_CTRL_ANEN, 0); - if (ret < 0) -@@ -497,7 +510,7 @@ static void gpy_update_interface(struct + if (ret < 0) { +@@ -573,7 +586,7 @@ static int gpy_update_interface(struct p case SPEED_100: case SPEED_10: phydev->interface = PHY_INTERFACE_MODE_SGMII; diff --git a/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch index b4c07a4b1f..74b16be152 100644 --- a/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ b/target/linux/mediatek/patches-6.6/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -326,6 +326,13 @@ config MEDIATEK_GE_SOC_PHY +@@ -330,6 +330,13 @@ config MEDIATEK_GE_SOC_PHY present in the SoCs efuse and will dynamically calibrate VCM (common-mode voltage) during startup. @@ -29,8 +29,8 @@ Signed-off-by: Daniel Golle depends on PTP_1588_CLOCK_OPTIONAL --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -79,6 +79,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell - obj-$(CONFIG_MARVELL_PHY) += marvell.o +@@ -82,6 +82,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o + obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o +obj-$(CONFIG_MEDIATEK_2P5G_PHY) += mediatek-2p5ge.o diff --git a/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch b/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch index fc173646e0..bf9fa57113 100644 --- a/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch +++ b/target/linux/mediatek/patches-6.6/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch @@ -47,7 +47,7 @@ Reviewed-by: Markus Schneider-Pargmann --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c -@@ -691,6 +691,9 @@ static const struct mtk_thermal_data mt7 +@@ -690,6 +690,9 @@ static const struct mtk_thermal_data mt7 .adcpnp = mt7986_adcpnp, .sensor_mux_values = mt7986_mux_values, .version = MTK_THERMAL_V3, diff --git a/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch b/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch index 69cc155d8d..544bd4cce0 100644 --- a/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch +++ b/target/linux/mediatek/patches-6.6/855-i2c-mt65xx-allow-optional-pmic-clock.patch @@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1444,15 +1444,19 @@ static int mtk_i2c_probe(struct platform +@@ -1442,15 +1442,19 @@ static int mtk_i2c_probe(struct platform if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk)) return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk); diff --git a/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch b/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch index bddcd4bb0c..784ae5b613 100644 --- a/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch +++ b/target/linux/mediatek/patches-6.6/864-arm64-dts-mt7986-add-sound-overlay-for-bpi-r3.patch @@ -65,7 +65,7 @@ +}; --- a/arch/arm64/boot/dts/mediatek/Makefile +++ b/arch/arm64/boot/dts/mediatek/Makefile -@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-b +@@ -13,6 +13,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-b dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo diff --git a/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch index 6dede02003..be63dbf761 100644 --- a/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch +++ b/target/linux/mediatek/patches-6.6/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -312,7 +312,7 @@ +@@ -311,7 +311,7 @@ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and * SATA functions. i.e. output-high: PCIe, output-low: SATA */ diff --git a/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch index bfca4b6389..8397915b26 100644 --- a/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch +++ b/target/linux/mediatek/patches-6.6/901-arm-add-cmdline-override.patch @@ -1,6 +1,6 @@ --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -1589,6 +1589,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN +@@ -1568,6 +1568,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN endchoice @@ -17,7 +17,7 @@ default "" --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c -@@ -1187,6 +1187,17 @@ int __init early_init_dt_scan_chosen(cha +@@ -1189,6 +1189,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); @@ -37,7 +37,7 @@ * CONFIG_CMDLINE is meant to be a default in case nothing else --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -2240,6 +2240,14 @@ config CMDLINE_FORCE +@@ -2269,6 +2269,14 @@ config CMDLINE_FORCE endchoice diff --git a/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch index 09ce417c35..50a7e261f0 100644 --- a/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch +++ b/target/linux/mediatek/patches-6.6/910-dts-mt7622-bpi-r64-wifi-eeprom.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -639,5 +639,28 @@ +@@ -638,5 +638,28 @@ }; &wmac { diff --git a/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch b/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch index 5d3153ded4..6b958ca1d4 100644 --- a/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch +++ b/target/linux/mediatek/patches-6.6/911-dts-mt7622-bpi-r64-add-rootdisk.patch @@ -37,7 +37,7 @@ }; &mmc1 { -@@ -249,6 +272,26 @@ +@@ -248,6 +271,26 @@ vqmmc-supply = <®_3p3v>; assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; @@ -64,16 +64,18 @@ }; &nandc { -@@ -283,14 +326,29 @@ +@@ -281,15 +324,30 @@ + read-only; }; - partition@80000 { +- partition@80000 { - label = "fip"; - reg = <0x80000 0x200000>; - read-only; - }; - - ubi: partition@280000 { ++ ubi: partition@80000 { label = "ubi"; - reg = <0x280000 0x7d80000>; + reg = <0x80000 0x7f80000>; diff --git a/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch b/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch index 6e6810b42a..5a387e4d6c 100644 --- a/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch +++ b/target/linux/mediatek/patches-6.6/930-spi-mt65xx-enable-sel-clk.patch @@ -1,6 +1,6 @@ --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c -@@ -1225,8 +1225,15 @@ static int mtk_spi_probe(struct platform +@@ -1226,8 +1226,15 @@ static int mtk_spi_probe(struct platform if (ret < 0) return dev_err_probe(dev, ret, "failed to enable hclk\n"); diff --git a/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch index 3ba485346c..6d75d6ed2a 100644 --- a/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch +++ b/target/linux/mediatek/patches-6.6/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi }; timer { -@@ -540,10 +534,11 @@ +@@ -544,10 +538,11 @@ interrupt-parent = <&gic>; interrupts = ; memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, @@ -38,7 +38,7 @@ Signed-off-by: Lorenzo Bianconi }; wed1: wed@15011000 { -@@ -553,10 +548,11 @@ +@@ -557,10 +552,11 @@ interrupt-parent = <&gic>; interrupts = ; memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, @@ -52,7 +52,7 @@ Signed-off-by: Lorenzo Bianconi }; wo_ccif0: syscon@151a5000 { -@@ -573,6 +569,11 @@ +@@ -577,6 +573,11 @@ interrupts = ; }; diff --git a/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch index c92fcd43ce..0701743ffb 100644 --- a/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch +++ b/target/linux/mediatek/patches-6.6/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1320,6 +1320,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device +@@ -1321,6 +1321,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device struct device_node *np; int index; @@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi index = of_property_match_string(dev->hw->node, "memory-region-names", "wo-dlm"); if (index < 0) -@@ -1336,6 +1354,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device +@@ -1337,6 +1355,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device return -ENODEV; dev->rro.miod_phys = rmem->base; diff --git a/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch index 0ba9bd7cf0..65c143e2f5 100644 --- a/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch +++ b/target/linux/mediatek/patches-6.6/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch @@ -34,7 +34,7 @@ Signed-off-by: Lorenzo Bianconi wo_data: wo-data@4fd80000 { reg = <0 0x4fd80000 0 0x240000>; no-map; -@@ -533,11 +523,10 @@ +@@ -537,11 +527,10 @@ reg = <0 0x15010000 0 0x1000>; interrupt-parent = <&gic>; interrupts = ; @@ -49,7 +49,7 @@ Signed-off-by: Lorenzo Bianconi mediatek,wo-cpuboot = <&wo_cpuboot>; }; -@@ -547,11 +536,10 @@ +@@ -551,11 +540,10 @@ reg = <0 0x15011000 0 0x1000>; interrupt-parent = <&gic>; interrupts = ; @@ -64,7 +64,7 @@ Signed-off-by: Lorenzo Bianconi mediatek,wo-cpuboot = <&wo_cpuboot>; }; -@@ -569,6 +557,16 @@ +@@ -573,6 +561,16 @@ interrupts = ; }; diff --git a/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch index 90b2bb91a2..c8a6bdea6a 100644 --- a/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch +++ b/target/linux/mediatek/patches-6.6/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch @@ -34,7 +34,7 @@ Signed-off-by: Lorenzo Bianconi }; timer { -@@ -523,10 +513,11 @@ +@@ -527,10 +517,11 @@ reg = <0 0x15010000 0 0x1000>; interrupt-parent = <&gic>; interrupts = ; @@ -48,7 +48,7 @@ Signed-off-by: Lorenzo Bianconi mediatek,wo-cpuboot = <&wo_cpuboot>; }; -@@ -536,10 +527,11 @@ +@@ -540,10 +531,11 @@ reg = <0 0x15011000 0 0x1000>; interrupt-parent = <&gic>; interrupts = ; @@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi mediatek,wo-cpuboot = <&wo_cpuboot>; }; -@@ -567,6 +559,16 @@ +@@ -571,6 +563,16 @@ reg = <0 0x151f0000 0 0x8000>; }; diff --git a/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch b/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch index 8b86c50429..cb3b394dc6 100644 --- a/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch +++ b/target/linux/mediatek/patches-6.6/950-smartrg-i2c-led-driver.patch @@ -5,7 +5,7 @@ --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig -@@ -874,6 +874,16 @@ source "drivers/leds/flash/Kconfig" +@@ -901,6 +901,16 @@ source "drivers/leds/flash/Kconfig" comment "RGB LED drivers" source "drivers/leds/rgb/Kconfig" @@ -24,9 +24,9 @@ --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o +@@ -78,6 +78,7 @@ obj-$(CONFIG_LEDS_POWERNV) += leds-powe + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o - obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o +obj-$(CONFIG_LEDS_SMARTRG_LED) += leds-smartrg-system.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o diff --git a/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch index 71cb3006ab..d4517af447 100644 --- a/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch +++ b/target/linux/mediatek/patches-6.6/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -15,7 +15,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1264,7 +1264,7 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1281,7 +1281,7 @@ static int mtk_init_fq_dma(struct mtk_et eth->scratch_ring = eth->sram_base; else eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi ð->phy_scratch_ring, GFP_KERNEL); if (unlikely(!eth->scratch_ring)) -@@ -1280,16 +1280,16 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1297,16 +1297,16 @@ static int mtk_init_fq_dma(struct mtk_et if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) return -ENOMEM; @@ -44,7 +44,7 @@ Signed-off-by: Lorenzo Bianconi txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); txd->txd4 = 0; -@@ -1538,7 +1538,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1555,7 +1555,7 @@ static int mtk_tx_map(struct sk_buff *sk if (itxd == ring->last_free) return -ENOMEM; @@ -53,7 +53,7 @@ Signed-off-by: Lorenzo Bianconi memset(itx_buf, 0, sizeof(*itx_buf)); txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, -@@ -1579,7 +1579,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1596,7 +1596,7 @@ static int mtk_tx_map(struct sk_buff *sk memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); txd_info.size = min_t(unsigned int, frag_size, @@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi txd_info.qid = queue; txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && !(frag_size - txd_info.size); -@@ -1592,7 +1592,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1609,7 +1609,7 @@ static int mtk_tx_map(struct sk_buff *sk mtk_tx_set_dma_desc(dev, txd, &txd_info); tx_buf = mtk_desc_to_tx_buf(ring, txd, @@ -71,7 +71,7 @@ Signed-off-by: Lorenzo Bianconi if (new_desc) memset(tx_buf, 0, sizeof(*tx_buf)); tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; -@@ -1635,7 +1635,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1652,7 +1652,7 @@ static int mtk_tx_map(struct sk_buff *sk } else { int next_idx; @@ -80,7 +80,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma_size); mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); } -@@ -1644,7 +1644,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1661,7 +1661,7 @@ static int mtk_tx_map(struct sk_buff *sk err_dma: do { @@ -89,7 +89,7 @@ Signed-off-by: Lorenzo Bianconi /* unmap dma */ mtk_tx_unmap(eth, tx_buf, NULL, false); -@@ -1669,7 +1669,7 @@ static int mtk_cal_txd_req(struct mtk_et +@@ -1686,7 +1686,7 @@ static int mtk_cal_txd_req(struct mtk_et for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; nfrags += DIV_ROUND_UP(skb_frag_size(frag), @@ -98,7 +98,7 @@ Signed-off-by: Lorenzo Bianconi } } else { nfrags += skb_shinfo(skb)->nr_frags; -@@ -1810,7 +1810,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri +@@ -1827,7 +1827,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri ring = ð->rx_ring[i]; idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); @@ -107,7 +107,7 @@ Signed-off-by: Lorenzo Bianconi if (rxd->rxd2 & RX_DMA_DONE) { ring->calc_idx_update = true; return ring; -@@ -1978,7 +1978,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -1995,7 +1995,7 @@ static int mtk_xdp_submit_frame(struct m } htxd = txd; @@ -116,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi memset(tx_buf, 0, sizeof(*tx_buf)); htx_buf = tx_buf; -@@ -1997,7 +1997,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -2014,7 +2014,7 @@ static int mtk_xdp_submit_frame(struct m goto unmap; tx_buf = mtk_desc_to_tx_buf(ring, txd, @@ -125,7 +125,7 @@ Signed-off-by: Lorenzo Bianconi memset(tx_buf, 0, sizeof(*tx_buf)); n_desc++; } -@@ -2035,7 +2035,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -2052,7 +2052,7 @@ static int mtk_xdp_submit_frame(struct m } else { int idx; @@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), MT7628_TX_CTX_IDX0); } -@@ -2046,7 +2046,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -2063,7 +2063,7 @@ static int mtk_xdp_submit_frame(struct m unmap: while (htxd != txd) { @@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi mtk_tx_unmap(eth, tx_buf, NULL, false); htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; -@@ -2177,7 +2177,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2194,7 +2194,7 @@ static int mtk_poll_rx(struct napi_struc goto rx_done; idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); @@ -152,7 +152,7 @@ Signed-off-by: Lorenzo Bianconi data = ring->data[idx]; if (!mtk_rx_get_desc(eth, &trxd, rxd)) -@@ -2312,7 +2312,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2329,7 +2329,7 @@ static int mtk_poll_rx(struct napi_struc rxdcsum = &trxd.rxd4; } @@ -161,7 +161,7 @@ Signed-off-by: Lorenzo Bianconi skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); -@@ -2436,7 +2436,7 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2453,7 +2453,7 @@ static int mtk_poll_tx_qdma(struct mtk_e break; tx_buf = mtk_desc_to_tx_buf(ring, desc, @@ -170,7 +170,7 @@ Signed-off-by: Lorenzo Bianconi if (!tx_buf->data) break; -@@ -2487,7 +2487,7 @@ static int mtk_poll_tx_pdma(struct mtk_e +@@ -2504,7 +2504,7 @@ static int mtk_poll_tx_pdma(struct mtk_e } mtk_tx_unmap(eth, tx_buf, &bq, true); @@ -179,7 +179,7 @@ Signed-off-by: Lorenzo Bianconi ring->last_free = desc; atomic_inc(&ring->free_count); -@@ -2577,7 +2577,7 @@ static int mtk_napi_rx(struct napi_struc +@@ -2594,7 +2594,7 @@ static int mtk_napi_rx(struct napi_struc do { int rx_done; @@ -188,7 +188,7 @@ Signed-off-by: Lorenzo Bianconi reg_map->pdma.irq_status); rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); rx_done_total += rx_done; -@@ -2593,10 +2593,10 @@ static int mtk_napi_rx(struct napi_struc +@@ -2610,10 +2610,10 @@ static int mtk_napi_rx(struct napi_struc return budget; } while (mtk_r32(eth, reg_map->pdma.irq_status) & @@ -201,7 +201,7 @@ Signed-off-by: Lorenzo Bianconi return rx_done_total; } -@@ -2605,7 +2605,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2622,7 +2622,7 @@ static int mtk_tx_alloc(struct mtk_eth * { const struct mtk_soc_data *soc = eth->soc; struct mtk_tx_ring *ring = ð->tx_ring; @@ -210,7 +210,7 @@ Signed-off-by: Lorenzo Bianconi struct mtk_tx_dma_v2 *txd; int ring_size; u32 ofs, val; -@@ -2728,14 +2728,14 @@ static void mtk_tx_clean(struct mtk_eth +@@ -2745,14 +2745,14 @@ static void mtk_tx_clean(struct mtk_eth } if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { dma_free_coherent(eth->dma_dev, @@ -227,7 +227,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma_pdma, ring->phys_pdma); ring->dma_pdma = NULL; } -@@ -2790,15 +2790,15 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2807,15 +2807,15 @@ static int mtk_rx_alloc(struct mtk_eth * if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || rx_flag != MTK_RX_FLAGS_NORMAL) { ring->dma = dma_alloc_coherent(eth->dma_dev, @@ -247,7 +247,7 @@ Signed-off-by: Lorenzo Bianconi } if (!ring->dma) -@@ -2809,7 +2809,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2826,7 +2826,7 @@ static int mtk_rx_alloc(struct mtk_eth * dma_addr_t dma_addr; void *data; @@ -256,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi if (ring->page_pool) { data = mtk_page_pool_get_buff(ring->page_pool, &dma_addr, GFP_KERNEL); -@@ -2900,7 +2900,7 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2917,7 +2917,7 @@ static void mtk_rx_clean(struct mtk_eth if (!ring->data[i]) continue; @@ -265,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi if (!rxd->rxd1) continue; -@@ -2917,7 +2917,7 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2934,7 +2934,7 @@ static void mtk_rx_clean(struct mtk_eth if (!in_sram && ring->dma) { dma_free_coherent(eth->dma_dev, @@ -274,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma, ring->phys); ring->dma = NULL; } -@@ -3280,7 +3280,7 @@ static void mtk_dma_free(struct mtk_eth +@@ -3297,7 +3297,7 @@ static void mtk_dma_free(struct mtk_eth netdev_reset_queue(eth->netdev[i]); if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { dma_free_coherent(eth->dma_dev, @@ -283,7 +283,7 @@ Signed-off-by: Lorenzo Bianconi eth->scratch_ring, eth->phy_scratch_ring); eth->scratch_ring = NULL; eth->phy_scratch_ring = 0; -@@ -3330,7 +3330,7 @@ static irqreturn_t mtk_handle_irq_rx(int +@@ -3347,7 +3347,7 @@ static irqreturn_t mtk_handle_irq_rx(int eth->rx_events++; if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -292,7 +292,7 @@ Signed-off-by: Lorenzo Bianconi __napi_schedule(ð->rx_napi); } -@@ -3356,9 +3356,9 @@ static irqreturn_t mtk_handle_irq(int ir +@@ -3373,9 +3373,9 @@ static irqreturn_t mtk_handle_irq(int ir const struct mtk_reg_map *reg_map = eth->soc->reg_map; if (mtk_r32(eth, reg_map->pdma.irq_mask) & @@ -304,7 +304,7 @@ Signed-off-by: Lorenzo Bianconi mtk_handle_irq_rx(irq, _eth); } if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { -@@ -3376,10 +3376,10 @@ static void mtk_poll_controller(struct n +@@ -3393,10 +3393,10 @@ static void mtk_poll_controller(struct n struct mtk_eth *eth = mac->hw; mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); @@ -317,7 +317,7 @@ Signed-off-by: Lorenzo Bianconi } #endif -@@ -3545,7 +3545,7 @@ static int mtk_open(struct net_device *d +@@ -3563,7 +3563,7 @@ static int mtk_open(struct net_device *d napi_enable(ð->tx_napi); napi_enable(ð->rx_napi); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); @@ -326,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi refcount_set(ð->dma_refcnt, 1); } else -@@ -3628,7 +3628,7 @@ static int mtk_stop(struct net_device *d +@@ -3647,7 +3647,7 @@ static int mtk_stop(struct net_device *d mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); @@ -335,7 +335,7 @@ Signed-off-by: Lorenzo Bianconi napi_disable(ð->tx_napi); napi_disable(ð->rx_napi); -@@ -4107,9 +4107,9 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -4126,9 +4126,9 @@ static int mtk_hw_init(struct mtk_eth *e /* FE int grouping */ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); @@ -347,7 +347,7 @@ Signed-off-by: Lorenzo Bianconi mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); if (mtk_is_netsys_v3_or_greater(eth)) { -@@ -5270,11 +5270,15 @@ static const struct mtk_soc_data mt2701_ +@@ -5305,11 +5305,15 @@ static const struct mtk_soc_data mt2701_ .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, .version = 1, @@ -368,7 +368,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5290,11 +5294,15 @@ static const struct mtk_soc_data mt7621_ +@@ -5325,11 +5329,15 @@ static const struct mtk_soc_data mt7621_ .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -389,7 +389,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5312,11 +5320,15 @@ static const struct mtk_soc_data mt7622_ +@@ -5347,11 +5355,15 @@ static const struct mtk_soc_data mt7622_ .hash_offset = 2, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -410,7 +410,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5333,11 +5345,15 @@ static const struct mtk_soc_data mt7623_ +@@ -5368,11 +5380,15 @@ static const struct mtk_soc_data mt7623_ .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, .disable_pll_modes = true, @@ -431,7 +431,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5352,11 +5368,15 @@ static const struct mtk_soc_data mt7629_ +@@ -5387,11 +5403,15 @@ static const struct mtk_soc_data mt7629_ .required_pctl = false, .has_accounting = true, .version = 1, @@ -452,7 +452,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5374,11 +5394,15 @@ static const struct mtk_soc_data mt7981_ +@@ -5409,11 +5429,15 @@ static const struct mtk_soc_data mt7981_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, @@ -473,7 +473,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5396,11 +5420,15 @@ static const struct mtk_soc_data mt7986_ +@@ -5431,11 +5455,15 @@ static const struct mtk_soc_data mt7986_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, @@ -494,7 +494,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5418,11 +5446,15 @@ static const struct mtk_soc_data mt7988_ +@@ -5453,11 +5481,15 @@ static const struct mtk_soc_data mt7988_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, @@ -515,7 +515,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5435,11 +5467,15 @@ static const struct mtk_soc_data rt5350_ +@@ -5470,11 +5502,15 @@ static const struct mtk_soc_data rt5350_ .required_clks = MT7628_CLKS_BITMAP, .required_pctl = false, .version = 1, diff --git a/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch index 8b7d5c0a1c..6b84f70110 100644 --- a/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch +++ b/target/linux/mediatek/patches-6.6/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -17,7 +17,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -110,16 +110,16 @@ static const struct mtk_reg_map mt7986_r +@@ -113,16 +113,16 @@ static const struct mtk_reg_map mt7986_r .tx_irq_mask = 0x461c, .tx_irq_status = 0x4618, .pdma = { @@ -44,7 +44,7 @@ Signed-off-by: Daniel Golle }, .qdma = { .qtx_cfg = 0x4400, -@@ -1232,7 +1232,7 @@ static bool mtk_rx_get_desc(struct mtk_e +@@ -1249,7 +1249,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); @@ -53,7 +53,7 @@ Signed-off-by: Daniel Golle rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); } -@@ -2184,7 +2184,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2201,7 +2201,7 @@ static int mtk_poll_rx(struct napi_struc break; /* find out which mac the packet come from. values start at 1 */ @@ -62,7 +62,7 @@ Signed-off-by: Daniel Golle u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); switch (val) { -@@ -2296,7 +2296,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2313,7 +2313,7 @@ static int mtk_poll_rx(struct napi_struc skb->dev = netdev; bytes += skb->len; @@ -71,7 +71,7 @@ Signed-off-by: Daniel Golle reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; if (hash != MTK_RXD5_FOE_ENTRY) -@@ -2846,7 +2846,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2863,7 +2863,7 @@ static int mtk_rx_alloc(struct mtk_eth * rxd->rxd3 = 0; rxd->rxd4 = 0; @@ -80,7 +80,7 @@ Signed-off-by: Daniel Golle rxd->rxd5 = 0; rxd->rxd6 = 0; rxd->rxd7 = 0; -@@ -4053,7 +4053,7 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -4072,7 +4072,7 @@ static int mtk_hw_init(struct mtk_eth *e else mtk_hw_reset(eth); @@ -89,7 +89,7 @@ Signed-off-by: Daniel Golle /* Set FE to PDMAv2 if necessary */ val = mtk_r32(eth, MTK_FE_GLO_MISC); mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); -@@ -5400,11 +5400,11 @@ static const struct mtk_soc_data mt7981_ +@@ -5435,11 +5435,11 @@ static const struct mtk_soc_data mt7981_ .dma_len_offset = 8, }, .rx = { @@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle }, }; -@@ -5426,11 +5426,11 @@ static const struct mtk_soc_data mt7986_ +@@ -5461,11 +5461,11 @@ static const struct mtk_soc_data mt7986_ .dma_len_offset = 8, }, .rx = { diff --git a/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch index 11b52d07ab..9974073d25 100644 --- a/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch +++ b/target/linux/mediatek/patches-6.6/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic +@@ -1072,13 +1072,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic static void mtk_wed_stop(struct mtk_wed_device *dev) { @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau if (!mtk_wed_get_rx_capa(dev)) return; -@@ -1090,7 +1090,6 @@ static void +@@ -1091,7 +1091,6 @@ static void mtk_wed_deinit(struct mtk_wed_device *dev) { mtk_wed_stop(dev); @@ -37,7 +37,7 @@ Signed-off-by: Felix Fietkau wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WDMA_INT_AGENT_EN | -@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d +@@ -2622,9 +2621,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d static void mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) { From dcac4a28e61bee2dc2df02a87d7a70813db1995b Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:23:22 +0000 Subject: [PATCH 081/108] mediatek: leds-smartrg-system: fix build on Linux 6.6 Adapt to changed function pointer prototypes. Signed-off-by: Daniel Golle --- .../linux/mediatek/files/drivers/leds/leds-smartrg-system.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/linux/mediatek/files/drivers/leds/leds-smartrg-system.c b/target/linux/mediatek/files/drivers/leds/leds-smartrg-system.c index 1679555068..7736905704 100644 --- a/target/linux/mediatek/files/drivers/leds/leds-smartrg-system.c +++ b/target/linux/mediatek/files/drivers/leds/leds-smartrg-system.c @@ -159,7 +159,12 @@ srg_led_init_led(struct srg_led_ctrl *sysled_ctrl, struct device_node *np) } static int + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0) srg_led_probe(struct i2c_client *client, const struct i2c_device_id *id) +#else +srg_led_probe(struct i2c_client *client) +#endif { struct device_node *np = client->dev.of_node, *child; struct srg_led_ctrl *sysled_ctrl; From 3043bd2621a190add88fd51e5b0d7f50e0157a90 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:24:15 +0000 Subject: [PATCH 082/108] mediatek: fix build of MT7988 clk drivers on Linux 6.6 As shared remove functions now returns void instead of int we need to use .remove_new instead of .remove. Signed-off-by: Daniel Golle --- ...249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch index dab08a5a39..6ec9bd2101 100644 --- a/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch +++ b/target/linux/mediatek/patches-6.6/249-v6.8-clk-mediatek-add-drivers-for-MT7988-SoC.patch @@ -327,7 +327,7 @@ Signed-off-by: Stephen Boyd + .of_match_table = of_match_clk_mt7988_eth, + }, + .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, ++ .remove_new = mtk_clk_simple_remove, +}; +module_platform_driver(clk_mt7988_eth_drv); + @@ -607,7 +607,7 @@ Signed-off-by: Stephen Boyd + .of_match_table = of_match_clk_mt7988_infracfg, + }, + .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, ++ .remove_new = mtk_clk_simple_remove, +}; +module_platform_driver(clk_mt7988_infracfg_drv); +MODULE_LICENSE("GPL"); @@ -931,7 +931,7 @@ Signed-off-by: Stephen Boyd + +static struct platform_driver clk_mt7988_topckgen_drv = { + .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, ++ .remove_new = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt7988-topckgen", + .of_match_table = of_match_clk_mt7988_topckgen, @@ -1018,7 +1018,7 @@ Signed-off-by: Stephen Boyd + .of_match_table = of_match_clk_mt7988_xfipll, + }, + .probe = clk_mt7988_xfipll_probe, -+ .remove = mtk_clk_simple_remove, ++ .remove_new = mtk_clk_simple_remove, +}; +module_platform_driver(clk_mt7988_xfipll_drv); + From cd509d739a8ec8a548fb7db62dab88ca13c38a7c Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:29:48 +0000 Subject: [PATCH 083/108] mediatek: add kernel configs for Linux 6.6 Add config-6.6 for all mediatek subtargets. Signed-off-by: Daniel Golle --- target/linux/mediatek/filogic/config-6.6 | 499 ++++++++++++++++++ target/linux/mediatek/mt7622/config-6.6 | 495 ++++++++++++++++++ target/linux/mediatek/mt7623/config-6.6 | 637 +++++++++++++++++++++++ target/linux/mediatek/mt7629/config-6.6 | 360 +++++++++++++ 4 files changed, 1991 insertions(+) create mode 100644 target/linux/mediatek/filogic/config-6.6 create mode 100644 target/linux/mediatek/mt7622/config-6.6 create mode 100644 target/linux/mediatek/mt7623/config-6.6 create mode 100644 target/linux/mediatek/mt7629/config-6.6 diff --git a/target/linux/mediatek/filogic/config-6.6 b/target/linux/mediatek/filogic/config-6.6 new file mode 100644 index 0000000000..704c32be8a --- /dev/null +++ b/target/linux/mediatek/filogic/config-6.6 @@ -0,0 +1,499 @@ +CONFIG_64BIT=y +# CONFIG_AHCI_MTK is not set +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MEDIATEK_CPUFREQ=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_SMMU_V3_PMU is not set +CONFIG_ATA=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_NVMEM=y +CONFIG_BLK_PM=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE_OVERRIDE=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +# CONFIG_COMMON_CLK_MT2712 is not set +# CONFIG_COMMON_CLK_MT6779 is not set +# CONFIG_COMMON_CLK_MT6795 is not set +# CONFIG_COMMON_CLK_MT6797 is not set +# CONFIG_COMMON_CLK_MT7622 is not set +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_MT8186 is not set +# CONFIG_COMMON_CLK_MT8195 is not set +# CONFIG_COMMON_CLK_MT8365 is not set +# CONFIG_COMMON_CLK_MT8516 is not set +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y +CONFIG_CRYPTO_SM4_ARM64_CE_CCM=y +CONFIG_CRYPTO_SM4_ARM64_CE_GCM=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MISC=y +CONFIG_DIMLIB=y +CONFIG_DMADEVICES=y +CONFIG_DMATEST=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_OF=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +CONFIG_FIT_PARTITION=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HWMON=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MT65XX=y +CONFIG_ICPLUS_PHY=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JUMP_LABEL=y +CONFIG_LEDS_SMARTRG_LED=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +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 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_MEDIATEK=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MTK=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_NVMEM=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_CMDQ is not set +CONFIG_MTK_CPUX_TIMER=y +# CONFIG_MTK_CQDMA is not set +CONFIG_MTK_HSDMA=y +CONFIG_MTK_INFRACFG=y +CONFIG_MTK_LVTS_THERMAL=y +CONFIG_MTK_LVTS_THERMAL_DEBUGFS=y +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MTK_REGULATOR_COUPLER=y +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_SOC_THERMAL=y +# CONFIG_MTK_SVS is not set +CONFIG_MTK_THERMAL=y +CONFIG_MTK_TIMER=y +# CONFIG_MTK_UART_APDMA is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +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_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_MTK_EFUSE=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +# CONFIG_PCIE_MEDIATEK is not set +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCS_MTK_LYNXI=y +CONFIG_PCS_MTK_USXGMII=y +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_MTK_DP is not set +# CONFIG_PHY_MTK_PCIE is not set +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +CONFIG_PHY_MTK_XFI_TPHY=y +CONFIG_PHY_MTK_XSPHY=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +# 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_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POLYNOMIAL=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PSTORE=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REALTEK_PHY=y +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_RESET_TI_SYSCON=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_MT7622=y +CONFIG_RTC_I2C_AND_SPI=y +# CONFIG_RTL8367S_GSW is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +# CONFIG_SPI_MTK_NOR is not set +CONFIG_SPI_MTK_SNFI=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +CONFIG_UIMAGE_FIT_BLK=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USB_SUPPORT=y +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_SYSFS=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7622/config-6.6 b/target/linux/mediatek/mt7622/config-6.6 new file mode 100644 index 0000000000..8eb7158914 --- /dev/null +++ b/target/linux/mediatek/mt7622/config-6.6 @@ -0,0 +1,495 @@ +CONFIG_64BIT=y +# CONFIG_AHCI_MTK is not set +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MEDIATEK_CPUFREQ=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_SMMU_V3_PMU is not set +CONFIG_ATA=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +CONFIG_COMMON_CLK_MT2712=y +# CONFIG_COMMON_CLK_MT2712_BDPSYS is not set +# CONFIG_COMMON_CLK_MT2712_IMGSYS is not set +# CONFIG_COMMON_CLK_MT2712_JPGDECSYS is not set +# CONFIG_COMMON_CLK_MT2712_MFGCFG is not set +# CONFIG_COMMON_CLK_MT2712_MMSYS is not set +# CONFIG_COMMON_CLK_MT2712_VDECSYS is not set +# CONFIG_COMMON_CLK_MT2712_VENCSYS is not set +# CONFIG_COMMON_CLK_MT6779 is not set +# CONFIG_COMMON_CLK_MT6795 is not set +# CONFIG_COMMON_CLK_MT6797 is not set +CONFIG_COMMON_CLK_MT7622=y +CONFIG_COMMON_CLK_MT7622_AUDSYS=y +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_MT8186 is not set +# CONFIG_COMMON_CLK_MT8195 is not set +# CONFIG_COMMON_CLK_MT8365 is not set +# CONFIG_COMMON_CLK_MT8516 is not set +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y +CONFIG_CRYPTO_SM4_ARM64_CE_CCM=y +CONFIG_CRYPTO_SM4_ARM64_CE_GCM=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MISC=y +CONFIG_DIMLIB=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +# CONFIG_FIT_PARTITION is not set +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIO_CDEV=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MT65XX=y +CONFIG_ICPLUS_PHY=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JUMP_LABEL=y +# CONFIG_LEDS_SMARTRG_LED is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAXLINEAR_GPHY=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 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_MEDIATEK=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MTK=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_NVMEM=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_CMDQ is not set +CONFIG_MTK_CPUX_TIMER=y +# CONFIG_MTK_CQDMA is not set +CONFIG_MTK_HSDMA=y +CONFIG_MTK_INFRACFG=y +# CONFIG_MTK_LVTS_THERMAL is not set +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MTK_REGULATOR_COUPLER=y +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_SOC_THERMAL=y +# CONFIG_MTK_SVS is not set +CONFIG_MTK_THERMAL=y +CONFIG_MTK_TIMER=y +# CONFIG_MTK_UART_APDMA is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +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_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=2 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_MTK_EFUSE=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCS_MTK_LYNXI=y +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_MTK_DP is not set +# CONFIG_PHY_MTK_PCIE is not set +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +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_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PSTORE=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REALTEK_PHY=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_MT6380=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_MT7622=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTL8367S_GSW=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +CONFIG_SPI_MTK_NOR=y +CONFIG_SPI_MTK_SNFI=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWCONFIG=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +CONFIG_UIMAGE_FIT_BLK=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USB_SUPPORT=y +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_SYSFS=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7623/config-6.6 b/target/linux/mediatek/mt7623/config-6.6 new file mode 100644 index 0000000000..fad11c8ae8 --- /dev/null +++ b/target/linux/mediatek/mt7623/config-6.6 @@ -0,0 +1,637 @@ +# CONFIG_AIO is not set +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +CONFIG_ARM_CPU_SUSPEND=y +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8 +CONFIG_ARM_DMA_USE_IOMMU=y +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_GROUP_RELOCS=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +# CONFIG_ARM_MEDIATEK_CCI_DEVFREQ is not set +CONFIG_ARM_MEDIATEK_CPUFREQ=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +# CONFIG_ARM_SMMU is not set +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_ATAGS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_BACKLIGHT_LED=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BOUNCE=y +CONFIG_BUFFER_HEAD=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="earlyprintk console=ttyS0,115200 rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CMDLINE_PARTITION=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +CONFIG_COMMON_CLK_MT2701=y +CONFIG_COMMON_CLK_MT2701_AUDSYS=y +CONFIG_COMMON_CLK_MT2701_BDPSYS=y +CONFIG_COMMON_CLK_MT2701_ETHSYS=y +CONFIG_COMMON_CLK_MT2701_G3DSYS=y +CONFIG_COMMON_CLK_MT2701_HIFSYS=y +CONFIG_COMMON_CLK_MT2701_IMGSYS=y +CONFIG_COMMON_CLK_MT2701_MMSYS=y +CONFIG_COMMON_CLK_MT2701_VDECSYS=y +# CONFIG_COMMON_CLK_MT6795 is not set +# CONFIG_COMMON_CLK_MT7622 is not set +# 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_MT8365 is not set +# CONFIG_COMMON_CLK_MT8516 is not set +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_COREDUMP=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_GPIO=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_MISC=y +CONFIG_DEBUG_MT6589_UART0=y +# CONFIG_DEBUG_MT8127_UART0 is not set +# CONFIG_DEBUG_MT8135_UART3 is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_UART_8250=y +CONFIG_DEBUG_UART_8250_SHIFT=2 +CONFIG_DEBUG_UART_PHYS=0x11004000 +CONFIG_DEBUG_UART_VIRT=0xf1004000 +# CONFIG_DEVFREQ_GOV_PASSIVE is not set +# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set +# CONFIG_DEVFREQ_GOV_POWERSAVE is not set +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +# CONFIG_DEVFREQ_GOV_USERSPACE is not set +# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DIMLIB=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DRM=y +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_DISPLAY_CONNECTOR=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=100 +CONFIG_DRM_GEM_SHMEM_HELPER=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_LIMA=y +CONFIG_DRM_LVDS_CODEC=y +CONFIG_DRM_MEDIATEK=y +# CONFIG_DRM_MEDIATEK_DP is not set +CONFIG_DRM_MEDIATEK_HDMI=y +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_PANEL=y +CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_PANEL_HIMAX_HX8394 is not set +# CONFIG_DRM_PANEL_JADARD_JD9365DA_H3 is not set +# CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966 is not set +# CONFIG_DRM_PANEL_NEWVISION_NV3051D is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36523 is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=y +# CONFIG_DRM_PANEL_SONY_TD4353_JDI is not set +# CONFIG_DRM_PANEL_STARTEK_KD070FHFID015 is not set +# CONFIG_DRM_PANEL_VISIONOX_R66451 is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +CONFIG_DRM_SCHED=y +CONFIG_DRM_SIMPLE_BRIDGE=y +CONFIG_DTC=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_ELF_CORE=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FB=y +CONFIG_FB_CORE=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_DEVICE=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FIT_PARTITION is not set +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FONT_SUPPORT=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FREEZER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_VDSO_32=y +CONFIG_GPIO_CDEV=y +CONFIG_GRO_CELLS=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HDMI=y +CONFIG_HID=y +CONFIG_HID_SUPPORT=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HWMON=y +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MT65XX=y +CONFIG_ICPLUS_PHY=y +CONFIG_IIO=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_IOMMUFD is not set +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IRQCHIP=y +CONFIG_IRQSTACKS=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_KALLSYMS=y +CONFIG_KCMP=y +CONFIG_KEYBOARD_MTK_PMIC=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_PLATFORM=y +CONFIG_LEDS_MT6323=y +# CONFIG_LEDS_QCOM_LPG is not set +# CONFIG_LEDS_SMARTRG_LED is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MACH_MT2701 is not set +# CONFIG_MACH_MT6589 is not set +# CONFIG_MACH_MT6592 is not set +CONFIG_MACH_MT7623=y +# CONFIG_MACH_MT7629 is not set +# CONFIG_MACH_MT8127 is not set +# CONFIG_MACH_MT8135 is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_GPIO=y +CONFIG_MEDIATEK_GE_PHY=y +CONFIG_MEDIATEK_MT6577_AUXADC=y +CONFIG_MEDIATEK_WATCHDOG=y +CONFIG_MEMORY=y +CONFIG_MFD_CORE=y +# CONFIG_MFD_HI6421_SPMI is not set +CONFIG_MFD_MT6397=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_NAND_ECC_MEDIATEK is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_ADSP_MBOX is not set +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CMDQ_MBOX=y +CONFIG_MTK_CPUX_TIMER=y +CONFIG_MTK_CQDMA=y +# CONFIG_MTK_HSDMA is not set +CONFIG_MTK_INFRACFG=y +CONFIG_MTK_IOMMU=y +CONFIG_MTK_IOMMU_V1=y +# CONFIG_MTK_LVTS_THERMAL is not set +CONFIG_MTK_MMSYS=y +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MTK_REGULATOR_COUPLER=y +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_SMI=y +CONFIG_MTK_SOC_THERMAL=y +# CONFIG_MTK_SVS is not set +CONFIG_MTK_THERMAL=y +CONFIG_MTK_TIMER=y +# CONFIG_MTK_UART_APDMA is not set +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_SRCU_NMI_SAFE=y +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_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_MTK_EFUSE=y +# CONFIG_NVMEM_SPMI_SDAM is not set +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCS_MTK_LYNXI=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +# CONFIG_PHY_MTK_DP is not set +CONFIG_PHY_MTK_HDMI=y +CONFIG_PHY_MTK_MIPI_DSI=y +# CONFIG_PHY_MTK_PCIE is not set +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_MT2701=y +# CONFIG_PINCTRL_MT6397 is not set +CONFIG_PINCTRL_MT7623=y +CONFIG_PINCTRL_MTK=y +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_DEVFREQ=y +# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_MT6323 is not set +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_SUPPLY_HWMON=y +CONFIG_PREEMPT=y +CONFIG_PREEMPTION=y +CONFIG_PREEMPT_BUILD=y +CONFIG_PREEMPT_COUNT=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_RCU=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_MT6323=y +# CONFIG_REGULATOR_MT6331 is not set +# CONFIG_REGULATOR_MT6332 is not set +# CONFIG_REGULATOR_MT6357 is not set +# CONFIG_REGULATOR_MT6358 is not set +# CONFIG_REGULATOR_MT6380 is not set +# CONFIG_REGULATOR_MT6397 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 +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_MT6397 is not set +# CONFIG_RTC_DRV_MT7622 is not set +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +# CONFIG_RTL8367S_GSW is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +# CONFIG_SMP_ON_UP is not set +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +# CONFIG_SPI_MTK_NOR is not set +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +# CONFIG_SPMI_MTK_PMIF is not set +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYNC_FILE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +# CONFIG_UACCE is not set +CONFIG_UBIFS_FS=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UIMAGE_FIT_BLK=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_F_ACM=y +CONFIG_USB_F_ECM=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GPIO_VBUS=y +CONFIG_USB_G_MULTI=y +CONFIG_USB_G_MULTI_CDC=y +# CONFIG_USB_G_MULTI_RNDIS is not set +CONFIG_USB_HID=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_INVENTRA_DMA=y +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_MUSB_DUAL_ROLE=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_MEDIATEK=y +CONFIG_USB_OTG=y +CONFIG_USB_PHY=y +CONFIG_USB_ROLE_SWITCH=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_U_ETHER=y +CONFIG_USB_U_SERIAL=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_VIDEO_CMDLINE=y +CONFIG_VIDEO_NOMODESET=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7629/config-6.6 b/target/linux/mediatek/mt7629/config-6.6 new file mode 100644 index 0000000000..15329133c0 --- /dev/null +++ b/target/linux/mediatek/mt7629/config-6.6 @@ -0,0 +1,360 @@ +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_GROUP_RELOCS=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ATAGS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CACHE_L2X0=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CHR_DEV_SCH=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +CONFIG_CMDLINE_OVERRIDE=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +# CONFIG_COMMON_CLK_MT2701 is not set +# CONFIG_COMMON_CLK_MT6795 is not set +# CONFIG_COMMON_CLK_MT7622 is not set +CONFIG_COMMON_CLK_MT7629=y +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_MT8365 is not set +# CONFIG_COMMON_CLK_MT8516 is not set +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DEBUG_MISC=y +CONFIG_DEFAULT_HOSTNAME="(mt7629)" +CONFIG_DIMLIB=y +CONFIG_DMA_OPS=y +CONFIG_DTC=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +# CONFIG_FIT_PARTITION is not set +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_VDSO_32=y +CONFIG_GPIO_CDEV=y +CONFIG_GRO_CELLS=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_HZ_FIXED=0 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQSTACKS=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MACH_MT2701 is not set +# CONFIG_MACH_MT6589 is not set +# CONFIG_MACH_MT6592 is not set +# CONFIG_MACH_MT7623 is not set +CONFIG_MACH_MT7629=y +# CONFIG_MACH_MT8127 is not set +# CONFIG_MACH_MT8135 is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_GE_PHY=y +CONFIG_MEDIATEK_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_MEDIATEK=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_CMDQ is not set +CONFIG_MTK_CPUX_TIMER=y +CONFIG_MTK_INFRACFG=y +# CONFIG_MTK_PMIC_WRAP is not set +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_TIMER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_BPF_LINK=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_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=2 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +# CONFIG_NVMEM_MTK_EFUSE is not set +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCS_MTK_LYNXI=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +# CONFIG_PHY_MTK_DP is not set +# CONFIG_PHY_MTK_PCIE is not set +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_MT7629=y +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +# CONFIG_RTL8367S_GSW is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +CONFIG_SPI_MTK_NOR=y +CONFIG_SPI_MTK_SNFI=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_STACKTRACE=y +# CONFIG_SWAP is not set +CONFIG_SWCONFIG=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_USE_OF=y +# CONFIG_VFP is not set +CONFIG_WATCHDOG_CORE=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y From 448b48c24566f6d7961bccaae1074da887b1b8b9 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2024 04:25:43 +0000 Subject: [PATCH 084/108] mediatek: add Linux 6.6 as testing kernel Add KERNEL_TESTING_PATCHVER for Linux 6.6. Signed-off-by: Daniel Golle --- target/linux/mediatek/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile index 279c167b83..288fb537a7 100644 --- a/target/linux/mediatek/Makefile +++ b/target/linux/mediatek/Makefile @@ -9,6 +9,7 @@ SUBTARGETS:=mt7622 mt7623 mt7629 filogic FEATURES:=dt-overlay emmc fpu gpio nand pci pcie rootfs-part separate_ramdisk squashfs usb KERNEL_PATCHVER:=6.1 +KERNEL_TESTING_PATCHVER:=6.6 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ From f7a68458b42d30ae4bb03f0be66cfd4cfae9602d Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 11 Mar 2024 23:23:23 +0000 Subject: [PATCH 085/108] kernel: modules: don't override NLS dependencies Recent changes for Linux 6.6 broke things when building with older kernels: Package kmod-fs-jfs is missing dependencies for the following libraries: nls_base.ko Fix this by adding NLS dependencies after the added dependency applying on Linux 6.6. Fixes: f9198480da ("kernel: modules: fs: adapt for kernel 6.6") Signed-off-by: Daniel Golle --- package/kernel/linux/modules/fs.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index 8f1ed41484..0d98c5a681 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -344,8 +344,8 @@ define KernelPackage/fs-jfs KCONFIG:=CONFIG_JFS_FS FILES:=$(LINUX_DIR)/fs/jfs/jfs.ko AUTOLOAD:=$(call AutoLoad,30,jfs,1) - $(call AddDepends/nls) DEPENDS:=+LINUX_6_6:kmod-nls-ucs2-utils + $(call AddDepends/nls) endef define KernelPackage/fs-jfs/description From 7ea82bc17d1583f4d9d46397846b0eb63e6651eb Mon Sep 17 00:00:00 2001 From: CharlesMengCA <58993776+CharlesMengCA@users.noreply.github.com> Date: Tue, 12 Mar 2024 00:06:14 -0400 Subject: [PATCH 086/108] kernel: config: add symbol introduced with 6.2 CONFIG_DEBUG_INFO_COMPRESSED_ZSTD, required by GCC 13.0+ Compress the debug information using zstd. This may provide better compression than zlib, for about the same time costs, but requires newer toolchain support. Requires GCC 13.0+ or Clang 16.0+, binutils 2.40+, and zstd. Signed-off-by: CharlesMengCA <58993776+CharlesMengCA@users.noreply.github.com> --- target/linux/generic/config-6.6 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 319f56fe01..db828745df 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -1412,6 +1412,7 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_INFO_BTF is not set CONFIG_DEBUG_INFO_COMPRESSED_NONE=y # CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set +# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set # CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y From a158f9f4058b3e401bd54e1efeee291ee6e9a256 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 12 Mar 2024 10:11:00 +0100 Subject: [PATCH 087/108] starfive: refresh patches CI reported that patches need to be refreshed, so lets refresh. Signed-off-by: Robert Marko --- ...16-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch | 4 ++-- ...-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch | 2 +- ...pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch | 2 +- ...32-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch | 2 +- .../0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch | 2 +- ...-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch | 4 ++-- .../0043-dt-bindings-net-Add-support-StarFive-dwmac.patch | 2 +- ...44-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch | 2 +- ...0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch | 2 +- .../0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch | 2 +- .../0108-mmc-starfive-Add-sdio-emmc-driver-support.patch | 2 +- ...hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch | 2 +- ...RISC-V-Add-arch-functions-to-support-hibernation-sus.patch | 2 +- .../starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch | 2 +- .../1022-reset-starfive-Add-JH7100-audio-reset-driver.patch | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch b/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch index 68b96fa388..d3f9a9cf22 100644 --- a/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch +++ b/target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch @@ -13,7 +13,7 @@ Signed-off-by: shanlong.li --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19650,12 +19650,13 @@ M: Emil Renner Berthing STARFIVE JH7100 PINCTRL DRIVER M: Emil Renner Berthing -@@ -19665,12 +19666,13 @@ F: Documentation/devicetree/bindings/pin +@@ -19672,12 +19673,13 @@ F: Documentation/devicetree/bindings/pin F: drivers/pinctrl/starfive/ F: include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h diff --git a/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch b/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch index eab4e6ee9f..9b3f41ec1e 100644 --- a/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch +++ b/target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch @@ -165,7 +165,7 @@ Signed-off-by: Hal Feng +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19658,13 +19658,15 @@ F: Documentation/devicetree/bindings/clo +@@ -19665,13 +19665,15 @@ F: Documentation/devicetree/bindings/clo F: drivers/clk/starfive/clk-starfive-jh71* F: include/dt-bindings/clock/starfive?jh71*.h diff --git a/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch b/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch index a9310aadc3..d5735b5980 100644 --- a/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch +++ b/target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch @@ -24,7 +24,7 @@ Signed-off-by: Hal Feng --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19664,7 +19664,7 @@ M: Jianlong Huang --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19650,6 +19650,12 @@ M: Emil Renner Berthing --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19682,6 +19682,20 @@ F: Documentation/devicetree/bindings/res +@@ -19689,6 +19689,20 @@ F: Documentation/devicetree/bindings/res F: drivers/reset/starfive/reset-starfive-jh71* F: include/dt-bindings/reset/starfive?jh71*.h diff --git a/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch b/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch index c4bf9bc56f..75b1d947b0 100644 --- a/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch +++ b/target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch @@ -76,7 +76,7 @@ Signed-off-by: William Qiu +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19656,6 +19656,11 @@ S: Supported +@@ -19663,6 +19663,11 @@ S: Supported F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml F: drivers/clk/starfive/clk-starfive-jh7110-pll.* @@ -88,7 +88,7 @@ Signed-off-by: William Qiu STARFIVE JH71X0 CLOCK DRIVERS M: Emil Renner Berthing M: Hal Feng -@@ -19686,6 +19691,7 @@ STARFIVE SOC DRIVER +@@ -19693,6 +19698,7 @@ STARFIVE SOC DRIVER M: Conor Dooley S: Maintained T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ diff --git a/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch b/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch index 4487c6995f..a66452c382 100644 --- a/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch +++ b/target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch @@ -175,7 +175,7 @@ Signed-off-by: Samin Guo + }; --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19650,6 +19650,12 @@ M: Emil Renner Berthing --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19655,6 +19655,7 @@ M: Emil Renner Berthing S: Maintained F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml diff --git a/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch b/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch index e9f8387e7f..1ab18838e6 100644 --- a/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch +++ b/target/linux/starfive/patches-6.1/0102-hwrng-starfive-Add-TRNG-driver-for-StarFive-SoC.patch @@ -19,7 +19,7 @@ Signed-off-by: Jia Jie Ho --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19709,6 +19709,12 @@ F: Documentation/devicetree/bindings/pow +@@ -19716,6 +19716,12 @@ F: Documentation/devicetree/bindings/pow F: drivers/soc/starfive/jh71xx_pmu.c F: include/dt-bindings/power/starfive,jh7110-pmu.h diff --git a/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch b/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch index ec330250e2..d7113de0ec 100644 --- a/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch +++ b/target/linux/starfive/patches-6.1/0105-drivers-watchdog-Add-StarFive-Watchdog-driver.patch @@ -18,7 +18,7 @@ Reviewed-by: Guenter Roeck --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19715,6 +19715,13 @@ S: Supported +@@ -19722,6 +19722,13 @@ S: Supported F: Documentation/devicetree/bindings/rng/starfive* F: drivers/char/hw_random/starfive-trng.c diff --git a/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch b/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch index 3aecc0a204..fecad30928 100644 --- a/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch +++ b/target/linux/starfive/patches-6.1/0108-mmc-starfive-Add-sdio-emmc-driver-support.patch @@ -17,7 +17,7 @@ Signed-off-by: William Qiu --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19657,6 +19657,12 @@ S: Maintained +@@ -19664,6 +19664,12 @@ S: Maintained F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c diff --git a/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch b/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch index b52cbd2ba5..aa062021ac 100644 --- a/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch +++ b/target/linux/starfive/patches-6.1/0110-hwmon-sfctemp-Add-StarFive-JH71x0-temperature-sensor.patch @@ -71,7 +71,7 @@ Signed-off-by: Hal Feng +================ ==== ============================================= --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -18679,6 +18679,14 @@ L: netdev@vger.kernel.org +@@ -18686,6 +18686,14 @@ L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/sfc/ diff --git a/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch b/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch index eae0559d9c..a47c49d968 100644 --- a/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch +++ b/target/linux/starfive/patches-6.1/0116-RISC-V-Add-arch-functions-to-support-hibernation-sus.patch @@ -132,7 +132,7 @@ Reviewed-by: Andrew Jones #endif --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile -@@ -65,6 +65,7 @@ obj-$(CONFIG_MODULES) += module.o +@@ -67,6 +67,7 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o obj-$(CONFIG_CPU_PM) += suspend_entry.o suspend.o diff --git a/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch b/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch index a341c96bcf..5bbb4cc4c5 100644 --- a/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch +++ b/target/linux/starfive/patches-6.1/1013-net-stmmac-use-GFP_DMA32.patch @@ -19,7 +19,7 @@ Signed-off-by: Matteo Croce if (priv->dma_cap.host_dma_width <= 32) gfp |= GFP_DMA32; -@@ -4613,7 +4613,7 @@ static inline void stmmac_rx_refill(stru +@@ -4615,7 +4615,7 @@ static inline void stmmac_rx_refill(stru struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; int dirty = stmmac_rx_dirty(priv, queue); unsigned int entry = rx_q->dirty_rx; diff --git a/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch b/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch index dc25d354d6..bf3eff0157 100644 --- a/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch +++ b/target/linux/starfive/patches-6.1/1022-reset-starfive-Add-JH7100-audio-reset-driver.patch @@ -20,7 +20,7 @@ Signed-off-by: Emil Renner Berthing --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19704,7 +19704,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS +@@ -19711,7 +19711,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS M: Emil Renner Berthing M: Hal Feng S: Maintained From 645b44d8ff06115602bdccdf2ef14b0fe0e410d4 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 12 Mar 2024 13:00:03 +0100 Subject: [PATCH 088/108] Revert "kernel: config: add symbol introduced with 6.2" This reverts commit 7ea82bc17d1583f4d9d46397846b0eb63e6651eb. This commit does not meet formal requirments, and has been merged due to my error. Signed-off-by: Robert Marko --- target/linux/generic/config-6.6 | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index db828745df..319f56fe01 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -1412,7 +1412,6 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_INFO_BTF is not set CONFIG_DEBUG_INFO_COMPRESSED_NONE=y # CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set -# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set # CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y From 4468cae502b5155f2bd4e1d8aac307acbb56800e Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 12 Mar 2024 22:44:37 +0800 Subject: [PATCH 089/108] kernel: config: add missing symbol for kenrel 6.6 CONFIG_HID_SUPPORT: Set default value for kmod-hid CONFIG_USB_CDNS3_IMX: CONFIG_USB_CDNS3_PCI_WRAP: CONFIG_USB_CDNSP_PCI: Introduced by db0d7cf6a1 (usb: add cdns3 support) Signed-off-by: Weijie Gao --- target/linux/generic/config-6.6 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 319f56fe01..4f3d7f2e23 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -2539,6 +2539,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_STEAM is not set # CONFIG_HID_STEELSERIES is not set # CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_SUPPORT is not set # CONFIG_HID_THINGM is not set # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_TIVO is not set @@ -7289,7 +7290,10 @@ CONFIG_USB_BELKIN=y # CONFIG_USB_CATC is not set # CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_IMX is not set +# CONFIG_USB_CDNS3_PCI_WRAP is not set # CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNSP_PCI is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_CHIPIDEA_GENERIC is not set From 1576474f55e9ffa08c171e4f74c64257fb0bed57 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Tue, 12 Mar 2024 12:12:41 +0100 Subject: [PATCH 090/108] ramips: switch to 6.1 kernel We have had the testing kernel for several weeks now. Let's switch to 6.1 to have more testers. Additionally, 6.6 is already in the pipeline. Signed-off-by: Nick Hainke --- target/linux/ramips/Makefile | 3 +- .../drivers/net/ethernet/ralink/ethtool.c | 10 - .../drivers/net/ethernet/ralink/mtk_eth_soc.c | 4 - .../files/drivers/pinctrl/pinctrl-aw9523.c | 6 - target/linux/ramips/modules.mk | 3 +- ...t-add-dt-binding-header-for-Mediatek.patch | 60 - ...ts-align-resets-with-binding-documen.patch | 114 - ...k-mediatek-mt7621-sysc-add-reset-cel.patch | 52 - ...system-controller-node-a-reset-provi.patch | 148 - ...21-avoid-to-init-common-ralink-reset.patch | 43 - ...-fix-mt7621_gate_is_enabled-function.patch | 77 - ...ck-add-mtmips-SoCs-system-controller.patch | 86 - ...lock-and-reset-driver-for-MTMIPS-SoC.patch | 1221 ------ ...ink-rt288x-remove-clock-related-code.patch | 81 - ...ink-rt305x-remove-clock-related-code.patch | 145 - ...ink-rt3883-remove-clock-related-code.patch | 85 - ...ink-mt7620-remove-clock-related-code.patch | 327 -- ...ips-ralink-remove-reset-related-code.patch | 121 - ...nk-get-cpu-rate-from-new-driver-code.patch | 102 - ...add-Mediatek-MTMIPS-Clock-maintainer.patch | 28 - ...oduce-commonly-used-remap-node-funct.patch | 189 - ...s-Fix-uninitialized-use-of-ret-in-mt.patch | 56 - ...h-all-supported-system-controller-co.patch | 40 - ...wdt-avoid-static-global-declarations.patch | 213 -- ...wdt-avoid-ralink-architecture-depend.patch | 104 - ...do-not-print-NFTS-register-value-as-.patch | 32 - ...use-dev_info-to-log-PCIe-device-dete.patch | 39 - ...ediaTek-MT7621-PCIe-host-controller-.patch | 1418 ------- ...1-Rename-mt7621_pci_-to-mt7621_pcie_.patch | 134 - ...mt7621-Declare-mt7621_pci_ops-static.patch | 30 - ...MIPS-setup-to-pcibios_root_bridge_pr.patch | 119 - ...of_match_ptr-to-avoid-unused-variabl.patch | 35 - ...7621-Remove-unused-function-pcie_rmw.patch | 35 - ...root_bridge_prepare-access-bridge-wi.patch | 38 - ...-mt7621-Add-sentinel-to-quirks-table.patch | 38 - ...t7621-Delay-phy-ports-initialization.patch | 52 - ...1-dma-handle-error-from-device_reset.patch | 31 - ...-dev_info-to-log-PCIe-card-detection.patch | 31 - .../patches-5.15/200-add-ralink-eth.patch | 20 - ...0-mt7620-export-chip-version-and-pkg.patch | 19 - ...e-to-enable-disable-the-cevt-r4k-irq.patch | 100 - ...IPS-ralink-add-cpu-frequency-scaling.patch | 195 - ...-MIPS-add-bootargs-override-property.patch | 63 - ...315-owrt-hack-fix-mt7688-cache-issue.patch | 28 - ...-select-illegal-access-driver-by-def.patch | 25 - ...ort-for-buggy-MT7621S-core-detection.patch | 74 - .../patches-5.15/324-mt7621-perfctr-fix.patch | 15 - ...mtd-cfi-cmdset-0002-force-word-write.patch | 20 - ...or-Add-support-for-BoHong-bh25q128as.patch | 75 - ...driver-support-for-MT7621-nand-flash.patch | 47 - ...documentation-for-mt7621-nand-driver.patch | 85 - ...ethernet-mediatek-support-net-labels.patch | 34 - ...y-simplify-phy_link_change-arguments.patch | 118 - .../721-NET-no-auto-carrier-off-support.patch | 47 - ...DT-Add-documentation-for-gpio-ralink.patch | 59 - ...alink-add-gpio-driver-for-ralink-SoC.patch | 416 --- ...support-for-GPIO-as-interrupt-contro.patch | 44 - .../patches-5.15/805-pinctrl-AW9523.patch | 72 - ...upport-requesting-different-function.patch | 45 - .../810-uvc-add-iPassion-iP2970-support.patch | 244 -- ...-DT-Add-documentation-for-spi-rt2880.patch | 44 - ...SPI-ralink-add-Ralink-SoC-spi-driver.patch | 579 --- .../825-i2c-MIPS-adds-ralink-I2C-driver.patch | 512 --- ...IPS-ralink-add-sdhci-for-mt7620a-SoC.patch | 43 - .../835-asoc-add-mt7620-support.patch | 1033 ------ ...erial-add-ugly-custom-baud-rate-hack.patch | 22 - .../845-pwm-add-mediatek-support.patch | 219 -- .../850-awake-rt305x-dwc2-controller.patch | 15 - .../patches-5.15/855-linkit_bootstrap.patch | 97 - .../860-ramips-add-eip93-driver.patch | 3276 ----------------- 70 files changed, 2 insertions(+), 13033 deletions(-) delete mode 100644 target/linux/ramips/patches-5.15/000-v5.18-01-dt-bindings-reset-add-dt-binding-header-for-Mediatek.patch delete mode 100644 target/linux/ramips/patches-5.15/000-v5.18-02-staging-mt7621-dts-align-resets-with-binding-documen.patch delete mode 100644 target/linux/ramips/patches-5.15/001-v5.18-01-dt-bindings-clock-mediatek-mt7621-sysc-add-reset-cel.patch delete mode 100644 target/linux/ramips/patches-5.15/001-v5.18-02-clk-ralink-make-system-controller-node-a-reset-provi.patch delete mode 100644 target/linux/ramips/patches-5.15/002-v6.0-MIPS-ralink-mt7621-avoid-to-init-common-ralink-reset.patch delete mode 100644 target/linux/ramips/patches-5.15/003-v6.3-clk-ralink-fix-mt7621_gate_is_enabled-function.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-01-dt-bindings-clock-add-mtmips-SoCs-system-controller.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-03-mips-ralink-rt288x-remove-clock-related-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-04-mips-ralink-rt305x-remove-clock-related-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-05-mips-ralink-rt3883-remove-clock-related-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-06-mips-ralink-mt7620-remove-clock-related-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-07-mips-ralink-remove-reset-related-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-08-mips-ralink-get-cpu-rate-from-new-driver-code.patch delete mode 100644 target/linux/ramips/patches-5.15/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch delete mode 100644 target/linux/ramips/patches-5.15/006-v6.5-mips-ralink-introduce-commonly-used-remap-node-funct.patch delete mode 100644 target/linux/ramips/patches-5.15/007-v6.5-clk-ralink-mtmips-Fix-uninitialized-use-of-ret-in-mt.patch delete mode 100644 target/linux/ramips/patches-5.15/008-v6.5-mips-ralink-match-all-supported-system-controller-co.patch delete mode 100644 target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch delete mode 100644 target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch delete mode 100644 target/linux/ramips/patches-5.15/010-v6.5-01-mips-pci-mt7620-do-not-print-NFTS-register-value-as-.patch delete mode 100644 target/linux/ramips/patches-5.15/010-v6.5-02-mips-pci-mt7620-use-dev_info-to-log-PCIe-device-dete.patch delete mode 100644 target/linux/ramips/patches-5.15/100-v5.16-PCI-mt7621-Add-MediaTek-MT7621-PCIe-host-controller-.patch delete mode 100644 target/linux/ramips/patches-5.15/101-v5.17-PCI-mt7621-Rename-mt7621_pci_-to-mt7621_pcie_.patch delete mode 100644 target/linux/ramips/patches-5.15/102-v5.17-PCI-mt7621-Declare-mt7621_pci_ops-static.patch delete mode 100644 target/linux/ramips/patches-5.15/103-v5.17-PCI-mt7621-Move-MIPS-setup-to-pcibios_root_bridge_pr.patch delete mode 100644 target/linux/ramips/patches-5.15/104-v5.17-PCI-mt7621-Drop-of_match_ptr-to-avoid-unused-variabl.patch delete mode 100644 target/linux/ramips/patches-5.15/105-v5.17-PCI-mt7621-Remove-unused-function-pcie_rmw.patch delete mode 100644 target/linux/ramips/patches-5.15/106-v5.17-PCI-Let-pcibios_root_bridge_prepare-access-bridge-wi.patch delete mode 100644 target/linux/ramips/patches-5.15/107-v6.2-PCI-mt7621-Add-sentinel-to-quirks-table.patch delete mode 100644 target/linux/ramips/patches-5.15/108-v6.3-PCI-mt7621-Delay-phy-ports-initialization.patch delete mode 100644 target/linux/ramips/patches-5.15/109-drivers-mt7621-dma-handle-error-from-device_reset.patch delete mode 100644 target/linux/ramips/patches-5.15/110-v6.4-PCI-mt7621-Use-dev_info-to-log-PCIe-card-detection.patch delete mode 100644 target/linux/ramips/patches-5.15/200-add-ralink-eth.patch delete mode 100644 target/linux/ramips/patches-5.15/300-mt7620-export-chip-version-and-pkg.patch delete mode 100644 target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch delete mode 100644 target/linux/ramips/patches-5.15/312-MIPS-ralink-add-cpu-frequency-scaling.patch delete mode 100644 target/linux/ramips/patches-5.15/314-MIPS-add-bootargs-override-property.patch delete mode 100644 target/linux/ramips/patches-5.15/315-owrt-hack-fix-mt7688-cache-issue.patch delete mode 100644 target/linux/ramips/patches-5.15/316-arch-mips-do-not-select-illegal-access-driver-by-def.patch delete mode 100644 target/linux/ramips/patches-5.15/320-MIPS-add-support-for-buggy-MT7621S-core-detection.patch delete mode 100644 target/linux/ramips/patches-5.15/324-mt7621-perfctr-fix.patch delete mode 100644 target/linux/ramips/patches-5.15/400-mtd-cfi-cmdset-0002-force-word-write.patch delete mode 100644 target/linux/ramips/patches-5.15/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch delete mode 100644 target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch delete mode 100644 target/linux/ramips/patches-5.15/411-dt-bindings-add-documentation-for-mt7621-nand-driver.patch delete mode 100644 target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch delete mode 100644 target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch delete mode 100644 target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch delete mode 100644 target/linux/ramips/patches-5.15/801-DT-Add-documentation-for-gpio-ralink.patch delete mode 100644 target/linux/ramips/patches-5.15/802-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch delete mode 100644 target/linux/ramips/patches-5.15/803-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch delete mode 100644 target/linux/ramips/patches-5.15/805-pinctrl-AW9523.patch delete mode 100644 target/linux/ramips/patches-5.15/808-pinctrl-mtmips-support-requesting-different-function.patch delete mode 100644 target/linux/ramips/patches-5.15/810-uvc-add-iPassion-iP2970-support.patch delete mode 100644 target/linux/ramips/patches-5.15/820-DT-Add-documentation-for-spi-rt2880.patch delete mode 100644 target/linux/ramips/patches-5.15/821-SPI-ralink-add-Ralink-SoC-spi-driver.patch delete mode 100644 target/linux/ramips/patches-5.15/825-i2c-MIPS-adds-ralink-I2C-driver.patch delete mode 100644 target/linux/ramips/patches-5.15/830-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch delete mode 100644 target/linux/ramips/patches-5.15/835-asoc-add-mt7620-support.patch delete mode 100644 target/linux/ramips/patches-5.15/840-serial-add-ugly-custom-baud-rate-hack.patch delete mode 100644 target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch delete mode 100644 target/linux/ramips/patches-5.15/850-awake-rt305x-dwc2-controller.patch delete mode 100644 target/linux/ramips/patches-5.15/855-linkit_bootstrap.patch delete mode 100644 target/linux/ramips/patches-5.15/860-ramips-add-eip93-driver.patch diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index 1aaa847345..787b2e94cc 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -10,8 +10,7 @@ BOARDNAME:=MediaTek Ralink MIPS SUBTARGETS:=mt7620 mt7621 mt76x8 rt288x rt305x rt3883 FEATURES:=squashfs gpio -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 define Target/Description Build firmware images for Ralink RT288x/RT3xxx based boards. diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c index 92cf0ef717..9b028fbbc9 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c @@ -125,15 +125,10 @@ out_get_link: return ethtool_op_get_link(dev); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) static int fe_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring, struct kernel_ethtool_ringparam *kernel_rp, struct netlink_ext_ack *extack) -#else -static int fe_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -#endif { struct fe_priv *priv = netdev_priv(dev); @@ -153,15 +148,10 @@ static int fe_set_ringparam(struct net_device *dev, return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) static void fe_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring, struct kernel_ethtool_ringparam *kernel_rp, struct netlink_ext_ack *extack) -#else -static void fe_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -#endif { struct fe_priv *priv = netdev_priv(dev); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index dda9abee49..3748264dad 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -1636,11 +1636,7 @@ static int fe_probe(struct platform_device *pdev) priv->tx_ring.tx_ring_size *= 4; priv->rx_ring.rx_ring_size *= 4; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) netif_napi_add_weight(netdev, &priv->rx_napi, fe_poll, napi_weight); -#else - netif_napi_add(netdev, &priv->rx_napi, fe_poll, napi_weight); -#endif fe_set_ethtool_ops(netdev); err = register_netdev(netdev); diff --git a/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c b/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c index e151f44590..65babf9946 100644 --- a/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c +++ b/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c @@ -1097,12 +1097,10 @@ static int aw9523_remove(struct i2c_client *client) return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) static void aw9523_remove_void(struct i2c_client *client) { aw9523_remove(client); } -#endif static const struct i2c_device_id aw9523_i2c_id_table[] = { { "aw9523_i2c", 0 }, @@ -1121,11 +1119,7 @@ static struct i2c_driver aw9523_driver = { .of_match_table = of_aw9523_i2c_match, }, .probe = aw9523_probe, - #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) .remove = aw9523_remove_void, - #else - .remove = aw9523_remove, - #endif .id_table = aw9523_i2c_id_table, }; module_i2c_driver(aw9523_driver); diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk index 4a8739fe5c..429bb2cd26 100644 --- a/target/linux/ramips/modules.mk +++ b/target/linux/ramips/modules.mk @@ -101,8 +101,7 @@ define KernelPackage/hsdma-mtk CONFIG_MTK_HSDMA FILES:= \ $(LINUX_DIR)/drivers/dma/virt-dma.ko \ - $(LINUX_DIR)/drivers/staging/mt7621-dma/hsdma-mt7621.ko@lt5.17 \ - $(LINUX_DIR)/drivers/dma/mediatek/hsdma-mt7621.ko@ge5.17 + $(LINUX_DIR)/drivers/dma/mediatek/hsdma-mt7621.ko AUTOLOAD:=$(call AutoLoad,53,hsdma-mt7621) endef diff --git a/target/linux/ramips/patches-5.15/000-v5.18-01-dt-bindings-reset-add-dt-binding-header-for-Mediatek.patch b/target/linux/ramips/patches-5.15/000-v5.18-01-dt-bindings-reset-add-dt-binding-header-for-Mediatek.patch deleted file mode 100644 index a102c607b6..0000000000 --- a/target/linux/ramips/patches-5.15/000-v5.18-01-dt-bindings-reset-add-dt-binding-header-for-Mediatek.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f383b0770612838e78986231710c0a3afee4db42 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 10 Jan 2022 12:49:27 +0100 -Subject: [PATCH 1/2] dt-bindings: reset: add dt binding header for Mediatek MT7621 resets -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add dt binding header for resets lines in Mediatek MT7621 SoCs. - -Acked-by: Rob Herring -Tested-by: Arınç ÜNAL -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20220110114930.1406665-2-sergio.paracuellos@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - include/dt-bindings/reset/mt7621-reset.h | 37 ++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - create mode 100644 include/dt-bindings/reset/mt7621-reset.h - ---- /dev/null -+++ b/include/dt-bindings/reset/mt7621-reset.h -@@ -0,0 +1,37 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2021 Sergio Paracuellos -+ * Author: Sergio Paracuellos -+ */ -+ -+#ifndef DT_BINDING_MT7621_RESET_H -+#define DT_BINDING_MT7621_RESET_H -+ -+#define MT7621_RST_SYS 0 -+#define MT7621_RST_MCM 2 -+#define MT7621_RST_HSDMA 5 -+#define MT7621_RST_FE 6 -+#define MT7621_RST_SPDIFTX 7 -+#define MT7621_RST_TIMER 8 -+#define MT7621_RST_INT 9 -+#define MT7621_RST_MC 10 -+#define MT7621_RST_PCM 11 -+#define MT7621_RST_PIO 13 -+#define MT7621_RST_GDMA 14 -+#define MT7621_RST_NFI 15 -+#define MT7621_RST_I2C 16 -+#define MT7621_RST_I2S 17 -+#define MT7621_RST_SPI 18 -+#define MT7621_RST_UART1 19 -+#define MT7621_RST_UART2 20 -+#define MT7621_RST_UART3 21 -+#define MT7621_RST_ETH 23 -+#define MT7621_RST_PCIE0 24 -+#define MT7621_RST_PCIE1 25 -+#define MT7621_RST_PCIE2 26 -+#define MT7621_RST_AUX_STCK 28 -+#define MT7621_RST_CRYPTO 29 -+#define MT7621_RST_SDXC 30 -+#define MT7621_RST_PPE 31 -+ -+#endif /* DT_BINDING_MT7621_RESET_H */ diff --git a/target/linux/ramips/patches-5.15/000-v5.18-02-staging-mt7621-dts-align-resets-with-binding-documen.patch b/target/linux/ramips/patches-5.15/000-v5.18-02-staging-mt7621-dts-align-resets-with-binding-documen.patch deleted file mode 100644 index e4fd34b28c..0000000000 --- a/target/linux/ramips/patches-5.15/000-v5.18-02-staging-mt7621-dts-align-resets-with-binding-documen.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 64b2d6ffff862c0e7278198b4229e42e1abb3bb1 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 10 Jan 2022 12:49:30 +0100 -Subject: [PATCH 2/2] staging: mt7621-dts: align resets with binding documentation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Binding documentation for compatible 'mediatek,mt7621-sysc' has been updated -to be used as a reset provider. Align reset related bits and system controller -node with binding documentation along the dtsi file. - -Tested-by: Arınç ÜNAL -Reviewed-by: Philipp Zabel -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20220110114930.1406665-5-sergio.paracuellos@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/staging/mt7621-dts/mt7621.dtsi | 21 +++++++++------------ - 1 file changed, 9 insertions(+), 12 deletions(-) - ---- a/drivers/staging/mt7621-dts/mt7621.dtsi -+++ b/drivers/staging/mt7621-dts/mt7621.dtsi -@@ -1,6 +1,7 @@ - #include - #include - #include -+#include - - / { - #address-cells = <1>; -@@ -59,6 +60,7 @@ - compatible = "mediatek,mt7621-sysc", "syscon"; - reg = <0x0 0x100>; - #clock-cells = <1>; -+ #reset-cells = <1>; - ralink,memctl = <&memc>; - clock-output-names = "xtal", "cpu", "bus", - "50m", "125m", "150m", -@@ -88,7 +90,7 @@ - - clocks = <&sysc MT7621_CLK_I2C>; - clock-names = "i2c"; -- resets = <&rstctrl 16>; -+ resets = <&sysc MT7621_RST_I2C>; - reset-names = "i2c"; - - #address-cells = <1>; -@@ -161,7 +163,7 @@ - clocks = <&sysc MT7621_CLK_SPI>; - clock-names = "spi"; - -- resets = <&rstctrl 18>; -+ resets = <&sysc MT7621_RST_SPI>; - reset-names = "spi"; - - #address-cells = <1>; -@@ -296,11 +298,6 @@ - }; - }; - -- rstctrl: rstctrl { -- compatible = "ralink,rt2880-reset"; -- #reset-cells = <1>; -- }; -- - sdhci: sdhci@1e130000 { - status = "disabled"; - -@@ -383,7 +380,7 @@ - #address-cells = <1>; - #size-cells = <0>; - -- resets = <&rstctrl 6 &rstctrl 23>; -+ resets = <&sysc MT7621_RST_FE &sysc MT7621_RST_ETH>; - reset-names = "fe", "eth"; - - interrupt-parent = <&gic>; -@@ -423,7 +420,7 @@ - #size-cells = <0>; - reg = <0>; - mediatek,mcm; -- resets = <&rstctrl 2>; -+ resets = <&sysc MT7621_RST_MCM>; - reset-names = "mcm"; - interrupt-controller; - #interrupt-cells = <1>; -@@ -516,7 +513,7 @@ - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>; -- resets = <&rstctrl 24>; -+ resets = <&sysc MT7621_RST_PCIE0>; - clocks = <&sysc MT7621_CLK_PCIE0>; - phys = <&pcie0_phy 1>; - phy-names = "pcie-phy0"; -@@ -531,7 +528,7 @@ - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>; -- resets = <&rstctrl 25>; -+ resets = <&sysc MT7621_RST_PCIE1>; - clocks = <&sysc MT7621_CLK_PCIE1>; - phys = <&pcie0_phy 1>; - phy-names = "pcie-phy1"; -@@ -546,7 +543,7 @@ - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; -- resets = <&rstctrl 26>; -+ resets = <&sysc MT7621_RST_PCIE2>; - clocks = <&sysc MT7621_CLK_PCIE2>; - phys = <&pcie2_phy 0>; - phy-names = "pcie-phy2"; diff --git a/target/linux/ramips/patches-5.15/001-v5.18-01-dt-bindings-clock-mediatek-mt7621-sysc-add-reset-cel.patch b/target/linux/ramips/patches-5.15/001-v5.18-01-dt-bindings-clock-mediatek-mt7621-sysc-add-reset-cel.patch deleted file mode 100644 index 7fb95064f0..0000000000 --- a/target/linux/ramips/patches-5.15/001-v5.18-01-dt-bindings-clock-mediatek-mt7621-sysc-add-reset-cel.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 478b09fa2c00cbc40d25bc061befdf11f04a27ad Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Thu, 10 Feb 2022 10:48:58 +0100 -Subject: [PATCH 1/2] dt-bindings: clock: mediatek,mt7621-sysc: add '#reset-cells' property - -Make system controller a reset provider for all the peripherals in the -MT7621 SoC adding '#reset-cells' property. - -Acked-by: Rob Herring -Acked-by: Stephen Boyd -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20220210094859.927868-2-sergio.paracuellos@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - .../devicetree/bindings/clock/mediatek,mt7621-sysc.yaml | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml -+++ b/Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml -@@ -22,6 +22,11 @@ description: | - - The clocks are provided inside a system controller node. - -+ This node is also a reset provider for all the peripherals. -+ -+ Reset related bits are defined in: -+ [2]: . -+ - properties: - compatible: - items: -@@ -37,6 +42,12 @@ properties: - clocks. - const: 1 - -+ "#reset-cells": -+ description: -+ The first cell indicates the reset bit within the register, see -+ [2] for available resets. -+ const: 1 -+ - ralink,memctl: - $ref: /schemas/types.yaml#/definitions/phandle - description: -@@ -61,6 +72,7 @@ examples: - compatible = "mediatek,mt7621-sysc", "syscon"; - reg = <0x0 0x100>; - #clock-cells = <1>; -+ #reset-cells = <1>; - ralink,memctl = <&memc>; - clock-output-names = "xtal", "cpu", "bus", - "50m", "125m", "150m", diff --git a/target/linux/ramips/patches-5.15/001-v5.18-02-clk-ralink-make-system-controller-node-a-reset-provi.patch b/target/linux/ramips/patches-5.15/001-v5.18-02-clk-ralink-make-system-controller-node-a-reset-provi.patch deleted file mode 100644 index c70a1c9bbc..0000000000 --- a/target/linux/ramips/patches-5.15/001-v5.18-02-clk-ralink-make-system-controller-node-a-reset-provi.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 38a8553b0a22ed54f014d8402fedd268b529175c Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Thu, 10 Feb 2022 10:48:59 +0100 -Subject: [PATCH 2/2] clk: ralink: make system controller node a reset provider - -MT7621 system controller node is already providing the clocks for the whole -system but must also serve as a reset provider. Hence, add reset controller -related code to the clock driver itself. To get resets properly ready for -the rest of the world we need to move platform driver initialization process -to 'arch_initcall'. - -CC: Philipp Zabel -Reviewed-by: Philipp Zabel -Acked-by: Stephen Boyd -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20220210094859.927868-3-sergio.paracuellos@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/clk/ralink/clk-mt7621.c | 92 ++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 91 insertions(+), 1 deletion(-) - ---- a/drivers/clk/ralink/clk-mt7621.c -+++ b/drivers/clk/ralink/clk-mt7621.c -@@ -11,14 +11,17 @@ - #include - #include - #include -+#include - #include - #include -+#include - - /* Configuration registers */ - #define SYSC_REG_SYSTEM_CONFIG0 0x10 - #define SYSC_REG_SYSTEM_CONFIG1 0x14 - #define SYSC_REG_CLKCFG0 0x2c - #define SYSC_REG_CLKCFG1 0x30 -+#define SYSC_REG_RESET_CTRL 0x34 - #define SYSC_REG_CUR_CLK_STS 0x44 - #define MEMC_REG_CPU_PLL 0x648 - -@@ -398,6 +401,82 @@ free_clk_priv: - } - CLK_OF_DECLARE_DRIVER(mt7621_clk, "mediatek,mt7621-sysc", mt7621_clk_init); - -+struct mt7621_rst { -+ struct reset_controller_dev rcdev; -+ struct regmap *sysc; -+}; -+ -+static struct mt7621_rst *to_mt7621_rst(struct reset_controller_dev *dev) -+{ -+ return container_of(dev, struct mt7621_rst, rcdev); -+} -+ -+static int mt7621_assert_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ struct mt7621_rst *data = to_mt7621_rst(rcdev); -+ struct regmap *sysc = data->sysc; -+ -+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); -+} -+ -+static int mt7621_deassert_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ struct mt7621_rst *data = to_mt7621_rst(rcdev); -+ struct regmap *sysc = data->sysc; -+ -+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0); -+} -+ -+static int mt7621_reset_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ int ret; -+ -+ ret = mt7621_assert_device(rcdev, id); -+ if (ret < 0) -+ return ret; -+ -+ return mt7621_deassert_device(rcdev, id); -+} -+ -+static int mt7621_rst_xlate(struct reset_controller_dev *rcdev, -+ const struct of_phandle_args *reset_spec) -+{ -+ unsigned long id = reset_spec->args[0]; -+ -+ if (id == MT7621_RST_SYS || id >= rcdev->nr_resets) -+ return -EINVAL; -+ -+ return id; -+} -+ -+static const struct reset_control_ops reset_ops = { -+ .reset = mt7621_reset_device, -+ .assert = mt7621_assert_device, -+ .deassert = mt7621_deassert_device -+}; -+ -+static int mt7621_reset_init(struct device *dev, struct regmap *sysc) -+{ -+ struct mt7621_rst *rst_data; -+ -+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); -+ if (!rst_data) -+ return -ENOMEM; -+ -+ rst_data->sysc = sysc; -+ rst_data->rcdev.ops = &reset_ops; -+ rst_data->rcdev.owner = THIS_MODULE; -+ rst_data->rcdev.nr_resets = 32; -+ rst_data->rcdev.of_reset_n_cells = 1; -+ rst_data->rcdev.of_xlate = mt7621_rst_xlate; -+ rst_data->rcdev.of_node = dev_of_node(dev); -+ -+ return devm_reset_controller_register(dev, &rst_data->rcdev); -+} -+ - static int mt7621_clk_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -@@ -424,6 +503,12 @@ static int mt7621_clk_probe(struct platf - return ret; - } - -+ ret = mt7621_reset_init(dev, priv->sysc); -+ if (ret) { -+ dev_err(dev, "Could not init reset controller\n"); -+ return ret; -+ } -+ - count = ARRAY_SIZE(mt7621_clks_base) + - ARRAY_SIZE(mt7621_fixed_clks) + ARRAY_SIZE(mt7621_gates); - clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count), -@@ -485,4 +570,9 @@ static struct platform_driver mt7621_clk - .of_match_table = mt7621_clk_of_match, - }, - }; --builtin_platform_driver(mt7621_clk_driver); -+ -+static int __init mt7621_clk_reset_init(void) -+{ -+ return platform_driver_register(&mt7621_clk_driver); -+} -+arch_initcall(mt7621_clk_reset_init); diff --git a/target/linux/ramips/patches-5.15/002-v6.0-MIPS-ralink-mt7621-avoid-to-init-common-ralink-reset.patch b/target/linux/ramips/patches-5.15/002-v6.0-MIPS-ralink-mt7621-avoid-to-init-common-ralink-reset.patch deleted file mode 100644 index cef73c6eae..0000000000 --- a/target/linux/ramips/patches-5.15/002-v6.0-MIPS-ralink-mt7621-avoid-to-init-common-ralink-reset.patch +++ /dev/null @@ -1,43 +0,0 @@ -From bb3ababe7f986900672e0048153c31aa4a21f96b Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Sat, 17 Dec 2022 08:48:06 +0100 -Subject: [PATCH] MIPS: ralink: mt7621: avoid to init common ralink reset controller - -[ Upstream commit 76ce51798cb16738a4a28a6662e7344aaf7ef769 ] - -Commit 38a8553b0a22 ("clk: ralink: make system controller node a reset provider") -make system controller a reset provider for mt7621 ralink SoCs. Ralink init code -also tries to start previous common reset controller which at the end tries to -find device tree node 'ralink,rt2880-reset'. mt7621 device tree file is not -using at all this node anymore. Hence avoid to init this common reset controller -for mt7621 ralink SoCs to avoid 'Failed to find reset controller node' boot -error trace error. - -Fixes: 64b2d6ffff86 ("staging: mt7621-dts: align resets with binding documentation") -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer -Signed-off-by: Sasha Levin ---- - arch/mips/ralink/of.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #include "common.h" - -@@ -95,7 +96,8 @@ static int __init plat_of_setup(void) - __dt_register_buses(soc_info.compatible, "palmbus"); - - /* make sure that the reset controller is setup early */ -- ralink_rst_init(); -+ if (ralink_soc != MT762X_SOC_MT7621AT) -+ ralink_rst_init(); - - return 0; - } diff --git a/target/linux/ramips/patches-5.15/003-v6.3-clk-ralink-fix-mt7621_gate_is_enabled-function.patch b/target/linux/ramips/patches-5.15/003-v6.3-clk-ralink-fix-mt7621_gate_is_enabled-function.patch deleted file mode 100644 index 4574f7977f..0000000000 --- a/target/linux/ramips/patches-5.15/003-v6.3-clk-ralink-fix-mt7621_gate_is_enabled-function.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 35dcae535afc153fa83f2fe51c0812536c192c58 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 6 Feb 2023 09:33:05 +0100 -Subject: [PATCH] clk: ralink: fix 'mt7621_gate_is_enabled()' function - -Compiling clock driver with CONFIG_UBSAN enabled shows the following trace: - -UBSAN: shift-out-of-bounds in drivers/clk/ralink/clk-mt7621.c:121:15 -shift exponent 131072 is too large for 32-bit type 'long unsigned int' -CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.15.86 #0 -Stack : ... - -Call Trace: -[<80009a58>] show_stack+0x38/0x118 -[<8045ce04>] dump_stack_lvl+0x60/0x80 -[<80458868>] ubsan_epilogue+0x10/0x54 -[<804590e0>] __ubsan_handle_shift_out_of_bounds+0x118/0x190 -[<804c9a10>] mt7621_gate_is_enabled+0x98/0xa0 -[<804bb774>] clk_core_is_enabled+0x34/0x90 -[<80aad73c>] clk_disable_unused_subtree+0x98/0x1e4 -[<80aad6d4>] clk_disable_unused_subtree+0x30/0x1e4 -[<80aad6d4>] clk_disable_unused_subtree+0x30/0x1e4 -[<80aad900>] clk_disable_unused+0x78/0x120 -[<80002030>] do_one_initcall+0x54/0x1f0 -[<80a922a4>] kernel_init_freeable+0x280/0x31c -[<808047c4>] kernel_init+0x20/0x118 -[<80003e58>] ret_from_kernel_thread+0x14/0x1c - -Shifting a value (131032) larger than the type (32 bit unsigned integer) -is undefined behaviour in C. - -The problem is in 'mt7621_gate_is_enabled()' function which is using the -'BIT()' kernel macro with the bit index for the clock gate to check if the -bit is set. When the clock gates structure is created driver is already -setting 'bit_idx' using 'BIT()' macro, so we are wrongly applying an extra -'BIT()' mask here. Removing it solve the problem and makes this function -correct. However when clock gating is correctly working, the kernel starts -disabling those clocks that are not requested. Some drivers for this SoC -are older than this clock driver itself. So to avoid the kernel to disable -clocks that have been enabled until now, we must apply 'CLK_IS_CRITICAL' -flag on gates initialization code. - -Fixes: 48df7a26f470 ("clk: ralink: add clock driver for mt7621 SoC") -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20230206083305.147582-1-sergio.paracuellos@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/ralink/clk-mt7621.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - ---- a/drivers/clk/ralink/clk-mt7621.c -+++ b/drivers/clk/ralink/clk-mt7621.c -@@ -121,7 +121,7 @@ static int mt7621_gate_is_enabled(struct - if (regmap_read(sysc, SYSC_REG_CLKCFG1, &val)) - return 0; - -- return val & BIT(clk_gate->bit_idx); -+ return val & clk_gate->bit_idx; - } - - static const struct clk_ops mt7621_gate_ops = { -@@ -133,8 +133,14 @@ static const struct clk_ops mt7621_gate_ - static int mt7621_gate_ops_init(struct device *dev, - struct mt7621_gate *sclk) - { -+ /* -+ * There are drivers for this SoC that are older -+ * than clock driver and are not prepared for the clock. -+ * We don't want the kernel to disable anything so we -+ * add CLK_IS_CRITICAL flag here. -+ */ - struct clk_init_data init = { -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .num_parents = 1, - .parent_names = &sclk->parent_name, - .ops = &mt7621_gate_ops, diff --git a/target/linux/ramips/patches-5.15/005-v6.5-01-dt-bindings-clock-add-mtmips-SoCs-system-controller.patch b/target/linux/ramips/patches-5.15/005-v6.5-01-dt-bindings-clock-add-mtmips-SoCs-system-controller.patch deleted file mode 100644 index 94784f7885..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-01-dt-bindings-clock-add-mtmips-SoCs-system-controller.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 612616e6381929e7f9e303f8b8ad3655cc101516 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:33 +0200 -Subject: [PATCH 1/9] dt-bindings: clock: add mtmips SoCs system controller - -Adds device tree binding documentation for system controller node present -in Mediatek MIPS and Ralink SOCs. This node is a clock and reset provider -for the rest of the world. This covers RT2880, RT3050, RT3052, RT3350, -RT3883, RT5350, MT7620, MT7628 and MT7688 SoCs. - -Reviewed-by: Rob Herring -Acked-by: Stephen Boyd -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - .../bindings/clock/mediatek,mtmips-sysc.yaml | 64 ++++++++++++++++++++++ - 1 file changed, 64 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml -@@ -0,0 +1,64 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/mediatek,mtmips-sysc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MTMIPS SoCs System Controller -+ -+maintainers: -+ - Sergio Paracuellos -+ -+description: | -+ MediaTek MIPS and Ralink SoCs provides a system controller to allow -+ to access to system control registers. These registers include clock -+ and reset related ones so this node is both clock and reset provider -+ for the rest of the world. -+ -+ These SoCs have an XTAL from where the cpu clock is -+ provided as well as derived clocks for the bus and the peripherals. -+ -+properties: -+ compatible: -+ items: -+ - enum: -+ - ralink,mt7620-sysc -+ - ralink,mt7628-sysc -+ - ralink,mt7688-sysc -+ - ralink,rt2880-sysc -+ - ralink,rt3050-sysc -+ - ralink,rt3052-sysc -+ - ralink,rt3352-sysc -+ - ralink,rt3883-sysc -+ - ralink,rt5350-sysc -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+ '#clock-cells': -+ description: -+ The first cell indicates the clock number. -+ const: 1 -+ -+ '#reset-cells': -+ description: -+ The first cell indicates the reset bit within the register. -+ const: 1 -+ -+required: -+ - compatible -+ - reg -+ - '#clock-cells' -+ - '#reset-cells' -+ -+additionalProperties: false -+ -+examples: -+ - | -+ syscon@0 { -+ compatible = "ralink,rt5350-sysc", "syscon"; -+ reg = <0x0 0x100>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; diff --git a/target/linux/ramips/patches-5.15/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch b/target/linux/ramips/patches-5.15/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch deleted file mode 100644 index cef39978e0..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-02-clk-ralink-add-clock-and-reset-driver-for-MTMIPS-SoC.patch +++ /dev/null @@ -1,1221 +0,0 @@ -From 6f3b15586eef736831abe6a14f2a6906bc0dc074 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:34 +0200 -Subject: [PATCH 2/9] clk: ralink: add clock and reset driver for MTMIPS SoCs - -Until now, clock related code for old ralink SoCs was based in fixed clocks -using 'clk_register_fixed_rate' and 'clkdev_create' directly doing in code -and not using device tree at all for their definition. Including this driver -is an effort to be able to define proper clocks using device tree and also -cleaning all the clock and reset related code from 'arch/mips/ralink' dir. -This clock and reset driver covers all the ralink SoCs but MT7621 which is -the newest and provides gating and some differences that make it different -from its predecesors. It has its own driver since some time ago. The ralink -SoCs we are taking about are RT2880, RT3050, RT3052, RT3350, RT3352, RT3883, -RT5350, MT7620, MT7628 and MT7688. Mostly the code in this new driver has -been extracted from 'arch/mips/ralink' and cleanly put using kernel clock -driver APIs. The clock plans for this SoCs only talks about relation between -CPU frequency and BUS frequency. This relation is different depending on the -particular SoC. CPU clock is derived from XTAL frequencies. - -Depending on the SoC we have the following frequencies: -* RT2880 SoC: - - XTAL: 40 MHz. - - CPU: 250, 266, 280 or 300 MHz. - - BUS: CPU / 2 MHz. -* RT3050, RT3052, RT3350: - - XTAL: 40 MHz. - - CPU: 320 or 384 MHz. - - BUS: CPU / 3 MHz. -* RT3352: - - XTAL: 40 MHz. - - CPU: 384 or 400 MHz. - - BUS: CPU / 3 MHz. - - PERIPH: 40 MHz. -* RT3383: - - XTAL: 40 MHz. - - CPU: 250, 384, 480 or 500 MHz. - - BUS: Depends on RAM Type and CPU: - + RAM DDR2: 125. ELSE 83 MHz. - + RAM DDR2: 128. ELSE 96 MHz. - + RAM DDR2: 160. ELSE 120 MHz. - + RAM DDR2: 166. ELSE 125 MHz. -* RT5350: - - XTAL: 40 MHz. - - CPU: 300, 320 or 360 MHz. - - BUS: CPU / 3, CPU / 4, CPU / 3 MHz. - - PERIPH: 40 MHz. -* MT7628 and MT7688: - - XTAL: 20 MHz or 40 MHz. - - CPU: 575 or 580 MHz. - - BUS: CPU / 3. - - PCMI2S: 480 MHz. - - PERIPH: 40 MHz. -* MT7620: - - XTAL: 20 MHz or 40 MHz. - - PLL: XTAL, 480, 600 MHz. - - CPU: depends on PLL and some mult and dividers. - - BUS: depends on PLL and some mult and dividers. - - PERIPH: 40 or XTAL MHz. - -MT7620 is a bit more complex deriving CPU clock from a PLL and an bunch of -register reads and predividers. To derive CPU and BUS frequencies in the -MT7620 SoC 'mt7620_calc_rate()' helper is used. - -In the case XTAL can have different frequencies and we need a different -clock frequency for peripherals 'periph' clock in introduced. - -The rest of the peripherals present in the SoC just follow their parent -frequencies. - -With this information the clk driver will provide all the clock and reset -functionality from a set of hardcoded clocks allowing to define a nice -device tree without fixed clocks. - -Acked-by: Stephen Boyd -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - drivers/clk/ralink/Kconfig | 7 + - drivers/clk/ralink/Makefile | 1 + - drivers/clk/ralink/clk-mtmips.c | 1115 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 1123 insertions(+) - create mode 100644 drivers/clk/ralink/clk-mtmips.c - ---- a/drivers/clk/ralink/Kconfig -+++ b/drivers/clk/ralink/Kconfig -@@ -9,3 +9,10 @@ config CLK_MT7621 - select MFD_SYSCON - help - This driver supports MediaTek MT7621 basic clocks. -+ -+config CLK_MTMIPS -+ bool "Clock driver for MTMIPS SoCs" -+ depends on SOC_RT305X || SOC_RT288X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST -+ select MFD_SYSCON -+ help -+ This driver supports MTMIPS basic clocks. ---- a/drivers/clk/ralink/Makefile -+++ b/drivers/clk/ralink/Makefile -@@ -1,2 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_CLK_MT7621) += clk-mt7621.o -+obj-$(CONFIG_CLK_MTMIPS) += clk-mtmips.o ---- /dev/null -+++ b/drivers/clk/ralink/clk-mtmips.c -@@ -0,0 +1,1115 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * MTMIPS SoCs Clock Driver -+ * Author: Sergio Paracuellos -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Configuration registers */ -+#define SYSC_REG_SYSTEM_CONFIG 0x10 -+#define SYSC_REG_CLKCFG0 0x2c -+#define SYSC_REG_RESET_CTRL 0x34 -+#define SYSC_REG_CPU_SYS_CLKCFG 0x3c -+#define SYSC_REG_CPLL_CONFIG0 0x54 -+#define SYSC_REG_CPLL_CONFIG1 0x58 -+ -+/* RT2880 SoC */ -+#define RT2880_CONFIG_CPUCLK_SHIFT 20 -+#define RT2880_CONFIG_CPUCLK_MASK 0x3 -+#define RT2880_CONFIG_CPUCLK_250 0x0 -+#define RT2880_CONFIG_CPUCLK_266 0x1 -+#define RT2880_CONFIG_CPUCLK_280 0x2 -+#define RT2880_CONFIG_CPUCLK_300 0x3 -+ -+/* RT305X SoC */ -+#define RT305X_SYSCFG_CPUCLK_SHIFT 18 -+#define RT305X_SYSCFG_CPUCLK_MASK 0x1 -+#define RT305X_SYSCFG_CPUCLK_LOW 0x0 -+#define RT305X_SYSCFG_CPUCLK_HIGH 0x1 -+ -+/* RT3352 SoC */ -+#define RT3352_SYSCFG0_CPUCLK_SHIFT 8 -+#define RT3352_SYSCFG0_CPUCLK_MASK 0x1 -+#define RT3352_SYSCFG0_CPUCLK_LOW 0x0 -+#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 -+ -+/* RT3383 SoC */ -+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) -+#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 -+#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 -+#define RT3883_SYSCFG0_CPUCLK_250 0x0 -+#define RT3883_SYSCFG0_CPUCLK_384 0x1 -+#define RT3883_SYSCFG0_CPUCLK_480 0x2 -+#define RT3883_SYSCFG0_CPUCLK_500 0x3 -+ -+/* RT5350 SoC */ -+#define RT5350_CLKCFG0_XTAL_SEL BIT(20) -+#define RT5350_SYSCFG0_CPUCLK_SHIFT 8 -+#define RT5350_SYSCFG0_CPUCLK_MASK 0x3 -+#define RT5350_SYSCFG0_CPUCLK_360 0x0 -+#define RT5350_SYSCFG0_CPUCLK_320 0x2 -+#define RT5350_SYSCFG0_CPUCLK_300 0x3 -+ -+/* MT7620 and MT76x8 SoCs */ -+#define MT7620_XTAL_FREQ_SEL BIT(6) -+#define CPLL_CFG0_SW_CFG BIT(31) -+#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 -+#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 -+#define CPLL_CFG0_LC_CURFCK BIT(15) -+#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) -+#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 -+#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 -+#define CPLL_CFG1_CPU_AUX1 BIT(25) -+#define CPLL_CFG1_CPU_AUX0 BIT(24) -+#define CLKCFG0_PERI_CLK_SEL BIT(4) -+#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 -+#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf -+#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ -+#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ -+#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 -+#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f -+#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 -+#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f -+ -+/* clock scaling */ -+#define CLKCFG_FDIV_MASK 0x1f00 -+#define CLKCFG_FDIV_USB_VAL 0x0300 -+#define CLKCFG_FFRAC_MASK 0x001f -+#define CLKCFG_FFRAC_USB_VAL 0x0003 -+ -+struct mtmips_clk; -+struct mtmips_clk_fixed; -+struct mtmips_clk_factor; -+ -+struct mtmips_clk_data { -+ struct mtmips_clk *clk_base; -+ size_t num_clk_base; -+ struct mtmips_clk_fixed *clk_fixed; -+ size_t num_clk_fixed; -+ struct mtmips_clk_factor *clk_factor; -+ size_t num_clk_factor; -+ struct mtmips_clk *clk_periph; -+ size_t num_clk_periph; -+}; -+ -+struct mtmips_clk_priv { -+ struct regmap *sysc; -+ const struct mtmips_clk_data *data; -+}; -+ -+struct mtmips_clk { -+ struct clk_hw hw; -+ struct mtmips_clk_priv *priv; -+}; -+ -+struct mtmips_clk_fixed { -+ const char *name; -+ const char *parent; -+ unsigned long rate; -+ struct clk_hw *hw; -+}; -+ -+struct mtmips_clk_factor { -+ const char *name; -+ const char *parent; -+ int mult; -+ int div; -+ unsigned long flags; -+ struct clk_hw *hw; -+}; -+ -+static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ return parent_rate; -+} -+ -+static const struct clk_ops mtmips_periph_clk_ops = { -+ .recalc_rate = mtmips_pherip_clk_rate, -+}; -+ -+#define CLK_PERIPH(_name, _parent) { \ -+ .init = &(const struct clk_init_data) { \ -+ .name = _name, \ -+ .ops = &mtmips_periph_clk_ops, \ -+ .parent_data = &(const struct clk_parent_data) {\ -+ .name = _parent, \ -+ .fw_name = _parent \ -+ }, \ -+ .num_parents = 1, \ -+ /* \ -+ * There are drivers for these SoCs that are \ -+ * older than clock driver and are not prepared \ -+ * for the clock. We don't want the kernel to \ -+ * disable anything so we add CLK_IS_CRITICAL \ -+ * flag here. \ -+ */ \ -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \ -+ }, \ -+} -+ -+static struct mtmips_clk rt2880_pherip_clks[] = { -+ { CLK_PERIPH("300100.timer", "bus") }, -+ { CLK_PERIPH("300120.watchdog", "bus") }, -+ { CLK_PERIPH("300500.uart", "bus") }, -+ { CLK_PERIPH("300900.i2c", "bus") }, -+ { CLK_PERIPH("300c00.uartlite", "bus") }, -+ { CLK_PERIPH("400000.ethernet", "bus") }, -+ { CLK_PERIPH("480000.wmac", "xtal") } -+}; -+ -+static struct mtmips_clk rt305x_pherip_clks[] = { -+ { CLK_PERIPH("10000100.timer", "bus") }, -+ { CLK_PERIPH("10000120.watchdog", "bus") }, -+ { CLK_PERIPH("10000500.uart", "bus") }, -+ { CLK_PERIPH("10000900.i2c", "bus") }, -+ { CLK_PERIPH("10000a00.i2s", "bus") }, -+ { CLK_PERIPH("10000b00.spi", "bus") }, -+ { CLK_PERIPH("10000b40.spi", "bus") }, -+ { CLK_PERIPH("10000c00.uartlite", "bus") }, -+ { CLK_PERIPH("10100000.ethernet", "bus") }, -+ { CLK_PERIPH("10180000.wmac", "xtal") } -+}; -+ -+static struct mtmips_clk rt5350_pherip_clks[] = { -+ { CLK_PERIPH("10000100.timer", "bus") }, -+ { CLK_PERIPH("10000120.watchdog", "bus") }, -+ { CLK_PERIPH("10000500.uart", "periph") }, -+ { CLK_PERIPH("10000900.i2c", "periph") }, -+ { CLK_PERIPH("10000a00.i2s", "periph") }, -+ { CLK_PERIPH("10000b00.spi", "bus") }, -+ { CLK_PERIPH("10000b40.spi", "bus") }, -+ { CLK_PERIPH("10000c00.uartlite", "periph") }, -+ { CLK_PERIPH("10100000.ethernet", "bus") }, -+ { CLK_PERIPH("10180000.wmac", "xtal") } -+}; -+ -+static struct mtmips_clk mt7620_pherip_clks[] = { -+ { CLK_PERIPH("10000100.timer", "periph") }, -+ { CLK_PERIPH("10000120.watchdog", "periph") }, -+ { CLK_PERIPH("10000500.uart", "periph") }, -+ { CLK_PERIPH("10000900.i2c", "periph") }, -+ { CLK_PERIPH("10000a00.i2s", "periph") }, -+ { CLK_PERIPH("10000b00.spi", "bus") }, -+ { CLK_PERIPH("10000b40.spi", "bus") }, -+ { CLK_PERIPH("10000c00.uartlite", "periph") }, -+ { CLK_PERIPH("10180000.wmac", "xtal") } -+}; -+ -+static struct mtmips_clk mt76x8_pherip_clks[] = { -+ { CLK_PERIPH("10000100.timer", "periph") }, -+ { CLK_PERIPH("10000120.watchdog", "periph") }, -+ { CLK_PERIPH("10000900.i2c", "periph") }, -+ { CLK_PERIPH("10000a00.i2s", "pcmi2s") }, -+ { CLK_PERIPH("10000b00.spi", "bus") }, -+ { CLK_PERIPH("10000b40.spi", "bus") }, -+ { CLK_PERIPH("10000c00.uart0", "periph") }, -+ { CLK_PERIPH("10000d00.uart1", "periph") }, -+ { CLK_PERIPH("10000e00.uart2", "periph") }, -+ { CLK_PERIPH("10300000.wmac", "xtal") } -+}; -+ -+static int mtmips_register_pherip_clocks(struct device_node *np, -+ struct clk_hw_onecell_data *clk_data, -+ struct mtmips_clk_priv *priv) -+{ -+ struct clk_hw **hws = clk_data->hws; -+ struct mtmips_clk *sclk; -+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed + -+ priv->data->num_clk_factor; -+ int ret, i; -+ -+ for (i = 0; i < priv->data->num_clk_periph; i++) { -+ int idx = idx_start + i; -+ -+ sclk = &priv->data->clk_periph[i]; -+ ret = of_clk_hw_register(np, &sclk->hw); -+ if (ret) { -+ pr_err("Couldn't register peripheral clock %d\n", idx); -+ goto err_clk_unreg; -+ } -+ -+ hws[idx] = &sclk->hw; -+ } -+ -+ return 0; -+ -+err_clk_unreg: -+ while (--i >= 0) { -+ sclk = &priv->data->clk_periph[i]; -+ clk_hw_unregister(&sclk->hw); -+ } -+ return ret; -+} -+ -+#define CLK_FIXED(_name, _parent, _rate) \ -+ { \ -+ .name = _name, \ -+ .parent = _parent, \ -+ .rate = _rate \ -+ } -+ -+static struct mtmips_clk_fixed rt305x_fixed_clocks[] = { -+ CLK_FIXED("xtal", NULL, 40000000) -+}; -+ -+static struct mtmips_clk_fixed rt3352_fixed_clocks[] = { -+ CLK_FIXED("periph", "xtal", 40000000) -+}; -+ -+static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = { -+ CLK_FIXED("pcmi2s", "xtal", 480000000), -+ CLK_FIXED("periph", "xtal", 40000000) -+}; -+ -+static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data, -+ struct mtmips_clk_priv *priv) -+{ -+ struct clk_hw **hws = clk_data->hws; -+ struct mtmips_clk_fixed *sclk; -+ size_t idx_start = priv->data->num_clk_base; -+ int ret, i; -+ -+ for (i = 0; i < priv->data->num_clk_fixed; i++) { -+ int idx = idx_start + i; -+ -+ sclk = &priv->data->clk_fixed[i]; -+ sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name, -+ sclk->parent, 0, -+ sclk->rate); -+ if (IS_ERR(sclk->hw)) { -+ pr_err("Couldn't register fixed clock %d\n", idx); -+ goto err_clk_unreg; -+ } -+ -+ hws[idx] = sclk->hw; -+ } -+ -+ return 0; -+ -+err_clk_unreg: -+ while (--i >= 0) { -+ sclk = &priv->data->clk_fixed[i]; -+ clk_hw_unregister_fixed_rate(sclk->hw); -+ } -+ return ret; -+} -+ -+#define CLK_FACTOR(_name, _parent, _mult, _div) \ -+ { \ -+ .name = _name, \ -+ .parent = _parent, \ -+ .mult = _mult, \ -+ .div = _div, \ -+ .flags = CLK_SET_RATE_PARENT \ -+ } -+ -+static struct mtmips_clk_factor rt2880_factor_clocks[] = { -+ CLK_FACTOR("bus", "cpu", 1, 2) -+}; -+ -+static struct mtmips_clk_factor rt305x_factor_clocks[] = { -+ CLK_FACTOR("bus", "cpu", 1, 3) -+}; -+ -+static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data, -+ struct mtmips_clk_priv *priv) -+{ -+ struct clk_hw **hws = clk_data->hws; -+ struct mtmips_clk_factor *sclk; -+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed; -+ int ret, i; -+ -+ for (i = 0; i < priv->data->num_clk_factor; i++) { -+ int idx = idx_start + i; -+ -+ sclk = &priv->data->clk_factor[i]; -+ sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name, -+ sclk->parent, sclk->flags, -+ sclk->mult, sclk->div); -+ if (IS_ERR(sclk->hw)) { -+ pr_err("Couldn't register factor clock %d\n", idx); -+ goto err_clk_unreg; -+ } -+ -+ hws[idx] = sclk->hw; -+ } -+ -+ return 0; -+ -+err_clk_unreg: -+ while (--i >= 0) { -+ sclk = &priv->data->clk_factor[i]; -+ clk_hw_unregister_fixed_factor(sclk->hw); -+ } -+ return ret; -+} -+ -+static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw) -+{ -+ return container_of(hw, struct mtmips_clk, hw); -+} -+ -+static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 val; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val); -+ if (!(val & RT5350_CLKCFG0_XTAL_SEL)) -+ return 20000000; -+ -+ return 40000000; -+} -+ -+static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK; -+ -+ switch (t) { -+ case RT5350_SYSCFG0_CPUCLK_360: -+ return 360000000; -+ case RT5350_SYSCFG0_CPUCLK_320: -+ return 320000000; -+ case RT5350_SYSCFG0_CPUCLK_300: -+ return 300000000; -+ default: -+ BUG(); -+ } -+} -+ -+static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ if (parent_rate == 320000000) -+ return parent_rate / 4; -+ -+ return parent_rate / 3; -+} -+ -+static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK; -+ -+ switch (t) { -+ case RT3352_SYSCFG0_CPUCLK_LOW: -+ return 384000000; -+ case RT3352_SYSCFG0_CPUCLK_HIGH: -+ return 400000000; -+ default: -+ BUG(); -+ } -+} -+ -+static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK; -+ -+ switch (t) { -+ case RT305X_SYSCFG_CPUCLK_LOW: -+ return 320000000; -+ case RT305X_SYSCFG_CPUCLK_HIGH: -+ return 384000000; -+ default: -+ BUG(); -+ } -+} -+ -+static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK; -+ -+ switch (t) { -+ case RT3883_SYSCFG0_CPUCLK_250: -+ return 250000000; -+ case RT3883_SYSCFG0_CPUCLK_384: -+ return 384000000; -+ case RT3883_SYSCFG0_CPUCLK_480: -+ return 480000000; -+ case RT3883_SYSCFG0_CPUCLK_500: -+ return 500000000; -+ default: -+ BUG(); -+ } -+} -+ -+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 ddr2; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2; -+ -+ switch (parent_rate) { -+ case 250000000: -+ return (ddr2) ? 125000000 : 83000000; -+ case 384000000: -+ return (ddr2) ? 128000000 : 96000000; -+ case 480000000: -+ return (ddr2) ? 160000000 : 120000000; -+ case 500000000: -+ return (ddr2) ? 166000000 : 125000000; -+ default: -+ WARN_ON_ONCE(parent_rate == 0); -+ return parent_rate / 4; -+ } -+} -+ -+static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK; -+ -+ switch (t) { -+ case RT2880_CONFIG_CPUCLK_250: -+ return 250000000; -+ case RT2880_CONFIG_CPUCLK_266: -+ return 266000000; -+ case RT2880_CONFIG_CPUCLK_280: -+ return 280000000; -+ case RT2880_CONFIG_CPUCLK_300: -+ return 300000000; -+ default: -+ BUG(); -+ } -+} -+ -+static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) -+{ -+ u64 t; -+ -+ t = ref_rate; -+ t *= mul; -+ t = div_u64(t, div); -+ -+ return t; -+} -+ -+static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ static const u32 clk_divider[] = { 2, 3, 4, 8 }; -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ unsigned long cpu_pll; -+ u32 t; -+ u32 mul; -+ u32 div; -+ -+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t); -+ if (t & CPLL_CFG0_BYPASS_REF_CLK) { -+ cpu_pll = parent_rate; -+ } else if ((t & CPLL_CFG0_SW_CFG) == 0) { -+ cpu_pll = 600000000; -+ } else { -+ mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & -+ CPLL_CFG0_PLL_MULT_RATIO_MASK; -+ mul += 24; -+ if (t & CPLL_CFG0_LC_CURFCK) -+ mul *= 2; -+ -+ div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & -+ CPLL_CFG0_PLL_DIV_RATIO_MASK; -+ -+ WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider)); -+ -+ cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]); -+ } -+ -+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t); -+ if (t & CPLL_CFG1_CPU_AUX1) -+ return parent_rate; -+ -+ if (t & CPLL_CFG1_CPU_AUX0) -+ return 480000000; -+ -+ return cpu_pll; -+} -+ -+static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ u32 mul; -+ u32 div; -+ -+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); -+ mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; -+ div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & -+ CPU_SYS_CLKCFG_CPU_FDIV_MASK; -+ -+ return mt7620_calc_rate(parent_rate, mul, div); -+} -+ -+static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ static const u32 ocp_dividers[16] = { -+ [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, -+ [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, -+ [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, -+ [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, -+ [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, -+ }; -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ u32 ocp_ratio; -+ u32 div; -+ -+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); -+ ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & -+ CPU_SYS_CLKCFG_OCP_RATIO_MASK; -+ -+ if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers))) -+ return parent_rate; -+ -+ div = ocp_dividers[ocp_ratio]; -+ -+ if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) -+ return parent_rate; -+ -+ return parent_rate / div; -+} -+ -+static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_CLKCFG0, &t); -+ if (t & CLKCFG0_PERI_CLK_SEL) -+ return parent_rate; -+ -+ return 40000000; -+} -+ -+static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct mtmips_clk *clk = to_mtmips_clk(hw); -+ struct regmap *sysc = clk->priv->sysc; -+ u32 t; -+ -+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); -+ if (t & MT7620_XTAL_FREQ_SEL) -+ return 40000000; -+ -+ return 20000000; -+} -+ -+static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw, -+ unsigned long xtal_clk) -+{ -+ if (xtal_clk == 40000000) -+ return 580000000; -+ -+ return 575000000; -+} -+ -+#define CLK_BASE(_name, _parent, _recalc) { \ -+ .init = &(const struct clk_init_data) { \ -+ .name = _name, \ -+ .ops = &(const struct clk_ops) { \ -+ .recalc_rate = _recalc, \ -+ }, \ -+ .parent_data = &(const struct clk_parent_data) { \ -+ .name = _parent, \ -+ .fw_name = _parent \ -+ }, \ -+ .num_parents = _parent ? 1 : 0 \ -+ }, \ -+} -+ -+static struct mtmips_clk rt2880_clks_base[] = { -+ { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) } -+}; -+ -+static struct mtmips_clk rt305x_clks_base[] = { -+ { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) } -+}; -+ -+static struct mtmips_clk rt3352_clks_base[] = { -+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, -+ { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) } -+}; -+ -+static struct mtmips_clk rt3883_clks_base[] = { -+ { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) }, -+ { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) } -+}; -+ -+static struct mtmips_clk rt5350_clks_base[] = { -+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, -+ { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) }, -+ { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) } -+}; -+ -+static struct mtmips_clk mt7620_clks_base[] = { -+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, -+ { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) }, -+ { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) }, -+ { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) }, -+ { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) } -+}; -+ -+static struct mtmips_clk mt76x8_clks_base[] = { -+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, -+ { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) } -+}; -+ -+static int mtmips_register_clocks(struct device_node *np, -+ struct clk_hw_onecell_data *clk_data, -+ struct mtmips_clk_priv *priv) -+{ -+ struct clk_hw **hws = clk_data->hws; -+ struct mtmips_clk *sclk; -+ int ret, i; -+ -+ for (i = 0; i < priv->data->num_clk_base; i++) { -+ sclk = &priv->data->clk_base[i]; -+ sclk->priv = priv; -+ ret = of_clk_hw_register(np, &sclk->hw); -+ if (ret) { -+ pr_err("Couldn't register top clock %i\n", i); -+ goto err_clk_unreg; -+ } -+ -+ hws[i] = &sclk->hw; -+ } -+ -+ return 0; -+ -+err_clk_unreg: -+ while (--i >= 0) { -+ sclk = &priv->data->clk_base[i]; -+ clk_hw_unregister(&sclk->hw); -+ } -+ return ret; -+} -+ -+static const struct mtmips_clk_data rt2880_clk_data = { -+ .clk_base = rt2880_clks_base, -+ .num_clk_base = ARRAY_SIZE(rt2880_clks_base), -+ .clk_fixed = rt305x_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), -+ .clk_factor = rt2880_factor_clocks, -+ .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks), -+ .clk_periph = rt2880_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data rt305x_clk_data = { -+ .clk_base = rt305x_clks_base, -+ .num_clk_base = ARRAY_SIZE(rt305x_clks_base), -+ .clk_fixed = rt305x_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), -+ .clk_factor = rt305x_factor_clocks, -+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), -+ .clk_periph = rt305x_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data rt3352_clk_data = { -+ .clk_base = rt3352_clks_base, -+ .num_clk_base = ARRAY_SIZE(rt3352_clks_base), -+ .clk_fixed = rt3352_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), -+ .clk_factor = rt305x_factor_clocks, -+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), -+ .clk_periph = rt5350_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data rt3883_clk_data = { -+ .clk_base = rt3883_clks_base, -+ .num_clk_base = ARRAY_SIZE(rt3883_clks_base), -+ .clk_fixed = rt305x_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), -+ .clk_factor = NULL, -+ .num_clk_factor = 0, -+ .clk_periph = rt5350_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data rt5350_clk_data = { -+ .clk_base = rt5350_clks_base, -+ .num_clk_base = ARRAY_SIZE(rt5350_clks_base), -+ .clk_fixed = rt3352_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), -+ .clk_factor = NULL, -+ .num_clk_factor = 0, -+ .clk_periph = rt5350_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data mt7620_clk_data = { -+ .clk_base = mt7620_clks_base, -+ .num_clk_base = ARRAY_SIZE(mt7620_clks_base), -+ .clk_fixed = NULL, -+ .num_clk_fixed = 0, -+ .clk_factor = NULL, -+ .num_clk_factor = 0, -+ .clk_periph = mt7620_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks), -+}; -+ -+static const struct mtmips_clk_data mt76x8_clk_data = { -+ .clk_base = mt76x8_clks_base, -+ .num_clk_base = ARRAY_SIZE(mt76x8_clks_base), -+ .clk_fixed = mt76x8_fixed_clocks, -+ .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks), -+ .clk_factor = rt305x_factor_clocks, -+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), -+ .clk_periph = mt76x8_pherip_clks, -+ .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks), -+}; -+ -+static const struct of_device_id mtmips_of_match[] = { -+ { -+ .compatible = "ralink,rt2880-sysc", -+ .data = &rt2880_clk_data, -+ }, -+ { -+ .compatible = "ralink,rt3050-sysc", -+ .data = &rt305x_clk_data, -+ }, -+ { -+ .compatible = "ralink,rt3052-sysc", -+ .data = &rt305x_clk_data, -+ }, -+ { -+ .compatible = "ralink,rt3352-sysc", -+ .data = &rt3352_clk_data, -+ }, -+ { -+ .compatible = "ralink,rt3883-sysc", -+ .data = &rt3883_clk_data, -+ }, -+ { -+ .compatible = "ralink,rt5350-sysc", -+ .data = &rt5350_clk_data, -+ }, -+ { -+ .compatible = "ralink,mt7620-sysc", -+ .data = &mt7620_clk_data, -+ }, -+ { -+ .compatible = "ralink,mt7628-sysc", -+ .data = &mt76x8_clk_data, -+ }, -+ { -+ .compatible = "ralink,mt7688-sysc", -+ .data = &mt76x8_clk_data, -+ }, -+ {} -+}; -+ -+static void __init mtmips_clk_regs_init(struct device_node *node, -+ struct mtmips_clk_priv *priv) -+{ -+ u32 t; -+ -+ if (!of_device_is_compatible(node, "ralink,mt7620-sysc")) -+ return; -+ -+ /* -+ * When the CPU goes into sleep mode, the BUS -+ * clock will be too low for USB to function properly. -+ * Adjust the busses fractional divider to fix this -+ */ -+ regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); -+ t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); -+ t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; -+ regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t); -+} -+ -+static void __init mtmips_clk_init(struct device_node *node) -+{ -+ const struct of_device_id *match; -+ const struct mtmips_clk_data *data; -+ struct mtmips_clk_priv *priv; -+ struct clk_hw_onecell_data *clk_data; -+ int ret, i, count; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return; -+ -+ priv->sysc = syscon_node_to_regmap(node); -+ if (IS_ERR(priv->sysc)) { -+ pr_err("Could not get sysc syscon regmap\n"); -+ goto free_clk_priv; -+ } -+ -+ mtmips_clk_regs_init(node, priv); -+ -+ match = of_match_node(mtmips_of_match, node); -+ if (WARN_ON(!match)) -+ return; -+ -+ data = match->data; -+ priv->data = data; -+ count = priv->data->num_clk_base + priv->data->num_clk_fixed + -+ priv->data->num_clk_factor + priv->data->num_clk_periph; -+ clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL); -+ if (!clk_data) -+ goto free_clk_priv; -+ -+ ret = mtmips_register_clocks(node, clk_data, priv); -+ if (ret) { -+ pr_err("Couldn't register top clocks\n"); -+ goto free_clk_data; -+ } -+ -+ ret = mtmips_register_fixed_clocks(clk_data, priv); -+ if (ret) { -+ pr_err("Couldn't register fixed clocks\n"); -+ goto unreg_clk_top; -+ } -+ -+ ret = mtmips_register_factor_clocks(clk_data, priv); -+ if (ret) { -+ pr_err("Couldn't register factor clocks\n"); -+ goto unreg_clk_fixed; -+ } -+ -+ ret = mtmips_register_pherip_clocks(node, clk_data, priv); -+ if (ret) { -+ pr_err("Couldn't register peripheral clocks\n"); -+ goto unreg_clk_factor; -+ } -+ -+ clk_data->num = count; -+ -+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ if (ret) { -+ pr_err("Couldn't add clk hw provider\n"); -+ goto unreg_clk_periph; -+ } -+ -+ return; -+ -+unreg_clk_periph: -+ for (i = 0; i < priv->data->num_clk_periph; i++) { -+ struct mtmips_clk *sclk = &priv->data->clk_periph[i]; -+ -+ clk_hw_unregister(&sclk->hw); -+ } -+ -+unreg_clk_factor: -+ for (i = 0; i < priv->data->num_clk_factor; i++) { -+ struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i]; -+ -+ clk_hw_unregister_fixed_factor(sclk->hw); -+ } -+ -+unreg_clk_fixed: -+ for (i = 0; i < priv->data->num_clk_fixed; i++) { -+ struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i]; -+ -+ clk_hw_unregister_fixed_rate(sclk->hw); -+ } -+ -+unreg_clk_top: -+ for (i = 0; i < priv->data->num_clk_base; i++) { -+ struct mtmips_clk *sclk = &priv->data->clk_base[i]; -+ -+ clk_hw_unregister(&sclk->hw); -+ } -+ -+free_clk_data: -+ kfree(clk_data); -+ -+free_clk_priv: -+ kfree(priv); -+} -+CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init); -+CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init); -+ -+struct mtmips_rst { -+ struct reset_controller_dev rcdev; -+ struct regmap *sysc; -+}; -+ -+static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev) -+{ -+ return container_of(dev, struct mtmips_rst, rcdev); -+} -+ -+static int mtmips_assert_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ struct mtmips_rst *data = to_mtmips_rst(rcdev); -+ struct regmap *sysc = data->sysc; -+ -+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); -+} -+ -+static int mtmips_deassert_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ struct mtmips_rst *data = to_mtmips_rst(rcdev); -+ struct regmap *sysc = data->sysc; -+ -+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0); -+} -+ -+static int mtmips_reset_device(struct reset_controller_dev *rcdev, -+ unsigned long id) -+{ -+ int ret; -+ -+ ret = mtmips_assert_device(rcdev, id); -+ if (ret < 0) -+ return ret; -+ -+ return mtmips_deassert_device(rcdev, id); -+} -+ -+static int mtmips_rst_xlate(struct reset_controller_dev *rcdev, -+ const struct of_phandle_args *reset_spec) -+{ -+ unsigned long id = reset_spec->args[0]; -+ -+ if (id == 0 || id >= rcdev->nr_resets) -+ return -EINVAL; -+ -+ return id; -+} -+ -+static const struct reset_control_ops reset_ops = { -+ .reset = mtmips_reset_device, -+ .assert = mtmips_assert_device, -+ .deassert = mtmips_deassert_device -+}; -+ -+static int mtmips_reset_init(struct device *dev, struct regmap *sysc) -+{ -+ struct mtmips_rst *rst_data; -+ -+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); -+ if (!rst_data) -+ return -ENOMEM; -+ -+ rst_data->sysc = sysc; -+ rst_data->rcdev.ops = &reset_ops; -+ rst_data->rcdev.owner = THIS_MODULE; -+ rst_data->rcdev.nr_resets = 32; -+ rst_data->rcdev.of_reset_n_cells = 1; -+ rst_data->rcdev.of_xlate = mtmips_rst_xlate; -+ rst_data->rcdev.of_node = dev_of_node(dev); -+ -+ return devm_reset_controller_register(dev, &rst_data->rcdev); -+} -+ -+static int mtmips_clk_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device *dev = &pdev->dev; -+ struct mtmips_clk_priv *priv; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->sysc = syscon_node_to_regmap(np); -+ if (IS_ERR(priv->sysc)) -+ return dev_err_probe(dev, PTR_ERR(priv->sysc), -+ "Could not get sysc syscon regmap\n"); -+ -+ ret = mtmips_reset_init(dev, priv->sysc); -+ if (ret) -+ return dev_err_probe(dev, ret, "Could not init reset controller\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id mtmips_clk_of_match[] = { -+ { .compatible = "ralink,rt2880-reset" }, -+ { .compatible = "ralink,rt2880-sysc" }, -+ { .compatible = "ralink,rt3050-sysc" }, -+ { .compatible = "ralink,rt3052-sysc" }, -+ { .compatible = "ralink,rt3352-sysc" }, -+ { .compatible = "ralink,rt3883-sysc" }, -+ { .compatible = "ralink,rt5350-sysc" }, -+ { .compatible = "ralink,mt7620-sysc" }, -+ { .compatible = "ralink,mt7628-sysc" }, -+ { .compatible = "ralink,mt7688-sysc" }, -+ {} -+}; -+ -+static struct platform_driver mtmips_clk_driver = { -+ .probe = mtmips_clk_probe, -+ .driver = { -+ .name = "mtmips-clk", -+ .of_match_table = mtmips_clk_of_match, -+ }, -+}; -+ -+static int __init mtmips_clk_reset_init(void) -+{ -+ return platform_driver_register(&mtmips_clk_driver); -+} -+arch_initcall(mtmips_clk_reset_init); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-03-mips-ralink-rt288x-remove-clock-related-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-03-mips-ralink-rt288x-remove-clock-related-code.patch deleted file mode 100644 index df4208b23d..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-03-mips-ralink-rt288x-remove-clock-related-code.patch +++ /dev/null @@ -1,81 +0,0 @@ -From ffcdf47379eae86dc8f8f02c62994dacf2c9038e Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:35 +0200 -Subject: [PATCH 3/9] mips: ralink: rt288x: remove clock related code - -A properly clock driver for ralink SoCs has been added. Hence there is no -need to have clock related code in 'arch/mips/ralink' folder anymore. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/include/asm/mach-ralink/rt288x.h | 10 ---------- - arch/mips/ralink/rt288x.c | 31 ------------------------------ - 2 files changed, 41 deletions(-) - ---- a/arch/mips/include/asm/mach-ralink/rt288x.h -+++ b/arch/mips/include/asm/mach-ralink/rt288x.h -@@ -17,7 +17,6 @@ - #define SYSC_REG_CHIP_NAME1 0x04 - #define SYSC_REG_CHIP_ID 0x0c - #define SYSC_REG_SYSTEM_CONFIG 0x10 --#define SYSC_REG_CLKCFG 0x30 - - #define RT2880_CHIP_NAME0 0x38325452 - #define RT2880_CHIP_NAME1 0x20203038 -@@ -26,15 +25,6 @@ - #define CHIP_ID_ID_SHIFT 8 - #define CHIP_ID_REV_MASK 0xff - --#define SYSTEM_CONFIG_CPUCLK_SHIFT 20 --#define SYSTEM_CONFIG_CPUCLK_MASK 0x3 --#define SYSTEM_CONFIG_CPUCLK_250 0x0 --#define SYSTEM_CONFIG_CPUCLK_266 0x1 --#define SYSTEM_CONFIG_CPUCLK_280 0x2 --#define SYSTEM_CONFIG_CPUCLK_300 0x3 -- --#define CLKCFG_SRAM_CS_N_WDT BIT(9) -- - #define RT2880_SDRAM_BASE 0x08000000 - #define RT2880_MEM_SIZE_MIN 2 - #define RT2880_MEM_SIZE_MAX 128 ---- a/arch/mips/ralink/rt288x.c -+++ b/arch/mips/ralink/rt288x.c -@@ -17,37 +17,6 @@ - - #include "common.h" - --void __init ralink_clk_init(void) --{ -- unsigned long cpu_rate, wmac_rate = 40000000; -- u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); -- t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); -- -- switch (t) { -- case SYSTEM_CONFIG_CPUCLK_250: -- cpu_rate = 250000000; -- break; -- case SYSTEM_CONFIG_CPUCLK_266: -- cpu_rate = 266666667; -- break; -- case SYSTEM_CONFIG_CPUCLK_280: -- cpu_rate = 280000000; -- break; -- case SYSTEM_CONFIG_CPUCLK_300: -- cpu_rate = 300000000; -- break; -- } -- -- ralink_clk_add("cpu", cpu_rate); -- ralink_clk_add("300100.timer", cpu_rate / 2); -- ralink_clk_add("300120.watchdog", cpu_rate / 2); -- ralink_clk_add("300500.uart", cpu_rate / 2); -- ralink_clk_add("300900.i2c", cpu_rate / 2); -- ralink_clk_add("300c00.uartlite", cpu_rate / 2); -- ralink_clk_add("400000.ethernet", cpu_rate / 2); -- ralink_clk_add("480000.wmac", wmac_rate); --} -- - void __init ralink_of_remap(void) - { - rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-04-mips-ralink-rt305x-remove-clock-related-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-04-mips-ralink-rt305x-remove-clock-related-code.patch deleted file mode 100644 index 12b4623b73..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-04-mips-ralink-rt305x-remove-clock-related-code.patch +++ /dev/null @@ -1,145 +0,0 @@ -From daf73c70f69386fb15960526772ef584a4efcaf2 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:36 +0200 -Subject: [PATCH 4/9] mips: ralink: rt305x: remove clock related code - -A properly clock driver for ralink SoCs has been added. Hence there is no -need to have clock related code in 'arch/mips/ralink' folder anymore. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/include/asm/mach-ralink/rt305x.h | 21 -------- - arch/mips/ralink/rt305x.c | 78 ------------------------------ - 2 files changed, 99 deletions(-) - ---- a/arch/mips/include/asm/mach-ralink/rt305x.h -+++ b/arch/mips/include/asm/mach-ralink/rt305x.h -@@ -66,26 +66,9 @@ static inline int soc_is_rt5350(void) - #define CHIP_ID_ID_SHIFT 8 - #define CHIP_ID_REV_MASK 0xff - --#define RT305X_SYSCFG_CPUCLK_SHIFT 18 --#define RT305X_SYSCFG_CPUCLK_MASK 0x1 --#define RT305X_SYSCFG_CPUCLK_LOW 0x0 --#define RT305X_SYSCFG_CPUCLK_HIGH 0x1 -- - #define RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT 2 --#define RT305X_SYSCFG_CPUCLK_MASK 0x1 - #define RT305X_SYSCFG_SRAM_CS0_MODE_WDT 0x1 - --#define RT3352_SYSCFG0_CPUCLK_SHIFT 8 --#define RT3352_SYSCFG0_CPUCLK_MASK 0x1 --#define RT3352_SYSCFG0_CPUCLK_LOW 0x0 --#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 -- --#define RT5350_SYSCFG0_CPUCLK_SHIFT 8 --#define RT5350_SYSCFG0_CPUCLK_MASK 0x3 --#define RT5350_SYSCFG0_CPUCLK_360 0x0 --#define RT5350_SYSCFG0_CPUCLK_320 0x2 --#define RT5350_SYSCFG0_CPUCLK_300 0x3 -- - #define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12 - #define RT5350_SYSCFG0_DRAM_SIZE_MASK 7 - #define RT5350_SYSCFG0_DRAM_SIZE_2M 0 -@@ -116,13 +99,9 @@ static inline int soc_is_rt5350(void) - - #define RT3352_SYSC_REG_SYSCFG0 0x010 - #define RT3352_SYSC_REG_SYSCFG1 0x014 --#define RT3352_SYSC_REG_CLKCFG1 0x030 - #define RT3352_SYSC_REG_RSTCTRL 0x034 - #define RT3352_SYSC_REG_USB_PS 0x05c - --#define RT3352_CLKCFG0_XTAL_SEL BIT(20) --#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18) --#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20) - #define RT3352_RSTCTRL_UHST BIT(22) - #define RT3352_RSTCTRL_UDEV BIT(25) - #define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -53,84 +53,6 @@ static unsigned long rt5350_get_mem_size - return ret; - } - --void __init ralink_clk_init(void) --{ -- unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; -- unsigned long wmac_rate = 40000000; -- -- u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); -- -- if (soc_is_rt305x() || soc_is_rt3350()) { -- t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & -- RT305X_SYSCFG_CPUCLK_MASK; -- switch (t) { -- case RT305X_SYSCFG_CPUCLK_LOW: -- cpu_rate = 320000000; -- break; -- case RT305X_SYSCFG_CPUCLK_HIGH: -- cpu_rate = 384000000; -- break; -- } -- sys_rate = uart_rate = wdt_rate = cpu_rate / 3; -- } else if (soc_is_rt3352()) { -- t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & -- RT3352_SYSCFG0_CPUCLK_MASK; -- switch (t) { -- case RT3352_SYSCFG0_CPUCLK_LOW: -- cpu_rate = 384000000; -- break; -- case RT3352_SYSCFG0_CPUCLK_HIGH: -- cpu_rate = 400000000; -- break; -- } -- sys_rate = wdt_rate = cpu_rate / 3; -- uart_rate = 40000000; -- } else if (soc_is_rt5350()) { -- t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & -- RT5350_SYSCFG0_CPUCLK_MASK; -- switch (t) { -- case RT5350_SYSCFG0_CPUCLK_360: -- cpu_rate = 360000000; -- sys_rate = cpu_rate / 3; -- break; -- case RT5350_SYSCFG0_CPUCLK_320: -- cpu_rate = 320000000; -- sys_rate = cpu_rate / 4; -- break; -- case RT5350_SYSCFG0_CPUCLK_300: -- cpu_rate = 300000000; -- sys_rate = cpu_rate / 3; -- break; -- default: -- BUG(); -- } -- uart_rate = 40000000; -- wdt_rate = sys_rate; -- } else { -- BUG(); -- } -- -- if (soc_is_rt3352() || soc_is_rt5350()) { -- u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0); -- -- if (!(val & RT3352_CLKCFG0_XTAL_SEL)) -- wmac_rate = 20000000; -- } -- -- ralink_clk_add("cpu", cpu_rate); -- ralink_clk_add("sys", sys_rate); -- ralink_clk_add("10000900.i2c", uart_rate); -- ralink_clk_add("10000a00.i2s", uart_rate); -- ralink_clk_add("10000b00.spi", sys_rate); -- ralink_clk_add("10000b40.spi", sys_rate); -- ralink_clk_add("10000100.timer", wdt_rate); -- ralink_clk_add("10000120.watchdog", wdt_rate); -- ralink_clk_add("10000500.uart", uart_rate); -- ralink_clk_add("10000c00.uartlite", uart_rate); -- ralink_clk_add("10100000.ethernet", sys_rate); -- ralink_clk_add("10180000.wmac", wmac_rate); --} -- - void __init ralink_of_remap(void) - { - rt_sysc_membase = plat_of_remap_node("ralink,rt3050-sysc"); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-05-mips-ralink-rt3883-remove-clock-related-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-05-mips-ralink-rt3883-remove-clock-related-code.patch deleted file mode 100644 index c13c4215f3..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-05-mips-ralink-rt3883-remove-clock-related-code.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 7cd1bb48885449a9323c7ff0f10012925e93b4e1 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:37 +0200 -Subject: [PATCH 5/9] mips: ralink: rt3883: remove clock related code - -A properly clock driver for ralink SoCs has been added. Hence there is no -need to have clock related code in 'arch/mips/ralink' folder anymore. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/include/asm/mach-ralink/rt3883.h | 8 ------ - arch/mips/ralink/rt3883.c | 44 ------------------------------ - 2 files changed, 52 deletions(-) - ---- a/arch/mips/include/asm/mach-ralink/rt3883.h -+++ b/arch/mips/include/asm/mach-ralink/rt3883.h -@@ -90,14 +90,6 @@ - #define RT3883_REVID_VER_ID_SHIFT 8 - #define RT3883_REVID_ECO_ID_MASK 0x0f - --#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) --#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 --#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 --#define RT3883_SYSCFG0_CPUCLK_250 0x0 --#define RT3883_SYSCFG0_CPUCLK_384 0x1 --#define RT3883_SYSCFG0_CPUCLK_480 0x2 --#define RT3883_SYSCFG0_CPUCLK_500 0x3 -- - #define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10) - #define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8) - #define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7) ---- a/arch/mips/ralink/rt3883.c -+++ b/arch/mips/ralink/rt3883.c -@@ -17,50 +17,6 @@ - - #include "common.h" - --void __init ralink_clk_init(void) --{ -- unsigned long cpu_rate, sys_rate; -- u32 syscfg0; -- u32 clksel; -- u32 ddr2; -- -- syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0); -- clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & -- RT3883_SYSCFG0_CPUCLK_MASK); -- ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; -- -- switch (clksel) { -- case RT3883_SYSCFG0_CPUCLK_250: -- cpu_rate = 250000000; -- sys_rate = (ddr2) ? 125000000 : 83000000; -- break; -- case RT3883_SYSCFG0_CPUCLK_384: -- cpu_rate = 384000000; -- sys_rate = (ddr2) ? 128000000 : 96000000; -- break; -- case RT3883_SYSCFG0_CPUCLK_480: -- cpu_rate = 480000000; -- sys_rate = (ddr2) ? 160000000 : 120000000; -- break; -- case RT3883_SYSCFG0_CPUCLK_500: -- cpu_rate = 500000000; -- sys_rate = (ddr2) ? 166000000 : 125000000; -- break; -- } -- -- ralink_clk_add("cpu", cpu_rate); -- ralink_clk_add("10000100.timer", sys_rate); -- ralink_clk_add("10000120.watchdog", sys_rate); -- ralink_clk_add("10000500.uart", 40000000); -- ralink_clk_add("10000900.i2c", 40000000); -- ralink_clk_add("10000a00.i2s", 40000000); -- ralink_clk_add("10000b00.spi", sys_rate); -- ralink_clk_add("10000b40.spi", sys_rate); -- ralink_clk_add("10000c00.uartlite", 40000000); -- ralink_clk_add("10100000.ethernet", sys_rate); -- ralink_clk_add("10180000.wmac", 40000000); --} -- - void __init ralink_of_remap(void) - { - rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-06-mips-ralink-mt7620-remove-clock-related-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-06-mips-ralink-mt7620-remove-clock-related-code.patch deleted file mode 100644 index 7b83cf54b4..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-06-mips-ralink-mt7620-remove-clock-related-code.patch +++ /dev/null @@ -1,327 +0,0 @@ -From 04b153abdfcbaba70ceef5a846067d4447fd0078 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:38 +0200 -Subject: [PATCH 6/9] mips: ralink: mt7620: remove clock related code - -A proper clock driver for ralink SoCs has been added. Hence there is no -need to have clock related code in 'arch/mips/ralink' folder anymore. -Since this is the last clock related code removal, remove also remaining -prototypes in 'common.h' header file. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/include/asm/mach-ralink/mt7620.h | 35 ----- - arch/mips/ralink/common.h | 3 - - arch/mips/ralink/mt7620.c | 226 ----------------------------- - 3 files changed, 264 deletions(-) - ---- a/arch/mips/include/asm/mach-ralink/mt7620.h -+++ b/arch/mips/include/asm/mach-ralink/mt7620.h -@@ -19,52 +19,17 @@ - #define SYSC_REG_CHIP_REV 0x0c - #define SYSC_REG_SYSTEM_CONFIG0 0x10 - #define SYSC_REG_SYSTEM_CONFIG1 0x14 --#define SYSC_REG_CLKCFG0 0x2c --#define SYSC_REG_CPU_SYS_CLKCFG 0x3c --#define SYSC_REG_CPLL_CONFIG0 0x54 --#define SYSC_REG_CPLL_CONFIG1 0x58 - - #define MT7620_CHIP_NAME0 0x3637544d - #define MT7620_CHIP_NAME1 0x20203032 - #define MT7628_CHIP_NAME1 0x20203832 - --#define SYSCFG0_XTAL_FREQ_SEL BIT(6) -- - #define CHIP_REV_PKG_MASK 0x1 - #define CHIP_REV_PKG_SHIFT 16 - #define CHIP_REV_VER_MASK 0xf - #define CHIP_REV_VER_SHIFT 8 - #define CHIP_REV_ECO_MASK 0xf - --#define CLKCFG0_PERI_CLK_SEL BIT(4) -- --#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 --#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf --#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ --#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ --#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ --#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ --#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ --#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ --#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ --#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ --#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ --#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 --#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f --#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 --#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f -- --#define CPLL_CFG0_SW_CFG BIT(31) --#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 --#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 --#define CPLL_CFG0_LC_CURFCK BIT(15) --#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) --#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 --#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 -- --#define CPLL_CFG1_CPU_AUX1 BIT(25) --#define CPLL_CFG1_CPU_AUX0 BIT(24) -- - #define SYSCFG0_DRAM_TYPE_MASK 0x3 - #define SYSCFG0_DRAM_TYPE_SHIFT 4 - #define SYSCFG0_DRAM_TYPE_SDRAM 0 ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -23,9 +23,6 @@ extern struct ralink_soc_info soc_info; - - extern void ralink_of_remap(void); - --extern void ralink_clk_init(void); --extern void ralink_clk_add(const char *dev, unsigned long rate); -- - extern void ralink_rst_init(void); - - extern void __init prom_soc_init(struct ralink_soc_info *soc_info); ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -34,12 +34,6 @@ - #define PMU1_CFG 0x8C - #define DIG_SW_SEL BIT(25) - --/* clock scaling */ --#define CLKCFG_FDIV_MASK 0x1f00 --#define CLKCFG_FDIV_USB_VAL 0x0300 --#define CLKCFG_FFRAC_MASK 0x001f --#define CLKCFG_FFRAC_USB_VAL 0x0003 -- - /* EFUSE bits */ - #define EFUSE_MT7688 0x100000 - -@@ -49,226 +43,6 @@ - /* does the board have sdram or ddram */ - static int dram_type; - --static __init u32 --mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) --{ -- u64 t; -- -- t = ref_rate; -- t *= mul; -- do_div(t, div); -- -- return t; --} -- --#define MHZ(x) ((x) * 1000 * 1000) -- --static __init unsigned long --mt7620_get_xtal_rate(void) --{ -- u32 reg; -- -- reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); -- if (reg & SYSCFG0_XTAL_FREQ_SEL) -- return MHZ(40); -- -- return MHZ(20); --} -- --static __init unsigned long --mt7620_get_periph_rate(unsigned long xtal_rate) --{ -- u32 reg; -- -- reg = rt_sysc_r32(SYSC_REG_CLKCFG0); -- if (reg & CLKCFG0_PERI_CLK_SEL) -- return xtal_rate; -- -- return MHZ(40); --} -- --static const u32 mt7620_clk_divider[] __initconst = { 2, 3, 4, 8 }; -- --static __init unsigned long --mt7620_get_cpu_pll_rate(unsigned long xtal_rate) --{ -- u32 reg; -- u32 mul; -- u32 div; -- -- reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); -- if (reg & CPLL_CFG0_BYPASS_REF_CLK) -- return xtal_rate; -- -- if ((reg & CPLL_CFG0_SW_CFG) == 0) -- return MHZ(600); -- -- mul = (reg >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & -- CPLL_CFG0_PLL_MULT_RATIO_MASK; -- mul += 24; -- if (reg & CPLL_CFG0_LC_CURFCK) -- mul *= 2; -- -- div = (reg >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & -- CPLL_CFG0_PLL_DIV_RATIO_MASK; -- -- WARN_ON(div >= ARRAY_SIZE(mt7620_clk_divider)); -- -- return mt7620_calc_rate(xtal_rate, mul, mt7620_clk_divider[div]); --} -- --static __init unsigned long --mt7620_get_pll_rate(unsigned long xtal_rate, unsigned long cpu_pll_rate) --{ -- u32 reg; -- -- reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); -- if (reg & CPLL_CFG1_CPU_AUX1) -- return xtal_rate; -- -- if (reg & CPLL_CFG1_CPU_AUX0) -- return MHZ(480); -- -- return cpu_pll_rate; --} -- --static __init unsigned long --mt7620_get_cpu_rate(unsigned long pll_rate) --{ -- u32 reg; -- u32 mul; -- u32 div; -- -- reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); -- -- mul = reg & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; -- div = (reg >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & -- CPU_SYS_CLKCFG_CPU_FDIV_MASK; -- -- return mt7620_calc_rate(pll_rate, mul, div); --} -- --static const u32 mt7620_ocp_dividers[16] __initconst = { -- [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, -- [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, -- [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, -- [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, -- [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, --}; -- --static __init unsigned long --mt7620_get_dram_rate(unsigned long pll_rate) --{ -- if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) -- return pll_rate / 4; -- -- return pll_rate / 3; --} -- --static __init unsigned long --mt7620_get_sys_rate(unsigned long cpu_rate) --{ -- u32 reg; -- u32 ocp_ratio; -- u32 div; -- -- reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); -- -- ocp_ratio = (reg >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & -- CPU_SYS_CLKCFG_OCP_RATIO_MASK; -- -- if (WARN_ON(ocp_ratio >= ARRAY_SIZE(mt7620_ocp_dividers))) -- return cpu_rate; -- -- div = mt7620_ocp_dividers[ocp_ratio]; -- if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) -- return cpu_rate; -- -- return cpu_rate / div; --} -- --void __init ralink_clk_init(void) --{ -- unsigned long xtal_rate; -- unsigned long cpu_pll_rate; -- unsigned long pll_rate; -- unsigned long cpu_rate; -- unsigned long sys_rate; -- unsigned long dram_rate; -- unsigned long periph_rate; -- unsigned long pcmi2s_rate; -- -- xtal_rate = mt7620_get_xtal_rate(); -- --#define RFMT(label) label ":%lu.%03luMHz " --#define RINT(x) ((x) / 1000000) --#define RFRAC(x) (((x) / 1000) % 1000) -- -- if (is_mt76x8()) { -- if (xtal_rate == MHZ(40)) -- cpu_rate = MHZ(580); -- else -- cpu_rate = MHZ(575); -- dram_rate = sys_rate = cpu_rate / 3; -- periph_rate = MHZ(40); -- pcmi2s_rate = MHZ(480); -- -- ralink_clk_add("10000d00.uartlite", periph_rate); -- ralink_clk_add("10000e00.uartlite", periph_rate); -- } else { -- cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); -- pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); -- -- cpu_rate = mt7620_get_cpu_rate(pll_rate); -- dram_rate = mt7620_get_dram_rate(pll_rate); -- sys_rate = mt7620_get_sys_rate(cpu_rate); -- periph_rate = mt7620_get_periph_rate(xtal_rate); -- pcmi2s_rate = periph_rate; -- -- pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), -- RINT(xtal_rate), RFRAC(xtal_rate), -- RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), -- RINT(pll_rate), RFRAC(pll_rate)); -- -- ralink_clk_add("10000500.uart", periph_rate); -- } -- -- pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), -- RINT(cpu_rate), RFRAC(cpu_rate), -- RINT(dram_rate), RFRAC(dram_rate), -- RINT(sys_rate), RFRAC(sys_rate), -- RINT(periph_rate), RFRAC(periph_rate)); --#undef RFRAC --#undef RINT --#undef RFMT -- -- ralink_clk_add("cpu", cpu_rate); -- ralink_clk_add("10000100.timer", periph_rate); -- ralink_clk_add("10000120.watchdog", periph_rate); -- ralink_clk_add("10000900.i2c", periph_rate); -- ralink_clk_add("10000a00.i2s", pcmi2s_rate); -- ralink_clk_add("10000b00.spi", sys_rate); -- ralink_clk_add("10000b40.spi", sys_rate); -- ralink_clk_add("10000c00.uartlite", periph_rate); -- ralink_clk_add("10000d00.uart1", periph_rate); -- ralink_clk_add("10000e00.uart2", periph_rate); -- ralink_clk_add("10180000.wmac", xtal_rate); -- -- if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) { -- /* -- * When the CPU goes into sleep mode, the BUS clock will be -- * too low for USB to function properly. Adjust the busses -- * fractional divider to fix this -- */ -- u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); -- -- val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); -- val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; -- -- rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG); -- } --} -- - void __init ralink_of_remap(void) - { - rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-07-mips-ralink-remove-reset-related-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-07-mips-ralink-remove-reset-related-code.patch deleted file mode 100644 index bdd9fcfd33..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-07-mips-ralink-remove-reset-related-code.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 201ddc05777cd8e084b508bcdda22214bfe2895e Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:39 +0200 -Subject: [PATCH 7/9] mips: ralink: remove reset related code - -A proper clock driver for ralink SoCs has been added. This driver is also -a reset provider for the SoC. Hence there is no need to have reset related -code in 'arch/mips/ralink' folder anymore. The only code that remains is -the one related with mips_reboot_setup where a PCI reset is performed. -We maintain this because I cannot test old ralink board with PCI to be -sure all works if we remove also this code. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/ralink/common.h | 2 -- - arch/mips/ralink/of.c | 4 ---- - arch/mips/ralink/reset.c | 61 ----------------------------------------------- - 3 files changed, 67 deletions(-) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -23,8 +23,6 @@ extern struct ralink_soc_info soc_info; - - extern void ralink_of_remap(void); - --extern void ralink_rst_init(void); -- - extern void __init prom_soc_init(struct ralink_soc_info *soc_info); - - __iomem void *plat_of_remap_node(const char *node); ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -95,10 +95,6 @@ static int __init plat_of_setup(void) - { - __dt_register_buses(soc_info.compatible, "palmbus"); - -- /* make sure that the reset controller is setup early */ -- if (ralink_soc != MT762X_SOC_MT7621AT) -- ralink_rst_init(); -- - return 0; - } - ---- a/arch/mips/ralink/reset.c -+++ b/arch/mips/ralink/reset.c -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - - #include - -@@ -22,66 +21,6 @@ - #define RSTCTL_RESET_PCI BIT(26) - #define RSTCTL_RESET_SYSTEM BIT(0) - --static int ralink_assert_device(struct reset_controller_dev *rcdev, -- unsigned long id) --{ -- u32 val; -- -- if (id == 0) -- return -1; -- -- val = rt_sysc_r32(SYSC_REG_RESET_CTRL); -- val |= BIT(id); -- rt_sysc_w32(val, SYSC_REG_RESET_CTRL); -- -- return 0; --} -- --static int ralink_deassert_device(struct reset_controller_dev *rcdev, -- unsigned long id) --{ -- u32 val; -- -- if (id == 0) -- return -1; -- -- val = rt_sysc_r32(SYSC_REG_RESET_CTRL); -- val &= ~BIT(id); -- rt_sysc_w32(val, SYSC_REG_RESET_CTRL); -- -- return 0; --} -- --static int ralink_reset_device(struct reset_controller_dev *rcdev, -- unsigned long id) --{ -- ralink_assert_device(rcdev, id); -- return ralink_deassert_device(rcdev, id); --} -- --static const struct reset_control_ops reset_ops = { -- .reset = ralink_reset_device, -- .assert = ralink_assert_device, -- .deassert = ralink_deassert_device, --}; -- --static struct reset_controller_dev reset_dev = { -- .ops = &reset_ops, -- .owner = THIS_MODULE, -- .nr_resets = 32, -- .of_reset_n_cells = 1, --}; -- --void ralink_rst_init(void) --{ -- reset_dev.of_node = of_find_compatible_node(NULL, NULL, -- "ralink,rt2880-reset"); -- if (!reset_dev.of_node) -- pr_err("Failed to find reset controller node"); -- else -- reset_controller_register(&reset_dev); --} -- - static void ralink_restart(char *command) - { - if (IS_ENABLED(CONFIG_PCI)) { diff --git a/target/linux/ramips/patches-5.15/005-v6.5-08-mips-ralink-get-cpu-rate-from-new-driver-code.patch b/target/linux/ramips/patches-5.15/005-v6.5-08-mips-ralink-get-cpu-rate-from-new-driver-code.patch deleted file mode 100644 index 2430c1f375..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-08-mips-ralink-get-cpu-rate-from-new-driver-code.patch +++ /dev/null @@ -1,102 +0,0 @@ -From ad38c17b0c26ae2108b50ac1eb0281a2e1ce08e9 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:40 +0200 -Subject: [PATCH 8/9] mips: ralink: get cpu rate from new driver code - -At very early stage on boot, there is a need to set 'mips_hpt_frequency'. -This timer frequency is a half of the CPU frequency. To get clocks properly -set we need to call to 'of_clk_init()' and properly get cpu clock frequency -afterwards. Depending on the SoC, CPU clock index and compatible differs, so -use them to get the proper clock frm the clock provider. Hence, adapt code -to be aligned with new clock driver. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/ralink/clk.c | 61 ++++++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 52 insertions(+), 9 deletions(-) - ---- a/arch/mips/ralink/clk.c -+++ b/arch/mips/ralink/clk.c -@@ -11,29 +11,72 @@ - #include - #include - #include -+#include - - #include - - #include "common.h" - --void ralink_clk_add(const char *dev, unsigned long rate) -+static const char *clk_cpu(int *idx) - { -- struct clk *clk = clk_register_fixed_rate(NULL, dev, NULL, 0, rate); -- -- if (!clk) -- panic("failed to add clock"); -- -- clkdev_create(clk, NULL, "%s", dev); -+ switch (ralink_soc) { -+ case RT2880_SOC: -+ *idx = 0; -+ return "ralink,rt2880-sysc"; -+ case RT3883_SOC: -+ *idx = 0; -+ return "ralink,rt3883-sysc"; -+ case RT305X_SOC_RT3050: -+ *idx = 0; -+ return "ralink,rt3050-sysc"; -+ case RT305X_SOC_RT3052: -+ *idx = 0; -+ return "ralink,rt3052-sysc"; -+ case RT305X_SOC_RT3350: -+ *idx = 1; -+ return "ralink,rt3350-sysc"; -+ case RT305X_SOC_RT3352: -+ *idx = 1; -+ return "ralink,rt3352-sysc"; -+ case RT305X_SOC_RT5350: -+ *idx = 1; -+ return "ralink,rt5350-sysc"; -+ case MT762X_SOC_MT7620A: -+ *idx = 2; -+ return "ralink,mt7620-sysc"; -+ case MT762X_SOC_MT7620N: -+ *idx = 2; -+ return "ralink,mt7620-sysc"; -+ case MT762X_SOC_MT7628AN: -+ *idx = 1; -+ return "ralink,mt7628-sysc"; -+ case MT762X_SOC_MT7688: -+ *idx = 1; -+ return "ralink,mt7688-sysc"; -+ default: -+ *idx = -1; -+ return "invalid"; -+ } - } - - void __init plat_time_init(void) - { -+ struct of_phandle_args clkspec; -+ const char *compatible; - struct clk *clk; -+ int cpu_clk_idx; - - ralink_of_remap(); - -- ralink_clk_init(); -- clk = clk_get_sys("cpu", NULL); -+ compatible = clk_cpu(&cpu_clk_idx); -+ if (cpu_clk_idx == -1) -+ panic("unable to get CPU clock index"); -+ -+ of_clk_init(NULL); -+ clkspec.np = of_find_compatible_node(NULL, NULL, compatible); -+ clkspec.args_count = 1; -+ clkspec.args[0] = cpu_clk_idx; -+ clk = of_clk_get_from_provider(&clkspec); - if (IS_ERR(clk)) - panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); - pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); diff --git a/target/linux/ramips/patches-5.15/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch b/target/linux/ramips/patches-5.15/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch deleted file mode 100644 index d05c1954f7..0000000000 --- a/target/linux/ramips/patches-5.15/005-v6.5-09-MAINTAINERS-add-Mediatek-MTMIPS-Clock-maintainer.patch +++ /dev/null @@ -1,28 +0,0 @@ -From fc15a7193a4d37d79e873fa06cc423180ddd2ddf Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Mon, 19 Jun 2023 06:09:41 +0200 -Subject: [PATCH 9/9] MAINTAINERS: add Mediatek MTMIPS Clock maintainer - -Adding myself as maintainer for Mediatek MTMIPS clock driver. - -Signed-off-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - MAINTAINERS | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -11859,6 +11859,12 @@ S: Maintained - F: Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml - F: drivers/clk/ralink/clk-mt7621.c - -+MEDIATEK MTMIPS CLOCK DRIVER -+M: Sergio Paracuellos -+S: Maintained -+F: Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml -+F: drivers/clk/ralink/clk-mtmips.c -+ - MEDIATEK MT7621/28/88 I2C DRIVER - M: Stefan Roese - L: linux-i2c@vger.kernel.org diff --git a/target/linux/ramips/patches-5.15/006-v6.5-mips-ralink-introduce-commonly-used-remap-node-funct.patch b/target/linux/ramips/patches-5.15/006-v6.5-mips-ralink-introduce-commonly-used-remap-node-funct.patch deleted file mode 100644 index 429b9feb9d..0000000000 --- a/target/linux/ramips/patches-5.15/006-v6.5-mips-ralink-introduce-commonly-used-remap-node-funct.patch +++ /dev/null @@ -1,189 +0,0 @@ -From fd99ac5055d4705e91c73d1adba18bc71c8511a8 Mon Sep 17 00:00:00 2001 -From: Shiji Yang -Date: Tue, 20 Jun 2023 19:44:32 +0800 -Subject: [PATCH] mips: ralink: introduce commonly used remap node function - -The ralink_of_remap() function is repeated several times on SoC specific -source files. They have the same structure, but just differ in compatible -strings. In order to make commonly use of these codes, this patch -introduces a newly designed mtmips_of_remap_node() function to match and -remap all supported system controller and memory controller nodes. - -Build and run tested on MT7620 and MT7628. - -Signed-off-by: Shiji Yang -Reviewed-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/ralink/common.h | 2 -- - arch/mips/ralink/mt7620.c | 9 --------- - arch/mips/ralink/mt7621.c | 9 --------- - arch/mips/ralink/of.c | 42 +++++++++++++++++++++++++++++++++++------- - arch/mips/ralink/rt288x.c | 9 --------- - arch/mips/ralink/rt305x.c | 9 --------- - arch/mips/ralink/rt3883.c | 9 --------- - 7 files changed, 35 insertions(+), 54 deletions(-) - ---- a/arch/mips/ralink/common.h -+++ b/arch/mips/ralink/common.h -@@ -25,6 +25,4 @@ extern void ralink_of_remap(void); - - extern void __init prom_soc_init(struct ralink_soc_info *soc_info); - --__iomem void *plat_of_remap_node(const char *node); -- - #endif /* _RALINK_COMMON_H__ */ ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -43,15 +43,6 @@ - /* does the board have sdram or ddram */ - static int dram_type; - --void __init ralink_of_remap(void) --{ -- rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); -- rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc"); -- -- if (!rt_sysc_membase || !rt_memc_membase) -- panic("Failed to remap core resources"); --} -- - static __init void - mt7620_dram_init(struct ralink_soc_info *soc_info) - { ---- a/arch/mips/ralink/mt7621.c -+++ b/arch/mips/ralink/mt7621.c -@@ -58,15 +58,6 @@ static void __init mt7621_memory_detect( - memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE); - } - --void __init ralink_of_remap(void) --{ -- rt_sysc_membase = plat_of_remap_node("mediatek,mt7621-sysc"); -- rt_memc_membase = plat_of_remap_node("mediatek,mt7621-memc"); -- -- if (!rt_sysc_membase || !rt_memc_membase) -- panic("Failed to remap core resources"); --} -- - static unsigned int __init mt7621_get_soc_name0(void) - { - return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -29,26 +29,56 @@ __iomem void *rt_sysc_membase; - __iomem void *rt_memc_membase; - EXPORT_SYMBOL_GPL(rt_sysc_membase); - --__iomem void *plat_of_remap_node(const char *node) -+static const struct of_device_id mtmips_memc_match[] = { -+ { .compatible = "mediatek,mt7621-memc" }, -+ { .compatible = "ralink,mt7620a-memc" }, -+ { .compatible = "ralink,rt2880-memc" }, -+ { .compatible = "ralink,rt3050-memc" }, -+ { .compatible = "ralink,rt3883-memc" }, -+ {} -+}; -+ -+static const struct of_device_id mtmips_sysc_match[] = { -+ { .compatible = "mediatek,mt7621-sysc" }, -+ { .compatible = "ralink,mt7620a-sysc" }, -+ { .compatible = "ralink,rt2880-sysc" }, -+ { .compatible = "ralink,rt3050-sysc" }, -+ { .compatible = "ralink,rt3883-sysc" }, -+ {} -+}; -+ -+static __iomem void * -+mtmips_of_remap_node(const struct of_device_id *match, const char *type) - { - struct resource res; - struct device_node *np; - -- np = of_find_compatible_node(NULL, NULL, node); -+ np = of_find_matching_node(NULL, match); - if (!np) -- panic("Failed to find %s node", node); -+ panic("Failed to find %s controller node", type); - - if (of_address_to_resource(np, 0, &res)) -- panic("Failed to get resource for %s", node); -+ panic("Failed to get resource for %s node", np->name); - - if (!request_mem_region(res.start, - resource_size(&res), - res.name)) -- panic("Failed to request resources for %s", node); -+ panic("Failed to request resources for %s node", np->name); -+ -+ of_node_put(np); - - return ioremap(res.start, resource_size(&res)); - } - -+void __init ralink_of_remap(void) -+{ -+ rt_sysc_membase = mtmips_of_remap_node(mtmips_sysc_match, "system"); -+ rt_memc_membase = mtmips_of_remap_node(mtmips_memc_match, "memory"); -+ -+ if (!rt_sysc_membase || !rt_memc_membase) -+ panic("Failed to remap core resources"); -+} -+ - void __init device_tree_init(void) - { - unflatten_and_copy_device_tree(); ---- a/arch/mips/ralink/rt288x.c -+++ b/arch/mips/ralink/rt288x.c -@@ -17,15 +17,6 @@ - - #include "common.h" - --void __init ralink_of_remap(void) --{ -- rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); -- rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc"); -- -- if (!rt_sysc_membase || !rt_memc_membase) -- panic("Failed to remap core resources"); --} -- - void __init prom_soc_init(struct ralink_soc_info *soc_info) - { - void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE); ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -53,15 +53,6 @@ static unsigned long rt5350_get_mem_size - return ret; - } - --void __init ralink_of_remap(void) --{ -- rt_sysc_membase = plat_of_remap_node("ralink,rt3050-sysc"); -- rt_memc_membase = plat_of_remap_node("ralink,rt3050-memc"); -- -- if (!rt_sysc_membase || !rt_memc_membase) -- panic("Failed to remap core resources"); --} -- - void __init prom_soc_init(struct ralink_soc_info *soc_info) - { - void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); ---- a/arch/mips/ralink/rt3883.c -+++ b/arch/mips/ralink/rt3883.c -@@ -17,15 +17,6 @@ - - #include "common.h" - --void __init ralink_of_remap(void) --{ -- rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); -- rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc"); -- -- if (!rt_sysc_membase || !rt_memc_membase) -- panic("Failed to remap core resources"); --} -- - void __init prom_soc_init(struct ralink_soc_info *soc_info) - { - void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE); diff --git a/target/linux/ramips/patches-5.15/007-v6.5-clk-ralink-mtmips-Fix-uninitialized-use-of-ret-in-mt.patch b/target/linux/ramips/patches-5.15/007-v6.5-clk-ralink-mtmips-Fix-uninitialized-use-of-ret-in-mt.patch deleted file mode 100644 index c0c2a6e204..0000000000 --- a/target/linux/ramips/patches-5.15/007-v6.5-clk-ralink-mtmips-Fix-uninitialized-use-of-ret-in-mt.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6e68dae946e3a0333fbde5487ce163142ca10ae0 Mon Sep 17 00:00:00 2001 -From: Nathan Chancellor -Date: Thu, 22 Jun 2023 15:56:19 +0000 -Subject: clk: ralink: mtmips: Fix uninitialized use of ret in - mtmips_register_{fixed,factor}_clocks() - -Clang warns: - - drivers/clk/ralink/clk-mtmips.c:309:9: error: variable 'ret' is uninitialized when used here [-Werror,-Wuninitialized] - 309 | return ret; - | ^~~ - drivers/clk/ralink/clk-mtmips.c:285:9: note: initialize the variable 'ret' to silence this warning - 285 | int ret, i; - | ^ - | = 0 - drivers/clk/ralink/clk-mtmips.c:359:9: error: variable 'ret' is uninitialized when used here [-Werror,-Wuninitialized] - 359 | return ret; - | ^~~ - drivers/clk/ralink/clk-mtmips.c:335:9: note: initialize the variable 'ret' to silence this warning - 335 | int ret, i; - | ^ - | = 0 - 2 errors generated. - -Set ret to the return value of clk_hw_register_fixed_rate() using the -PTR_ERR() macro, which ensures ret is not used uninitialized, clearing -up the warning. - -Fixes: 6f3b15586eef ("clk: ralink: add clock and reset driver for MTMIPS SoCs") -Closes: https://github.com/ClangBuiltLinux/linux/issues/1879 -Signed-off-by: Nathan Chancellor -Reviewed-by: Nick Desaulniers -Acked-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - drivers/clk/ralink/clk-mtmips.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/clk/ralink/clk-mtmips.c -+++ b/drivers/clk/ralink/clk-mtmips.c -@@ -292,6 +292,7 @@ static int mtmips_register_fixed_clocks( - sclk->parent, 0, - sclk->rate); - if (IS_ERR(sclk->hw)) { -+ ret = PTR_ERR(sclk->hw); - pr_err("Couldn't register fixed clock %d\n", idx); - goto err_clk_unreg; - } -@@ -342,6 +343,7 @@ static int mtmips_register_factor_clocks - sclk->parent, sclk->flags, - sclk->mult, sclk->div); - if (IS_ERR(sclk->hw)) { -+ ret = PTR_ERR(sclk->hw); - pr_err("Couldn't register factor clock %d\n", idx); - goto err_clk_unreg; - } diff --git a/target/linux/ramips/patches-5.15/008-v6.5-mips-ralink-match-all-supported-system-controller-co.patch b/target/linux/ramips/patches-5.15/008-v6.5-mips-ralink-match-all-supported-system-controller-co.patch deleted file mode 100644 index 6940a2b4b9..0000000000 --- a/target/linux/ramips/patches-5.15/008-v6.5-mips-ralink-match-all-supported-system-controller-co.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 670f77f76f650b1b341d31d009cc2fb03a4d1fcf Mon Sep 17 00:00:00 2001 -From: Shiji Yang -Date: Fri, 23 Jun 2023 08:17:48 +0800 -Subject: mips: ralink: match all supported system controller compatible - strings - -Recently, A new clock and reset controller driver has been introduced to -the ralink mips target[1]. It provides proper system control and adds more -SoC specific compatible strings. In order to better initialize CPUs, this -patch removes the outdated "ralink,mt7620a-sysc" and add all dt-binding -documented compatible strings to the system controller match table. - -[1] https://lore.kernel.org/all/20230619040941.1340372-1-sergio.paracuellos@gmail.com/ - -Signed-off-by: Shiji Yang -Reviewed-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/ralink/of.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - ---- a/arch/mips/ralink/of.c -+++ b/arch/mips/ralink/of.c -@@ -40,10 +40,15 @@ static const struct of_device_id mtmips_ - - static const struct of_device_id mtmips_sysc_match[] = { - { .compatible = "mediatek,mt7621-sysc" }, -- { .compatible = "ralink,mt7620a-sysc" }, -+ { .compatible = "ralink,mt7620-sysc" }, -+ { .compatible = "ralink,mt7628-sysc" }, -+ { .compatible = "ralink,mt7688-sysc" }, - { .compatible = "ralink,rt2880-sysc" }, - { .compatible = "ralink,rt3050-sysc" }, -+ { .compatible = "ralink,rt3052-sysc" }, -+ { .compatible = "ralink,rt3352-sysc" }, - { .compatible = "ralink,rt3883-sysc" }, -+ { .compatible = "ralink,rt5350-sysc" }, - {} - }; - diff --git a/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch b/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch deleted file mode 100644 index e06d5621e1..0000000000 --- a/target/linux/ramips/patches-5.15/009-v6.3-01-watchdog-mt7621-wdt-avoid-static-global-declarations.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 783c7cb4659b53b5e1b809dac5e8cdf250145919 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Tue, 14 Feb 2023 11:39:35 +0100 -Subject: [PATCH 1/2] watchdog: mt7621-wdt: avoid static global declarations - -Instead of using static global definitions in driver code, refactor code -introducing a new watchdog driver data structure and use it along the -code. - -Reviewed-by: Guenter Roeck -Signed-off-by: Sergio Paracuellos -Link: https://lore.kernel.org/r/20230214103936.1061078-5-sergio.paracuellos@gmail.com -[groeck: unsigned -> unsigned int] -Signed-off-by: Guenter Roeck -Signed-off-by: Wim Van Sebroeck ---- - drivers/watchdog/mt7621_wdt.c | 102 +++++++++++++++++++++++++++--------------- - 1 file changed, 65 insertions(+), 37 deletions(-) - ---- a/drivers/watchdog/mt7621_wdt.c -+++ b/drivers/watchdog/mt7621_wdt.c -@@ -31,8 +31,11 @@ - #define TMR1CTL_RESTART BIT(9) - #define TMR1CTL_PRESCALE_SHIFT 16 - --static void __iomem *mt7621_wdt_base; --static struct reset_control *mt7621_wdt_reset; -+struct mt7621_wdt_data { -+ void __iomem *base; -+ struct reset_control *rst; -+ struct watchdog_device wdt; -+}; - - static bool nowayout = WATCHDOG_NOWAYOUT; - module_param(nowayout, bool, 0); -@@ -40,27 +43,31 @@ MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - --static inline void rt_wdt_w32(unsigned reg, u32 val) -+static inline void rt_wdt_w32(void __iomem *base, unsigned int reg, u32 val) - { -- iowrite32(val, mt7621_wdt_base + reg); -+ iowrite32(val, base + reg); - } - --static inline u32 rt_wdt_r32(unsigned reg) -+static inline u32 rt_wdt_r32(void __iomem *base, unsigned int reg) - { -- return ioread32(mt7621_wdt_base + reg); -+ return ioread32(base + reg); - } - - static int mt7621_wdt_ping(struct watchdog_device *w) - { -- rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART); -+ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); -+ -+ rt_wdt_w32(drvdata->base, TIMER_REG_TMRSTAT, TMR1CTL_RESTART); - - return 0; - } - - static int mt7621_wdt_set_timeout(struct watchdog_device *w, unsigned int t) - { -+ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); -+ - w->timeout = t; -- rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000); -+ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1LOAD, t * 1000); - mt7621_wdt_ping(w); - - return 0; -@@ -68,29 +75,31 @@ static int mt7621_wdt_set_timeout(struct - - static int mt7621_wdt_start(struct watchdog_device *w) - { -+ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); - u32 t; - - /* set the prescaler to 1ms == 1000us */ -- rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); -+ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); - - mt7621_wdt_set_timeout(w, w->timeout); - -- t = rt_wdt_r32(TIMER_REG_TMR1CTL); -+ t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); - t |= TMR1CTL_ENABLE; -- rt_wdt_w32(TIMER_REG_TMR1CTL, t); -+ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); - - return 0; - } - - static int mt7621_wdt_stop(struct watchdog_device *w) - { -+ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); - u32 t; - - mt7621_wdt_ping(w); - -- t = rt_wdt_r32(TIMER_REG_TMR1CTL); -+ t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); - t &= ~TMR1CTL_ENABLE; -- rt_wdt_w32(TIMER_REG_TMR1CTL, t); -+ rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); - - return 0; - } -@@ -105,7 +114,9 @@ static int mt7621_wdt_bootcause(void) - - static int mt7621_wdt_is_running(struct watchdog_device *w) - { -- return !!(rt_wdt_r32(TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); -+ struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); -+ -+ return !!(rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); - } - - static const struct watchdog_info mt7621_wdt_info = { -@@ -121,30 +132,39 @@ static const struct watchdog_ops mt7621_ - .set_timeout = mt7621_wdt_set_timeout, - }; - --static struct watchdog_device mt7621_wdt_dev = { -- .info = &mt7621_wdt_info, -- .ops = &mt7621_wdt_ops, -- .min_timeout = 1, -- .max_timeout = 0xfffful / 1000, --}; -- - static int mt7621_wdt_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- mt7621_wdt_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(mt7621_wdt_base)) -- return PTR_ERR(mt7621_wdt_base); -- -- mt7621_wdt_reset = devm_reset_control_get_exclusive(dev, NULL); -- if (!IS_ERR(mt7621_wdt_reset)) -- reset_control_deassert(mt7621_wdt_reset); -- -- mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause(); -- -- watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout, -- dev); -- watchdog_set_nowayout(&mt7621_wdt_dev, nowayout); -- if (mt7621_wdt_is_running(&mt7621_wdt_dev)) { -+ struct watchdog_device *mt7621_wdt; -+ struct mt7621_wdt_data *drvdata; -+ int err; -+ -+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); -+ if (!drvdata) -+ return -ENOMEM; -+ -+ drvdata->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(drvdata->base)) -+ return PTR_ERR(drvdata->base); -+ -+ drvdata->rst = devm_reset_control_get_exclusive(dev, NULL); -+ if (!IS_ERR(drvdata->rst)) -+ reset_control_deassert(drvdata->rst); -+ -+ mt7621_wdt = &drvdata->wdt; -+ mt7621_wdt->info = &mt7621_wdt_info; -+ mt7621_wdt->ops = &mt7621_wdt_ops; -+ mt7621_wdt->min_timeout = 1; -+ mt7621_wdt->max_timeout = 0xfffful / 1000; -+ mt7621_wdt->parent = dev; -+ -+ mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); -+ -+ watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); -+ watchdog_set_nowayout(mt7621_wdt, nowayout); -+ watchdog_set_drvdata(mt7621_wdt, drvdata); -+ -+ if (mt7621_wdt_is_running(mt7621_wdt)) { - /* - * Make sure to apply timeout from watchdog core, taking - * the prescaler of this driver here into account (the -@@ -154,17 +174,25 @@ static int mt7621_wdt_probe(struct platf - * we first disable the watchdog, set the new prescaler - * and timeout, and then re-enable the watchdog. - */ -- mt7621_wdt_stop(&mt7621_wdt_dev); -- mt7621_wdt_start(&mt7621_wdt_dev); -- set_bit(WDOG_HW_RUNNING, &mt7621_wdt_dev.status); -+ mt7621_wdt_stop(mt7621_wdt); -+ mt7621_wdt_start(mt7621_wdt); -+ set_bit(WDOG_HW_RUNNING, &mt7621_wdt->status); - } - -- return devm_watchdog_register_device(dev, &mt7621_wdt_dev); -+ err = devm_watchdog_register_device(dev, &drvdata->wdt); -+ if (err) -+ return err; -+ -+ platform_set_drvdata(pdev, drvdata); -+ -+ return 0; - } - - static void mt7621_wdt_shutdown(struct platform_device *pdev) - { -- mt7621_wdt_stop(&mt7621_wdt_dev); -+ struct mt7621_wdt_data *drvdata = platform_get_drvdata(pdev); -+ -+ mt7621_wdt_stop(&drvdata->wdt); - } - - static const struct of_device_id mt7621_wdt_match[] = { diff --git a/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch b/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch deleted file mode 100644 index 8e6265404b..0000000000 --- a/target/linux/ramips/patches-5.15/009-v6.3-02-watchdog-mt7621-wdt-avoid-ralink-architecture-depend.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ff8ec4ac39ad413b580d611dbf68e1d8a82eba56 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Tue, 14 Feb 2023 11:39:36 +0100 -Subject: [PATCH 2/2] watchdog: mt7621-wdt: avoid ralink architecture dependent code - -MT7621 SoC has a system controller node. Watchdog need to access to reset -status register. Ralink architecture and related driver are old and from -the beggining they are using some architecture dependent operations for -accessing this shared registers through 'asm/mach-ralink/ralink_regs.h' -header file. However this is not ideal from a driver perspective which can -just access to the system controller registers in an arch independent way -using regmap syscon APIs. Update Kconfig accordingly to select new added -dependencies and allow driver to be compile tested. - -Signed-off-by: Sergio Paracuellos -Reviewed-by: Guenter Roeck -Link: https://lore.kernel.org/r/20230214103936.1061078-6-sergio.paracuellos@gmail.com -Signed-off-by: Guenter Roeck -Signed-off-by: Wim Van Sebroeck ---- - drivers/watchdog/Kconfig | 4 +++- - drivers/watchdog/mt7621_wdt.c | 22 +++++++++++++++++----- - 2 files changed, 20 insertions(+), 6 deletions(-) - ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1799,7 +1799,9 @@ config RALINK_WDT - config MT7621_WDT - tristate "Mediatek SoC watchdog" - select WATCHDOG_CORE -- depends on SOC_MT7620 || SOC_MT7621 -+ select REGMAP_MMIO -+ select MFD_SYSCON -+ depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST - help - Hardware driver for the Mediatek/Ralink MT7621/8 SoC Watchdog Timer. - ---- a/drivers/watchdog/mt7621_wdt.c -+++ b/drivers/watchdog/mt7621_wdt.c -@@ -15,8 +15,8 @@ - #include - #include - #include -- --#include -+#include -+#include - - #define SYSC_RSTSTAT 0x38 - #define WDT_RST_CAUSE BIT(1) -@@ -34,6 +34,7 @@ - struct mt7621_wdt_data { - void __iomem *base; - struct reset_control *rst; -+ struct regmap *sysc; - struct watchdog_device wdt; - }; - -@@ -104,9 +105,12 @@ static int mt7621_wdt_stop(struct watchd - return 0; - } - --static int mt7621_wdt_bootcause(void) -+static int mt7621_wdt_bootcause(struct mt7621_wdt_data *d) - { -- if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) -+ u32 val; -+ -+ regmap_read(d->sysc, SYSC_RSTSTAT, &val); -+ if (val & WDT_RST_CAUSE) - return WDIOF_CARDRESET; - - return 0; -@@ -134,6 +138,7 @@ static const struct watchdog_ops mt7621_ - - static int mt7621_wdt_probe(struct platform_device *pdev) - { -+ struct device_node *np = pdev->dev.of_node; - struct device *dev = &pdev->dev; - struct watchdog_device *mt7621_wdt; - struct mt7621_wdt_data *drvdata; -@@ -143,6 +148,13 @@ static int mt7621_wdt_probe(struct platf - if (!drvdata) - return -ENOMEM; - -+ drvdata->sysc = syscon_regmap_lookup_by_phandle(np, "mediatek,sysctl"); -+ if (IS_ERR(drvdata->sysc)) { -+ drvdata->sysc = syscon_regmap_lookup_by_compatible("mediatek,mt7621-sysc"); -+ if (IS_ERR(drvdata->sysc)) -+ return PTR_ERR(drvdata->sysc); -+ } -+ - drvdata->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(drvdata->base)) - return PTR_ERR(drvdata->base); -@@ -158,7 +170,7 @@ static int mt7621_wdt_probe(struct platf - mt7621_wdt->max_timeout = 0xfffful / 1000; - mt7621_wdt->parent = dev; - -- mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); -+ mt7621_wdt->bootstatus = mt7621_wdt_bootcause(drvdata); - - watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); - watchdog_set_nowayout(mt7621_wdt, nowayout); diff --git a/target/linux/ramips/patches-5.15/010-v6.5-01-mips-pci-mt7620-do-not-print-NFTS-register-value-as-.patch b/target/linux/ramips/patches-5.15/010-v6.5-01-mips-pci-mt7620-do-not-print-NFTS-register-value-as-.patch deleted file mode 100644 index 704e861b82..0000000000 --- a/target/linux/ramips/patches-5.15/010-v6.5-01-mips-pci-mt7620-do-not-print-NFTS-register-value-as-.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 9f9a035e6156a57d9da062b26d2a48d031744a1e Mon Sep 17 00:00:00 2001 -From: Shiji Yang -Date: Tue, 20 Jun 2023 18:43:22 +0800 -Subject: [PATCH 1/2] mips: pci-mt7620: do not print NFTS register value as - error log - -These codes are used to read NFTS_TIMEOUT_DELAY register value and -write it into kernel log after writing the register. they are only -used for debugging during driver development, so there is no need -to keep them now. - -Tested on MT7628AN router Motorola MWR03. - -Signed-off-by: Shiji Yang -Reviewed-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/pci/pci-mt7620.c | 3 --- - 1 file changed, 3 deletions(-) - ---- a/arch/mips/pci/pci-mt7620.c -+++ b/arch/mips/pci/pci-mt7620.c -@@ -274,9 +274,6 @@ static int mt7628_pci_hw_init(struct pla - val |= 0x50 << 8; - pci_config_write(NULL, 0, 0x70c, 4, val); - -- pci_config_read(NULL, 0, 0x70c, 4, &val); -- dev_err(&pdev->dev, "Port 0 N_FTS = %x\n", (unsigned int) val); -- - return 0; - } - diff --git a/target/linux/ramips/patches-5.15/010-v6.5-02-mips-pci-mt7620-use-dev_info-to-log-PCIe-device-dete.patch b/target/linux/ramips/patches-5.15/010-v6.5-02-mips-pci-mt7620-use-dev_info-to-log-PCIe-device-dete.patch deleted file mode 100644 index 5898a110ea..0000000000 --- a/target/linux/ramips/patches-5.15/010-v6.5-02-mips-pci-mt7620-use-dev_info-to-log-PCIe-device-dete.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 89ec9bbe60b61cc6ae3eddd6d4f43e128f8a88de Mon Sep 17 00:00:00 2001 -From: Shiji Yang -Date: Tue, 20 Jun 2023 18:43:23 +0800 -Subject: [PATCH 2/2] mips: pci-mt7620: use dev_info() to log PCIe device - detection result - -Usually, We only need to print the error log when there is a PCIe card but -initialization fails. Whether the driver finds the PCIe card or not is the -expected behavior. So it's better to log these information with dev_info(). - -Tested on MT7628AN router Motorola MWR03. - -Signed-off-by: Shiji Yang -Reviewed-by: Sergio Paracuellos -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/pci/pci-mt7620.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/mips/pci/pci-mt7620.c -+++ b/arch/mips/pci/pci-mt7620.c -@@ -331,7 +331,7 @@ static int mt7620_pci_probe(struct platf - rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); - if (ralink_soc == MT762X_SOC_MT7620A) - rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV); -- dev_err(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n"); -+ dev_info(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n"); - return -1; - } - -@@ -374,7 +374,7 @@ int pcibios_map_irq(const struct pci_dev - dev->bus->number, slot); - return 0; - } -- dev_err(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n", -+ dev_info(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n", - dev->bus->number, slot, irq); - - /* configure the cache line size to 0x14 */ diff --git a/target/linux/ramips/patches-5.15/100-v5.16-PCI-mt7621-Add-MediaTek-MT7621-PCIe-host-controller-.patch b/target/linux/ramips/patches-5.15/100-v5.16-PCI-mt7621-Add-MediaTek-MT7621-PCIe-host-controller-.patch deleted file mode 100644 index 1c8c7cd3d0..0000000000 --- a/target/linux/ramips/patches-5.15/100-v5.16-PCI-mt7621-Add-MediaTek-MT7621-PCIe-host-controller-.patch +++ /dev/null @@ -1,1418 +0,0 @@ -From: Sergio Paracuellos -Date: Wed, 22 Sep 2021 07:00:34 +0200 -Subject: [PATCH] PCI: mt7621: Add MediaTek MT7621 PCIe host controller driver - -Add driver for the PCIe controller of the MT7621 SoC. - -[bhelgaas: rename from pci-mt7621.c to pcie-mt7621.c; also rename Kconfig -symbol from PCI_MT7621 to PCIE_MT7621] -Link: https://lore.kernel.org/r/20210922050035.18162-3-sergio.paracuellos@gmail.com -Signed-off-by: Sergio Paracuellos -Signed-off-by: Lorenzo Pieralisi -Signed-off-by: Bjorn Helgaas -Acked-by: Greg Kroah-Hartman ---- - rename drivers/{staging/mt7621-pci/pci-mt7621.c => pci/controller/pcie-mt7621.c} (95%) - delete mode 100644 drivers/staging/mt7621-pci/Kconfig - delete mode 100644 drivers/staging/mt7621-pci/Makefile - delete mode 100644 drivers/staging/mt7621-pci/TODO - delete mode 100644 drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -51,7 +51,8 @@ choice - select SYS_SUPPORTS_HIGHMEM - select MIPS_GIC - select CLKSRC_MIPS_GIC -- select HAVE_PCI if PCI_MT7621 -+ select HAVE_PCI -+ select PCI_DRIVERS_GENERIC - select SOC_BUS - endchoice - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -312,6 +312,14 @@ config PCIE_HISI_ERR - Say Y here if you want error handling support - for the PCIe controller's errors on HiSilicon HIP SoCs - -+config PCIE_MT7621 -+ tristate "MediaTek MT7621 PCIe Controller" -+ depends on (RALINK && SOC_MT7621) || (MIPS && COMPILE_TEST) -+ select PHY_MT7621_PCI -+ default SOC_MT7621 -+ help -+ This selects a driver for the MediaTek MT7621 PCIe Controller. -+ - source "drivers/pci/controller/dwc/Kconfig" - source "drivers/pci/controller/mobiveil/Kconfig" - source "drivers/pci/controller/cadence/Kconfig" ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -37,6 +37,8 @@ obj-$(CONFIG_VMD) += vmd.o - obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o - obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o - obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o -+obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o -+ - # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW - obj-y += dwc/ - obj-y += mobiveil/ ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -86,8 +86,6 @@ source "drivers/staging/vc04_services/Kc - - source "drivers/staging/pi433/Kconfig" - --source "drivers/staging/mt7621-pci/Kconfig" -- - source "drivers/staging/mt7621-dma/Kconfig" - - source "drivers/staging/ralink-gdma/Kconfig" ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -33,7 +33,6 @@ obj-$(CONFIG_KS7010) += ks7010/ - obj-$(CONFIG_GREYBUS) += greybus/ - obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ - obj-$(CONFIG_PI433) += pi433/ --obj-$(CONFIG_PCI_MT7621) += mt7621-pci/ - obj-$(CONFIG_SOC_MT7621) += mt7621-dma/ - obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ - obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ ---- a/drivers/staging/mt7621-pci/Kconfig -+++ /dev/null -@@ -1,8 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --config PCI_MT7621 -- tristate "MediaTek MT7621 PCI Controller" -- depends on RALINK -- select PCI_DRIVERS_GENERIC -- help -- This selects a driver for the MediaTek MT7621 PCI Controller. -- ---- a/drivers/staging/mt7621-pci/Makefile -+++ /dev/null -@@ -1,2 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --obj-$(CONFIG_PCI_MT7621) += pci-mt7621.o ---- a/drivers/staging/mt7621-pci/TODO -+++ /dev/null -@@ -1,4 +0,0 @@ -- --- general code review and cleanup -- --Cc: NeilBrown ---- a/drivers/staging/mt7621-pci/mediatek,mt7621-pci.txt -+++ /dev/null -@@ -1,104 +0,0 @@ --MediaTek MT7621 PCIe controller -- --Required properties: --- compatible: "mediatek,mt7621-pci" --- device_type: Must be "pci" --- reg: Base addresses and lengths of the PCIe subsys and root ports. --- bus-range: Range of bus numbers associated with this controller. --- #address-cells: Address representation for root ports (must be 3) --- pinctrl-names : The pin control state names. --- pinctrl-0: The "default" pinctrl state. --- #size-cells: Size representation for root ports (must be 2) --- ranges: Ranges for the PCI memory and I/O regions. --- #interrupt-cells: Must be 1 --- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties. -- Please refer to the standard PCI bus binding document for a more detailed -- explanation. --- status: either "disabled" or "okay". --- resets: Must contain an entry for each entry in reset-names. -- See ../reset/reset.txt for details. --- reset-names: Must be "pcie0", "pcie1", "pcieN"... based on the number of -- root ports. --- clocks: Must contain an entry for each entry in clock-names. -- See ../clocks/clock-bindings.txt for details. --- clock-names: Must be "pcie0", "pcie1", "pcieN"... based on the number of -- root ports. --- reset-gpios: GPIO specs for the reset pins. -- --In addition, the device tree node must have sub-nodes describing each PCIe port --interface, having the following mandatory properties: -- --Required properties: --- reg: Only the first four bytes are used to refer to the correct bus number -- and device number. --- #address-cells: Must be 3 --- #size-cells: Must be 2 --- ranges: Sub-ranges distributed from the PCIe controller node. An empty -- property is sufficient. --- bus-range: Range of bus numbers associated with this port. -- --Example for MT7621: -- -- pcie: pcie@1e140000 { -- compatible = "mediatek,mt7621-pci"; -- reg = <0x1e140000 0x100 /* host-pci bridge registers */ -- 0x1e142000 0x100 /* pcie port 0 RC control registers */ -- 0x1e143000 0x100 /* pcie port 1 RC control registers */ -- 0x1e144000 0x100>; /* pcie port 2 RC control registers */ -- -- #address-cells = <3>; -- #size-cells = <2>; -- -- pinctrl-names = "default"; -- pinctrl-0 = <&pcie_pins>; -- -- device_type = "pci"; -- -- bus-range = <0 255>; -- ranges = < -- 0x02000000 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */ -- 0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */ -- >; -- -- #interrupt-cells = <1>; -- interrupt-map-mask = <0xF0000 0 0 1>; -- interrupt-map = <0x10000 0 0 1 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>, -- <0x20000 0 0 1 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>, -- <0x30000 0 0 1 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; -- -- status = "disabled"; -- -- resets = <&rstctrl 24 &rstctrl 25 &rstctrl 26>; -- reset-names = "pcie0", "pcie1", "pcie2"; -- clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>; -- clock-names = "pcie0", "pcie1", "pcie2"; -- -- reset-gpios = <&gpio 19 GPIO_ACTIVE_LOW>, -- <&gpio 8 GPIO_ACTIVE_LOW>, -- <&gpio 7 GPIO_ACTIVE_LOW>; -- -- pcie@0,0 { -- reg = <0x0000 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -- ranges; -- bus-range = <0x00 0xff>; -- }; -- -- pcie@1,0 { -- reg = <0x0800 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -- ranges; -- bus-range = <0x00 0xff>; -- }; -- -- pcie@2,0 { -- reg = <0x1000 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -- ranges; -- bus-range = <0x00 0xff>; -- }; -- }; -- ---- a/drivers/staging/mt7621-pci/pci-mt7621.c -+++ /dev/null -@@ -1,601 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0+ --/* -- * BRIEF MODULE DESCRIPTION -- * PCI init for Ralink RT2880 solution -- * -- * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) -- * -- * May 2007 Bruce Chang -- * Initial Release -- * -- * May 2009 Bruce Chang -- * support RT2880/RT3883 PCIe -- * -- * May 2011 Bruce Chang -- * support RT6855/MT7620 PCIe -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --/* MediaTek specific configuration registers */ --#define PCIE_FTS_NUM 0x70c --#define PCIE_FTS_NUM_MASK GENMASK(15, 8) --#define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8) -- --/* Host-PCI bridge registers */ --#define RALINK_PCI_PCICFG_ADDR 0x0000 --#define RALINK_PCI_PCIMSK_ADDR 0x000C --#define RALINK_PCI_CONFIG_ADDR 0x0020 --#define RALINK_PCI_CONFIG_DATA 0x0024 --#define RALINK_PCI_MEMBASE 0x0028 --#define RALINK_PCI_IOBASE 0x002C -- --/* PCIe RC control registers */ --#define RALINK_PCI_ID 0x0030 --#define RALINK_PCI_CLASS 0x0034 --#define RALINK_PCI_SUBID 0x0038 --#define RALINK_PCI_STATUS 0x0050 -- --/* Some definition values */ --#define PCIE_REVISION_ID BIT(0) --#define PCIE_CLASS_CODE (0x60400 << 8) --#define PCIE_BAR_MAP_MAX GENMASK(30, 16) --#define PCIE_BAR_ENABLE BIT(0) --#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) --#define PCIE_PORT_LINKUP BIT(0) --#define PCIE_PORT_CNT 3 -- --#define PERST_DELAY_MS 100 -- --/** -- * struct mt7621_pcie_port - PCIe port information -- * @base: I/O mapped register base -- * @list: port list -- * @pcie: pointer to PCIe host info -- * @clk: pointer to the port clock gate -- * @phy: pointer to PHY control block -- * @pcie_rst: pointer to port reset control -- * @gpio_rst: gpio reset -- * @slot: port slot -- * @enabled: indicates if port is enabled -- */ --struct mt7621_pcie_port { -- void __iomem *base; -- struct list_head list; -- struct mt7621_pcie *pcie; -- struct clk *clk; -- struct phy *phy; -- struct reset_control *pcie_rst; -- struct gpio_desc *gpio_rst; -- u32 slot; -- bool enabled; --}; -- --/** -- * struct mt7621_pcie - PCIe host information -- * @base: IO Mapped Register Base -- * @dev: Pointer to PCIe device -- * @ports: pointer to PCIe port information -- * @resets_inverted: depends on chip revision -- * reset lines are inverted. -- */ --struct mt7621_pcie { -- struct device *dev; -- void __iomem *base; -- struct list_head ports; -- bool resets_inverted; --}; -- --static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg) --{ -- return readl_relaxed(pcie->base + reg); --} -- --static inline void pcie_write(struct mt7621_pcie *pcie, u32 val, u32 reg) --{ -- writel_relaxed(val, pcie->base + reg); --} -- --static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set) --{ -- u32 val = readl_relaxed(pcie->base + reg); -- -- val &= ~clr; -- val |= set; -- writel_relaxed(val, pcie->base + reg); --} -- --static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg) --{ -- return readl_relaxed(port->base + reg); --} -- --static inline void pcie_port_write(struct mt7621_pcie_port *port, -- u32 val, u32 reg) --{ -- writel_relaxed(val, port->base + reg); --} -- --static inline u32 mt7621_pcie_get_cfgaddr(unsigned int bus, unsigned int slot, -- unsigned int func, unsigned int where) --{ -- return (((where & 0xF00) >> 8) << 24) | (bus << 16) | (slot << 11) | -- (func << 8) | (where & 0xfc) | 0x80000000; --} -- --static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus, -- unsigned int devfn, int where) --{ -- struct mt7621_pcie *pcie = bus->sysdata; -- u32 address = mt7621_pcie_get_cfgaddr(bus->number, PCI_SLOT(devfn), -- PCI_FUNC(devfn), where); -- -- writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR); -- -- return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); --} -- --struct pci_ops mt7621_pcie_ops = { -- .map_bus = mt7621_pcie_map_bus, -- .read = pci_generic_config_read, -- .write = pci_generic_config_write, --}; -- --static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg) --{ -- u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); -- -- pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); -- return pcie_read(pcie, RALINK_PCI_CONFIG_DATA); --} -- --static void write_config(struct mt7621_pcie *pcie, unsigned int dev, -- u32 reg, u32 val) --{ -- u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); -- -- pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); -- pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); --} -- --static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port) --{ -- if (port->gpio_rst) -- gpiod_set_value(port->gpio_rst, 1); --} -- --static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port) --{ -- if (port->gpio_rst) -- gpiod_set_value(port->gpio_rst, 0); --} -- --static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port) --{ -- return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0; --} -- --static inline void mt7621_control_assert(struct mt7621_pcie_port *port) --{ -- struct mt7621_pcie *pcie = port->pcie; -- -- if (pcie->resets_inverted) -- reset_control_assert(port->pcie_rst); -- else -- reset_control_deassert(port->pcie_rst); --} -- --static inline void mt7621_control_deassert(struct mt7621_pcie_port *port) --{ -- struct mt7621_pcie *pcie = port->pcie; -- -- if (pcie->resets_inverted) -- reset_control_deassert(port->pcie_rst); -- else -- reset_control_assert(port->pcie_rst); --} -- --static int setup_cm_memory_region(struct pci_host_bridge *host) --{ -- struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -- struct device *dev = pcie->dev; -- struct resource_entry *entry; -- resource_size_t mask; -- -- entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); -- if (!entry) { -- dev_err(dev, "Cannot get memory resource\n"); -- return -EINVAL; -- } -- -- if (mips_cps_numiocu(0)) { -- /* -- * FIXME: hardware doesn't accept mask values with 1s after -- * 0s (e.g. 0xffef), so it would be great to warn if that's -- * about to happen -- */ -- mask = ~(entry->res->end - entry->res->start); -- -- write_gcr_reg1_base(entry->res->start); -- write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); -- dev_info(dev, "PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n", -- (unsigned long long)read_gcr_reg1_base(), -- (unsigned long long)read_gcr_reg1_mask()); -- } -- -- return 0; --} -- --static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, -- struct device_node *node, -- int slot) --{ -- struct mt7621_pcie_port *port; -- struct device *dev = pcie->dev; -- struct platform_device *pdev = to_platform_device(dev); -- char name[10]; -- int err; -- -- port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); -- if (!port) -- return -ENOMEM; -- -- port->base = devm_platform_ioremap_resource(pdev, slot + 1); -- if (IS_ERR(port->base)) -- return PTR_ERR(port->base); -- -- port->clk = devm_get_clk_from_child(dev, node, NULL); -- if (IS_ERR(port->clk)) { -- dev_err(dev, "failed to get pcie%d clock\n", slot); -- return PTR_ERR(port->clk); -- } -- -- port->pcie_rst = of_reset_control_get_exclusive(node, NULL); -- if (PTR_ERR(port->pcie_rst) == -EPROBE_DEFER) { -- dev_err(dev, "failed to get pcie%d reset control\n", slot); -- return PTR_ERR(port->pcie_rst); -- } -- -- snprintf(name, sizeof(name), "pcie-phy%d", slot); -- port->phy = devm_of_phy_get(dev, node, name); -- if (IS_ERR(port->phy)) { -- dev_err(dev, "failed to get pcie-phy%d\n", slot); -- err = PTR_ERR(port->phy); -- goto remove_reset; -- } -- -- port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, -- GPIOD_OUT_LOW); -- if (IS_ERR(port->gpio_rst)) { -- dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot); -- err = PTR_ERR(port->gpio_rst); -- goto remove_reset; -- } -- -- port->slot = slot; -- port->pcie = pcie; -- -- INIT_LIST_HEAD(&port->list); -- list_add_tail(&port->list, &pcie->ports); -- -- return 0; -- --remove_reset: -- reset_control_put(port->pcie_rst); -- return err; --} -- --static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) --{ -- struct device *dev = pcie->dev; -- struct platform_device *pdev = to_platform_device(dev); -- struct device_node *node = dev->of_node, *child; -- int err; -- -- pcie->base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(pcie->base)) -- return PTR_ERR(pcie->base); -- -- for_each_available_child_of_node(node, child) { -- int slot; -- -- err = of_pci_get_devfn(child); -- if (err < 0) { -- of_node_put(child); -- dev_err(dev, "failed to parse devfn: %d\n", err); -- return err; -- } -- -- slot = PCI_SLOT(err); -- -- err = mt7621_pcie_parse_port(pcie, child, slot); -- if (err) { -- of_node_put(child); -- return err; -- } -- } -- -- return 0; --} -- --static int mt7621_pcie_init_port(struct mt7621_pcie_port *port) --{ -- struct mt7621_pcie *pcie = port->pcie; -- struct device *dev = pcie->dev; -- u32 slot = port->slot; -- int err; -- -- err = phy_init(port->phy); -- if (err) { -- dev_err(dev, "failed to initialize port%d phy\n", slot); -- return err; -- } -- -- err = phy_power_on(port->phy); -- if (err) { -- dev_err(dev, "failed to power on port%d phy\n", slot); -- phy_exit(port->phy); -- return err; -- } -- -- port->enabled = true; -- -- return 0; --} -- --static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie) --{ -- struct mt7621_pcie_port *port; -- -- list_for_each_entry(port, &pcie->ports, list) { -- /* PCIe RC reset assert */ -- mt7621_control_assert(port); -- -- /* PCIe EP reset assert */ -- mt7621_rst_gpio_pcie_assert(port); -- } -- -- msleep(PERST_DELAY_MS); --} -- --static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) --{ -- struct mt7621_pcie_port *port; -- -- list_for_each_entry(port, &pcie->ports, list) -- mt7621_control_deassert(port); --} -- --static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie) --{ -- struct mt7621_pcie_port *port; -- -- list_for_each_entry(port, &pcie->ports, list) -- mt7621_rst_gpio_pcie_deassert(port); -- -- msleep(PERST_DELAY_MS); --} -- --static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie) --{ -- struct device *dev = pcie->dev; -- struct mt7621_pcie_port *port, *tmp; -- u8 num_disabled = 0; -- int err; -- -- mt7621_pcie_reset_assert(pcie); -- mt7621_pcie_reset_rc_deassert(pcie); -- -- list_for_each_entry_safe(port, tmp, &pcie->ports, list) { -- u32 slot = port->slot; -- -- if (slot == 1) { -- port->enabled = true; -- continue; -- } -- -- err = mt7621_pcie_init_port(port); -- if (err) { -- dev_err(dev, "Initiating port %d failed\n", slot); -- list_del(&port->list); -- } -- } -- -- mt7621_pcie_reset_ep_deassert(pcie); -- -- tmp = NULL; -- list_for_each_entry(port, &pcie->ports, list) { -- u32 slot = port->slot; -- -- if (!mt7621_pcie_port_is_linkup(port)) { -- dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", -- slot); -- mt7621_control_assert(port); -- port->enabled = false; -- num_disabled++; -- -- if (slot == 0) { -- tmp = port; -- continue; -- } -- -- if (slot == 1 && tmp && !tmp->enabled) -- phy_power_off(tmp->phy); -- } -- } -- -- return (num_disabled != PCIE_PORT_CNT) ? 0 : -ENODEV; --} -- --static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) --{ -- struct mt7621_pcie *pcie = port->pcie; -- u32 slot = port->slot; -- u32 val; -- -- /* enable pcie interrupt */ -- val = pcie_read(pcie, RALINK_PCI_PCIMSK_ADDR); -- val |= PCIE_PORT_INT_EN(slot); -- pcie_write(pcie, val, RALINK_PCI_PCIMSK_ADDR); -- -- /* map 2G DDR region */ -- pcie_port_write(port, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, -- PCI_BASE_ADDRESS_0); -- -- /* configure class code and revision ID */ -- pcie_port_write(port, PCIE_CLASS_CODE | PCIE_REVISION_ID, -- RALINK_PCI_CLASS); -- -- /* configure RC FTS number to 250 when it leaves L0s */ -- val = read_config(pcie, slot, PCIE_FTS_NUM); -- val &= ~PCIE_FTS_NUM_MASK; -- val |= PCIE_FTS_NUM_L0(0x50); -- write_config(pcie, slot, PCIE_FTS_NUM, val); --} -- --static int mt7621_pcie_enable_ports(struct pci_host_bridge *host) --{ -- struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -- struct device *dev = pcie->dev; -- struct mt7621_pcie_port *port; -- struct resource_entry *entry; -- int err; -- -- entry = resource_list_first_type(&host->windows, IORESOURCE_IO); -- if (!entry) { -- dev_err(dev, "Cannot get io resource\n"); -- return -EINVAL; -- } -- -- /* Setup MEMWIN and IOWIN */ -- pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE); -- pcie_write(pcie, entry->res->start, RALINK_PCI_IOBASE); -- -- list_for_each_entry(port, &pcie->ports, list) { -- if (port->enabled) { -- err = clk_prepare_enable(port->clk); -- if (err) { -- dev_err(dev, "enabling clk pcie%d\n", -- port->slot); -- return err; -- } -- -- mt7621_pcie_enable_port(port); -- dev_info(dev, "PCIE%d enabled\n", port->slot); -- } -- } -- -- return 0; --} -- --static int mt7621_pcie_register_host(struct pci_host_bridge *host) --{ -- struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -- -- host->ops = &mt7621_pcie_ops; -- host->sysdata = pcie; -- return pci_host_probe(host); --} -- --static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { -- { .soc_id = "mt7621", .revision = "E2" }, -- { /* sentinel */ } --}; -- --static int mt7621_pcie_probe(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- const struct soc_device_attribute *attr; -- struct mt7621_pcie_port *port; -- struct mt7621_pcie *pcie; -- struct pci_host_bridge *bridge; -- int err; -- -- if (!dev->of_node) -- return -ENODEV; -- -- bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); -- if (!bridge) -- return -ENOMEM; -- -- pcie = pci_host_bridge_priv(bridge); -- pcie->dev = dev; -- platform_set_drvdata(pdev, pcie); -- INIT_LIST_HEAD(&pcie->ports); -- -- attr = soc_device_match(mt7621_pcie_quirks_match); -- if (attr) -- pcie->resets_inverted = true; -- -- err = mt7621_pcie_parse_dt(pcie); -- if (err) { -- dev_err(dev, "Parsing DT failed\n"); -- return err; -- } -- -- err = mt7621_pcie_init_ports(pcie); -- if (err) { -- dev_err(dev, "Nothing connected in virtual bridges\n"); -- return 0; -- } -- -- err = mt7621_pcie_enable_ports(bridge); -- if (err) { -- dev_err(dev, "Error enabling pcie ports\n"); -- goto remove_resets; -- } -- -- err = setup_cm_memory_region(bridge); -- if (err) { -- dev_err(dev, "Error setting up iocu mem regions\n"); -- goto remove_resets; -- } -- -- return mt7621_pcie_register_host(bridge); -- --remove_resets: -- list_for_each_entry(port, &pcie->ports, list) -- reset_control_put(port->pcie_rst); -- -- return err; --} -- --static int mt7621_pcie_remove(struct platform_device *pdev) --{ -- struct mt7621_pcie *pcie = platform_get_drvdata(pdev); -- struct mt7621_pcie_port *port; -- -- list_for_each_entry(port, &pcie->ports, list) -- reset_control_put(port->pcie_rst); -- -- return 0; --} -- --static const struct of_device_id mt7621_pcie_ids[] = { -- { .compatible = "mediatek,mt7621-pci" }, -- {}, --}; --MODULE_DEVICE_TABLE(of, mt7621_pcie_ids); -- --static struct platform_driver mt7621_pcie_driver = { -- .probe = mt7621_pcie_probe, -- .remove = mt7621_pcie_remove, -- .driver = { -- .name = "mt7621-pci", -- .of_match_table = of_match_ptr(mt7621_pcie_ids), -- }, --}; --builtin_platform_driver(mt7621_pcie_driver); ---- /dev/null -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -0,0 +1,600 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * BRIEF MODULE DESCRIPTION -+ * PCI init for Ralink RT2880 solution -+ * -+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) -+ * -+ * May 2007 Bruce Chang -+ * Initial Release -+ * -+ * May 2009 Bruce Chang -+ * support RT2880/RT3883 PCIe -+ * -+ * May 2011 Bruce Chang -+ * support RT6855/MT7620 PCIe -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* MediaTek-specific configuration registers */ -+#define PCIE_FTS_NUM 0x70c -+#define PCIE_FTS_NUM_MASK GENMASK(15, 8) -+#define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8) -+ -+/* Host-PCI bridge registers */ -+#define RALINK_PCI_PCICFG_ADDR 0x0000 -+#define RALINK_PCI_PCIMSK_ADDR 0x000c -+#define RALINK_PCI_CONFIG_ADDR 0x0020 -+#define RALINK_PCI_CONFIG_DATA 0x0024 -+#define RALINK_PCI_MEMBASE 0x0028 -+#define RALINK_PCI_IOBASE 0x002c -+ -+/* PCIe RC control registers */ -+#define RALINK_PCI_ID 0x0030 -+#define RALINK_PCI_CLASS 0x0034 -+#define RALINK_PCI_SUBID 0x0038 -+#define RALINK_PCI_STATUS 0x0050 -+ -+/* Some definition values */ -+#define PCIE_REVISION_ID BIT(0) -+#define PCIE_CLASS_CODE (0x60400 << 8) -+#define PCIE_BAR_MAP_MAX GENMASK(30, 16) -+#define PCIE_BAR_ENABLE BIT(0) -+#define PCIE_PORT_INT_EN(x) BIT(20 + (x)) -+#define PCIE_PORT_LINKUP BIT(0) -+#define PCIE_PORT_CNT 3 -+ -+#define PERST_DELAY_MS 100 -+ -+/** -+ * struct mt7621_pcie_port - PCIe port information -+ * @base: I/O mapped register base -+ * @list: port list -+ * @pcie: pointer to PCIe host info -+ * @clk: pointer to the port clock gate -+ * @phy: pointer to PHY control block -+ * @pcie_rst: pointer to port reset control -+ * @gpio_rst: gpio reset -+ * @slot: port slot -+ * @enabled: indicates if port is enabled -+ */ -+struct mt7621_pcie_port { -+ void __iomem *base; -+ struct list_head list; -+ struct mt7621_pcie *pcie; -+ struct clk *clk; -+ struct phy *phy; -+ struct reset_control *pcie_rst; -+ struct gpio_desc *gpio_rst; -+ u32 slot; -+ bool enabled; -+}; -+ -+/** -+ * struct mt7621_pcie - PCIe host information -+ * @base: IO Mapped Register Base -+ * @dev: Pointer to PCIe device -+ * @ports: pointer to PCIe port information -+ * @resets_inverted: depends on chip revision -+ * reset lines are inverted. -+ */ -+struct mt7621_pcie { -+ void __iomem *base; -+ struct device *dev; -+ struct list_head ports; -+ bool resets_inverted; -+}; -+ -+static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg) -+{ -+ return readl_relaxed(pcie->base + reg); -+} -+ -+static inline void pcie_write(struct mt7621_pcie *pcie, u32 val, u32 reg) -+{ -+ writel_relaxed(val, pcie->base + reg); -+} -+ -+static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set) -+{ -+ u32 val = readl_relaxed(pcie->base + reg); -+ -+ val &= ~clr; -+ val |= set; -+ writel_relaxed(val, pcie->base + reg); -+} -+ -+static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg) -+{ -+ return readl_relaxed(port->base + reg); -+} -+ -+static inline void pcie_port_write(struct mt7621_pcie_port *port, -+ u32 val, u32 reg) -+{ -+ writel_relaxed(val, port->base + reg); -+} -+ -+static inline u32 mt7621_pci_get_cfgaddr(unsigned int bus, unsigned int slot, -+ unsigned int func, unsigned int where) -+{ -+ return (((where & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | -+ (func << 8) | (where & 0xfc) | 0x80000000; -+} -+ -+static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus, -+ unsigned int devfn, int where) -+{ -+ struct mt7621_pcie *pcie = bus->sysdata; -+ u32 address = mt7621_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ PCI_FUNC(devfn), where); -+ -+ writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR); -+ -+ return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); -+} -+ -+struct pci_ops mt7621_pci_ops = { -+ .map_bus = mt7621_pcie_map_bus, -+ .read = pci_generic_config_read, -+ .write = pci_generic_config_write, -+}; -+ -+static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg) -+{ -+ u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); -+ -+ pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); -+ return pcie_read(pcie, RALINK_PCI_CONFIG_DATA); -+} -+ -+static void write_config(struct mt7621_pcie *pcie, unsigned int dev, -+ u32 reg, u32 val) -+{ -+ u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); -+ -+ pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); -+ pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); -+} -+ -+static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port) -+{ -+ if (port->gpio_rst) -+ gpiod_set_value(port->gpio_rst, 1); -+} -+ -+static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port) -+{ -+ if (port->gpio_rst) -+ gpiod_set_value(port->gpio_rst, 0); -+} -+ -+static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port) -+{ -+ return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0; -+} -+ -+static inline void mt7621_control_assert(struct mt7621_pcie_port *port) -+{ -+ struct mt7621_pcie *pcie = port->pcie; -+ -+ if (pcie->resets_inverted) -+ reset_control_assert(port->pcie_rst); -+ else -+ reset_control_deassert(port->pcie_rst); -+} -+ -+static inline void mt7621_control_deassert(struct mt7621_pcie_port *port) -+{ -+ struct mt7621_pcie *pcie = port->pcie; -+ -+ if (pcie->resets_inverted) -+ reset_control_deassert(port->pcie_rst); -+ else -+ reset_control_assert(port->pcie_rst); -+} -+ -+static int setup_cm_memory_region(struct pci_host_bridge *host) -+{ -+ struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -+ struct device *dev = pcie->dev; -+ struct resource_entry *entry; -+ resource_size_t mask; -+ -+ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); -+ if (!entry) { -+ dev_err(dev, "cannot get memory resource\n"); -+ return -EINVAL; -+ } -+ -+ if (mips_cps_numiocu(0)) { -+ /* -+ * FIXME: hardware doesn't accept mask values with 1s after -+ * 0s (e.g. 0xffef), so it would be great to warn if that's -+ * about to happen -+ */ -+ mask = ~(entry->res->end - entry->res->start); -+ -+ write_gcr_reg1_base(entry->res->start); -+ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); -+ dev_info(dev, "PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n", -+ (unsigned long long)read_gcr_reg1_base(), -+ (unsigned long long)read_gcr_reg1_mask()); -+ } -+ -+ return 0; -+} -+ -+static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, -+ struct device_node *node, -+ int slot) -+{ -+ struct mt7621_pcie_port *port; -+ struct device *dev = pcie->dev; -+ struct platform_device *pdev = to_platform_device(dev); -+ char name[10]; -+ int err; -+ -+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); -+ if (!port) -+ return -ENOMEM; -+ -+ port->base = devm_platform_ioremap_resource(pdev, slot + 1); -+ if (IS_ERR(port->base)) -+ return PTR_ERR(port->base); -+ -+ port->clk = devm_get_clk_from_child(dev, node, NULL); -+ if (IS_ERR(port->clk)) { -+ dev_err(dev, "failed to get pcie%d clock\n", slot); -+ return PTR_ERR(port->clk); -+ } -+ -+ port->pcie_rst = of_reset_control_get_exclusive(node, NULL); -+ if (PTR_ERR(port->pcie_rst) == -EPROBE_DEFER) { -+ dev_err(dev, "failed to get pcie%d reset control\n", slot); -+ return PTR_ERR(port->pcie_rst); -+ } -+ -+ snprintf(name, sizeof(name), "pcie-phy%d", slot); -+ port->phy = devm_of_phy_get(dev, node, name); -+ if (IS_ERR(port->phy)) { -+ dev_err(dev, "failed to get pcie-phy%d\n", slot); -+ err = PTR_ERR(port->phy); -+ goto remove_reset; -+ } -+ -+ port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, -+ GPIOD_OUT_LOW); -+ if (IS_ERR(port->gpio_rst)) { -+ dev_err(dev, "failed to get GPIO for PCIe%d\n", slot); -+ err = PTR_ERR(port->gpio_rst); -+ goto remove_reset; -+ } -+ -+ port->slot = slot; -+ port->pcie = pcie; -+ -+ INIT_LIST_HEAD(&port->list); -+ list_add_tail(&port->list, &pcie->ports); -+ -+ return 0; -+ -+remove_reset: -+ reset_control_put(port->pcie_rst); -+ return err; -+} -+ -+static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) -+{ -+ struct device *dev = pcie->dev; -+ struct platform_device *pdev = to_platform_device(dev); -+ struct device_node *node = dev->of_node, *child; -+ int err; -+ -+ pcie->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(pcie->base)) -+ return PTR_ERR(pcie->base); -+ -+ for_each_available_child_of_node(node, child) { -+ int slot; -+ -+ err = of_pci_get_devfn(child); -+ if (err < 0) { -+ of_node_put(child); -+ dev_err(dev, "failed to parse devfn: %d\n", err); -+ return err; -+ } -+ -+ slot = PCI_SLOT(err); -+ -+ err = mt7621_pcie_parse_port(pcie, child, slot); -+ if (err) { -+ of_node_put(child); -+ return err; -+ } -+ } -+ -+ return 0; -+} -+ -+static int mt7621_pcie_init_port(struct mt7621_pcie_port *port) -+{ -+ struct mt7621_pcie *pcie = port->pcie; -+ struct device *dev = pcie->dev; -+ u32 slot = port->slot; -+ int err; -+ -+ err = phy_init(port->phy); -+ if (err) { -+ dev_err(dev, "failed to initialize port%d phy\n", slot); -+ return err; -+ } -+ -+ err = phy_power_on(port->phy); -+ if (err) { -+ dev_err(dev, "failed to power on port%d phy\n", slot); -+ phy_exit(port->phy); -+ return err; -+ } -+ -+ port->enabled = true; -+ -+ return 0; -+} -+ -+static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie) -+{ -+ struct mt7621_pcie_port *port; -+ -+ list_for_each_entry(port, &pcie->ports, list) { -+ /* PCIe RC reset assert */ -+ mt7621_control_assert(port); -+ -+ /* PCIe EP reset assert */ -+ mt7621_rst_gpio_pcie_assert(port); -+ } -+ -+ msleep(PERST_DELAY_MS); -+} -+ -+static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) -+{ -+ struct mt7621_pcie_port *port; -+ -+ list_for_each_entry(port, &pcie->ports, list) -+ mt7621_control_deassert(port); -+} -+ -+static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie) -+{ -+ struct mt7621_pcie_port *port; -+ -+ list_for_each_entry(port, &pcie->ports, list) -+ mt7621_rst_gpio_pcie_deassert(port); -+ -+ msleep(PERST_DELAY_MS); -+} -+ -+static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie) -+{ -+ struct device *dev = pcie->dev; -+ struct mt7621_pcie_port *port, *tmp; -+ u8 num_disabled = 0; -+ int err; -+ -+ mt7621_pcie_reset_assert(pcie); -+ mt7621_pcie_reset_rc_deassert(pcie); -+ -+ list_for_each_entry_safe(port, tmp, &pcie->ports, list) { -+ u32 slot = port->slot; -+ -+ if (slot == 1) { -+ port->enabled = true; -+ continue; -+ } -+ -+ err = mt7621_pcie_init_port(port); -+ if (err) { -+ dev_err(dev, "initializing port %d failed\n", slot); -+ list_del(&port->list); -+ } -+ } -+ -+ mt7621_pcie_reset_ep_deassert(pcie); -+ -+ tmp = NULL; -+ list_for_each_entry(port, &pcie->ports, list) { -+ u32 slot = port->slot; -+ -+ if (!mt7621_pcie_port_is_linkup(port)) { -+ dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", -+ slot); -+ mt7621_control_assert(port); -+ port->enabled = false; -+ num_disabled++; -+ -+ if (slot == 0) { -+ tmp = port; -+ continue; -+ } -+ -+ if (slot == 1 && tmp && !tmp->enabled) -+ phy_power_off(tmp->phy); -+ } -+ } -+ -+ return (num_disabled != PCIE_PORT_CNT) ? 0 : -ENODEV; -+} -+ -+static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) -+{ -+ struct mt7621_pcie *pcie = port->pcie; -+ u32 slot = port->slot; -+ u32 val; -+ -+ /* enable pcie interrupt */ -+ val = pcie_read(pcie, RALINK_PCI_PCIMSK_ADDR); -+ val |= PCIE_PORT_INT_EN(slot); -+ pcie_write(pcie, val, RALINK_PCI_PCIMSK_ADDR); -+ -+ /* map 2G DDR region */ -+ pcie_port_write(port, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, -+ PCI_BASE_ADDRESS_0); -+ -+ /* configure class code and revision ID */ -+ pcie_port_write(port, PCIE_CLASS_CODE | PCIE_REVISION_ID, -+ RALINK_PCI_CLASS); -+ -+ /* configure RC FTS number to 250 when it leaves L0s */ -+ val = read_config(pcie, slot, PCIE_FTS_NUM); -+ val &= ~PCIE_FTS_NUM_MASK; -+ val |= PCIE_FTS_NUM_L0(0x50); -+ write_config(pcie, slot, PCIE_FTS_NUM, val); -+} -+ -+static int mt7621_pcie_enable_ports(struct pci_host_bridge *host) -+{ -+ struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -+ struct device *dev = pcie->dev; -+ struct mt7621_pcie_port *port; -+ struct resource_entry *entry; -+ int err; -+ -+ entry = resource_list_first_type(&host->windows, IORESOURCE_IO); -+ if (!entry) { -+ dev_err(dev, "cannot get io resource\n"); -+ return -EINVAL; -+ } -+ -+ /* Setup MEMWIN and IOWIN */ -+ pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE); -+ pcie_write(pcie, entry->res->start, RALINK_PCI_IOBASE); -+ -+ list_for_each_entry(port, &pcie->ports, list) { -+ if (port->enabled) { -+ err = clk_prepare_enable(port->clk); -+ if (err) { -+ dev_err(dev, "enabling clk pcie%d\n", -+ port->slot); -+ return err; -+ } -+ -+ mt7621_pcie_enable_port(port); -+ dev_info(dev, "PCIE%d enabled\n", port->slot); -+ } -+ } -+ -+ return 0; -+} -+ -+static int mt7621_pcie_register_host(struct pci_host_bridge *host) -+{ -+ struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -+ -+ host->ops = &mt7621_pci_ops; -+ host->sysdata = pcie; -+ return pci_host_probe(host); -+} -+ -+static const struct soc_device_attribute mt7621_pci_quirks_match[] = { -+ { .soc_id = "mt7621", .revision = "E2" } -+}; -+ -+static int mt7621_pci_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct soc_device_attribute *attr; -+ struct mt7621_pcie_port *port; -+ struct mt7621_pcie *pcie; -+ struct pci_host_bridge *bridge; -+ int err; -+ -+ if (!dev->of_node) -+ return -ENODEV; -+ -+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); -+ if (!bridge) -+ return -ENOMEM; -+ -+ pcie = pci_host_bridge_priv(bridge); -+ pcie->dev = dev; -+ platform_set_drvdata(pdev, pcie); -+ INIT_LIST_HEAD(&pcie->ports); -+ -+ attr = soc_device_match(mt7621_pci_quirks_match); -+ if (attr) -+ pcie->resets_inverted = true; -+ -+ err = mt7621_pcie_parse_dt(pcie); -+ if (err) { -+ dev_err(dev, "parsing DT failed\n"); -+ return err; -+ } -+ -+ err = mt7621_pcie_init_ports(pcie); -+ if (err) { -+ dev_err(dev, "nothing connected in virtual bridges\n"); -+ return 0; -+ } -+ -+ err = mt7621_pcie_enable_ports(bridge); -+ if (err) { -+ dev_err(dev, "error enabling pcie ports\n"); -+ goto remove_resets; -+ } -+ -+ err = setup_cm_memory_region(bridge); -+ if (err) { -+ dev_err(dev, "error setting up iocu mem regions\n"); -+ goto remove_resets; -+ } -+ -+ return mt7621_pcie_register_host(bridge); -+ -+remove_resets: -+ list_for_each_entry(port, &pcie->ports, list) -+ reset_control_put(port->pcie_rst); -+ -+ return err; -+} -+ -+static int mt7621_pci_remove(struct platform_device *pdev) -+{ -+ struct mt7621_pcie *pcie = platform_get_drvdata(pdev); -+ struct mt7621_pcie_port *port; -+ -+ list_for_each_entry(port, &pcie->ports, list) -+ reset_control_put(port->pcie_rst); -+ -+ return 0; -+} -+ -+static const struct of_device_id mt7621_pci_ids[] = { -+ { .compatible = "mediatek,mt7621-pci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mt7621_pci_ids); -+ -+static struct platform_driver mt7621_pci_driver = { -+ .probe = mt7621_pci_probe, -+ .remove = mt7621_pci_remove, -+ .driver = { -+ .name = "mt7621-pci", -+ .of_match_table = of_match_ptr(mt7621_pci_ids), -+ }, -+}; -+builtin_platform_driver(mt7621_pci_driver); diff --git a/target/linux/ramips/patches-5.15/101-v5.17-PCI-mt7621-Rename-mt7621_pci_-to-mt7621_pcie_.patch b/target/linux/ramips/patches-5.15/101-v5.17-PCI-mt7621-Rename-mt7621_pci_-to-mt7621_pcie_.patch deleted file mode 100644 index 916477511d..0000000000 --- a/target/linux/ramips/patches-5.15/101-v5.17-PCI-mt7621-Rename-mt7621_pci_-to-mt7621_pcie_.patch +++ /dev/null @@ -1,134 +0,0 @@ -From: Bjorn Helgaas -Date: Wed, 22 Dec 2021 19:10:48 -0600 -Subject: [PATCH] PCI: mt7621: Rename mt7621_pci_ to mt7621_pcie_ - -Rename mt7621_pci_* structs and functions to mt7621_pcie_* for consistency -with the rest of the file. - -Link: https://lore.kernel.org/r/20211223011054.1227810-18-helgaas@kernel.org -Signed-off-by: Bjorn Helgaas -Reviewed-by: Sergio Paracuellos -Cc: Matthias Brugger ---- - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -93,8 +93,8 @@ struct mt7621_pcie_port { - * reset lines are inverted. - */ - struct mt7621_pcie { -- void __iomem *base; - struct device *dev; -+ void __iomem *base; - struct list_head ports; - bool resets_inverted; - }; -@@ -129,7 +129,7 @@ static inline void pcie_port_write(struc - writel_relaxed(val, port->base + reg); - } - --static inline u32 mt7621_pci_get_cfgaddr(unsigned int bus, unsigned int slot, -+static inline u32 mt7621_pcie_get_cfgaddr(unsigned int bus, unsigned int slot, - unsigned int func, unsigned int where) - { - return (((where & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | -@@ -140,7 +140,7 @@ static void __iomem *mt7621_pcie_map_bus - unsigned int devfn, int where) - { - struct mt7621_pcie *pcie = bus->sysdata; -- u32 address = mt7621_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), -+ u32 address = mt7621_pcie_get_cfgaddr(bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where); - - writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR); -@@ -148,7 +148,7 @@ static void __iomem *mt7621_pcie_map_bus - return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); - } - --struct pci_ops mt7621_pci_ops = { -+struct pci_ops mt7621_pcie_ops = { - .map_bus = mt7621_pcie_map_bus, - .read = pci_generic_config_read, - .write = pci_generic_config_write, -@@ -156,7 +156,7 @@ struct pci_ops mt7621_pci_ops = { - - static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg) - { -- u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); -+ u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); - - pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); - return pcie_read(pcie, RALINK_PCI_CONFIG_DATA); -@@ -165,7 +165,7 @@ static u32 read_config(struct mt7621_pci - static void write_config(struct mt7621_pcie *pcie, unsigned int dev, - u32 reg, u32 val) - { -- u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); -+ u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); - - pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); - pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); -@@ -505,16 +505,16 @@ static int mt7621_pcie_register_host(str - { - struct mt7621_pcie *pcie = pci_host_bridge_priv(host); - -- host->ops = &mt7621_pci_ops; -+ host->ops = &mt7621_pcie_ops; - host->sysdata = pcie; - return pci_host_probe(host); - } - --static const struct soc_device_attribute mt7621_pci_quirks_match[] = { -+static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { - { .soc_id = "mt7621", .revision = "E2" } - }; - --static int mt7621_pci_probe(struct platform_device *pdev) -+static int mt7621_pcie_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - const struct soc_device_attribute *attr; -@@ -535,7 +535,7 @@ static int mt7621_pci_probe(struct platf - platform_set_drvdata(pdev, pcie); - INIT_LIST_HEAD(&pcie->ports); - -- attr = soc_device_match(mt7621_pci_quirks_match); -+ attr = soc_device_match(mt7621_pcie_quirks_match); - if (attr) - pcie->resets_inverted = true; - -@@ -572,7 +572,7 @@ remove_resets: - return err; - } - --static int mt7621_pci_remove(struct platform_device *pdev) -+static int mt7621_pcie_remove(struct platform_device *pdev) - { - struct mt7621_pcie *pcie = platform_get_drvdata(pdev); - struct mt7621_pcie_port *port; -@@ -583,18 +583,18 @@ static int mt7621_pci_remove(struct plat - return 0; - } - --static const struct of_device_id mt7621_pci_ids[] = { -+static const struct of_device_id mt7621_pcie_ids[] = { - { .compatible = "mediatek,mt7621-pci" }, - {}, - }; --MODULE_DEVICE_TABLE(of, mt7621_pci_ids); -+MODULE_DEVICE_TABLE(of, mt7621_pcie_ids); - --static struct platform_driver mt7621_pci_driver = { -- .probe = mt7621_pci_probe, -- .remove = mt7621_pci_remove, -+static struct platform_driver mt7621_pcie_driver = { -+ .probe = mt7621_pcie_probe, -+ .remove = mt7621_pcie_remove, - .driver = { - .name = "mt7621-pci", -- .of_match_table = of_match_ptr(mt7621_pci_ids), -+ .of_match_table = of_match_ptr(mt7621_pcie_ids), - }, - }; --builtin_platform_driver(mt7621_pci_driver); -+builtin_platform_driver(mt7621_pcie_driver); diff --git a/target/linux/ramips/patches-5.15/102-v5.17-PCI-mt7621-Declare-mt7621_pci_ops-static.patch b/target/linux/ramips/patches-5.15/102-v5.17-PCI-mt7621-Declare-mt7621_pci_ops-static.patch deleted file mode 100644 index 815ecc7d37..0000000000 --- a/target/linux/ramips/patches-5.15/102-v5.17-PCI-mt7621-Declare-mt7621_pci_ops-static.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Sergio Paracuellos -Date: Wed, 17 Nov 2021 16:29:52 +0100 -Subject: [PATCH] PCI: mt7621: Declare mt7621_pci_ops static -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Sparse complains about mt7621_pci_ops symbol is not declared and asks if -it should be declared as static instead. Sparse is right. Hence declare -symbol as static. - -Link: https://lore.kernel.org/r/20211117152952.12271-1-sergio.paracuellos@gmail.com -Reported-by: kernel test robot -Signed-off-by: Sergio Paracuellos -Signed-off-by: Lorenzo Pieralisi -Signed-off-by: Bjorn Helgaas -Reviewed-by: Krzysztof Wilczyński ---- - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -148,7 +148,7 @@ static void __iomem *mt7621_pcie_map_bus - return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); - } - --struct pci_ops mt7621_pcie_ops = { -+static struct pci_ops mt7621_pcie_ops = { - .map_bus = mt7621_pcie_map_bus, - .read = pci_generic_config_read, - .write = pci_generic_config_write, diff --git a/target/linux/ramips/patches-5.15/103-v5.17-PCI-mt7621-Move-MIPS-setup-to-pcibios_root_bridge_pr.patch b/target/linux/ramips/patches-5.15/103-v5.17-PCI-mt7621-Move-MIPS-setup-to-pcibios_root_bridge_pr.patch deleted file mode 100644 index 4b46b3e3f6..0000000000 --- a/target/linux/ramips/patches-5.15/103-v5.17-PCI-mt7621-Move-MIPS-setup-to-pcibios_root_bridge_pr.patch +++ /dev/null @@ -1,119 +0,0 @@ -From: Sergio Paracuellos -Date: Tue, 7 Dec 2021 11:49:21 +0100 -Subject: [PATCH] PCI: mt7621: Move MIPS setup to pcibios_root_bridge_prepare() - -On the MIPS ralink mt7621 platform, we need to set up I/O coherency units -based on the host bridge apertures. - -To remove this arch dependency from the driver itself, move the coherency -setup from the driver to pcibios_root_bridge_prepare(). - -[bhelgaas: squash add/remove into one patch, commit log] -Link: https://lore.kernel.org/r/20211207104924.21327-3-sergio.paracuellos@gmail.com -Link: https://lore.kernel.org/r/20211207104924.21327-4-sergio.paracuellos@gmail.com -Signed-off-by: Sergio Paracuellos -Signed-off-by: Bjorn Helgaas -Reviewed-by: Guenter Roeck # arch/mips -Acked-by: Thomas Bogendoerfer # arch/mips ---- - ---- a/arch/mips/ralink/mt7621.c -+++ b/arch/mips/ralink/mt7621.c -@@ -10,6 +10,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -25,6 +27,35 @@ - static u32 detect_magic __initdata; - static struct ralink_soc_info *soc_info_ptr; - -+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -+{ -+ struct resource_entry *entry; -+ resource_size_t mask; -+ -+ entry = resource_list_first_type(&bridge->windows, IORESOURCE_MEM); -+ if (!entry) { -+ pr_err("Cannot get memory resource\n"); -+ return -EINVAL; -+ } -+ -+ if (mips_cps_numiocu(0)) { -+ /* -+ * Hardware doesn't accept mask values with 1s after -+ * 0s (e.g. 0xffef), so warn if that's happen -+ */ -+ mask = ~(entry->res->end - entry->res->start) & CM_GCR_REGn_MASK_ADDRMASK; -+ WARN_ON(mask && BIT(ffz(~mask)) - 1 != ~mask); -+ -+ write_gcr_reg1_base(entry->res->start); -+ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); -+ pr_info("PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n", -+ (unsigned long long)read_gcr_reg1_base(), -+ (unsigned long long)read_gcr_reg1_mask()); -+ } -+ -+ return 0; -+} -+ - phys_addr_t mips_cpc_default_phys_base(void) - { - panic("Cannot detect cpc address"); ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -208,37 +208,6 @@ static inline void mt7621_control_deasse - reset_control_assert(port->pcie_rst); - } - --static int setup_cm_memory_region(struct pci_host_bridge *host) --{ -- struct mt7621_pcie *pcie = pci_host_bridge_priv(host); -- struct device *dev = pcie->dev; -- struct resource_entry *entry; -- resource_size_t mask; -- -- entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); -- if (!entry) { -- dev_err(dev, "cannot get memory resource\n"); -- return -EINVAL; -- } -- -- if (mips_cps_numiocu(0)) { -- /* -- * FIXME: hardware doesn't accept mask values with 1s after -- * 0s (e.g. 0xffef), so it would be great to warn if that's -- * about to happen -- */ -- mask = ~(entry->res->end - entry->res->start); -- -- write_gcr_reg1_base(entry->res->start); -- write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); -- dev_info(dev, "PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n", -- (unsigned long long)read_gcr_reg1_base(), -- (unsigned long long)read_gcr_reg1_mask()); -- } -- -- return 0; --} -- - static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, - struct device_node *node, - int slot) -@@ -557,12 +526,6 @@ static int mt7621_pcie_probe(struct plat - goto remove_resets; - } - -- err = setup_cm_memory_region(bridge); -- if (err) { -- dev_err(dev, "error setting up iocu mem regions\n"); -- goto remove_resets; -- } -- - return mt7621_pcie_register_host(bridge); - - remove_resets: diff --git a/target/linux/ramips/patches-5.15/104-v5.17-PCI-mt7621-Drop-of_match_ptr-to-avoid-unused-variabl.patch b/target/linux/ramips/patches-5.15/104-v5.17-PCI-mt7621-Drop-of_match_ptr-to-avoid-unused-variabl.patch deleted file mode 100644 index 0913a452c6..0000000000 --- a/target/linux/ramips/patches-5.15/104-v5.17-PCI-mt7621-Drop-of_match_ptr-to-avoid-unused-variabl.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Sergio Paracuellos -Date: Mon, 24 Jan 2022 12:30:02 +0100 -Subject: [PATCH] PCI: mt7621: Drop of_match_ptr() to avoid unused variable - -We have stubs for most OF interfaces even when CONFIG_OF is not set, so we -allow building of pcie-mt7621.c in that case for compile testing. - -When CONFIG_OF is not set, "of_match_ptr(mt7621_pcie_ids)" compiles to -NULL, which leaves mt7621_pcie_ids unused: - - $ make W=1 - drivers/pci/controller/pcie-mt7621.c:549:34: warning: unused variable 'mt7621_pcie_ids' [-Wunused-const-variable] - -Drop of_match_ptr() to avoid the unused variable warning. - -[bhelgaas: commit log] -Fixes: 2bdd5238e756 ("PCI: mt7621: Add MediaTek MT7621 PCIe host controller driver") -Link: https://lore.kernel.org/r/20220124113003.406224-2-sergio.paracuellos@gmail.com -Link: https://lore.kernel.org/r/202201241754.igtHzgHv-lkp@intel.com -Reported-by: kernel test robot -Signed-off-by: Sergio Paracuellos -Signed-off-by: Bjorn Helgaas ---- - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -557,7 +557,7 @@ static struct platform_driver mt7621_pci - .remove = mt7621_pcie_remove, - .driver = { - .name = "mt7621-pci", -- .of_match_table = of_match_ptr(mt7621_pcie_ids), -+ .of_match_table = mt7621_pcie_ids, - }, - }; - builtin_platform_driver(mt7621_pcie_driver); diff --git a/target/linux/ramips/patches-5.15/105-v5.17-PCI-mt7621-Remove-unused-function-pcie_rmw.patch b/target/linux/ramips/patches-5.15/105-v5.17-PCI-mt7621-Remove-unused-function-pcie_rmw.patch deleted file mode 100644 index 0323588e5a..0000000000 --- a/target/linux/ramips/patches-5.15/105-v5.17-PCI-mt7621-Remove-unused-function-pcie_rmw.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Sergio Paracuellos -Date: Mon, 24 Jan 2022 12:30:03 +0100 -Subject: [PATCH] PCI: mt7621: Remove unused function pcie_rmw() - -Function pcie_rmw() is not being used at all and can be deleted. Hence get -rid of it, which fixes this warning: - - drivers/pci/controller/pcie-mt7621.c:112:20: warning: unused function 'pcie_rmw' [-Wunused-function] - -Fixes: 2bdd5238e756 ("PCI: mt7621: Add MediaTek MT7621 PCIe host controller driver") -Link: https://lore.kernel.org/r/20220124113003.406224-3-sergio.paracuellos@gmail.com -Link: https://lore.kernel.org/all/202201241754.igtHzgHv-lkp@intel.com/ -Reported-by: kernel test robot -Signed-off-by: Sergio Paracuellos -Signed-off-by: Bjorn Helgaas ---- - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -109,15 +109,6 @@ static inline void pcie_write(struct mt7 - writel_relaxed(val, pcie->base + reg); - } - --static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set) --{ -- u32 val = readl_relaxed(pcie->base + reg); -- -- val &= ~clr; -- val |= set; -- writel_relaxed(val, pcie->base + reg); --} -- - static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg) - { - return readl_relaxed(port->base + reg); diff --git a/target/linux/ramips/patches-5.15/106-v5.17-PCI-Let-pcibios_root_bridge_prepare-access-bridge-wi.patch b/target/linux/ramips/patches-5.15/106-v5.17-PCI-Let-pcibios_root_bridge_prepare-access-bridge-wi.patch deleted file mode 100644 index 2fbbf9a7aa..0000000000 --- a/target/linux/ramips/patches-5.15/106-v5.17-PCI-Let-pcibios_root_bridge_prepare-access-bridge-wi.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Sergio Paracuellos -Date: Tue, 7 Dec 2021 11:49:20 +0100 -Subject: [PATCH] PCI: Let pcibios_root_bridge_prepare() access bridge->windows - -When pci_register_host_bridge() is called, bridge->windows are already -available. However these windows are being moved temporarily from there. - -To let pcibios_root_bridge_prepare() have access to these windows, move the -windows movement after calling this function. This is useful for the MIPS -ralink mt7621 platform so it can set up I/O coherence units and avoid -custom MIPS code in the mt7621 PCIe controller driver. - -Link: https://lore.kernel.org/r/20211207104924.21327-2-sergio.paracuellos@gmail.com -Signed-off-by: Sergio Paracuellos -Signed-off-by: Bjorn Helgaas -Acked-by: Arnd Bergmann ---- - ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -898,8 +898,6 @@ static int pci_register_host_bridge(stru - - bridge->bus = bus; - -- /* Temporarily move resources off the list */ -- list_splice_init(&bridge->windows, &resources); - bus->sysdata = bridge->sysdata; - bus->ops = bridge->ops; - bus->number = bus->busn_res.start = bridge->busnr; -@@ -925,6 +923,8 @@ static int pci_register_host_bridge(stru - if (err) - goto free; - -+ /* Temporarily move resources off the list */ -+ list_splice_init(&bridge->windows, &resources); - err = device_add(&bridge->dev); - if (err) { - put_device(&bridge->dev); diff --git a/target/linux/ramips/patches-5.15/107-v6.2-PCI-mt7621-Add-sentinel-to-quirks-table.patch b/target/linux/ramips/patches-5.15/107-v6.2-PCI-mt7621-Add-sentinel-to-quirks-table.patch deleted file mode 100644 index c055f0096d..0000000000 --- a/target/linux/ramips/patches-5.15/107-v6.2-PCI-mt7621-Add-sentinel-to-quirks-table.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 19098934f910b4d47cb30251dd39ffa57bef9523 Mon Sep 17 00:00:00 2001 -From: John Thomson -Date: Tue, 6 Dec 2022 06:46:45 +1000 -Subject: [PATCH] PCI: mt7621: Add sentinel to quirks table - -Current driver is missing a sentinel in the struct soc_device_attribute -array, which causes an oops when assessed by the -soc_device_match(mt7621_pcie_quirks_match) call. - -This was only exposed once the CONFIG_SOC_MT7621 mt7621 soc_dev_attr -was fixed to register the SOC as a device, in: - -commit 7c18b64bba3b ("mips: ralink: mt7621: do not use kzalloc too early") - -Fix it by adding the required sentinel. - -Link: https://lore.kernel.org/lkml/26ebbed1-0fe9-4af9-8466-65f841d0b382@app.fastmail.com -Link: https://lore.kernel.org/r/20221205204645.301301-1-git@johnthomson.fastmail.com.au -Fixes: b483b4e4d3f6 ("staging: mt7621-pci: add quirks for 'E2' revision using 'soc_device_attribute'") -Signed-off-by: John Thomson -Signed-off-by: Lorenzo Pieralisi -Acked-by: Sergio Paracuellos ---- - drivers/pci/controller/pcie-mt7621.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -471,7 +471,8 @@ static int mt7621_pcie_register_host(str - } - - static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { -- { .soc_id = "mt7621", .revision = "E2" } -+ { .soc_id = "mt7621", .revision = "E2" }, -+ { /* sentinel */ } - }; - - static int mt7621_pcie_probe(struct platform_device *pdev) diff --git a/target/linux/ramips/patches-5.15/108-v6.3-PCI-mt7621-Delay-phy-ports-initialization.patch b/target/linux/ramips/patches-5.15/108-v6.3-PCI-mt7621-Delay-phy-ports-initialization.patch deleted file mode 100644 index de1d4cfc12..0000000000 --- a/target/linux/ramips/patches-5.15/108-v6.3-PCI-mt7621-Delay-phy-ports-initialization.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0cb2a8f3456ff1cc51d571e287a48e8fddc98ec2 Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Sat, 31 Dec 2022 08:40:41 +0100 -Subject: PCI: mt7621: Delay phy ports initialization - -Some devices like ZBT WE1326 and ZBT WF3526-P and some Netgear models need -to delay phy port initialization after calling the mt7621_pcie_init_port() -driver function to get into reliable boots for both warm and hard resets. - -The delay required to detect the ports seems to be in the range [75-100] -milliseconds. - -If the ports are not detected the controller is not functional. - -There is no datasheet or something similar to really understand why this -extra delay is needed only for these devices and it is not for most of -the boards that are built on mt7621 SoC. - -This issue has been reported by openWRT community and the complete -discussion is in [0]. The 100 milliseconds delay has been tested in all -devices to validate it. - -Add the extra 100 milliseconds delay to fix the issue. - -[0]: https://github.com/openwrt/openwrt/pull/11220 - -Link: https://lore.kernel.org/r/20221231074041.264738-1-sergio.paracuellos@gmail.com -Fixes: 2bdd5238e756 ("PCI: mt7621: Add MediaTek MT7621 PCIe host controller driver") -Signed-off-by: Sergio Paracuellos -Signed-off-by: Lorenzo Pieralisi ---- - drivers/pci/controller/pcie-mt7621.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -58,6 +58,7 @@ - #define PCIE_PORT_LINKUP BIT(0) - #define PCIE_PORT_CNT 3 - -+#define INIT_PORTS_DELAY_MS 100 - #define PERST_DELAY_MS 100 - - /** -@@ -374,6 +375,7 @@ static int mt7621_pcie_init_ports(struct - } - } - -+ msleep(INIT_PORTS_DELAY_MS); - mt7621_pcie_reset_ep_deassert(pcie); - - tmp = NULL; diff --git a/target/linux/ramips/patches-5.15/109-drivers-mt7621-dma-handle-error-from-device_reset.patch b/target/linux/ramips/patches-5.15/109-drivers-mt7621-dma-handle-error-from-device_reset.patch deleted file mode 100644 index a4543337ff..0000000000 --- a/target/linux/ramips/patches-5.15/109-drivers-mt7621-dma-handle-error-from-device_reset.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 3f6dfa25128e428acfba20792bc7506d58806baa Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 7 May 2023 01:06:17 +0200 -Subject: [PATCH] drivers: mt7621-dma: handle error from device_reset - -Handle error from device reset to fix compilation warning. -Fix compilation warning: -drivers/staging/mt7621-dma/hsdma-mt7621.c: In function 'mtk_hsdma_probe': -drivers/staging/mt7621-dma/hsdma-mt7621.c:685:9: error: ignoring return value of 'device_reset' declared with attribute 'warn_unused_result' [-Werror=unused-result] - 685 | device_reset(&pdev->dev); - | ^~~~~~~~~~~~~~~~~~~~~~~~ -cc1: all warnings being treated as errors - -Signed-off-by: Christian Marangi ---- - drivers/staging/mt7621-dma/hsdma-mt7621.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/staging/mt7621-dma/hsdma-mt7621.c -+++ b/drivers/staging/mt7621-dma/hsdma-mt7621.c -@@ -682,7 +682,9 @@ static int mtk_hsdma_probe(struct platfo - return ret; - } - -- device_reset(&pdev->dev); -+ ret = device_reset(&pdev->dev); -+ if (ret) -+ dev_err(&pdev->dev, "failed to reset device\n"); - - dd = &hsdma->ddev; - dma_cap_set(DMA_MEMCPY, dd->cap_mask); diff --git a/target/linux/ramips/patches-5.15/110-v6.4-PCI-mt7621-Use-dev_info-to-log-PCIe-card-detection.patch b/target/linux/ramips/patches-5.15/110-v6.4-PCI-mt7621-Use-dev_info-to-log-PCIe-card-detection.patch deleted file mode 100644 index 94519b9c01..0000000000 --- a/target/linux/ramips/patches-5.15/110-v6.4-PCI-mt7621-Use-dev_info-to-log-PCIe-card-detection.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 50233e105a0332ec0f3bc83180c416e6b200471e Mon Sep 17 00:00:00 2001 -From: Sergio Paracuellos -Date: Fri, 24 Mar 2023 08:37:33 +0100 -Subject: PCI: mt7621: Use dev_info() to log PCIe card detection - -When there is no card plugged on a PCIe port a log reporting that -the port will be disabled is flagged as an error (dev_err()). - -Since this is not an error at all, change the log level by using -dev_info() instead. - -Link: https://lore.kernel.org/r/20230324073733.1596231-1-sergio.paracuellos@gmail.com -Signed-off-by: Sergio Paracuellos -Signed-off-by: Lorenzo Pieralisi ---- - drivers/pci/controller/pcie-mt7621.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/pci/controller/pcie-mt7621.c -+++ b/drivers/pci/controller/pcie-mt7621.c -@@ -383,8 +383,8 @@ static int mt7621_pcie_init_ports(struct - u32 slot = port->slot; - - if (!mt7621_pcie_port_is_linkup(port)) { -- dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", -- slot); -+ dev_info(dev, "pcie%d no card, disable it (RST & CLK)\n", -+ slot); - mt7621_control_assert(port); - port->enabled = false; - num_disabled++; diff --git a/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch b/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch deleted file mode 100644 index 63c864ff7c..0000000000 --- a/target/linux/ramips/patches-5.15/200-add-ralink-eth.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/net/ethernet/Kconfig -+++ b/drivers/net/ethernet/Kconfig -@@ -162,6 +162,7 @@ source "drivers/net/ethernet/pensando/Kc - source "drivers/net/ethernet/qlogic/Kconfig" - source "drivers/net/ethernet/brocade/Kconfig" - source "drivers/net/ethernet/qualcomm/Kconfig" -+source "drivers/net/ethernet/ralink/Kconfig" - source "drivers/net/ethernet/rdc/Kconfig" - source "drivers/net/ethernet/realtek/Kconfig" - source "drivers/net/ethernet/renesas/Kconfig" ---- a/drivers/net/ethernet/Makefile -+++ b/drivers/net/ethernet/Makefile -@@ -73,6 +73,7 @@ obj-$(CONFIG_NET_VENDOR_PACKET_ENGINES) - obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ - obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ - obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/ -+obj-$(CONFIG_NET_VENDOR_RALINK) += ralink/ - obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ - obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/ - obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ diff --git a/target/linux/ramips/patches-5.15/300-mt7620-export-chip-version-and-pkg.patch b/target/linux/ramips/patches-5.15/300-mt7620-export-chip-version-and-pkg.patch deleted file mode 100644 index 4f4fe9018a..0000000000 --- a/target/linux/ramips/patches-5.15/300-mt7620-export-chip-version-and-pkg.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/arch/mips/include/asm/mach-ralink/mt7620.h -+++ b/arch/mips/include/asm/mach-ralink/mt7620.h -@@ -61,4 +61,16 @@ static inline int mt7620_get_eco(void) - return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK; - } - -+static inline int mt7620_get_chipver(void) -+{ -+ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_VER_SHIFT) & -+ CHIP_REV_VER_MASK; -+} -+ -+static inline int mt7620_get_pkg(void) -+{ -+ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_PKG_SHIFT) & -+ CHIP_REV_PKG_MASK; -+} -+ - #endif diff --git a/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch deleted file mode 100644 index 172cf98ad1..0000000000 --- a/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch +++ /dev/null @@ -1,100 +0,0 @@ -From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 14 Jul 2013 23:08:11 +0200 -Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k - irq - -Signed-off-by: John Crispin ---- - arch/mips/ralink/Kconfig | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -1,12 +1,17 @@ - # SPDX-License-Identifier: GPL-2.0 - if RALINK - -+config CEVT_SYSTICK_QUIRK -+ bool -+ default n -+ - config CLKEVT_RT3352 - bool - depends on SOC_RT305X || SOC_MT7620 - default y - select TIMER_OF - select CLKSRC_MMIO -+ select CEVT_SYSTICK_QUIRK - - config RALINK_ILL_ACC - bool ---- a/arch/mips/kernel/cevt-r4k.c -+++ b/arch/mips/kernel/cevt-r4k.c -@@ -16,6 +16,31 @@ - #include - #include - -+#ifdef CONFIG_CEVT_SYSTICK_QUIRK -+static int mips_state_oneshot(struct clock_event_device *evt) -+{ -+ unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED; -+ if (!cp0_timer_irq_installed) { -+ cp0_timer_irq_installed = 1; -+ if (request_irq(evt->irq, c0_compare_interrupt, flags, "timer", -+ c0_compare_interrupt)) -+ pr_err("Failed to request irq %d (timer)\n", evt->irq); -+ } -+ -+ return 0; -+} -+ -+static int mips_state_shutdown(struct clock_event_device *evt) -+{ -+ if (cp0_timer_irq_installed) { -+ cp0_timer_irq_installed = 0; -+ free_irq(evt->irq, NULL); -+ } -+ -+ return 0; -+} -+#endif -+ - static int mips_next_event(unsigned long delta, - struct clock_event_device *evt) - { -@@ -292,7 +317,9 @@ core_initcall(r4k_register_cpufreq_notif - - int r4k_clockevent_init(void) - { -+#ifndef CONFIG_CEVT_SYSTICK_QUIRK - unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED; -+#endif - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd; - unsigned int irq, min_delta; -@@ -322,11 +349,16 @@ int r4k_clockevent_init(void) - cd->rating = 300; - cd->irq = irq; - cd->cpumask = cpumask_of(cpu); -+#ifdef CONFIG_CEVT_SYSTICK_QUIRK -+ cd->set_state_shutdown = mips_state_shutdown; -+ cd->set_state_oneshot = mips_state_oneshot; -+#endif - cd->set_next_event = mips_next_event; - cd->event_handler = mips_event_handler; - - clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); - -+#ifndef CONFIG_CEVT_SYSTICK_QUIRK - if (cp0_timer_irq_installed) - return 0; - -@@ -335,6 +367,7 @@ int r4k_clockevent_init(void) - if (request_irq(irq, c0_compare_interrupt, flags, "timer", - c0_compare_interrupt)) - pr_err("Failed to request irq %d (timer)\n", irq); -+#endif - - return 0; - } diff --git a/target/linux/ramips/patches-5.15/312-MIPS-ralink-add-cpu-frequency-scaling.patch b/target/linux/ramips/patches-5.15/312-MIPS-ralink-add-cpu-frequency-scaling.patch deleted file mode 100644 index 0d70770941..0000000000 --- a/target/linux/ramips/patches-5.15/312-MIPS-ralink-add-cpu-frequency-scaling.patch +++ /dev/null @@ -1,195 +0,0 @@ -From bd30f19a006fb52bac80c6463c49dd2f4159f4ac Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 28 Jul 2013 16:26:41 +0200 -Subject: [PATCH 06/53] MIPS: ralink: add cpu frequency scaling - -This feature will break udelay() and cause the delay loop to have longer delays -when the frequency is scaled causing a performance hit. - -Signed-off-by: John Crispin ---- - arch/mips/ralink/cevt-rt3352.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - ---- a/arch/mips/ralink/cevt-rt3352.c -+++ b/arch/mips/ralink/cevt-rt3352.c -@@ -29,6 +29,10 @@ - /* enable the counter */ - #define CFG_CNT_EN 0x1 - -+/* mt7620 frequency scaling defines */ -+#define CLK_LUT_CFG 0x40 -+#define SLEEP_EN BIT(31) -+ - struct systick_device { - void __iomem *membase; - struct clock_event_device dev; -@@ -36,21 +40,53 @@ struct systick_device { - int freq_scale; - }; - -+static void (*systick_freq_scaling)(struct systick_device *sdev, int status); -+ - static int systick_set_oneshot(struct clock_event_device *evt); - static int systick_shutdown(struct clock_event_device *evt); - -+static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) -+{ -+ if (sdev->freq_scale == status) -+ return; -+ -+ sdev->freq_scale = status; -+ -+ pr_info("%s: %s autosleep mode\n", sdev->dev.name, -+ (status) ? ("enable") : ("disable")); -+ if (status) -+ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); -+ else -+ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); -+} -+ -+static inline unsigned int read_count(struct systick_device *sdev) -+{ -+ return ioread32(sdev->membase + SYSTICK_COUNT); -+} -+ -+static inline unsigned int read_compare(struct systick_device *sdev) -+{ -+ return ioread32(sdev->membase + SYSTICK_COMPARE); -+} -+ -+static inline void write_compare(struct systick_device *sdev, unsigned int val) -+{ -+ iowrite32(val, sdev->membase + SYSTICK_COMPARE); -+} -+ - static int systick_next_event(unsigned long delta, - struct clock_event_device *evt) - { - struct systick_device *sdev; -- u32 count; -+ int res; - - sdev = container_of(evt, struct systick_device, dev); -- count = ioread32(sdev->membase + SYSTICK_COUNT); -- count = (count + delta) % SYSTICK_FREQ; -- iowrite32(count, sdev->membase + SYSTICK_COMPARE); -+ delta += read_count(sdev); -+ write_compare(sdev, delta); -+ res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0; - -- return 0; -+ return res; - } - - static void systick_event_handler(struct clock_event_device *dev) -@@ -60,20 +96,25 @@ static void systick_event_handler(struct - - static irqreturn_t systick_interrupt(int irq, void *dev_id) - { -- struct clock_event_device *dev = (struct clock_event_device *) dev_id; -+ int ret = 0; -+ struct clock_event_device *cdev; -+ struct systick_device *sdev; - -- dev->event_handler(dev); -+ if (read_c0_cause() & STATUSF_IP7) { -+ cdev = (struct clock_event_device *) dev_id; -+ sdev = container_of(cdev, struct systick_device, dev); -+ -+ /* Clear Count/Compare Interrupt */ -+ write_compare(sdev, read_compare(sdev)); -+ cdev->event_handler(cdev); -+ ret = 1; -+ } - -- return IRQ_HANDLED; -+ return IRQ_RETVAL(ret); - } - - static struct systick_device systick = { - .dev = { -- /* -- * cevt-r4k uses 300, make sure systick -- * gets used if available -- */ -- .rating = 310, - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = systick_next_event, - .set_state_shutdown = systick_shutdown, -@@ -91,7 +132,13 @@ static int systick_shutdown(struct clock - if (sdev->irq_requested) - free_irq(systick.dev.irq, &systick.dev); - sdev->irq_requested = 0; -- iowrite32(0, systick.membase + SYSTICK_CONFIG); -+ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); -+ -+ if (systick_freq_scaling) -+ systick_freq_scaling(sdev, 0); -+ -+ if (systick_freq_scaling) -+ systick_freq_scaling(sdev, 1); - - return 0; - } -@@ -116,33 +163,46 @@ static int systick_set_oneshot(struct cl - return 0; - } - -+static const struct of_device_id systick_match[] = { -+ { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling}, -+ {}, -+}; -+ - static int __init ralink_systick_init(struct device_node *np) - { -- int ret; -+ const struct of_device_id *match; -+ int rating = 200; - - systick.membase = of_iomap(np, 0); - if (!systick.membase) - return -ENXIO; - -- systick.dev.name = np->name; -- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); -- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); -- systick.dev.max_delta_ticks = 0x7fff; -- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); -- systick.dev.min_delta_ticks = 0x3; -+ match = of_match_node(systick_match, np); -+ if (match) { -+ systick_freq_scaling = match->data; -+ /* -+ * cevt-r4k uses 300, make sure systick -+ * gets used if available -+ */ -+ rating = 310; -+ } -+ -+ /* enable counter than register clock source */ -+ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); -+ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, -+ SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up); -+ -+ /* register clock event */ - systick.dev.irq = irq_of_parse_and_map(np, 0); - if (!systick.dev.irq) { - pr_err("%pOFn: request_irq failed", np); - return -EINVAL; - } - -- ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, -- SYSTICK_FREQ, 301, 16, -- clocksource_mmio_readl_up); -- if (ret) -- return ret; -- -- clockevents_register_device(&systick.dev); -+ systick.dev.name = np->name; -+ systick.dev.rating = rating; -+ systick.dev.cpumask = cpumask_of(0); -+ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); - - pr_info("%pOFn: running - mult: %d, shift: %d\n", - np, systick.dev.mult, systick.dev.shift); diff --git a/target/linux/ramips/patches-5.15/314-MIPS-add-bootargs-override-property.patch b/target/linux/ramips/patches-5.15/314-MIPS-add-bootargs-override-property.patch deleted file mode 100644 index e7dca7af88..0000000000 --- a/target/linux/ramips/patches-5.15/314-MIPS-add-bootargs-override-property.patch +++ /dev/null @@ -1,63 +0,0 @@ -From f15d27f9c90ede4b16eb37f9ae573ef81c2b6996 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Thu, 31 Dec 2020 18:49:12 +0100 -Subject: [PATCH] MIPS: add bootargs-override property - -Add support for the bootargs-override property to the chosen node -similar to the one used on ipq806x or mpc85xx. - -This is necessary, as the U-Boot used on some boards, notably the -Ubiquiti UniFi 6 Lite, overwrite the bootargs property of the chosen -node leading to a kernel panic when loading OpenWrt. - -Signed-off-by: David Bauer ---- - arch/mips/kernel/setup.c | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -547,8 +547,28 @@ static int __init bootcmdline_scan_chose - - #endif /* CONFIG_OF_EARLY_FLATTREE */ - -+static int __init bootcmdline_scan_chosen_override(unsigned long node, const char *uname, -+ int depth, void *data) -+{ -+ bool *dt_bootargs = data; -+ const char *p; -+ int l; -+ -+ if (depth != 1 || !data || strcmp(uname, "chosen") != 0) -+ return 0; -+ -+ p = of_get_flat_dt_prop(node, "bootargs-override", &l); -+ if (p != NULL && l > 0) { -+ strlcpy(boot_command_line, p, COMMAND_LINE_SIZE); -+ *dt_bootargs = true; -+ } -+ -+ return 1; -+} -+ - static void __init bootcmdline_init(void) - { -+ bool dt_bootargs_override = false; - bool dt_bootargs = false; - - /* -@@ -562,6 +582,14 @@ static void __init bootcmdline_init(void - } - - /* -+ * If bootargs-override in the chosen node is set, use this as the -+ * command line -+ */ -+ of_scan_flat_dt(bootcmdline_scan_chosen_override, &dt_bootargs_override); -+ if (dt_bootargs_override) -+ return; -+ -+ /* - * If the user specified a built-in command line & - * MIPS_CMDLINE_BUILTIN_EXTEND, then the built-in command line is - * prepended to arguments from the bootloader or DT so we'll copy them diff --git a/target/linux/ramips/patches-5.15/315-owrt-hack-fix-mt7688-cache-issue.patch b/target/linux/ramips/patches-5.15/315-owrt-hack-fix-mt7688-cache-issue.patch deleted file mode 100644 index 4f9eec7271..0000000000 --- a/target/linux/ramips/patches-5.15/315-owrt-hack-fix-mt7688-cache-issue.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5ede027f6c4a57ed25da872420508b7f1168b36b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 7 Dec 2015 17:15:32 +0100 -Subject: [PATCH 13/53] owrt: hack: fix mt7688 cache issue - -Signed-off-by: John Crispin ---- - arch/mips/kernel/setup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -689,7 +689,6 @@ static void __init arch_mem_init(char ** - mips_reserve_vmcore(); - - mips_parse_crashkernel(); -- device_tree_init(); - - /* - * In order to reduce the possibility of kernel panic when failed to -@@ -806,6 +805,7 @@ void __init setup_arch(char **cmdline_p) - - cpu_cache_init(); - paging_init(); -+ device_tree_init(); - - memblock_dump_all(); - } diff --git a/target/linux/ramips/patches-5.15/316-arch-mips-do-not-select-illegal-access-driver-by-def.patch b/target/linux/ramips/patches-5.15/316-arch-mips-do-not-select-illegal-access-driver-by-def.patch deleted file mode 100644 index 1dc54ccf23..0000000000 --- a/target/linux/ramips/patches-5.15/316-arch-mips-do-not-select-illegal-access-driver-by-def.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 9e6ce539092a1dd605a20bf73c655a9de58d8641 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 7 Dec 2015 17:18:05 +0100 -Subject: [PATCH 15/53] arch: mips: do not select illegal access driver by - default - -Signed-off-by: John Crispin ---- - arch/mips/ralink/Kconfig | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/mips/ralink/Kconfig -+++ b/arch/mips/ralink/Kconfig -@@ -14,9 +14,9 @@ config CLKEVT_RT3352 - select CEVT_SYSTICK_QUIRK - - config RALINK_ILL_ACC -- bool -+ bool "illegal access irq" - depends on SOC_RT305X -- default y -+ default n - - config IRQ_INTC - bool diff --git a/target/linux/ramips/patches-5.15/320-MIPS-add-support-for-buggy-MT7621S-core-detection.patch b/target/linux/ramips/patches-5.15/320-MIPS-add-support-for-buggy-MT7621S-core-detection.patch deleted file mode 100644 index 0eb6676414..0000000000 --- a/target/linux/ramips/patches-5.15/320-MIPS-add-support-for-buggy-MT7621S-core-detection.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 6decd1aad15f56b169217789630a0098b496de0e Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Wed, 7 Apr 2021 13:07:38 -0700 -Subject: [PATCH] MIPS: add support for buggy MT7621S core detection - -Most MT7621 SoCs have 2 cores, which is detected and supported properly -by CPS. - -Unfortunately, MT7621 SoC has a less common S variant with only one core. -On MT7621S, GCR_CONFIG still reports 2 cores, which leads to hangs when -starting SMP. CPULAUNCH registers can be used in that case to detect the -absence of the second core and override the GCR_CONFIG PCORES field. - -Rework a long-standing OpenWrt patch to override the value of -mips_cps_numcores on single-core MT7621 systems. - -Tested on a dual-core MT7621 device (Ubiquiti ER-X) and a single-core -MT7621 device (Netgear R6220). - -Original 4.14 OpenWrt patch: -Link: https://git.openwrt.org/?p=openwrt/openwrt.git;a=commitdiff;h=4cdbc90a376dd0555201c1434a2081e055e9ceb7 -Current 5.10 OpenWrt patch: -Link: https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/ramips/patches-5.10/320-mt7621-core-detect-hack.patch;h=c63f0f4c1ec742e24d8480e80553863744b58f6a;hb=10267e17299806f9885d086147878f6c492cb904 - -Suggested-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/include/asm/mips-cps.h | 23 ++++++++++++++++++++++- - 1 file changed, 22 insertions(+), 1 deletion(-) - ---- a/arch/mips/include/asm/mips-cps.h -+++ b/arch/mips/include/asm/mips-cps.h -@@ -10,6 +10,8 @@ - #include - #include - -+#include -+ - extern unsigned long __cps_access_bad_size(void) - __compiletime_error("Bad size for CPS accessor"); - -@@ -165,11 +167,30 @@ static inline uint64_t mips_cps_cluster_ - */ - static inline unsigned int mips_cps_numcores(unsigned int cluster) - { -+ unsigned int ncores; -+ - if (!mips_cm_present()) - return 0; - - /* Add one before masking to handle 0xff indicating no cores */ -- return (mips_cps_cluster_config(cluster) + 1) & CM_GCR_CONFIG_PCORES; -+ ncores = (mips_cps_cluster_config(cluster) + 1) & CM_GCR_CONFIG_PCORES; -+ -+ if (IS_ENABLED(CONFIG_SOC_MT7621)) { -+ struct cpulaunch *launch; -+ -+ /* -+ * Ralink MT7621S SoC is single core, but the GCR_CONFIG method -+ * always reports 2 cores. Check the second core's LAUNCH_FREADY -+ * flag to detect if the second core is missing. This method -+ * only works before the core has been started. -+ */ -+ launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); -+ launch += 2; /* MT7621 has 2 VPEs per core */ -+ if (!(launch->flags & LAUNCH_FREADY)) -+ ncores = 1; -+ } -+ -+ return ncores; - } - - /** diff --git a/target/linux/ramips/patches-5.15/324-mt7621-perfctr-fix.patch b/target/linux/ramips/patches-5.15/324-mt7621-perfctr-fix.patch deleted file mode 100644 index dfeac7eb99..0000000000 --- a/target/linux/ramips/patches-5.15/324-mt7621-perfctr-fix.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/arch/mips/ralink/irq-gic.c -+++ b/arch/mips/ralink/irq-gic.c -@@ -13,6 +13,12 @@ - - int get_c0_perfcount_int(void) - { -+ /* -+ * Performance counter events are routed through GIC. -+ * Prevent them from firing on CPU IRQ7 as well -+ */ -+ clear_c0_status(IE_SW0 << 7); -+ - return gic_get_c0_perfcount_int(); - } - EXPORT_SYMBOL_GPL(get_c0_perfcount_int); diff --git a/target/linux/ramips/patches-5.15/400-mtd-cfi-cmdset-0002-force-word-write.patch b/target/linux/ramips/patches-5.15/400-mtd-cfi-cmdset-0002-force-word-write.patch deleted file mode 100644 index 7011bbe50b..0000000000 --- a/target/linux/ramips/patches-5.15/400-mtd-cfi-cmdset-0002-force-word-write.patch +++ /dev/null @@ -1,20 +0,0 @@ -From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 15 Jul 2013 00:39:21 +0200 -Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write - ---- - drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -40,7 +40,7 @@ - #include - - #define AMD_BOOTLOC_BUG --#define FORCE_WORD_WRITE 0 -+#define FORCE_WORD_WRITE 1 - - #define MAX_RETRIES 3 - diff --git a/target/linux/ramips/patches-5.15/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch b/target/linux/ramips/patches-5.15/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch deleted file mode 100644 index 4cbb84efc6..0000000000 --- a/target/linux/ramips/patches-5.15/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 52d14545d2fc276b1bf9ccf48d4612fab6edfb6a Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Thu, 6 May 2021 17:49:55 +0200 -Subject: [PATCH] mtd: spi-nor: Add support for BoHong bh25q128as - -Add MTD support for the BoHong bh25q128as SPI NOR chip. -The chip has 16MB of total capacity, divided into a total of 256 -sectors, each 64KB sized. The chip also supports 4KB sectors. -Additionally, it supports dual and quad read modes. - -Functionality was verified on an Tenbay WR1800K / MTK MT7621 board. - -Signed-off-by: David Bauer ---- - drivers/mtd/spi-nor/Makefile | 1 + - drivers/mtd/spi-nor/bohong.c | 21 +++++++++++++++++++++ - drivers/mtd/spi-nor/core.c | 1 + - drivers/mtd/spi-nor/core.h | 1 + - 4 files changed, 24 insertions(+) - create mode 100644 drivers/mtd/spi-nor/bohong.c - ---- a/drivers/mtd/spi-nor/Makefile -+++ b/drivers/mtd/spi-nor/Makefile -@@ -2,6 +2,7 @@ - - spi-nor-objs := core.o sfdp.o swp.o otp.o sysfs.o - spi-nor-objs += atmel.o -+spi-nor-objs += bohong.o - spi-nor-objs += catalyst.o - spi-nor-objs += eon.o - spi-nor-objs += esmt.o ---- /dev/null -+++ b/drivers/mtd/spi-nor/bohong.c -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2005, Intec Automation Inc. -+ * Copyright (C) 2014, Freescale Semiconductor, Inc. -+ */ -+ -+#include -+ -+#include "core.h" -+ -+static const struct flash_info bohong_parts[] = { -+ /* BoHong Microelectronics */ -+ { "bh25q128as", INFO(0x684018, 0, 64 * 1024, 256, -+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+}; -+ -+const struct spi_nor_manufacturer spi_nor_bohong = { -+ .name = "bohong", -+ .parts = bohong_parts, -+ .nparts = ARRAY_SIZE(bohong_parts), -+}; ---- a/drivers/mtd/spi-nor/core.c -+++ b/drivers/mtd/spi-nor/core.c -@@ -1844,6 +1844,7 @@ int spi_nor_sr2_bit7_quad_enable(struct - - static const struct spi_nor_manufacturer *manufacturers[] = { - &spi_nor_atmel, -+ &spi_nor_bohong, - &spi_nor_catalyst, - &spi_nor_eon, - &spi_nor_esmt, ---- a/drivers/mtd/spi-nor/core.h -+++ b/drivers/mtd/spi-nor/core.h -@@ -473,6 +473,7 @@ struct sfdp { - - /* Manufacturer drivers. */ - extern const struct spi_nor_manufacturer spi_nor_atmel; -+extern const struct spi_nor_manufacturer spi_nor_bohong; - extern const struct spi_nor_manufacturer spi_nor_catalyst; - extern const struct spi_nor_manufacturer spi_nor_eon; - extern const struct spi_nor_manufacturer spi_nor_esmt; diff --git a/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch b/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch deleted file mode 100644 index 33a741e531..0000000000 --- a/target/linux/ramips/patches-5.15/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch +++ /dev/null @@ -1,47 +0,0 @@ -From e84e2430ee0e483842b4ff013ae8a6e7e2fa2734 Mon Sep 17 00:00:00 2001 -From: Weijie Gao -Date: Wed, 1 Apr 2020 02:07:58 +0800 -Subject: [PATCH 1/2] mtd: rawnand: add driver support for MT7621 nand - flash controller - -This patch adds NAND flash controller driver for MediaTek MT7621 SoC. - -The NAND flash controller is similar with controllers described in -mtk_nand.c, except that the controller from MT7621 doesn't support DMA -transmission, and some registers' offset and fields are different. - -Signed-off-by: Weijie Gao ---- - drivers/mtd/nand/raw/Kconfig | 8 + - drivers/mtd/nand/raw/Makefile | 1 + - drivers/mtd/nand/raw/mt7621_nand.c | 1348 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 1357 insertions(+) - create mode 100644 drivers/mtd/nand/raw/mt7621_nand.c - ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -358,6 +358,14 @@ config MTD_NAND_QCOM - Enables support for NAND flash chips on SoCs containing the EBI2 NAND - controller. This controller is found on IPQ806x SoC. - -+config MTD_NAND_MT7621 -+ tristate "MT7621 NAND controller" -+ depends on SOC_MT7621 || COMPILE_TEST -+ depends on HAS_IOMEM -+ help -+ Enables support for NAND controller on MT7621 SoC. -+ This driver uses PIO mode for data transmission instead of DMA mode. -+ - config MTD_NAND_MTK - tristate "MTK NAND controller" - depends on ARCH_MEDIATEK || COMPILE_TEST ---- a/drivers/mtd/nand/raw/Makefile -+++ b/drivers/mtd/nand/raw/Makefile -@@ -48,6 +48,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_n - obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o - obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ - obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o -+obj-$(CONFIG_MTD_NAND_MT7621) += mt7621_nand.o - obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o - obj-$(CONFIG_MTD_NAND_MXIC) += mxic_nand.o - obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o diff --git a/target/linux/ramips/patches-5.15/411-dt-bindings-add-documentation-for-mt7621-nand-driver.patch b/target/linux/ramips/patches-5.15/411-dt-bindings-add-documentation-for-mt7621-nand-driver.patch deleted file mode 100644 index 3d122c10c0..0000000000 --- a/target/linux/ramips/patches-5.15/411-dt-bindings-add-documentation-for-mt7621-nand-driver.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 3d5f4da8296b23eb3abf8b13122b0d06a215e79c Mon Sep 17 00:00:00 2001 -From: Weijie Gao -Date: Wed, 1 Apr 2020 02:07:59 +0800 -Subject: [PATCH 2/2] dt-bindings: add documentation for mt7621-nand driver - -This patch adds documentation for MediaTek MT7621 NAND flash controller -driver. - -Signed-off-by: Weijie Gao ---- - .../bindings/mtd/mediatek,mt7621-nfc.yaml | 68 ++++++++++++++++++++++ - 1 file changed, 68 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml -@@ -0,0 +1,68 @@ -+# SPDX-License-Identifier: GPL-2.0 -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/mediatek,mt7621-nfc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: MediaTek MT7621 SoC NAND Flash Controller (NFC) DT binding -+ -+maintainers: -+ - Weijie Gao -+ -+description: | -+ This driver uses a single node to describe both NAND Flash controller -+ interface (NFI) and ECC engine for MT7621 SoC. -+ MT7621 supports only one chip select. -+ -+properties: -+ "#address-cells": false -+ "#size-cells": false -+ -+ compatible: -+ enum: -+ - mediatek,mt7621-nfc -+ -+ reg: -+ items: -+ - description: Register base of NFI core -+ - description: Register base of ECC engine -+ -+ reg-names: -+ items: -+ - const: nfi -+ - const: ecc -+ -+ clocks: -+ items: -+ - description: Source clock for NFI core, fixed 125MHz -+ -+ clock-names: -+ items: -+ - const: nfi_clk -+ -+required: -+ - compatible -+ - reg -+ - reg-names -+ - clocks -+ - clock-names -+ -+examples: -+ - | -+ nficlock: nficlock { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ -+ clock-frequency = <125000000>; -+ }; -+ -+ nand@1e003000 { -+ compatible = "mediatek,mt7621-nfc"; -+ -+ reg = <0x1e003000 0x800 -+ 0x1e003800 0x800>; -+ reg-names = "nfi", "ecc"; -+ -+ clocks = <&nficlock>; -+ clock-names = "nfi_clk"; -+ }; 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 deleted file mode 100644 index d9fc379bed..0000000000 --- a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch +++ /dev/null @@ -1,34 +0,0 @@ -From bd0f89de5476ca25e73fae829ba3e1dafae1d90d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= -Date: Fri, 21 Jun 2019 10:04:05 +0200 -Subject: [PATCH] net: ethernet: mediatek: support net-labels - -With this patch, device name can be set within dts file in the same way as dsa -port can. -Add: label = "wan"; to GMAC node. - -Signed-off-by: René van Dorst ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4558,6 +4558,7 @@ static const struct net_device_ops mtk_n - - static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) - { -+ const char *name = of_get_property(np, "label", NULL); - const __be32 *_id = of_get_property(np, "reg", NULL); - phy_interface_t phy_mode; - struct phylink *phylink; -@@ -4729,6 +4730,9 @@ static int mtk_add_mac(struct mtk_eth *e - register_netdevice_notifier(&mac->device_notifier); - } - -+ if (name) -+ strlcpy(eth->netdev[id]->name, name, IFNAMSIZ); -+ - return 0; - - free_netdev: diff --git a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch deleted file mode 100644 index 1262e9498d..0000000000 --- a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch +++ /dev/null @@ -1,118 +0,0 @@ -From ffbb1b37a3e1ce1a5c574a6bd4f5aede8bc468ac Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Sat, 27 Feb 2021 20:20:07 -0800 -Subject: [PATCH] Revert "net: phy: simplify phy_link_change arguments" - -This reverts commit a307593a644443db12888f45eed0dafb5869e2cc. - -This brings back the do_carrier flags used by the (hacky) next patch, -still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c ---- - drivers/net/phy/phy.c | 12 ++++++------ - drivers/net/phy/phy_device.c | 12 +++++++----- - drivers/net/phy/phylink.c | 3 ++- - include/linux/phy.h | 2 +- - 4 files changed, 16 insertions(+), 13 deletions(-) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -71,13 +71,13 @@ static void phy_process_state_change(str - - static void phy_link_up(struct phy_device *phydev) - { -- phydev->phy_link_change(phydev, true); -+ phydev->phy_link_change(phydev, true, true); - phy_led_trigger_change_speed(phydev); - } - --static void phy_link_down(struct phy_device *phydev) -+static void phy_link_down(struct phy_device *phydev, bool do_carrier) - { -- phydev->phy_link_change(phydev, false); -+ phydev->phy_link_change(phydev, false, do_carrier); - phy_led_trigger_change_speed(phydev); - } - -@@ -591,7 +591,7 @@ int phy_start_cable_test(struct phy_devi - goto out; - - /* Mark the carrier down until the test is complete */ -- phy_link_down(phydev); -+ phy_link_down(phydev, true); - - netif_testing_on(dev); - err = phydev->drv->cable_test_start(phydev); -@@ -662,7 +662,7 @@ int phy_start_cable_test_tdr(struct phy_ - goto out; - - /* Mark the carrier down until the test is complete */ -- phy_link_down(phydev); -+ phy_link_down(phydev, true); - - netif_testing_on(dev); - err = phydev->drv->cable_test_tdr_start(phydev, config); -@@ -734,7 +734,7 @@ static int phy_check_link_status(struct - phy_link_up(phydev); - } else if (!phydev->link && phydev->state != PHY_NOLINK) { - phydev->state = PHY_NOLINK; -- phy_link_down(phydev); -+ phy_link_down(phydev, true); - } - - return 0; -@@ -1220,7 +1220,7 @@ void phy_state_machine(struct work_struc - case PHY_HALTED: - if (phydev->link) { - phydev->link = 0; -- phy_link_down(phydev); -+ phy_link_down(phydev, true); - } - do_suspend = true; - break; ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -1035,14 +1035,16 @@ struct phy_device *phy_find_first(struct - } - EXPORT_SYMBOL(phy_find_first); - --static void phy_link_change(struct phy_device *phydev, bool up) -+static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier) - { - struct net_device *netdev = phydev->attached_dev; - -- if (up) -- netif_carrier_on(netdev); -- else -- netif_carrier_off(netdev); -+ if (do_carrier) { -+ if (up) -+ netif_carrier_on(netdev); -+ else -+ netif_carrier_off(netdev); -+ } - phydev->adjust_link(netdev); - if (phydev->mii_ts && phydev->mii_ts->link_state) - phydev->mii_ts->link_state(phydev->mii_ts, phydev); ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1373,7 +1373,8 @@ void phylink_destroy(struct phylink *pl) - } - EXPORT_SYMBOL_GPL(phylink_destroy); - --static void phylink_phy_change(struct phy_device *phydev, bool up) -+static void phylink_phy_change(struct phy_device *phydev, bool up, -+ bool do_carrier) - { - struct phylink *pl = phydev->phylink; - bool tx_pause, rx_pause; ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -716,7 +716,7 @@ struct phy_device { - u8 mdix; - u8 mdix_ctrl; - -- void (*phy_link_change)(struct phy_device *phydev, bool up); -+ void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier); - void (*adjust_link)(struct net_device *dev); - - #if IS_ENABLED(CONFIG_MACSEC) diff --git a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch deleted file mode 100644 index fc7873a01b..0000000000 --- a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:38:50 +0100 -Subject: [PATCH 34/53] NET: multi phy support - -Signed-off-by: John Crispin ---- - drivers/net/phy/phy.c | 9 ++++++--- - include/linux/phy.h | 1 + - 2 files changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -734,7 +734,10 @@ static int phy_check_link_status(struct - phy_link_up(phydev); - } else if (!phydev->link && phydev->state != PHY_NOLINK) { - phydev->state = PHY_NOLINK; -- phy_link_down(phydev, true); -+ if (!phydev->no_auto_carrier_off) -+ phy_link_down(phydev, true); -+ else -+ phy_link_down(phydev, false); - } - - return 0; -@@ -1220,7 +1223,10 @@ void phy_state_machine(struct work_struc - case PHY_HALTED: - if (phydev->link) { - phydev->link = 0; -- phy_link_down(phydev, true); -+ if (!phydev->no_auto_carrier_off) -+ phy_link_down(phydev, true); -+ else -+ phy_link_down(phydev, false); - } - do_suspend = true; - break; ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -630,6 +630,7 @@ struct phy_device { - unsigned downshifted_rate:1; - unsigned is_on_sfp_module:1; - unsigned mac_managed_pm:1; -+ unsigned no_auto_carrier_off:1; - - unsigned autoneg:1; - /* The most recently read link state */ diff --git a/target/linux/ramips/patches-5.15/801-DT-Add-documentation-for-gpio-ralink.patch b/target/linux/ramips/patches-5.15/801-DT-Add-documentation-for-gpio-ralink.patch deleted file mode 100644 index 93dabf8776..0000000000 --- a/target/linux/ramips/patches-5.15/801-DT-Add-documentation-for-gpio-ralink.patch +++ /dev/null @@ -1,59 +0,0 @@ -From d410e5478c622c01fcf31427533df5f433df9146 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 28 Jul 2013 19:45:30 +0200 -Subject: [PATCH 26/53] DT: Add documentation for gpio-ralink - -Describe gpio-ralink binding. - -Signed-off-by: John Crispin -Cc: linux-mips@linux-mips.org -Cc: devicetree@vger.kernel.org -Cc: linux-gpio@vger.kernel.org ---- - .../devicetree/bindings/gpio/gpio-ralink.txt | 40 ++++++++++++++++++++ - 1 file changed, 40 insertions(+) - create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt -@@ -0,0 +1,40 @@ -+Ralink SoC GPIO controller bindings -+ -+Required properties: -+- compatible: -+ - "ralink,rt2880-gpio" for Ralink controllers -+- #gpio-cells : Should be two. -+ - first cell is the pin number -+ - second cell is used to specify optional parameters (unused) -+- gpio-controller : Marks the device node as a GPIO controller -+- reg : Physical base address and length of the controller's registers -+- interrupt-parent: phandle to the INTC device node -+- interrupts : Specify the INTC interrupt number -+- ngpios : Specify the number of GPIOs -+- ralink,register-map : The register layout depends on the GPIO bank and actual -+ SoC type. Register offsets need to be in this order. -+ [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ] -+ -+Optional properties: -+- ralink,gpio-base : Specify the GPIO chips base number -+ -+Example: -+ -+ gpio0: gpio@600 { -+ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; -+ -+ #gpio-cells = <2>; -+ gpio-controller; -+ -+ reg = <0x600 0x34>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <6>; -+ -+ ngpios = <24>; -+ ralink,gpio-base = <0>; -+ ralink,register-map = [ 00 04 08 0c -+ 20 24 28 2c -+ 30 34 ]; -+ -+ }; diff --git a/target/linux/ramips/patches-5.15/802-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-5.15/802-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch deleted file mode 100644 index 02fafbdc9b..0000000000 --- a/target/linux/ramips/patches-5.15/802-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch +++ /dev/null @@ -1,416 +0,0 @@ -From 69fdd2c4f937796b934e89c33acde9d082e27bfd Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 4 Aug 2014 20:36:29 +0200 -Subject: [PATCH 27/53] GPIO: MIPS: ralink: add gpio driver for ralink SoC - -Add gpio driver for Ralink SoC. This driver makes the gpio core on -RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. - -Signed-off-by: John Crispin -Cc: linux-mips@linux-mips.org -Cc: linux-gpio@vger.kernel.org ---- - arch/mips/include/asm/mach-ralink/gpio.h | 24 ++ - drivers/gpio/Kconfig | 6 + - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-ralink.c | 355 ++++++++++++++++++++++++++++++ - 4 files changed, 386 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h - create mode 100644 drivers/gpio/gpio-ralink.c - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ralink/gpio.h -@@ -0,0 +1,24 @@ -+/* -+ * Ralink SoC GPIO API support -+ * -+ * Copyright (C) 2008-2009 Gabor Juhos -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ */ -+ -+#ifndef __ASM_MACH_RALINK_GPIO_H -+#define __ASM_MACH_RALINK_GPIO_H -+ -+#define ARCH_NR_GPIOS 128 -+#include -+ -+#define gpio_get_value __gpio_get_value -+#define gpio_set_value __gpio_set_value -+#define gpio_cansleep __gpio_cansleep -+#define gpio_to_irq __gpio_to_irq -+ -+#endif /* __ASM_MACH_RALINK_GPIO_H */ ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -569,6 +569,12 @@ config GPIO_SNPS_CREG - where only several fields in register belong to GPIO lines and - each GPIO line owns a field with different length and on/off value. - -+config GPIO_RALINK -+ bool "Ralink GPIO Support" -+ depends on RALINK -+ help -+ Say yes here to support the Ralink SoC GPIO device -+ - config GPIO_SPEAR_SPICS - bool "ST SPEAr13xx SPI Chip Select as GPIO support" - depends on PLAT_SPEAR ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -121,6 +121,7 @@ obj-$(CONFIG_GPIO_PISOSR) += gpio-pisos - obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o - obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o - obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o -+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o - obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o - obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o - obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o ---- /dev/null -+++ b/drivers/gpio/gpio-ralink.c -@@ -0,0 +1,341 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2009-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum ralink_gpio_reg { -+ GPIO_REG_INT = 0, -+ GPIO_REG_EDGE, -+ GPIO_REG_RENA, -+ GPIO_REG_FENA, -+ GPIO_REG_DATA, -+ GPIO_REG_DIR, -+ GPIO_REG_POL, -+ GPIO_REG_SET, -+ GPIO_REG_RESET, -+ GPIO_REG_TOGGLE, -+ GPIO_REG_MAX -+}; -+ -+struct ralink_gpio_chip { -+ struct gpio_chip chip; -+ u8 regs[GPIO_REG_MAX]; -+ -+ spinlock_t lock; -+ void __iomem *membase; -+ struct irq_domain *domain; -+ int irq; -+ -+ u32 rising; -+ u32 falling; -+}; -+ -+#define MAP_MAX 4 -+static struct irq_domain *irq_map[MAP_MAX]; -+static int irq_map_count; -+static atomic_t irq_refcount = ATOMIC_INIT(0); -+ -+static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) -+{ -+ struct ralink_gpio_chip *rg; -+ -+ rg = container_of(chip, struct ralink_gpio_chip, chip); -+ -+ return rg; -+} -+ -+static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) -+{ -+ iowrite32(val, rg->membase + rg->regs[reg]); -+} -+ -+static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) -+{ -+ return ioread32(rg->membase + rg->regs[reg]); -+} -+ -+static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ -+ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); -+} -+ -+static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ -+ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); -+} -+ -+static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ t = rt_gpio_r32(rg, GPIO_REG_DIR); -+ t &= ~BIT(offset); -+ rt_gpio_w32(rg, GPIO_REG_DIR, t); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int ralink_gpio_direction_output(struct gpio_chip *chip, -+ unsigned offset, int value) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ ralink_gpio_set(chip, offset, value); -+ t = rt_gpio_r32(rg, GPIO_REG_DIR); -+ t |= BIT(offset); -+ rt_gpio_w32(rg, GPIO_REG_DIR, t); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) -+{ -+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); -+ -+ if (rg->irq < 1) -+ return -1; -+ -+ return irq_create_mapping(rg->domain, pin); -+} -+ -+static void ralink_gpio_irq_handler(struct irq_desc *desc) -+{ -+ int i; -+ -+ for (i = 0; i < irq_map_count; i++) { -+ struct irq_domain *domain = irq_map[i]; -+ struct ralink_gpio_chip *rg; -+ unsigned long pending; -+ int bit; -+ -+ rg = (struct ralink_gpio_chip *) domain->host_data; -+ pending = rt_gpio_r32(rg, GPIO_REG_INT); -+ -+ for_each_set_bit(bit, &pending, rg->chip.ngpio) { -+ u32 map = irq_find_mapping(domain, bit); -+ generic_handle_irq(map); -+ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); -+ } -+ } -+} -+ -+static void ralink_gpio_irq_unmask(struct irq_data *d) -+{ -+ struct ralink_gpio_chip *rg; -+ unsigned long flags; -+ u32 rise, fall; -+ -+ rg = (struct ralink_gpio_chip *) d->domain->host_data; -+ rise = rt_gpio_r32(rg, GPIO_REG_RENA); -+ fall = rt_gpio_r32(rg, GPIO_REG_FENA); -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); -+ rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); -+ spin_unlock_irqrestore(&rg->lock, flags); -+} -+ -+static void ralink_gpio_irq_mask(struct irq_data *d) -+{ -+ struct ralink_gpio_chip *rg; -+ unsigned long flags; -+ u32 rise, fall; -+ -+ rg = (struct ralink_gpio_chip *) d->domain->host_data; -+ rise = rt_gpio_r32(rg, GPIO_REG_RENA); -+ fall = rt_gpio_r32(rg, GPIO_REG_FENA); -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); -+ rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); -+ spin_unlock_irqrestore(&rg->lock, flags); -+} -+ -+static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) -+{ -+ struct ralink_gpio_chip *rg; -+ u32 mask = BIT(d->hwirq); -+ -+ rg = (struct ralink_gpio_chip *) d->domain->host_data; -+ -+ if (type == IRQ_TYPE_PROBE) { -+ if ((rg->rising | rg->falling) & mask) -+ return 0; -+ -+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; -+ } -+ -+ if (type & IRQ_TYPE_EDGE_RISING) -+ rg->rising |= mask; -+ else -+ rg->rising &= ~mask; -+ -+ if (type & IRQ_TYPE_EDGE_FALLING) -+ rg->falling |= mask; -+ else -+ rg->falling &= ~mask; -+ -+ return 0; -+} -+ -+static struct irq_chip ralink_gpio_irq_chip = { -+ .name = "GPIO", -+ .irq_unmask = ralink_gpio_irq_unmask, -+ .irq_mask = ralink_gpio_irq_mask, -+ .irq_mask_ack = ralink_gpio_irq_mask, -+ .irq_set_type = ralink_gpio_irq_type, -+}; -+ -+static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); -+ irq_set_handler_data(irq, d); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = gpio_map, -+}; -+ -+static void ralink_gpio_irq_init(struct device_node *np, -+ struct ralink_gpio_chip *rg) -+{ -+ if (irq_map_count >= MAP_MAX) -+ return; -+ -+ rg->irq = irq_of_parse_and_map(np, 0); -+ if (!rg->irq) -+ return; -+ -+ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, -+ &irq_domain_ops, rg); -+ if (!rg->domain) { -+ dev_err(rg->chip.parent, "irq_domain_add_linear failed\n"); -+ return; -+ } -+ -+ irq_map[irq_map_count++] = rg->domain; -+ -+ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); -+ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); -+ -+ if (!atomic_read(&irq_refcount)) -+ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); -+ atomic_inc(&irq_refcount); -+ -+ dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio); -+} -+ -+static int ralink_gpio_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ struct ralink_gpio_chip *rg; -+ const __be32 *ngpio, *gpiobase; -+ -+ if (!res) { -+ dev_err(&pdev->dev, "failed to find resource\n"); -+ return -ENOMEM; -+ } -+ -+ rg = devm_kzalloc(&pdev->dev, -+ sizeof(struct ralink_gpio_chip), GFP_KERNEL); -+ if (!rg) -+ return -ENOMEM; -+ -+ rg->membase = devm_ioremap_resource(&pdev->dev, res); -+ if (!rg->membase) { -+ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); -+ return -ENOMEM; -+ } -+ -+ if (of_property_read_u8_array(np, "ralink,register-map", -+ rg->regs, GPIO_REG_MAX)) { -+ dev_err(&pdev->dev, "failed to read register definition\n"); -+ return -EINVAL; -+ } -+ -+ ngpio = of_get_property(np, "ngpios", NULL); -+ if (!ngpio) { -+ dev_err(&pdev->dev, "failed to read number of pins\n"); -+ return -EINVAL; -+ } -+ -+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); -+ if (gpiobase) -+ rg->chip.base = be32_to_cpu(*gpiobase); -+ else -+ rg->chip.base = -1; -+ -+ spin_lock_init(&rg->lock); -+ -+ rg->chip.parent = &pdev->dev; -+ rg->chip.label = dev_name(&pdev->dev); -+ rg->chip.of_node = np; -+ rg->chip.ngpio = be32_to_cpu(*ngpio); -+ rg->chip.direction_input = ralink_gpio_direction_input; -+ rg->chip.direction_output = ralink_gpio_direction_output; -+ rg->chip.get = ralink_gpio_get; -+ rg->chip.set = ralink_gpio_set; -+ rg->chip.request = gpiochip_generic_request; -+ rg->chip.to_irq = ralink_gpio_to_irq; -+ rg->chip.free = gpiochip_generic_free; -+ -+ /* set polarity to low for all lines */ -+ rt_gpio_w32(rg, GPIO_REG_POL, 0); -+ -+ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); -+ -+ ralink_gpio_irq_init(np, rg); -+ -+ return gpiochip_add(&rg->chip); -+} -+ -+static const struct of_device_id ralink_gpio_match[] = { -+ { .compatible = "ralink,rt2880-gpio" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_gpio_match); -+ -+static struct platform_driver ralink_gpio_driver = { -+ .probe = ralink_gpio_probe, -+ .driver = { -+ .name = "rt2880_gpio", -+ .owner = THIS_MODULE, -+ .of_match_table = ralink_gpio_match, -+ }, -+}; -+ -+static int __init ralink_gpio_init(void) -+{ -+ return platform_driver_register(&ralink_gpio_driver); -+} -+ -+subsys_initcall(ralink_gpio_init); diff --git a/target/linux/ramips/patches-5.15/803-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch b/target/linux/ramips/patches-5.15/803-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch deleted file mode 100644 index 8520ce32ff..0000000000 --- a/target/linux/ramips/patches-5.15/803-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 57fa7f2f4ef6f78ce1d30509c0d111aa3791b524 Mon Sep 17 00:00:00 2001 -From: Daniel Santos -Date: Sun, 4 Nov 2018 20:24:32 -0600 -Subject: gpio-ralink: Add support for GPIO as interrupt-controller - -Signed-off-by: Daniel Santos ---- - Documentation/devicetree/bindings/gpio/gpio-ralink.txt | 6 ++++++ - drivers/gpio/gpio-ralink.c | 2 +- - 2 files changed, 7 insertions(+), 1 deletion(-) - ---- a/Documentation/devicetree/bindings/gpio/gpio-ralink.txt -+++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt -@@ -17,6 +17,9 @@ Required properties: - - Optional properties: - - ralink,gpio-base : Specify the GPIO chips base number -+- interrupt-controller : marks this as an interrupt controller -+- #interrupt-cells : a standard two-cell interrupt flag, see -+ interrupt-controller/interrupts.txt - - Example: - -@@ -28,6 +31,9 @@ Example: - - reg = <0x600 0x34>; - -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ - interrupt-parent = <&intc>; - interrupts = <6>; - ---- a/drivers/gpio/gpio-ralink.c -+++ b/drivers/gpio/gpio-ralink.c -@@ -220,7 +220,7 @@ static int gpio_map(struct irq_domain *d - } - - static const struct irq_domain_ops irq_domain_ops = { -- .xlate = irq_domain_xlate_onecell, -+ .xlate = irq_domain_xlate_twocell, - .map = gpio_map, - }; - diff --git a/target/linux/ramips/patches-5.15/805-pinctrl-AW9523.patch b/target/linux/ramips/patches-5.15/805-pinctrl-AW9523.patch deleted file mode 100644 index 34220acdd1..0000000000 --- a/target/linux/ramips/patches-5.15/805-pinctrl-AW9523.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: AngeloGioacchino Del Regno - -To: linus.walleij@linaro.org -Cc: linux-kernel@vger.kernel.org, konrad.dybcio@somainline.org, - marijn.suijten@somainline.org, martin.botka@somainline.org, - phone-devel@vger.kernel.org, linux-gpio@vger.kernel.org, - devicetree@vger.kernel.org, robh+dt@kernel.org, - AngeloGioacchino Del Regno - -Subject: [PATCH v5 1/2] pinctrl: Add driver for Awinic AW9523/B I2C GPIO - Expander -Date: Mon, 25 Jan 2021 19:22:18 +0100 - -The Awinic AW9523(B) is a multi-function I2C gpio expander in a -TQFN-24L package, featuring PWM (max 37mA per pin, or total max -power 3.2Watts) for LED driving capability. - -It has two ports with 8 pins per port (for a total of 16 pins), -configurable as either PWM with 1/256 stepping or GPIO input/output, -1.8V logic input; each GPIO can be configured as input or output -independently from each other. - -This IC also has an internal interrupt controller, which is capable -of generating an interrupt for each GPIO, depending on the -configuration, and will raise an interrupt on the INTN pin to -advertise this to an external interrupt controller. - -Signed-off-by: AngeloGioacchino Del Regno ---- - drivers/pinctrl/Kconfig | 17 + - drivers/pinctrl/Makefile | 1 + - drivers/pinctrl/pinctrl-aw9523.c | 1122 ++++++++++++++++++++++++++++++ - 3 files changed, 1140 insertions(+) - create mode 100644 drivers/pinctrl/pinctrl-aw9523.c - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -111,6 +111,24 @@ config PINCTRL_AMD - Requires ACPI/FDT device enumeration code to set up a platform - device. - -+config PINCTRL_AW9523 -+ bool "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver" -+ depends on OF && I2C -+ select PINMUX -+ select PINCONF -+ select GENERIC_PINCONF -+ select GPIOLIB -+ select GPIOLIB_IRQCHIP -+ select REGMAP -+ select REGMAP_I2C -+ help -+ The Awinic AW9523/AW9523B is a multi-function I2C GPIO -+ expander with PWM functionality. This driver bundles a -+ pinctrl driver to select the function muxing and a GPIO -+ driver to handle GPIO, when the GPIO function is selected. -+ -+ Say yes to enable pinctrl and GPIO support for the AW9523(B). -+ - config PINCTRL_BM1880 - bool "Bitmain BM1880 Pinctrl driver" - depends on OF && (ARCH_BITMAIN || COMPILE_TEST) ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_AXP209) += pinctrl- - obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o - obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o - obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o -+obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o - obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o - obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o - obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o diff --git a/target/linux/ramips/patches-5.15/808-pinctrl-mtmips-support-requesting-different-function.patch b/target/linux/ramips/patches-5.15/808-pinctrl-mtmips-support-requesting-different-function.patch deleted file mode 100644 index 047808f1e6..0000000000 --- a/target/linux/ramips/patches-5.15/808-pinctrl-mtmips-support-requesting-different-function.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Shiji Yang -Date: Wed, 26 Jul 2023 01:32:55 +0800 -Subject: [PATCH] pinctrl: mtmips: support requesting different functions for - same group - -Sometimes pinctrl consumers may request different functions for the -same pin group in different situations. This patch can help to reset -the group function flag when requesting a different function. - -Signed-off-by: Shiji Yang ---- - drivers/pinctrl/ralink/pinctrl-ralink.c | 21 +++++++++++++++++---- - 1 file changed, 17 insertions(+), 4 deletions(-) - ---- a/drivers/pinctrl/ralink/pinctrl-ralink.c -+++ b/drivers/pinctrl/ralink/pinctrl-ralink.c -@@ -123,11 +123,24 @@ static int ralink_pmx_group_enable(struc - int i; - int shift; - -- /* dont allow double use */ -+ /* -+ * for the same pin group, if request a different function, -+ * then clear the group function flag and continue, else exit. -+ */ - if (p->groups[group].enabled) { -- dev_err(p->dev, "%s is already enabled\n", -- p->groups[group].name); -- return 0; -+ for (i = 0; i < p->groups[group].func_count; i++) { -+ if (p->groups[group].func[i].enabled == 1) { -+ if (!strcmp(p->func[func]->name, -+ p->groups[group].func[i].name)) -+ return 0; -+ p->groups[group].func[i].enabled = 0; -+ break; -+ } -+ } -+ -+ /* exit if request the "gpio" function again */ -+ if (i == p->groups[group].func_count && func == 0) -+ return 0; - } - - p->groups[group].enabled = 1; diff --git a/target/linux/ramips/patches-5.15/810-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-5.15/810-uvc-add-iPassion-iP2970-support.patch deleted file mode 100644 index 88809ae68d..0000000000 --- a/target/linux/ramips/patches-5.15/810-uvc-add-iPassion-iP2970-support.patch +++ /dev/null @@ -1,244 +0,0 @@ -From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 19 Sep 2013 01:50:59 +0200 -Subject: [PATCH 31/53] uvc: add iPassion iP2970 support - -Signed-off-by: John Crispin ---- - drivers/media/usb/uvc/uvc_driver.c | 12 +++ - drivers/media/usb/uvc/uvc_status.c | 2 + - drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++ - drivers/media/usb/uvc/uvcvideo.h | 5 +- - 4 files changed, 165 insertions(+), 1 deletion(-) - ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -3158,6 +3158,18 @@ static const struct usb_device_id uvc_id - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, -+ /* iPassion iP2970 */ -+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE -+ | USB_DEVICE_ID_MATCH_INT_INFO, -+ .idVendor = 0x1B3B, -+ .idProduct = 0x2970, -+ .bInterfaceClass = USB_CLASS_VIDEO, -+ .bInterfaceSubClass = 1, -+ .bInterfaceProtocol = 0, -+ .driver_info = UVC_QUIRK_PROBE_MINMAX -+ | UVC_QUIRK_STREAM_NO_FID -+ | UVC_QUIRK_MOTION -+ | UVC_QUIRK_SINGLE_ISO }, - /* Generic USB Video Class */ - { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, - { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, ---- a/drivers/media/usb/uvc/uvc_status.c -+++ b/drivers/media/usb/uvc/uvc_status.c -@@ -224,6 +224,7 @@ static void uvc_status_complete(struct u - if (uvc_event_control(urb, status, len)) - /* The URB will be resubmitted in work context. */ - return; -+ dev->motion = 1; - break; - } - -@@ -272,6 +273,7 @@ int uvc_status_init(struct uvc_device *d - } - - pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); -+ dev->motion = 0; - - /* For high-speed interrupt endpoints, the bInterval value is used as - * an exponent of two. Some developers forgot about it. ---- a/drivers/media/usb/uvc/uvc_video.c -+++ b/drivers/media/usb/uvc/uvc_video.c -@@ -19,6 +19,11 @@ - #include - #include - #include -+#include -+#include -+#include -+#include -+#include - - #include - -@@ -1214,9 +1219,149 @@ static void uvc_video_decode_data(struct - uvc_urb->async_operations++; - } - -+struct bh_priv { -+ unsigned long seen; -+}; -+ -+struct bh_event { -+ const char *name; -+ struct sk_buff *skb; -+ struct work_struct work; -+}; -+ -+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args ) -+#define BH_DBG(fmt, args...) do {} while (0) -+#define BH_SKB_SIZE 2048 -+ -+extern u64 uevent_next_seqnum(void); -+static int seen = 0; -+ -+static int bh_event_add_var(struct bh_event *event, int argv, -+ const char *format, ...) -+{ -+ static char buf[128]; -+ char *s; -+ va_list args; -+ int len; -+ -+ if (argv) -+ return 0; -+ -+ va_start(args, format); -+ len = vsnprintf(buf, sizeof(buf), format, args); -+ va_end(args); -+ -+ if (len >= sizeof(buf)) { -+ BH_ERR("buffer size too small\n"); -+ WARN_ON(1); -+ return -ENOMEM; -+ } -+ -+ s = skb_put(event->skb, len + 1); -+ strcpy(s, buf); -+ -+ BH_DBG("added variable '%s'\n", s); -+ -+ return 0; -+} -+ -+static int motion_hotplug_fill_event(struct bh_event *event) -+{ -+ int s = jiffies; -+ int ret; -+ -+ if (!seen) -+ seen = jiffies; -+ -+ ret = bh_event_add_var(event, 0, "HOME=%s", "/"); -+ if (ret) -+ return ret; -+ -+ ret = bh_event_add_var(event, 0, "PATH=%s", -+ "/sbin:/bin:/usr/sbin:/usr/bin"); -+ if (ret) -+ return ret; -+ -+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb"); -+ if (ret) -+ return ret; -+ -+ ret = bh_event_add_var(event, 0, "ACTION=motion"); -+ if (ret) -+ return ret; -+ -+ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen); -+ if (ret) -+ return ret; -+ seen = s; -+ -+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); -+ -+ return ret; -+} -+ -+static void motion_hotplug_work(struct work_struct *work) -+{ -+ struct bh_event *event = container_of(work, struct bh_event, work); -+ int ret = 0; -+ -+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); -+ if (!event->skb) -+ goto out_free_event; -+ -+ ret = bh_event_add_var(event, 0, "%s@", "add"); -+ if (ret) -+ goto out_free_skb; -+ -+ ret = motion_hotplug_fill_event(event); -+ if (ret) -+ goto out_free_skb; -+ -+ NETLINK_CB(event->skb).dst_group = 1; -+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); -+ -+out_free_skb: -+ if (ret) { -+ BH_ERR("work error %d\n", ret); -+ kfree_skb(event->skb); -+ } -+out_free_event: -+ kfree(event); -+} -+ -+static int motion_hotplug_create_event(void) -+{ -+ struct bh_event *event; -+ -+ event = kzalloc(sizeof(*event), GFP_KERNEL); -+ if (!event) -+ return -ENOMEM; -+ -+ event->name = "motion"; -+ -+ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work); -+ schedule_work(&event->work); -+ -+ return 0; -+} -+ -+#define MOTION_FLAG_OFFSET 4 - static void uvc_video_decode_end(struct uvc_streaming *stream, - struct uvc_buffer *buf, const u8 *data, int len) - { -+ if ((stream->dev->quirks & UVC_QUIRK_MOTION) && -+ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { -+ u8 *mem; -+ buf->state = UVC_BUF_STATE_READY; -+ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET); -+ if ( stream->dev->motion ) { -+ stream->dev->motion = 0; -+ motion_hotplug_create_event(); -+ } else { -+ *mem &= 0x7f; -+ } -+ } -+ - /* Mark the buffer as done if the EOF marker is set. */ - if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { - uvc_dbg(stream->dev, FRAME, "Frame complete (EOF found)\n"); -@@ -1801,6 +1946,8 @@ static int uvc_init_video_isoc(struct uv - if (npackets == 0) - return -ENOMEM; - -+ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO) -+ npackets = 1; - size = npackets * psize; - - for_each_uvc_urb(uvc_urb, stream) { ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -210,6 +210,8 @@ - #define UVC_QUIRK_FORCE_Y8 0x00000800 - #define UVC_QUIRK_FORCE_BPP 0x00001000 - #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000 -+#define UVC_QUIRK_MOTION 0x00004000 -+#define UVC_QUIRK_SINGLE_ISO 0x00008000 - - /* Format flags */ - #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -@@ -701,6 +703,7 @@ struct uvc_device { - u8 *status; - struct input_dev *input; - char input_phys[64]; -+ int motion; - - struct uvc_ctrl_work { - struct work_struct work; diff --git a/target/linux/ramips/patches-5.15/820-DT-Add-documentation-for-spi-rt2880.patch b/target/linux/ramips/patches-5.15/820-DT-Add-documentation-for-spi-rt2880.patch deleted file mode 100644 index e2643e3f25..0000000000 --- a/target/linux/ramips/patches-5.15/820-DT-Add-documentation-for-spi-rt2880.patch +++ /dev/null @@ -1,44 +0,0 @@ -From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 9 Aug 2013 20:12:59 +0200 -Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880 - -Describe the SPI master found on the MIPS based Ralink RT2880 SoC. - -Signed-off-by: John Crispin ---- - .../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++ - 1 file changed, 28 insertions(+) - create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt -@@ -0,0 +1,28 @@ -+Ralink SoC RT2880 SPI master controller. -+ -+This SPI controller is found on most wireless SoCs made by ralink. -+ -+Required properties: -+- compatible : "ralink,rt2880-spi" -+- reg : The register base for the controller. -+- #address-cells : <1>, as required by generic SPI binding. -+- #size-cells : <0>, also as required by generic SPI binding. -+ -+Child nodes as per the generic SPI binding. -+ -+Example: -+ -+ spi@b00 { -+ compatible = "ralink,rt2880-spi"; -+ reg = <0xb00 0x100>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ m25p80@0 { -+ compatible = "m25p80"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ }; -+ }; -+ diff --git a/target/linux/ramips/patches-5.15/821-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-5.15/821-SPI-ralink-add-Ralink-SoC-spi-driver.patch deleted file mode 100644 index fa119ab211..0000000000 --- a/target/linux/ramips/patches-5.15/821-SPI-ralink-add-Ralink-SoC-spi-driver.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 683af4ebb91a1600df1946ac4769d916b8a1be65 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 11:15:12 +0100 -Subject: [PATCH 42/53] SPI: ralink: add Ralink SoC spi driver - -Add the driver needed to make SPI work on Ralink SoC. - -Signed-off-by: Gabor Juhos -Acked-by: John Crispin ---- - drivers/spi/Kconfig | 6 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-rt2880.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 537 insertions(+) - create mode 100644 drivers/spi/spi-rt2880.c - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -718,6 +718,12 @@ config SPI_QCOM_GENI - This driver can also be built as a module. If so, the module - will be called spi-geni-qcom. - -+config SPI_RT2880 -+ tristate "Ralink RT288x SPI Controller" -+ depends on RALINK -+ help -+ This selects a driver for the Ralink RT288x/RT305x SPI Controller. -+ - config SPI_S3C24XX - tristate "Samsung S3C24XX series SPI" - depends on ARCH_S3C24XX ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -100,6 +100,7 @@ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o - obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o - obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o - obj-$(CONFIG_SPI_RSPI) += spi-rspi.o -+obj-$(CONFIG_SPI_RT2880) += spi-rt2880.o - obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o - spi-s3c24xx-hw-y := spi-s3c24xx.o - obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o ---- /dev/null -+++ b/drivers/spi/spi-rt2880.c -@@ -0,0 +1,535 @@ -+/* -+ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver -+ * -+ * Copyright (C) 2011 Sergiy -+ * Copyright (C) 2011-2013 Gabor Juhos -+ * -+ * Some parts are based on spi-orion.c: -+ * Author: Shadi Ammouri -+ * Copyright (C) 2007-2008 Marvell Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "spi-rt2880" -+ -+#define RAMIPS_SPI_STAT 0x00 -+#define RAMIPS_SPI_CFG 0x10 -+#define RAMIPS_SPI_CTL 0x14 -+#define RAMIPS_SPI_DATA 0x20 -+#define RAMIPS_SPI_ADDR 0x24 -+#define RAMIPS_SPI_BS 0x28 -+#define RAMIPS_SPI_USER 0x2C -+#define RAMIPS_SPI_TXFIFO 0x30 -+#define RAMIPS_SPI_RXFIFO 0x34 -+#define RAMIPS_SPI_FIFO_STAT 0x38 -+#define RAMIPS_SPI_MODE 0x3C -+#define RAMIPS_SPI_DEV_OFFSET 0x40 -+#define RAMIPS_SPI_DMA 0x80 -+#define RAMIPS_SPI_DMASTAT 0x84 -+#define RAMIPS_SPI_ARBITER 0xF0 -+ -+/* SPISTAT register bit field */ -+#define SPISTAT_BUSY BIT(0) -+ -+/* SPICFG register bit field */ -+#define SPICFG_ADDRMODE BIT(12) -+#define SPICFG_RXENVDIS BIT(11) -+#define SPICFG_RXCAP BIT(10) -+#define SPICFG_SPIENMODE BIT(9) -+#define SPICFG_MSBFIRST BIT(8) -+#define SPICFG_SPICLKPOL BIT(6) -+#define SPICFG_RXCLKEDGE_FALLING BIT(5) -+#define SPICFG_TXCLKEDGE_FALLING BIT(4) -+#define SPICFG_HIZSPI BIT(3) -+#define SPICFG_SPICLK_PRESCALE_MASK 0x7 -+#define SPICFG_SPICLK_DIV2 0 -+#define SPICFG_SPICLK_DIV4 1 -+#define SPICFG_SPICLK_DIV8 2 -+#define SPICFG_SPICLK_DIV16 3 -+#define SPICFG_SPICLK_DIV32 4 -+#define SPICFG_SPICLK_DIV64 5 -+#define SPICFG_SPICLK_DIV128 6 -+#define SPICFG_SPICLK_DISABLE 7 -+ -+/* SPICTL register bit field */ -+#define SPICTL_START BIT(4) -+#define SPICTL_HIZSDO BIT(3) -+#define SPICTL_STARTWR BIT(2) -+#define SPICTL_STARTRD BIT(1) -+#define SPICTL_SPIENA BIT(0) -+ -+/* SPIUSER register bit field */ -+#define SPIUSER_USERMODE BIT(21) -+#define SPIUSER_INSTR_PHASE BIT(20) -+#define SPIUSER_ADDR_PHASE_MASK 0x7 -+#define SPIUSER_ADDR_PHASE_OFFSET 17 -+#define SPIUSER_MODE_PHASE BIT(16) -+#define SPIUSER_DUMMY_PHASE_MASK 0x3 -+#define SPIUSER_DUMMY_PHASE_OFFSET 14 -+#define SPIUSER_DATA_PHASE_MASK 0x3 -+#define SPIUSER_DATA_PHASE_OFFSET 12 -+#define SPIUSER_DATA_READ (BIT(0) << SPIUSER_DATA_PHASE_OFFSET) -+#define SPIUSER_DATA_WRITE (BIT(1) << SPIUSER_DATA_PHASE_OFFSET) -+#define SPIUSER_ADDR_TYPE_OFFSET 9 -+#define SPIUSER_MODE_TYPE_OFFSET 6 -+#define SPIUSER_DUMMY_TYPE_OFFSET 3 -+#define SPIUSER_DATA_TYPE_OFFSET 0 -+#define SPIUSER_TRANSFER_MASK 0x7 -+#define SPIUSER_TRANSFER_SINGLE BIT(0) -+#define SPIUSER_TRANSFER_DUAL BIT(1) -+#define SPIUSER_TRANSFER_QUAD BIT(2) -+ -+#define SPIUSER_TRANSFER_TYPE(type) ( \ -+ (type << SPIUSER_ADDR_TYPE_OFFSET) | \ -+ (type << SPIUSER_MODE_TYPE_OFFSET) | \ -+ (type << SPIUSER_DUMMY_TYPE_OFFSET) | \ -+ (type << SPIUSER_DATA_TYPE_OFFSET) \ -+) -+ -+/* SPIFIFOSTAT register bit field */ -+#define SPIFIFOSTAT_TXEMPTY BIT(19) -+#define SPIFIFOSTAT_RXEMPTY BIT(18) -+#define SPIFIFOSTAT_TXFULL BIT(17) -+#define SPIFIFOSTAT_RXFULL BIT(16) -+#define SPIFIFOSTAT_FIFO_MASK 0xff -+#define SPIFIFOSTAT_TX_OFFSET 8 -+#define SPIFIFOSTAT_RX_OFFSET 0 -+ -+#define SPI_FIFO_DEPTH 16 -+ -+/* SPIMODE register bit field */ -+#define SPIMODE_MODE_OFFSET 24 -+#define SPIMODE_DUMMY_OFFSET 0 -+ -+/* SPIARB register bit field */ -+#define SPICTL_ARB_EN BIT(31) -+#define SPICTL_CSCTL1 BIT(16) -+#define SPI1_POR BIT(1) -+#define SPI0_POR BIT(0) -+ -+#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \ -+ SPI_CS_HIGH) -+ -+static atomic_t hw_reset_count = ATOMIC_INIT(0); -+ -+struct rt2880_spi { -+ struct spi_master *master; -+ void __iomem *base; -+ u32 speed; -+ u16 wait_loops; -+ u16 mode; -+ struct clk *clk; -+}; -+ -+static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) -+{ -+ return spi_master_get_devdata(spi->master); -+} -+ -+static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg) -+{ -+ return ioread32(rs->base + reg); -+} -+ -+static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, -+ const u32 val) -+{ -+ iowrite32(val, rs->base + reg); -+} -+ -+static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask) -+{ -+ void __iomem *addr = rs->base + reg; -+ -+ iowrite32((ioread32(addr) | mask), addr); -+} -+ -+static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask) -+{ -+ void __iomem *addr = rs->base + reg; -+ -+ iowrite32((ioread32(addr) & ~mask), addr); -+} -+ -+static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed) -+{ -+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); -+ u32 rate; -+ u32 prescale; -+ -+ /* -+ * the supported rates are: 2, 4, 8, ... 128 -+ * round up as we look for equal or less speed -+ */ -+ rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed); -+ rate = roundup_pow_of_two(rate); -+ -+ /* Convert the rate to SPI clock divisor value. */ -+ prescale = ilog2(rate / 2); -+ -+ /* some tolerance. double and add 100 */ -+ rs->wait_loops = (8 * HZ * loops_per_jiffy) / -+ (clk_get_rate(rs->clk) / rate); -+ rs->wait_loops = (rs->wait_loops << 1) + 100; -+ rs->speed = speed; -+ -+ dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n", -+ clk_get_rate(rs->clk) / rate, speed, rate, prescale, -+ rs->wait_loops); -+ -+ return prescale; -+} -+ -+static u32 get_arbiter_offset(struct spi_master *master) -+{ -+ u32 offset; -+ -+ offset = RAMIPS_SPI_ARBITER; -+ if (master->bus_num == 1) -+ offset -= RAMIPS_SPI_DEV_OFFSET; -+ -+ return offset; -+} -+ -+static void rt2880_spi_set_cs(struct spi_device *spi, bool enable) -+{ -+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); -+ -+ if (enable) -+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); -+ else -+ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); -+} -+ -+static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len) -+{ -+ int loop = rs->wait_loops * len; -+ -+ while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop) -+ cpu_relax(); -+ -+ if (loop) -+ return 0; -+ -+ return -ETIMEDOUT; -+} -+ -+static void rt2880_dump_reg(struct spi_master *master) -+{ -+ struct rt2880_spi *rs = spi_master_get_devdata(master); -+ -+ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \ -+ "data: %08x, arb: %08x\n", -+ rt2880_spi_read(rs, RAMIPS_SPI_STAT), -+ rt2880_spi_read(rs, RAMIPS_SPI_CFG), -+ rt2880_spi_read(rs, RAMIPS_SPI_CTL), -+ rt2880_spi_read(rs, RAMIPS_SPI_DATA), -+ rt2880_spi_read(rs, get_arbiter_offset(master))); -+} -+ -+static int rt2880_spi_transfer_one(struct spi_master *master, -+ struct spi_device *spi, struct spi_transfer *xfer) -+{ -+ struct rt2880_spi *rs = spi_master_get_devdata(master); -+ unsigned len; -+ const u8 *tx = xfer->tx_buf; -+ u8 *rx = xfer->rx_buf; -+ int err = 0; -+ -+ /* change clock speed */ -+ if (unlikely(rs->speed != xfer->speed_hz)) { -+ u32 reg; -+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); -+ reg &= ~SPICFG_SPICLK_PRESCALE_MASK; -+ reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz); -+ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); -+ } -+ -+ if (tx) { -+ len = xfer->len; -+ while (len-- > 0) { -+ rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++); -+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); -+ err = rt2880_spi_wait_ready(rs, 1); -+ if (err) { -+ dev_err(&spi->dev, "TX failed, err=%d\n", err); -+ goto out; -+ } -+ } -+ } -+ -+ if (rx) { -+ len = xfer->len; -+ while (len-- > 0) { -+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); -+ err = rt2880_spi_wait_ready(rs, 1); -+ if (err) { -+ dev_err(&spi->dev, "RX failed, err=%d\n", err); -+ goto out; -+ } -+ *rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); -+ } -+ } -+ -+out: -+ return err; -+} -+ -+/* copy from spi.c */ -+static void spi_set_cs(struct spi_device *spi, bool enable) -+{ -+ if (spi->mode & SPI_CS_HIGH) -+ enable = !enable; -+ -+ if (spi->cs_gpio >= 0) -+ gpio_set_value(spi->cs_gpio, !enable); -+ else if (spi->master->set_cs) -+ spi->master->set_cs(spi, !enable); -+} -+ -+static int rt2880_spi_setup(struct spi_device *spi) -+{ -+ struct spi_master *master = spi->master; -+ struct rt2880_spi *rs = spi_master_get_devdata(master); -+ u32 reg, old_reg, arbit_off; -+ -+ if ((spi->max_speed_hz > master->max_speed_hz) || -+ (spi->max_speed_hz < master->min_speed_hz)) { -+ dev_err(&spi->dev, "invalide requested speed %d Hz\n", -+ spi->max_speed_hz); -+ return -EINVAL; -+ } -+ -+ if (!(master->bits_per_word_mask & -+ BIT(spi->bits_per_word - 1))) { -+ dev_err(&spi->dev, "invalide bits_per_word %d\n", -+ spi->bits_per_word); -+ return -EINVAL; -+ } -+ -+ /* the hardware seems can't work on mode0 force it to mode3 */ -+ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) { -+ dev_warn(&spi->dev, "force spi mode3\n"); -+ spi->mode |= SPI_MODE_3; -+ } -+ -+ /* chip polarity */ -+ arbit_off = get_arbiter_offset(master); -+ reg = old_reg = rt2880_spi_read(rs, arbit_off); -+ if (spi->mode & SPI_CS_HIGH) { -+ switch (master->bus_num) { -+ case 1: -+ reg |= SPI1_POR; -+ break; -+ default: -+ reg |= SPI0_POR; -+ break; -+ } -+ } else { -+ switch (master->bus_num) { -+ case 1: -+ reg &= ~SPI1_POR; -+ break; -+ default: -+ reg &= ~SPI0_POR; -+ break; -+ } -+ } -+ -+ /* enable spi1 */ -+ if (master->bus_num == 1) -+ reg |= SPICTL_ARB_EN; -+ -+ if (reg != old_reg) -+ rt2880_spi_write(rs, arbit_off, reg); -+ -+ /* deselected the spi device */ -+ spi_set_cs(spi, false); -+ -+ rt2880_dump_reg(master); -+ -+ return 0; -+} -+ -+static int rt2880_spi_prepare_message(struct spi_master *master, -+ struct spi_message *msg) -+{ -+ struct rt2880_spi *rs = spi_master_get_devdata(master); -+ struct spi_device *spi = msg->spi; -+ u32 reg; -+ -+ if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz)) -+ return 0; -+ -+#if 0 -+ /* set spido to tri-state */ -+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO); -+#endif -+ -+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); -+ -+ reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL | -+ SPICFG_RXCLKEDGE_FALLING | -+ SPICFG_TXCLKEDGE_FALLING | -+ SPICFG_SPICLK_PRESCALE_MASK); -+ -+ /* MSB */ -+ if (!(spi->mode & SPI_LSB_FIRST)) -+ reg |= SPICFG_MSBFIRST; -+ -+ /* spi mode */ -+ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { -+ case SPI_MODE_0: -+ reg |= SPICFG_TXCLKEDGE_FALLING; -+ break; -+ case SPI_MODE_1: -+ reg |= SPICFG_RXCLKEDGE_FALLING; -+ break; -+ case SPI_MODE_2: -+ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING; -+ break; -+ case SPI_MODE_3: -+ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING; -+ break; -+ } -+ rs->mode = spi->mode; -+ -+#if 0 -+ /* set spiclk and spiena to tri-state */ -+ reg |= SPICFG_HIZSPI; -+#endif -+ -+ /* clock divide */ -+ reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz); -+ -+ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); -+ -+ return 0; -+} -+ -+static int rt2880_spi_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct rt2880_spi *rs; -+ void __iomem *base; -+ struct resource *r; -+ struct clk *clk; -+ int ret; -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, r); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "unable to get SYS clock\n"); -+ return PTR_ERR(clk); -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret) -+ goto err_clk; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); -+ if (master == NULL) { -+ dev_dbg(&pdev->dev, "master allocation failed\n"); -+ ret = -ENOMEM; -+ goto err_clk; -+ } -+ -+ master->dev.of_node = pdev->dev.of_node; -+ master->mode_bits = RT2880_SPI_MODE_BITS; -+ master->bits_per_word_mask = SPI_BPW_MASK(8); -+ master->min_speed_hz = clk_get_rate(clk) / 128; -+ master->max_speed_hz = clk_get_rate(clk) / 2; -+ master->flags = SPI_MASTER_HALF_DUPLEX; -+ master->setup = rt2880_spi_setup; -+ master->prepare_message = rt2880_spi_prepare_message; -+ master->set_cs = rt2880_spi_set_cs; -+ master->transfer_one = rt2880_spi_transfer_one, -+ -+ dev_set_drvdata(&pdev->dev, master); -+ -+ rs = spi_master_get_devdata(master); -+ rs->master = master; -+ rs->base = base; -+ rs->clk = clk; -+ -+ if (atomic_inc_return(&hw_reset_count) == 1) { -+ ret = device_reset(&pdev->dev); -+ if (ret) { -+ dev_err(&pdev->dev, "device_reset error.\n"); -+ goto err_master; -+ } -+ } -+ -+ ret = devm_spi_register_master(&pdev->dev, master); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "devm_spi_register_master error.\n"); -+ goto err_master; -+ } -+ -+ return ret; -+ -+err_master: -+ spi_master_put(master); -+ kfree(master); -+err_clk: -+ clk_disable_unprepare(clk); -+ -+ return ret; -+} -+ -+static int rt2880_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct rt2880_spi *rs; -+ -+ master = dev_get_drvdata(&pdev->dev); -+ rs = spi_master_get_devdata(master); -+ -+ clk_disable_unprepare(rs->clk); -+ atomic_dec(&hw_reset_count); -+ -+ return 0; -+} -+ -+MODULE_ALIAS("platform:" DRIVER_NAME); -+ -+static const struct of_device_id rt2880_spi_match[] = { -+ { .compatible = "ralink,rt2880-spi" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rt2880_spi_match); -+ -+static struct platform_driver rt2880_spi_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = rt2880_spi_match, -+ }, -+ .probe = rt2880_spi_probe, -+ .remove = rt2880_spi_remove, -+}; -+ -+module_platform_driver(rt2880_spi_driver); -+ -+MODULE_DESCRIPTION("Ralink SPI driver"); -+MODULE_AUTHOR("Sergiy "); -+MODULE_AUTHOR("Gabor Juhos "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-5.15/825-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-5.15/825-i2c-MIPS-adds-ralink-I2C-driver.patch deleted file mode 100644 index da6f8e5a1e..0000000000 --- a/target/linux/ramips/patches-5.15/825-i2c-MIPS-adds-ralink-I2C-driver.patch +++ /dev/null @@ -1,512 +0,0 @@ -From 723b8beaabf3c3c4b1ce69480141f1e926f3f3b2 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:52:56 +0100 -Subject: [PATCH 44/53] i2c: MIPS: adds ralink I2C driver - -Signed-off-by: John Crispin ---- - .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++ - drivers/i2c/busses/Kconfig | 4 + - drivers/i2c/busses/Makefile | 1 + - drivers/i2c/busses/i2c-ralink.c | 327 ++++++++++++++++++++ - 4 files changed, 359 insertions(+) - create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt - create mode 100644 drivers/i2c/busses/i2c-ralink.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt -@@ -0,0 +1,27 @@ -+I2C for Ralink platforms -+ -+Required properties : -+- compatible : Must be "link,rt3052-i2c" -+- reg: physical base address of the controller and length of memory mapped -+ region. -+- #address-cells = <1>; -+- #size-cells = <0>; -+ -+Optional properties: -+- Child nodes conforming to i2c bus binding -+ -+Example : -+ -+palmbus@10000000 { -+ i2c@900 { -+ compatible = "link,rt3052-i2c"; -+ reg = <0x900 0x100>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hwmon@4b { -+ compatible = "national,lm92"; -+ reg = <0x4b>; -+ }; -+ }; -+}; ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -949,6 +949,11 @@ config I2C_RK3X - This driver can also be built as a module. If so, the module will - be called i2c-rk3x. - -+config I2C_RALINK -+ tristate "Ralink I2C Controller" -+ depends on RALINK && !SOC_MT7621 -+ select OF_I2C -+ - config HAVE_S3C2410_I2C - bool - help ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -89,6 +89,7 @@ obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pc - obj-$(CONFIG_I2C_PNX) += i2c-pnx.o - obj-$(CONFIG_I2C_PXA) += i2c-pxa.o - obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o -+obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o - obj-$(CONFIG_I2C_QCOM_CCI) += i2c-qcom-cci.o - obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o - obj-$(CONFIG_I2C_QUP) += i2c-qup.o ---- /dev/null -+++ b/drivers/i2c/busses/i2c-ralink.c -@@ -0,0 +1,440 @@ -+/* -+ * drivers/i2c/busses/i2c-ralink.c -+ * -+ * Copyright (C) 2013 Steven Liu -+ * Copyright (C) 2016 Michael Lee -+ * -+ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. -+ * (C) 2014 Sittisak -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define REG_CONFIG_REG 0x00 -+#define REG_CLKDIV_REG 0x04 -+#define REG_DEVADDR_REG 0x08 -+#define REG_ADDR_REG 0x0C -+#define REG_DATAOUT_REG 0x10 -+#define REG_DATAIN_REG 0x14 -+#define REG_STATUS_REG 0x18 -+#define REG_STARTXFR_REG 0x1C -+#define REG_BYTECNT_REG 0x20 -+ -+/* REG_CONFIG_REG */ -+#define I2C_ADDRLEN_OFFSET 5 -+#define I2C_DEVADLEN_OFFSET 2 -+#define I2C_ADDRLEN_MASK 0x3 -+#define I2C_ADDR_DIS BIT(1) -+#define I2C_DEVADDR_DIS BIT(0) -+#define I2C_ADDRLEN_8 (7 << I2C_ADDRLEN_OFFSET) -+#define I2C_DEVADLEN_7 (6 << I2C_DEVADLEN_OFFSET) -+#define I2C_CONF_DEFAULT (I2C_ADDRLEN_8 | I2C_DEVADLEN_7) -+ -+/* REG_CLKDIV_REG */ -+#define I2C_CLKDIV_MASK 0xffff -+ -+/* REG_DEVADDR_REG */ -+#define I2C_DEVADDR_MASK 0x7f -+ -+/* REG_ADDR_REG */ -+#define I2C_ADDR_MASK 0xff -+ -+/* REG_STATUS_REG */ -+#define I2C_STARTERR BIT(4) -+#define I2C_ACKERR BIT(3) -+#define I2C_DATARDY BIT(2) -+#define I2C_SDOEMPTY BIT(1) -+#define I2C_BUSY BIT(0) -+ -+/* REG_STARTXFR_REG */ -+#define NOSTOP_CMD BIT(2) -+#define NODATA_CMD BIT(1) -+#define READ_CMD BIT(0) -+ -+/* REG_BYTECNT_REG */ -+#define BYTECNT_MAX 64 -+#define SET_BYTECNT(x) (x - 1) -+ -+/* timeout waiting for I2C devices to respond (clock streching) */ -+#define TIMEOUT_MS 1000 -+#define DELAY_INTERVAL_US 100 -+ -+struct rt_i2c { -+ void __iomem *base; -+ struct clk *clk; -+ struct device *dev; -+ struct i2c_adapter adap; -+ u32 cur_clk; -+ u32 clk_div; -+ u32 flags; -+}; -+ -+static void rt_i2c_w32(struct rt_i2c *i2c, u32 val, unsigned reg) -+{ -+ iowrite32(val, i2c->base + reg); -+} -+ -+static u32 rt_i2c_r32(struct rt_i2c *i2c, unsigned reg) -+{ -+ return ioread32(i2c->base + reg); -+} -+ -+static int poll_down_timeout(void __iomem *addr, u32 mask) -+{ -+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); -+ -+ do { -+ if (!(readl_relaxed(addr) & mask)) -+ return 0; -+ -+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); -+ } while (time_before(jiffies, timeout)); -+ -+ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; -+} -+ -+static int rt_i2c_wait_idle(struct rt_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_down_timeout(i2c->base + REG_STATUS_REG, I2C_BUSY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "idle err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static int poll_up_timeout(void __iomem *addr, u32 mask) -+{ -+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); -+ u32 status; -+ -+ do { -+ status = readl_relaxed(addr); -+ -+ /* check error status */ -+ if (status & I2C_STARTERR) -+ return -EAGAIN; -+ else if (status & I2C_ACKERR) -+ return -ENXIO; -+ else if (status & mask) -+ return 0; -+ -+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); -+ } while (time_before(jiffies, timeout)); -+ -+ return -ETIMEDOUT; -+} -+ -+static int rt_i2c_wait_rx_done(struct rt_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_DATARDY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "rx err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static int rt_i2c_wait_tx_done(struct rt_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_SDOEMPTY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "tx err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static void rt_i2c_reset(struct rt_i2c *i2c) -+{ -+ int ret; -+ -+ ret = device_reset(i2c->adap.dev.parent); -+ if (ret) -+ dev_err(i2c->dev, "Failed to reset device"); -+ -+ barrier(); -+ rt_i2c_w32(i2c, i2c->clk_div, REG_CLKDIV_REG); -+} -+ -+static void rt_i2c_dump_reg(struct rt_i2c *i2c) -+{ -+ dev_dbg(i2c->dev, "conf %08x, clkdiv %08x, devaddr %08x, " \ -+ "addr %08x, dataout %08x, datain %08x, " \ -+ "status %08x, startxfr %08x, bytecnt %08x\n", -+ rt_i2c_r32(i2c, REG_CONFIG_REG), -+ rt_i2c_r32(i2c, REG_CLKDIV_REG), -+ rt_i2c_r32(i2c, REG_DEVADDR_REG), -+ rt_i2c_r32(i2c, REG_ADDR_REG), -+ rt_i2c_r32(i2c, REG_DATAOUT_REG), -+ rt_i2c_r32(i2c, REG_DATAIN_REG), -+ rt_i2c_r32(i2c, REG_STATUS_REG), -+ rt_i2c_r32(i2c, REG_STARTXFR_REG), -+ rt_i2c_r32(i2c, REG_BYTECNT_REG)); -+} -+ -+static int rt_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, -+ int num) -+{ -+ struct rt_i2c *i2c; -+ struct i2c_msg *pmsg; -+ unsigned char addr; -+ int i, j, ret; -+ u32 cmd; -+ -+ i2c = i2c_get_adapdata(adap); -+ -+ for (i = 0; i < num; i++) { -+ pmsg = &msgs[i]; -+ if (i == (num - 1)) -+ cmd = 0; -+ else -+ cmd = NOSTOP_CMD; -+ -+ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x, stop: %d\n", -+ pmsg->addr, pmsg->len, pmsg->flags, -+ (cmd == 0)? 1 : 0); -+ -+ /* wait hardware idle */ -+ if ((ret = rt_i2c_wait_idle(i2c))) -+ goto err_timeout; -+ -+ if (pmsg->flags & I2C_M_TEN) { -+ rt_i2c_w32(i2c, I2C_CONF_DEFAULT, REG_CONFIG_REG); -+ /* 10 bits address */ -+ addr = 0x78 | ((pmsg->addr >> 8) & 0x03); -+ rt_i2c_w32(i2c, addr & I2C_DEVADDR_MASK, -+ REG_DEVADDR_REG); -+ rt_i2c_w32(i2c, pmsg->addr & I2C_ADDR_MASK, -+ REG_ADDR_REG); -+ } else { -+ rt_i2c_w32(i2c, I2C_CONF_DEFAULT | I2C_ADDR_DIS, -+ REG_CONFIG_REG); -+ /* 7 bits address */ -+ rt_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, -+ REG_DEVADDR_REG); -+ } -+ -+ /* buffer length */ -+ if (pmsg->len == 0) -+ cmd |= NODATA_CMD; -+ else -+ rt_i2c_w32(i2c, SET_BYTECNT(pmsg->len), -+ REG_BYTECNT_REG); -+ -+ j = 0; -+ if (pmsg->flags & I2C_M_RD) { -+ cmd |= READ_CMD; -+ /* start transfer */ -+ barrier(); -+ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); -+ do { -+ /* wait */ -+ if ((ret = rt_i2c_wait_rx_done(i2c))) -+ goto err_timeout; -+ /* read data */ -+ if (pmsg->len) -+ pmsg->buf[j] = rt_i2c_r32(i2c, -+ REG_DATAIN_REG); -+ j++; -+ } while (j < pmsg->len); -+ } else { -+ do { -+ /* write data */ -+ if (pmsg->len) -+ rt_i2c_w32(i2c, pmsg->buf[j], -+ REG_DATAOUT_REG); -+ /* start transfer */ -+ if (j == 0) { -+ barrier(); -+ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); -+ } -+ /* wait */ -+ if ((ret = rt_i2c_wait_tx_done(i2c))) -+ goto err_timeout; -+ j++; -+ } while (j < pmsg->len); -+ } -+ } -+ /* the return value is number of executed messages */ -+ ret = i; -+ -+ return ret; -+ -+err_timeout: -+ rt_i2c_dump_reg(i2c); -+ rt_i2c_reset(i2c); -+ return ret; -+} -+ -+static u32 rt_i2c_func(struct i2c_adapter *a) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm rt_i2c_algo = { -+ .master_xfer = rt_i2c_master_xfer, -+ .functionality = rt_i2c_func, -+}; -+ -+static const struct of_device_id i2c_rt_dt_ids[] = { -+ { .compatible = "ralink,rt2880-i2c" }, -+ { /* sentinel */ } -+}; -+ -+MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); -+ -+static struct i2c_adapter_quirks rt_i2c_quirks = { -+ .max_write_len = BYTECNT_MAX, -+ .max_read_len = BYTECNT_MAX, -+}; -+ -+static int rt_i2c_init(struct rt_i2c *i2c) -+{ -+ u32 reg; -+ -+ /* i2c_sclk = periph_clk / ((2 * clk_div) + 5) */ -+ i2c->clk_div = (clk_get_rate(i2c->clk) - (5 * i2c->cur_clk)) / -+ (2 * i2c->cur_clk); -+ if (i2c->clk_div < 8) -+ i2c->clk_div = 8; -+ if (i2c->clk_div > I2C_CLKDIV_MASK) -+ i2c->clk_div = I2C_CLKDIV_MASK; -+ -+ /* check support combinde/repeated start message */ -+ rt_i2c_w32(i2c, NOSTOP_CMD, REG_STARTXFR_REG); -+ reg = rt_i2c_r32(i2c, REG_STARTXFR_REG) & NOSTOP_CMD; -+ -+ rt_i2c_reset(i2c); -+ -+ return reg; -+} -+ -+static int rt_i2c_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct rt_i2c *i2c; -+ struct i2c_adapter *adap; -+ const struct of_device_id *match; -+ int ret, restart; -+ -+ match = of_match_device(i2c_rt_dt_ids, &pdev->dev); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no memory resource found\n"); -+ return -ENODEV; -+ } -+ -+ i2c = devm_kzalloc(&pdev->dev, sizeof(struct rt_i2c), GFP_KERNEL); -+ if (!i2c) { -+ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); -+ return -ENOMEM; -+ } -+ -+ i2c->base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(i2c->base)) -+ return PTR_ERR(i2c->base); -+ -+ i2c->clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(i2c->clk)) { -+ dev_err(&pdev->dev, "no clock defined\n"); -+ return -ENODEV; -+ } -+ clk_prepare_enable(i2c->clk); -+ i2c->dev = &pdev->dev; -+ -+ if (of_property_read_u32(pdev->dev.of_node, -+ "clock-frequency", &i2c->cur_clk)) -+ i2c->cur_clk = 100000; -+ -+ adap = &i2c->adap; -+ adap->owner = THIS_MODULE; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; -+ adap->algo = &rt_i2c_algo; -+ adap->retries = 3; -+ adap->dev.parent = &pdev->dev; -+ i2c_set_adapdata(adap, i2c); -+ adap->dev.of_node = pdev->dev.of_node; -+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ adap->quirks = &rt_i2c_quirks; -+ -+ platform_set_drvdata(pdev, i2c); -+ -+ restart = rt_i2c_init(i2c); -+ -+ ret = i2c_add_adapter(adap); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to add adapter\n"); -+ clk_disable_unprepare(i2c->clk); -+ return ret; -+ } -+ -+ dev_info(&pdev->dev, "clock %uKHz, re-start %ssupport\n", -+ i2c->cur_clk/1000, restart ? "" : "not "); -+ -+ return ret; -+} -+ -+static int rt_i2c_remove(struct platform_device *pdev) -+{ -+ struct rt_i2c *i2c = platform_get_drvdata(pdev); -+ -+ i2c_del_adapter(&i2c->adap); -+ clk_disable_unprepare(i2c->clk); -+ -+ return 0; -+} -+ -+static struct platform_driver rt_i2c_driver = { -+ .probe = rt_i2c_probe, -+ .remove = rt_i2c_remove, -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "i2c-ralink", -+ .of_match_table = i2c_rt_dt_ids, -+ }, -+}; -+ -+static int __init i2c_rt_init (void) -+{ -+ return platform_driver_register(&rt_i2c_driver); -+} -+subsys_initcall(i2c_rt_init); -+ -+static void __exit i2c_rt_exit (void) -+{ -+ platform_driver_unregister(&rt_i2c_driver); -+} -+module_exit(i2c_rt_exit); -+ -+MODULE_AUTHOR("Steven Liu "); -+MODULE_DESCRIPTION("Ralink I2c host driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:Ralink-I2C"); diff --git a/target/linux/ramips/patches-5.15/830-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-5.15/830-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch deleted file mode 100644 index 9a0dbd7bb8..0000000000 --- a/target/linux/ramips/patches-5.15/830-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 23147af14531cbdada194b94120ef8774f46292d Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 13 Nov 2014 19:08:40 +0100 -Subject: [PATCH 46/53] mmc: MIPS: ralink: add sdhci for mt7620a SoC - -Signed-off-by: John Crispin ---- - drivers/mmc/host/Kconfig | 2 + - drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/mtk-mmc/Kconfig | 16 + - drivers/mmc/host/mtk-mmc/Makefile | 42 + - drivers/mmc/host/mtk-mmc/board.h | 137 ++ - drivers/mmc/host/mtk-mmc/dbg.c | 347 ++++ - drivers/mmc/host/mtk-mmc/dbg.h | 156 ++ - drivers/mmc/host/mtk-mmc/mt6575_sd.h | 1001 +++++++++++ - drivers/mmc/host/mtk-mmc/sd.c | 3060 ++++++++++++++++++++++++++++++++++ - 9 files changed, 4762 insertions(+) - create mode 100644 drivers/mmc/host/mtk-mmc/Kconfig - create mode 100644 drivers/mmc/host/mtk-mmc/Makefile - create mode 100644 drivers/mmc/host/mtk-mmc/board.h - create mode 100644 drivers/mmc/host/mtk-mmc/dbg.c - create mode 100644 drivers/mmc/host/mtk-mmc/dbg.h - create mode 100644 drivers/mmc/host/mtk-mmc/mt6575_sd.h - create mode 100644 drivers/mmc/host/mtk-mmc/sd.c - ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -1095,3 +1095,5 @@ config MMC_OWL - - config MMC_SDHCI_EXTERNAL_DMA - bool -+ -+source "drivers/mmc/host/mtk-mmc/Kconfig" ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -3,6 +3,7 @@ - # Makefile for MMC/SD host controller drivers - # - -+obj-$(CONFIG_MTK_MMC) += mtk-mmc/ - obj-$(CONFIG_MMC_ARMMMCI) += armmmci.o - armmmci-y := mmci.o - armmmci-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o diff --git a/target/linux/ramips/patches-5.15/835-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-5.15/835-asoc-add-mt7620-support.patch deleted file mode 100644 index 551fdd8b3c..0000000000 --- a/target/linux/ramips/patches-5.15/835-asoc-add-mt7620-support.patch +++ /dev/null @@ -1,1033 +0,0 @@ -From 7f29222b1731e8182ba94a331531dec18865a1e4 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:31:47 +0100 -Subject: [PATCH 48/53] asoc: add mt7620 support - -Signed-off-by: John Crispin ---- - arch/mips/ralink/of.c | 2 + - sound/soc/Kconfig | 1 + - sound/soc/Makefile | 1 + - sound/soc/ralink/Kconfig | 15 ++ - sound/soc/ralink/Makefile | 11 + - sound/soc/ralink/mt7620-i2s.c | 436 ++++++++++++++++++++++++++++++++++++++ - sound/soc/ralink/mt7620-wm8960.c | 233 ++++++++++++++++++++ - 7 files changed, 699 insertions(+) - create mode 100644 sound/soc/ralink/Kconfig - create mode 100644 sound/soc/ralink/Makefile - create mode 100644 sound/soc/ralink/mt7620-i2s.c - create mode 100644 sound/soc/ralink/mt7620-wm8960.c - ---- a/sound/soc/Kconfig -+++ b/sound/soc/Kconfig -@@ -78,6 +78,7 @@ source "sound/soc/mxs/Kconfig" - source "sound/soc/pxa/Kconfig" - source "sound/soc/qcom/Kconfig" - source "sound/soc/rockchip/Kconfig" -+source "sound/soc/ralink/Kconfig" - source "sound/soc/samsung/Kconfig" - source "sound/soc/sh/Kconfig" - source "sound/soc/sof/Kconfig" ---- a/sound/soc/Makefile -+++ b/sound/soc/Makefile -@@ -48,6 +48,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ - obj-$(CONFIG_SND_SOC) += pxa/ - obj-$(CONFIG_SND_SOC) += qcom/ - obj-$(CONFIG_SND_SOC) += rockchip/ -+obj-$(CONFIG_SND_SOC) += ralink/ - obj-$(CONFIG_SND_SOC) += samsung/ - obj-$(CONFIG_SND_SOC) += sh/ - obj-$(CONFIG_SND_SOC) += sof/ ---- /dev/null -+++ b/sound/soc/ralink/Kconfig -@@ -0,0 +1,8 @@ -+config SND_RALINK_SOC_I2S -+ depends on RALINK && SND_SOC && !SOC_RT288X -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ select REGMAP_MMIO -+ tristate "SoC Audio (I2S protocol) for Ralink SoC" -+ help -+ Say Y if you want to use I2S protocol and I2S codec on Ralink/MediaTek -+ based boards. ---- /dev/null -+++ b/sound/soc/ralink/Makefile -@@ -0,0 +1,6 @@ -+# -+# Ralink/MediaTek Platform Support -+# -+snd-soc-ralink-i2s-objs := ralink-i2s.o -+ -+obj-$(CONFIG_SND_RALINK_SOC_I2S) += snd-soc-ralink-i2s.o ---- /dev/null -+++ b/sound/soc/ralink/ralink-i2s.c -@@ -0,0 +1,970 @@ -+/* -+ * Copyright (C) 2010, Lars-Peter Clausen -+ * Copyright (C) 2016 Michael Lee -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define DRV_NAME "ralink-i2s" -+ -+#define I2S_REG_CFG0 0x00 -+#define I2S_REG_INT_STATUS 0x04 -+#define I2S_REG_INT_EN 0x08 -+#define I2S_REG_FF_STATUS 0x0c -+#define I2S_REG_WREG 0x10 -+#define I2S_REG_RREG 0x14 -+#define I2S_REG_CFG1 0x18 -+#define I2S_REG_DIVCMP 0x20 -+#define I2S_REG_DIVINT 0x24 -+ -+/* I2S_REG_CFG0 */ -+#define I2S_REG_CFG0_EN BIT(31) -+#define I2S_REG_CFG0_DMA_EN BIT(30) -+#define I2S_REG_CFG0_BYTE_SWAP BIT(28) -+#define I2S_REG_CFG0_TX_EN BIT(24) -+#define I2S_REG_CFG0_RX_EN BIT(20) -+#define I2S_REG_CFG0_SLAVE BIT(16) -+#define I2S_REG_CFG0_RX_THRES 12 -+#define I2S_REG_CFG0_TX_THRES 4 -+#define I2S_REG_CFG0_THRES_MASK (0xf << I2S_REG_CFG0_RX_THRES) | \ -+ (4 << I2S_REG_CFG0_TX_THRES) -+#define I2S_REG_CFG0_DFT_THRES (4 << I2S_REG_CFG0_RX_THRES) | \ -+ (4 << I2S_REG_CFG0_TX_THRES) -+/* RT305x */ -+#define I2S_REG_CFG0_CLK_DIS BIT(8) -+#define I2S_REG_CFG0_TXCH_SWAP BIT(3) -+#define I2S_REG_CFG0_TXCH1_OFF BIT(2) -+#define I2S_REG_CFG0_TXCH0_OFF BIT(1) -+#define I2S_REG_CFG0_SLAVE_EN BIT(0) -+/* RT3883 */ -+#define I2S_REG_CFG0_RXCH_SWAP BIT(11) -+#define I2S_REG_CFG0_RXCH1_OFF BIT(10) -+#define I2S_REG_CFG0_RXCH0_OFF BIT(9) -+#define I2S_REG_CFG0_WS_INV BIT(0) -+/* MT7628 */ -+#define I2S_REG_CFG0_FMT_LE BIT(29) -+#define I2S_REG_CFG0_SYS_BE BIT(28) -+#define I2S_REG_CFG0_NORM_24 BIT(18) -+#define I2S_REG_CFG0_DATA_24 BIT(17) -+ -+/* I2S_REG_INT_STATUS */ -+#define I2S_REG_INT_RX_FAULT BIT(7) -+#define I2S_REG_INT_RX_OVRUN BIT(6) -+#define I2S_REG_INT_RX_UNRUN BIT(5) -+#define I2S_REG_INT_RX_THRES BIT(4) -+#define I2S_REG_INT_TX_FAULT BIT(3) -+#define I2S_REG_INT_TX_OVRUN BIT(2) -+#define I2S_REG_INT_TX_UNRUN BIT(1) -+#define I2S_REG_INT_TX_THRES BIT(0) -+#define I2S_REG_INT_TX_MASK 0xf -+#define I2S_REG_INT_RX_MASK 0xf0 -+ -+/* I2S_REG_INT_STATUS */ -+#define I2S_RX_AVCNT(x) ((x >> 4) & 0xf) -+#define I2S_TX_AVCNT(x) (x & 0xf) -+/* MT7628 */ -+#define MT7628_I2S_RX_AVCNT(x) ((x >> 8) & 0x1f) -+#define MT7628_I2S_TX_AVCNT(x) (x & 0x1f) -+ -+/* I2S_REG_CFG1 */ -+#define I2S_REG_CFG1_LBK BIT(31) -+#define I2S_REG_CFG1_EXTLBK BIT(30) -+/* RT3883 */ -+#define I2S_REG_CFG1_LEFT_J BIT(0) -+#define I2S_REG_CFG1_RIGHT_J BIT(1) -+#define I2S_REG_CFG1_FMT_MASK 0x3 -+ -+/* I2S_REG_DIVCMP */ -+#define I2S_REG_DIVCMP_CLKEN BIT(31) -+#define I2S_REG_DIVCMP_DIVCOMP_MASK 0x1ff -+ -+/* I2S_REG_DIVINT */ -+#define I2S_REG_DIVINT_MASK 0x3ff -+ -+/* BCLK dividers */ -+#define RALINK_I2S_DIVCMP 0 -+#define RALINK_I2S_DIVINT 1 -+ -+/* FIFO */ -+#define RALINK_I2S_FIFO_SIZE 32 -+ -+/* feature flags */ -+#define RALINK_FLAGS_TXONLY BIT(0) -+#define RALINK_FLAGS_LEFT_J BIT(1) -+#define RALINK_FLAGS_RIGHT_J BIT(2) -+#define RALINK_FLAGS_ENDIAN BIT(3) -+#define RALINK_FLAGS_24BIT BIT(4) -+ -+#define RALINK_I2S_INT_EN 0 -+ -+struct ralink_i2s_stats { -+ u32 dmafault; -+ u32 overrun; -+ u32 underrun; -+ u32 belowthres; -+}; -+ -+struct ralink_i2s { -+ struct device *dev; -+ void __iomem *regs; -+ struct clk *clk; -+ struct regmap *regmap; -+ u32 flags; -+ unsigned int fmt; -+ u16 txdma_req; -+ u16 rxdma_req; -+ -+ struct snd_dmaengine_dai_dma_data playback_dma_data; -+ struct snd_dmaengine_dai_dma_data capture_dma_data; -+ -+ struct dentry *dbg_dir; -+ struct dentry *dbg_stats; -+ struct ralink_i2s_stats txstats; -+ struct ralink_i2s_stats rxstats; -+}; -+ -+static void ralink_i2s_dump_regs(struct ralink_i2s *i2s) -+{ -+ u32 buf[10]; -+ int ret; -+ -+ ret = regmap_bulk_read(i2s->regmap, I2S_REG_CFG0, -+ buf, ARRAY_SIZE(buf)); -+ -+ dev_dbg(i2s->dev, "CFG0: %08x, INTSTAT: %08x, INTEN: %08x, " \ -+ "FFSTAT: %08x, WREG: %08x, RREG: %08x, " \ -+ "CFG1: %08x, DIVCMP: %08x, DIVINT: %08x\n", -+ buf[0], buf[1], buf[2], buf[3], buf[4], -+ buf[5], buf[6], buf[8], buf[9]); -+} -+ -+static int ralink_i2s_set_sysclk(struct snd_soc_dai *dai, -+ int clk_id, unsigned int freq, int dir) -+{ -+ return 0; -+} -+ -+static int ralink_i2s_set_sys_bclk(struct snd_soc_dai *dai, int width, int rate) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ unsigned long clk = clk_get_rate(i2s->clk); -+ int div; -+ uint32_t data; -+ -+ /* disable clock at slave mode */ -+ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == -+ SND_SOC_DAIFMT_CBM_CFM) { -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_CLK_DIS, -+ I2S_REG_CFG0_CLK_DIS); -+ return 0; -+ } -+ -+ /* FREQOUT = FREQIN / (I2S_CLK_DIV + 1) */ -+ div = (clk / rate ) - 1; -+ -+ data = rt_sysc_r32(0x30); -+ data &= (0xff << 8); -+ data |= (0x1 << 15) | (div << 8); -+ rt_sysc_w32(data, 0x30); -+ -+ /* enable clock */ -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_CLK_DIS, 0); -+ -+ dev_dbg(i2s->dev, "clk: %lu, rate: %u, div: %d\n", -+ clk, rate, div); -+ -+ return 0; -+} -+ -+static int ralink_i2s_set_bclk(struct snd_soc_dai *dai, int width, int rate) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ unsigned long clk = clk_get_rate(i2s->clk); -+ int divint, divcomp; -+ -+ /* disable clock at slave mode */ -+ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == -+ SND_SOC_DAIFMT_CBM_CFM) { -+ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, -+ I2S_REG_DIVCMP_CLKEN, 0); -+ return 0; -+ } -+ -+ /* FREQOUT = FREQIN * (1/2) * (1/(DIVINT + DIVCOMP/512)) */ -+ clk = clk / (2 * 2 * width); -+ divint = clk / rate; -+ divcomp = ((clk % rate) * 512) / rate; -+ -+ if ((divint > I2S_REG_DIVINT_MASK) || -+ (divcomp > I2S_REG_DIVCMP_DIVCOMP_MASK)) -+ return -EINVAL; -+ -+ regmap_update_bits(i2s->regmap, I2S_REG_DIVINT, -+ I2S_REG_DIVINT_MASK, divint); -+ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, -+ I2S_REG_DIVCMP_DIVCOMP_MASK, divcomp); -+ -+ /* enable clock */ -+ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, I2S_REG_DIVCMP_CLKEN, -+ I2S_REG_DIVCMP_CLKEN); -+ -+ dev_dbg(i2s->dev, "clk: %lu, rate: %u, int: %d, comp: %d\n", -+ clk_get_rate(i2s->clk), rate, divint, divcomp); -+ -+ return 0; -+} -+ -+static int ralink_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ unsigned int cfg0 = 0, cfg1 = 0; -+ -+ /* set master/slave audio interface */ -+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBM_CFM: -+ if (i2s->flags & RALINK_FLAGS_TXONLY) -+ cfg0 |= I2S_REG_CFG0_SLAVE_EN; -+ else -+ cfg0 |= I2S_REG_CFG0_SLAVE; -+ break; -+ case SND_SOC_DAIFMT_CBS_CFS: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* interface format */ -+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ break; -+ case SND_SOC_DAIFMT_RIGHT_J: -+ if (i2s->flags & RALINK_FLAGS_RIGHT_J) { -+ cfg1 |= I2S_REG_CFG1_RIGHT_J; -+ break; -+ } -+ return -EINVAL; -+ case SND_SOC_DAIFMT_LEFT_J: -+ if (i2s->flags & RALINK_FLAGS_LEFT_J) { -+ cfg1 |= I2S_REG_CFG1_LEFT_J; -+ break; -+ } -+ return -EINVAL; -+ default: -+ return -EINVAL; -+ } -+ -+ /* clock inversion */ -+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (i2s->flags & RALINK_FLAGS_TXONLY) { -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_SLAVE_EN, cfg0); -+ } else { -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_SLAVE, cfg0); -+ } -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG1, -+ I2S_REG_CFG1_FMT_MASK, cfg1); -+ i2s->fmt = fmt; -+ -+ return 0; -+} -+ -+static int ralink_i2s_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ -+ if (snd_soc_dai_active(dai)) -+ return 0; -+ -+ /* setup status interrupt */ -+#if (RALINK_I2S_INT_EN) -+ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0xff); -+#else -+ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0x0); -+#endif -+ -+ /* enable */ -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | -+ I2S_REG_CFG0_THRES_MASK, -+ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | -+ I2S_REG_CFG0_DFT_THRES); -+ -+ return 0; -+} -+ -+static void ralink_i2s_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ -+ /* If both streams are stopped, disable module and clock */ -+ if (snd_soc_dai_active(dai)) -+ return; -+ -+ /* -+ * datasheet mention when disable all control regs are cleared -+ * to initial values. need reinit at startup. -+ */ -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_EN, 0); -+} -+ -+static int ralink_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ int width; -+ int ret; -+ -+ width = params_width(params); -+ switch (width) { -+ case 16: -+ if (i2s->flags & RALINK_FLAGS_24BIT) -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_DATA_24, 0); -+ break; -+ case 24: -+ if (i2s->flags & RALINK_FLAGS_24BIT) { -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_DATA_24, -+ I2S_REG_CFG0_DATA_24); -+ break; -+ } -+ return -EINVAL; -+ default: -+ return -EINVAL; -+ } -+ -+ switch (params_channels(params)) { -+ case 2: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (i2s->flags & RALINK_FLAGS_ENDIAN) { -+ /* system endian */ -+#ifdef SNDRV_LITTLE_ENDIAN -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_SYS_BE, 0); -+#else -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_SYS_BE, -+ I2S_REG_CFG0_SYS_BE); -+#endif -+ -+ /* data endian */ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ case SNDRV_PCM_FORMAT_S24_LE: -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_FMT_LE, -+ I2S_REG_CFG0_FMT_LE); -+ break; -+ case SNDRV_PCM_FORMAT_S16_BE: -+ case SNDRV_PCM_FORMAT_S24_BE: -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, -+ I2S_REG_CFG0_FMT_LE, 0); -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ /* setup bclk rate */ -+ if (i2s->flags & RALINK_FLAGS_TXONLY) -+ ret = ralink_i2s_set_sys_bclk(dai, width, params_rate(params)); -+ else -+ ret = ralink_i2s_set_bclk(dai, width, params_rate(params)); -+ -+ return ret; -+} -+ -+static int ralink_i2s_trigger(struct snd_pcm_substream *substream, int cmd, -+ struct snd_soc_dai *dai) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ unsigned int mask, val; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ mask = I2S_REG_CFG0_TX_EN; -+ else -+ mask = I2S_REG_CFG0_RX_EN; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ val = mask; -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ val = 0; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, mask, val); -+ -+ return 0; -+} -+ -+static void ralink_i2s_init_dma_data(struct ralink_i2s *i2s, -+ struct resource *res) -+{ -+ struct snd_dmaengine_dai_dma_data *dma_data; -+ -+ /* Playback */ -+ dma_data = &i2s->playback_dma_data; -+ dma_data->addr = res->start + I2S_REG_WREG; -+ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ dma_data->maxburst = 1; -+ dma_data->slave_id = i2s->txdma_req; -+ -+ if (i2s->flags & RALINK_FLAGS_TXONLY) -+ return; -+ -+ /* Capture */ -+ dma_data = &i2s->capture_dma_data; -+ dma_data->addr = res->start + I2S_REG_RREG; -+ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -+ dma_data->maxburst = 1; -+ dma_data->slave_id = i2s->rxdma_req; -+} -+ -+static int ralink_i2s_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ -+ snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, -+ &i2s->capture_dma_data); -+ -+ return 0; -+} -+ -+static int ralink_i2s_dai_remove(struct snd_soc_dai *dai) -+{ -+ return 0; -+} -+ -+static const struct snd_soc_dai_ops ralink_i2s_dai_ops = { -+ .set_sysclk = ralink_i2s_set_sysclk, -+ .set_fmt = ralink_i2s_set_fmt, -+ .startup = ralink_i2s_startup, -+ .shutdown = ralink_i2s_shutdown, -+ .hw_params = ralink_i2s_hw_params, -+ .trigger = ralink_i2s_trigger, -+}; -+ -+static struct snd_soc_dai_driver ralink_i2s_dai = { -+ .name = DRV_NAME, -+ .probe = ralink_i2s_dai_probe, -+ .remove = ralink_i2s_dai_remove, -+ .ops = &ralink_i2s_dai_ops, -+ .capture = { -+ .stream_name = "I2S Capture", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rate_min = 5512, -+ .rate_max = 192000, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ }, -+ .playback = { -+ .stream_name = "I2S Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rate_min = 5512, -+ .rate_max = 192000, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ }, -+ .symmetric_rate = 1, -+}; -+ -+static struct snd_pcm_hardware ralink_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_BLOCK_TRANSFER, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ .channels_min = 2, -+ .channels_max = 2, -+ .period_bytes_min = PAGE_SIZE, -+ .period_bytes_max = PAGE_SIZE * 2, -+ .periods_min = 2, -+ .periods_max = 128, -+ .buffer_bytes_max = 128 * 1024, -+ .fifo_size = RALINK_I2S_FIFO_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config ralink_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &ralink_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ -+static const struct snd_soc_component_driver ralink_i2s_component = { -+ .name = DRV_NAME, -+}; -+ -+static bool ralink_i2s_readable_reg(struct device *dev, unsigned int reg) -+{ -+ return true; -+} -+ -+static bool ralink_i2s_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_REG_INT_STATUS: -+ case I2S_REG_FF_STATUS: -+ return true; -+ } -+ return false; -+} -+ -+static bool ralink_i2s_writeable_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case I2S_REG_FF_STATUS: -+ case I2S_REG_RREG: -+ return false; -+ } -+ return true; -+} -+ -+static const struct regmap_config ralink_i2s_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .writeable_reg = ralink_i2s_writeable_reg, -+ .readable_reg = ralink_i2s_readable_reg, -+ .volatile_reg = ralink_i2s_volatile_reg, -+ .max_register = I2S_REG_DIVINT, -+}; -+ -+#if (RALINK_I2S_INT_EN) -+static irqreturn_t ralink_i2s_irq(int irq, void *devid) -+{ -+ struct ralink_i2s *i2s = devid; -+ u32 status; -+ -+ regmap_read(i2s->regmap, I2S_REG_INT_STATUS, &status); -+ if (unlikely(!status)) -+ return IRQ_NONE; -+ -+ /* tx stats */ -+ if (status & I2S_REG_INT_TX_MASK) { -+ if (status & I2S_REG_INT_TX_THRES) -+ i2s->txstats.belowthres++; -+ if (status & I2S_REG_INT_TX_UNRUN) -+ i2s->txstats.underrun++; -+ if (status & I2S_REG_INT_TX_OVRUN) -+ i2s->txstats.overrun++; -+ if (status & I2S_REG_INT_TX_FAULT) -+ i2s->txstats.dmafault++; -+ } -+ -+ /* rx stats */ -+ if (status & I2S_REG_INT_RX_MASK) { -+ if (status & I2S_REG_INT_RX_THRES) -+ i2s->rxstats.belowthres++; -+ if (status & I2S_REG_INT_RX_UNRUN) -+ i2s->rxstats.underrun++; -+ if (status & I2S_REG_INT_RX_OVRUN) -+ i2s->rxstats.overrun++; -+ if (status & I2S_REG_INT_RX_FAULT) -+ i2s->rxstats.dmafault++; -+ } -+ -+ /* clean status bits */ -+ regmap_write(i2s->regmap, I2S_REG_INT_STATUS, status); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+#if IS_ENABLED(CONFIG_DEBUG_FS) -+static int ralink_i2s_stats_show(struct seq_file *s, void *unused) -+{ -+ struct ralink_i2s *i2s = s->private; -+ -+ seq_printf(s, "tx stats\n"); -+ seq_printf(s, "\tbelow threshold\t%u\n", i2s->txstats.belowthres); -+ seq_printf(s, "\tunder run\t%u\n", i2s->txstats.underrun); -+ seq_printf(s, "\tover run\t%u\n", i2s->txstats.overrun); -+ seq_printf(s, "\tdma fault\t%u\n", i2s->txstats.dmafault); -+ -+ seq_printf(s, "rx stats\n"); -+ seq_printf(s, "\tbelow threshold\t%u\n", i2s->rxstats.belowthres); -+ seq_printf(s, "\tunder run\t%u\n", i2s->rxstats.underrun); -+ seq_printf(s, "\tover run\t%u\n", i2s->rxstats.overrun); -+ seq_printf(s, "\tdma fault\t%u\n", i2s->rxstats.dmafault); -+ -+ ralink_i2s_dump_regs(i2s); -+ -+ return 0; -+} -+ -+static int ralink_i2s_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, ralink_i2s_stats_show, inode->i_private); -+} -+ -+static const struct file_operations ralink_i2s_stats_ops = { -+ .open = ralink_i2s_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) -+{ -+ i2s->dbg_dir = debugfs_create_dir(dev_name(i2s->dev), NULL); -+ if (!i2s->dbg_dir) -+ return -ENOMEM; -+ -+ i2s->dbg_stats = debugfs_create_file("stats", S_IRUGO, -+ i2s->dbg_dir, i2s, &ralink_i2s_stats_ops); -+ if (!i2s->dbg_stats) { -+ debugfs_remove(i2s->dbg_dir); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static inline void ralink_i2s_debugfs_remove(struct ralink_i2s *i2s) -+{ -+ debugfs_remove(i2s->dbg_stats); -+ debugfs_remove(i2s->dbg_dir); -+} -+#else -+static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) -+{ -+ return 0; -+} -+ -+static inline void ralink_i2s_debugfs_remove(struct ralink_i2s *i2s) -+{ -+} -+#endif -+ -+/* -+ * TODO: these refclk setup functions should use -+ * clock framework instead. hardcode it now. -+ */ -+static void rt3350_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data |= (0x1 << 8); -+ rt_sysc_w32(data, 0x2c); -+} -+ -+static void rt3883_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data &= ~(0x3 << 13); -+ data |= (0x1 << 13); -+ rt_sysc_w32(data, 0x2c); -+} -+ -+static void rt3552_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data &= ~(0xf << 8); -+ data |= (0x3 << 8); -+ rt_sysc_w32(data, 0x2c); -+} -+ -+static void mt7620_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data &= ~(0x7 << 9); -+ data |= 0x1 << 9; -+ rt_sysc_w32(data, 0x2c); -+} -+ -+static void mt7621_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data &= ~(0x1f << 18); -+ data |= (0x19 << 18); -+ data &= ~(0x1f << 12); -+ data |= (0x1 << 12); -+ data &= ~(0x7 << 9); -+ data |= (0x5 << 9); -+ rt_sysc_w32(data, 0x2c); -+} -+ -+static void mt7628_refclk_setup(void) -+{ -+ uint32_t data; -+ -+ /* set i2s and refclk digital pad */ -+ data = rt_sysc_r32(0x3c); -+ data |= 0x1f; -+ rt_sysc_w32(data, 0x3c); -+ -+ /* Adjust REFCLK0's driving strength */ -+ data = rt_sysc_r32(0x1354); -+ data &= ~(0x1 << 5); -+ rt_sysc_w32(data, 0x1354); -+ data = rt_sysc_r32(0x1364); -+ data |= ~(0x1 << 5); -+ rt_sysc_w32(data, 0x1364); -+ -+ /* set refclk output 12Mhz clock */ -+ data = rt_sysc_r32(0x2c); -+ data &= ~(0x7 << 9); -+ data |= 0x1 << 9; -+ rt_sysc_w32(data, 0x2c); -+} -+ -+struct rt_i2s_data { -+ u32 flags; -+ void (*refclk_setup)(void); -+}; -+ -+struct rt_i2s_data rt3050_i2s_data = { .flags = RALINK_FLAGS_TXONLY }; -+struct rt_i2s_data rt3350_i2s_data = { .flags = RALINK_FLAGS_TXONLY, -+ .refclk_setup = rt3350_refclk_setup }; -+struct rt_i2s_data rt3883_i2s_data = { -+ .flags = (RALINK_FLAGS_LEFT_J | RALINK_FLAGS_RIGHT_J), -+ .refclk_setup = rt3883_refclk_setup }; -+struct rt_i2s_data rt3352_i2s_data = { .refclk_setup = rt3552_refclk_setup}; -+struct rt_i2s_data mt7620_i2s_data = { .refclk_setup = mt7620_refclk_setup}; -+struct rt_i2s_data mt7621_i2s_data = { .refclk_setup = mt7621_refclk_setup}; -+struct rt_i2s_data mt7628_i2s_data = { -+ .flags = (RALINK_FLAGS_ENDIAN | RALINK_FLAGS_24BIT | -+ RALINK_FLAGS_LEFT_J), -+ .refclk_setup = mt7628_refclk_setup}; -+ -+static const struct of_device_id ralink_i2s_match_table[] = { -+ { .compatible = "ralink,rt3050-i2s", -+ .data = (void *)&rt3050_i2s_data }, -+ { .compatible = "ralink,rt3350-i2s", -+ .data = (void *)&rt3350_i2s_data }, -+ { .compatible = "ralink,rt3883-i2s", -+ .data = (void *)&rt3883_i2s_data }, -+ { .compatible = "ralink,rt3352-i2s", -+ .data = (void *)&rt3352_i2s_data }, -+ { .compatible = "mediatek,mt7620-i2s", -+ .data = (void *)&mt7620_i2s_data }, -+ { .compatible = "mediatek,mt7621-i2s", -+ .data = (void *)&mt7621_i2s_data }, -+ { .compatible = "mediatek,mt7628-i2s", -+ .data = (void *)&mt7628_i2s_data }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, ralink_i2s_match_table); -+ -+static int ralink_i2s_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *match; -+ struct device_node *np = pdev->dev.of_node; -+ struct ralink_i2s *i2s; -+ struct resource *res; -+ int irq, ret; -+ u32 dma_req; -+ struct rt_i2s_data *data; -+ -+ i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); -+ if (!i2s) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, i2s); -+ i2s->dev = &pdev->dev; -+ -+ match = of_match_device(ralink_i2s_match_table, &pdev->dev); -+ if (!match) -+ return -EINVAL; -+ data = (struct rt_i2s_data *)match->data; -+ i2s->flags = data->flags; -+ /* setup out 12Mhz refclk to codec as mclk */ -+ if (data->refclk_setup) -+ data->refclk_setup(); -+ -+ if (of_property_read_u32(np, "txdma-req", &dma_req)) { -+ dev_err(&pdev->dev, "no txdma-req define\n"); -+ return -EINVAL; -+ } -+ i2s->txdma_req = (u16)dma_req; -+ if (!(i2s->flags & RALINK_FLAGS_TXONLY)) { -+ if (of_property_read_u32(np, "rxdma-req", &dma_req)) { -+ dev_err(&pdev->dev, "no rxdma-req define\n"); -+ return -EINVAL; -+ } -+ i2s->rxdma_req = (u16)dma_req; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ i2s->regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(i2s->regs)) -+ return PTR_ERR(i2s->regs); -+ -+ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->regs, -+ &ralink_i2s_regmap_config); -+ if (IS_ERR(i2s->regmap)) { -+ dev_err(&pdev->dev, "regmap init failed\n"); -+ return PTR_ERR(i2s->regmap); -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "failed to get irq\n"); -+ return -EINVAL; -+ } -+ -+#if (RALINK_I2S_INT_EN) -+ ret = devm_request_irq(&pdev->dev, irq, ralink_i2s_irq, -+ 0, dev_name(&pdev->dev), i2s); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to request irq\n"); -+ return ret; -+ } -+#endif -+ -+ i2s->clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(i2s->clk)) { -+ dev_err(&pdev->dev, "no clock defined\n"); -+ return PTR_ERR(i2s->clk); -+ } -+ -+ ret = clk_prepare_enable(i2s->clk); -+ if (ret) -+ return ret; -+ -+ ralink_i2s_init_dma_data(i2s, res); -+ -+ ret = device_reset(&pdev->dev); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to reset device\n"); -+ goto err_clk_disable; -+ } -+ -+ ret = ralink_i2s_debugfs_create(i2s); -+ if (ret) { -+ dev_err(&pdev->dev, "create debugfs failed\n"); -+ goto err_clk_disable; -+ } -+ -+ /* enable 24bits support */ -+ if (i2s->flags & RALINK_FLAGS_24BIT) { -+ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S24_LE; -+ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S24_LE; -+ } -+ -+ /* enable big endian support */ -+ if (i2s->flags & RALINK_FLAGS_ENDIAN) { -+ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S16_BE; -+ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S16_BE; -+ ralink_pcm_hardware.formats |= SNDRV_PCM_FMTBIT_S16_BE; -+ if (i2s->flags & RALINK_FLAGS_24BIT) { -+ ralink_i2s_dai.capture.formats |= -+ SNDRV_PCM_FMTBIT_S24_BE; -+ ralink_i2s_dai.playback.formats |= -+ SNDRV_PCM_FMTBIT_S24_BE; -+ ralink_pcm_hardware.formats |= -+ SNDRV_PCM_FMTBIT_S24_BE; -+ } -+ } -+ -+ /* disable capture support */ -+ if (i2s->flags & RALINK_FLAGS_TXONLY) -+ memset(&ralink_i2s_dai.capture, sizeof(ralink_i2s_dai.capture), -+ 0); -+ -+ ret = devm_snd_soc_register_component(&pdev->dev, &ralink_i2s_component, -+ &ralink_i2s_dai, 1); -+ if (ret) -+ goto err_debugfs; -+ -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, -+ &ralink_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); -+ if (ret) -+ goto err_debugfs; -+ -+ dev_info(i2s->dev, "mclk %luMHz\n", clk_get_rate(i2s->clk) / 1000000); -+ -+ return 0; -+ -+err_debugfs: -+ ralink_i2s_debugfs_remove(i2s); -+ -+err_clk_disable: -+ clk_disable_unprepare(i2s->clk); -+ -+ return ret; -+} -+ -+static int ralink_i2s_remove(struct platform_device *pdev) -+{ -+ struct ralink_i2s *i2s = platform_get_drvdata(pdev); -+ -+ ralink_i2s_debugfs_remove(i2s); -+ clk_disable_unprepare(i2s->clk); -+ -+ return 0; -+} -+ -+static struct platform_driver ralink_i2s_driver = { -+ .probe = ralink_i2s_probe, -+ .remove = ralink_i2s_remove, -+ .driver = { -+ .name = DRV_NAME, -+ .of_match_table = ralink_i2s_match_table, -+ }, -+}; -+module_platform_driver(ralink_i2s_driver); -+ -+MODULE_AUTHOR("Lars-Peter Clausen, "); -+MODULE_DESCRIPTION("Ralink/MediaTek I2S driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:" DRV_NAME); diff --git a/target/linux/ramips/patches-5.15/840-serial-add-ugly-custom-baud-rate-hack.patch b/target/linux/ramips/patches-5.15/840-serial-add-ugly-custom-baud-rate-hack.patch deleted file mode 100644 index 7148bb16f3..0000000000 --- a/target/linux/ramips/patches-5.15/840-serial-add-ugly-custom-baud-rate-hack.patch +++ /dev/null @@ -1,22 +0,0 @@ -From a7eb46e0ea4a11e4dfb56ab129bf816d1059a6c5 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 7 Dec 2015 17:31:08 +0100 -Subject: [PATCH 51/53] serial: add ugly custom baud rate hack - -Signed-off-by: John Crispin ---- - drivers/tty/serial/serial_core.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/tty/serial/serial_core.c -+++ b/drivers/tty/serial/serial_core.c -@@ -393,6 +393,9 @@ uart_get_baud_rate(struct uart_port *por - break; - } - -+ if (tty_termios_baud_rate(termios) == 2500000) -+ return 250000; -+ - for (try = 0; try < 2; try++) { - baud = tty_termios_baud_rate(termios); - diff --git a/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch b/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch deleted file mode 100644 index 06074d6031..0000000000 --- a/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch +++ /dev/null @@ -1,219 +0,0 @@ -From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 7 Dec 2015 17:16:50 +0100 -Subject: [PATCH 52/53] pwm: add mediatek support - -Signed-off-by: John Crispin ---- - drivers/pwm/Kconfig | 9 +++ - drivers/pwm/Makefile | 1 + - drivers/pwm/pwm-mediatek.c | 173 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 183 insertions(+) - create mode 100644 drivers/pwm/pwm-mediatek.c - ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -383,6 +383,15 @@ config PWM_MEDIATEK - To compile this driver as a module, choose M here: the module - will be called pwm-mediatek. - -+config PWM_MEDIATEK_RAMIPS -+ tristate "Mediatek PWM support" -+ depends on RALINK && OF -+ help -+ Generic PWM framework driver for Mediatek ARM SoC. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called pwm-mxs. -+ - config PWM_MXS - tristate "Freescale MXS PWM support" - depends on ARCH_MXS || COMPILE_TEST ---- a/drivers/pwm/Makefile -+++ b/drivers/pwm/Makefile -@@ -33,6 +33,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p - obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o - obj-$(CONFIG_PWM_MESON) += pwm-meson.o - obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o -+obj-$(CONFIG_PWM_MEDIATEK_RAMIPS) += pwm-mediatek-ramips.o - obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o - obj-$(CONFIG_PWM_MXS) += pwm-mxs.o - obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o ---- /dev/null -+++ b/drivers/pwm/pwm-mediatek-ramips.c -@@ -0,0 +1,175 @@ -+/* -+ * Mediatek Pulse Width Modulator driver -+ * -+ * Copyright (C) 2015 John Crispin -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define NUM_PWM 4 -+ -+/* PWM registers and bits definitions */ -+#define PWMCON 0x00 -+#define PWMHDUR 0x04 -+#define PWMLDUR 0x08 -+#define PWMGDUR 0x0c -+#define PWMWAVENUM 0x28 -+#define PWMDWIDTH 0x2c -+#define PWMTHRES 0x30 -+ -+/** -+ * struct mtk_pwm_chip - struct representing pwm chip -+ * -+ * @mmio_base: base address of pwm chip -+ * @chip: linux pwm chip representation -+ */ -+struct mtk_pwm_chip { -+ void __iomem *mmio_base; -+ struct pwm_chip chip; -+}; -+ -+static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) -+{ -+ return container_of(chip, struct mtk_pwm_chip, chip); -+} -+ -+static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, -+ unsigned long offset) -+{ -+ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); -+} -+ -+static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, -+ unsigned int num, unsigned long offset, -+ unsigned long val) -+{ -+ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); -+} -+ -+static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, -+ int duty_ns, int period_ns) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 resolution = 100 / 4; -+ u32 clkdiv = 0; -+ -+ while (period_ns / resolution > 8191) { -+ clkdiv++; -+ resolution *= 2; -+ } -+ -+ if (clkdiv > 7) -+ return -1; -+ -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); -+ return 0; -+} -+ -+static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 val; -+ -+ val = ioread32(pc->mmio_base); -+ val |= BIT(pwm->hwpwm); -+ iowrite32(val, pc->mmio_base); -+ -+ return 0; -+} -+ -+static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 val; -+ -+ val = ioread32(pc->mmio_base); -+ val &= ~BIT(pwm->hwpwm); -+ iowrite32(val, pc->mmio_base); -+} -+ -+static const struct pwm_ops mtk_pwm_ops = { -+ .config = mtk_pwm_config, -+ .enable = mtk_pwm_enable, -+ .disable = mtk_pwm_disable, -+ .owner = THIS_MODULE, -+}; -+ -+static int mtk_pwm_probe(struct platform_device *pdev) -+{ -+ struct mtk_pwm_chip *pc; -+ struct resource *r; -+ int ret; -+ -+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); -+ if (!pc) -+ return -ENOMEM; -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); -+ if (IS_ERR(pc->mmio_base)) -+ return PTR_ERR(pc->mmio_base); -+ -+ platform_set_drvdata(pdev, pc); -+ -+ pc->chip.dev = &pdev->dev; -+ pc->chip.ops = &mtk_pwm_ops; -+ pc->chip.base = -1; -+ pc->chip.npwm = NUM_PWM; -+ -+ ret = pwmchip_add(&pc->chip); -+ if (ret < 0) -+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int mtk_pwm_remove(struct platform_device *pdev) -+{ -+ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < NUM_PWM; i++) -+ pwm_disable(&pc->chip.pwms[i]); -+ -+ pwmchip_remove(&pc->chip); -+ -+ return 0; -+} -+ -+static const struct of_device_id mtk_pwm_of_match[] = { -+ { .compatible = "mediatek,mt7628-pwm" }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); -+ -+static struct platform_driver mtk_pwm_driver = { -+ .driver = { -+ .name = "mtk-pwm", -+ .owner = THIS_MODULE, -+ .of_match_table = mtk_pwm_of_match, -+ }, -+ .probe = mtk_pwm_probe, -+ .remove = mtk_pwm_remove, -+}; -+ -+module_platform_driver(mtk_pwm_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("John Crispin "); -+MODULE_ALIAS("platform:mtk-pwm"); diff --git a/target/linux/ramips/patches-5.15/850-awake-rt305x-dwc2-controller.patch b/target/linux/ramips/patches-5.15/850-awake-rt305x-dwc2-controller.patch deleted file mode 100644 index 5fb3664ae5..0000000000 --- a/target/linux/ramips/patches-5.15/850-awake-rt305x-dwc2-controller.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/drivers/usb/dwc2/platform.c -+++ b/drivers/usb/dwc2/platform.c -@@ -508,6 +508,12 @@ static int dwc2_driver_probe(struct plat - if (retval) - return retval; - -+ /* Enable USB port before any regs access */ -+ if (readl(hsotg->regs + PCGCTL) & 0x0f) { -+ writel(0x00, hsotg->regs + PCGCTL); -+ /* TODO: mdelay(25) here? vendor driver don't use it */ -+ } -+ - hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); - - retval = dwc2_get_dr_mode(hsotg); diff --git a/target/linux/ramips/patches-5.15/855-linkit_bootstrap.patch b/target/linux/ramips/patches-5.15/855-linkit_bootstrap.patch deleted file mode 100644 index cd81601a72..0000000000 --- a/target/linux/ramips/patches-5.15/855-linkit_bootstrap.patch +++ /dev/null @@ -1,97 +0,0 @@ ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_ECHO) += echo/ - obj-$(CONFIG_CXL_BASE) += cxl/ - obj-$(CONFIG_DW_XDATA_PCIE) += dw-xdata-pcie.o - obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o -+obj-$(CONFIG_SOC_MT7620) += linkit.o - obj-$(CONFIG_OCXL) += ocxl/ - obj-$(CONFIG_BCM_VK) += bcm-vk/ - obj-y += cardreader/ ---- /dev/null -+++ b/drivers/misc/linkit.c -@@ -0,0 +1,84 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * publishhed by the Free Software Foundation. -+ * -+ * Copyright (C) 2015 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define LINKIT_LATCH_GPIO 11 -+ -+struct linkit_hw_data { -+ char board[16]; -+ char rev[16]; -+}; -+ -+static void sanify_string(char *s) -+{ -+ int i; -+ -+ for (i = 0; i < 15; i++) -+ if (s[i] <= 0x20) -+ s[i] = '\0'; -+ s[15] = '\0'; -+} -+ -+static int linkit_probe(struct platform_device *pdev) -+{ -+ struct linkit_hw_data hw; -+ struct mtd_info *mtd; -+ size_t retlen; -+ int ret; -+ -+ mtd = get_mtd_device_nm("factory"); -+ if (IS_ERR(mtd)) -+ return PTR_ERR(mtd); -+ -+ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw); -+ put_mtd_device(mtd); -+ -+ sanify_string(hw.board); -+ sanify_string(hw.rev); -+ -+ dev_info(&pdev->dev, "Version : %s\n", hw.board); -+ dev_info(&pdev->dev, "Revision : %s\n", hw.rev); -+ -+ if (!strcmp(hw.board, "LINKITS7688")) { -+ dev_info(&pdev->dev, "setting up bootstrap latch\n"); -+ -+ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) { -+ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n"); -+ return -1; -+ } -+ gpio_direction_output(LINKIT_LATCH_GPIO, 0); -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id linkit_match[] = { -+ { .compatible = "mediatek,linkit" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, linkit_match); -+ -+static struct platform_driver linkit_driver = { -+ .probe = linkit_probe, -+ .driver = { -+ .name = "mtk-linkit", -+ .owner = THIS_MODULE, -+ .of_match_table = linkit_match, -+ }, -+}; -+ -+int __init linkit_init(void) -+{ -+ return platform_driver_register(&linkit_driver); -+} -+late_initcall_sync(linkit_init); diff --git a/target/linux/ramips/patches-5.15/860-ramips-add-eip93-driver.patch b/target/linux/ramips/patches-5.15/860-ramips-add-eip93-driver.patch deleted file mode 100644 index 4008d5fe7c..0000000000 --- a/target/linux/ramips/patches-5.15/860-ramips-add-eip93-driver.patch +++ /dev/null @@ -1,3276 +0,0 @@ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/Kconfig -@@ -0,0 +1,64 @@ -+# SPDX-License-Identifier: GPL-2.0 -+config CRYPTO_DEV_EIP93_SKCIPHER -+ tristate -+ -+config CRYPTO_DEV_EIP93_HMAC -+ tristate -+ -+config CRYPTO_DEV_EIP93 -+ tristate "Support for EIP93 crypto HW accelerators" -+ depends on SOC_MT7621 || COMPILE_TEST -+ help -+ EIP93 have various crypto HW accelerators. Select this if -+ you want to use the EIP93 modules for any of the crypto algorithms. -+ -+if CRYPTO_DEV_EIP93 -+ -+config CRYPTO_DEV_EIP93_AES -+ bool "Register AES algorithm implementations with the Crypto API" -+ default y -+ select CRYPTO_DEV_EIP93_SKCIPHER -+ select CRYPTO_LIB_AES -+ select CRYPTO_SKCIPHER -+ help -+ Selecting this will offload AES - ECB, CBC and CTR crypto -+ to the EIP-93 crypto engine. -+ -+config CRYPTO_DEV_EIP93_DES -+ bool "Register legacy DES / 3DES algorithm with the Crypto API" -+ default y -+ select CRYPTO_DEV_EIP93_SKCIPHER -+ select CRYPTO_LIB_DES -+ select CRYPTO_SKCIPHER -+ help -+ Selecting this will offload DES and 3DES ECB and CBC -+ crypto to the EIP-93 crypto engine. -+ -+config CRYPTO_DEV_EIP93_AEAD -+ bool "Register AEAD algorithm with the Crypto API" -+ default y -+ select CRYPTO_DEV_EIP93_HMAC -+ select CRYPTO_AEAD -+ select CRYPTO_AUTHENC -+ select CRYPTO_MD5 -+ select CRYPTO_SHA1 -+ select CRYPTO_SHA256 -+ help -+ Selecting this will offload AEAD authenc(hmac(x), cipher(y)) -+ crypto to the EIP-93 crypto engine. -+ -+config CRYPTO_DEV_EIP93_GENERIC_SW_MAX_LEN -+ int "Max skcipher software fallback length" -+ default 256 -+ help -+ Max length of crypt request which -+ will fallback to software crypt of skcipher *except* AES-128. -+ -+config CRYPTO_DEV_EIP93_AES_128_SW_MAX_LEN -+ int "Max AES-128 skcipher software fallback length" -+ default 512 -+ help -+ Max length of crypt request which -+ will fallback to software crypt of AES-128 skcipher. -+ -+endif ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/Makefile -@@ -0,0 +1,7 @@ -+obj-$(CONFIG_CRYPTO_DEV_EIP93) += crypto-hw-eip93.o -+ -+crypto-hw-eip93-y += eip93-main.o eip93-common.o -+ -+crypto-hw-eip93-$(CONFIG_CRYPTO_DEV_EIP93_SKCIPHER) += eip93-cipher.o -+crypto-hw-eip93-$(CONFIG_CRYPTO_DEV_EIP93_AEAD) += eip93-aead.o -+ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-aead.c -@@ -0,0 +1,768 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+#include -+#endif -+ -+#include -+#include -+ -+#include "eip93-aead.h" -+#include "eip93-cipher.h" -+#include "eip93-common.h" -+#include "eip93-regs.h" -+ -+void mtk_aead_handle_result(struct crypto_async_request *async, int err) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); -+ struct mtk_device *mtk = ctx->mtk; -+ struct aead_request *req = aead_request_cast(async); -+ struct mtk_cipher_reqctx *rctx = aead_request_ctx(req); -+ -+ mtk_unmap_dma(mtk, rctx, req->src, req->dst); -+ mtk_handle_result(mtk, rctx, req->iv); -+ -+ if (err == 1) -+ err = -EBADMSG; -+ /* let software handle anti-replay errors */ -+ if (err == 4) -+ err = 0; -+ -+ aead_request_complete(req, err); -+} -+ -+static int mtk_aead_send_req(struct crypto_async_request *async) -+{ -+ struct aead_request *req = aead_request_cast(async); -+ struct mtk_cipher_reqctx *rctx = aead_request_ctx(req); -+ int err; -+ -+ err = check_valid_request(rctx); -+ if (err) { -+ aead_request_complete(req, err); -+ return err; -+ } -+ -+ return mtk_send_req(async, req->iv, rctx); -+} -+ -+/* Crypto aead API functions */ -+static int mtk_aead_cra_init(struct crypto_tfm *tfm) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg, -+ struct mtk_alg_template, alg.aead.base); -+ u32 flags = tmpl->flags; -+ char *alg_base; -+ -+ crypto_aead_set_reqsize(__crypto_aead_cast(tfm), -+ sizeof(struct mtk_cipher_reqctx)); -+ -+ ctx->mtk = tmpl->mtk; -+ ctx->in_first = true; -+ ctx->out_first = true; -+ -+ ctx->sa_in = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL); -+ if (!ctx->sa_in) -+ return -ENOMEM; -+ -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ -+ ctx->sa_out = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL); -+ if (!ctx->sa_out) -+ return -ENOMEM; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ -+ /* software workaround for now */ -+ if (IS_HASH_MD5(flags)) -+ alg_base = "md5"; -+ if (IS_HASH_SHA1(flags)) -+ alg_base = "sha1"; -+ if (IS_HASH_SHA224(flags)) -+ alg_base = "sha224"; -+ if (IS_HASH_SHA256(flags)) -+ alg_base = "sha256"; -+ -+ ctx->shash = crypto_alloc_shash(alg_base, 0, CRYPTO_ALG_NEED_FALLBACK); -+ -+ if (IS_ERR(ctx->shash)) { -+ dev_err(ctx->mtk->dev, "base driver %s could not be loaded.\n", -+ alg_base); -+ return PTR_ERR(ctx->shash); -+ } -+ -+ return 0; -+} -+ -+static void mtk_aead_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ if (ctx->shash) -+ crypto_free_shash(ctx->shash); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ kfree(ctx->sa_in); -+ kfree(ctx->sa_out); -+} -+ -+static int mtk_aead_setkey(struct crypto_aead *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg, -+ struct mtk_alg_template, alg.skcipher.base); -+ u32 flags = tmpl->flags; -+ u32 nonce = 0; -+ struct crypto_authenc_keys keys; -+ struct crypto_aes_ctx aes; -+ struct saRecord_s *saRecord = ctx->sa_out; -+ int sa_size = sizeof(struct saRecord_s); -+ int err = -EINVAL; -+ -+ -+ if (crypto_authenc_extractkeys(&keys, key, len)) -+ return err; -+ -+ if (IS_RFC3686(flags)) { -+ if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) -+ return err; -+ -+ keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; -+ memcpy(&nonce, keys.enckey + keys.enckeylen, -+ CTR_RFC3686_NONCE_SIZE); -+ } -+ -+ switch ((flags & MTK_ALG_MASK)) { -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+ case MTK_ALG_DES: -+ err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen); -+ break; -+ case MTK_ALG_3DES: -+ if (keys.enckeylen != DES3_EDE_KEY_SIZE) -+ return -EINVAL; -+ -+ err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen); -+ break; -+#endif -+ case MTK_ALG_AES: -+ err = aes_expandkey(&aes, keys.enckey, keys.enckeylen); -+ } -+ if (err) -+ return err; -+ -+ ctx->blksize = crypto_aead_blocksize(ctfm); -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, sa_size, -+ DMA_TO_DEVICE); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, sa_size, -+ DMA_TO_DEVICE); -+ /* Encryption key */ -+ mtk_set_saRecord(saRecord, keys.enckeylen, flags); -+ saRecord->saCmd0.bits.opCode = 1; -+ saRecord->saCmd0.bits.digestLength = ctx->authsize >> 2; -+ -+ memcpy(saRecord->saKey, keys.enckey, keys.enckeylen); -+ ctx->saNonce = nonce; -+ saRecord->saNonce = nonce; -+ -+ /* authentication key */ -+ err = mtk_authenc_setkey(ctx->shash, saRecord, keys.authkey, -+ keys.authkeylen); -+ -+ saRecord->saCmd0.bits.direction = 0; -+ memcpy(ctx->sa_in, saRecord, sa_size); -+ ctx->sa_in->saCmd0.bits.direction = 1; -+ ctx->sa_in->saCmd1.bits.copyDigest = 0; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, sa_size, -+ DMA_TO_DEVICE); -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, sa_size, -+ DMA_TO_DEVICE); -+ ctx->in_first = true; -+ ctx->out_first = true; -+ -+ return err; -+} -+ -+static int mtk_aead_setauthsize(struct crypto_aead *ctfm, -+ unsigned int authsize) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ -+ ctx->authsize = authsize; -+ ctx->sa_in->saCmd0.bits.digestLength = ctx->authsize >> 2; -+ ctx->sa_out->saCmd0.bits.digestLength = ctx->authsize >> 2; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ return 0; -+} -+ -+static void mtk_aead_setassoc(struct mtk_crypto_ctx *ctx, -+ struct aead_request *req, bool in) -+{ -+ struct saRecord_s *saRecord; -+ -+ if (in) { -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ saRecord = ctx->sa_in; -+ saRecord->saCmd1.bits.hashCryptOffset = req->assoclen >> 2; -+ -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ ctx->assoclen_in = req->assoclen; -+ } else { -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ saRecord = ctx->sa_out; -+ saRecord->saCmd1.bits.hashCryptOffset = req->assoclen >> 2; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ ctx->assoclen_out = req->assoclen; -+ } -+} -+ -+static int mtk_aead_crypt(struct aead_request *req) -+{ -+ struct mtk_cipher_reqctx *rctx = aead_request_ctx(req); -+ struct crypto_async_request *async = &req->base; -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ -+ rctx->textsize = req->cryptlen; -+ rctx->blksize = ctx->blksize; -+ rctx->assoclen = req->assoclen; -+ rctx->authsize = ctx->authsize; -+ rctx->sg_src = req->src; -+ rctx->sg_dst = req->dst; -+ rctx->ivsize = crypto_aead_ivsize(aead); -+ rctx->flags |= MTK_DESC_AEAD; -+ -+ if IS_DECRYPT(rctx->flags) -+ rctx->textsize -= rctx->authsize; -+ -+ return mtk_aead_send_req(async); -+} -+ -+static int mtk_aead_encrypt(struct aead_request *req) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct mtk_cipher_reqctx *rctx = aead_request_ctx(req); -+ struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, -+ struct mtk_alg_template, alg.aead.base); -+ -+ rctx->flags = tmpl->flags; -+ rctx->flags |= MTK_ENCRYPT; -+ if (ctx->out_first) { -+ mtk_aead_setassoc(ctx, req, false); -+ ctx->out_first = false; -+ } -+ -+ if (req->assoclen != ctx->assoclen_out) { -+ dev_err(ctx->mtk->dev, "Request AAD length error\n"); -+ return -EINVAL; -+ } -+ -+ rctx->saRecord_base = ctx->sa_base_out; -+ -+ return mtk_aead_crypt(req); -+} -+ -+static int mtk_aead_decrypt(struct aead_request *req) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct mtk_cipher_reqctx *rctx = aead_request_ctx(req); -+ struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, -+ struct mtk_alg_template, alg.aead.base); -+ -+ rctx->flags = tmpl->flags; -+ rctx->flags |= MTK_DECRYPT; -+ if (ctx->in_first) { -+ mtk_aead_setassoc(ctx, req, true); -+ ctx->in_first = false; -+ } -+ -+ if (req->assoclen != ctx->assoclen_in) { -+ dev_err(ctx->mtk->dev, "Request AAD length error\n"); -+ return -EINVAL; -+ } -+ -+ rctx->saRecord_base = ctx->sa_base_in; -+ -+ return mtk_aead_crypt(req); -+} -+ -+/* Available authenc algorithms in this module */ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_MD5 | MTK_MODE_CBC | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(aes))", -+ .cra_driver_name = -+ "authenc(hmac(md5-eip93), cbc(aes-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA1 | MTK_MODE_CBC | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(aes))", -+ .cra_driver_name = -+ "authenc(hmac(sha1-eip93),cbc(aes-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA224 | MTK_MODE_CBC | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(aes))", -+ .cra_driver_name = -+ "authenc(hmac(sha224-eip93),cbc(aes-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA256 | MTK_MODE_CBC | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(aes))", -+ .cra_driver_name = -+ "authenc(hmac(sha256-eip93),cbc(aes-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_md5_rfc3686_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_MD5 | -+ MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(md5),rfc3686(ctr(aes)))", -+ .cra_driver_name = -+ "authenc(hmac(md5-eip93),rfc3686(ctr(aes-eip93)))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha1_rfc3686_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA1 | -+ MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", -+ .cra_driver_name = -+ "authenc(hmac(sha1-eip93),rfc3686(ctr(aes-eip93)))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha224_rfc3686_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA224 | -+ MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", -+ .cra_driver_name = -+ "authenc(hmac(sha224-eip93),rfc3686(ctr(aes-eip93)))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha256_rfc3686_aes = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA256 | -+ MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", -+ .cra_driver_name = -+ "authenc(hmac(sha256-eip93),rfc3686(ctr(aes-eip93)))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_des = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_MD5 | MTK_MODE_CBC | MTK_ALG_DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(des))", -+ .cra_driver_name = -+ "authenc(hmac(md5-eip93),cbc(des-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_des = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA1 | MTK_MODE_CBC | MTK_ALG_DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(des))", -+ .cra_driver_name = -+ "authenc(hmac(sha1-eip93),cbc(des-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_des = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA224 | MTK_MODE_CBC | MTK_ALG_DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des))", -+ .cra_driver_name = -+ "authenc(hmac(sha224-eip93),cbc(des-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_des = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA256 | MTK_MODE_CBC | MTK_ALG_DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des))", -+ .cra_driver_name = -+ "authenc(hmac(sha256-eip93),cbc(des-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_des3_ede = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_MD5 | MTK_MODE_CBC | MTK_ALG_3DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(des3_ede))", -+ .cra_driver_name = -+ "authenc(hmac(md5-eip93),cbc(des3_ede-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0x0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_des3_ede = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA1 | MTK_MODE_CBC | MTK_ALG_3DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(des3_ede))", -+ .cra_driver_name = -+ "authenc(hmac(sha1-eip93),cbc(des3_ede-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0x0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_des3_ede = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA224 | MTK_MODE_CBC | MTK_ALG_3DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", -+ .cra_driver_name = -+ "authenc(hmac(sha224-eip93),cbc(des3_ede-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0x0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_des3_ede = { -+ .type = MTK_ALG_TYPE_AEAD, -+ .flags = MTK_HASH_HMAC | MTK_HASH_SHA256 | MTK_MODE_CBC | MTK_ALG_3DES, -+ .alg.aead = { -+ .setkey = mtk_aead_setkey, -+ .encrypt = mtk_aead_encrypt, -+ .decrypt = mtk_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .setauthsize = mtk_aead_setauthsize, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", -+ .cra_driver_name = -+ "authenc(hmac(sha256-eip93),cbc(des3_ede-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0x0, -+ .cra_init = mtk_aead_cra_init, -+ .cra_exit = mtk_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+#endif ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-aead.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef _EIP93_AEAD_H_ -+#define _EIP93_AEAD_H_ -+ -+extern struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_md5_rfc3686_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha1_rfc3686_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha224_rfc3686_aes; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha256_rfc3686_aes; -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+extern struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_des; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_des; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_des; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_des; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_md5_cbc_des3_ede; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha1_cbc_des3_ede; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha224_cbc_des3_ede; -+extern struct mtk_alg_template mtk_alg_authenc_hmac_sha256_cbc_des3_ede; -+#endif -+ -+void mtk_aead_handle_result(struct crypto_async_request *async, int err); -+ -+#endif /* _EIP93_AEAD_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-aes.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef _EIP93_AES_H_ -+#define _EIP93_AES_H_ -+ -+extern struct mtk_alg_template mtk_alg_ecb_aes; -+extern struct mtk_alg_template mtk_alg_cbc_aes; -+extern struct mtk_alg_template mtk_alg_ctr_aes; -+extern struct mtk_alg_template mtk_alg_rfc3686_aes; -+ -+#endif /* _EIP93_AES_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-cipher.c -@@ -0,0 +1,483 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+#include -+#include -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+#include -+#endif -+#include -+ -+#include "eip93-cipher.h" -+#include "eip93-common.h" -+#include "eip93-regs.h" -+ -+void mtk_skcipher_handle_result(struct crypto_async_request *async, int err) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); -+ struct mtk_device *mtk = ctx->mtk; -+ struct skcipher_request *req = skcipher_request_cast(async); -+ struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ -+ mtk_unmap_dma(mtk, rctx, req->src, req->dst); -+ mtk_handle_result(mtk, rctx, req->iv); -+ -+ skcipher_request_complete(req, err); -+} -+ -+static inline bool mtk_skcipher_is_fallback(const struct crypto_tfm *tfm, -+ u32 flags) -+{ -+ return (tfm->__crt_alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) && -+ !IS_RFC3686(flags); -+} -+ -+static int mtk_skcipher_send_req(struct crypto_async_request *async) -+{ -+ struct skcipher_request *req = skcipher_request_cast(async); -+ struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ int err; -+ -+ err = check_valid_request(rctx); -+ -+ if (err) { -+ skcipher_request_complete(req, err); -+ return err; -+ } -+ -+ return mtk_send_req(async, req->iv, rctx); -+} -+ -+/* Crypto skcipher API functions */ -+static int mtk_skcipher_cra_init(struct crypto_tfm *tfm) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg, -+ struct mtk_alg_template, alg.skcipher.base); -+ bool fallback = mtk_skcipher_is_fallback(tfm, tmpl->flags); -+ -+ if (fallback) { -+ ctx->fallback = crypto_alloc_skcipher( -+ crypto_tfm_alg_name(tfm), 0, CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->fallback)) -+ return PTR_ERR(ctx->fallback); -+ } -+ -+ crypto_skcipher_set_reqsize( -+ __crypto_skcipher_cast(tfm), -+ sizeof(struct mtk_cipher_reqctx) + -+ (fallback ? crypto_skcipher_reqsize(ctx->fallback) : -+ 0)); -+ -+ ctx->mtk = tmpl->mtk; -+ -+ ctx->sa_in = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL); -+ if (!ctx->sa_in) -+ return -ENOMEM; -+ -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ -+ ctx->sa_out = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL); -+ if (!ctx->sa_out) -+ return -ENOMEM; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ return 0; -+} -+ -+static void mtk_skcipher_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, -+ sizeof(struct saRecord_s), DMA_TO_DEVICE); -+ kfree(ctx->sa_in); -+ kfree(ctx->sa_out); -+ -+ crypto_free_skcipher(ctx->fallback); -+} -+ -+static int mtk_skcipher_setkey(struct crypto_skcipher *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg, -+ struct mtk_alg_template, alg.skcipher.base); -+ struct saRecord_s *saRecord = ctx->sa_out; -+ u32 flags = tmpl->flags; -+ u32 nonce = 0; -+ unsigned int keylen = len; -+ int sa_size = sizeof(struct saRecord_s); -+ int err = -EINVAL; -+ -+ if (!key || !keylen) -+ return err; -+ -+ ctx->keylen = keylen; -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+ if (IS_RFC3686(flags)) { -+ if (len < CTR_RFC3686_NONCE_SIZE) -+ return err; -+ -+ keylen = len - CTR_RFC3686_NONCE_SIZE; -+ memcpy(&nonce, key + keylen, CTR_RFC3686_NONCE_SIZE); -+ } -+#endif -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+ if (flags & MTK_ALG_DES) { -+ ctx->blksize = DES_BLOCK_SIZE; -+ err = verify_skcipher_des_key(ctfm, key); -+ } -+ if (flags & MTK_ALG_3DES) { -+ ctx->blksize = DES3_EDE_BLOCK_SIZE; -+ err = verify_skcipher_des3_key(ctfm, key); -+ } -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+ if (flags & MTK_ALG_AES) { -+ struct crypto_aes_ctx aes; -+ bool fallback = mtk_skcipher_is_fallback(tfm, flags); -+ -+ if (fallback && !IS_RFC3686(flags)) { -+ err = crypto_skcipher_setkey(ctx->fallback, key, -+ keylen); -+ if (err) -+ return err; -+ } -+ -+ ctx->blksize = AES_BLOCK_SIZE; -+ err = aes_expandkey(&aes, key, keylen); -+ } -+#endif -+ if (err) -+ return err; -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, sa_size, -+ DMA_TO_DEVICE); -+ -+ dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, sa_size, -+ DMA_TO_DEVICE); -+ -+ mtk_set_saRecord(saRecord, keylen, flags); -+ -+ memcpy(saRecord->saKey, key, keylen); -+ ctx->saNonce = nonce; -+ saRecord->saNonce = nonce; -+ saRecord->saCmd0.bits.direction = 0; -+ -+ memcpy(ctx->sa_in, saRecord, sa_size); -+ ctx->sa_in->saCmd0.bits.direction = 1; -+ -+ ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, sa_size, -+ DMA_TO_DEVICE); -+ -+ ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, sa_size, -+ DMA_TO_DEVICE); -+ return err; -+} -+ -+static int mtk_skcipher_crypt(struct skcipher_request *req, bool encrypt) -+{ -+ struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct crypto_async_request *async = &req->base; -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ bool fallback = mtk_skcipher_is_fallback(req->base.tfm, rctx->flags); -+ -+ if (!req->cryptlen) -+ return 0; -+ -+ /* -+ * ECB and CBC algorithms require message lengths to be -+ * multiples of block size. -+ */ -+ if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) -+ if (!IS_ALIGNED(req->cryptlen, -+ crypto_skcipher_blocksize(skcipher))) -+ return -EINVAL; -+ -+ if (fallback && -+ req->cryptlen <= (AES_KEYSIZE_128 ? -+ CONFIG_CRYPTO_DEV_EIP93_AES_128_SW_MAX_LEN : -+ CONFIG_CRYPTO_DEV_EIP93_GENERIC_SW_MAX_LEN)) { -+ skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); -+ skcipher_request_set_callback(&rctx->fallback_req, -+ req->base.flags, -+ req->base.complete, -+ req->base.data); -+ skcipher_request_set_crypt(&rctx->fallback_req, req->src, -+ req->dst, req->cryptlen, req->iv); -+ return encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) : -+ crypto_skcipher_decrypt(&rctx->fallback_req); -+ } -+ -+ rctx->assoclen = 0; -+ rctx->textsize = req->cryptlen; -+ rctx->authsize = 0; -+ rctx->sg_src = req->src; -+ rctx->sg_dst = req->dst; -+ rctx->ivsize = crypto_skcipher_ivsize(skcipher); -+ rctx->blksize = ctx->blksize; -+ rctx->flags |= MTK_DESC_SKCIPHER; -+ if (!IS_ECB(rctx->flags)) -+ rctx->flags |= MTK_DESC_DMA_IV; -+ -+ return mtk_skcipher_send_req(async); -+} -+ -+static int mtk_skcipher_encrypt(struct skcipher_request *req) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, -+ struct mtk_alg_template, alg.skcipher.base); -+ -+ rctx->flags = tmpl->flags; -+ rctx->flags |= MTK_ENCRYPT; -+ rctx->saRecord_base = ctx->sa_base_out; -+ -+ return mtk_skcipher_crypt(req, true); -+} -+ -+static int mtk_skcipher_decrypt(struct skcipher_request *req) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); -+ struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req); -+ struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, -+ struct mtk_alg_template, alg.skcipher.base); -+ -+ rctx->flags = tmpl->flags; -+ rctx->flags |= MTK_DECRYPT; -+ rctx->saRecord_base = ctx->sa_base_in; -+ -+ return mtk_skcipher_crypt(req, false); -+} -+ -+/* Available algorithms in this module */ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+struct mtk_alg_template mtk_alg_ecb_aes = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_ECB | MTK_ALG_AES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = 0, -+ .base = { -+ .cra_name = "ecb(aes)", -+ .cra_driver_name = "ecb(aes-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0xf, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_cbc_aes = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_CBC | MTK_ALG_AES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "cbc(aes-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0xf, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_ctr_aes = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_CTR | MTK_ALG_AES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .base = { -+ .cra_name = "ctr(aes)", -+ .cra_driver_name = "ctr(aes-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0xf, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_rfc3686_aes = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .base = { -+ .cra_name = "rfc3686(ctr(aes))", -+ .cra_driver_name = "rfc3686(ctr(aes-eip93))", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0xf, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+struct mtk_alg_template mtk_alg_ecb_des = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_ECB | MTK_ALG_DES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .ivsize = 0, -+ .base = { -+ .cra_name = "ecb(des)", -+ .cra_driver_name = "ebc(des-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_cbc_des = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_CBC | MTK_ALG_DES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cbc(des)", -+ .cra_driver_name = "cbc(des-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_ecb_des3_ede = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_ECB | MTK_ALG_3DES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .ivsize = 0, -+ .base = { -+ .cra_name = "ecb(des3_ede)", -+ .cra_driver_name = "ecb(des3_ede-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+struct mtk_alg_template mtk_alg_cbc_des3_ede = { -+ .type = MTK_ALG_TYPE_SKCIPHER, -+ .flags = MTK_MODE_CBC | MTK_ALG_3DES, -+ .alg.skcipher = { -+ .setkey = mtk_skcipher_setkey, -+ .encrypt = mtk_skcipher_encrypt, -+ .decrypt = mtk_skcipher_decrypt, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cbc(des3_ede)", -+ .cra_driver_name = "cbc(des3_ede-eip93)", -+ .cra_priority = MTK_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct mtk_crypto_ctx), -+ .cra_alignmask = 0, -+ .cra_init = mtk_skcipher_cra_init, -+ .cra_exit = mtk_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+#endif ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-cipher.h -@@ -0,0 +1,66 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef _EIP93_CIPHER_H_ -+#define _EIP93_CIPHER_H_ -+ -+#include "eip93-main.h" -+ -+struct mtk_crypto_ctx { -+ struct mtk_device *mtk; -+ struct saRecord_s *sa_in; -+ dma_addr_t sa_base_in; -+ struct saRecord_s *sa_out; -+ dma_addr_t sa_base_out; -+ uint32_t saNonce; -+ int blksize; -+ /* AEAD specific */ -+ unsigned int authsize; -+ unsigned int assoclen_in; -+ unsigned int assoclen_out; -+ bool in_first; -+ bool out_first; -+ struct crypto_shash *shash; -+ unsigned int keylen; -+ struct crypto_skcipher *fallback; -+}; -+ -+struct mtk_cipher_reqctx { -+ unsigned long flags; -+ unsigned int blksize; -+ unsigned int ivsize; -+ unsigned int textsize; -+ unsigned int assoclen; -+ unsigned int authsize; -+ dma_addr_t saRecord_base; -+ struct saState_s *saState; -+ dma_addr_t saState_base; -+ uint32_t saState_idx; -+ struct eip93_descriptor_s *cdesc; -+ struct scatterlist *sg_src; -+ struct scatterlist *sg_dst; -+ int src_nents; -+ int dst_nents; -+ struct saState_s *saState_ctr; -+ dma_addr_t saState_base_ctr; -+ uint32_t saState_ctr_idx; -+ struct skcipher_request fallback_req; // keep at the end -+}; -+ -+int check_valid_request(struct mtk_cipher_reqctx *rctx); -+ -+void mtk_unmap_dma(struct mtk_device *mtk, struct mtk_cipher_reqctx *rctx, -+ struct scatterlist *reqsrc, struct scatterlist *reqdst); -+ -+void mtk_skcipher_handle_result(struct crypto_async_request *async, int err); -+ -+int mtk_send_req(struct crypto_async_request *async, -+ const u8 *reqiv, struct mtk_cipher_reqctx *rctx); -+ -+void mtk_handle_result(struct mtk_device *mtk, struct mtk_cipher_reqctx *rctx, -+ u8 *reqiv); -+ -+#endif /* _EIP93_CIPHER_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-common.c -@@ -0,0 +1,749 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "eip93-cipher.h" -+#include "eip93-common.h" -+#include "eip93-main.h" -+#include "eip93-regs.h" -+ -+inline void *mtk_ring_next_wptr(struct mtk_device *mtk, -+ struct mtk_desc_ring *ring) -+{ -+ void *ptr = ring->write; -+ -+ if ((ring->write == ring->read - ring->offset) || -+ (ring->read == ring->base && ring->write == ring->base_end)) -+ return ERR_PTR(-ENOMEM); -+ -+ if (ring->write == ring->base_end) -+ ring->write = ring->base; -+ else -+ ring->write += ring->offset; -+ -+ return ptr; -+} -+ -+inline void *mtk_ring_next_rptr(struct mtk_device *mtk, -+ struct mtk_desc_ring *ring) -+{ -+ void *ptr = ring->read; -+ -+ if (ring->write == ring->read) -+ return ERR_PTR(-ENOENT); -+ -+ if (ring->read == ring->base_end) -+ ring->read = ring->base; -+ else -+ ring->read += ring->offset; -+ -+ return ptr; -+} -+ -+inline int mtk_put_descriptor(struct mtk_device *mtk, -+ struct eip93_descriptor_s *desc) -+{ -+ struct eip93_descriptor_s *cdesc; -+ struct eip93_descriptor_s *rdesc; -+ unsigned long irqflags; -+ -+ spin_lock_irqsave(&mtk->ring->write_lock, irqflags); -+ -+ rdesc = mtk_ring_next_wptr(mtk, &mtk->ring->rdr); -+ -+ if (IS_ERR(rdesc)) { -+ spin_unlock_irqrestore(&mtk->ring->write_lock, irqflags); -+ return -ENOENT; -+ } -+ -+ cdesc = mtk_ring_next_wptr(mtk, &mtk->ring->cdr); -+ -+ if (IS_ERR(cdesc)) { -+ spin_unlock_irqrestore(&mtk->ring->write_lock, irqflags); -+ return -ENOENT; -+ } -+ -+ memset(rdesc, 0, sizeof(struct eip93_descriptor_s)); -+ memcpy(cdesc, desc, sizeof(struct eip93_descriptor_s)); -+ -+ atomic_dec(&mtk->ring->free); -+ spin_unlock_irqrestore(&mtk->ring->write_lock, irqflags); -+ -+ return 0; -+} -+ -+inline void *mtk_get_descriptor(struct mtk_device *mtk) -+{ -+ struct eip93_descriptor_s *cdesc; -+ void *ptr; -+ unsigned long irqflags; -+ -+ spin_lock_irqsave(&mtk->ring->read_lock, irqflags); -+ -+ cdesc = mtk_ring_next_rptr(mtk, &mtk->ring->cdr); -+ -+ if (IS_ERR(cdesc)) { -+ spin_unlock_irqrestore(&mtk->ring->read_lock, irqflags); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ memset(cdesc, 0, sizeof(struct eip93_descriptor_s)); -+ -+ ptr = mtk_ring_next_rptr(mtk, &mtk->ring->rdr); -+ if (IS_ERR(ptr)) { -+ spin_unlock_irqrestore(&mtk->ring->read_lock, irqflags); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ atomic_inc(&mtk->ring->free); -+ spin_unlock_irqrestore(&mtk->ring->read_lock, irqflags); -+ -+ return ptr; -+} -+ -+inline int mtk_get_free_saState(struct mtk_device *mtk) -+{ -+ struct mtk_state_pool *saState_pool; -+ int i; -+ -+ for (i = 0; i < MTK_RING_SIZE; i++) { -+ saState_pool = &mtk->ring->saState_pool[i]; -+ if (saState_pool->in_use == false) { -+ saState_pool->in_use = true; -+ return i; -+ } -+ -+ } -+ -+ return -ENOENT; -+} -+ -+static inline void mtk_free_sg_copy(const int len, struct scatterlist **sg) -+{ -+ if (!*sg || !len) -+ return; -+ -+ free_pages((unsigned long)sg_virt(*sg), get_order(len)); -+ kfree(*sg); -+ *sg = NULL; -+} -+ -+static inline int mtk_make_sg_copy(struct scatterlist *src, -+ struct scatterlist **dst, -+ const uint32_t len, const bool copy) -+{ -+ void *pages; -+ -+ *dst = kmalloc(sizeof(**dst), GFP_KERNEL); -+ if (!*dst) -+ return -ENOMEM; -+ -+ -+ pages = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, -+ get_order(len)); -+ -+ if (!pages) { -+ kfree(*dst); -+ *dst = NULL; -+ return -ENOMEM; -+ } -+ -+ sg_init_table(*dst, 1); -+ sg_set_buf(*dst, pages, len); -+ -+ /* copy only as requested */ -+ if (copy) -+ sg_copy_to_buffer(src, sg_nents(src), pages, len); -+ -+ return 0; -+} -+ -+static inline bool mtk_is_sg_aligned(struct scatterlist *sg, u32 len, -+ const int blksize) -+{ -+ int nents; -+ -+ for (nents = 0; sg; sg = sg_next(sg), ++nents) { -+ if (!IS_ALIGNED(sg->offset, 4)) -+ return false; -+ -+ if (len <= sg->length) { -+ if (!IS_ALIGNED(len, blksize)) -+ return false; -+ -+ return true; -+ } -+ -+ if (!IS_ALIGNED(sg->length, blksize)) -+ return false; -+ -+ len -= sg->length; -+ } -+ return false; -+} -+ -+int check_valid_request(struct mtk_cipher_reqctx *rctx) -+{ -+ struct scatterlist *src = rctx->sg_src; -+ struct scatterlist *dst = rctx->sg_dst; -+ uint32_t src_nents, dst_nents; -+ u32 textsize = rctx->textsize; -+ u32 authsize = rctx->authsize; -+ u32 blksize = rctx->blksize; -+ u32 totlen_src = rctx->assoclen + rctx->textsize; -+ u32 totlen_dst = rctx->assoclen + rctx->textsize; -+ u32 copy_len; -+ bool src_align, dst_align; -+ int err = -EINVAL; -+ -+ if (!IS_CTR(rctx->flags)) { -+ if (!IS_ALIGNED(textsize, blksize)) -+ return err; -+ } -+ -+ if (authsize) { -+ if (IS_ENCRYPT(rctx->flags)) -+ totlen_dst += authsize; -+ else -+ totlen_src += authsize; -+ } -+ -+ src_nents = sg_nents_for_len(src, totlen_src); -+ dst_nents = sg_nents_for_len(dst, totlen_dst); -+ -+ if (src == dst) { -+ src_nents = max(src_nents, dst_nents); -+ dst_nents = src_nents; -+ if (unlikely((totlen_src || totlen_dst) && (src_nents <= 0))) -+ return err; -+ -+ } else { -+ if (unlikely(totlen_src && (src_nents <= 0))) -+ return err; -+ -+ if (unlikely(totlen_dst && (dst_nents <= 0))) -+ return err; -+ } -+ -+ if (authsize) { -+ if (dst_nents == 1 && src_nents == 1) { -+ src_align = mtk_is_sg_aligned(src, totlen_src, blksize); -+ if (src == dst) -+ dst_align = src_align; -+ else -+ dst_align = mtk_is_sg_aligned(dst, -+ totlen_dst, blksize); -+ } else { -+ src_align = false; -+ dst_align = false; -+ } -+ } else { -+ src_align = mtk_is_sg_aligned(src, totlen_src, blksize); -+ if (src == dst) -+ dst_align = src_align; -+ else -+ dst_align = mtk_is_sg_aligned(dst, totlen_dst, blksize); -+ } -+ -+ copy_len = max(totlen_src, totlen_dst); -+ if (!src_align) { -+ err = mtk_make_sg_copy(src, &rctx->sg_src, copy_len, true); -+ if (err) -+ return err; -+ } -+ -+ if (!dst_align) { -+ err = mtk_make_sg_copy(dst, &rctx->sg_dst, copy_len, false); -+ if (err) -+ return err; -+ } -+ -+ rctx->src_nents = sg_nents_for_len(rctx->sg_src, totlen_src); -+ rctx->dst_nents = sg_nents_for_len(rctx->sg_dst, totlen_dst); -+ -+ return 0; -+} -+/* -+ * Set saRecord function: -+ * Even saRecord is set to "0", keep " = 0" for readability. -+ */ -+void mtk_set_saRecord(struct saRecord_s *saRecord, const unsigned int keylen, -+ const u32 flags) -+{ -+ saRecord->saCmd0.bits.ivSource = 2; -+ if (IS_ECB(flags)) -+ saRecord->saCmd0.bits.saveIv = 0; -+ else -+ saRecord->saCmd0.bits.saveIv = 1; -+ -+ saRecord->saCmd0.bits.opGroup = 0; -+ saRecord->saCmd0.bits.opCode = 0; -+ -+ switch ((flags & MTK_ALG_MASK)) { -+ case MTK_ALG_AES: -+ saRecord->saCmd0.bits.cipher = 3; -+ saRecord->saCmd1.bits.aesKeyLen = keylen >> 3; -+ break; -+ case MTK_ALG_3DES: -+ saRecord->saCmd0.bits.cipher = 1; -+ break; -+ case MTK_ALG_DES: -+ saRecord->saCmd0.bits.cipher = 0; -+ break; -+ default: -+ saRecord->saCmd0.bits.cipher = 15; -+ } -+ -+ switch ((flags & MTK_HASH_MASK)) { -+ case MTK_HASH_SHA256: -+ saRecord->saCmd0.bits.hash = 3; -+ break; -+ case MTK_HASH_SHA224: -+ saRecord->saCmd0.bits.hash = 2; -+ break; -+ case MTK_HASH_SHA1: -+ saRecord->saCmd0.bits.hash = 1; -+ break; -+ case MTK_HASH_MD5: -+ saRecord->saCmd0.bits.hash = 0; -+ break; -+ default: -+ saRecord->saCmd0.bits.hash = 15; -+ } -+ -+ saRecord->saCmd0.bits.hdrProc = 0; -+ saRecord->saCmd0.bits.padType = 3; -+ saRecord->saCmd0.bits.extPad = 0; -+ saRecord->saCmd0.bits.scPad = 0; -+ -+ switch ((flags & MTK_MODE_MASK)) { -+ case MTK_MODE_CBC: -+ saRecord->saCmd1.bits.cipherMode = 1; -+ break; -+ case MTK_MODE_CTR: -+ saRecord->saCmd1.bits.cipherMode = 2; -+ break; -+ case MTK_MODE_ECB: -+ saRecord->saCmd1.bits.cipherMode = 0; -+ break; -+ } -+ -+ saRecord->saCmd1.bits.byteOffset = 0; -+ saRecord->saCmd1.bits.hashCryptOffset = 0; -+ saRecord->saCmd0.bits.digestLength = 0; -+ saRecord->saCmd1.bits.copyPayload = 0; -+ -+ if (IS_HMAC(flags)) { -+ saRecord->saCmd1.bits.hmac = 1; -+ saRecord->saCmd1.bits.copyDigest = 1; -+ saRecord->saCmd1.bits.copyHeader = 1; -+ } else { -+ saRecord->saCmd1.bits.hmac = 0; -+ saRecord->saCmd1.bits.copyDigest = 0; -+ saRecord->saCmd1.bits.copyHeader = 0; -+ } -+ -+ saRecord->saCmd1.bits.seqNumCheck = 0; -+ saRecord->saSpi = 0x0; -+ saRecord->saSeqNumMask[0] = 0xFFFFFFFF; -+ saRecord->saSeqNumMask[1] = 0x0; -+} -+ -+/* -+ * Poor mans Scatter/gather function: -+ * Create a Descriptor for every segment to avoid copying buffers. -+ * For performance better to wait for hardware to perform multiple DMA -+ * -+ */ -+static inline int mtk_scatter_combine(struct mtk_device *mtk, -+ struct mtk_cipher_reqctx *rctx, -+ u32 datalen, u32 split, int offsetin) -+{ -+ struct eip93_descriptor_s *cdesc = rctx->cdesc; -+ struct scatterlist *sgsrc = rctx->sg_src; -+ struct scatterlist *sgdst = rctx->sg_dst; -+ unsigned int remainin = sg_dma_len(sgsrc); -+ unsigned int remainout = sg_dma_len(sgdst); -+ dma_addr_t saddr = sg_dma_address(sgsrc); -+ dma_addr_t daddr = sg_dma_address(sgdst); -+ dma_addr_t stateAddr; -+ u32 srcAddr, dstAddr, len, n; -+ bool nextin = false; -+ bool nextout = false; -+ int offsetout = 0; -+ int ndesc_cdr = 0, err; -+ -+ if (IS_ECB(rctx->flags)) -+ rctx->saState_base = 0; -+ -+ if (split < datalen) { -+ stateAddr = rctx->saState_base_ctr; -+ n = split; -+ } else { -+ stateAddr = rctx->saState_base; -+ n = datalen; -+ } -+ -+ do { -+ if (nextin) { -+ sgsrc = sg_next(sgsrc); -+ remainin = sg_dma_len(sgsrc); -+ if (remainin == 0) -+ continue; -+ -+ saddr = sg_dma_address(sgsrc); -+ offsetin = 0; -+ nextin = false; -+ } -+ -+ if (nextout) { -+ sgdst = sg_next(sgdst); -+ remainout = sg_dma_len(sgdst); -+ if (remainout == 0) -+ continue; -+ -+ daddr = sg_dma_address(sgdst); -+ offsetout = 0; -+ nextout = false; -+ } -+ srcAddr = saddr + offsetin; -+ dstAddr = daddr + offsetout; -+ -+ if (remainin == remainout) { -+ len = remainin; -+ if (len > n) { -+ len = n; -+ remainin -= n; -+ remainout -= n; -+ offsetin += n; -+ offsetout += n; -+ } else { -+ nextin = true; -+ nextout = true; -+ } -+ } else if (remainin < remainout) { -+ len = remainin; -+ if (len > n) { -+ len = n; -+ remainin -= n; -+ remainout -= n; -+ offsetin += n; -+ offsetout += n; -+ } else { -+ offsetout += len; -+ remainout -= len; -+ nextin = true; -+ } -+ } else { -+ len = remainout; -+ if (len > n) { -+ len = n; -+ remainin -= n; -+ remainout -= n; -+ offsetin += n; -+ offsetout += n; -+ } else { -+ offsetin += len; -+ remainin -= len; -+ nextout = true; -+ } -+ } -+ n -= len; -+ -+ cdesc->srcAddr = srcAddr; -+ cdesc->dstAddr = dstAddr; -+ cdesc->stateAddr = stateAddr; -+ cdesc->peLength.bits.peReady = 0; -+ cdesc->peLength.bits.byPass = 0; -+ cdesc->peLength.bits.length = len; -+ cdesc->peLength.bits.hostReady = 1; -+ -+ if (n == 0) { -+ n = datalen - split; -+ split = datalen; -+ stateAddr = rctx->saState_base; -+ } -+ -+ if (n == 0) -+ cdesc->userId |= MTK_DESC_LAST; -+ -+ /* Loop - Delay - No need to rollback -+ * Maybe refine by slowing down at MTK_RING_BUSY -+ */ -+again: -+ err = mtk_put_descriptor(mtk, cdesc); -+ if (err) { -+ udelay(500); -+ goto again; -+ } -+ /* Writing new descriptor count starts DMA action */ -+ writel(1, mtk->base + EIP93_REG_PE_CD_COUNT); -+ -+ ndesc_cdr++; -+ } while (n); -+ -+ return -EINPROGRESS; -+} -+ -+int mtk_send_req(struct crypto_async_request *async, -+ const u8 *reqiv, struct mtk_cipher_reqctx *rctx) -+{ -+ struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); -+ struct mtk_device *mtk = ctx->mtk; -+ struct scatterlist *src = rctx->sg_src; -+ struct scatterlist *dst = rctx->sg_dst; -+ struct saState_s *saState; -+ struct mtk_state_pool *saState_pool; -+ struct eip93_descriptor_s cdesc; -+ u32 flags = rctx->flags; -+ int idx; -+ int offsetin = 0, err = -ENOMEM; -+ u32 datalen = rctx->assoclen + rctx->textsize; -+ u32 split = datalen; -+ u32 start, end, ctr, blocks; -+ u32 iv[AES_BLOCK_SIZE / sizeof(u32)]; -+ -+ rctx->saState_ctr = NULL; -+ rctx->saState = NULL; -+ -+ if (IS_ECB(flags)) -+ goto skip_iv; -+ -+ memcpy(iv, reqiv, rctx->ivsize); -+ -+ if (!IS_ALIGNED((u32)reqiv, rctx->ivsize) || IS_RFC3686(flags)) { -+ rctx->flags &= ~MTK_DESC_DMA_IV; -+ flags = rctx->flags; -+ } -+ -+ if (IS_DMA_IV(flags)) { -+ rctx->saState = (void *)reqiv; -+ } else { -+ idx = mtk_get_free_saState(mtk); -+ if (idx < 0) -+ goto send_err; -+ saState_pool = &mtk->ring->saState_pool[idx]; -+ rctx->saState_idx = idx; -+ rctx->saState = saState_pool->base; -+ rctx->saState_base = saState_pool->base_dma; -+ memcpy(rctx->saState->stateIv, iv, rctx->ivsize); -+ } -+ -+ saState = rctx->saState; -+ -+ if (IS_RFC3686(flags)) { -+ saState->stateIv[0] = ctx->saNonce; -+ saState->stateIv[1] = iv[0]; -+ saState->stateIv[2] = iv[1]; -+ saState->stateIv[3] = cpu_to_be32(1); -+ } else if (!IS_HMAC(flags) && IS_CTR(flags)) { -+ /* Compute data length. */ -+ blocks = DIV_ROUND_UP(rctx->textsize, AES_BLOCK_SIZE); -+ ctr = be32_to_cpu(iv[3]); -+ /* Check 32bit counter overflow. */ -+ start = ctr; -+ end = start + blocks - 1; -+ if (end < start) { -+ split = AES_BLOCK_SIZE * -start; -+ /* -+ * Increment the counter manually to cope with -+ * the hardware counter overflow. -+ */ -+ iv[3] = 0xffffffff; -+ crypto_inc((u8 *)iv, AES_BLOCK_SIZE); -+ idx = mtk_get_free_saState(mtk); -+ if (idx < 0) -+ goto free_state; -+ saState_pool = &mtk->ring->saState_pool[idx]; -+ rctx->saState_ctr_idx = idx; -+ rctx->saState_ctr = saState_pool->base; -+ rctx->saState_base_ctr = saState_pool->base_dma; -+ -+ memcpy(rctx->saState_ctr->stateIv, reqiv, rctx->ivsize); -+ memcpy(saState->stateIv, iv, rctx->ivsize); -+ } -+ } -+ -+ if (IS_DMA_IV(flags)) { -+ rctx->saState_base = dma_map_single(mtk->dev, (void *)reqiv, -+ rctx->ivsize, DMA_TO_DEVICE); -+ if (dma_mapping_error(mtk->dev, rctx->saState_base)) -+ goto free_state; -+ } -+skip_iv: -+ cdesc.peCrtlStat.bits.hostReady = 1; -+ cdesc.peCrtlStat.bits.prngMode = 0; -+ cdesc.peCrtlStat.bits.hashFinal = 0; -+ cdesc.peCrtlStat.bits.padCrtlStat = 0; -+ cdesc.peCrtlStat.bits.peReady = 0; -+ cdesc.saAddr = rctx->saRecord_base; -+ cdesc.arc4Addr = (uint32_t)async; -+ cdesc.userId = flags; -+ rctx->cdesc = &cdesc; -+ -+ /* map DMA_BIDIRECTIONAL to invalidate cache on destination -+ * implies __dma_cache_wback_inv -+ */ -+ dma_map_sg(mtk->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL); -+ if (src != dst) -+ dma_map_sg(mtk->dev, src, rctx->src_nents, DMA_TO_DEVICE); -+ -+ err = mtk_scatter_combine(mtk, rctx, datalen, split, offsetin); -+ -+ return err; -+ -+free_state: -+ if (rctx->saState) { -+ saState_pool = &mtk->ring->saState_pool[rctx->saState_idx]; -+ saState_pool->in_use = false; -+ } -+ -+ if (rctx->saState_ctr) { -+ saState_pool = &mtk->ring->saState_pool[rctx->saState_ctr_idx]; -+ saState_pool->in_use = false; -+ } -+send_err: -+ return err; -+} -+ -+void mtk_unmap_dma(struct mtk_device *mtk, struct mtk_cipher_reqctx *rctx, -+ struct scatterlist *reqsrc, struct scatterlist *reqdst) -+{ -+ u32 len = rctx->assoclen + rctx->textsize; -+ u32 authsize = rctx->authsize; -+ u32 flags = rctx->flags; -+ u32 *otag; -+ int i; -+ -+ if (rctx->sg_src == rctx->sg_dst) { -+ dma_unmap_sg(mtk->dev, rctx->sg_dst, rctx->dst_nents, -+ DMA_BIDIRECTIONAL); -+ goto process_tag; -+ } -+ -+ dma_unmap_sg(mtk->dev, rctx->sg_src, rctx->src_nents, -+ DMA_TO_DEVICE); -+ -+ if (rctx->sg_src != reqsrc) -+ mtk_free_sg_copy(len + rctx->authsize, &rctx->sg_src); -+ -+ dma_unmap_sg(mtk->dev, rctx->sg_dst, rctx->dst_nents, -+ DMA_BIDIRECTIONAL); -+ -+ /* SHA tags need conversion from net-to-host */ -+process_tag: -+ if (IS_DECRYPT(flags)) -+ authsize = 0; -+ -+ if (authsize) { -+ if (!IS_HASH_MD5(flags)) { -+ otag = sg_virt(rctx->sg_dst) + len; -+ for (i = 0; i < (authsize / 4); i++) -+ otag[i] = ntohl(otag[i]); -+ } -+ } -+ -+ if (rctx->sg_dst != reqdst) { -+ sg_copy_from_buffer(reqdst, sg_nents(reqdst), -+ sg_virt(rctx->sg_dst), len + authsize); -+ mtk_free_sg_copy(len + rctx->authsize, &rctx->sg_dst); -+ } -+} -+ -+void mtk_handle_result(struct mtk_device *mtk, struct mtk_cipher_reqctx *rctx, -+ u8 *reqiv) -+{ -+ struct mtk_state_pool *saState_pool; -+ -+ if (IS_DMA_IV(rctx->flags)) -+ dma_unmap_single(mtk->dev, rctx->saState_base, rctx->ivsize, -+ DMA_TO_DEVICE); -+ -+ if (!IS_ECB(rctx->flags)) -+ memcpy(reqiv, rctx->saState->stateIv, rctx->ivsize); -+ -+ if ((rctx->saState) && !(IS_DMA_IV(rctx->flags))) { -+ saState_pool = &mtk->ring->saState_pool[rctx->saState_idx]; -+ saState_pool->in_use = false; -+ } -+ -+ if (rctx->saState_ctr) { -+ saState_pool = &mtk->ring->saState_pool[rctx->saState_ctr_idx]; -+ saState_pool->in_use = false; -+ } -+} -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_HMAC) -+/* basically this is set hmac - key */ -+int mtk_authenc_setkey(struct crypto_shash *cshash, struct saRecord_s *sa, -+ const u8 *authkey, unsigned int authkeylen) -+{ -+ int bs = crypto_shash_blocksize(cshash); -+ int ds = crypto_shash_digestsize(cshash); -+ int ss = crypto_shash_statesize(cshash); -+ u8 *ipad, *opad; -+ unsigned int i, err; -+ -+ SHASH_DESC_ON_STACK(shash, cshash); -+ -+ shash->tfm = cshash; -+ -+ /* auth key -+ * -+ * EIP93 can only authenticate with hash of the key -+ * do software shash until EIP93 hash function complete. -+ */ -+ ipad = kcalloc(2, SHA256_BLOCK_SIZE + ss, GFP_KERNEL); -+ if (!ipad) -+ return -ENOMEM; -+ -+ opad = ipad + SHA256_BLOCK_SIZE + ss; -+ -+ if (authkeylen > bs) { -+ err = crypto_shash_digest(shash, authkey, -+ authkeylen, ipad); -+ if (err) -+ return err; -+ -+ authkeylen = ds; -+ } else -+ memcpy(ipad, authkey, authkeylen); -+ -+ memset(ipad + authkeylen, 0, bs - authkeylen); -+ memcpy(opad, ipad, bs); -+ -+ for (i = 0; i < bs; i++) { -+ ipad[i] ^= HMAC_IPAD_VALUE; -+ opad[i] ^= HMAC_OPAD_VALUE; -+ } -+ -+ err = crypto_shash_init(shash) ?: -+ crypto_shash_update(shash, ipad, bs) ?: -+ crypto_shash_export(shash, ipad) ?: -+ crypto_shash_init(shash) ?: -+ crypto_shash_update(shash, opad, bs) ?: -+ crypto_shash_export(shash, opad); -+ -+ if (err) -+ return err; -+ -+ /* add auth key */ -+ memcpy(&sa->saIDigest, ipad, SHA256_DIGEST_SIZE); -+ memcpy(&sa->saODigest, opad, SHA256_DIGEST_SIZE); -+ -+ kfree(ipad); -+ return 0; -+} -+#endif ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-common.h -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+ -+#ifndef _EIP93_COMMON_H_ -+#define _EIP93_COMMON_H_ -+ -+#include "eip93-main.h" -+ -+inline int mtk_put_descriptor(struct mtk_device *mtk, -+ struct eip93_descriptor_s *desc); -+ -+inline void *mtk_get_descriptor(struct mtk_device *mtk); -+ -+inline int mtk_get_free_saState(struct mtk_device *mtk); -+ -+void mtk_set_saRecord(struct saRecord_s *saRecord, const unsigned int keylen, -+ const u32 flags); -+ -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_HMAC) -+int mtk_authenc_setkey(struct crypto_shash *cshash, struct saRecord_s *sa, -+ const u8 *authkey, unsigned int authkeylen); -+#endif -+ -+#endif /* _EIP93_COMMON_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-des.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef _EIP93_DES_H_ -+#define _EIP93_DES_H_ -+ -+extern struct mtk_alg_template mtk_alg_ecb_des; -+extern struct mtk_alg_template mtk_alg_cbc_des; -+extern struct mtk_alg_template mtk_alg_ecb_des3_ede; -+extern struct mtk_alg_template mtk_alg_cbc_des3_ede; -+ -+#endif /* _EIP93_DES_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-main.c -@@ -0,0 +1,467 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "eip93-main.h" -+#include "eip93-regs.h" -+#include "eip93-common.h" -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_SKCIPHER) -+#include "eip93-cipher.h" -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+#include "eip93-aes.h" -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+#include "eip93-des.h" -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AEAD) -+#include "eip93-aead.h" -+#endif -+ -+static struct mtk_alg_template *mtk_algs[] = { -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+ &mtk_alg_ecb_des, -+ &mtk_alg_cbc_des, -+ &mtk_alg_ecb_des3_ede, -+ &mtk_alg_cbc_des3_ede, -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+ &mtk_alg_ecb_aes, -+ &mtk_alg_cbc_aes, -+ &mtk_alg_ctr_aes, -+ &mtk_alg_rfc3686_aes, -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AEAD) -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+ &mtk_alg_authenc_hmac_md5_cbc_des, -+ &mtk_alg_authenc_hmac_sha1_cbc_des, -+ &mtk_alg_authenc_hmac_sha224_cbc_des, -+ &mtk_alg_authenc_hmac_sha256_cbc_des, -+ &mtk_alg_authenc_hmac_md5_cbc_des3_ede, -+ &mtk_alg_authenc_hmac_sha1_cbc_des3_ede, -+ &mtk_alg_authenc_hmac_sha224_cbc_des3_ede, -+ &mtk_alg_authenc_hmac_sha256_cbc_des3_ede, -+#endif -+ &mtk_alg_authenc_hmac_md5_cbc_aes, -+ &mtk_alg_authenc_hmac_sha1_cbc_aes, -+ &mtk_alg_authenc_hmac_sha224_cbc_aes, -+ &mtk_alg_authenc_hmac_sha256_cbc_aes, -+ &mtk_alg_authenc_hmac_md5_rfc3686_aes, -+ &mtk_alg_authenc_hmac_sha1_rfc3686_aes, -+ &mtk_alg_authenc_hmac_sha224_rfc3686_aes, -+ &mtk_alg_authenc_hmac_sha256_rfc3686_aes, -+#endif -+}; -+ -+inline void mtk_irq_disable(struct mtk_device *mtk, u32 mask) -+{ -+ __raw_writel(mask, mtk->base + EIP93_REG_MASK_DISABLE); -+} -+ -+inline void mtk_irq_enable(struct mtk_device *mtk, u32 mask) -+{ -+ __raw_writel(mask, mtk->base + EIP93_REG_MASK_ENABLE); -+} -+ -+inline void mtk_irq_clear(struct mtk_device *mtk, u32 mask) -+{ -+ __raw_writel(mask, mtk->base + EIP93_REG_INT_CLR); -+} -+ -+static void mtk_unregister_algs(unsigned int i) -+{ -+ unsigned int j; -+ -+ for (j = 0; j < i; j++) { -+ switch (mtk_algs[j]->type) { -+ case MTK_ALG_TYPE_SKCIPHER: -+ crypto_unregister_skcipher(&mtk_algs[j]->alg.skcipher); -+ break; -+ case MTK_ALG_TYPE_AEAD: -+ crypto_unregister_aead(&mtk_algs[j]->alg.aead); -+ break; -+ } -+ } -+} -+ -+static int mtk_register_algs(struct mtk_device *mtk) -+{ -+ unsigned int i; -+ int err = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(mtk_algs); i++) { -+ mtk_algs[i]->mtk = mtk; -+ -+ switch (mtk_algs[i]->type) { -+ case MTK_ALG_TYPE_SKCIPHER: -+ err = crypto_register_skcipher(&mtk_algs[i]->alg.skcipher); -+ break; -+ case MTK_ALG_TYPE_AEAD: -+ err = crypto_register_aead(&mtk_algs[i]->alg.aead); -+ break; -+ } -+ if (err) -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ mtk_unregister_algs(i); -+ -+ return err; -+} -+ -+static void mtk_handle_result_descriptor(struct mtk_device *mtk) -+{ -+ struct crypto_async_request *async; -+ struct eip93_descriptor_s *rdesc; -+ bool last_entry; -+ u32 flags; -+ int handled, ready, err; -+ union peCrtlStat_w done1; -+ union peLength_w done2; -+ -+get_more: -+ handled = 0; -+ -+ ready = readl(mtk->base + EIP93_REG_PE_RD_COUNT) & GENMASK(10, 0); -+ -+ if (!ready) { -+ mtk_irq_clear(mtk, EIP93_INT_PE_RDRTHRESH_REQ); -+ mtk_irq_enable(mtk, EIP93_INT_PE_RDRTHRESH_REQ); -+ return; -+ } -+ -+ last_entry = false; -+ -+ while (ready) { -+ rdesc = mtk_get_descriptor(mtk); -+ if (IS_ERR(rdesc)) { -+ dev_err(mtk->dev, "Ndesc: %d nreq: %d\n", -+ handled, ready); -+ err = -EIO; -+ break; -+ } -+ /* make sure DMA is finished writing */ -+ do { -+ done1.word = READ_ONCE(rdesc->peCrtlStat.word); -+ done2.word = READ_ONCE(rdesc->peLength.word); -+ } while ((!done1.bits.peReady) || (!done2.bits.peReady)); -+ -+ err = rdesc->peCrtlStat.bits.errStatus; -+ -+ flags = rdesc->userId; -+ async = (struct crypto_async_request *)rdesc->arc4Addr; -+ -+ writel(1, mtk->base + EIP93_REG_PE_RD_COUNT); -+ mtk_irq_clear(mtk, EIP93_INT_PE_RDRTHRESH_REQ); -+ -+ handled++; -+ ready--; -+ -+ if (flags & MTK_DESC_LAST) { -+ last_entry = true; -+ break; -+ } -+ } -+ -+ if (!last_entry) -+ goto get_more; -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_SKCIPHER) -+ if (flags & MTK_DESC_SKCIPHER) -+ mtk_skcipher_handle_result(async, err); -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AEAD) -+ if (flags & MTK_DESC_AEAD) -+ mtk_aead_handle_result(async, err); -+#endif -+ goto get_more; -+} -+ -+static void mtk_done_task(unsigned long data) -+{ -+ struct mtk_device *mtk = (struct mtk_device *)data; -+ -+ mtk_handle_result_descriptor(mtk); -+} -+ -+static irqreturn_t mtk_irq_handler(int irq, void *dev_id) -+{ -+ struct mtk_device *mtk = (struct mtk_device *)dev_id; -+ u32 irq_status; -+ -+ irq_status = readl(mtk->base + EIP93_REG_INT_MASK_STAT); -+ -+ if (irq_status & EIP93_INT_PE_RDRTHRESH_REQ) { -+ mtk_irq_disable(mtk, EIP93_INT_PE_RDRTHRESH_REQ); -+ tasklet_schedule(&mtk->ring->done_task); -+ return IRQ_HANDLED; -+ } -+ -+ mtk_irq_clear(mtk, irq_status); -+ if (irq_status) -+ mtk_irq_disable(mtk, irq_status); -+ -+ return IRQ_NONE; -+} -+ -+static void mtk_initialize(struct mtk_device *mtk) -+{ -+ union peConfig_w peConfig; -+ union peEndianCfg_w peEndianCfg; -+ union peIntCfg_w peIntCfg; -+ union peClockCfg_w peClockCfg; -+ union peBufThresh_w peBufThresh; -+ union peRingThresh_w peRingThresh; -+ -+ /* Reset Engine and setup Mode */ -+ peConfig.word = 0; -+ peConfig.bits.resetPE = 1; -+ peConfig.bits.resetRing = 1; -+ peConfig.bits.peMode = 3; -+ peConfig.bits.enCDRupdate = 1; -+ -+ writel(peConfig.word, mtk->base + EIP93_REG_PE_CONFIG); -+ -+ udelay(10); -+ -+ peConfig.bits.resetPE = 0; -+ peConfig.bits.resetRing = 0; -+ -+ writel(peConfig.word, mtk->base + EIP93_REG_PE_CONFIG); -+ -+ /* Initialize the BYTE_ORDER_CFG register */ -+ peEndianCfg.word = 0; -+ writel(peEndianCfg.word, mtk->base + EIP93_REG_PE_ENDIAN_CONFIG); -+ -+ /* Initialize the INT_CFG register */ -+ peIntCfg.word = 0; -+ writel(peIntCfg.word, mtk->base + EIP93_REG_INT_CFG); -+ -+ /* Config Clocks */ -+ peClockCfg.word = 0; -+ peClockCfg.bits.enPEclk = 1; -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES) -+ peClockCfg.bits.enDESclk = 1; -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES) -+ peClockCfg.bits.enAESclk = 1; -+#endif -+#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_HMAC) -+ peClockCfg.bits.enHASHclk = 1; -+#endif -+ writel(peClockCfg.word, mtk->base + EIP93_REG_PE_CLOCK_CTRL); -+ -+ /* Config DMA thresholds */ -+ peBufThresh.word = 0; -+ peBufThresh.bits.inputBuffer = 128; -+ peBufThresh.bits.outputBuffer = 128; -+ -+ writel(peBufThresh.word, mtk->base + EIP93_REG_PE_BUF_THRESH); -+ -+ /* Clear/ack all interrupts before disable all */ -+ mtk_irq_clear(mtk, 0xFFFFFFFF); -+ mtk_irq_disable(mtk, 0xFFFFFFFF); -+ -+ /* Config Ring Threshold */ -+ peRingThresh.word = 0; -+ peRingThresh.bits.CDRThresh = MTK_RING_SIZE - MTK_RING_BUSY; -+ peRingThresh.bits.RDRThresh = 0; -+ peRingThresh.bits.RDTimeout = 5; -+ peRingThresh.bits.enTimeout = 1; -+ -+ writel(peRingThresh.word, mtk->base + EIP93_REG_PE_RING_THRESH); -+} -+ -+static void mtk_desc_free(struct mtk_device *mtk) -+{ -+ writel(0, mtk->base + EIP93_REG_PE_RING_CONFIG); -+ writel(0, mtk->base + EIP93_REG_PE_CDR_BASE); -+ writel(0, mtk->base + EIP93_REG_PE_RDR_BASE); -+} -+ -+static int mtk_set_ring(struct mtk_device *mtk, struct mtk_desc_ring *ring, -+ int Offset) -+{ -+ ring->offset = Offset; -+ ring->base = dmam_alloc_coherent(mtk->dev, Offset * MTK_RING_SIZE, -+ &ring->base_dma, GFP_KERNEL); -+ if (!ring->base) -+ return -ENOMEM; -+ -+ ring->write = ring->base; -+ ring->base_end = ring->base + Offset * (MTK_RING_SIZE - 1); -+ ring->read = ring->base; -+ -+ return 0; -+} -+ -+static int mtk_desc_init(struct mtk_device *mtk) -+{ -+ struct mtk_state_pool *saState_pool; -+ struct mtk_desc_ring *cdr = &mtk->ring->cdr; -+ struct mtk_desc_ring *rdr = &mtk->ring->rdr; -+ union peRingCfg_w peRingCfg; -+ int RingOffset, err, i; -+ -+ RingOffset = sizeof(struct eip93_descriptor_s); -+ -+ err = mtk_set_ring(mtk, cdr, RingOffset); -+ if (err) -+ return err; -+ -+ err = mtk_set_ring(mtk, rdr, RingOffset); -+ if (err) -+ return err; -+ -+ writel((u32)cdr->base_dma, mtk->base + EIP93_REG_PE_CDR_BASE); -+ writel((u32)rdr->base_dma, mtk->base + EIP93_REG_PE_RDR_BASE); -+ -+ peRingCfg.word = 0; -+ peRingCfg.bits.ringSize = MTK_RING_SIZE - 1; -+ peRingCfg.bits.ringOffset = RingOffset / 4; -+ -+ writel(peRingCfg.word, mtk->base + EIP93_REG_PE_RING_CONFIG); -+ -+ atomic_set(&mtk->ring->free, MTK_RING_SIZE - 1); -+ /* Create State record DMA pool */ -+ RingOffset = sizeof(struct saState_s); -+ mtk->ring->saState = dmam_alloc_coherent(mtk->dev, -+ RingOffset * MTK_RING_SIZE, -+ &mtk->ring->saState_dma, GFP_KERNEL); -+ if (!mtk->ring->saState) -+ return -ENOMEM; -+ -+ mtk->ring->saState_pool = devm_kcalloc(mtk->dev, 1, -+ sizeof(struct mtk_state_pool) * MTK_RING_SIZE, -+ GFP_KERNEL); -+ -+ for (i = 0; i < MTK_RING_SIZE; i++) { -+ saState_pool = &mtk->ring->saState_pool[i]; -+ saState_pool->base = mtk->ring->saState + (i * RingOffset); -+ saState_pool->base_dma = mtk->ring->saState_dma + (i * RingOffset); -+ saState_pool->in_use = false; -+ } -+ -+ return 0; -+} -+ -+static void mtk_cleanup(struct mtk_device *mtk) -+{ -+ tasklet_kill(&mtk->ring->done_task); -+ -+ /* Clear/ack all interrupts before disable all */ -+ mtk_irq_clear(mtk, 0xFFFFFFFF); -+ mtk_irq_disable(mtk, 0xFFFFFFFF); -+ -+ writel(0, mtk->base + EIP93_REG_PE_CLOCK_CTRL); -+ -+ mtk_desc_free(mtk); -+} -+ -+static int mtk_crypto_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct mtk_device *mtk; -+ struct resource *res; -+ int err; -+ -+ mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL); -+ if (!mtk) -+ return -ENOMEM; -+ -+ mtk->dev = dev; -+ platform_set_drvdata(pdev, mtk); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mtk->base = devm_ioremap_resource(&pdev->dev, res); -+ -+ if (IS_ERR(mtk->base)) -+ return PTR_ERR(mtk->base); -+ -+ mtk->irq = platform_get_irq(pdev, 0); -+ -+ if (mtk->irq < 0) -+ return mtk->irq; -+ -+ err = devm_request_threaded_irq(mtk->dev, mtk->irq, mtk_irq_handler, -+ NULL, IRQF_ONESHOT, -+ dev_name(mtk->dev), mtk); -+ -+ mtk->ring = devm_kcalloc(mtk->dev, 1, sizeof(*mtk->ring), GFP_KERNEL); -+ -+ if (!mtk->ring) -+ return -ENOMEM; -+ -+ err = mtk_desc_init(mtk); -+ if (err) -+ return err; -+ -+ tasklet_init(&mtk->ring->done_task, mtk_done_task, (unsigned long)mtk); -+ -+ spin_lock_init(&mtk->ring->read_lock); -+ spin_lock_init(&mtk->ring->write_lock); -+ -+ mtk_initialize(mtk); -+ -+ /* Init. finished, enable RDR interupt */ -+ mtk_irq_enable(mtk, EIP93_INT_PE_RDRTHRESH_REQ); -+ -+ err = mtk_register_algs(mtk); -+ if (err) { -+ mtk_cleanup(mtk); -+ return err; -+ } -+ -+ dev_info(mtk->dev, "EIP93 Crypto Engine Initialized."); -+ -+ return 0; -+} -+ -+static int mtk_crypto_remove(struct platform_device *pdev) -+{ -+ struct mtk_device *mtk = platform_get_drvdata(pdev); -+ -+ mtk_unregister_algs(ARRAY_SIZE(mtk_algs)); -+ mtk_cleanup(mtk); -+ dev_info(mtk->dev, "EIP93 removed.\n"); -+ -+ return 0; -+} -+ -+#if defined(CONFIG_OF) -+static const struct of_device_id mtk_crypto_of_match[] = { -+ { .compatible = "mediatek,mtk-eip93", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, mtk_crypto_of_match); -+#endif -+ -+static struct platform_driver mtk_crypto_driver = { -+ .probe = mtk_crypto_probe, -+ .remove = mtk_crypto_remove, -+ .driver = { -+ .name = "mtk-eip93", -+ .of_match_table = of_match_ptr(mtk_crypto_of_match), -+ }, -+}; -+module_platform_driver(mtk_crypto_driver); -+ -+MODULE_AUTHOR("Richard van Schagen "); -+MODULE_ALIAS("platform:" KBUILD_MODNAME); -+MODULE_DESCRIPTION("Mediatek EIP-93 crypto engine driver"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-main.h -@@ -0,0 +1,146 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef _EIP93_MAIN_H_ -+#define _EIP93_MAIN_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MTK_RING_SIZE 512 -+#define MTK_RING_BUSY 32 -+#define MTK_CRA_PRIORITY 1500 -+ -+/* cipher algorithms */ -+#define MTK_ALG_DES BIT(0) -+#define MTK_ALG_3DES BIT(1) -+#define MTK_ALG_AES BIT(2) -+#define MTK_ALG_MASK GENMASK(2, 0) -+/* hash and hmac algorithms */ -+#define MTK_HASH_MD5 BIT(3) -+#define MTK_HASH_SHA1 BIT(4) -+#define MTK_HASH_SHA224 BIT(5) -+#define MTK_HASH_SHA256 BIT(6) -+#define MTK_HASH_HMAC BIT(7) -+#define MTK_HASH_MASK GENMASK(6, 3) -+/* cipher modes */ -+#define MTK_MODE_CBC BIT(8) -+#define MTK_MODE_ECB BIT(9) -+#define MTK_MODE_CTR BIT(10) -+#define MTK_MODE_RFC3686 BIT(11) -+#define MTK_MODE_MASK GENMASK(10, 8) -+ -+/* cipher encryption/decryption operations */ -+#define MTK_ENCRYPT BIT(12) -+#define MTK_DECRYPT BIT(13) -+ -+#define MTK_BUSY BIT(14) -+ -+/* descriptor flags */ -+#define MTK_DESC_ASYNC BIT(31) -+#define MTK_DESC_SKCIPHER BIT(30) -+#define MTK_DESC_AEAD BIT(29) -+#define MTK_DESC_AHASH BIT(28) -+#define MTK_DESC_PRNG BIT(27) -+#define MTK_DESC_FAKE_HMAC BIT(26) -+#define MTK_DESC_LAST BIT(25) -+#define MTK_DESC_FINISH BIT(24) -+#define MTK_DESC_IPSEC BIT(23) -+#define MTK_DESC_DMA_IV BIT(22) -+ -+#define IS_DES(flags) (flags & MTK_ALG_DES) -+#define IS_3DES(flags) (flags & MTK_ALG_3DES) -+#define IS_AES(flags) (flags & MTK_ALG_AES) -+ -+#define IS_HASH_MD5(flags) (flags & MTK_HASH_MD5) -+#define IS_HASH_SHA1(flags) (flags & MTK_HASH_SHA1) -+#define IS_HASH_SHA224(flags) (flags & MTK_HASH_SHA224) -+#define IS_HASH_SHA256(flags) (flags & MTK_HASH_SHA256) -+#define IS_HMAC(flags) (flags & MTK_HASH_HMAC) -+ -+#define IS_CBC(mode) (mode & MTK_MODE_CBC) -+#define IS_ECB(mode) (mode & MTK_MODE_ECB) -+#define IS_CTR(mode) (mode & MTK_MODE_CTR) -+#define IS_RFC3686(mode) (mode & MTK_MODE_RFC3686) -+ -+#define IS_BUSY(flags) (flags & MTK_BUSY) -+#define IS_DMA_IV(flags) (flags & MTK_DESC_DMA_IV) -+ -+#define IS_ENCRYPT(dir) (dir & MTK_ENCRYPT) -+#define IS_DECRYPT(dir) (dir & MTK_DECRYPT) -+ -+#define IS_CIPHER(flags) (flags & (MTK_ALG_DES || \ -+ MTK_ALG_3DES || \ -+ MTK_ALG_AES)) -+ -+#define IS_HASH(flags) (flags & (MTK_HASH_MD5 || \ -+ MTK_HASH_SHA1 || \ -+ MTK_HASH_SHA224 || \ -+ MTK_HASH_SHA256)) -+ -+/** -+ * struct mtk_device - crypto engine device structure -+ */ -+struct mtk_device { -+ void __iomem *base; -+ struct device *dev; -+ struct clk *clk; -+ int irq; -+ struct mtk_ring *ring; -+ struct mtk_state_pool *saState_pool; -+}; -+ -+struct mtk_desc_ring { -+ void *base; -+ void *base_end; -+ dma_addr_t base_dma; -+ /* write and read pointers */ -+ void *read; -+ void *write; -+ /* descriptor element offset */ -+ u32 offset; -+}; -+ -+struct mtk_state_pool { -+ void *base; -+ dma_addr_t base_dma; -+ bool in_use; -+}; -+ -+struct mtk_ring { -+ struct tasklet_struct done_task; -+ /* command/result rings */ -+ struct mtk_desc_ring cdr; -+ struct mtk_desc_ring rdr; -+ spinlock_t write_lock; -+ spinlock_t read_lock; -+ atomic_t free; -+ /* saState */ -+ struct mtk_state_pool *saState_pool; -+ void *saState; -+ dma_addr_t saState_dma; -+}; -+ -+enum mtk_alg_type { -+ MTK_ALG_TYPE_AEAD, -+ MTK_ALG_TYPE_SKCIPHER, -+}; -+ -+struct mtk_alg_template { -+ struct mtk_device *mtk; -+ enum mtk_alg_type type; -+ u32 flags; -+ union { -+ struct aead_alg aead; -+ struct skcipher_alg skcipher; -+ } alg; -+}; -+ -+#endif /* _EIP93_MAIN_H_ */ ---- /dev/null -+++ b/drivers/crypto/mtk-eip93/eip93-regs.h -@@ -0,0 +1,382 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) 2019 - 2021 -+ * -+ * Richard van Schagen -+ */ -+#ifndef REG_EIP93_H -+#define REG_EIP93_H -+ -+#define EIP93_REG_WIDTH 4 -+/*----------------------------------------------------------------------------- -+ * Register Map -+ */ -+#define DESP_BASE 0x0000000 -+#define EIP93_REG_PE_CTRL_STAT ((DESP_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_SOURCE_ADDR ((DESP_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_DEST_ADDR ((DESP_BASE)+(0x02 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_SA_ADDR ((DESP_BASE)+(0x03 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_ADDR ((DESP_BASE)+(0x04 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_USER_ID ((DESP_BASE)+(0x06 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_LENGTH ((DESP_BASE)+(0x07 * EIP93_REG_WIDTH)) -+ -+//PACKET ENGINE RING configuration registers -+#define PE_RNG_BASE 0x0000080 -+ -+#define EIP93_REG_PE_CDR_BASE ((PE_RNG_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_RDR_BASE ((PE_RNG_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_RING_CONFIG ((PE_RNG_BASE)+(0x02 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_RING_THRESH ((PE_RNG_BASE)+(0x03 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_CD_COUNT ((PE_RNG_BASE)+(0x04 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_RD_COUNT ((PE_RNG_BASE)+(0x05 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_RING_RW_PNTR ((PE_RNG_BASE)+(0x06 * EIP93_REG_WIDTH)) -+ -+//PACKET ENGINE configuration registers -+#define PE_CFG_BASE 0x0000100 -+#define EIP93_REG_PE_CONFIG ((PE_CFG_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_STATUS ((PE_CFG_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_BUF_THRESH ((PE_CFG_BASE)+(0x03 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_INBUF_COUNT ((PE_CFG_BASE)+(0x04 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_OUTBUF_COUNT ((PE_CFG_BASE)+(0x05 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_BUF_RW_PNTR ((PE_CFG_BASE)+(0x06 * EIP93_REG_WIDTH)) -+ -+//PACKET ENGINE endian config -+#define EN_CFG_BASE 0x00001CC -+#define EIP93_REG_PE_ENDIAN_CONFIG ((EN_CFG_BASE)+(0x00 * EIP93_REG_WIDTH)) -+ -+//EIP93 CLOCK control registers -+#define CLOCK_BASE 0x01E8 -+#define EIP93_REG_PE_CLOCK_CTRL ((CLOCK_BASE)+(0x00 * EIP93_REG_WIDTH)) -+ -+//EIP93 Device Option and Revision Register -+#define REV_BASE 0x01F4 -+#define EIP93_REG_PE_OPTION_1 ((REV_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_OPTION_0 ((REV_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PE_REVISION ((REV_BASE)+(0x02 * EIP93_REG_WIDTH)) -+ -+//EIP93 Interrupt Control Register -+#define INT_BASE 0x0200 -+#define EIP93_REG_INT_UNMASK_STAT ((INT_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_INT_MASK_STAT ((INT_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_INT_CLR ((INT_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_INT_MASK ((INT_BASE)+(0x02 * EIP93_REG_WIDTH)) -+#define EIP93_REG_INT_CFG ((INT_BASE)+(0x03 * EIP93_REG_WIDTH)) -+#define EIP93_REG_MASK_ENABLE ((INT_BASE)+(0X04 * EIP93_REG_WIDTH)) -+#define EIP93_REG_MASK_DISABLE ((INT_BASE)+(0X05 * EIP93_REG_WIDTH)) -+ -+//EIP93 SA Record register -+#define SA_BASE 0x0400 -+#define EIP93_REG_SA_CMD_0 ((SA_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_SA_CMD_1 ((SA_BASE)+(0x01 * EIP93_REG_WIDTH)) -+ -+//#define EIP93_REG_SA_READY ((SA_BASE)+(31 * EIP93_REG_WIDTH)) -+ -+//State save register -+#define STATE_BASE 0x0500 -+#define EIP93_REG_STATE_IV_0 ((STATE_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_STATE_IV_1 ((STATE_BASE)+(0x01 * EIP93_REG_WIDTH)) -+ -+#define EIP93_PE_ARC4STATE_BASEADDR_REG 0x0700 -+ -+//RAM buffer start address -+#define EIP93_INPUT_BUFFER 0x0800 -+#define EIP93_OUTPUT_BUFFER 0x0800 -+ -+//EIP93 PRNG Configuration Register -+#define PRNG_BASE 0x0300 -+#define EIP93_REG_PRNG_STAT ((PRNG_BASE)+(0x00 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_CTRL ((PRNG_BASE)+(0x01 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_SEED_0 ((PRNG_BASE)+(0x02 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_SEED_1 ((PRNG_BASE)+(0x03 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_SEED_2 ((PRNG_BASE)+(0x04 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_SEED_3 ((PRNG_BASE)+(0x05 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_KEY_0 ((PRNG_BASE)+(0x06 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_KEY_1 ((PRNG_BASE)+(0x07 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_KEY_2 ((PRNG_BASE)+(0x08 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_KEY_3 ((PRNG_BASE)+(0x09 * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_RES_0 ((PRNG_BASE)+(0x0A * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_RES_1 ((PRNG_BASE)+(0x0B * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_RES_2 ((PRNG_BASE)+(0x0C * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_RES_3 ((PRNG_BASE)+(0x0D * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_LFSR_0 ((PRNG_BASE)+(0x0E * EIP93_REG_WIDTH)) -+#define EIP93_REG_PRNG_LFSR_1 ((PRNG_BASE)+(0x0F * EIP93_REG_WIDTH)) -+ -+/*----------------------------------------------------------------------------- -+ * Constants & masks -+ */ -+ -+#define EIP93_SUPPORTED_INTERRUPTS_MASK 0xffff7f00 -+#define EIP93_PRNG_DT_TEXT_LOWERHALF 0xDEAD -+#define EIP93_PRNG_DT_TEXT_UPPERHALF 0xC0DE -+#define EIP93_10BITS_MASK 0X3FF -+#define EIP93_12BITS_MASK 0XFFF -+#define EIP93_4BITS_MASK 0X04 -+#define EIP93_20BITS_MASK 0xFFFFF -+ -+#define EIP93_MIN_DESC_DONE_COUNT 0 -+#define EIP93_MAX_DESC_DONE_COUNT 15 -+ -+#define EIP93_MIN_DESC_PENDING_COUNT 0 -+#define EIP93_MAX_DESC_PENDING_COUNT 1023 -+ -+#define EIP93_MIN_TIMEOUT_COUNT 0 -+#define EIP93_MAX_TIMEOUT_COUNT 15 -+ -+#define EIP93_MIN_PE_INPUT_THRESHOLD 1 -+#define EIP93_MAX_PE_INPUT_THRESHOLD 511 -+ -+#define EIP93_MIN_PE_OUTPUT_THRESHOLD 1 -+#define EIP93_MAX_PE_OUTPUT_THRESHOLD 432 -+ -+#define EIP93_MIN_PE_RING_SIZE 1 -+#define EIP93_MAX_PE_RING_SIZE 1023 -+ -+#define EIP93_MIN_PE_DESCRIPTOR_SIZE 7 -+#define EIP93_MAX_PE_DESCRIPTOR_SIZE 15 -+ -+//3DES keys,seed,known data and its result -+#define EIP93_KEY_0 0x133b3454 -+#define EIP93_KEY_1 0x5e5b890b -+#define EIP93_KEY_2 0x5eb30757 -+#define EIP93_KEY_3 0x93ab15f7 -+#define EIP93_SEED_0 0x62c4bf5e -+#define EIP93_SEED_1 0x972667c8 -+#define EIP93_SEED_2 0x6345bf67 -+#define EIP93_SEED_3 0xcb3482bf -+#define EIP93_LFSR_0 0xDEADC0DE -+#define EIP93_LFSR_1 0xBEEFF00D -+ -+/*----------------------------------------------------------------------------- -+ * EIP93 device initialization specifics -+ */ -+ -+/*---------------------------------------------------------------------------- -+ * Byte Order Reversal Mechanisms Supported in EIP93 -+ * EIP93_BO_REVERSE_HALF_WORD : reverse the byte order within a half-word -+ * EIP93_BO_REVERSE_WORD : reverse the byte order within a word -+ * EIP93_BO_REVERSE_DUAL_WORD : reverse the byte order within a dual-word -+ * EIP93_BO_REVERSE_QUAD_WORD : reverse the byte order within a quad-word -+ */ -+enum EIP93_Byte_Order_Value_t { -+ EIP93_BO_REVERSE_HALF_WORD = 1, -+ EIP93_BO_REVERSE_WORD = 2, -+ EIP93_BO_REVERSE_DUAL_WORD = 4, -+ EIP93_BO_REVERSE_QUAD_WORD = 8, -+}; -+ -+/*---------------------------------------------------------------------------- -+ * Byte Order Reversal Mechanisms Supported in EIP93 for Target Data -+ * EIP93_BO_REVERSE_HALF_WORD : reverse the byte order within a half-word -+ * EIP93_BO_REVERSE_WORD : reverse the byte order within a word -+ */ -+enum EIP93_Byte_Order_Value_TD_t { -+ EIP93_BO_REVERSE_HALF_WORD_TD = 1, -+ EIP93_BO_REVERSE_WORD_TD = 2, -+}; -+ -+// BYTE_ORDER_CFG register values -+#define EIP93_BYTE_ORDER_PD EIP93_BO_REVERSE_WORD -+#define EIP93_BYTE_ORDER_SA EIP93_BO_REVERSE_WORD -+#define EIP93_BYTE_ORDER_DATA EIP93_BO_REVERSE_WORD -+#define EIP93_BYTE_ORDER_TD EIP93_BO_REVERSE_WORD_TD -+ -+// INT_CFG register values -+#define EIP93_INT_HOST_OUTPUT_TYPE 0 -+#define EIP93_INT_PULSE_CLEAR 0 -+ -+/* -+ * Interrupts of EIP93 -+ */ -+ -+enum EIP93_InterruptSource_t { -+ EIP93_INT_PE_CDRTHRESH_REQ = BIT(0), -+ EIP93_INT_PE_RDRTHRESH_REQ = BIT(1), -+ EIP93_INT_PE_OPERATION_DONE = BIT(9), -+ EIP93_INT_PE_INBUFTHRESH_REQ = BIT(10), -+ EIP93_INT_PE_OUTBURTHRSH_REQ = BIT(11), -+ EIP93_INT_PE_PRNG_IRQ = BIT(12), -+ EIP93_INT_PE_ERR_REG = BIT(13), -+ EIP93_INT_PE_RD_DONE_IRQ = BIT(16), -+}; -+ -+union peConfig_w { -+ u32 word; -+ struct { -+ u32 resetPE :1; -+ u32 resetRing :1; -+ u32 reserved :6; -+ u32 peMode :2; -+ u32 enCDRupdate :1; -+ u32 reserved2 :5; -+ u32 swapCDRD :1; -+ u32 swapSA :1; -+ u32 swapData :1; -+ u32 reserved3 :13; -+ } bits; -+} __packed; -+ -+union peEndianCfg_w { -+ u32 word; -+ struct { -+ u32 masterByteSwap :8; -+ u32 reserved :8; -+ u32 targetByteSwap :8; -+ u32 reserved2 :8; -+ } bits; -+} __packed; -+ -+union peIntCfg_w { -+ u32 word; -+ struct { -+ u32 PulseClear :1; -+ u32 IntType :1; -+ u32 reserved :30; -+ } bits; -+} __packed; -+ -+union peClockCfg_w { -+ u32 word; -+ struct { -+ u32 enPEclk :1; -+ u32 enDESclk :1; -+ u32 enAESclk :1; -+ u32 reserved :1; -+ u32 enHASHclk :1; -+ u32 reserved2 :27; -+ } bits; -+} __packed; -+ -+union peBufThresh_w { -+ u32 word; -+ struct { -+ u32 inputBuffer :8; -+ u32 reserved :8; -+ u32 outputBuffer :8; -+ u32 reserved2 :8; -+ } bits; -+} __packed; -+ -+union peRingThresh_w { -+ u32 word; -+ struct { -+ u32 CDRThresh :10; -+ u32 reserved :6; -+ u32 RDRThresh :10; -+ u32 RDTimeout :4; -+ u32 reserved2 :1; -+ u32 enTimeout :1; -+ } bits; -+} __packed; -+ -+union peRingCfg_w { -+ u32 word; -+ struct { -+ u32 ringSize :10; -+ u32 reserved :6; -+ u32 ringOffset :8; -+ u32 reserved2 :8; -+ } bits; -+} __packed; -+ -+union saCmd0 { -+ u32 word; -+ struct { -+ u32 opCode :3; -+ u32 direction :1; -+ u32 opGroup :2; -+ u32 padType :2; -+ u32 cipher :4; -+ u32 hash :4; -+ u32 reserved2 :1; -+ u32 scPad :1; -+ u32 extPad :1; -+ u32 hdrProc :1; -+ u32 digestLength :4; -+ u32 ivSource :2; -+ u32 hashSource :2; -+ u32 saveIv :1; -+ u32 saveHash :1; -+ u32 reserved1 :2; -+ } bits; -+} __packed; -+ -+union saCmd1 { -+ u32 word; -+ struct { -+ u32 copyDigest :1; -+ u32 copyHeader :1; -+ u32 copyPayload :1; -+ u32 copyPad :1; -+ u32 reserved4 :4; -+ u32 cipherMode :2; -+ u32 reserved3 :1; -+ u32 sslMac :1; -+ u32 hmac :1; -+ u32 byteOffset :1; -+ u32 reserved2 :2; -+ u32 hashCryptOffset :8; -+ u32 aesKeyLen :3; -+ u32 reserved1 :1; -+ u32 aesDecKey :1; -+ u32 seqNumCheck :1; -+ u32 reserved0 :2; -+ } bits; -+} __packed; -+ -+struct saRecord_s { -+ union saCmd0 saCmd0; -+ union saCmd1 saCmd1; -+ u32 saKey[8]; -+ u32 saIDigest[8]; -+ u32 saODigest[8]; -+ u32 saSpi; -+ u32 saSeqNum[2]; -+ u32 saSeqNumMask[2]; -+ u32 saNonce; -+} __packed; -+ -+struct saState_s { -+ u32 stateIv[4]; -+ u32 stateByteCnt[2]; -+ u32 stateIDigest[8]; -+} __packed; -+ -+union peCrtlStat_w { -+ u32 word; -+ struct { -+ u32 hostReady :1; -+ u32 peReady :1; -+ u32 reserved :1; -+ u32 initArc4 :1; -+ u32 hashFinal :1; -+ u32 haltMode :1; -+ u32 prngMode :2; -+ u32 padValue :8; -+ u32 errStatus :8; -+ u32 padCrtlStat :8; -+ } bits; -+} __packed; -+ -+union peLength_w { -+ u32 word; -+ struct { -+ u32 length :20; -+ u32 reserved :2; -+ u32 hostReady :1; -+ u32 peReady :1; -+ u32 byPass :8; -+ } bits; -+} __packed; -+ -+struct eip93_descriptor_s { -+ union peCrtlStat_w peCrtlStat; -+ u32 srcAddr; -+ u32 dstAddr; -+ u32 saAddr; -+ u32 stateAddr; -+ u32 arc4Addr; -+ u32 userId; -+ union peLength_w peLength; -+} __packed; -+ -+#endif ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -918,4 +918,6 @@ config CRYPTO_DEV_SA2UL - - source "drivers/crypto/keembay/Kconfig" - -+source "drivers/crypto/mtk-eip93/Kconfig" -+ - endif # CRYPTO_HW ---- a/drivers/crypto/Makefile -+++ b/drivers/crypto/Makefile -@@ -51,3 +51,4 @@ obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_AES) += x - obj-y += hisilicon/ - obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ - obj-y += keembay/ -+obj-$(CONFIG_CRYPTO_DEV_EIP93) += mtk-eip93/ From 65df33fc76f722701f161dd88828f61c9e31f1d1 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 8 Mar 2024 20:20:23 +0000 Subject: [PATCH 091/108] ramips: add support for YunCore G720 The YunCore G720 is a dual band 802.11ax router with 5 GbE ports. Specs: - SoC: MediaTek MT7621 - Ethernet: 5x GbE ports (built-in MT7530) - Wireless 2.4GHz / 5GHz: MediaTek MT7915E - RAM: 256MiB - ROM: 16MiB (W25Q128) - 1 Button (reset) - 8 LEDs (1x system, 2x wifi, 5x switch ports) Flash instructions: The vendor firmware is based on OpenWrt, the sysupgrade image can be flashed using the '-F' (force) option on the CLI. Make sure not to keep settings when doing so. Signed-off-by: Daniel Golle --- .../linux/ramips/dts/mt7621_yuncore_g720.dts | 188 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 10 + .../mt7621/base-files/etc/board.d/01_leds | 3 +- .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 3 +- 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 target/linux/ramips/dts/mt7621_yuncore_g720.dts diff --git a/target/linux/ramips/dts/mt7621_yuncore_g720.dts b/target/linux/ramips/dts/mt7621_yuncore_g720.dts new file mode 100644 index 0000000000..4b88064b49 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_yuncore_g720.dts @@ -0,0 +1,188 @@ +#include +#include +#include + +#include "mt7621.dtsi" + +/ { + compatible = "yuncore,g720", "mediatek,mt7621-soc"; + model = "YunCore G720"; + + aliases { + label-mac-device = &wifi0; + led-boot = &led_sys_red; + led-failsafe = &led_sys_red; + led-running = &led_sys_red; + led-upgrade = &led_sys_red; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + leds { + compatible = "gpio-leds"; + + led_sys_red: led-sys { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <200>; + always-running; + }; +}; + +&gpio { + s1 { + gpio-hog; + line-name = "s1"; + gpios = <4 GPIO_ACTIVE_LOW>; + output-high; + }; + + s2 { + gpio-hog; + line-name = "s2"; + gpios = <3 GPIO_ACTIVE_LOW>; + output-high; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "w25q128", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "factory"; + reg = <0x50000 0x40000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + macaddr_factory_e000: macaddr@e000 { + reg = <0xe000 0x6>; + }; + + macaddr_factory_e006: macaddr@e006 { + reg = <0xe006 0x6>; + }; + }; + }; + + partition@50000 { + compatible = "denx,uimage"; + label = "firmware"; + reg = <0x90000 0xf70000>; + }; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_e000>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_factory_e006>; + nvmem-cell-names = "mac-address"; +}; + +&mdio { + ethphy4: ethernet-phy@4 { + reg = <4>; + }; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wifi0: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + }; +}; + +&state_default { + gpio { + groups = "jtag", "wdt"; + function = "gpio"; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index a46ea39d59..3b9ee022f6 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -2918,6 +2918,16 @@ define Device/yuncore_fap690 endef TARGET_DEVICES += yuncore_fap690 +define Device/yuncore_g720 + $(Device/dsa-migration) + DEVICE_VENDOR := YunCore + DEVICE_MODEL := G720 + DEVICE_PACKAGES := kmod-mt7915-firmware + IMAGE_SIZE := 15808k + SUPPORTED_DEVICES += mt7621-rfb-ax-nor +endef +TARGET_DEVICES += yuncore_g720 + define Device/zbtlink_zbt-we1326 $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 1061de6f44..81afa45e80 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -30,7 +30,8 @@ asus,rt-ax53u) ucidef_set_led_wlan "wlan2g" "WiFi 2.4GHz" "mt76-phy0" "phy0tpt" ucidef_set_led_wlan "wlan5g" "WiFi 5GHz" "mt76-phy1" "phy1tpt" ;; -asus,rt-ax54) +asus,rt-ax54|\ +yuncore,g720) ucidef_set_led_wlan "wlan2g" "WiFi 2.4GHz" "mt76-phy0" "phy0tpt" ucidef_set_led_wlan "wlan5g" "WiFi 5GHz" "mt76-phy1" "phy1tpt" ;; diff --git a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac index 8a977e68ae..3be4e24e09 100644 --- a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +++ b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -184,7 +184,8 @@ case "$board" in hw_mac_addr="$(mtd_get_mac_binary rom_file 0xf100)" [ "$PHYNBR" = "1" ] && macaddr_add "$hw_mac_addr" 2 > "/sys${DEVPATH}/macaddress" ;; - yuncore,ax820) + yuncore,ax820|\ + yuncore,g720) [ "$PHYNBR" = "1" ] && \ macaddr_setbit_la "$(mtd_get_mac_binary Factory 0xe000)" > /sys${DEVPATH}/macaddress ;; From 532de62e4cd4def2ec261fa7d5fba968cfd8c97f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 12 Mar 2024 00:06:14 -0400 Subject: [PATCH 092/108] kernel: config: 6.6: disable ZSTD debug info compression by default When kernel 6.6 is being compiled with GCC13 it will prompt for: Compressed Debug information > 1. Don't compress debug information (DEBUG_INFO_COMPRESSED_NONE) 2. Compress debugging information with zlib (DEBUG_INFO_COMPRESSED_ZLIB) 3. Compress debugging information with zstd (DEBUG_INFO_COMPRESSED_ZSTD) (NEW) This is because kernel now also has support for compressing debug info with ZSTD, so add the missing symbol and disable it by default. Signed-off-by: Robert Marko --- target/linux/generic/config-6.6 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 4f3d7f2e23..3cb50bc274 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -1412,6 +1412,7 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_INFO_BTF is not set CONFIG_DEBUG_INFO_COMPRESSED_NONE=y # CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set +# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set # CONFIG_DEBUG_INFO_DWARF4 is not set # CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y From 497fafb8aea48e764ce0e456f20ab346691e585f Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Thu, 8 Feb 2024 20:35:31 +0100 Subject: [PATCH 093/108] lldpd: implement lldp_policy parameter For certain lldp_class scenarios (2 & 3) a policy must be set also. Class 4 is default, although it's good to handle the policy eventuality. Here, set a default lldp_policy for all lldp_class scenarios. Any lldp_policy can now be set. Depends on PR #14584 (which introduced an `if` block) Tested on 22.03.5, 22.03.6 Signed-off-by: Paul Donald --- package/network/services/lldpd/Makefile | 2 +- package/network/services/lldpd/files/lldpd.config | 2 ++ package/network/services/lldpd/files/lldpd.init | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/package/network/services/lldpd/Makefile b/package/network/services/lldpd/Makefile index 1f8d1e546b..ffe2a8d015 100644 --- a/package/network/services/lldpd/Makefile +++ b/package/network/services/lldpd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lldpd PKG_VERSION:=1.0.17 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/lldpd/lldpd/releases/download/$(PKG_VERSION)/ diff --git a/package/network/services/lldpd/files/lldpd.config b/package/network/services/lldpd/files/lldpd.config index fa9fe2b4f8..6df3f73bf7 100644 --- a/package/network/services/lldpd/files/lldpd.config +++ b/package/network/services/lldpd/files/lldpd.config @@ -7,6 +7,8 @@ config lldpd config option agentxsocket /var/run/agentx.sock option lldp_class 4 + # lldp_policy only needed for lldp_class 2-3 + # option lldp_policy 'application streaming-video unknown' option lldp_location "address country EU" # if empty, the distribution description is sent diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 498c9e615e..0ba438c379 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -118,6 +118,12 @@ write_lldpd_conf() local lldp_location config_get lldp_location 'config' 'lldp_location' + local lldp_class + config_get lldp_class 'config' 'lldp_class' + + local lldp_policy + config_get lldp_policy 'config' 'lldp_policy' + fi local lldp_agenttype @@ -154,6 +160,12 @@ write_lldpd_conf() [ -n "$lldp_location" ] && echo "configure med location" "$lldp_location" >> "$LLDPD_CONF" + # Manual states that if Class (-M) is 2 or 3, at least one network policy must be defined + case "$lldp_class" in + 2 | 3 ) [ -n "$lldp_policy" ] && echo "configure med policy $lldp_policy" >> "$LLDPD_CONF" + ;; + esac + fi [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF" From 5364fe0f01ca11b47c55d78f756d3176748dd0c2 Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Mon, 11 Mar 2024 23:33:47 +0100 Subject: [PATCH 094/108] lldpd: shellcheck fixes No functionality/behaviour changes; code is synonymous Tested on: 22.03.6 Signed-off-by: Paul Donald --- .../network/services/lldpd/files/lldpd.init | 93 ++++++++++--------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 0ba438c379..67ee011ae2 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -1,5 +1,6 @@ #!/bin/sh /etc/rc.common # Copyright (C) 2008-2015 OpenWrt.org +# shellcheck disable=1091,2034,3037,3043,3045 START=90 STOP=01 @@ -39,38 +40,38 @@ get_config_restart_hash() { config_load 'lldpd' config_get v 'config' 'lldp_class'; append _string "$v" "," - if [ "$CONFIG_LLDPD_WITH_SNMP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then config_get v 'config' 'agentxsocket'; append _string "$v" "," fi config_get v 'config' 'cid_interface'; append _string "$v" "," config_get v 'config' 'filter'; append _string "$v" "," config_get_bool v 'config' 'readonly_mode'; append _string "$v" "," config_get_bool v 'config' 'lldp_no_version'; append _string "$v" "," - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then config_get_bool v 'config' 'lldpmed_no_inventory'; append _string "$v" "," fi config_get_bool v 'config' 'enable_lldp' 1; append _string "$v" "," config_get_bool v 'config' 'force_lldp'; append _string "$v" "," - if [ "$CONFIG_LLDPD_WITH_CDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ]; then config_get_bool v 'config' 'enable_cdp'; append _string "$v" "," config_get v 'config' 'cdp_version'; append _string "$v" "," config_get_bool v 'config' 'force_cdp'; append _string "$v" "," config_get_bool v 'config' 'force_cdpv2'; append _string "$v" "," fi - if [ "$CONFIG_LLDPD_WITH_EDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ]; then config_get_bool v 'config' 'enable_edp'; append _string "$v" "," config_get_bool v 'config' 'force_edp'; append _string "$v" "," fi - if [ "$CONFIG_LLDPD_WITH_FDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ]; then config_get_bool v 'config' 'enable_fdp'; append _string "$v" "," config_get_bool v 'config' 'force_fdp'; append _string "$v" "," fi - if [ "$CONFIG_LLDPD_WITH_SONMP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ]; then config_get_bool v 'config' 'enable_sonmp'; append _string "$v" "," config_get_bool v 'config' 'force_sonmp'; append _string "$v" "," fi - _hash=`echo -n "${_string}" | md5sum | awk '{ print \$1 }'` + _hash=$(echo -n "${_string}" | md5sum | awk '{ print $1 }') export -n "$var=$_hash" } @@ -108,7 +109,7 @@ write_lldpd_conf() local lldp_syscapabilities config_get lldp_syscapabilities 'config' 'lldp_syscapabilities' - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then local lldpmed_fast_start config_get_bool lldpmed_fast_start 'config' 'lldpmed_fast_start' 0 @@ -148,14 +149,14 @@ write_lldpd_conf() [ -n "$lldp_hostname" ] && echo "configure system hostname" "\"$lldp_hostname\"" >> "$LLDPD_CONF" [ -n "$lldp_mgmt_ip" ] && echo "configure system ip management pattern" "\"$lldp_mgmt_ip\"" >> "$LLDPD_CONF" [ -n "$lldp_syscapabilities" ] && echo "configure system capabilities enabled $lldp_syscapabilities" >> "$LLDPD_CONF" - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ] && [ $lldpmed_fast_start -gt 0 ]; then - if [ $lldpmed_fast_start_tx_interval -gt 0 ]; then + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ] && [ "$lldpmed_fast_start" -gt 0 ]; then + if [ "$lldpmed_fast_start_tx_interval" -gt 0 ]; then echo "configure med fast-start tx-interval $lldpmed_fast_start_tx_interval" >> "$LLDPD_CONF" else echo "configure med fast-start enable" >> "$LLDPD_CONF" fi fi - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then # other 'configure med xxx' statements go here [ -n "$lldp_location" ] && echo "configure med location" "$lldp_location" >> "$LLDPD_CONF" @@ -171,11 +172,11 @@ write_lldpd_conf() [ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF" [ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype" "\"$lldp_portidsubtype\"" >> "$LLDPD_CONF" [ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF" - [ -n $lldp_tx_interval ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" - [ $lldp_tx_hold -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF" + [ -n "$lldp_tx_interval" ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF" + [ "$lldp_tx_hold" -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF" # Since lldpd's sysconfdir is /tmp, we'll symlink /etc/lldpd.d to /tmp/$LLDPD_CONFS_DIR - [ -e $LLDPD_CONFS_DIR ] || ln -s /etc/lldpd.d $LLDPD_CONFS_DIR + [ -e "$LLDPD_CONFS_DIR" ] || ln -s /etc/lldpd.d "$LLDPD_CONFS_DIR" } start_service() { @@ -202,31 +203,31 @@ start_service() { config_load 'lldpd' config_get_bool enable_lldp 'config' 'enable_lldp' 1 config_get_bool force_lldp 'config' 'force_lldp' 0 - if [ "$CONFIG_LLDPD_WITH_CDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ]; then config_get_bool enable_cdp 'config' 'enable_cdp' 0 config_get cdp_version 'config' 'cdp_version' 'cdpv1v2' config_get_bool force_cdp 'config' 'force_cdp' 0 config_get_bool force_cdpv2 'config' 'force_cdpv2' 0 fi - if [ "$CONFIG_LLDPD_WITH_FDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ]; then config_get_bool enable_fdp 'config' 'enable_fdp' 0 config_get_bool force_fdp 'config' 'force_fdp' 0 fi - if [ "$CONFIG_LLDPD_WITH_SONMP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ]; then config_get_bool enable_sonmp 'config' 'enable_sonmp' 0 config_get_bool force_sonmp 'config' 'force_sonmp' 0 fi - if [ "$CONFIG_LLDPD_WITH_EDP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ]; then config_get_bool enable_edp 'config' 'enable_edp' 0 config_get_bool force_edp 'config' 'force_edp' 0 fi config_get lldp_class 'config' 'lldp_class' config_get_bool lldp_no_version 'config' 'lldp_no_version' 0 - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then config_get_bool lldpmed_no_inventory 'config' 'lldpmed_no_inventory' 0 fi config_get_bool readonly_mode 'config' 'readonly_mode' 0 - if [ "$CONFIG_LLDPD_WITH_SNMP" == "y" ]; then + if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then config_get agentxsocket 'config' 'agentxsocket' fi config_get filter 'config' 'filter' 15 @@ -241,8 +242,8 @@ start_service() { procd_set_param command ${LLDPDBIN} procd_append_param command -d - if [ $enable_lldp -gt 0 ]; then - if [ $force_lldp -gt 0 ]; then + if [ "$enable_lldp" -gt 0 ]; then + if [ "$force_lldp" -gt 0 ]; then procd_append_param command '-l' fi else @@ -250,20 +251,20 @@ start_service() { procd_append_param command '-ll' fi - if [ "$CONFIG_LLDPD_WITH_CDP" == "y" ] && [ $enable_cdp -gt 0 ]; then - if [ $cdp_version == "cdpv2" ]; then - if [ $force_cdp -gt 0 ]; then + if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ] && [ "$enable_cdp" -gt 0 ]; then + if [ "$cdp_version" = "cdpv2" ]; then + if [ "$force_cdp" -gt 0 ]; then # CDPv1 disabled, CDPv2 forced procd_append_param command '-ccccc' else # CDPv1 disabled, CDPv2 enabled procd_append_param command '-cccc' fi - elif [ $cdp_version == "cdpv1v2" ]; then - if [ $force_cdp -gt 0 ] && [ $force_cdpv2 -gt 0 ]; then + elif [ "$cdp_version" = "cdpv1v2" ]; then + if [ "$force_cdp" -gt 0 ] && [ "$force_cdpv2" -gt 0 ]; then # CDPv1 enabled, CDPv2 forced procd_append_param command '-ccc' - elif [ $force_cdp -gt 0 ]; then + elif [ "$force_cdp" -gt 0 ]; then # CDPv1 forced, CDPv2 enabled procd_append_param command '-cc' else @@ -273,8 +274,8 @@ start_service() { fi fi - if [ "$CONFIG_LLDPD_WITH_FDP" == "y" ] && [ $enable_fdp -gt 0 ]; then - if [ $force_fdp -gt 0 ]; then + if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ] && [ "$enable_fdp" -gt 0 ]; then + if [ "$force_fdp" -gt 0 ]; then # FDP enabled and forced procd_append_param command '-ff' else @@ -283,8 +284,8 @@ start_service() { fi fi - if [ "$CONFIG_LLDPD_WITH_SONMP" == "y" ] && [ $enable_sonmp -gt 0 ]; then - if [ $force_sonmp -gt 0 ]; then + if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ] && [ "$enable_sonmp" -gt 0 ]; then + if [ "$force_sonmp" -gt 0 ]; then # SONMP enabled and forced procd_append_param command '-ss' else @@ -293,8 +294,8 @@ start_service() { fi fi - if [ "$CONFIG_LLDPD_WITH_EDP" == "y" ] && [ $enable_edp -gt 0 ]; then - if [ $force_edp -gt 0 ]; then + if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ] && [ "$enable_edp" -gt 0 ]; then + if [ "$force_edp" -gt 0 ]; then # EDP enabled and forced procd_append_param command '-ee' else @@ -303,11 +304,11 @@ start_service() { fi fi - [ $readonly_mode -gt 0 ] && procd_append_param command '-r' - [ $lldp_no_version -gt 0 ] && procd_append_param command '-k' - [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ] && [ $lldpmed_no_inventory -gt 0 ] && procd_append_param command '-i' + [ "$readonly_mode" -gt 0 ] && procd_append_param command '-r' + [ "$lldp_no_version" -gt 0 ] && procd_append_param command '-k' + [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ] && [ "$lldpmed_no_inventory" -gt 0 ] && procd_append_param command '-i' [ -n "$lldp_class" ] && procd_append_param command -M "$lldp_class" - [ "$CONFIG_LLDPD_WITH_SNMP" == "y" ] && [ -n "$agentxsocket" ] && procd_append_param command -x -X "$agentxsocket" + [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ] && [ -n "$agentxsocket" ] && procd_append_param command -x -X "$agentxsocket" [ -n "$filter" ] && procd_append_param command -H "$filter" # ChassisID interfaces @@ -321,7 +322,7 @@ start_service() { local restart_hash get_config_restart_hash restart_hash - echo -n "$restart_hash" > $LLDPD_RESTART_HASH + echo -n "$restart_hash" > "$LLDPD_RESTART_HASH" # set auto respawn behavior procd_set_param respawn @@ -339,7 +340,7 @@ reload_service() { local config_hash="" get_config_restart_hash config_hash - if [ -f ${LLDPD_RESTART_HASH} ]; then running_hash=`cat $LLDPD_RESTART_HASH`; fi + [ -f ${LLDPD_RESTART_HASH} ] && running_hash=$(cat "$LLDPD_RESTART_HASH") if [ "x$running_hash" != "x$config_hash" ]; then # Restart LLDPd @@ -348,7 +349,7 @@ reload_service() { return 0 fi - $LLDPCLI -u $LLDPSOCKET &> /dev/null <<-EOF + $LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF pause unconfigure lldp custom-tlv unconfigure system interface pattern @@ -357,8 +358,8 @@ reload_service() { unconfigure system ip management pattern unconfigure system platform EOF - if [ "$CONFIG_LLDPD_WITH_LLDPMED" == "y" ]; then - $LLDPCLI -u $LLDPSOCKET &> /dev/null <<-EOF + if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then + $LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF unconfigure med fast-start EOF @@ -366,9 +367,9 @@ reload_service() { # Rewrite lldpd.conf # If something changed it should be included by the lldpcli call write_lldpd_conf - $LLDPCLI -u $LLDPSOCKET -c $LLDPD_CONF -c $LLDPD_CONFS_DIR &> /dev/null + $LLDPCLI -u "$LLDPSOCKET" -c "$LLDPD_CONF" -c "$LLDPD_CONFS_DIR" 2>&1 /dev/null # Broadcast update over the wire - $LLDPCLI -u $LLDPSOCKET &> /dev/null <<-EOF + $LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF resume update EOF @@ -376,6 +377,6 @@ reload_service() { } stop_service() { - rm -rf ${LLDPD_RUN} $LLDPSOCKET 2>/dev/null + rm -rf ${LLDPD_RUN} "$LLDPSOCKET" 2> /dev/null } From f753d3152f81bd037e9b7abb1b8c5bf9fe54596b Mon Sep 17 00:00:00 2001 From: Paul Donald Date: Tue, 12 Mar 2024 00:31:15 +0100 Subject: [PATCH 095/108] lldpd: update URL update Makefile URL Signed-off-by: Paul Donald --- package/network/services/lldpd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/lldpd/Makefile b/package/network/services/lldpd/Makefile index ffe2a8d015..18cdda33ce 100644 --- a/package/network/services/lldpd/Makefile +++ b/package/network/services/lldpd/Makefile @@ -31,7 +31,7 @@ define Package/lldpd CATEGORY:=Network SUBMENU:=Routing and Redirection TITLE:=Link Layer Discovery Protocol daemon - URL:=https://vincentbernat.github.io/lldpd/ + URL:=https://lldpd.github.io/ DEPENDS:=+libcap +libevent2 +USE_GLIBC:libbsd +LLDPD_WITH_JSON:libjson-c +LLDPD_WITH_SNMP:libnetsnmp USERID:=lldp=121:lldp=129 MENU:=1 From 1d3d6ef8269aca7ee34fb6ddd1c11d3fe45e785b Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 2 Mar 2024 19:58:40 +0000 Subject: [PATCH 096/108] ramips: add support for Z-ROUTER ZR-2660 This commit adds support for Z-ROUTER ZR-2660 (also known as Routerich AX1800) wireless WiFi 6 router. Specification ------------- - SoC : MediaTek MT7621AT, MIPS, 880 MHz - RAM : 256 MiB - Flash : NAND 128 MiB (AMD/Spansion S34ML01G2) - WLAN : - 2.4 GHz : MediaTek MT7905D/MT7975 (14c3:7916), b/g/n/ax, MIMO 2x2 - 5 GHz : MediaTek MT7915E (14c3:7915), a/n/ac/ax, MIMO 2x2 - Ethernet : 10/100/1000 Mbps x4 (1x WAN, 3x LAN) - USB : 1x 2.0 - UART : 3.3V, 115200n8, pins are silkscreened on the pcb - Buttons : 1x Reset - LEDs : 1x WiFi 2.4 GHz (green) 1x WiFi 5 GHz (green) 1x LAN (green) 1x WAN (green) 1x WAN no-internet (red) - Power : 12 VDC, 1 A Installation ------------ 1. Run tftp server on your PC (IP: 192.168.2.2) and put OpenWrt initramfs image (initramfs.bin) to the tftp root dir 2. Open the following link in the browser to enable telnet: http://192.168.2.1/cgi-bin/telnet_ssh 3. Connect to the router (default IP: 192.168.2.1) using telnet shell (credentials - user:admin) 4. Run the following commands in the telnet shell (this will install OpenWrt initramfs image on nand flash): cd /tmp tftp -g -r initramfs.bin 192.168.2.2 mtd write initramfs.bin firmware mtd erase firmware_backup reboot 5. Copy OpenWrt sysupgrade image (sysupgrade.bin) to the /tmp dir of the router 6. Connect to the router (IP: 192.168.1.1) using ssh shell and run sysupgrade command: sysupgrade -n /tmp/sysupgrade.bin Return to stock --------------- 1. Copy stock firmware (stock.bin) to the /tmp dir of the router using scp 2. Run following command in the router shell: cd /tmp mtd write stock.bin firmware reboot Recovery -------- Connect uart (pins are silkscreened on the pcb), interrupt boot process by pressing any key, use u-boot menu to flash stock firmware image or OpenWrt initramfs image. MAC addresses ------------- +---------+-------------------+-----------+ | | MAC | Algorithm | +---------+-------------------+-----------+ | LAN | 24:0f:5e:xx:xx:4c | label | | WAN | 24:0f:5e:xx:xx:4d | label+1 | | WLAN 2g | 24:0f:5e:xx:xx:4e | label+2 | | WLAN 5g | 24:0f:5e:xx:xx:4f | label+3 | +---------+-------------------+-----------+ The WLAN 2.4 MAC was found in 'factory', 0x4 The LAN MAC was found in 'factory', 0xfff4 The WAN MAC was found in 'factory', 0xfffa Signed-off-by: Mikhail Zhilkin --- .../ramips/dts/mt7621_z-router_zr-2660.dts | 211 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 15 ++ .../mt7621/base-files/etc/board.d/01_leds | 5 + .../mt7621/base-files/etc/board.d/02_network | 1 + .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 3 +- .../mt7621/base-files/lib/upgrade/platform.sh | 1 + 6 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 target/linux/ramips/dts/mt7621_z-router_zr-2660.dts diff --git a/target/linux/ramips/dts/mt7621_z-router_zr-2660.dts b/target/linux/ramips/dts/mt7621_z-router_zr-2660.dts new file mode 100644 index 0000000000..34b151be75 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_z-router_zr-2660.dts @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "z-router,zr-2660", "mediatek,mt7621-soc"; + model = "Z-ROUTER ZR-2660"; + + aliases { + label-mac-device = &gmac0; + + led-boot = &led_power_green; + led-failsafe = &led_power_green; + led-running = &led_power_green; + led-upgrade = &led_power_green; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + keys { + compatible = "gpio-keys"; + + key-0 { + label = "reset"; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + led-1 { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <50>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led-2 { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <24>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-4 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; + }; + + led_power_green: led-5 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_3fff4>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_factory_3fffa>; + nvmem-cell-names = "mac-address"; +}; + +&mdio { + ethphy4: ethernet-phy@4 { + reg = <4>; + }; +}; + +&nand { + status = "okay"; + + 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 = "u-boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "Config"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "factory"; + reg = <0x100000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + macaddr_factory_3fff4: macaddr@3fff4 { + reg = <0x3fff4 0x6>; + }; + + macaddr_factory_3fffa: macaddr@3fffa { + reg = <0x3fffa 0x6>; + }; + }; + }; + + partition@180000 { + label = "firmware"; + reg = <0x180000 0x7680000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x400000 0x7280000>; + }; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + + mediatek,disable-radar-background; + + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + }; +}; + +&state_default { + gpio { + groups = "i2c", "jtag", "wdt"; + function = "gpio"; + }; +}; + +&switch0 { + ports { + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 3b9ee022f6..5fd95463c8 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -2928,6 +2928,21 @@ define Device/yuncore_g720 endef TARGET_DEVICES += yuncore_g720 +define Device/z-router_zr-2660 + $(Device/dsa-migration) + $(Device/nand) + DEVICE_VENDOR := Z-ROUTER + DEVICE_MODEL := ZR-2660 + DEVICE_ALT0_VENDOR := Routerich + DEVICE_ALT0_MODEL := AX1800 + IMAGE_SIZE := 90112k + KERNEL_LOADADDR := 0x82000000 + KERNEL := kernel-bin | relocate-kernel $(loadaddr-y) | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + DEVICE_PACKAGES += kmod-mt7915-firmware kmod-usb3 -uboot-envtools +endef +TARGET_DEVICES += z-router_zr-2660 + define Device/zbtlink_zbt-we1326 $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 81afa45e80..3eba20bb79 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -251,6 +251,11 @@ yuncore,ax820) ucidef_set_led_netdev "lan" "LAN" "green:lan" "lan" ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" ;; +z-router,zr-2660) + ucidef_set_led_netdev "lan" "lan" "green:lan" "br-lan" "link tx rx" + ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" + ucidef_set_led_netdev "wan-off" "wan-off" "red:wan" "wan" "link" + ;; zyxel,lte3301-plus) ucidef_set_led_netdev "internet" "internet" "white:internet" "wwan0" ;; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index d0481b78e9..d932313cf1 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -26,6 +26,7 @@ ramips_setup_interfaces() xiaomi,mi-router-cr6608|\ xiaomi,mi-router-cr6609|\ xiaomi,redmi-router-ac2100|\ + z-router,zr-2660|\ zyxel,wsm20) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ;; diff --git a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac index 3be4e24e09..962e1f7019 100644 --- a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +++ b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -72,7 +72,8 @@ case "$board" in macaddr_setbit_la "$base_mac" > /sys${DEVPATH}/macaddress fi ;; - glinet,gl-mt1300) + glinet,gl-mt1300|\ + z-router,zr-2660) [ "$PHYNBR" = "1" ] && \ macaddr_add "$(mtd_get_mac_binary factory 0x4)" 1 > /sys${DEVPATH}/macaddress ;; diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh index 6151714145..eba02e6599 100755 --- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh @@ -124,6 +124,7 @@ platform_do_upgrade() { xiaomi,mi-router-cr6608|\ xiaomi,mi-router-cr6609|\ xiaomi,redmi-router-ac2100|\ + z-router,zr-2660|\ zyxel,nwa50ax|\ zyxel,nwa55axe) nand_do_upgrade "$1" From 51752fa14bebb6d026b36dc18e4562f93caa96b5 Mon Sep 17 00:00:00 2001 From: Liu Dongmiao Date: Tue, 12 Mar 2024 06:48:08 +0000 Subject: [PATCH 097/108] libevent2: make cmake use relative imported path libevent2's cmake use absolute path, then cmake cannot find it when cross compiling: ``` -- Found libevent include directory: /builder/staging_dir/target-mips_24kc_musl/usr/include -- Found libevent component: /builder/staging_dir/target-mips_24kc_musl/usr/lib/libevent_core.so -- Found libevent component: /builder/staging_dir/target-mips_24kc_musl/usr/lib/libevent_extra.so -- Found libevent component: /builder/staging_dir/target-mips_24kc_musl/usr/lib/libevent_openssl.so -- Found libevent 2.1.12 in /builder/staging_dir/target-mips_24kc_musl/usr CMake Error at /builder/staging_dir/target-mips_24kc_musl/usr/lib/cmake/libevent/LibeventTargets-shared.cmake:102 (message): The imported target "libevent::core" references the file "/usr/lib/libevent_core-2.1.so.7.0.1" but this file does not exist. Possible reasons include: * The file was deleted, renamed, or moved to another location. * An install or uninstall procedure did not complete successfully. * The installation package was faulty and contained "/builder/staging_dir/target-mips_24kc_musl/usr/lib/cmake/libevent/LibeventTargets-shared.cmake" but not all the files it references. Call Stack (most recent call first): /builder/staging_dir/target-mips_24kc_musl/usr/lib/cmake/libevent/LibeventConfig.cmake:168 (include) CMakeLists.txt:34 (find_package) ``` This patch make cmake use relative imported path, so it can find libevent. Signed-off-by: Liu Dongmiao --- package/libs/libevent2/Makefile | 2 +- .../patches/001-relative-cmake.patch | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 package/libs/libevent2/patches/001-relative-cmake.patch diff --git a/package/libs/libevent2/Makefile b/package/libs/libevent2/Makefile index 92602607ae..e0a080d60e 100644 --- a/package/libs/libevent2/Makefile +++ b/package/libs/libevent2/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libevent2 PKG_VERSION:=2.1.12 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=libevent-$(PKG_VERSION)-stable.tar.gz PKG_SOURCE_URL:=https://github.com/libevent/libevent/releases/download/release-$(PKG_VERSION)-stable diff --git a/package/libs/libevent2/patches/001-relative-cmake.patch b/package/libs/libevent2/patches/001-relative-cmake.patch new file mode 100644 index 0000000000..38dc187df6 --- /dev/null +++ b/package/libs/libevent2/patches/001-relative-cmake.patch @@ -0,0 +1,58 @@ +From 81c6b8823c1b58d7837e827bb1098aa5f9e5956b Mon Sep 17 00:00:00 2001 +From: "Jeremy W. Murphy" +Date: Tue, 16 May 2023 05:07:36 +1000 +Subject: [PATCH] cmake: Only use relative paths for install DESTINATION option + (#1405) + +As described in #1404, the explicit use of CMAKE_INSTALL_PREFIX conflicts with using command-line --prefix. + +This simply removes all explicit use of CMAKE_INSTALL_PREFIX. + +Otherwise this path will be duplicated: + + $ cmake -DCMAKE_BUILD_TYPE=debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_INSTALL_PREFIX=inst .. + $ DESTDIR=inst ninja install + ... + -- Installing: inst/src/le/libevent/.cmake-debug/inst/include/event2/util.h + -- Installing: inst/src/le/libevent/.cmake-debug/inst/include/event2/ws.h + ... + +Fixes: #1404 +Co-authored-by: Jeremy Murphy +--- + CMakeLists.txt | 3 +-- + cmake/AddEventLibrary.cmake | 4 ++-- + 2 files changed, 3 insertions(+), 4 deletions(-) + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1452,8 +1452,7 @@ endif() + # Installation preparation. + # + +-set(EVENT_INSTALL_CMAKE_DIR +- "${CMAKE_INSTALL_PREFIX}/lib/cmake/libevent") ++set(EVENT_INSTALL_CMAKE_DIR "lib/cmake/libevent") + + export(PACKAGE libevent) + +--- a/cmake/AddEventLibrary.cmake ++++ b/cmake/AddEventLibrary.cmake +@@ -31,7 +31,7 @@ macro(generate_pkgconfig LIB_NAME) + configure_file("lib${LIB_NAME}.pc.in" "lib${LIB_NAME}.pc" @ONLY) + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${LIB_NAME}.pc" +- DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig" ++ DESTINATION "lib/pkgconfig" + ) + endmacro() + +@@ -150,7 +150,7 @@ macro(add_event_library LIB_NAME) + set_target_properties( + "${LIB_NAME}_shared" PROPERTIES + OUTPUT_NAME "${LIB_NAME}-${EVENT_PACKAGE_RELEASE}.${CURRENT_MINUS_AGE}" +- INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" ++ INSTALL_NAME_DIR "lib" + LINK_FLAGS "-compatibility_version ${COMPATIBILITY_VERSION} -current_version ${COMPATIBILITY_VERSION}.${EVENT_ABI_LIBVERSION_REVISION}") + else() + math(EXPR CURRENT_MINUS_AGE "${EVENT_ABI_LIBVERSION_CURRENT}-${EVENT_ABI_LIBVERSION_AGE}") From a4379507704a9ed48b009ce26e3c5ef1eefa1d4d Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Wed, 13 Mar 2024 14:27:08 +0800 Subject: [PATCH 098/108] ath79: switch default kernel to 6.1 The 6.1 kernel has been tested for over half a year. Signed-off-by: Shiji Yang --- target/linux/ath79/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/ath79/Makefile b/target/linux/ath79/Makefile index f7bb31c4ad..3ef4b32c72 100644 --- a/target/linux/ath79/Makefile +++ b/target/linux/ath79/Makefile @@ -8,8 +8,7 @@ SUBTARGETS:=generic mikrotik nand tiny FEATURES:=ramdisk squashfs usbgadget -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 include $(INCLUDE_DIR)/target.mk From 0efa91d6ea93952e1b20d8aa32fffcb0d2f5bee9 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Wed, 13 Mar 2024 14:27:08 +0800 Subject: [PATCH 099/108] ath79: remove obsolete 5.15 kernel support The 5.15 kenel config file, patches and version switches will be removed in this patch. We will introduce kernel 6.6 support soon. Signed-off-by: Shiji Yang --- target/linux/ath79/config-5.15 | 200 ---- .../ethernet/atheros/ag71xx/ag71xx_ethtool.c | 28 +- .../net/ethernet/atheros/ag71xx/ag71xx_main.c | 4 - ...-ar934x-fix-transfer-and-word-delays.patch | 27 - ...1-v5.17-spi-ar934x-fix-transfer-size.patch | 62 -- ...th79-Implement-the-spi_mem-interface.patch | 68 -- ...th79-add-support-for-booting-QCN550x.patch | 48 - ...reset-ath79-read-back-reset-register.patch | 33 - ...9-intc-add-irq-cascade-driver-for-QC.patch | 168 ---- ...ip-irq-ath79-cpu-drop-OF-init-helper.patch | 23 - ...ngs-PCI-qcom-ar7100-adds-binding-doc.patch | 57 -- .../311-MIPS-pci-ar71xx-convert-to-OF.patch | 206 ---- ...ngs-PCI-qcom-ar7240-adds-binding-doc.patch | 61 -- .../313-MIPS-pci-ar724x-convert-to-OF.patch | 213 ----- ...-MIPS-ath79-remove-irq-code-from-pci.patch | 149 --- ...ci-ar724x-add-QCA9550-reset-sequence.patch | 130 --- ...ath79-swizzle-pci-address-for-ar71xx.patch | 109 --- .../patches-5.15/330-missing-registers.patch | 20 - ...9-add-missing-QCA955x-GMAC-registers.patch | 90 -- .../patches-5.15/332-ath79-sgmii-config.patch | 30 - .../340-register_gpio_driver_earlier.patch | 26 - .../350-MIPS-ath79-ath9k-exports.patch | 36 - .../351-MIPS-ath79-common-exports.patch | 26 - ...S-ath79-export-UART1-reference-clock.patch | 67 -- .../370-MIPS-ath79-sanitize-symbols.patch | 93 -- ...or-support-mtd-name-from-device-tree.patch | 54 -- .../410-mtd-cybertan-trx-parser.patch | 45 - .../420-drivers-link-spi-before-mtd.patch | 20 - .../430-mtd-ar934x-nand-driver.patch | 34 - .../700-phy-add-ath79-usb-phys.patch | 333 ------- ...701-usb-add-more-OF-quirk-properties.patch | 24 - .../710-net-use-downstream-ag71xx.patch | 42 - .../720-mdio_bitbang_ignore_ta_value.patch | 44 - ...-prevent-rescheduling-during-command.patch | 61 -- .../730-ar8216-make-reg-access-atomic.patch | 59 -- ...ds-add-reset-controller-based-driver.patch | 186 ---- .../900-unaligned_access_hacks.patch | 900 ------------------ .../patches-5.15/910-mikrotik-rb4xx.patch | 121 --- .../patches-5.15/911-mikrotik-rb91x.patch | 97 -- 39 files changed, 10 insertions(+), 3984 deletions(-) delete mode 100644 target/linux/ath79/config-5.15 delete mode 100644 target/linux/ath79/patches-5.15/010-v5.17-spi-ar934x-fix-transfer-and-word-delays.patch delete mode 100644 target/linux/ath79/patches-5.15/011-v5.17-spi-ar934x-fix-transfer-size.patch delete mode 100644 target/linux/ath79/patches-5.15/020-v5.18-spi-ath79-Implement-the-spi_mem-interface.patch delete mode 100644 target/linux/ath79/patches-5.15/030-v5.18-ath79-add-support-for-booting-QCN550x.patch delete mode 100644 target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch delete mode 100644 target/linux/ath79/patches-5.15/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch delete mode 100644 target/linux/ath79/patches-5.15/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch delete mode 100644 target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch delete mode 100644 target/linux/ath79/patches-5.15/311-MIPS-pci-ar71xx-convert-to-OF.patch delete mode 100644 target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch delete mode 100644 target/linux/ath79/patches-5.15/313-MIPS-pci-ar724x-convert-to-OF.patch delete mode 100644 target/linux/ath79/patches-5.15/314-MIPS-ath79-remove-irq-code-from-pci.patch delete mode 100644 target/linux/ath79/patches-5.15/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch delete mode 100644 target/linux/ath79/patches-5.15/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch delete mode 100644 target/linux/ath79/patches-5.15/330-missing-registers.patch delete mode 100644 target/linux/ath79/patches-5.15/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch delete mode 100644 target/linux/ath79/patches-5.15/332-ath79-sgmii-config.patch delete mode 100644 target/linux/ath79/patches-5.15/340-register_gpio_driver_earlier.patch delete mode 100644 target/linux/ath79/patches-5.15/350-MIPS-ath79-ath9k-exports.patch delete mode 100644 target/linux/ath79/patches-5.15/351-MIPS-ath79-common-exports.patch delete mode 100644 target/linux/ath79/patches-5.15/360-MIPS-ath79-export-UART1-reference-clock.patch delete mode 100644 target/linux/ath79/patches-5.15/370-MIPS-ath79-sanitize-symbols.patch delete mode 100644 target/linux/ath79/patches-5.15/400-mtd-nor-support-mtd-name-from-device-tree.patch delete mode 100644 target/linux/ath79/patches-5.15/410-mtd-cybertan-trx-parser.patch delete mode 100644 target/linux/ath79/patches-5.15/420-drivers-link-spi-before-mtd.patch delete mode 100644 target/linux/ath79/patches-5.15/430-mtd-ar934x-nand-driver.patch delete mode 100644 target/linux/ath79/patches-5.15/700-phy-add-ath79-usb-phys.patch delete mode 100644 target/linux/ath79/patches-5.15/701-usb-add-more-OF-quirk-properties.patch delete mode 100644 target/linux/ath79/patches-5.15/710-net-use-downstream-ag71xx.patch delete mode 100644 target/linux/ath79/patches-5.15/720-mdio_bitbang_ignore_ta_value.patch delete mode 100644 target/linux/ath79/patches-5.15/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch delete mode 100644 target/linux/ath79/patches-5.15/730-ar8216-make-reg-access-atomic.patch delete mode 100644 target/linux/ath79/patches-5.15/800-leds-add-reset-controller-based-driver.patch delete mode 100644 target/linux/ath79/patches-5.15/900-unaligned_access_hacks.patch delete mode 100644 target/linux/ath79/patches-5.15/910-mikrotik-rb4xx.patch delete mode 100644 target/linux/ath79/patches-5.15/911-mikrotik-rb91x.patch diff --git a/target/linux/ath79/config-5.15 b/target/linux/ath79/config-5.15 deleted file mode 100644 index 5b1b0d5add..0000000000 --- a/target/linux/ath79/config-5.15 +++ /dev/null @@ -1,200 +0,0 @@ -CONFIG_AG71XX=y -# CONFIG_AG71XX_DEBUG is not set -CONFIG_AG71XX_DEBUG_FS=y -CONFIG_AR8216_PHY=y -CONFIG_AR8216_PHY_LEDS=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_AT803X_PHY=y -CONFIG_ATH79=y -CONFIG_ATH79_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_CEVT_R4K=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_ETHERNET_PACKET_MANGLE=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_74X164=y -CONFIG_GPIO_ATH79=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -# CONFIG_GPIO_LATCH is not set -# CONFIG_GPIO_RB91X_KEY is not set -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LEDS_GPIO=y -# CONFIG_LEDS_RESET is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_GPIO=y -CONFIG_MEMFD_CREATE=y -# CONFIG_MFD_RB4XX_CPLD is not set -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_CFI_I2 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set -CONFIG_MTD_PARSER_CYBERTAN=y -# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_ELF_FW=y -CONFIG_MTD_SPLIT_LZMA_FW=y -CONFIG_MTD_SPLIT_SEAMA_FW=y -CONFIG_MTD_SPLIT_TPLINK_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_SPLIT_WRGG_FW=y -CONFIG_MTD_VIRT_CONCAT=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_SELFTESTS=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI=y -CONFIG_PCI_AR71XX=y -CONFIG_PCI_AR724X=y -CONFIG_PCI_DISABLE_COMMON_QUIRKS=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_AR7100_USB is not set -# CONFIG_PHY_AR7200_USB is not set -# CONFIG_PHY_ATH79_USB is not set -CONFIG_PINCTRL=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_RESET_ATH79=y -CONFIG_RESET_CONTROLLER=y -CONFIG_SERIAL_8250_NR_UARTS=1 -CONFIG_SERIAL_8250_RUNTIME_UARTS=1 -CONFIG_SERIAL_AR933X=y -CONFIG_SERIAL_AR933X_CONSOLE=y -CONFIG_SERIAL_AR933X_NR_UARTS=2 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SPI=y -CONFIG_SPI_AR934X=y -CONFIG_SPI_ATH79=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_GPIO=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_RB4XX is not set -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWCONFIG_LEDS=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TINY_SRCU=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c index b022a3e9fb..14c6560907 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c @@ -80,15 +80,11 @@ static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level) ag->msg_enable = msg_level; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -static void ag71xx_ethtool_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *er, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *extack) -#else -static void ag71xx_ethtool_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *er) -#endif +static void +ag71xx_ethtool_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *er, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *extack) { struct ag71xx *ag = netdev_priv(dev); @@ -106,15 +102,11 @@ static void ag71xx_ethtool_get_ringparam(struct net_device *dev, er->tx_pending /= AG71XX_TX_RING_DS_PER_PKT; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -static int ag71xx_ethtool_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *er, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *extack) -#else -static int ag71xx_ethtool_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *er) -#endif +static int +ag71xx_ethtool_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *er, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *extack) { struct ag71xx *ag = netdev_priv(dev); unsigned tx_size; diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index 8a5cd3bcde..8132849a9a 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -1698,11 +1698,7 @@ static int ag71xx_probe(struct platform_device *pdev) break; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,19,0) netif_napi_add_weight(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); -#else - netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); -#endif ag71xx_dump_regs(ag); diff --git a/target/linux/ath79/patches-5.15/010-v5.17-spi-ar934x-fix-transfer-and-word-delays.patch b/target/linux/ath79/patches-5.15/010-v5.17-spi-ar934x-fix-transfer-and-word-delays.patch deleted file mode 100644 index 7ce6df6d7b..0000000000 --- a/target/linux/ath79/patches-5.15/010-v5.17-spi-ar934x-fix-transfer-and-word-delays.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c70282457c380db7deb57c81a6894debc8f88efa Mon Sep 17 00:00:00 2001 -From: Oskari Lemmela -Date: Wed, 22 Dec 2021 07:59:58 +0200 -Subject: [PATCH] spi: ar934x: fix transfer and word delays - -Add missing delay between transferred messages and words. - -Signed-off-by: Oskari Lemmela -Link: https://lore.kernel.org/r/20211222055958.1383233-3-oskari@lemmela.net -Signed-off-by: Mark Brown ---- - drivers/spi/spi-ar934x.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/spi/spi-ar934x.c -+++ b/drivers/spi/spi-ar934x.c -@@ -137,8 +137,10 @@ static int ar934x_spi_transfer_one_messa - reg >>= 8; - } - } -+ spi_delay_exec(&t->word_delay, t); - } - m->actual_length += t->len; -+ spi_transfer_delay_exec(t); - } - - msg_done: diff --git a/target/linux/ath79/patches-5.15/011-v5.17-spi-ar934x-fix-transfer-size.patch b/target/linux/ath79/patches-5.15/011-v5.17-spi-ar934x-fix-transfer-size.patch deleted file mode 100644 index 87f5da2c60..0000000000 --- a/target/linux/ath79/patches-5.15/011-v5.17-spi-ar934x-fix-transfer-size.patch +++ /dev/null @@ -1,62 +0,0 @@ -From ebe33e5a98dcf14a9630845f3f10c193584ac054 Mon Sep 17 00:00:00 2001 -From: Oskari Lemmela -Date: Wed, 22 Dec 2021 07:59:57 +0200 -Subject: [PATCH] spi: ar934x: fix transfer size - -If bits_per_word is configured, transfer only word amount -of data per iteration. - -Signed-off-by: Oskari Lemmela -Link: https://lore.kernel.org/r/20211222055958.1383233-2-oskari@lemmela.net -Signed-off-by: Mark Brown ---- - drivers/spi/spi-ar934x.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - ---- a/drivers/spi/spi-ar934x.c -+++ b/drivers/spi/spi-ar934x.c -@@ -82,7 +82,7 @@ static int ar934x_spi_transfer_one_messa - struct spi_device *spi = m->spi; - unsigned long trx_done, trx_cur; - int stat = 0; -- u8 term = 0; -+ u8 bpw, term = 0; - int div, i; - u32 reg; - const u8 *tx_buf; -@@ -90,6 +90,11 @@ static int ar934x_spi_transfer_one_messa - - m->actual_length = 0; - list_for_each_entry(t, &m->transfers, transfer_list) { -+ if (t->bits_per_word >= 8 && t->bits_per_word < 32) -+ bpw = t->bits_per_word >> 3; -+ else -+ bpw = 4; -+ - if (t->speed_hz) - div = ar934x_spi_clk_div(sp, t->speed_hz); - else -@@ -105,10 +110,10 @@ static int ar934x_spi_transfer_one_messa - iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL); - iowrite32(0, sp->base + AR934X_SPI_DATAOUT); - -- for (trx_done = 0; trx_done < t->len; trx_done += 4) { -+ for (trx_done = 0; trx_done < t->len; trx_done += bpw) { - trx_cur = t->len - trx_done; -- if (trx_cur > 4) -- trx_cur = 4; -+ if (trx_cur > bpw) -+ trx_cur = bpw; - else if (list_is_last(&t->transfer_list, &m->transfers)) - term = 1; - -@@ -193,7 +198,8 @@ static int ar934x_spi_probe(struct platf - ctlr->mode_bits = SPI_LSB_FIRST; - ctlr->setup = ar934x_spi_setup; - ctlr->transfer_one_message = ar934x_spi_transfer_one_message; -- ctlr->bits_per_word_mask = SPI_BPW_MASK(8); -+ ctlr->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) | -+ SPI_BPW_MASK(16) | SPI_BPW_MASK(8); - ctlr->dev.of_node = pdev->dev.of_node; - ctlr->num_chipselect = 3; - diff --git a/target/linux/ath79/patches-5.15/020-v5.18-spi-ath79-Implement-the-spi_mem-interface.patch b/target/linux/ath79/patches-5.15/020-v5.18-spi-ath79-Implement-the-spi_mem-interface.patch deleted file mode 100644 index 5746a889e8..0000000000 --- a/target/linux/ath79/patches-5.15/020-v5.18-spi-ath79-Implement-the-spi_mem-interface.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 8d8cdb4a6ccee5b62cc0dc64651c3946364514dc Mon Sep 17 00:00:00 2001 -From: Luiz Angelo Daros de Luca -Date: Mon, 10 Feb 2020 16:11:27 -0300 -Subject: [PATCH] spi: ath79: Implement the spi_mem interface - -Signed-off-by: Luiz Angelo Daros de Luca ---- - drivers/spi/spi-ath79.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - ---- a/drivers/spi/spi-ath79.c -+++ b/drivers/spi/spi-ath79.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -133,6 +134,39 @@ static u32 ath79_spi_txrx_mode0(struct s - return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); - } - -+static int ath79_exec_mem_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi); -+ -+ /* Ensures that reading is performed on device connected -+ to hardware cs0 */ -+ if (mem->spi->chip_select || mem->spi->cs_gpiod) -+ return -ENOTSUPP; -+ -+ /* Only use for fast-read op. */ -+ if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN || -+ op->addr.nbytes != 3 || op->dummy.nbytes != 1) -+ return -ENOTSUPP; -+ -+ /* disable GPIO mode */ -+ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); -+ -+ memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes); -+ -+ /* enable GPIO mode */ -+ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); -+ -+ /* restore IOC register */ -+ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); -+ -+ return 0; -+} -+ -+static const struct spi_controller_mem_ops ath79_mem_ops = { -+ .exec_op = ath79_exec_mem_op, -+}; -+ - static int ath79_spi_probe(struct platform_device *pdev) - { - struct spi_master *master; -@@ -165,6 +199,7 @@ static int ath79_spi_probe(struct platfo - ret = PTR_ERR(sp->base); - goto err_put_master; - } -+ master->mem_ops = &ath79_mem_ops; - - sp->clk = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(sp->clk)) { diff --git a/target/linux/ath79/patches-5.15/030-v5.18-ath79-add-support-for-booting-QCN550x.patch b/target/linux/ath79/patches-5.15/030-v5.18-ath79-add-support-for-booting-QCN550x.patch deleted file mode 100644 index 41ea5d2ef0..0000000000 --- a/target/linux/ath79/patches-5.15/030-v5.18-ath79-add-support-for-booting-QCN550x.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Wenli Looi -Date: Sun, 20 Jun 2021 23:32:28 -0700 -Subject: [PATCH] ath79: add support for booting QCN550x - -Based on wikidevi, QCN550x is a "Dragonfly" like QCA9561 and QCA9563. -Treating it as QCA956x seems to work. -Tested on Netgear EX7300v2 which boots successfully with -the same CPU clock as the stock firmware. - -Link: https://wikidevi.wi-cat.ru/Qualcomm#bgn -Link: https://wikidevi.wi-cat.ru/Qualcomm_Atheros#.28a.29bgn_2 -Signed-off-by: Wenli Looi - ---- a/arch/mips/ath79/early_printk.c -+++ b/arch/mips/ath79/early_printk.c -@@ -121,6 +121,7 @@ static void prom_putchar_init(void) - case REV_ID_MAJOR_QCA9558: - case REV_ID_MAJOR_TP9343: - case REV_ID_MAJOR_QCA956X: -+ case REV_ID_MAJOR_QCN550X: - _prom_putchar = prom_putchar_ar71xx; - break; - ---- a/arch/mips/ath79/setup.c -+++ b/arch/mips/ath79/setup.c -@@ -168,6 +168,12 @@ static void __init ath79_detect_sys_type - rev = id & QCA956X_REV_ID_REVISION_MASK; - break; - -+ case REV_ID_MAJOR_QCN550X: -+ ath79_soc = ATH79_SOC_QCA956X; -+ chip = "550X"; -+ rev = id & QCA956X_REV_ID_REVISION_MASK; -+ break; -+ - case REV_ID_MAJOR_TP9343: - ath79_soc = ATH79_SOC_TP9343; - chip = "9343"; ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -862,6 +862,7 @@ - #define REV_ID_MAJOR_QCA9558 0x1130 - #define REV_ID_MAJOR_TP9343 0x0150 - #define REV_ID_MAJOR_QCA956X 0x1150 -+#define REV_ID_MAJOR_QCN550X 0x2170 - - #define AR71XX_REV_ID_MINOR_MASK 0x3 - #define AR71XX_REV_ID_MINOR_AR7130 0x0 diff --git a/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch deleted file mode 100644 index 7aa501514d..0000000000 --- a/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Tue, 9 Jan 2024 20:48:46 +0100 -Subject: [PATCH] reset: ath79: read back reset register - -Read back the reset register in order to flush the cache. This fixes -spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel -DRAM chips. - -This issue was fixed in the past, but switching to the reset-driver -specific implementation removed the old fix. - -Link: https://github.com/freifunk-gluon/gluon/issues/2904 -Link: https://github.com/openwrt/openwrt/issues/13043 -Link: https://dev.archive.openwrt.org/ticket/17839 -Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") - -Signed-off-by: David Bauer ---- - drivers/reset/reset-ath79.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/reset/reset-ath79.c -+++ b/drivers/reset/reset-ath79.c -@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res - else - val &= ~BIT(id); - writel(val, ath79_reset->base); -+ /* Flush cache */ -+ readl(ath79_reset->base); - spin_unlock_irqrestore(&ath79_reset->lock, flags); - - return 0; diff --git a/target/linux/ath79/patches-5.15/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-5.15/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch deleted file mode 100644 index ceda511c21..0000000000 --- a/target/linux/ath79/patches-5.15/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ /dev/null @@ -1,168 +0,0 @@ -From f3eacff2310a60348a755c50a8da6fc251fc8587 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 6 Mar 2018 09:55:13 +0100 -Subject: [PATCH 07/33] irqchip/irq-ath79-intc: add irq cascade driver for - QCA9556 SoCs - -Signed-off-by: John Crispin ---- - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 143 insertions(+) - create mode 100644 drivers/irqchip/irq-ath79-intc.c - ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o - obj-$(CONFIG_AL_FIC) += irq-al-fic.o - obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o - obj-$(CONFIG_ATH79) += irq-ath79-cpu.o -+obj-$(CONFIG_ATH79) += irq-ath79-intc.o - obj-$(CONFIG_ATH79) += irq-ath79-misc.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o - obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); diff --git a/target/linux/ath79/patches-5.15/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch b/target/linux/ath79/patches-5.15/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch deleted file mode 100644 index 13117d9a8e..0000000000 --- a/target/linux/ath79/patches-5.15/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch +++ /dev/null @@ -1,23 +0,0 @@ -From e029f998594f151008ecbfa024e2957edd2a5189 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 6 Mar 2018 09:58:19 +0100 -Subject: [PATCH 08/33] irqchip/irq-ath79-cpu: drop !OF init helper - -Signed-off-by: John Crispin ---- - drivers/irqchip/irq-ath79-cpu.c | 7 ------- - 1 file changed, 7 deletions(-) - ---- a/drivers/irqchip/irq-ath79-cpu.c -+++ b/drivers/irqchip/irq-ath79-cpu.c -@@ -85,10 +85,3 @@ static int __init ar79_cpu_intc_of_init( - } - IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", - ar79_cpu_intc_of_init); -- --void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) --{ -- irq_wb_chan[2] = irq_wb_chan2; -- irq_wb_chan[3] = irq_wb_chan3; -- mips_cpu_irq_init(); --} diff --git a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch deleted file mode 100644 index cf0a75c791..0000000000 --- a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 4a4f869ec58ed8910b9b2e68d0eee50957e9bb20 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 25 Jun 2018 15:52:10 +0200 -Subject: [PATCH 17/33] dt-bindings: PCI: qcom,ar7100: adds binding doc - -With the driver being converted from platform_data to pure OF, we need to -also add some docs. - -Cc: Rob Herring -Cc: devicetree@vger.kernel.org -Signed-off-by: John Crispin ---- - .../devicetree/bindings/pci/qcom,ar7100-pci.txt | 38 ++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt -@@ -0,0 +1,38 @@ -+* Qualcomm Atheros AR7100 PCI express root complex -+ -+Required properties: -+- compatible: should contain "qcom,ar7100-pci" to identify the core. -+- reg: Should contain the register ranges as listed in the reg-names property. -+- reg-names: Definition: Must include the following entries -+ - "cfg_base" IO Memory -+- #address-cells: set to <3> -+- #size-cells: set to <2> -+- ranges: ranges for the PCI memory and I/O regions -+- interrupt-map-mask and interrupt-map: standard PCI -+ properties to define the mapping of the PCIe interface to interrupt -+ numbers. -+- #interrupt-cells: set to <1> -+- interrupt-controller: define to enable the builtin IRQ cascade. -+ -+Optional properties: -+- interrupt-parent: phandle to the MIPS IRQ controller -+ -+* Example for ar7100 -+ pcie@180c0000 { -+ compatible = "qca,ar7100-pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ bus-range = <0x0 0x0>; -+ reg = <0x17010000 0x100>; -+ reg-names = "cfg_base"; -+ ranges = <0x2000000 0 0x10000000 0x10000000 0 0x07000000 -+ 0x1000000 0 0x00000000 0x00000000 0 0x00000001>; -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-map-mask = <0 0 0 1>; -+ interrupt-map = <0 0 0 0 &pcie0 0>; -+ }; diff --git a/target/linux/ath79/patches-5.15/311-MIPS-pci-ar71xx-convert-to-OF.patch b/target/linux/ath79/patches-5.15/311-MIPS-pci-ar71xx-convert-to-OF.patch deleted file mode 100644 index 9a315aed0b..0000000000 --- a/target/linux/ath79/patches-5.15/311-MIPS-pci-ar71xx-convert-to-OF.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 1855ab6b1d27f5b38a648baf57ff6a534afec26d Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 23 Jun 2018 15:07:23 +0200 -Subject: [PATCH 18/33] MIPS: pci-ar71xx: convert to OF - -With the ath79 target getting converted to pure OF, we can drop all the -platform data code and add the missing OF bits to the driver. We also add -a irq domain for the PCI/e controllers cascade, thus making it usable from -dts files. - -Signed-off-by: John Crispin ---- - arch/mips/pci/pci-ar71xx.c | 82 +++++++++++++++++++++++----------------------- - 1 file changed, 41 insertions(+), 41 deletions(-) - ---- a/arch/mips/pci/pci-ar71xx.c -+++ b/arch/mips/pci/pci-ar71xx.c -@@ -15,8 +15,11 @@ - #include - #include - #include -+#include - #include - #include -+#include -+#include - - #include - #include -@@ -46,12 +49,13 @@ - #define AR71XX_PCI_IRQ_COUNT 5 - - struct ar71xx_pci_controller { -+ struct device_node *np; - void __iomem *cfg_base; - int irq; -- int irq_base; - struct pci_controller pci_ctrl; - struct resource io_res; - struct resource mem_res; -+ struct irq_domain *domain; - }; - - /* Byte lane enable bits */ -@@ -225,29 +229,30 @@ static struct pci_ops ar71xx_pci_ops = { - - static void ar71xx_pci_irq_handler(struct irq_desc *desc) - { -- struct ar71xx_pci_controller *apc; - void __iomem *base = ath79_reset_base; -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); - u32 pending; - -- apc = irq_desc_get_handler_data(desc); -- -+ chained_irq_enter(chip, desc); - pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & - __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); - - if (pending & AR71XX_PCI_INT_DEV0) -- generic_handle_irq(apc->irq_base + 0); -+ generic_handle_irq(irq_linear_revmap(apc->domain, 1)); - - else if (pending & AR71XX_PCI_INT_DEV1) -- generic_handle_irq(apc->irq_base + 1); -+ generic_handle_irq(irq_linear_revmap(apc->domain, 2)); - - else if (pending & AR71XX_PCI_INT_DEV2) -- generic_handle_irq(apc->irq_base + 2); -+ generic_handle_irq(irq_linear_revmap(apc->domain, 3)); - - else if (pending & AR71XX_PCI_INT_CORE) -- generic_handle_irq(apc->irq_base + 4); -+ generic_handle_irq(irq_linear_revmap(apc->domain, 4)); - - else - spurious_interrupt(); -+ chained_irq_exit(chip, desc); - } - - static void ar71xx_pci_irq_unmask(struct irq_data *d) -@@ -258,7 +263,7 @@ static void ar71xx_pci_irq_unmask(struct - u32 t; - - apc = irq_data_get_irq_chip_data(d); -- irq = d->irq - apc->irq_base; -+ irq = irq_linear_revmap(apc->domain, d->irq); - - t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); - __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); -@@ -275,7 +280,7 @@ static void ar71xx_pci_irq_mask(struct i - u32 t; - - apc = irq_data_get_irq_chip_data(d); -- irq = d->irq - apc->irq_base; -+ irq = irq_linear_revmap(apc->domain, d->irq); - - t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); - __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); -@@ -291,24 +296,31 @@ static struct irq_chip ar71xx_pci_irq_ch - .irq_mask_ack = ar71xx_pci_irq_mask, - }; - -+static int ar71xx_pci_irq_map(struct irq_domain *d, -+ unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ar71xx_pci_controller *apc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); -+ irq_set_chip_data(irq, apc); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ar71xx_pci_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ar71xx_pci_irq_map, -+}; -+ - static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) - { - void __iomem *base = ath79_reset_base; -- int i; - - __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); - __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); - -- BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); -- -- apc->irq_base = ATH79_PCI_IRQ_BASE; -- for (i = apc->irq_base; -- i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) { -- irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, -- handle_level_irq); -- irq_set_chip_data(i, apc); -- } -- -+ apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, -+ &ar71xx_pci_domain_ops, apc); - irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, - apc); - } -@@ -325,10 +337,14 @@ static void ar71xx_pci_reset(void) - mdelay(100); - } - -+static const struct of_device_id ar71xx_pci_ids[] = { -+ { .compatible = "qca,ar7100-pci" }, -+ {}, -+}; -+ - static int ar71xx_pci_probe(struct platform_device *pdev) - { - struct ar71xx_pci_controller *apc; -- struct resource *res; - u32 t; - - apc = devm_kzalloc(&pdev->dev, sizeof(struct ar71xx_pci_controller), -@@ -345,26 +361,6 @@ static int ar71xx_pci_probe(struct platf - if (apc->irq < 0) - return -EINVAL; - -- res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); -- if (!res) -- return -EINVAL; -- -- apc->io_res.parent = res; -- apc->io_res.name = "PCI IO space"; -- apc->io_res.start = res->start; -- apc->io_res.end = res->end; -- apc->io_res.flags = IORESOURCE_IO; -- -- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); -- if (!res) -- return -EINVAL; -- -- apc->mem_res.parent = res; -- apc->mem_res.name = "PCI memory space"; -- apc->mem_res.start = res->start; -- apc->mem_res.end = res->end; -- apc->mem_res.flags = IORESOURCE_MEM; -- - ar71xx_pci_reset(); - - /* setup COMMAND register */ -@@ -377,9 +373,11 @@ static int ar71xx_pci_probe(struct platf - - ar71xx_pci_irq_init(apc); - -+ apc->np = pdev->dev.of_node; - apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; - apc->pci_ctrl.mem_resource = &apc->mem_res; - apc->pci_ctrl.io_resource = &apc->io_res; -+ pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node); - - register_pci_controller(&apc->pci_ctrl); - -@@ -390,6 +388,7 @@ static struct platform_driver ar71xx_pci - .probe = ar71xx_pci_probe, - .driver = { - .name = "ar71xx-pci", -+ .of_match_table = of_match_ptr(ar71xx_pci_ids), - }, - }; - diff --git a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch deleted file mode 100644 index a32c9bdcde..0000000000 --- a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch +++ /dev/null @@ -1,61 +0,0 @@ -From ea27764bc3ef2a05decf3ae05edffc289cd0d93c Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 25 Jun 2018 15:52:02 +0200 -Subject: [PATCH 19/33] dt-bindings: PCI: qcom,ar7240: adds binding doc - -With the driver being converted from platform_data to pure OF, we need to -also add some docs. - -Cc: Rob Herring -Cc: devicetree@vger.kernel.org -Signed-off-by: John Crispin ---- - .../devicetree/bindings/pci/qcom,ar7240-pci.txt | 42 ++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt -@@ -0,0 +1,42 @@ -+* Qualcomm Atheros AR724X PCI express root complex -+ -+Required properties: -+- compatible: should contain "qcom,ar7240-pci" to identify the core. -+- reg: Should contain the register ranges as listed in the reg-names property. -+- reg-names: Definition: Must include the following entries -+ - "crp_base" Configuration registers -+ - "ctrl_base" Control registers -+ - "cfg_base" IO Memory -+- #address-cells: set to <3> -+- #size-cells: set to <2> -+- ranges: ranges for the PCI memory and I/O regions -+- interrupt-map-mask and interrupt-map: standard PCI -+ properties to define the mapping of the PCIe interface to interrupt -+ numbers. -+- #interrupt-cells: set to <1> -+- interrupt-parent: phandle to the MIPS IRQ controller -+ -+Optional properties: -+- interrupt-controller: define to enable the builtin IRQ cascade. -+ -+* Example for qca9557 -+ pcie@180c0000 { -+ compatible = "qcom,ar7240-pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ bus-range = <0x0 0x0>; -+ reg = <0x180c0000 0x1000>, -+ <0x180f0000 0x100>, -+ <0x14000000 0x1000>; -+ reg-names = "crp_base", "ctrl_base", "cfg_base"; -+ ranges = <0x2000000 0 0x10000000 0x10000000 0 0x04000000 -+ 0x1000000 0 0x00000000 0x00000000 0 0x00000001>; -+ interrupt-parent = <&intc2>; -+ interrupts = <1>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-map-mask = <0 0 0 1>; -+ interrupt-map = <0 0 0 0 &pcie0 0>; -+ }; diff --git a/target/linux/ath79/patches-5.15/313-MIPS-pci-ar724x-convert-to-OF.patch b/target/linux/ath79/patches-5.15/313-MIPS-pci-ar724x-convert-to-OF.patch deleted file mode 100644 index 7927c1cbf5..0000000000 --- a/target/linux/ath79/patches-5.15/313-MIPS-pci-ar724x-convert-to-OF.patch +++ /dev/null @@ -1,213 +0,0 @@ -From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 23 Jun 2018 15:07:37 +0200 -Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF - -With the ath79 target getting converted to pure OF, we can drop all the -platform data code and add the missing OF bits to the driver. We also add -a irq domain for the PCI/e controllers cascade, thus making it usable from -dts files. - -Signed-off-by: John Crispin ---- - arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------ - 1 file changed, 42 insertions(+), 46 deletions(-) - ---- a/arch/mips/pci/pci-ar724x.c -+++ b/arch/mips/pci/pci-ar724x.c -@@ -11,8 +11,11 @@ - #include - #include - #include -+#include - #include - #include -+#include -+#include - - #define AR724X_PCI_REG_APP 0x00 - #define AR724X_PCI_REG_RESET 0x18 -@@ -42,17 +45,20 @@ struct ar724x_pci_controller { - void __iomem *crp_base; - - int irq; -- int irq_base; - - bool link_up; - bool bar0_is_cached; - u32 bar0_value; - -+ struct device_node *np; - struct pci_controller pci_controller; -+ struct irq_domain *domain; - struct resource io_res; - struct resource mem_res; - }; - -+static struct irq_chip ar724x_pci_irq_chip; -+ - static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc) - { - u32 reset; -@@ -228,35 +234,31 @@ static struct pci_ops ar724x_pci_ops = { - - static void ar724x_pci_irq_handler(struct irq_desc *desc) - { -- struct ar724x_pci_controller *apc; -- void __iomem *base; -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc); - u32 pending; - -- apc = irq_desc_get_handler_data(desc); -- base = apc->ctrl_base; -- -- pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & -- __raw_readl(base + AR724X_PCI_REG_INT_MASK); -+ chained_irq_enter(chip, desc); -+ pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) & -+ __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK); - - if (pending & AR724X_PCI_INT_DEV0) -- generic_handle_irq(apc->irq_base + 0); -- -+ generic_handle_irq(irq_linear_revmap(apc->domain, 1)); - else - spurious_interrupt(); -+ chained_irq_exit(chip, desc); - } - - static void ar724x_pci_irq_unmask(struct irq_data *d) - { - struct ar724x_pci_controller *apc; - void __iomem *base; -- int offset; - u32 t; - - apc = irq_data_get_irq_chip_data(d); - base = apc->ctrl_base; -- offset = apc->irq_base - d->irq; - -- switch (offset) { -+ switch (irq_linear_revmap(apc->domain, d->irq)) { - case 0: - t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); - __raw_writel(t | AR724X_PCI_INT_DEV0, -@@ -270,14 +272,12 @@ static void ar724x_pci_irq_mask(struct i - { - struct ar724x_pci_controller *apc; - void __iomem *base; -- int offset; - u32 t; - - apc = irq_data_get_irq_chip_data(d); - base = apc->ctrl_base; -- offset = apc->irq_base - d->irq; - -- switch (offset) { -+ switch (irq_linear_revmap(apc->domain, d->irq)) { - case 0: - t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); - __raw_writel(t & ~AR724X_PCI_INT_DEV0, -@@ -302,26 +302,34 @@ static struct irq_chip ar724x_pci_irq_ch - .irq_mask_ack = ar724x_pci_irq_mask, - }; - -+static int ar724x_pci_irq_map(struct irq_domain *d, -+ unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ar724x_pci_controller *apc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq); -+ irq_set_chip_data(irq, apc); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ar724x_pci_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ar724x_pci_irq_map, -+}; -+ - static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc, - int id) - { - void __iomem *base; -- int i; - - base = apc->ctrl_base; - - __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); - __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); - -- apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT); -- -- for (i = apc->irq_base; -- i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) { -- irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, -- handle_level_irq); -- irq_set_chip_data(i, apc); -- } -- -+ apc->domain = irq_domain_add_linear(apc->np, 2, -+ &ar724x_pci_domain_ops, apc); - irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler, - apc); - } -@@ -360,7 +368,6 @@ static void ar724x_pci_hw_init(struct ar - static int ar724x_pci_probe(struct platform_device *pdev) - { - struct ar724x_pci_controller *apc; -- struct resource *res; - int id; - - id = pdev->id; -@@ -388,29 +395,11 @@ static int ar724x_pci_probe(struct platf - if (apc->irq < 0) - return -EINVAL; - -- res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); -- if (!res) -- return -EINVAL; -- -- apc->io_res.parent = res; -- apc->io_res.name = "PCI IO space"; -- apc->io_res.start = res->start; -- apc->io_res.end = res->end; -- apc->io_res.flags = IORESOURCE_IO; -- -- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); -- if (!res) -- return -EINVAL; -- -- apc->mem_res.parent = res; -- apc->mem_res.name = "PCI memory space"; -- apc->mem_res.start = res->start; -- apc->mem_res.end = res->end; -- apc->mem_res.flags = IORESOURCE_MEM; -- -+ apc->np = pdev->dev.of_node; - apc->pci_controller.pci_ops = &ar724x_pci_ops; - apc->pci_controller.io_resource = &apc->io_res; - apc->pci_controller.mem_resource = &apc->mem_res; -+ pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node); - - /* - * Do the full PCIE Root Complex Initialization Sequence if the PCIe -@@ -432,10 +421,16 @@ static int ar724x_pci_probe(struct platf - return 0; - } - -+static const struct of_device_id ar724x_pci_ids[] = { -+ { .compatible = "qcom,ar7240-pci" }, -+ {}, -+}; -+ - static struct platform_driver ar724x_pci_driver = { - .probe = ar724x_pci_probe, - .driver = { - .name = "ar724x-pci", -+ .of_match_table = of_match_ptr(ar724x_pci_ids), - }, - }; - diff --git a/target/linux/ath79/patches-5.15/314-MIPS-ath79-remove-irq-code-from-pci.patch b/target/linux/ath79/patches-5.15/314-MIPS-ath79-remove-irq-code-from-pci.patch deleted file mode 100644 index 01549eec68..0000000000 --- a/target/linux/ath79/patches-5.15/314-MIPS-ath79-remove-irq-code-from-pci.patch +++ /dev/null @@ -1,149 +0,0 @@ -From: John Crispin -Subject: ath79: fix remove irq code from pci driver patch - -This patch got mangled in the void while rebasing it. - -Submitted-by: John Crispin ---- - arch/mips/pci/pci-ar71xx.c | 107 ------------------ - 1 file changed, 141 deletions(-) - ---- a/arch/mips/pci/pci-ar71xx.c -+++ b/arch/mips/pci/pci-ar71xx.c -@@ -51,11 +51,9 @@ - struct ar71xx_pci_controller { - struct device_node *np; - void __iomem *cfg_base; -- int irq; - struct pci_controller pci_ctrl; - struct resource io_res; - struct resource mem_res; -- struct irq_domain *domain; - }; - - /* Byte lane enable bits */ -@@ -227,104 +225,6 @@ static struct pci_ops ar71xx_pci_ops = { - .write = ar71xx_pci_write_config, - }; - --static void ar71xx_pci_irq_handler(struct irq_desc *desc) --{ -- void __iomem *base = ath79_reset_base; -- struct irq_chip *chip = irq_desc_get_chip(desc); -- struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); -- u32 pending; -- -- chained_irq_enter(chip, desc); -- pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & -- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- -- if (pending & AR71XX_PCI_INT_DEV0) -- generic_handle_irq(irq_linear_revmap(apc->domain, 1)); -- -- else if (pending & AR71XX_PCI_INT_DEV1) -- generic_handle_irq(irq_linear_revmap(apc->domain, 2)); -- -- else if (pending & AR71XX_PCI_INT_DEV2) -- generic_handle_irq(irq_linear_revmap(apc->domain, 3)); -- -- else if (pending & AR71XX_PCI_INT_CORE) -- generic_handle_irq(irq_linear_revmap(apc->domain, 4)); -- -- else -- spurious_interrupt(); -- chained_irq_exit(chip, desc); --} -- --static void ar71xx_pci_irq_unmask(struct irq_data *d) --{ -- struct ar71xx_pci_controller *apc; -- unsigned int irq; -- void __iomem *base = ath79_reset_base; -- u32 t; -- -- apc = irq_data_get_irq_chip_data(d); -- irq = irq_linear_revmap(apc->domain, d->irq); -- -- t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- -- /* flush write */ -- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); --} -- --static void ar71xx_pci_irq_mask(struct irq_data *d) --{ -- struct ar71xx_pci_controller *apc; -- unsigned int irq; -- void __iomem *base = ath79_reset_base; -- u32 t; -- -- apc = irq_data_get_irq_chip_data(d); -- irq = irq_linear_revmap(apc->domain, d->irq); -- -- t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- -- /* flush write */ -- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); --} -- --static struct irq_chip ar71xx_pci_irq_chip = { -- .name = "AR71XX PCI", -- .irq_mask = ar71xx_pci_irq_mask, -- .irq_unmask = ar71xx_pci_irq_unmask, -- .irq_mask_ack = ar71xx_pci_irq_mask, --}; -- --static int ar71xx_pci_irq_map(struct irq_domain *d, -- unsigned int irq, irq_hw_number_t hw) --{ -- struct ar71xx_pci_controller *apc = d->host_data; -- -- irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); -- irq_set_chip_data(irq, apc); -- -- return 0; --} -- --static const struct irq_domain_ops ar71xx_pci_domain_ops = { -- .xlate = irq_domain_xlate_onecell, -- .map = ar71xx_pci_irq_map, --}; -- --static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) --{ -- void __iomem *base = ath79_reset_base; -- -- __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); -- __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); -- -- apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, -- &ar71xx_pci_domain_ops, apc); -- irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, -- apc); --} -- - static void ar71xx_pci_reset(void) - { - ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); -@@ -357,10 +257,6 @@ static int ar71xx_pci_probe(struct platf - if (IS_ERR(apc->cfg_base)) - return PTR_ERR(apc->cfg_base); - -- apc->irq = platform_get_irq(pdev, 0); -- if (apc->irq < 0) -- return -EINVAL; -- - ar71xx_pci_reset(); - - /* setup COMMAND register */ -@@ -371,8 +267,6 @@ static int ar71xx_pci_probe(struct platf - /* clear bus errors */ - ar71xx_pci_check_error(apc, 1); - -- ar71xx_pci_irq_init(apc); -- - apc->np = pdev->dev.of_node; - apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; - apc->pci_ctrl.mem_resource = &apc->mem_res; diff --git a/target/linux/ath79/patches-5.15/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch b/target/linux/ath79/patches-5.15/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch deleted file mode 100644 index 375dec8ba2..0000000000 --- a/target/linux/ath79/patches-5.15/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch +++ /dev/null @@ -1,130 +0,0 @@ -From: David Bauer -Date: Sat, 11 Apr 2020 14:03:12 +0200 -Subject: MIPS: pci-ar724x: add QCA9550 reset sequence - -The QCA9550 family of SoCs have a slightly different reset -sequence compared to older chips. - -Normally the bootloader performs this sequence, however -some bootloader implementation expect the operating system -to clear the reset. - -Also get the resets from OF to support handling of the second -PCIe root-complex on the QCA9558. - -Signed-off-by: David Bauer - ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -390,6 +390,7 @@ - #define QCA955X_PLL_CPU_CONFIG_REG 0x00 - #define QCA955X_PLL_DDR_CONFIG_REG 0x04 - #define QCA955X_PLL_CLK_CTRL_REG 0x08 -+#define QCA955X_PLL_PCIE_CONFIG_REG 0x0c - #define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 - #define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 - #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x4c -@@ -475,6 +476,9 @@ - #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) - #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) - -+#define QCA955X_PLL_PCIE_CONFIG_PLL_PWD BIT(30) -+#define QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS BIT(16) -+ - #define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB BIT(5) - #define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1 BIT(6) - #define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL BIT(7) ---- a/arch/mips/pci/pci-ar724x.c -+++ b/arch/mips/pci/pci-ar724x.c -@@ -8,6 +8,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -55,6 +56,9 @@ struct ar724x_pci_controller { - struct irq_domain *domain; - struct resource io_res; - struct resource mem_res; -+ -+ struct reset_control *hc_reset; -+ struct reset_control *phy_reset; - }; - - static struct irq_chip ar724x_pci_irq_chip; -@@ -340,18 +344,30 @@ static void ar724x_pci_hw_init(struct ar - int wait = 0; - - /* deassert PCIe host controller and PCIe PHY reset */ -- ath79_device_reset_clear(AR724X_RESET_PCIE); -- ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); -+ reset_control_deassert(apc->hc_reset); -+ reset_control_deassert(apc->phy_reset); - -- /* remove the reset of the PCIE PLL */ -- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); -- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; -- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); -- -- /* deassert bypass for the PCIE PLL */ -- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); -- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; -- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); -+ if (of_device_is_compatible(apc->np, "qcom,qca9550-pci")) { -+ /* remove the reset of the PCIE PLL */ -+ ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); -+ ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_PWD; -+ ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); -+ -+ /* deassert bypass for the PCIE PLL */ -+ ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); -+ ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS; -+ ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); -+ } else { -+ /* remove the reset of the PCIE PLL */ -+ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); -+ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; -+ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); -+ -+ /* deassert bypass for the PCIE PLL */ -+ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); -+ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; -+ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); -+ } - - /* set PCIE Application Control to ready */ - app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); -@@ -395,6 +411,14 @@ static int ar724x_pci_probe(struct platf - if (apc->irq < 0) - return -EINVAL; - -+ apc->hc_reset = devm_reset_control_get_exclusive(&pdev->dev, "hc"); -+ if (IS_ERR(apc->hc_reset)) -+ return PTR_ERR(apc->hc_reset); -+ -+ apc->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, "phy"); -+ if (IS_ERR(apc->phy_reset)) -+ return PTR_ERR(apc->phy_reset); -+ - apc->np = pdev->dev.of_node; - apc->pci_controller.pci_ops = &ar724x_pci_ops; - apc->pci_controller.io_resource = &apc->io_res; -@@ -405,7 +429,7 @@ static int ar724x_pci_probe(struct platf - * Do the full PCIE Root Complex Initialization Sequence if the PCIe - * host controller is in reset. - */ -- if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) -+ if (reset_control_status(apc->hc_reset)) - ar724x_pci_hw_init(apc); - - apc->link_up = ar724x_pci_check_link(apc); -@@ -423,6 +447,7 @@ static int ar724x_pci_probe(struct platf - - static const struct of_device_id ar724x_pci_ids[] = { - { .compatible = "qcom,ar7240-pci" }, -+ { .compatible = "qcom,qca9550-pci" }, - {}, - }; - diff --git a/target/linux/ath79/patches-5.15/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/target/linux/ath79/patches-5.15/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch deleted file mode 100644 index 1e2715b84c..0000000000 --- a/target/linux/ath79/patches-5.15/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch +++ /dev/null @@ -1,109 +0,0 @@ -From: Gabor Juhos -Subject: [PATCH] ar71xx: swizzle address for PCI byte/word access on AR71xx - -Closes #11683. - -SVN-Revision: 32639 ---- - .../mips/include/asm/mach-ath79/mangle-port.h | 111 ++++++++++++++++++ - 1 file changed, 111 insertions(+) - create mode 100644 arch/mips/include/asm/mach-ath79/mangle-port.h - ---- /dev/null -+++ b/arch/mips/include/asm/mach-ath79/mangle-port.h -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (C) 2012 Gabor Juhos -+ * -+ * This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h -+ * Copyright (C) 2003, 2004 Ralf Baechle -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_MACH_ATH79_MANGLE_PORT_H -+#define __ASM_MACH_ATH79_MANGLE_PORT_H -+ -+#ifdef CONFIG_PCI_AR71XX -+extern unsigned long (ath79_pci_swizzle_b)(unsigned long port); -+extern unsigned long (ath79_pci_swizzle_w)(unsigned long port); -+#else -+#define ath79_pci_swizzle_b(port) (port) -+#define ath79_pci_swizzle_w(port) (port) -+#endif -+ -+#define __swizzle_addr_b(port) ath79_pci_swizzle_b(port) -+#define __swizzle_addr_w(port) ath79_pci_swizzle_w(port) -+#define __swizzle_addr_l(port) (port) -+#define __swizzle_addr_q(port) (port) -+ -+# define ioswabb(a, x) (x) -+# define __mem_ioswabb(a, x) (x) -+# define ioswabw(a, x) (x) -+# define __mem_ioswabw(a, x) cpu_to_le16(x) -+# define ioswabl(a, x) (x) -+# define __mem_ioswabl(a, x) cpu_to_le32(x) -+# define ioswabq(a, x) (x) -+# define __mem_ioswabq(a, x) cpu_to_le64(x) -+ -+#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */ ---- a/arch/mips/pci/pci-ar71xx.c -+++ b/arch/mips/pci/pci-ar71xx.c -@@ -68,6 +68,45 @@ static const u32 ar71xx_pci_read_mask[8] - 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 - }; - -+static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port); -+static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port); -+ -+static inline bool ar71xx_is_pci_addr(unsigned long port) -+{ -+ unsigned long phys = CPHYSADDR(port); -+ -+ return (phys >= AR71XX_PCI_MEM_BASE && -+ phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE); -+} -+ -+static unsigned long ar71xx_pci_swizzle_b(unsigned long port) -+{ -+ return ar71xx_is_pci_addr(port) ? port ^ 3 : port; -+} -+ -+static unsigned long ar71xx_pci_swizzle_w(unsigned long port) -+{ -+ return ar71xx_is_pci_addr(port) ? port ^ 2 : port; -+} -+ -+unsigned long ath79_pci_swizzle_b(unsigned long port) -+{ -+ if (__ath79_pci_swizzle_b) -+ return __ath79_pci_swizzle_b(port); -+ -+ return port; -+} -+EXPORT_SYMBOL(ath79_pci_swizzle_b); -+ -+unsigned long ath79_pci_swizzle_w(unsigned long port) -+{ -+ if (__ath79_pci_swizzle_w) -+ return __ath79_pci_swizzle_w(port); -+ -+ return port; -+} -+EXPORT_SYMBOL(ath79_pci_swizzle_w); -+ - static inline u32 ar71xx_pci_get_ble(int where, int size, int local) - { - u32 t; -@@ -275,6 +314,9 @@ static int ar71xx_pci_probe(struct platf - - register_pci_controller(&apc->pci_ctrl); - -+ __ath79_pci_swizzle_b = ar71xx_pci_swizzle_b; -+ __ath79_pci_swizzle_w = ar71xx_pci_swizzle_w; -+ - return 0; - } - diff --git a/target/linux/ath79/patches-5.15/330-missing-registers.patch b/target/linux/ath79/patches-5.15/330-missing-registers.patch deleted file mode 100644 index 74789437ec..0000000000 --- a/target/linux/ath79/patches-5.15/330-missing-registers.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Christian Lamparter -Subject: [PATCH] ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for - - ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for AR9344 - - Signed-off-by: Christian Lamparter - ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -1231,6 +1231,10 @@ - #define AR934X_ETH_CFG_RDV_DELAY BIT(16) - #define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 - #define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 -+#define AR934X_ETH_CFG_TXD_DELAY_MASK 0x3 -+#define AR934X_ETH_CFG_TXD_DELAY_SHIFT 18 -+#define AR934X_ETH_CFG_TXE_DELAY_MASK 0x3 -+#define AR934X_ETH_CFG_TXE_DELAY_SHIFT 20 - - /* - * QCA953X GMAC Interface diff --git a/target/linux/ath79/patches-5.15/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch b/target/linux/ath79/patches-5.15/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch deleted file mode 100644 index c2f228dfe1..0000000000 --- a/target/linux/ath79/patches-5.15/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Mon, 18 Mar 2019 00:54:06 +0100 -Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers - -This adds missing GMAC register definitions for the Qualcomm Atheros -QCA955X series MIPS SoCs. - -They originate from the platforms U-Boot code and the AVM FRITZ!WLAN -Repeater 450E's GPL tarball. - -Signed-off-by: David Bauer ---- - .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++ - 1 file changed, 54 insertions(+) - ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -1251,7 +1251,12 @@ - */ - - #define QCA955X_GMAC_REG_ETH_CFG 0x00 -+#define QCA955X_GMAC_REG_SGMII_RESET 0x14 - #define QCA955X_GMAC_REG_SGMII_SERDES 0x18 -+#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c -+#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20 -+#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34 -+#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58 - - #define QCA955X_ETH_CFG_RGMII_EN BIT(0) - #define QCA955X_ETH_CFG_MII_GE0 BIT(1) -@@ -1273,9 +1278,58 @@ - #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 - #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 - -+#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0 -+#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0) -+#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1) -+#define QCA955X_SGMII_RESET_RX_125M_N BIT(2) -+#define QCA955X_SGMII_RESET_TX_125M_N BIT(3) -+#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4) -+ - #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15) - #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 - #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf -+ -+#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6) -+#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8) -+#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9) -+#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11) -+#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12) -+#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13) -+#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14) -+#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15) -+ -+#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0) -+#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2) -+#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3) -+#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4) -+#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5) -+#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6) -+#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7) -+ -+#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0 -+#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7 -+#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3) -+#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4) -+#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5) -+#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6 -+#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0 -+#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8) -+#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9) -+#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10) -+#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11) -+#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12) -+#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13) -+#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14) -+ -+#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff -+#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0 -+#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00 -+#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8 -+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000 -+#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16 -+#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000 -+#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24 -+ - /* - * QCA956X GMAC Interface - */ diff --git a/target/linux/ath79/patches-5.15/332-ath79-sgmii-config.patch b/target/linux/ath79/patches-5.15/332-ath79-sgmii-config.patch deleted file mode 100644 index a6a50e4a8a..0000000000 --- a/target/linux/ath79/patches-5.15/332-ath79-sgmii-config.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: David Bauer -Subject: [PATCH] ath79: force SGMII SerDes mode to MAC operation - -The mode on the SGMII SerDes on the QCA9563 is 1000 Base-X by default. -This only allows for 1000 Mbit/s links, however when used with an SGMII -PHY in 100 Mbit/s link mode, the link remains dead. - -This strictly has nothing to do with the SerDes calibration, however it -is done at the same point in the QCA reference U-Boot which is the -blueprint for everything happening here. As the current state is more or -less a hack, this should be fine. - -This fixes the issues outlined above on a TP-Link EAP-225 Outdoor. - -Reported-by: Tom Herbers -Tested-by: Tom Herbers -Submitted-by: David Bauer ---- - arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 1 + - 1 files changed, 1 insertion(+) - ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -1380,5 +1380,6 @@ - - #define QCA956X_SGMII_CONFIG_MODE_CTRL_SHIFT 0 - #define QCA956X_SGMII_CONFIG_MODE_CTRL_MASK 0x7 -+#define QCA956X_SGMII_CONFIG_MODE_CTRL_SGMII_MAC 0x2 - - #endif /* __ASM_MACH_AR71XX_REGS_H */ diff --git a/target/linux/ath79/patches-5.15/340-register_gpio_driver_earlier.patch b/target/linux/ath79/patches-5.15/340-register_gpio_driver_earlier.patch deleted file mode 100644 index a8680ceac4..0000000000 --- a/target/linux/ath79/patches-5.15/340-register_gpio_driver_earlier.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: John Crispin -Subject: ath79: Register GPIO driver earlier - -HACK: register the GPIO driver earlier to ensure that gpio_request calls -from mach files succeed. - -Submitted-by: John Crispin ---- - drivers/gpio/gpio-ath79.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/gpio/gpio-ath79.c -+++ b/drivers/gpio/gpio-ath79.c -@@ -297,7 +297,11 @@ static struct platform_driver ath79_gpio - .probe = ath79_gpio_probe, - }; - --module_platform_driver(ath79_gpio_driver); -+static int __init ath79_gpio_init(void) -+{ -+ return platform_driver_register(&ath79_gpio_driver); -+} -+postcore_initcall(ath79_gpio_init); - - MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support"); - MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/patches-5.15/350-MIPS-ath79-ath9k-exports.patch b/target/linux/ath79/patches-5.15/350-MIPS-ath79-ath9k-exports.patch deleted file mode 100644 index e460fe58f3..0000000000 --- a/target/linux/ath79/patches-5.15/350-MIPS-ath79-ath9k-exports.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: John Crispin -Subject: [PATCH] ath79: make ahb wifi work - -Submitted-by: John Crispin ---- - arch/mips/ath79/common.c | 3 +++ - mips/include/asm/mach-ath79/ath79.h | 1+ - 1 file changed, 4 insertions(+) - ---- a/arch/mips/ath79/common.c -+++ b/arch/mips/ath79/common.c -@@ -31,11 +31,13 @@ EXPORT_SYMBOL_GPL(ath79_ddr_freq); - - enum ath79_soc_type ath79_soc; - unsigned int ath79_soc_rev; -+EXPORT_SYMBOL_GPL(ath79_soc_rev); - - void __iomem *ath79_pll_base; - void __iomem *ath79_reset_base; - EXPORT_SYMBOL_GPL(ath79_reset_base); --static void __iomem *ath79_ddr_base; -+void __iomem *ath79_ddr_base; -+EXPORT_SYMBOL_GPL(ath79_ddr_base); - static void __iomem *ath79_ddr_wb_flush_base; - static void __iomem *ath79_ddr_pci_win_base; - ---- a/arch/mips/include/asm/mach-ath79/ath79.h -+++ b/arch/mips/include/asm/mach-ath79/ath79.h -@@ -149,6 +149,7 @@ void ath79_ddr_wb_flush(unsigned int reg - void ath79_ddr_set_pci_windows(void); - - extern void __iomem *ath79_pll_base; -+extern void __iomem *ath79_ddr_base; - extern void __iomem *ath79_reset_base; - - static inline void ath79_pll_wr(unsigned reg, u32 val) diff --git a/target/linux/ath79/patches-5.15/351-MIPS-ath79-common-exports.patch b/target/linux/ath79/patches-5.15/351-MIPS-ath79-common-exports.patch deleted file mode 100644 index befcf2d50f..0000000000 --- a/target/linux/ath79/patches-5.15/351-MIPS-ath79-common-exports.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Luiz Angelo Daros de Luca -Subject: [PATCH] ath79: export ath79_pll_base - -This symbol is declared as extern but nobody exported it. -Any module including arch/mips/include/asm/mach-ath79/ath79.h -will not build. Without this export, ag71xx.ko will not build -as a module and the build will fail like this: - -ERROR: modpost: "ath79_pll_base" [drivers/net/ethernet/atheros/ag71xx/ag71xx.ko] undefined! - -The ath79_pll_base symbol is accessed in the ath79_pll_wr() inline function. - ---- - arch/mips/ath79/common.c | 1 + - 1 file changed, 1 insertions(+) - ---- a/arch/mips/ath79/common.c -+++ b/arch/mips/ath79/common.c -@@ -34,6 +34,7 @@ unsigned int ath79_soc_rev; - EXPORT_SYMBOL_GPL(ath79_soc_rev); - - void __iomem *ath79_pll_base; -+EXPORT_SYMBOL_GPL(ath79_pll_base); - void __iomem *ath79_reset_base; - EXPORT_SYMBOL_GPL(ath79_reset_base); - void __iomem *ath79_ddr_base; diff --git a/target/linux/ath79/patches-5.15/360-MIPS-ath79-export-UART1-reference-clock.patch b/target/linux/ath79/patches-5.15/360-MIPS-ath79-export-UART1-reference-clock.patch deleted file mode 100644 index b24ff21692..0000000000 --- a/target/linux/ath79/patches-5.15/360-MIPS-ath79-export-UART1-reference-clock.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Daniel Golle -Subject: [PATCH] ath79: add support for Atheros AR934x HS UART - -AR934x chips also got the 'old' qca,ar9330-uart in addition to the -'new' ns16550a compatible one. Add support for UART1 clock selector as -well as device-tree bindings in ar934x.dtsi to make use of that uart. - -Reported-by: Piotr Dymacz -Submitted-by: Daniel Golle ---- - arch/mips/ath79/clock.c | 7 +++++++ - .../mips/include/asm/mach-ath79/ar71xx_regs.h | 1 + - include/dt-bindings/clock/ath79-clk.h | 3 ++- - 3 files changed, 10 insertions(+), 1 deletion(-) - ---- a/arch/mips/ath79/clock.c -+++ b/arch/mips/ath79/clock.c -@@ -40,6 +40,7 @@ static const char * const clk_names[ATH7 - [ATH79_CLK_AHB] = "ahb", - [ATH79_CLK_REF] = "ref", - [ATH79_CLK_MDIO] = "mdio", -+ [ATH79_CLK_UART1] = "uart1", - }; - - static const char * __init ath79_clk_name(int type) -@@ -344,6 +345,9 @@ static void __init ar934x_clocks_init(vo - if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) - ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000); - -+ if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL) -+ ath79_set_clk(ATH79_CLK_UART1, 100 * 1000 * 1000); -+ - iounmap(dpll_base); - } - -@@ -649,6 +653,9 @@ static void __init ath79_clocks_init_dt( - if (!clks[ATH79_CLK_MDIO]) - clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF]; - -+ if (!clks[ATH79_CLK_UART1]) -+ clks[ATH79_CLK_UART1] = clks[ATH79_CLK_REF]; -+ - if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { - pr_err("%pOF: could not register clk provider\n", np); - goto err_iounmap; ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -348,6 +348,7 @@ - #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) - - #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL BIT(6) -+#define AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL BIT(7) - - #define QCA953X_PLL_CPU_CONFIG_REG 0x00 - #define QCA953X_PLL_DDR_CONFIG_REG 0x04 ---- a/include/dt-bindings/clock/ath79-clk.h -+++ b/include/dt-bindings/clock/ath79-clk.h -@@ -11,7 +11,8 @@ - #define ATH79_CLK_AHB 2 - #define ATH79_CLK_REF 3 - #define ATH79_CLK_MDIO 4 -+#define ATH79_CLK_UART1 5 - --#define ATH79_CLK_END 5 -+#define ATH79_CLK_END 6 - - #endif /* __DT_BINDINGS_ATH79_CLK_H */ diff --git a/target/linux/ath79/patches-5.15/370-MIPS-ath79-sanitize-symbols.patch b/target/linux/ath79/patches-5.15/370-MIPS-ath79-sanitize-symbols.patch deleted file mode 100644 index 5eb23ba6c6..0000000000 --- a/target/linux/ath79/patches-5.15/370-MIPS-ath79-sanitize-symbols.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 3fc8585cf76022dba7496627074d42af88c30718 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sat, 23 Jun 2018 15:16:55 +0200 -Subject: [PATCH 32/33] MIPS: ath79: sanitize symbols - -We no longer need to select which SoCs are supported as the whole arch -code is always built. So lets drop all the SoC symbols - -Signed-off-by: John Crispin ---- - arch/mips/Kconfig | 2 ++ - arch/mips/ath79/Kconfig | 44 +++++--------------------------------------- - arch/mips/pci/Makefile | 2 +- - 3 files changed, 8 insertions(+), 40 deletions(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -258,6 +258,8 @@ config ATH79 - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_MIPS16 - select SYS_SUPPORTS_ZBOOT_UART_PROM -+ select HAVE_PCI -+ select USB_ARCH_HAS_EHCI - select USE_OF - select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM - help ---- a/arch/mips/ath79/Kconfig -+++ b/arch/mips/ath79/Kconfig -@@ -1,48 +1,14 @@ - # SPDX-License-Identifier: GPL-2.0 - if ATH79 - --config SOC_AR71XX -- select HAVE_PCI -- def_bool n -- --config SOC_AR724X -- select HAVE_PCI -- select PCI_AR724X if PCI -- def_bool n -- --config SOC_AR913X -- def_bool n -- --config SOC_AR933X -- def_bool n -- --config SOC_AR934X -- select HAVE_PCI -- select PCI_AR724X if PCI -- def_bool n -- --config SOC_QCA955X -- select HAVE_PCI -- select PCI_AR724X if PCI -+config PCI_AR71XX -+ bool "PCI support for AR7100 type SoCs" -+ depends on PCI - def_bool n - - config PCI_AR724X -- def_bool n -- --config ATH79_DEV_GPIO_BUTTONS -- def_bool n -- --config ATH79_DEV_LEDS_GPIO -- def_bool n -- --config ATH79_DEV_SPI -- def_bool n -- --config ATH79_DEV_USB -- def_bool n -- --config ATH79_DEV_WMAC -- depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X) -+ bool "PCI support for AR724x type SoCs" -+ depends on PCI - def_bool n - - endif ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o - ops-bcm63xx.o - obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o - obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o --obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o -+obj-$(CONFIG_PCI_AR71XX) += pci-ar71xx.o - obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o - obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xtalk-bridge.o - # diff --git a/target/linux/ath79/patches-5.15/400-mtd-nor-support-mtd-name-from-device-tree.patch b/target/linux/ath79/patches-5.15/400-mtd-nor-support-mtd-name-from-device-tree.patch deleted file mode 100644 index 36f5331bd0..0000000000 --- a/target/linux/ath79/patches-5.15/400-mtd-nor-support-mtd-name-from-device-tree.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f32bc2aa01edcba2f2ed5db151cf183eac9ef919 Mon Sep 17 00:00:00 2001 -From: Abhimanyu Vishwakarma -Date: Sat, 25 Feb 2017 16:42:50 +0000 -Subject: mtd: nor: support mtd name from device tree - -Signed-off-by: Abhimanyu Vishwakarma ---- - drivers/mtd/spi-nor/spi-nor.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/spi-nor/core.c -+++ b/drivers/mtd/spi-nor/core.c -@@ -3108,6 +3108,7 @@ int spi_nor_scan(struct spi_nor *nor, co - struct device *dev = nor->dev; - struct mtd_info *mtd = &nor->mtd; - struct device_node *np = spi_nor_get_flash_node(nor); -+ const char __maybe_unused *of_mtd_name = NULL; - int ret; - int i; - -@@ -3162,7 +3163,12 @@ int spi_nor_scan(struct spi_nor *nor, co - if (ret) - return ret; - -- if (!mtd->name) -+#ifdef CONFIG_MTD_OF_PARTS -+ of_property_read_string(np, "linux,mtd-name", &of_mtd_name); -+#endif -+ if (of_mtd_name) -+ mtd->name = of_mtd_name; -+ else if (!mtd->name) - mtd->name = dev_name(dev); - mtd->priv = nor; - mtd->type = MTD_NORFLASH; ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -870,6 +870,17 @@ out_error: - */ - static void mtd_set_dev_defaults(struct mtd_info *mtd) - { -+#ifdef CONFIG_MTD_OF_PARTS -+ const char __maybe_unused *of_mtd_name = NULL; -+ struct device_node *np; -+ -+ np = mtd_get_of_node(mtd); -+ if (np && !mtd->name) { -+ of_property_read_string(np, "linux,mtd-name", &of_mtd_name); -+ if (of_mtd_name) -+ mtd->name = of_mtd_name; -+ } else -+#endif - if (mtd->dev.parent) { - if (!mtd->owner && mtd->dev.parent->driver) - mtd->owner = mtd->dev.parent->driver->owner; diff --git a/target/linux/ath79/patches-5.15/410-mtd-cybertan-trx-parser.patch b/target/linux/ath79/patches-5.15/410-mtd-cybertan-trx-parser.patch deleted file mode 100644 index 4e8e536e29..0000000000 --- a/target/linux/ath79/patches-5.15/410-mtd-cybertan-trx-parser.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Christian Lamparter -Subject: [PATCH] ath79: port cybertan_part from ar71xx - -This patch ports the cybertan_part code from ar71xx and converts the -driver to a DT-supported mtd parser. As a result, it will no longer -add the u-boot, nvram and art partitions, which were never part of -the special Cybertan header. - -Instead these partitions have to be specified in the DT, which has the -upside of making it possible to add properties (i.e.: read-only), labels -and references to these important partitions. - -Submitted-by: Christian Lamparter ---- - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/Kconfig | 8 ++++++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o - ofpart-y += ofpart_core.o - ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o - ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o -+obj-$(CONFIG_MTD_PARSER_CYBERTAN) += parser_cybertan.o - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -102,6 +102,14 @@ config MTD_OF_PARTS_LINKSYS_NS - two "firmware" partitions. Currently used firmware has to be detected - using CFE environment variable. - -+config MTD_PARSER_CYBERTAN -+ tristate "Parser for Cybertan format partitions" -+ depends on MTD && (ATH79 || COMPILE_TEST) -+ help -+ Cybertan has a proprietory header than encompasses a Broadcom trx -+ header. This driver will parse the header and take care of the -+ special offsets that result in the extra headers. -+ - config MTD_PARSER_IMAGETAG - tristate "Parser for BCM963XX Image Tag format partitions" - depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST diff --git a/target/linux/ath79/patches-5.15/420-drivers-link-spi-before-mtd.patch b/target/linux/ath79/patches-5.15/420-drivers-link-spi-before-mtd.patch deleted file mode 100644 index 0cd96909eb..0000000000 --- a/target/linux/ath79/patches-5.15/420-drivers-link-spi-before-mtd.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Gabor Juhos -Subject: [PATCH] ar71xx: Link SPI before MTD - -SVN-Revision: 22863 ---- - drivers/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -80,8 +80,8 @@ obj-y += scsi/ - obj-y += nvme/ - obj-$(CONFIG_ATA) += ata/ - obj-$(CONFIG_TARGET_CORE) += target/ --obj-$(CONFIG_MTD) += mtd/ - obj-$(CONFIG_SPI) += spi/ -+obj-$(CONFIG_MTD) += mtd/ - obj-$(CONFIG_SPMI) += spmi/ - obj-$(CONFIG_HSI) += hsi/ - obj-$(CONFIG_SLIMBUS) += slimbus/ diff --git a/target/linux/ath79/patches-5.15/430-mtd-ar934x-nand-driver.patch b/target/linux/ath79/patches-5.15/430-mtd-ar934x-nand-driver.patch deleted file mode 100644 index 63bc98e14c..0000000000 --- a/target/linux/ath79/patches-5.15/430-mtd-ar934x-nand-driver.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Gabor Juhos -Subject: ar71xx: ar934x_nfc: experimental NAND Flash Controller driver for AR934x - -SVN-Revision: 33385 ---- - drivers/mtd/nand/raw/Kconfig | 8 ++++++++ - drivers/mtd/nand/raw/Makefile | 1 + - 2 files changed, 9 insertions(+) - ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -555,4 +555,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE - load time (assuming you build diskonchip as a module) with the module - parameter "inftl_bbt_write=1". - -+config MTD_NAND_AR934X -+ tristate "Support for NAND controller on Qualcomm Atheros AR934x/QCA955x SoCs" -+ depends on ATH79 || COMPILE_TEST -+ depends on HAS_IOMEM -+ help -+ Enables support for NAND controller on Qualcomm Atheros SoCs. -+ This controller is found on AR934x and QCA955x SoCs. -+ - endif # MTD_RAW_NAND ---- a/drivers/mtd/nand/raw/Makefile -+++ b/drivers/mtd/nand/raw/Makefile -@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_ARASAN) += arasan - obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o - obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o - obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o -+obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o - - nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o - nand-objs += nand_onfi.o diff --git a/target/linux/ath79/patches-5.15/700-phy-add-ath79-usb-phys.patch b/target/linux/ath79/patches-5.15/700-phy-add-ath79-usb-phys.patch deleted file mode 100644 index 21b655a109..0000000000 --- a/target/linux/ath79/patches-5.15/700-phy-add-ath79-usb-phys.patch +++ /dev/null @@ -1,333 +0,0 @@ -From 08c9d6ceef01893678a5d2e8a15517c745417f21 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 6 Mar 2018 10:04:05 +0100 -Subject: [PATCH 04/27] phy: add ath79 usb phys - -Signed-off-by: John Crispin ---- - drivers/phy/Kconfig | 16 ++++++ - drivers/phy/Makefile | 2 + - drivers/phy/phy-ar7100-usb.c | 124 +++++++++++++++++++++++++++++++++++++++++++ - drivers/phy/phy-ar7200-usb.c | 108 +++++++++++++++++++++++++++++++++++++ - 4 files changed, 250 insertions(+) - create mode 100644 drivers/phy/phy-ar7100-usb.c - create mode 100644 drivers/phy/phy-ar7200-usb.c - ---- a/drivers/phy/Kconfig -+++ b/drivers/phy/Kconfig -@@ -24,6 +24,22 @@ config GENERIC_PHY_MIPI_DPHY - Provides a number of helpers a core functions for MIPI D-PHY - drivers to us. - -+config PHY_AR7100_USB -+ tristate "Atheros AR7100 USB PHY driver" -+ depends on ATH79 || COMPILE_TEST -+ default y if USB_EHCI_HCD_PLATFORM -+ select GENERIC_PHY -+ help -+ Enable this to support the USB PHY on Atheros AR7100 SoCs. -+ -+config PHY_AR7200_USB -+ tristate "Atheros AR7200 USB PHY driver" -+ depends on ATH79 || COMPILE_TEST -+ default y if USB_EHCI_HCD_PLATFORM -+ select GENERIC_PHY -+ help -+ Enable this to support the USB PHY on Atheros AR7200 SoCs. -+ - config PHY_LPC18XX_USB_OTG - tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" - depends on OF && (ARCH_LPC18XX || COMPILE_TEST) ---- a/drivers/phy/Makefile -+++ b/drivers/phy/Makefile -@@ -4,6 +4,8 @@ - # - - obj-$(CONFIG_GENERIC_PHY) += phy-core.o -+obj-$(CONFIG_PHY_AR7100_USB) += phy-ar7100-usb.o -+obj-$(CONFIG_PHY_AR7200_USB) += phy-ar7200-usb.o - obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o - obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o - obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o ---- /dev/null -+++ b/drivers/phy/phy-ar7100-usb.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct ar7100_usb_phy { -+ struct reset_control *rst_phy; -+ struct reset_control *rst_host; -+ struct reset_control *rst_ohci_dll; -+ void __iomem *io_base; -+ struct phy *phy; -+ int gpio; -+}; -+ -+static int ar7100_usb_phy_power_off(struct phy *phy) -+{ -+ struct ar7100_usb_phy *priv = phy_get_drvdata(phy); -+ int err = 0; -+ -+ err |= reset_control_assert(priv->rst_host); -+ err |= reset_control_assert(priv->rst_phy); -+ err |= reset_control_assert(priv->rst_ohci_dll); -+ -+ return err; -+} -+ -+static int ar7100_usb_phy_power_on(struct phy *phy) -+{ -+ struct ar7100_usb_phy *priv = phy_get_drvdata(phy); -+ int err = 0; -+ -+ err |= ar7100_usb_phy_power_off(phy); -+ mdelay(100); -+ err |= reset_control_deassert(priv->rst_ohci_dll); -+ err |= reset_control_deassert(priv->rst_phy); -+ err |= reset_control_deassert(priv->rst_host); -+ mdelay(500); -+ iowrite32(0xf0000, priv->io_base + AR71XX_USB_CTRL_REG_CONFIG); -+ iowrite32(0x20c00, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ); -+ -+ return err; -+} -+ -+static const struct phy_ops ar7100_usb_phy_ops = { -+ .power_on = ar7100_usb_phy_power_on, -+ .power_off = ar7100_usb_phy_power_off, -+ .owner = THIS_MODULE, -+}; -+ -+static int ar7100_usb_phy_probe(struct platform_device *pdev) -+{ -+ struct phy_provider *phy_provider; -+ struct resource *res; -+ struct ar7100_usb_phy *priv; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->io_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(priv->io_base)) -+ return PTR_ERR(priv->io_base); -+ -+ priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy"); -+ if (IS_ERR(priv->rst_phy)) { -+ dev_err(&pdev->dev, "phy reset is missing\n"); -+ return PTR_ERR(priv->rst_phy); -+ } -+ -+ priv->rst_host = devm_reset_control_get(&pdev->dev, "usb-host"); -+ if (IS_ERR(priv->rst_host)) { -+ dev_err(&pdev->dev, "host reset is missing\n"); -+ return PTR_ERR(priv->rst_host); -+ } -+ -+ priv->rst_ohci_dll = devm_reset_control_get(&pdev->dev, "usb-ohci-dll"); -+ if (IS_ERR(priv->rst_ohci_dll)) { -+ dev_err(&pdev->dev, "ohci-dll reset is missing\n"); -+ return PTR_ERR(priv->rst_host); -+ } -+ -+ priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7100_usb_phy_ops); -+ if (IS_ERR(priv->phy)) { -+ dev_err(&pdev->dev, "failed to create PHY\n"); -+ return PTR_ERR(priv->phy); -+ } -+ -+ priv->gpio = of_get_gpio(pdev->dev.of_node, 0); -+ if (priv->gpio >= 0) { -+ int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev)); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "failed to request gpio\n"); -+ return ret; -+ } -+ gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev)); -+ gpio_set_value(priv->gpio, 1); -+ } -+ -+ phy_set_drvdata(priv->phy, priv); -+ -+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); -+ -+ -+ return PTR_ERR_OR_ZERO(phy_provider); -+} -+ -+static const struct of_device_id ar7100_usb_phy_of_match[] = { -+ { .compatible = "qca,ar7100-usb-phy" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, ar7100_usb_phy_of_match); -+ -+static struct platform_driver ar7100_usb_phy_driver = { -+ .probe = ar7100_usb_phy_probe, -+ .driver = { -+ .of_match_table = ar7100_usb_phy_of_match, -+ .name = "ar7100-usb-phy", -+ } -+}; -+module_platform_driver(ar7100_usb_phy_driver); -+ -+MODULE_DESCRIPTION("ATH79 USB PHY driver"); -+MODULE_AUTHOR("Alban Bedel "); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/phy/phy-ar7200-usb.c -@@ -0,0 +1,136 @@ -+/* -+ * Copyright (C) 2015 Alban Bedel -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct ar7200_usb_phy { -+ struct reset_control *rst_phy; -+ struct reset_control *rst_phy_analog; -+ struct reset_control *suspend_override; -+ struct phy *phy; -+ int gpio; -+}; -+ -+static int ar7200_usb_phy_power_on(struct phy *phy) -+{ -+ struct ar7200_usb_phy *priv = phy_get_drvdata(phy); -+ int err = 0; -+ -+ if (priv->suspend_override) -+ err = reset_control_assert(priv->suspend_override); -+ if (priv->rst_phy) -+ err |= reset_control_deassert(priv->rst_phy); -+ if (priv->rst_phy_analog) -+ err |= reset_control_deassert(priv->rst_phy_analog); -+ -+ return err; -+} -+ -+static int ar7200_usb_phy_power_off(struct phy *phy) -+{ -+ struct ar7200_usb_phy *priv = phy_get_drvdata(phy); -+ int err = 0; -+ -+ if (priv->suspend_override) -+ err = reset_control_deassert(priv->suspend_override); -+ if (priv->rst_phy) -+ err |= reset_control_assert(priv->rst_phy); -+ if (priv->rst_phy_analog) -+ err |= reset_control_assert(priv->rst_phy_analog); -+ -+ return err; -+} -+ -+static const struct phy_ops ar7200_usb_phy_ops = { -+ .power_on = ar7200_usb_phy_power_on, -+ .power_off = ar7200_usb_phy_power_off, -+ .owner = THIS_MODULE, -+}; -+ -+static int ar7200_usb_phy_probe(struct platform_device *pdev) -+{ -+ struct phy_provider *phy_provider; -+ struct ar7200_usb_phy *priv; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy"); -+ if (IS_ERR(priv->rst_phy)) { -+ if (PTR_ERR(priv->rst_phy) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "phy reset is missing\n"); -+ return PTR_ERR(priv->rst_phy); -+ } -+ -+ priv->rst_phy_analog = devm_reset_control_get_optional( -+ &pdev->dev, "usb-phy-analog"); -+ if (IS_ERR(priv->rst_phy_analog)) { -+ if (PTR_ERR(priv->rst_phy_analog) == -ENOENT) -+ priv->rst_phy_analog = NULL; -+ else -+ return PTR_ERR(priv->rst_phy_analog); -+ } -+ -+ priv->suspend_override = devm_reset_control_get_optional( -+ &pdev->dev, "usb-suspend-override"); -+ if (IS_ERR(priv->suspend_override)) { -+ if (PTR_ERR(priv->suspend_override) == -ENOENT) -+ priv->suspend_override = NULL; -+ else -+ return PTR_ERR(priv->suspend_override); -+ } -+ -+ priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7200_usb_phy_ops); -+ if (IS_ERR(priv->phy)) { -+ dev_err(&pdev->dev, "failed to create PHY\n"); -+ return PTR_ERR(priv->phy); -+ } -+ -+ priv->gpio = of_get_gpio(pdev->dev.of_node, 0); -+ if (priv->gpio >= 0) { -+ int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev)); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "failed to request gpio\n"); -+ return ret; -+ } -+ gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev)); -+ gpio_set_value(priv->gpio, 1); -+ } -+ -+ phy_set_drvdata(priv->phy, priv); -+ -+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); -+ -+ return PTR_ERR_OR_ZERO(phy_provider); -+} -+ -+static const struct of_device_id ar7200_usb_phy_of_match[] = { -+ { .compatible = "qca,ar7200-usb-phy" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, ar7200_usb_phy_of_match); -+ -+static struct platform_driver ar7200_usb_phy_driver = { -+ .probe = ar7200_usb_phy_probe, -+ .driver = { -+ .of_match_table = ar7200_usb_phy_of_match, -+ .name = "ar7200-usb-phy", -+ } -+}; -+module_platform_driver(ar7200_usb_phy_driver); -+ -+MODULE_DESCRIPTION("ATH79 USB PHY driver"); -+MODULE_AUTHOR("Alban Bedel "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ath79/patches-5.15/701-usb-add-more-OF-quirk-properties.patch b/target/linux/ath79/patches-5.15/701-usb-add-more-OF-quirk-properties.patch deleted file mode 100644 index d6d8cb6952..0000000000 --- a/target/linux/ath79/patches-5.15/701-usb-add-more-OF-quirk-properties.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2201818e5bd33f389beceb3943fdfcf5a698fc5b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 6 Mar 2018 10:01:43 +0100 -Subject: [PATCH 05/27] usb: add more OF/quirk properties - -Signed-off-by: John Crispin ---- - drivers/usb/host/ehci-platform.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -277,6 +277,11 @@ static int ehci_platform_probe(struct pl - ehci = hcd_to_ehci(hcd); - - if (pdata == &ehci_platform_defaults && dev->dev.of_node) { -+ of_property_read_u32(dev->dev.of_node, "caps-offset", &pdata->caps_offset); -+ -+ if (of_property_read_bool(dev->dev.of_node, "has-synopsys-hc-bug")) -+ pdata->has_synopsys_hc_bug = 1; -+ - if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) - ehci->big_endian_mmio = 1; - diff --git a/target/linux/ath79/patches-5.15/710-net-use-downstream-ag71xx.patch b/target/linux/ath79/patches-5.15/710-net-use-downstream-ag71xx.patch deleted file mode 100644 index 54e64fb11c..0000000000 --- a/target/linux/ath79/patches-5.15/710-net-use-downstream-ag71xx.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: John Crispin -Subject: [PATCH] ath79: add new OF only target for QCA MIPS silicon - -This target aims to replace ar71xx mid-term. The big part that is still -missing is making the MMIO/AHB wifi work using OF. NAND and mikrotik -subtargets will follow. - -Submitted-by: John Crispin ---- - drivers/net/ethernet/atheros/Kconfig | 8 +------- - drivers/net/ethernet/atheros/Makefile | 2 +- - 2 files changed, 2 insertions(+), 8 deletions(-) - ---- a/drivers/net/ethernet/atheros/Kconfig -+++ b/drivers/net/ethernet/atheros/Kconfig -@@ -17,14 +17,7 @@ config NET_VENDOR_ATHEROS - - if NET_VENDOR_ATHEROS - --config AG71XX -- tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support" -- depends on ATH79 -- select PHYLINK -- imply NET_SELFTESTS -- help -- If you wish to compile a kernel for AR7XXX/91XXX and enable -- ethernet support, then you should always answer Y to this. -+source "drivers/net/ethernet/atheros/ag71xx/Kconfig" - - config ATL2 - tristate "Atheros L2 Fast Ethernet support" ---- a/drivers/net/ethernet/atheros/Makefile -+++ b/drivers/net/ethernet/atheros/Makefile -@@ -3,7 +3,7 @@ - # Makefile for the Atheros network device drivers. - # - --obj-$(CONFIG_AG71XX) += ag71xx.o -+obj-$(CONFIG_AG71XX) += ag71xx/ - obj-$(CONFIG_ATL1) += atlx/ - obj-$(CONFIG_ATL2) += atlx/ - obj-$(CONFIG_ATL1E) += atl1e/ diff --git a/target/linux/ath79/patches-5.15/720-mdio_bitbang_ignore_ta_value.patch b/target/linux/ath79/patches-5.15/720-mdio_bitbang_ignore_ta_value.patch deleted file mode 100644 index 5363bb37b0..0000000000 --- a/target/linux/ath79/patches-5.15/720-mdio_bitbang_ignore_ta_value.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Jonas Gorski -Subject: ar71xx: add a workaround for ar8316 not always driving the TA bit to low - -AR8316 behind a GPIO bitbanged MDIO bus fails to drive the turnaround bit -to low despite returning a valid value. Ignore it and just use the -returned value anyway. - -SVN-Revision: 28422 ---- - drivers/net/mdio/mdio-bitbang.c | 16 ++----------------- - 1 file changed, 2 insertions(+), 14 deletions(-) - ---- a/drivers/net/mdio/mdio-bitbang.c -+++ b/drivers/net/mdio/mdio-bitbang.c -@@ -152,7 +152,7 @@ static int mdiobb_cmd_addr(struct mdiobb - int mdiobb_read(struct mii_bus *bus, int phy, int reg) - { - struct mdiobb_ctrl *ctrl = bus->priv; -- int ret, i; -+ int ret; - - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); -@@ -162,19 +162,7 @@ int mdiobb_read(struct mii_bus *bus, int - - ctrl->ops->set_mdio_dir(ctrl, 0); - -- /* check the turnaround bit: the PHY should be driving it to zero, if this -- * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that -- */ -- if (mdiobb_get_bit(ctrl) != 0 && -- !(bus->phy_ignore_ta_mask & (1 << phy))) { -- /* PHY didn't drive TA low -- flush any bits it -- * may be trying to send. -- */ -- for (i = 0; i < 32; i++) -- mdiobb_get_bit(ctrl); -- -- return 0xffff; -- } -+ mdiobb_get_bit(ctrl); - - ret = mdiobb_get_num(ctrl, 16); - mdiobb_get_bit(ctrl); diff --git a/target/linux/ath79/patches-5.15/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ath79/patches-5.15/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch deleted file mode 100644 index e37d9a1f63..0000000000 --- a/target/linux/ath79/patches-5.15/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Tue, 16 Jun 2015 13:15:08 +0200 -Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command - -It seems some phys have some maximum timings for accessing the MDIO line, -resulting in bit errors under cpu stress. Prevent this from happening by -disabling interrupts when sending commands. - -Signed-off-by: Jonas Gorski ---- - drivers/net/mdio/mdio-bitbang.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/drivers/net/mdio/mdio-bitbang.c -+++ b/drivers/net/mdio/mdio-bitbang.c -@@ -14,6 +14,7 @@ - * Vitaly Bordug - */ - -+#include - #include - #include - #include -@@ -153,7 +154,9 @@ int mdiobb_read(struct mii_bus *bus, int - { - struct mdiobb_ctrl *ctrl = bus->priv; - int ret; -+ unsigned long flags; - -+ local_irq_save(flags); - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); -@@ -166,6 +169,7 @@ int mdiobb_read(struct mii_bus *bus, int - - ret = mdiobb_get_num(ctrl, 16); - mdiobb_get_bit(ctrl); -+ local_irq_restore(flags); - return ret; - } - EXPORT_SYMBOL(mdiobb_read); -@@ -173,7 +177,9 @@ EXPORT_SYMBOL(mdiobb_read); - int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) - { - struct mdiobb_ctrl *ctrl = bus->priv; -+ unsigned long flags; - -+ local_irq_save(flags); - if (reg & MII_ADDR_C45) { - reg = mdiobb_cmd_addr(ctrl, phy, reg); - mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); -@@ -188,6 +194,8 @@ int mdiobb_write(struct mii_bus *bus, in - - ctrl->ops->set_mdio_dir(ctrl, 0); - mdiobb_get_bit(ctrl); -+ local_irq_restore(flags); -+ - return 0; - } - EXPORT_SYMBOL(mdiobb_write); diff --git a/target/linux/ath79/patches-5.15/730-ar8216-make-reg-access-atomic.patch b/target/linux/ath79/patches-5.15/730-ar8216-make-reg-access-atomic.patch deleted file mode 100644 index 02f763534e..0000000000 --- a/target/linux/ath79/patches-5.15/730-ar8216-make-reg-access-atomic.patch +++ /dev/null @@ -1,59 +0,0 @@ -From b3797d1a92afe97c173b00fdb7824cedba24eef0 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Sun, 20 Sep 2020 01:00:45 +0800 -Subject: [PATCH] ath79: ar8216: make switch register access atomic - -due to some unknown reason these register accesses sometimes fail -on the integrated switch without this patch. - -THIS ONLY WORKS ON ATH79 AND MAY BREAK THE DRIVER ON OTHER PLATFORMS! -The mdio bus on ath79 works in polling mode and doesn't rely on -any interrupt. This patch breaks the driver on any mdio master -with interrupts used. - ---- ---- a/drivers/net/phy/ar8216.c -+++ b/drivers/net/phy/ar8216.c -@@ -252,6 +252,7 @@ ar8xxx_mii_write32(struct ar8xxx_priv *p - u32 - ar8xxx_read(struct ar8xxx_priv *priv, int reg) - { -+ unsigned long flags; - struct mii_bus *bus = priv->mii_bus; - u16 r1, r2, page; - u32 val; -@@ -259,11 +260,13 @@ ar8xxx_read(struct ar8xxx_priv *priv, in - split_addr((u32) reg, &r1, &r2, &page); - - mutex_lock(&bus->mdio_lock); -+ local_irq_save(flags); - - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - val = ar8xxx_mii_read32(priv, 0x10 | r2, r1); - -+ local_irq_restore(flags); - mutex_unlock(&bus->mdio_lock); - - return val; -@@ -272,17 +275,20 @@ ar8xxx_read(struct ar8xxx_priv *priv, in - void - ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val) - { -+ unsigned long flags; - struct mii_bus *bus = priv->mii_bus; - u16 r1, r2, page; - - split_addr((u32) reg, &r1, &r2, &page); - - mutex_lock(&bus->mdio_lock); -+ local_irq_save(flags); - - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - ar8xxx_mii_write32(priv, 0x10 | r2, r1, val); - -+ local_irq_restore(flags); - mutex_unlock(&bus->mdio_lock); - } - diff --git a/target/linux/ath79/patches-5.15/800-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-5.15/800-leds-add-reset-controller-based-driver.patch deleted file mode 100644 index bbf8d7ef8c..0000000000 --- a/target/linux/ath79/patches-5.15/800-leds-add-reset-controller-based-driver.patch +++ /dev/null @@ -1,186 +0,0 @@ -From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 6 Mar 2018 10:03:03 +0100 -Subject: [PATCH 03/27] leds: add reset-controller based driver - -Signed-off-by: John Crispin ---- - drivers/leds/Kconfig | 11 ++++ - drivers/leds/Makefile | 1 + - drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 149 insertions(+) - create mode 100644 drivers/leds/leds-reset.c - ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -878,6 +878,17 @@ source "drivers/leds/blink/Kconfig" - comment "Flash and Torch LED drivers" - source "drivers/leds/flash/Kconfig" - -+config LEDS_RESET -+ tristate "LED support for reset-controller API" -+ depends on LEDS_CLASS -+ depends on RESET_CONTROLLER -+ help -+ This option enables support for LEDs connected to pins driven by reset -+ controllers. Yes, DNI actual built HW like that. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called leds-reset. -+ - comment "LED Triggers" - source "drivers/leds/trigger/Kconfig" - ---- /dev/null -+++ b/drivers/leds/leds-reset.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct reset_led_data { -+ struct led_classdev cdev; -+ struct reset_control *rst; -+}; -+ -+static inline struct reset_led_data * -+ cdev_to_reset_led_data(struct led_classdev *led_cdev) -+{ -+ return container_of(led_cdev, struct reset_led_data, cdev); -+} -+ -+static void reset_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); -+ -+ if (value == LED_OFF) -+ reset_control_assert(led_dat->rst); -+ else -+ reset_control_deassert(led_dat->rst); -+} -+ -+struct reset_leds_priv { -+ int num_leds; -+ struct reset_led_data leds[]; -+}; -+ -+static inline int sizeof_reset_leds_priv(int num_leds) -+{ -+ return sizeof(struct reset_leds_priv) + -+ (sizeof(struct reset_led_data) * num_leds); -+} -+ -+static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *child; -+ struct reset_leds_priv *priv; -+ int count, ret; -+ -+ count = device_get_child_node_count(dev); -+ if (!count) -+ return ERR_PTR(-ENODEV); -+ -+ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); -+ if (!priv) -+ return ERR_PTR(-ENOMEM); -+ -+ device_for_each_child_node(dev, child) { -+ struct reset_led_data *led = &priv->leds[priv->num_leds]; -+ struct device_node *np = to_of_node(child); -+ -+ ret = fwnode_property_read_string(child, "label", &led->cdev.name); -+ if (!led->cdev.name) { -+ fwnode_handle_put(child); -+ return ERR_PTR(-EINVAL); -+ } -+ led->rst = __of_reset_control_get(np, NULL, 0, 0, 0, true); -+ if (IS_ERR(led->rst)) -+ return ERR_PTR(-EINVAL); -+ -+ fwnode_property_read_string(child, "linux,default-trigger", -+ &led->cdev.default_trigger); -+ -+ led->cdev.brightness_set = reset_led_set; -+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ led->cdev.dev->of_node = np; -+ priv->num_leds++; -+ } -+ -+ return priv; -+} -+ -+static const struct of_device_id of_reset_leds_match[] = { -+ { .compatible = "reset-leds", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, of_reset_leds_match); -+ -+static int reset_led_probe(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv; -+ -+ priv = reset_leds_create(pdev); -+ if (IS_ERR(priv)) -+ return PTR_ERR(priv); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static void reset_led_shutdown(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ struct reset_led_data *led = &priv->leds[i]; -+ -+ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) -+ reset_led_set(&led->cdev, LED_OFF); -+ } -+} -+ -+static struct platform_driver reset_led_driver = { -+ .probe = reset_led_probe, -+ .shutdown = reset_led_shutdown, -+ .driver = { -+ .name = "leds-reset", -+ .of_match_table = of_reset_leds_match, -+ }, -+}; -+ -+module_platform_driver(reset_led_driver); -+ -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("reset controller LED driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:leds-reset"); ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -87,6 +87,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds - obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o - obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o - obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o -+obj-$(CONFIG_LEDS_RESET) += leds-reset.o - - # LED SPI Drivers - obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o diff --git a/target/linux/ath79/patches-5.15/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-5.15/900-unaligned_access_hacks.patch deleted file mode 100644 index 3c15a016ff..0000000000 --- a/target/linux/ath79/patches-5.15/900-unaligned_access_hacks.patch +++ /dev/null @@ -1,900 +0,0 @@ -From: Felix Fietkau -Subject: [PATCH] ar71xx: fix unaligned access in a few more places - -SVN-Revision: 35130 ---- - arch/mips/include/asm/checksum.h | 83 +++--------------- - include/uapi/linux/ip.h | 2 +- - include/uapi/linux/ipv6.h | 2 +- - include/uapi/linux/tcp.h | 4 ++-- - include/uapi/linux/udp.h | 2 +- - net/netfilter/nf_conntrack_core.c | 4 ++-- - include/uapi/linux/icmp.h | 2 +- - include/uapi/linux/in6.h | 2 +- - net/ipv6/tcp_ipv6.c | 9 +++-- - net/ipv6/datagram.c | 6 ++-- - net/ipv6/exthdrs.c | 2 +- - include/linux/types.h | 5 +++ - net/ipv4/af_inet.c | 4 ++-- - net/ipv4/tcp_output.c | 69 +++++++++-------- - include/uapi/linux/igmp.h | 8 +++--- - net/core/flow_dissector.c | 2 +- - include/uapi/linux/icmpv6.h | 2 +- - include/net/ndisc.h | 10 ++++---- - net/sched/cls_u32.c | 6 +++--- - net/ipv6/ip6_offload.c | 2 +- - include/net/addrconf.h | 2 +- - include/net/inet_ecn.h | 4 ++-- - include/net/ipv6.h | 23 +++++---- - include/net/secure_seq.h | 1 + - include/uapi/linux/in.h | 2 +- - net/ipv6/ip6_fib.h | 2 +- - net/netfilter/nf_conntrack_proto_tcp.c | 2 +- - net/xfrm/xfrm_input.c | 4 ++-- - net/ipv4/tcp_input.c | 12 ++++--- - include/uapi/linux/if_pppox.h | 1 + - net/ipv6/netfilter/nf_log_ipv6.c | 4 ++-- - include/net/neighbour.h | 6 +++-- - include/uapi/linux/netfilter_arp/arp_tables.h | 2 +- - net/core/utils.c | 10 +++++-- - include/linux/etherdevice.h | 11 ++++--- - net/ipv4/tcp_offload.c | 6 +++--- - net/ipv6/netfilter/ip6table_mangle.c | 4 ++-- - 37 file changed, 171 insertions(+), 141 deletions(-) - ---- a/arch/mips/include/asm/checksum.h -+++ b/arch/mips/include/asm/checksum.h -@@ -100,26 +100,30 @@ static inline __sum16 ip_fast_csum(const - const unsigned int *stop = word + ihl; - unsigned int csum; - int carry; -+ unsigned int w; - -- csum = word[0]; -- csum += word[1]; -- carry = (csum < word[1]); -+ csum = net_hdr_word(word++); -+ -+ w = net_hdr_word(word++); -+ csum += w; -+ carry = (csum < w); - csum += carry; - -- csum += word[2]; -- carry = (csum < word[2]); -+ w = net_hdr_word(word++); -+ csum += w; -+ carry = (csum < w); - csum += carry; - -- csum += word[3]; -- carry = (csum < word[3]); -+ w = net_hdr_word(word++); -+ csum += w; -+ carry = (csum < w); - csum += carry; - -- word += 4; - do { -- csum += *word; -- carry = (csum < *word); -+ w = net_hdr_word(word++); -+ csum += w; -+ carry = (csum < w); - csum += carry; -- word++; - } while (word != stop); - - return csum_fold(csum); -@@ -182,74 +186,6 @@ static inline __sum16 ip_compute_csum(co - return csum_fold(csum_partial(buff, len, 0)); - } - --#define _HAVE_ARCH_IPV6_CSUM --static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, -- const struct in6_addr *daddr, -- __u32 len, __u8 proto, -- __wsum sum) --{ -- __wsum tmp; -- -- __asm__( -- " .set push # csum_ipv6_magic\n" -- " .set noreorder \n" -- " .set noat \n" -- " addu %0, %5 # proto (long in network byte order)\n" -- " sltu $1, %0, %5 \n" -- " addu %0, $1 \n" -- -- " addu %0, %6 # csum\n" -- " sltu $1, %0, %6 \n" -- " lw %1, 0(%2) # four words source address\n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 4(%2) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 8(%2) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 12(%2) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 0(%3) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 4(%3) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 8(%3) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " lw %1, 12(%3) \n" -- " addu %0, $1 \n" -- " addu %0, %1 \n" -- " sltu $1, %0, %1 \n" -- -- " addu %0, $1 # Add final carry\n" -- " .set pop" -- : "=&r" (sum), "=&r" (tmp) -- : "r" (saddr), "r" (daddr), -- "0" (htonl(len)), "r" (htonl(proto)), "r" (sum) -- : "memory"); -- -- return csum_fold(sum); --} -- - #include - #endif /* CONFIG_GENERIC_CSUM */ - ---- a/include/uapi/linux/ip.h -+++ b/include/uapi/linux/ip.h -@@ -106,7 +106,7 @@ struct iphdr { - __be32 daddr; - ); - /*The options start here. */ --}; -+} __attribute__((packed, aligned(2))); - - - struct ip_auth_hdr { ---- a/include/uapi/linux/ipv6.h -+++ b/include/uapi/linux/ipv6.h -@@ -135,7 +135,7 @@ struct ipv6hdr { - struct in6_addr saddr; - struct in6_addr daddr; - ); --}; -+} __attribute__((packed, aligned(2))); - - - /* index values for the variables in ipv6_devconf */ ---- a/include/uapi/linux/tcp.h -+++ b/include/uapi/linux/tcp.h -@@ -55,7 +55,7 @@ struct tcphdr { - __be16 window; - __sum16 check; - __be16 urg_ptr; --}; -+} __attribute__((packed, aligned(2))); - - /* - * The union cast uses a gcc extension to avoid aliasing problems -@@ -65,7 +65,7 @@ struct tcphdr { - union tcp_word_hdr { - struct tcphdr hdr; - __be32 words[5]; --}; -+} __attribute__((packed, aligned(2))); - - #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3]) - ---- a/include/uapi/linux/udp.h -+++ b/include/uapi/linux/udp.h -@@ -25,7 +25,7 @@ struct udphdr { - __be16 dest; - __be16 len; - __sum16 check; --}; -+} __attribute__((packed, aligned(2))); - - /* UDP socket options */ - #define UDP_CORK 1 /* Never send partially complete segments */ ---- a/net/netfilter/nf_conntrack_core.c -+++ b/net/netfilter/nf_conntrack_core.c -@@ -308,8 +308,8 @@ nf_ct_get_tuple(const struct sk_buff *sk - - switch (l3num) { - case NFPROTO_IPV4: -- tuple->src.u3.ip = ap[0]; -- tuple->dst.u3.ip = ap[1]; -+ tuple->src.u3.ip = net_hdr_word(ap++); -+ tuple->dst.u3.ip = net_hdr_word(ap); - break; - case NFPROTO_IPV6: - memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6)); ---- a/include/uapi/linux/icmp.h -+++ b/include/uapi/linux/icmp.h -@@ -102,7 +102,7 @@ struct icmphdr { - } frag; - __u8 reserved[4]; - } un; --}; -+} __attribute__((packed, aligned(2))); - - - /* ---- a/include/uapi/linux/in6.h -+++ b/include/uapi/linux/in6.h -@@ -43,7 +43,7 @@ struct in6_addr { - #define s6_addr16 in6_u.u6_addr16 - #define s6_addr32 in6_u.u6_addr32 - #endif --}; -+} __attribute__((packed, aligned(2))); - #endif /* __UAPI_DEF_IN6_ADDR */ - - #if __UAPI_DEF_SOCKADDR_IN6 ---- a/net/ipv6/tcp_ipv6.c -+++ b/net/ipv6/tcp_ipv6.c -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -944,10 +945,10 @@ static void tcp_v6_send_response(const s - topt = (__be32 *)(t1 + 1); - - if (tsecr) { -- *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | -- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); -- *topt++ = htonl(tsval); -- *topt++ = htonl(tsecr); -+ put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | -+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++); -+ put_unaligned_be32(tsval, topt++); -+ put_unaligned_be32(tsecr, topt++); - } - - if (mrst) ---- a/include/linux/ipv6.h -+++ b/include/linux/ipv6.h -@@ -6,6 +6,7 @@ - - #define ipv6_optlen(p) (((p)->hdrlen+1) << 3) - #define ipv6_authlen(p) (((p)->hdrlen+2) << 2) -+ - /* - * This structure contains configuration options per IPv6 link. - */ ---- a/net/ipv6/datagram.c -+++ b/net/ipv6/datagram.c -@@ -492,7 +492,7 @@ int ipv6_recv_error(struct sock *sk, str - ipv6_iface_scope_id(&sin->sin6_addr, - IP6CB(skb)->iif); - } else { -- ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), -+ ipv6_addr_set_v4mapped(net_hdr_word(nh + serr->addr_offset), - &sin->sin6_addr); - sin->sin6_scope_id = 0; - } -@@ -846,12 +846,12 @@ int ip6_datagram_send_ctl(struct net *ne - } - - if (fl6->flowlabel&IPV6_FLOWINFO_MASK) { -- if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { -+ if ((fl6->flowlabel^net_hdr_word(CMSG_DATA(cmsg)))&~IPV6_FLOWINFO_MASK) { - err = -EINVAL; - goto exit_f; - } - } -- fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); -+ fl6->flowlabel = IPV6_FLOWINFO_MASK & net_hdr_word(CMSG_DATA(cmsg)); - break; - - case IPV6_2292HOPOPTS: ---- a/net/ipv6/exthdrs.c -+++ b/net/ipv6/exthdrs.c -@@ -1002,7 +1002,7 @@ static bool ipv6_hop_jumbo(struct sk_buf - goto drop; - } - -- pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); -+ pkt_len = ntohl(net_hdr_word(nh + optoff + 2)); - if (pkt_len <= IPV6_MAXPLEN) { - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); ---- a/include/linux/types.h -+++ b/include/linux/types.h -@@ -231,5 +231,11 @@ typedef void (*swap_func_t)(void *a, voi - typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv); - typedef int (*cmp_func_t)(const void *a, const void *b); - -+struct net_hdr_word { -+ u32 words[1]; -+} __attribute__((packed, aligned(2))); -+ -+#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0]) -+ - #endif /* __ASSEMBLY__ */ - #endif /* _LINUX_TYPES_H */ ---- a/net/ipv4/af_inet.c -+++ b/net/ipv4/af_inet.c -@@ -1480,8 +1480,8 @@ struct sk_buff *inet_gro_receive(struct - if (unlikely(ip_fast_csum((u8 *)iph, 5))) - goto out_unlock; - -- id = ntohl(*(__be32 *)&iph->id); -- flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); -+ id = ntohl(net_hdr_word(&iph->id)); -+ flush = (u16)((ntohl(net_hdr_word(iph)) ^ skb_gro_len(skb)) | (id & ~IP_DF)); - id >>= 16; - - list_for_each_entry(p, head, list) { ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -609,48 +609,53 @@ static void tcp_options_write(__be32 *pt - u16 options = opts->options; /* mungable copy */ - - if (unlikely(OPTION_MD5 & options)) { -- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | -- (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | -+ (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); - /* overload cookie hash location */ - opts->hash_location = (__u8 *)ptr; - ptr += 4; - } - - if (unlikely(opts->mss)) { -- *ptr++ = htonl((TCPOPT_MSS << 24) | -- (TCPOLEN_MSS << 16) | -- opts->mss); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | -+ opts->mss); - } - - if (likely(OPTION_TS & options)) { - if (unlikely(OPTION_SACK_ADVERTISE & options)) { -- *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | -- (TCPOLEN_SACK_PERM << 16) | -- (TCPOPT_TIMESTAMP << 8) | -- TCPOLEN_TIMESTAMP); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_SACK_PERM << 24) | -+ (TCPOLEN_SACK_PERM << 16) | -+ (TCPOPT_TIMESTAMP << 8) | -+ TCPOLEN_TIMESTAMP); - options &= ~OPTION_SACK_ADVERTISE; - } else { -- *ptr++ = htonl((TCPOPT_NOP << 24) | -- (TCPOPT_NOP << 16) | -- (TCPOPT_TIMESTAMP << 8) | -- TCPOLEN_TIMESTAMP); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_NOP << 24) | -+ (TCPOPT_NOP << 16) | -+ (TCPOPT_TIMESTAMP << 8) | -+ TCPOLEN_TIMESTAMP); - } -- *ptr++ = htonl(opts->tsval); -- *ptr++ = htonl(opts->tsecr); -+ net_hdr_word(ptr++) = htonl(opts->tsval); -+ net_hdr_word(ptr++) = htonl(opts->tsecr); - } - - if (unlikely(OPTION_SACK_ADVERTISE & options)) { -- *ptr++ = htonl((TCPOPT_NOP << 24) | -- (TCPOPT_NOP << 16) | -- (TCPOPT_SACK_PERM << 8) | -- TCPOLEN_SACK_PERM); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_NOP << 24) | -+ (TCPOPT_NOP << 16) | -+ (TCPOPT_SACK_PERM << 8) | -+ TCPOLEN_SACK_PERM); - } - - if (unlikely(OPTION_WSCALE & options)) { -- *ptr++ = htonl((TCPOPT_NOP << 24) | -- (TCPOPT_WINDOW << 16) | -- (TCPOLEN_WINDOW << 8) | -- opts->ws); -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_NOP << 24) | -+ (TCPOPT_WINDOW << 16) | -+ (TCPOLEN_WINDOW << 8) | -+ opts->ws); - } - - if (unlikely(opts->num_sack_blocks)) { -@@ -658,16 +663,17 @@ static void tcp_options_write(__be32 *pt - tp->duplicate_sack : tp->selective_acks; - int this_sack; - -- *ptr++ = htonl((TCPOPT_NOP << 24) | -- (TCPOPT_NOP << 16) | -- (TCPOPT_SACK << 8) | -- (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * -+ net_hdr_word(ptr++) = -+ htonl((TCPOPT_NOP << 24) | -+ (TCPOPT_NOP << 16) | -+ (TCPOPT_SACK << 8) | -+ (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * - TCPOLEN_SACK_PERBLOCK))); - - for (this_sack = 0; this_sack < opts->num_sack_blocks; - ++this_sack) { -- *ptr++ = htonl(sp[this_sack].start_seq); -- *ptr++ = htonl(sp[this_sack].end_seq); -+ net_hdr_word(ptr++) = htonl(sp[this_sack].start_seq); -+ net_hdr_word(ptr++) = htonl(sp[this_sack].end_seq); - } - - tp->rx_opt.dsack = 0; -@@ -680,13 +686,14 @@ static void tcp_options_write(__be32 *pt - - if (foc->exp) { - len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; -- *ptr = htonl((TCPOPT_EXP << 24) | (len << 16) | -+ net_hdr_word(ptr) = -+ htonl((TCPOPT_EXP << 24) | (len << 16) | - TCPOPT_FASTOPEN_MAGIC); - p += TCPOLEN_EXP_FASTOPEN_BASE; - } else { - len = TCPOLEN_FASTOPEN_BASE + foc->len; -- *p++ = TCPOPT_FASTOPEN; -- *p++ = len; -+ net_hdr_word(p++) = TCPOPT_FASTOPEN; -+ net_hdr_word(p++) = len; - } - - memcpy(p, foc->val, foc->len); ---- a/include/uapi/linux/igmp.h -+++ b/include/uapi/linux/igmp.h -@@ -33,7 +33,7 @@ struct igmphdr { - __u8 code; /* For newer IGMP */ - __sum16 csum; - __be32 group; --}; -+} __attribute__((packed, aligned(2))); - - /* V3 group record types [grec_type] */ - #define IGMPV3_MODE_IS_INCLUDE 1 -@@ -49,7 +49,7 @@ struct igmpv3_grec { - __be16 grec_nsrcs; - __be32 grec_mca; - __be32 grec_src[0]; --}; -+} __attribute__((packed, aligned(2))); - - struct igmpv3_report { - __u8 type; -@@ -58,7 +58,7 @@ struct igmpv3_report { - __be16 resv2; - __be16 ngrec; - struct igmpv3_grec grec[0]; --}; -+} __attribute__((packed, aligned(2))); - - struct igmpv3_query { - __u8 type; -@@ -79,7 +79,7 @@ struct igmpv3_query { - __u8 qqic; - __be16 nsrcs; - __be32 srcs[0]; --}; -+} __attribute__((packed, aligned(2))); - - #define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ - #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ ---- a/net/core/flow_dissector.c -+++ b/net/core/flow_dissector.c -@@ -129,7 +129,7 @@ __be32 __skb_flow_get_ports(const struct - ports = __skb_header_pointer(skb, thoff + poff, - sizeof(_ports), data, hlen, &_ports); - if (ports) -- return *ports; -+ return (__be32)net_hdr_word(ports); - } - - return 0; ---- a/include/uapi/linux/icmpv6.h -+++ b/include/uapi/linux/icmpv6.h -@@ -78,7 +78,7 @@ struct icmp6hdr { - #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other - #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime - #define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref --}; -+} __attribute__((packed, aligned(2))); - - - #define ICMPV6_ROUTER_PREF_LOW 0x3 ---- a/include/net/ndisc.h -+++ b/include/net/ndisc.h -@@ -93,7 +93,7 @@ struct ra_msg { - struct icmp6hdr icmph; - __be32 reachable_time; - __be32 retrans_timer; --}; -+} __attribute__((packed, aligned(2))); - - struct rd_msg { - struct icmp6hdr icmph; -@@ -372,10 +372,10 @@ static inline u32 ndisc_hashfn(const voi - { - const u32 *p32 = pkey; - -- return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) + -- (p32[1] * hash_rnd[1]) + -- (p32[2] * hash_rnd[2]) + -- (p32[3] * hash_rnd[3])); -+ return (((net_hdr_word(&p32[0]) ^ hash32_ptr(dev)) * hash_rnd[0]) + -+ (net_hdr_word(&p32[1]) * hash_rnd[1]) + -+ (net_hdr_word(&p32[2]) * hash_rnd[2]) + -+ (net_hdr_word(&p32[3]) * hash_rnd[3])); - } - - static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) ---- a/net/sched/cls_u32.c -+++ b/net/sched/cls_u32.c -@@ -155,7 +155,7 @@ next_knode: - data = skb_header_pointer(skb, toff, 4, &hdata); - if (!data) - goto out; -- if ((*data ^ key->val) & key->mask) { -+ if ((net_hdr_word(data) ^ key->val) & key->mask) { - n = rcu_dereference_bh(n->next); - goto next_knode; - } -@@ -206,8 +206,8 @@ check_terminal: - &hdata); - if (!data) - goto out; -- sel = ht->divisor & u32_hash_fold(*data, &n->sel, -- n->fshift); -+ sel = ht->divisor & u32_hash_fold(net_hdr_word(data), -+ &n->sel, n->fshift); - } - if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT))) - goto next_ht; ---- a/net/ipv6/ip6_offload.c -+++ b/net/ipv6/ip6_offload.c -@@ -241,7 +241,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff * - continue; - - iph2 = (struct ipv6hdr *)(p->data + off); -- first_word = *(__be32 *)iph ^ *(__be32 *)iph2; -+ first_word = net_hdr_word(iph) ^ net_hdr_word(iph2); - - /* All fields must match except length and Traffic Class. - * XXX skbs on the gro_list have all been parsed and pulled ---- a/include/net/addrconf.h -+++ b/include/net/addrconf.h -@@ -52,7 +52,7 @@ struct prefix_info { - __be32 reserved2; - - struct in6_addr prefix; --}; -+} __attribute__((packed, aligned(2))); - - /* rfc4861 4.6.2: IPv6 PIO is 32 bytes in size */ - static_assert(sizeof(struct prefix_info) == 32); ---- a/include/net/inet_ecn.h -+++ b/include/net/inet_ecn.h -@@ -138,9 +138,9 @@ static inline int IP6_ECN_set_ce(struct - if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) - return 0; - -- from = *(__be32 *)iph; -+ from = net_hdr_word(iph); - to = from | htonl(INET_ECN_CE << 20); -- *(__be32 *)iph = to; -+ net_hdr_word(iph) = to; - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), - (__force __wsum)to); ---- a/include/net/ipv6.h -+++ b/include/net/ipv6.h -@@ -147,7 +147,7 @@ struct frag_hdr { - __u8 reserved; - __be16 frag_off; - __be32 identification; --}; -+} __attribute__((packed, aligned(2))); - - #define IP6_MF 0x0001 - #define IP6_OFFSET 0xFFF8 -@@ -561,8 +561,8 @@ static inline void __ipv6_addr_set_half( - } - #endif - #endif -- addr[0] = wh; -- addr[1] = wl; -+ net_hdr_word(&addr[0]) = wh; -+ net_hdr_word(&addr[1]) = wl; - } - - static inline void ipv6_addr_set(struct in6_addr *addr, -@@ -621,6 +621,8 @@ static inline bool ipv6_prefix_equal(con - const __be32 *a1 = addr1->s6_addr32; - const __be32 *a2 = addr2->s6_addr32; - unsigned int pdw, pbi; -+ /* Used for last <32-bit fraction of prefix */ -+ u32 pbia1, pbia2; - - /* check complete u32 in prefix */ - pdw = prefixlen >> 5; -@@ -629,7 +631,9 @@ static inline bool ipv6_prefix_equal(con - - /* check incomplete u32 in prefix */ - pbi = prefixlen & 0x1f; -- if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) -+ pbia1 = net_hdr_word(&a1[pdw]); -+ pbia2 = net_hdr_word(&a2[pdw]); -+ if (pbi && ((pbia1 ^ pbia2) & htonl((0xffffffff) << (32 - pbi)))) - return false; - - return true; -@@ -746,13 +750,13 @@ static inline void ipv6_addr_set_v4mappe - */ - static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen) - { -- const __be32 *a1 = token1, *a2 = token2; -+ const struct in6_addr *a1 = token1, *a2 = token2; - int i; - - addrlen >>= 2; - - for (i = 0; i < addrlen; i++) { -- __be32 xb = a1[i] ^ a2[i]; -+ __be32 xb = a1->s6_addr32[i] ^ a2->s6_addr32[i]; - if (xb) - return i * 32 + 31 - __fls(ntohl(xb)); - } -@@ -946,17 +950,18 @@ static inline u32 ip6_multipath_hash_fie - static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass, - __be32 flowlabel) - { -- *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel; -+ net_hdr_word((__be32 *)hdr) = -+ htonl(0x60000000 | (tclass << 20)) | flowlabel; - } - - static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) - { -- return *(__be32 *)hdr & IPV6_FLOWINFO_MASK; -+ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK; - } - - static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) - { -- return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; -+ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK; - } - - static inline u8 ip6_tclass(__be32 flowinfo) ---- a/include/net/secure_seq.h -+++ b/include/net/secure_seq.h -@@ -3,6 +3,7 @@ - #define _NET_SECURE_SEQ - - #include -+#include - - u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); - u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, ---- a/include/uapi/linux/in.h -+++ b/include/uapi/linux/in.h -@@ -88,7 +88,7 @@ enum { - /* Internet address. */ - struct in_addr { - __be32 s_addr; --}; -+} __attribute__((packed, aligned(2))); - #endif - - #define IP_TOS 1 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -141,7 +141,7 @@ static __be32 addr_bit_set(const void *t - * See include/asm-generic/bitops/le.h. - */ - return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & -- addr[fn_bit >> 5]; -+ net_hdr_word(&addr[fn_bit >> 5]); - } - - struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh) ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -400,7 +400,7 @@ static void tcp_sack(const struct sk_buf - - /* Fast path for timestamp-only option */ - if (length == TCPOLEN_TSTAMP_ALIGNED -- && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24) -+ && net_hdr_word(ptr) == htonl((TCPOPT_NOP << 24) - | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) - | TCPOLEN_TIMESTAMP)) ---- a/net/xfrm/xfrm_input.c -+++ b/net/xfrm/xfrm_input.c -@@ -167,8 +167,8 @@ int xfrm_parse_spi(struct sk_buff *skb, - if (!pskb_may_pull(skb, hlen)) - return -EINVAL; - -- *spi = *(__be32 *)(skb_transport_header(skb) + offset); -- *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); -+ *spi = net_hdr_word(skb_transport_header(skb) + offset); -+ *seq = net_hdr_word(skb_transport_header(skb) + offset_seq); - return 0; - } - EXPORT_SYMBOL(xfrm_parse_spi); ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -4175,14 +4175,16 @@ static bool tcp_parse_aligned_timestamp( - { - const __be32 *ptr = (const __be32 *)(th + 1); - -- if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) -- | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { -+ if (net_hdr_word(ptr) == -+ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | -+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { - tp->rx_opt.saw_tstamp = 1; - ++ptr; -- tp->rx_opt.rcv_tsval = ntohl(*ptr); -+ tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr); - ++ptr; -- if (*ptr) -- tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset; -+ if (net_hdr_word(ptr)) -+ tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) - -+ tp->tsoffset; - else - tp->rx_opt.rcv_tsecr = 0; - return true; ---- a/include/uapi/linux/if_pppox.h -+++ b/include/uapi/linux/if_pppox.h -@@ -51,6 +51,7 @@ struct pppoe_addr { - */ - struct pptp_addr { - __u16 call_id; -+ __u16 pad; - struct in_addr sin_addr; - }; - ---- a/include/net/neighbour.h -+++ b/include/net/neighbour.h -@@ -270,8 +270,10 @@ static inline bool neigh_key_eq128(const - const u32 *n32 = (const u32 *)n->primary_key; - const u32 *p32 = pkey; - -- return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | -- (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; -+ return ((n32[0] ^ net_hdr_word(&p32[0])) | -+ (n32[1] ^ net_hdr_word(&p32[1])) | -+ (n32[2] ^ net_hdr_word(&p32[2])) | -+ (n32[3] ^ net_hdr_word(&p32[3]))) == 0; - } - - static inline struct neighbour *___neigh_lookup_noref( ---- a/include/uapi/linux/netfilter_arp/arp_tables.h -+++ b/include/uapi/linux/netfilter_arp/arp_tables.h -@@ -70,7 +70,7 @@ struct arpt_arp { - __u8 flags; - /* Inverse flags */ - __u16 invflags; --}; -+} __attribute__((aligned(4))); - - /* Values for "flag" field in struct arpt_ip (general arp structure). - * No flags defined yet. ---- a/net/core/utils.c -+++ b/net/core/utils.c -@@ -460,8 +460,14 @@ void inet_proto_csum_replace16(__sum16 * - bool pseudohdr) - { - __be32 diff[] = { -- ~from[0], ~from[1], ~from[2], ~from[3], -- to[0], to[1], to[2], to[3], -+ ~net_hdr_word(&from[0]), -+ ~net_hdr_word(&from[1]), -+ ~net_hdr_word(&from[2]), -+ ~net_hdr_word(&from[3]), -+ net_hdr_word(&to[0]), -+ net_hdr_word(&to[1]), -+ net_hdr_word(&to[2]), -+ net_hdr_word(&to[3]), - }; - if (skb->ip_summed != CHECKSUM_PARTIAL) { - *sum = csum_fold(csum_partial(diff, sizeof(diff), ---- a/include/linux/etherdevice.h -+++ b/include/linux/etherdevice.h -@@ -525,7 +525,7 @@ static inline bool is_etherdev_addr(cons - * @b: Pointer to Ethernet header - * - * Compare two Ethernet headers, returns 0 if equal. -- * This assumes that the network header (i.e., IP header) is 4-byte -+ * This assumes that the network header (i.e., IP header) is 2-byte - * aligned OR the platform can handle unaligned access. This is the - * case for all packets coming into netif_receive_skb or similar - * entry points. -@@ -548,11 +548,12 @@ static inline unsigned long compare_ethe - fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); - return fold; - #else -- u32 *a32 = (u32 *)((u8 *)a + 2); -- u32 *b32 = (u32 *)((u8 *)b + 2); -+ const u16 *a16 = a; -+ const u16 *b16 = b; - -- return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | -- (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); -+ return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) | -+ (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) | -+ (a16[6] ^ b16[6]); - #endif - } - ---- a/net/ipv4/tcp_offload.c -+++ b/net/ipv4/tcp_offload.c -@@ -223,7 +223,7 @@ struct sk_buff *tcp_gro_receive(struct l - - th2 = tcp_hdr(p); - -- if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { -+ if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) { - NAPI_GRO_CB(p)->same_flow = 0; - continue; - } -@@ -241,8 +241,8 @@ found: - ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); - flush |= (__force int)(th->ack_seq ^ th2->ack_seq); - for (i = sizeof(*th); i < thlen; i += 4) -- flush |= *(u32 *)((u8 *)th + i) ^ -- *(u32 *)((u8 *)th2 + i); -+ flush |= net_hdr_word((u8 *)th + i) ^ -+ net_hdr_word((u8 *)th2 + i); - - /* When we receive our second frame we can made a decision on if we - * continue this flow as an atomic flow with a fixed ID or if we use ---- a/net/ipv6/netfilter/ip6table_mangle.c -+++ b/net/ipv6/netfilter/ip6table_mangle.c -@@ -44,7 +44,7 @@ ip6t_mangle_out(struct sk_buff *skb, con - hop_limit = ipv6_hdr(skb)->hop_limit; - - /* flowlabel and prio (includes version, which shouldn't change either */ -- flowlabel = *((u_int32_t *)ipv6_hdr(skb)); -+ flowlabel = net_hdr_word(ipv6_hdr(skb)); - - ret = ip6t_do_table(skb, state, priv); - -@@ -53,7 +53,7 @@ ip6t_mangle_out(struct sk_buff *skb, con - !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || - skb->mark != mark || - ipv6_hdr(skb)->hop_limit != hop_limit || -- flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { -+ flowlabel != net_hdr_word(ipv6_hdr(skb)))) { - err = ip6_route_me_harder(state->net, state->sk, skb); - if (err < 0) - ret = NF_DROP_ERR(err); diff --git a/target/linux/ath79/patches-5.15/910-mikrotik-rb4xx.patch b/target/linux/ath79/patches-5.15/910-mikrotik-rb4xx.patch deleted file mode 100644 index 16c8f11af7..0000000000 --- a/target/linux/ath79/patches-5.15/910-mikrotik-rb4xx.patch +++ /dev/null @@ -1,121 +0,0 @@ -From: Christopher Hill -Subject: [PATCH] ath79: add Mikrotik rb4xx series drivers - -This adds 3 Mikrotik rb4xx series drivers as follows: - -rb4xx-cpld: This is in the mfd subsystem, and is the parent CPLD device -that interfaces between the SoC SPI bus and its two children below. -rb4xx-gpio: This is the GPIO expander. -rb4xx-nand: This is the NAND driver. - -The history of this code comes in three phases. - -1. The first is a May 2015 attempt to push the equivalient ar71xx rb4xx -drivers upstream. See https://lore.kernel.org/patchwork/patch/940880/. - -Module-author: Gabor Juhos -Module-author: Imre Kaloz -Module-author: Bert Vermeulen - -2. Next several ar71xx patches were applied bringing the code current. - -commit 7bbf4117c6fe4b764d9d7c62fb2bcf6dd93bff2c -Submitted-by: Hauke Mehrtens - -commit af79fdbe4af32a287798b579141204bda056b8aa -commit 889272d92db689fd9c910243635e44c9d8323095 -commit e21cb649a235180563363b8af5ba8296b9ac0baa -commit 7c09fa4a7492ca436f2c94bd9a465b7c5bbeed6f -Submitted-by: Felix Fietkau - -3. Finally a heavy refactor to split the driver into the three new -subsystems, and updated to work with the device tree configuration, plus -updates and review feedback incorporated - -Reviewed-by: Thibaut VARÈNE -Submitted-by: Christopher Hill ---- - drivers/mfd/Kconfig | 8 ++++++++ - drivers/mfd/Makefile | 1 + - drivers/gpio/Kconfig | 6 ++++++ - drivers/gpio/Makefile | 1 + - drivers/mtd/nand/raw/Kconfig | 7 +++++++ - drivers/mtd/nand/raw/Makefile | 1 + - 6 files changed, 24 insertions(+) - ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -2177,6 +2177,14 @@ config RAVE_SP_CORE - Select this to get support for the Supervisory Processor - device found on several devices in RAVE line of hardware. - -+config MFD_RB4XX_CPLD -+ tristate "CPLD driver for Mikrotik RB4xx series boards" -+ select MFD_CORE -+ depends on ATH79 || COMPILE_TEST -+ help -+ Enables support for the CPLD chip (NAND & GPIO) on Mikrotik -+ Routerboard RB4xx series. -+ - config SGI_MFD_IOC3 - bool "SGI IOC3 core driver" - depends on PCI && MIPS && 64BIT ---- a/drivers/mfd/Makefile -+++ b/drivers/mfd/Makefile -@@ -267,6 +267,7 @@ obj-$(CONFIG_MFD_KHADAS_MCU) += khadas- - obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o - obj-$(CONFIG_MFD_QCOM_PM8008) += qcom-pm8008.o - -+obj-$(CONFIG_MFD_RB4XX_CPLD) += rb4xx-cpld.o - obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o - obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o - obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -1574,6 +1574,12 @@ config GPIO_SODAVILLE - help - Say Y here to support Intel Sodaville GPIO. - -+config GPIO_RB4XX -+ tristate "GPIO expander for Mikrotik RB4xx series boards" -+ depends on MFD_RB4XX_CPLD -+ help -+ GPIO driver for Mikrotik Routerboard RB4xx series. -+ - endmenu - - menu "SPI GPIO expanders" ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -122,6 +122,7 @@ obj-$(CONFIG_GPIO_PL061) += gpio-pl061. - obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o - obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o - obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o -+obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o - obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o - obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o - obj-$(CONFIG_GPIO_RDA) += gpio-rda.o ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -563,4 +563,11 @@ config MTD_NAND_AR934X - Enables support for NAND controller on Qualcomm Atheros SoCs. - This controller is found on AR934x and QCA955x SoCs. - -+config MTD_NAND_RB4XX -+ tristate "Support for NAND driver for Mikrotik RB4xx series boards" -+ depends on MFD_RB4XX_CPLD -+ help -+ Enables support for the NAND flash chip on Mikrotik Routerboard -+ RB4xx series. -+ - endif # MTD_RAW_NAND ---- a/drivers/mtd/nand/raw/Makefile -+++ b/drivers/mtd/nand/raw/Makefile -@@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_INTEL_LGM) += inte - obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o - obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o - obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o -+obj-$(CONFIG_MTD_NAND_RB4XX) += nand_rb4xx.o - - nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o - nand-objs += nand_onfi.o diff --git a/target/linux/ath79/patches-5.15/911-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.15/911-mikrotik-rb91x.patch deleted file mode 100644 index 94967bf674..0000000000 --- a/target/linux/ath79/patches-5.15/911-mikrotik-rb91x.patch +++ /dev/null @@ -1,97 +0,0 @@ -From: Denis Kalashnikov -Subject: [PATCH] ath79: add support for reset key on MikroTik RB912UAG-2HPnD - -On MikroTik RB91x board series a reset key shares SoC gpio -line #15 with NAND ALE and NAND IO7. So we need a custom -gpio driver to manage this non-trivial connection schema. -Also rb91x-nand needs to have an ability to disable a polling -of the key while it works with NAND. - -While we've been integrating rb91x-key into a firmware, we've -figured out that: -* In the gpio-latch driver we need to add a "cansleep" suffix to -several gpiolib calls, -* When gpio-latch and rb91x-nand fail to get a gpio and an error -is -EPROBE_DEFER, they shouldn't report about this, since this -actually is not an error and occurs when the gpio-latch probe -function is called before the rb91x-key probe. -We fix these related things here too. - -Submitted-by: Denis Kalashnikov -Reviewed-by: Sergey Ryazanov -Tested-by: Koen Vandeputte ---- - drivers/gpio/Kconfig | 11 +++++++++++ - drivers/gpio/Makefile | 2 ++ - drivers/mtd/nand/raw/Kconfig | 6 ++++++ - drivers/mtd/nand/raw/Makefile | 1 + - 7 files changed, 20 insertions(+) - ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -353,6 +353,13 @@ config GPIO_IXP4XX - IXP4xx series of chips. - - If unsure, say N. -+ -+config GPIO_LATCH -+ tristate "MikroTik RouterBOARD GPIO latch support" -+ depends on ATH79 -+ help -+ GPIO driver for latch on some MikroTik RouterBOARDs. -+ - config GPIO_LOGICVC - tristate "Xylon LogiCVC GPIO support" - depends on MFD_SYSCON && OF -@@ -529,6 +536,10 @@ config GPIO_ROCKCHIP - help - Say yes here to support GPIO on Rockchip SoCs. - -+config GPIO_RB91X_KEY -+ tristate "MikroTik RB91x board series reset key support" -+ depends on ATH79 -+ - config GPIO_SAMA5D2_PIOBU - tristate "SAMA5D2 PIOBU GPIO support" - depends on MFD_SYSCON ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -75,6 +75,7 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o - obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o - obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o - obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o -+obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o - obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o - obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o - obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o -@@ -123,6 +124,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio - obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o - obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o - obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o -+obj-$(CONFIG_GPIO_RB91X_KEY) += gpio-rb91x-key.o - obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o - obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o - obj-$(CONFIG_GPIO_RDA) += gpio-rda.o ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -570,4 +570,10 @@ config MTD_NAND_RB4XX - Enables support for the NAND flash chip on Mikrotik Routerboard - RB4xx series. - -+config MTD_NAND_RB91X -+ tristate "MikroTik RB91x NAND driver support" -+ depends on ATH79 && MTD_RAW_NAND -+ help -+ Enables support for the NAND flash chip on MikroTik RB91x series. -+ - endif # MTD_RAW_NAND ---- a/drivers/mtd/nand/raw/Makefile -+++ b/drivers/mtd/nand/raw/Makefile -@@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rock - obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o - obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o - obj-$(CONFIG_MTD_NAND_RB4XX) += nand_rb4xx.o -+obj-$(CONFIG_MTD_NAND_RB91X) += rb91x_nand.o - - nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o - nand-objs += nand_onfi.o From 33c812b6398951406914f060b07a511b22ae823f Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Wed, 13 Mar 2024 14:27:08 +0800 Subject: [PATCH 100/108] ath79: add missing kernel config symbols Refresh kernel configs to add the missing symbols. Signed-off-by: Shiji Yang --- target/linux/ath79/config-6.1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/ath79/config-6.1 b/target/linux/ath79/config-6.1 index e3119f99a1..f2a6969aa1 100644 --- a/target/linux/ath79/config-6.1 +++ b/target/linux/ath79/config-6.1 @@ -54,6 +54,7 @@ CONFIG_FWNODE_MDIO=y CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_FW_LOADER_SYSFS=y CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CMOS_UPDATE=y @@ -142,6 +143,7 @@ CONFIG_NEED_PER_CPU_KM=y CONFIG_NET_SELFTESTS=y CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_EARLY_FLATTREE=y @@ -162,12 +164,14 @@ CONFIG_PCI_DRIVERS_LEGACY=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y # CONFIG_PHY_AR7100_USB is not set # CONFIG_PHY_AR7200_USB is not set # CONFIG_PHY_ATH79_USB is not set CONFIG_PINCTRL=y CONFIG_PREEMPT_NONE_BUILD=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QCOM_NET_PHYLIB=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RATIONAL=y CONFIG_REGMAP=y From 694e6477848eade21851ec27d90c173b373099fc Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 13 Mar 2024 12:47:31 +0100 Subject: [PATCH 101/108] dnsmasq: reset PKG_RELEASE dnsmasq was recently updated to 2.90, but PKG_RELEASE was not reset to 1. Fixes: 838a27f64f56 ("dnsmasq: version 2.90") Signed-off-by: Robert Marko --- package/network/services/dnsmasq/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index d2de74d9da..9020278d53 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_UPSTREAM_VERSION:=2.90 PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION))) -PKG_RELEASE:=8 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq/ From 33d6ba5045023ee05ca884dc162dbd9202d8698e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 13 Mar 2024 18:43:28 +0000 Subject: [PATCH 102/108] generic: 5.15: mtk_eth_soc: backport fix for hang on link up Backport commit faa5f17fe2 ("kernel: mtk_eth_soc: release MAC_MCR_FORCE_LINK only when MAC is up") to Linux 5.15 as well. Signed-off-by: Daniel Golle --- ..._eth_soc-release-MAC_MCR_FORCE_LINK-.patch | 50 +++++++++++++++++++ ..._eth_soc-add-paths-and-SerDes-modes-.patch | 17 ++++--- 2 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 target/linux/generic/pending-5.15/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch diff --git a/target/linux/generic/pending-5.15/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch b/target/linux/generic/pending-5.15/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch new file mode 100644 index 0000000000..7e9ff5c25f --- /dev/null +++ b/target/linux/generic/pending-5.15/735-net-mediatek-mtk_eth_soc-release-MAC_MCR_FORCE_LINK-.patch @@ -0,0 +1,50 @@ +From ef5976ae4e117fae9a61bb3c0f8319a917a425ea Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 11 Mar 2024 17:43:28 +0000 +Subject: [PATCH] net: mediatek: mtk_eth_soc: release MAC_MCR_FORCE_LINK only when MAC is up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Clearing bit MAC_MCR_FORCE_LINK which forces the link down too early +can result in MAC ending up in a broken/blocked state. + +Fix this by handling this bit in the .mac_link_up and .mac_link_down +calls instead of in .mac_finish. + +Fixes: b8fc9f30821ec ("net: ethernet: mediatek: Add basic PHYLINK support") +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -619,8 +619,7 @@ static int mtk_mac_finish(struct phylink + mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr_new = mcr_cur; + mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | +- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK | +- MAC_MCR_RX_FIFO_CLR_DIS; ++ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_RX_FIFO_CLR_DIS; + + /* Only update control register when needed! */ + if (mcr_new != mcr_cur) +@@ -636,7 +635,7 @@ static void mtk_mac_link_down(struct phy + phylink_config); + u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); ++ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + +@@ -745,7 +744,7 @@ static void mtk_mac_link_up(struct phyli + if (rx_pause) + mcr |= MAC_MCR_FORCE_RX_FC; + +- mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN; ++ mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + diff --git a/target/linux/generic/pending-5.15/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-5.15/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index 29f565d312..61c23da821 100644 --- a/target/linux/generic/pending-5.15/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/target/linux/generic/pending-5.15/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -387,24 +387,25 @@ Signed-off-by: Daniel Golle return; err_phy: -@@ -634,10 +698,13 @@ static void mtk_mac_link_down(struct phy +@@ -633,10 +697,14 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); - u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + if (!mtk_interface_mode_is_xgmii(interface)) { -+ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); -+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); ++ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, MTK_MAC_MCR(mac->id)); ++ if (mtk_is_netsys_v3_or_greater(eth)) ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); + } else if (mac->id != MTK_GMAC1_ID) { + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id)); + } } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -709,13 +776,11 @@ static void mtk_set_queue_speed(struct m +@@ -708,13 +776,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -422,7 +423,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -749,6 +814,55 @@ static void mtk_mac_link_up(struct phyli +@@ -748,6 +814,55 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -478,7 +479,7 @@ Signed-off-by: Daniel Golle static const struct phylink_mac_ops mtk_phylink_ops = { .validate = phylink_generic_validate, .mac_select_pcs = mtk_mac_select_pcs, -@@ -4563,8 +4677,21 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4562,8 +4677,21 @@ static int mtk_add_mac(struct mtk_eth *e phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); @@ -500,7 +501,7 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4757,6 +4884,13 @@ static int mtk_probe(struct platform_dev +@@ -4756,6 +4884,13 @@ static int mtk_probe(struct platform_dev if (err) return err; From 003b9ff61c081dd820764d4d0a83bb2514646576 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 13 Mar 2024 18:44:52 +0000 Subject: [PATCH 103/108] generic: mtk_eth_soc: fix PPE hanging issue A patch to resolve an issue was found in MediaTek's GPL-licensed SDK: In the mtk_ppe_stop() function, the PPE scan mode is not disabled before disabling the PPE. This can potentially lead to a hang during the process of disabling the PPE. Without this patch, the PPE may experience a hang during the reboot test. Reference: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b40da332dfe763932a82f9f62a4709457a15dd6c Suggested-by: Bc-bocun Chen Signed-off-by: Daniel Golle --- ...et-mtk_eth_soc-fix-PPE-hanging-issue.patch | 59 +++++++++++++++++++ ...et-mtk_eth_soc-fix-PPE-hanging-issue.patch | 59 +++++++++++++++++++ ...et-mtk_eth_soc-fix-PPE-hanging-issue.patch | 59 +++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 target/linux/generic/pending-5.15/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch create mode 100644 target/linux/generic/pending-6.1/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch create mode 100644 target/linux/generic/pending-6.6/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch diff --git a/target/linux/generic/pending-5.15/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch b/target/linux/generic/pending-5.15/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch new file mode 100644 index 0000000000..59b06a925a --- /dev/null +++ b/target/linux/generic/pending-5.15/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch @@ -0,0 +1,59 @@ +From c8262ebbf7ca546dd5ead3c0383a89eb401627ff Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 13 Mar 2024 17:55:02 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix PPE hanging issue + +A patch to resolve an issue was found in MediaTek's GPL-licensed SDK: +In the mtk_ppe_stop() function, the PPE scan mode is not disabled before +disabling the PPE. This can potentially lead to a hang during the process +of disabling the PPE. + +Without this patch, the PPE may experience a hang during the reboot test. + +Reference: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b40da332dfe763932a82f9f62a4709457a15dd6c + +Suggested-by: Bc-bocun Chen +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -1008,7 +1008,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_KEEPALIVE_DISABLE) | + FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) | + FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, +- MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | ++ MTK_PPE_SCAN_MODE_CHECK_AGE) | + FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, + MTK_PPE_ENTRIES_SHIFT); + if (mtk_is_netsys_v2_or_greater(ppe->eth)) +@@ -1104,17 +1104,21 @@ int mtk_ppe_stop(struct mtk_ppe *ppe) + + mtk_ppe_cache_enable(ppe, false); + +- /* disable offload engine */ +- ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); +- ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); +- + /* disable aging */ + val = MTK_PPE_TB_CFG_AGE_NON_L4 | + MTK_PPE_TB_CFG_AGE_UNBIND | + MTK_PPE_TB_CFG_AGE_TCP | + MTK_PPE_TB_CFG_AGE_UDP | +- MTK_PPE_TB_CFG_AGE_TCP_FIN; ++ MTK_PPE_TB_CFG_AGE_TCP_FIN | ++ MTK_PPE_TB_CFG_SCAN_MODE; + ppe_clear(ppe, MTK_PPE_TB_CFG, val); + +- return mtk_ppe_wait_busy(ppe); ++ if (mtk_ppe_wait_busy(ppe)) ++ return -ETIMEDOUT; ++ ++ /* disable offload engine */ ++ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); ++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); ++ ++ return 0; + } diff --git a/target/linux/generic/pending-6.1/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch b/target/linux/generic/pending-6.1/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch new file mode 100644 index 0000000000..3b190c1801 --- /dev/null +++ b/target/linux/generic/pending-6.1/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch @@ -0,0 +1,59 @@ +From c8262ebbf7ca546dd5ead3c0383a89eb401627ff Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 13 Mar 2024 17:55:02 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix PPE hanging issue + +A patch to resolve an issue was found in MediaTek's GPL-licensed SDK: +In the mtk_ppe_stop() function, the PPE scan mode is not disabled before +disabling the PPE. This can potentially lead to a hang during the process +of disabling the PPE. + +Without this patch, the PPE may experience a hang during the reboot test. + +Reference: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b40da332dfe763932a82f9f62a4709457a15dd6c + +Suggested-by: Bc-bocun Chen +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -1002,7 +1002,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_KEEPALIVE_DISABLE) | + FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) | + FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, +- MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | ++ MTK_PPE_SCAN_MODE_CHECK_AGE) | + FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, + MTK_PPE_ENTRIES_SHIFT); + if (mtk_is_netsys_v2_or_greater(ppe->eth)) +@@ -1098,17 +1098,21 @@ int mtk_ppe_stop(struct mtk_ppe *ppe) + + mtk_ppe_cache_enable(ppe, false); + +- /* disable offload engine */ +- ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); +- ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); +- + /* disable aging */ + val = MTK_PPE_TB_CFG_AGE_NON_L4 | + MTK_PPE_TB_CFG_AGE_UNBIND | + MTK_PPE_TB_CFG_AGE_TCP | + MTK_PPE_TB_CFG_AGE_UDP | +- MTK_PPE_TB_CFG_AGE_TCP_FIN; ++ MTK_PPE_TB_CFG_AGE_TCP_FIN | ++ MTK_PPE_TB_CFG_SCAN_MODE; + ppe_clear(ppe, MTK_PPE_TB_CFG, val); + +- return mtk_ppe_wait_busy(ppe); ++ if (mtk_ppe_wait_busy(ppe)) ++ return -ETIMEDOUT; ++ ++ /* disable offload engine */ ++ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); ++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); ++ ++ return 0; + } diff --git a/target/linux/generic/pending-6.6/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch b/target/linux/generic/pending-6.6/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch new file mode 100644 index 0000000000..3b190c1801 --- /dev/null +++ b/target/linux/generic/pending-6.6/736-net-ethernet-mtk_eth_soc-fix-PPE-hanging-issue.patch @@ -0,0 +1,59 @@ +From c8262ebbf7ca546dd5ead3c0383a89eb401627ff Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 13 Mar 2024 17:55:02 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix PPE hanging issue + +A patch to resolve an issue was found in MediaTek's GPL-licensed SDK: +In the mtk_ppe_stop() function, the PPE scan mode is not disabled before +disabling the PPE. This can potentially lead to a hang during the process +of disabling the PPE. + +Without this patch, the PPE may experience a hang during the reboot test. + +Reference: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b40da332dfe763932a82f9f62a4709457a15dd6c + +Suggested-by: Bc-bocun Chen +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -1002,7 +1002,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_KEEPALIVE_DISABLE) | + FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) | + FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, +- MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | ++ MTK_PPE_SCAN_MODE_CHECK_AGE) | + FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, + MTK_PPE_ENTRIES_SHIFT); + if (mtk_is_netsys_v2_or_greater(ppe->eth)) +@@ -1098,17 +1098,21 @@ int mtk_ppe_stop(struct mtk_ppe *ppe) + + mtk_ppe_cache_enable(ppe, false); + +- /* disable offload engine */ +- ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); +- ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); +- + /* disable aging */ + val = MTK_PPE_TB_CFG_AGE_NON_L4 | + MTK_PPE_TB_CFG_AGE_UNBIND | + MTK_PPE_TB_CFG_AGE_TCP | + MTK_PPE_TB_CFG_AGE_UDP | +- MTK_PPE_TB_CFG_AGE_TCP_FIN; ++ MTK_PPE_TB_CFG_AGE_TCP_FIN | ++ MTK_PPE_TB_CFG_SCAN_MODE; + ppe_clear(ppe, MTK_PPE_TB_CFG, val); + +- return mtk_ppe_wait_busy(ppe); ++ if (mtk_ppe_wait_busy(ppe)) ++ return -ETIMEDOUT; ++ ++ /* disable offload engine */ ++ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); ++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); ++ ++ return 0; + } From 80e6e5202622a894e1739e15b761ceb8db7d9568 Mon Sep 17 00:00:00 2001 From: Jean Thomas Date: Thu, 7 Dec 2023 16:16:30 +0100 Subject: [PATCH 104/108] mediatek: mt7981: pinctrl: add additional uart group Add uart1_3 (pins 26, 27) group to the pinctrl driver for the MediaTek MT7981 SoC. Signed-off-by: Jean Thomas --- ...tek-mt7981-add-additional-uart-group.patch | 63 +++++++++++++++++++ ...tek-mt7981-add-additional-uart-group.patch | 63 +++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 target/linux/mediatek/patches-6.1/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch create mode 100644 target/linux/mediatek/patches-6.6/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch diff --git a/target/linux/mediatek/patches-6.1/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch b/target/linux/mediatek/patches-6.1/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch new file mode 100644 index 0000000000..1e53777d65 --- /dev/null +++ b/target/linux/mediatek/patches-6.1/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch @@ -0,0 +1,63 @@ +From patchwork Wed Jan 17 12:42:33 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Jean Thomas +X-Patchwork-Id: 13521682 +Return-Path: + +From: Jean Thomas +To: sean.wang@kernel.org, + linus.walleij@linaro.org, + matthias.bgg@gmail.com, + angelogioacchino.delregno@collabora.com, + linux-mediatek@lists.infradead.org, + linux-gpio@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org +Cc: Jean Thomas +Subject: [PATCH 1/2] pinctrl: mediatek: mt7981: add additional uart group +Date: Wed, 17 Jan 2024 13:42:33 +0100 +Message-Id: <20240117124234.3137050-1-jean.thomas@wifirst.fr> +MIME-Version: 1.0 +List-Id: + +Add uart1_3 (pins 26, 27) group to the pinctrl driver for the +MediaTek MT7981 SoC. + +Signed-off-by: Jean Thomas +Reviewed-by: Daniel Golle +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -737,6 +737,9 @@ static int mt7981_uart1_1_funcs[] = { 2, + static int mt7981_uart1_2_pins[] = { 9, 10, }; + static int mt7981_uart1_2_funcs[] = { 2, 2, }; + ++static int mt7981_uart1_3_pins[] = { 26, 27, }; ++static int mt7981_uart1_3_funcs[] = { 2, 2, }; ++ + /* UART2 */ + static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; + static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; +@@ -871,6 +874,8 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), + /* @GPIO(9,10): UART1(2) */ + PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2), ++ /* @GPIO(26,27): UART1(2) */ ++ PINCTRL_PIN_GROUP("uart1_3", mt7981_uart1_3), + /* @GPIO(22,25): UART1(3) */ + PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), + /* @GPIO(22,24) PTA_EXT(4) */ +@@ -933,7 +938,7 @@ static const struct group_desc mt7981_gr + static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", + "wa_aice3", "wm_aice1_2", }; + static const char *mt7981_uart_groups[] = { "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", +- "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart2_0", ++ "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart1_3", "uart2_0", + "uart2_0_tx_rx", "uart2_1", "wm_uart_0", "wm_aurt_1", "wm_aurt_2", }; + static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; + static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; diff --git a/target/linux/mediatek/patches-6.6/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch b/target/linux/mediatek/patches-6.6/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch new file mode 100644 index 0000000000..1e53777d65 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/253-pinctrl-mediatek-mt7981-add-additional-uart-group.patch @@ -0,0 +1,63 @@ +From patchwork Wed Jan 17 12:42:33 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Jean Thomas +X-Patchwork-Id: 13521682 +Return-Path: + +From: Jean Thomas +To: sean.wang@kernel.org, + linus.walleij@linaro.org, + matthias.bgg@gmail.com, + angelogioacchino.delregno@collabora.com, + linux-mediatek@lists.infradead.org, + linux-gpio@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org +Cc: Jean Thomas +Subject: [PATCH 1/2] pinctrl: mediatek: mt7981: add additional uart group +Date: Wed, 17 Jan 2024 13:42:33 +0100 +Message-Id: <20240117124234.3137050-1-jean.thomas@wifirst.fr> +MIME-Version: 1.0 +List-Id: + +Add uart1_3 (pins 26, 27) group to the pinctrl driver for the +MediaTek MT7981 SoC. + +Signed-off-by: Jean Thomas +Reviewed-by: Daniel Golle +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -737,6 +737,9 @@ static int mt7981_uart1_1_funcs[] = { 2, + static int mt7981_uart1_2_pins[] = { 9, 10, }; + static int mt7981_uart1_2_funcs[] = { 2, 2, }; + ++static int mt7981_uart1_3_pins[] = { 26, 27, }; ++static int mt7981_uart1_3_funcs[] = { 2, 2, }; ++ + /* UART2 */ + static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; + static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; +@@ -871,6 +874,8 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), + /* @GPIO(9,10): UART1(2) */ + PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2), ++ /* @GPIO(26,27): UART1(2) */ ++ PINCTRL_PIN_GROUP("uart1_3", mt7981_uart1_3), + /* @GPIO(22,25): UART1(3) */ + PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), + /* @GPIO(22,24) PTA_EXT(4) */ +@@ -933,7 +938,7 @@ static const struct group_desc mt7981_gr + static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", + "wa_aice3", "wm_aice1_2", }; + static const char *mt7981_uart_groups[] = { "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", +- "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart2_0", ++ "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart1_3", "uart2_0", + "uart2_0_tx_rx", "uart2_1", "wm_uart_0", "wm_aurt_1", "wm_aurt_2", }; + static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; + static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; From e1831321de15ba4a8401cbf8c2c713939de968c1 Mon Sep 17 00:00:00 2001 From: Jean Thomas Date: Thu, 7 Dec 2023 16:18:02 +0100 Subject: [PATCH 105/108] mediatek: mt7981: pinctrl: add additional emmc groups Add new emmc groups in the pinctrl driver for the MediaTek MT7981 SoC: * emmc reset, with pin 15. * emmc 4-bit bus-width, with pins 16 to 19, and 24 to 25. * emmc 8-bit bus-width, with pins 16 to 25. The existing emmc_45 group is kept for legacy reasons, even if this is the union of emmc_reset and emmc_8 groups. Signed-off-by: Jean Thomas --- ...tek-mt7981-add-additional-emmc-group.patch | 82 +++++++++++++++++++ ...tek-mt7981-add-additional-emmc-group.patch | 82 +++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 target/linux/mediatek/patches-6.1/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch create mode 100644 target/linux/mediatek/patches-6.6/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch diff --git a/target/linux/mediatek/patches-6.1/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch b/target/linux/mediatek/patches-6.1/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch new file mode 100644 index 0000000000..df4d82c9d9 --- /dev/null +++ b/target/linux/mediatek/patches-6.1/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch @@ -0,0 +1,82 @@ +From patchwork Wed Jan 17 14:55:47 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Jean Thomas +X-Patchwork-Id: 13521855 +Return-Path: + +From: Jean Thomas +To: sean.wang@kernel.org, + linus.walleij@linaro.org, + matthias.bgg@gmail.com, + angelogioacchino.delregno@collabora.com, + linux-mediatek@lists.infradead.org, + linux-gpio@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org +Cc: Jean Thomas , + Daniel Golle +Subject: [PATCH v2 2/2] pinctrl: mediatek: mt7981: add additional emmc groups +Date: Wed, 17 Jan 2024 15:55:47 +0100 +Message-Id: <20240117145547.3354242-1-jean.thomas@wifirst.fr> +List-Id: + +Add new emmc groups in the pinctrl driver for the +MediaTek MT7981 SoC: +* emmc reset, with pin 15. +* emmc 4-bit bus-width, with pins 16 to 19, and 24 to 25. +* emmc 8-bit bus-width, with pins 16 to 25. + +The existing emmc_45 group is kept for legacy reasons, even +if this is the union of emmc_reset and emmc_8 groups. + +Signed-off-by: Jean Thomas +Reviewed-by: Daniel Golle +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +-- +2.39.2 + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -700,6 +700,15 @@ static int mt7981_drv_vbus_pins[] = { 14 + static int mt7981_drv_vbus_funcs[] = { 1, }; + + /* EMMC */ ++static int mt7981_emmc_reset_pins[] = { 15, }; ++static int mt7981_emmc_reset_funcs[] = { 2, }; ++ ++static int mt7981_emmc_4_pins[] = { 16, 17, 18, 19, 24, 25, }; ++static int mt7981_emmc_4_funcs[] = { 2, 2, 2, 2, 2, 2, }; ++ ++static int mt7981_emmc_8_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; ++static int mt7981_emmc_8_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ + static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; + static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; + +@@ -854,6 +863,12 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("udi", mt7981_udi), + /* @GPIO(14) DRV_VBUS(1) */ + PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), ++ /* @GPIO(15): EMMC_RSTB(2) */ ++ PINCTRL_PIN_GROUP("emmc_reset", mt7981_emmc_reset), ++ /* @GPIO(16,17,18,19,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */ ++ PINCTRL_PIN_GROUP("emmc_4", mt7981_emmc_4), ++ /* @GPIO(16,17,18,19,20,21,22,23,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */ ++ PINCTRL_PIN_GROUP("emmc_8", mt7981_emmc_8), + /* @GPIO(15,25): EMMC(2) */ + PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), + /* @GPIO(16,21): SNFI(3) */ +@@ -957,7 +972,7 @@ static const char *mt7981_i2c_groups[] = + static const char *mt7981_pcm_groups[] = { "pcm", }; + static const char *mt7981_udi_groups[] = { "udi", }; + static const char *mt7981_usb_groups[] = { "drv_vbus", }; +-static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; ++static const char *mt7981_flash_groups[] = { "emmc_reset", "emmc_4", "emmc_8", "emmc_45", "snfi", }; + static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", + "wf0_mode1", "wf0_mode3", "mt7531_int", }; + static const char *mt7981_ant_groups[] = { "ant_sel", }; diff --git a/target/linux/mediatek/patches-6.6/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch b/target/linux/mediatek/patches-6.6/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch new file mode 100644 index 0000000000..df4d82c9d9 --- /dev/null +++ b/target/linux/mediatek/patches-6.6/254-pinctrl-mediatek-mt7981-add-additional-emmc-group.patch @@ -0,0 +1,82 @@ +From patchwork Wed Jan 17 14:55:47 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Jean Thomas +X-Patchwork-Id: 13521855 +Return-Path: + +From: Jean Thomas +To: sean.wang@kernel.org, + linus.walleij@linaro.org, + matthias.bgg@gmail.com, + angelogioacchino.delregno@collabora.com, + linux-mediatek@lists.infradead.org, + linux-gpio@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org +Cc: Jean Thomas , + Daniel Golle +Subject: [PATCH v2 2/2] pinctrl: mediatek: mt7981: add additional emmc groups +Date: Wed, 17 Jan 2024 15:55:47 +0100 +Message-Id: <20240117145547.3354242-1-jean.thomas@wifirst.fr> +List-Id: + +Add new emmc groups in the pinctrl driver for the +MediaTek MT7981 SoC: +* emmc reset, with pin 15. +* emmc 4-bit bus-width, with pins 16 to 19, and 24 to 25. +* emmc 8-bit bus-width, with pins 16 to 25. + +The existing emmc_45 group is kept for legacy reasons, even +if this is the union of emmc_reset and emmc_8 groups. + +Signed-off-by: Jean Thomas +Reviewed-by: Daniel Golle +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +-- +2.39.2 + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -700,6 +700,15 @@ static int mt7981_drv_vbus_pins[] = { 14 + static int mt7981_drv_vbus_funcs[] = { 1, }; + + /* EMMC */ ++static int mt7981_emmc_reset_pins[] = { 15, }; ++static int mt7981_emmc_reset_funcs[] = { 2, }; ++ ++static int mt7981_emmc_4_pins[] = { 16, 17, 18, 19, 24, 25, }; ++static int mt7981_emmc_4_funcs[] = { 2, 2, 2, 2, 2, 2, }; ++ ++static int mt7981_emmc_8_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; ++static int mt7981_emmc_8_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ + static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; + static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; + +@@ -854,6 +863,12 @@ static const struct group_desc mt7981_gr + PINCTRL_PIN_GROUP("udi", mt7981_udi), + /* @GPIO(14) DRV_VBUS(1) */ + PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), ++ /* @GPIO(15): EMMC_RSTB(2) */ ++ PINCTRL_PIN_GROUP("emmc_reset", mt7981_emmc_reset), ++ /* @GPIO(16,17,18,19,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */ ++ PINCTRL_PIN_GROUP("emmc_4", mt7981_emmc_4), ++ /* @GPIO(16,17,18,19,20,21,22,23,24,25): EMMC_DATx, EMMC_CLK, EMMC_CMD */ ++ PINCTRL_PIN_GROUP("emmc_8", mt7981_emmc_8), + /* @GPIO(15,25): EMMC(2) */ + PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), + /* @GPIO(16,21): SNFI(3) */ +@@ -957,7 +972,7 @@ static const char *mt7981_i2c_groups[] = + static const char *mt7981_pcm_groups[] = { "pcm", }; + static const char *mt7981_udi_groups[] = { "udi", }; + static const char *mt7981_usb_groups[] = { "drv_vbus", }; +-static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; ++static const char *mt7981_flash_groups[] = { "emmc_reset", "emmc_4", "emmc_8", "emmc_45", "snfi", }; + static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", + "wf0_mode1", "wf0_mode3", "mt7531_int", }; + static const char *mt7981_ant_groups[] = { "ant_sel", }; From d1016446dacd16a87e807478227f4f96a0a37a45 Mon Sep 17 00:00:00 2001 From: Jean Thomas Date: Thu, 9 Nov 2023 11:28:45 +0100 Subject: [PATCH 106/108] mediatek: Add support for GL.iNet X3000 (Spitz AX) and XE3000 (Puli AX) The GL.iNet X3000 and XE3000 are Wi-Fi 6 5G cellular routers, based on MediaTek MT7981A SoC. The XE3000 is the same device as the X3000, except for an additional battery. Specifications: - SoC: Filogic 820 MT7981A (1.3GHz) - RAM: DDR4 512M - Flash: eMMC 8G, MicroSD card slot - WiFi: 2.4GHz and 5GHz with 6 antennas - Ethernet: - 1x LAN (10/100/1000M) - 1x WAN (10/100/1000/2500M) - 5G: Quectel RM520N-GL with two nano-SIM card slots - USB: 1x USB 2.0 port - UART: - 3.3V, TX, RX, GND / 115200 8N1 MAC addresses as verified by OEM firmware: vendor OpenWrt address source WAN eth0 label factory 0x0a (label) LAN eth1 label + 1 2g phy0-ap0 label + 2 factory 0x04 5g phy1-ap0 label + 3 Installation via U-Boot rescue: 1. Press and hold reset button while booting the device 2. Wait for the Internet led to blink 5 times 3. Release reset button 4. The rescue page is accessible via http://192.168.1.1 5. Select the OpenWrt sysupgrade image and start upgrade 6. Wait for the router to flash new firmware and reboot Revert to stock firmware: 1. Download the stock firmware from GL.iNet website 2. Use the method explained above to flash the stock firmware Switch the modem network port between PCIe and USB interfaces: 1. Connect to the AT commands (/dev/ttyUSB2) port using e.g. minicom: minicom -D /dev/ttyUSB2 2. Check the current modem mode with 'AT+QCFG="data_interface"': - 0,0 indicates that the network port uses the USB interface - 1,0 indicates that the network port uses the PCIe interface 3. Switch the active interface with: - 'AT+QCFG="data_interface",0,0' to use the USB interface - 'AT+QCFG="data_interface",1,0' to use the PCIe interface 4. Reboot Signed-off-by: Jean Thomas --- ...mt7981a-glinet-gl-x3000-xe3000-common.dtsi | 273 ++++++++++++++++++ .../mediatek/dts/mt7981a-glinet-gl-x3000.dts | 8 + .../mediatek/dts/mt7981a-glinet-gl-xe3000.dts | 23 ++ .../filogic/base-files/etc/board.d/01_leds | 11 + .../filogic/base-files/etc/board.d/02_network | 4 +- .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 4 +- .../base-files/lib/upgrade/platform.sh | 6 +- target/linux/mediatek/image/filogic.mk | 25 ++ 8 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi new file mode 100644 index 0000000000..4b311dbe21 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + chosen { + bootargs = "console=ttyS0,115200n8 root=PARTLABEL=rootfs rootwait"; + }; + + aliases { + label-mac-device = &gmac0; + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + fan_5v: regulator-fan-5v { + compatible = "regulator-fixed"; + regulator-name = "fan"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 28 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + hub_power { + gpio-export,name = "hub_power"; + gpio-export,output = <1>; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + 5G_power { + gpio-export,name = "5G_power"; + gpio-export,output = <1>; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + 5G_control { + gpio-export,name = "5G_control"; + gpio-export,output = <1>; + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + }; + + 5G_reset { + gpio-export,name = "5G_reset"; + gpio-export,output = <0>; + gpios = <&pio 10 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + wifi2g { + label = "green:wifi2g"; + gpios = <&pio 30 GPIO_ACTIVE_LOW>; + }; + + wifi5g { + label = "green:wifi5g"; + gpios = <&pio 38 GPIO_ACTIVE_LOW>; + }; + + 5g_led1 { + label = "green:5g:led1"; + gpios = <&pio 6 GPIO_ACTIVE_LOW>; + }; + + 5g_led2 { + label = "green:5g:led2"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + + 5g_led3 { + label = "green:5g:led3"; + gpios = <&pio 8 GPIO_ACTIVE_LOW>; + }; + + 5g_led4 { + label = "green:5g:led4"; + gpios = <&pio 4 GPIO_ACTIVE_HIGH>; + }; + + led_power: power { + label = "green:power"; + gpios = <&pio 39 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "green:wan"; + gpios = <&pio 31 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <52000000>; + cap-mmc-highspeed; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "u-boot-env"; + + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_a: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&mdio_bus { + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + reset-delay-us = <600>; + reset-post-delay-us = <20000>; + + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + nvmem-cells = <&macaddr_factory_a 0>; + nvmem-cell-names = "mac-address"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cells = <&macaddr_factory_a 1>; + nvmem-cell-names = "mac-address"; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_8"; + }; + }; + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_8"; + }; + }; + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_pereset", "pcie_clk", "pcie_wake"; + }; + }; + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_1"; + }; + }; +}; + +&xhci { + phys = <&u2port0 PHY_TYPE_USB2>; + vbus-supply = <®_5v>; + mediatek,u3p-dis-msk = <0x01>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; + +&fan { + pwms = <&pwm 0 40000 0>; + fan-supply = <&fan_5v>; + interrupt-parent = <&pio>; + interrupts = <29 IRQ_TYPE_EDGE_RISING>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts new file mode 100644 index 0000000000..bee1ecd89a --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981a-glinet-gl-x3000-xe3000-common.dtsi" + +/ { + model = "GL.iNet GL-X3000"; + compatible = "glinet,gl-x3000", "mediatek,mt7981"; +}; diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts b/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts new file mode 100644 index 0000000000..e14b944bc9 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981a-glinet-gl-x3000-xe3000-common.dtsi" + +/ { + model = "GL.iNet GL-XE3000"; + compatible = "glinet,gl-xe3000", "mediatek,mt7981"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&pio { + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_3"; + }; + }; +}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index b3dceb74c4..69afdfde56 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -32,6 +32,17 @@ cudy,re3000-v1) cudy,wr3000-v1) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" ;; +glinet,gl-x3000|\ +glinet,gl-xe3000) + ucidef_set_led_default "power" "POWER" "green:power" "1" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth0" + ucidef_set_led_netdev "5g_1" "5G_1" "green:5g:led1" "wwan0" + ucidef_set_led_netdev "5g_2" "5G_2" "green:5g:led2" "wwan0" + ucidef_set_led_netdev "5g_3" "5G_3" "green:5g:led3" "wwan0" + ucidef_set_led_netdev "5g_4" "5G_4" "green:5g:led4" "wwan0" + ucidef_set_led_netdev "wlan2g" "WLAN2G" "green:wifi2g" "phy0-ap0" + ucidef_set_led_netdev "wlan5g" "WLAN5G" "green:wifi5g" "phy1-ap0" + ;; mercusys,mr90x-v1) ucidef_set_led_netdev "lan-0" "lan-0" "green:lan-0" "lan0" "link tx rx" ucidef_set_led_netdev "lan-1" "lan-1" "green:lan-1" "lan1" "link tx rx" 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 dbda950cc5..8e4fd8003c 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 @@ -50,7 +50,9 @@ mediatek_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1" eth1 ;; glinet,gl-mt2500|\ - glinet,gl-mt3000) + glinet,gl-mt3000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000) ucidef_set_interfaces_lan_wan eth1 eth0 ;; glinet,gl-mt6000|\ diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index ebee1b931f..facd2079c4 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -74,7 +74,9 @@ case "$board" in [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(macaddr_add $addr 1) > /sys${DEVPATH}/macaddress ;; - glinet,gl-mt6000) + glinet,gl-mt6000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000) addr=$(mmc_get_mac_binary factory 0x04) [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index abb692fb41..4df4370f0f 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -120,7 +120,9 @@ platform_do_upgrade() { default_do_upgrade "$1" ;; glinet,gl-mt2500|\ - glinet,gl-mt6000) + glinet,gl-mt6000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000) CI_KERNPART="kernel" CI_ROOTPART="rootfs" emmc_do_upgrade "$1" @@ -216,6 +218,8 @@ platform_copy_config() { acer,predator-w6|\ glinet,gl-mt2500|\ glinet,gl-mt6000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000|\ jdcloud,re-cp-03|\ ubnt,unifi-6-plus) emmc_copy_config diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index b1c043bef2..7d2fac56b6 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -535,6 +535,31 @@ define Device/glinet_gl-mt6000 endef TARGET_DEVICES += glinet_gl-mt6000 +define Device/glinet_gl-x3000-xe3000-common + DEVICE_VENDOR := GL.iNet + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware mkf2fs \ + kmod-fs-f2fs kmod-hwmon-pwmfan kmod-usb3 kmod-usb-serial-option \ + kmod-usb-storage kmod-usb-net-qmi-wwan uqmi + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/glinet_gl-x3000 + DEVICE_MODEL := GL-X3000 + DEVICE_DTS := mt7981a-glinet-gl-x3000 + SUPPORTED_DEVICES := glinet,gl-x3000 + $(call Device/glinet_gl-x3000-xe3000-common) +endef +TARGET_DEVICES += glinet_gl-x3000 + +define Device/glinet_gl-xe3000 + DEVICE_MODEL := GL-XE3000 + DEVICE_DTS := mt7981a-glinet-gl-xe3000 + SUPPORTED_DEVICES := glinet,gl-xe3000 + $(call Device/glinet_gl-x3000-xe3000-common) +endef +TARGET_DEVICES += glinet_gl-xe3000 + define Device/h3c_magic-nx30-pro DEVICE_VENDOR := H3C DEVICE_MODEL := Magic NX30 Pro From 7b89388674ed6a33c5145064888c2505b5dbb4e1 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 13 Mar 2024 23:49:32 +0100 Subject: [PATCH 107/108] ramips: 5.15: delete remaining files Remove the remaining configuration entries that were omitted in the previous commit. Fixes: 1576474f55e9 ("ramips: switch to 6.1 kernel") Signed-off-by: Nick Hainke --- target/linux/ramips/mt7620/config-5.15 | 201 ----------------- target/linux/ramips/mt7621/config-5.15 | 297 ------------------------- target/linux/ramips/mt76x8/config-5.15 | 199 ----------------- target/linux/ramips/rt288x/config-5.15 | 187 ---------------- target/linux/ramips/rt305x/config-5.15 | 182 --------------- target/linux/ramips/rt3883/config-5.15 | 182 --------------- 6 files changed, 1248 deletions(-) delete mode 100644 target/linux/ramips/mt7620/config-5.15 delete mode 100644 target/linux/ramips/mt7621/config-5.15 delete mode 100644 target/linux/ramips/mt76x8/config-5.15 delete mode 100644 target/linux/ramips/rt288x/config-5.15 delete mode 100644 target/linux/ramips/rt305x/config-5.15 delete mode 100644 target/linux/ramips/rt3883/config-5.15 diff --git a/target/linux/ramips/mt7620/config-5.15 b/target/linux/ramips/mt7620/config-5.15 deleted file mode 100644 index 641b93e582..0000000000 --- a/target/linux/ramips/mt7620/config-5.15 +++ /dev/null @@ -1,201 +0,0 @@ -CONFIG_AR8216_PHY=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_CEVT_R4K=y -CONFIG_CEVT_SYSTICK_QUIRK=y -CONFIG_CLKEVT_RT3352=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLK_MTMIPS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MIPSR2_IRQ_VI=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_PINCTRL=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_MT7620A_EVAL is not set -# CONFIG_DTB_OMEGA2P is not set -CONFIG_DTB_RT_NONE=y -# CONFIG_DTB_VOCORE2 is not set -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_ETHERNET_PACKET_MANGLE=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIO_CDEV=y -# CONFIG_GPIO_MT7621 is not set -CONFIG_GPIO_RALINK=y -CONFIG_GPIO_WATCHDOG=y -# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_ICPLUS_PHY=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_INTC=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MARVELL_PHY=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MT7621_WDT is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_JIMAGE_FW=y -CONFIG_MTD_SPLIT_SEAMA_FW=y -CONFIG_MTD_SPLIT_TPLINK_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_VIRT_CONCAT=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_RALINK_GSW_MT7620=y -CONFIG_NET_RALINK_MDIO=y -CONFIG_NET_RALINK_MDIO_MT7620=y -CONFIG_NET_RALINK_MT7620=y -# CONFIG_NET_RALINK_RT3050 is not set -CONFIG_NET_RALINK_SOC=y -CONFIG_NET_SELFTESTS=y -# CONFIG_NET_VENDOR_MEDIATEK is not set -CONFIG_NET_VENDOR_RALINK=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_MT7621_PCI is not set -CONFIG_PHY_RALINK_USB=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_AW9523 is not set -CONFIG_PINCTRL_MT7620=y -CONFIG_PINCTRL_RALINK=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RALINK=y -CONFIG_RALINK_WDT=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_SERIAL_8250_RT288X=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SOC_MT7620=y -# CONFIG_SOC_MT7621 is not set -# CONFIG_SOC_RT288X is not set -# CONFIG_SOC_RT305X is not set -# CONFIG_SOC_RT3883 is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_MT7621 is not set -CONFIG_SPI_RT2880=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWCONFIG_LEDS=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TINY_SRCU=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/mt7621/config-5.15 b/target/linux/ramips/mt7621/config-5.15 deleted file mode 100644 index 05e4c1ce87..0000000000 --- a/target/linux/ramips/mt7621/config-5.15 +++ /dev/null @@ -1,297 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_AT803X_PHY=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BOARD_SCACHE=y -CONFIG_CEVT_R4K=y -CONFIG_CLKSRC_MIPS_GIC=y -CONFIG_CLK_MT7621=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MIPSR2_IRQ_EI=y -CONFIG_CPU_MIPSR2_IRQ_VI=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_PINCTRL=y -CONFIG_DIMLIB=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_GNUBEE1 is not set -# CONFIG_DTB_GNUBEE2 is not set -CONFIG_DTB_RT_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_MT7621=y -# CONFIG_GPIO_RALINK is not set -CONFIG_GPIO_WATCHDOG=y -# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_I2C_MT7621=y -CONFIG_ICPLUS_PHY=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LED_TRIGGER_PHY=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIKROTIK=y -CONFIG_MIKROTIK_RB_SYSFS=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -CONFIG_MIPS_CM=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_CPC=y -CONFIG_MIPS_CPS=y -# CONFIG_MIPS_CPS_NS16550_BOOL is not set -CONFIG_MIPS_CPU_SCACHE=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_GIC=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -CONFIG_MIPS_MT=y -CONFIG_MIPS_MT_FPAFF=y -CONFIG_MIPS_MT_SMP=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=4 -CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MT7621_WDT=y -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MT7621=y -CONFIG_MTD_NAND_MTK_BMT=y -# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_ROUTERBOOT_PARTS=y -CONFIG_MTD_SERCOMM_PARTS=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_SPLIT_MINOR_FW=y -CONFIG_MTD_SPLIT_SEAMA_FW=y -CONFIG_MTD_SPLIT_TPLINK_FW=y -CONFIG_MTD_SPLIT_TRX_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_VIRT_CONCAT=y -# CONFIG_MTK_HSDMA is not set -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 -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -# CONFIG_NET_VENDOR_RALINK is not set -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PCI=y -CONFIG_PCIE_MT7621=y -CONFIG_PCI_DISABLE_COMMON_QUIRKS=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_DRIVERS_GENERIC=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHY_MT7621_PCI=y -# CONFIG_PHY_RALINK_USB is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_AW9523=y -CONFIG_PINCTRL_MT7621=y -CONFIG_PINCTRL_RALINK=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PINCTRL_SX150X=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_GPIO=y -CONFIG_POWER_SUPPLY=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RALINK=y -# CONFIG_RALINK_WDT is not set -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_BQ32K=y -CONFIG_RTC_DRV_PCF8563=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_SMT=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -# CONFIG_SOC_MT7620 is not set -CONFIG_SOC_MT7621=y -# CONFIG_SOC_RT288X is not set -# CONFIG_SOC_RT305X is not set -# CONFIG_SOC_RT3883 is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT7621=y -# CONFIG_SPI_RT2880 is not set -CONFIG_SRCU=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_HIGHMEM=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_MIPS_CPS=y -CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/ramips/mt76x8/config-5.15 b/target/linux/ramips/mt76x8/config-5.15 deleted file mode 100644 index fc9aebc46a..0000000000 --- a/target/linux/ramips/mt76x8/config-5.15 +++ /dev/null @@ -1,199 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_CEVT_R4K=y -CONFIG_CEVT_SYSTICK_QUIRK=y -CONFIG_CLKEVT_RT3352=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLK_MTMIPS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MIPSR2_IRQ_VI=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_PINCTRL=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_MT7620A_EVAL is not set -# CONFIG_DTB_OMEGA2P is not set -CONFIG_DTB_RT_NONE=y -# CONFIG_DTB_VOCORE2 is not set -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_MT7621=y -# CONFIG_GPIO_RALINK is not set -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_ICPLUS_PHY=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_INTC=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MT7621_WDT=y -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set -CONFIG_MTD_PARSER_TRX=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_TPLINK_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_VIRT_CONCAT=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_RALINK_ESW_RT3050=y -# CONFIG_NET_RALINK_MT7620 is not set -CONFIG_NET_RALINK_RT3050=y -CONFIG_NET_RALINK_SOC=y -CONFIG_NET_SELFTESTS=y -# CONFIG_NET_VENDOR_MEDIATEK is not set -CONFIG_NET_VENDOR_RALINK=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_MT7621_PCI is not set -CONFIG_PHY_RALINK_USB=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_AW9523 is not set -CONFIG_PINCTRL_MT7620=y -CONFIG_PINCTRL_RALINK=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RALINK=y -# CONFIG_RALINK_WDT is not set -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RTC_CLASS=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SOC_MT7620=y -# CONFIG_SOC_MT7621 is not set -# CONFIG_SOC_RT288X is not set -# CONFIG_SOC_RT305X is not set -# CONFIG_SOC_RT3883 is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT7621=y -# CONFIG_SPI_RT2880 is not set -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWCONFIG_LEDS=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TINY_SRCU=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/rt288x/config-5.15 b/target/linux/ramips/rt288x/config-5.15 deleted file mode 100644 index 9f502c220f..0000000000 --- a/target/linux/ramips/rt288x/config-5.15 +++ /dev/null @@ -1,187 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_CEVT_R4K=y -CONFIG_CLK_MTMIPS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_RT2880_EVAL is not set -CONFIG_DTB_RT_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_RALINK=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IP17XX_PHY=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_INTC=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_AUTO_PFN_OFFSET=y -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=4 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_LZMA_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_SPLIT_WRGG_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_RALINK_MDIO=y -CONFIG_NET_RALINK_MDIO_RT2880=y -CONFIG_NET_RALINK_RT2880=y -CONFIG_NET_RALINK_SOC=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_VENDOR_RALINK=y -CONFIG_NLS=m -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_MT7621_PCI is not set -# CONFIG_PHY_RALINK_USB is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_AW9523 is not set -CONFIG_PINCTRL_RALINK=y -CONFIG_PINCTRL_RT288X=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RALINK=y -CONFIG_RALINK_WDT=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_SERIAL_8250_RT288X=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -# CONFIG_SOC_MT7620 is not set -# CONFIG_SOC_MT7621 is not set -CONFIG_SOC_RT288X=y -# CONFIG_SOC_RT305X is not set -# CONFIG_SOC_RT3883 is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_MT7621 is not set -CONFIG_SPI_RT2880=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TINY_SRCU=y -CONFIG_USB=m -CONFIG_USB_COMMON=m -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_EHCI_HCD_PLATFORM=m -CONFIG_USB_OHCI_HCD=m -CONFIG_USB_OHCI_HCD_PLATFORM=m -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/rt305x/config-5.15 b/target/linux/ramips/rt305x/config-5.15 deleted file mode 100644 index 5af80adca6..0000000000 --- a/target/linux/ramips/rt305x/config-5.15 +++ /dev/null @@ -1,182 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_CEVT_R4K=y -CONFIG_CEVT_SYSTICK_QUIRK=y -CONFIG_CLKEVT_RT3352=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLK_MTMIPS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_PINCTRL=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_RT305X_EVAL is not set -CONFIG_DTB_RT_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_RALINK=y -CONFIG_GPIO_WATCHDOG=y -# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_INTC=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_JIMAGE_FW=y -CONFIG_MTD_SPLIT_SEAMA_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_RALINK_ESW_RT3050=y -CONFIG_NET_RALINK_RT3050=y -CONFIG_NET_RALINK_SOC=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_VENDOR_RALINK=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_MT7621_PCI is not set -CONFIG_PHY_RALINK_USB=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_AW9523 is not set -CONFIG_PINCTRL_RALINK=y -CONFIG_PINCTRL_RT305X=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RALINK=y -# CONFIG_RALINK_ILL_ACC is not set -CONFIG_RALINK_WDT=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_SERIAL_8250_RT288X=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -# CONFIG_SOC_MT7620 is not set -# CONFIG_SOC_MT7621 is not set -# CONFIG_SOC_RT288X is not set -CONFIG_SOC_RT305X=y -# CONFIG_SOC_RT3883 is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_MT7621 is not set -CONFIG_SPI_RT2880=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TINY_SRCU=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/rt3883/config-5.15 b/target/linux/ramips/rt3883/config-5.15 deleted file mode 100644 index 2977a3b531..0000000000 --- a/target/linux/ramips/rt3883/config-5.15 +++ /dev/null @@ -1,182 +0,0 @@ -CONFIG_AR8216_PHY=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_CEVT_R4K=y -CONFIG_CLK_MTMIPS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_BOOL=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_RNG2=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_PINCTRL=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_DTB_RT3883_EVAL is not set -CONFIG_DTB_RT_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_ETHERNET_PACKET_MANGLE=y -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_RALINK=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_INTC=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_SEAMA_FW=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_RALINK_MDIO=y -CONFIG_NET_RALINK_MDIO_RT2880=y -CONFIG_NET_RALINK_RT3883=y -CONFIG_NET_RALINK_SOC=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_VENDOR_RALINK=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -# CONFIG_PHY_MT7621_PCI is not set -CONFIG_PHY_RALINK_USB=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_AW9523 is not set -CONFIG_PINCTRL_RALINK=y -CONFIG_PINCTRL_RT3883=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RALINK=y -CONFIG_RALINK_WDT=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RTL8366_SMI=y -CONFIG_RTL8367B_PHY=y -CONFIG_RTL8367_PHY=y -CONFIG_SERIAL_8250_RT288X=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -# CONFIG_SOC_MT7620 is not set -# CONFIG_SOC_MT7621 is not set -# CONFIG_SOC_RT288X is not set -# CONFIG_SOC_RT305X is not set -CONFIG_SOC_RT3883=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_MT7621 is not set -CONFIG_SPI_RT2880=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TINY_SRCU=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_WATCHDOG_CORE=y From af860c4dbf5ecbddfbb589df82639f0ba2417467 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Thu, 14 Mar 2024 14:21:17 +0100 Subject: [PATCH 108/108] mxs: switch default kernel to 6.1 The testing kernel has been available since Jul/2023, let's switch to it by default. Signed-off-by: Zoltan HERPAI --- target/linux/mxs/Makefile | 3 +- target/linux/mxs/config-5.15 | 246 ----------------------------------- 2 files changed, 1 insertion(+), 248 deletions(-) delete mode 100644 target/linux/mxs/config-5.15 diff --git a/target/linux/mxs/Makefile b/target/linux/mxs/Makefile index 34e826dfbb..9e88e5aea2 100644 --- a/target/linux/mxs/Makefile +++ b/target/linux/mxs/Makefile @@ -11,8 +11,7 @@ FEATURES:=ext4 rtc usb gpio CPU_TYPE:=arm926ej-s SUBTARGETS:=generic -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 KERNELNAME:=zImage dtbs diff --git a/target/linux/mxs/config-5.15 b/target/linux/mxs/config-5.15 deleted file mode 100644 index 67b2cfa373..0000000000 --- a/target/linux/mxs/config-5.15 +++ /dev/null @@ -1,246 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_CPU_AUTO=y -# CONFIG_ARCH_MULTI_V4 is not set -# CONFIG_ARCH_MULTI_V4T is not set -CONFIG_ARCH_MULTI_V4_V5=y -CONFIG_ARCH_MULTI_V5=y -CONFIG_ARCH_MXS=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_CRYPTO=y -CONFIG_ARM_HAS_SG_CHAIN=y -CONFIG_ARM_L1_CACHE_SHIFT=5 -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_THUMB=y -CONFIG_ARM_UNWIND=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_PM=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="console=ttyAMA0,115200 root=/dev/mmcblk0p2 rw rootwait" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_COREDUMP=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_ARM926T=y -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_PM=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_USE_DOMAINS=y -CONFIG_CRC16=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_DEV_MXS_DCP=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_RNG2=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_OPS=y -CONFIG_DMA_REMAP=y -CONFIG_DTC=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -CONFIG_FEC=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -# CONFIG_GIANFAR is not set -CONFIG_GLOB=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MXS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_FIXED=0 -CONFIG_HZ_PERIODIC=y -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_ALGOPCA=y -CONFIG_I2C_ALGOPCF=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_MUX=y -CONFIG_I2C_MUX_PINCTRL=y -CONFIG_I2C_MXS=y -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_SYSFS_TRIGGER=y -CONFIG_IIO_TRIGGER=y -# CONFIG_IIO_TRIGGERED_BUFFER is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MXS=y -CONFIG_IRQ_WORK=y -# CONFIG_ISDN is not set -CONFIG_JBD2=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_CORE=y -CONFIG_MFD_MXS_LRADC=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_MXS=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MXS_DMA=y -# CONFIG_MXS_LRADC_ADC is not set -CONFIG_MXS_TIMER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_KUSER_HELPERS=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_SELFTESTS=y -CONFIG_NLS=y -CONFIG_NVMEM=y -CONFIG_NVMEM_MXS_OCOTP=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_IMX23=y -CONFIG_PINCTRL_IMX28=y -CONFIG_PINCTRL_MXS=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_POWER_SUPPLY=y -CONFIG_PPS=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_RATIONAL=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_GPIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_STMP=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_MXS_AUART=y -CONFIG_SERIAL_MXS_AUART_CONSOLE=y -CONFIG_SMSC_PHY=y -CONFIG_SOC_BUS=y -CONFIG_SOC_IMX23=y -CONFIG_SOC_IMX28=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MXS=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -CONFIG_SRCU=y -CONFIG_STMP3XXX_RTC_WATCHDOG=y -CONFIG_STMP_DEVICE=y -CONFIG_SWPHY=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TINY_SRCU=y -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_CHIPIDEA=y -CONFIG_USB_CHIPIDEA_HOST=y -CONFIG_USB_CHIPIDEA_IMX=y -CONFIG_USB_CHIPIDEA_UDC=y -CONFIG_USB_COMMON=y -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_HCD_PLATFORM is not set -CONFIG_USB_GADGET=y -CONFIG_USB_MXS_PHY=y -CONFIG_USB_OTG=y -CONFIG_USB_PHY=y -CONFIG_USB_ROLE_SWITCH=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_ULPI_BUS=y -CONFIG_USE_OF=y -# CONFIG_VFP is not set -CONFIG_WATCHDOG_CORE=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0